Personalizzazione del comportamento dell'editor tramite Configurazione lingua

È possibile implementare una sintassi personalizzata specifica del linguaggio nell'editor di Visual Studio usando Configurazione del linguaggio per abilitare operazioni di sintassi specifiche del linguaggio. Rispetto all'uso di un server di linguaggio, l'uso di Configurazione lingua può migliorare le prestazioni, poiché tutte le relative operazioni sono locali.

Informazioni sulla configurazione del linguaggio

Visual Studio offre funzionalità di modifica intelligente per vari linguaggi di programmazione tramite le estensioni del linguaggio. La configurazione del linguaggio integra i server che usano il protocollo LSP (Language Server Protocol) e fornisce dati dichiarativi che consentono all'editor di Visual Studio di prendere decisioni di formattazione, colorazione e completamento senza il ritardo di eseguire una query asincrona nel server LSP. Le funzionalità del linguaggio dichiarativo sono definite nei file di configurazione. Ad esempio, le estensioni HTML, CSS e typescript-basic in bundle con Visual Studio offrono un subset delle funzionalità del linguaggio dichiarativo seguenti:

  • Evidenziazione della sintassi
  • Completamento del frammento
  • Corrispondenza tra parentesi graffe
  • Chiusura automatica tra parentesi quadre
  • Attivazione/disattivazione dei commenti
  • Rientro automatico

Visual Studio offre la funzionalità per le estensioni per definire una configurazione del linguaggio per qualsiasi linguaggio di programmazione. Il file di configurazione del linguaggio controlla le funzionalità di modifica fondamentali, ad esempio l'attivazione/disattivazione dei commenti e la corrispondenza tra parentesi quadre e circostanti.

L'uso della configurazione del linguaggio consente di:

  • Lavoro sincrono sulla digitazione dell'utente
  • Semplicità: i file JSON brevi con espressioni regolari sono più facili da gestire rispetto all'algoritmo complesso
  • Portabilità: richiedere modifiche non necessarie o minime tra Visual Studio Code e Visual Studio

Inoltre, i file di configurazione del linguaggio offrono un modo semplice per estendere Visual Studio per supportare alcune funzionalità di refactoring di base tramite un file JSON di facile lettura.

Aggiungere il supporto di Configurazione del linguaggio a un'estensione di Visual Studio

Esistono tre parti per aggiungere il supporto di Configurazione del linguaggio a un'estensione di Visual Studio:

  1. Creare un progetto VSIX
  2. Creare un file di configurazione della lingua
  3. Aggiungere un file di grammatica
  4. Aggiornare il file pkgdef

È possibile esplorare un esempio funzionante in Esempio di configurazione del linguaggio.

Creare un progetto VSIX

Per creare un'estensione del servizio di linguaggio usando Configurazione del linguaggio, assicurarsi di avere installato il carico di lavoro sviluppo di estensioni di Visual Studio per l'istanza di Visual Studio.

Creare quindi un nuovo progetto VSIX passando a File>Nuovo progetto, cercare "vsix" e cercare progetto VSIX:

Screenshot showing how to create a VSIX project.

Creare un file di configurazione della lingua

Quando si crea un file di configurazione del linguaggio personalizzato, è possibile scegliere quali aspetti eseguire l'onboarding nel file JSON. Ad esempio, è possibile scegliere di supportare l'attivazione/disattivazione dei commenti, la chiusura automatica delle parentesi graffe o qualsiasi combinazione delle funzionalità disponibili descritte in questa sezione.

Per aggiungere il supporto all'estensione, creare prima di tutto un file di configurazione della lingua. Il nome del file deve seguire uno standard: usare trattini per separare le parole nel nome file e assicurarsi che termini con language-configuration.json.

Il codice seguente illustra un file di configurazione della lingua di esempio.

{
    "comments": {
      "lineComment": "***",
      "blockComment": ["{*", "*}"]
    },
    "brackets": [
      ["@", "@"],
      ["#", "#"],
      ["$", "$"],
      ["(", ")"]
    ],
    "autoClosingPairs": [
      { "open": "{", "close": "}" },
      { "open": "@", "close": "@" },
      { "open": "#", "close": "#" },
      { "open": "$", "close": "$" },
      { "open": "(", "close": ")" },
      { "open": "'", "close": "'", "notIn": ["string", "comment"] },
      { "open": "\"", "close": "\"", "notIn": ["string"] },
    ],
    "autoCloseBefore": ";:.,=}])>` \n\t",
    "surroundingPairs": [
      ["@", "@"],
      ["#", "#"],
      ["$", "$"],
      ["[", "]"],
      ["(", ")"],
      ["'", "'"],
      ["\"", "\""],
      ["`", "`"]
    ],
    "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
    "indentationRules": {
      "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
      "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
    }
  }

Impostazioni di configurazione

Le sezioni seguenti descrivono le impostazioni disponibili nel file di configurazione della lingua.

Attivazione/disattivazione dei commenti

I file di configurazione della lingua offrono due comandi per l'attivazione/disattivazione dei commenti. Attiva/Disattiva commento riga e Attiva/Disattiva commento blocco. È possibile specificare comments.blockComment e comments.lineComment per controllare il modo in cui Visual Studio deve impostare come impostare come commentare righe/blocchi.

{
  "comments": {
    "lineComment": "//",
    "blockComment": ["/*", "*/"]
  }
}

Questa impostazione influisce sul comportamento dell'editor di testo di Visual Studio quando si preme CTRL+K, CTRL+C.

Definizione parentesi quadre

Quando si sposta il cursore in una parentesi quadre definita qui, Visual Studio evidenzia tale parentesi insieme alla coppia corrispondente.

{
  "brackets": [["{", "}"], ["[", "]"], ["(", ")"]]
}

L'impostazione pertinente nella finestra di dialogo Opzioni strumenti di Visual Studio>, in Editor di testo Generale, Visualizzazione è la casella di controllo Abilita colorazione coppia parentesi graffa.

Chiusura automatica

Quando si digita ', Visual Studio crea una coppia di virgolette singole e posiziona il cursore al centro: '|'. Questa sezione definisce tali coppie.

{
  "autoClosingPairs": [
    { "open": "{", "close": "}" },
    { "open": "[", "close": "]" },
    { "open": "(", "close": ")" },
    { "open": "'", "close": "'", "notIn": ["string", "comment"] },
    { "open": "\"", "close": "\"", "notIn": ["string"] },
    { "open": "`", "close": "`", "notIn": ["string", "comment"] },
    { "open": "/**", "close": " */", "notIn": ["string"] }
  ]
}

La notIn chiave disabilita questa funzionalità in determinati intervalli di codice. Ad esempio, quando si scrive il codice seguente:

// ES6's Template String
`ES6's Template String`;

La virgoletta singola non viene chiuso automaticamente.

Anche le coppie che non richiedono una notIn proprietà possono usare una sintassi più semplice:

{
  "autoClosingPairs": [ ["{", "}"], ["[", "]"] ]
}
Chiusura automatica prima

Per impostazione predefinita, Visual Studio rimuove automaticamente le coppie solo se è presente uno spazio vuoto subito dopo il cursore. Quindi, quando si digita { il codice JSX seguente, non si otterrebbe la chiusura automatica:

const Component = () =>
  <div className={>
                  ^ Does not get autoclosed by default
  </div>

Tuttavia, questa definizione esegue l'override di tale comportamento:

{
  "autoCloseBefore": ";:.,=}])>` \n\t"
}

Quando si immette { subito prima >di , Visual Studio lo blocca automaticamente con }.

Autosurrounding

Quando si seleziona un intervallo in Visual Studio e si immette una parentesi aperta, Visual Studio racchiude il contenuto selezionato con una coppia di parentesi quadre. Questa funzionalità è denominata Autosurrounding e qui è possibile definire le coppie di autosurrounding per una lingua specifica:

{
  "surroundingPairs": [
    ["{", "}"],
    ["[", "]"],
    ["(", ")"],
    ["'", "'"],
    ["\"", "\""],
    ["`", "`"]
  ]
}

L'impostazione pertinente in Opzioni degli strumenti di Visual Studio si trova in Editor di testo Generale, Visualizza la casella di controllo Racchiude automaticamente le selezioni quando si digitano virgolette o parentesi quadre.>

Modello di parola

wordPattern definisce ciò che viene considerato come una parola nel linguaggio di programmazione. Le funzionalità di suggerimento del codice usano questa impostazione per determinare i limiti delle parole se wordPattern è impostata.

{
  "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)"
}

Regole di rientro

indentationRulesdefinisce il modo in cui l'editor deve regolare il rientro della riga corrente o della riga successiva quando si digita, si incollano e si spostano le righe oppure quando si formatta il testo con CTRL+K, CTRL+D (formato documento) e CTRL K, CTRL++F (formattazione selezione).

{
  "indentationRules": {
    "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
    "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
  }
}

Ad esempio, if (true) { corrisponde increaseIndentPatterna , quindi se si preme INVIO dopo la parentesi quadra {aperta, l'editor verrà rientrato automaticamente una volta e il codice finirà come:

if (true) {
  console.log();

Oltre a increaseIndentPattern e decreaseIndentPatter, sono disponibili altre due regole di rientro:

  • indentNextLinePattern - Se una riga corrisponde a questo modello, deve essere rientrata una sola volta la riga successiva.
  • unIndentedLinePattern - Se una riga corrisponde a questo modello, il rientro non deve essere modificato e non deve essere valutato rispetto alle altre regole.

Se non è impostato alcun rientro per il linguaggio di programmazione, il rientro dell'editor termina con una parentesi quadra aperta e un rientro quando si digita una parentesi chiusa. La parentesi quadra qui è definita da brackets.

Premendo INVIO

onEnterRules definisce un elenco di regole da valutare quando viene premuto INVIO nell'editor.

{
  "onEnterRules": [{
    "beforeText": "^\\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async).*?:\\s*$",
    "action": { "indent": "indent" }
  }]
}

Quando si preme INVIO, il testo prima, dopo o una riga sopra il cursore viene verificata in base alle proprietà seguenti:

  • beforeText (obbligatorio). Espressione regolare che corrisponde al testo prima del cursore (limitata alla riga corrente).
  • afterText. Espressione regolare che corrisponde al testo dopo il cursore (limitato alla riga corrente).
  • previousLineText. Espressione regolare che corrisponde al testo di una riga sopra il cursore.

Se tutte le proprietà specificate corrispondono, la regola viene considerata corrispondente e non vengono valutate altre onEnterRules proprietà. Un onEnterRule oggetto può specificare le azioni seguenti:

  • indent (obbligatorio). Uno di none, indent, outdent, indentOutdent.
    • none significa che la nuova riga eredita il rientro della riga corrente.
    • indent indica che il rientro della nuova riga è relativo alla riga corrente.
    • outdent indica che la nuova riga non è rientrata rispetto alla riga corrente.
    • indentOutdent significa che vengono inserite due nuove righe, un rientro e il secondo senza rientro.
  • appendText. Stringa aggiunta dopo la nuova riga e dopo il rientro.
  • removeText. Numero di caratteri da rimuovere dal rientro della nuova riga.

Impostazioni delle proprietà

Nel progetto di estensione verificare che il language-configuration.json file disponga delle impostazioni delle proprietà seguenti:

Build Action = Content
Include in VSIX = True
Copy to output = Copy always 

(facoltativo) Aggiungere un file di grammatica

Inoltre, è possibile aggiungere un file di grammatica TextMate per fornire la colorazione della sintassi per il linguaggio. Le grammatiche TextMate sono una raccolta strutturata di espressioni regolari e vengono scritte come file plist (XML) o JSON. Vedere Grammatiche del linguaggio. Se non si specifica un file di grammatica specifico della lingua, viene usata un'impostazione predefinita predefinita.

Per aggiungere file di grammatica o tema TextMate personalizzati, seguire questa procedura:

  1. Creare una cartella denominata "Grammars" all'interno dell'estensione (o può essere qualsiasi nome scelto).

  2. All'interno della cartella Grammars includere qualsiasi file *.tmlanguage, *.plist, *.tmtheme o *.json che si desidera fornire la colorazione personalizzata.

    Suggerimento

    Un file con estensione tmtheme definisce il mapping degli ambiti alle classificazioni di Visual Studio (chiavi di colore denominate). Per indicazioni, è possibile fare riferimento al file tmtheme globale nella directory %ProgramFiles(x86)%\Microsoft Visual Studio\<version>\SKU>\<Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg.

Creare un file pkgdef

Creare quindi un .pkgdef file. Un .pkgdef file contiene tutte le informazioni di registrazione che altrimenti verrebbero aggiunte al Registro di sistema. Per altre informazioni sui pkgdef file, vedere Registrazione di pacchetti VSPackage e Che cos'è un file pkgdef? E perché? pkgdef Nel file è necessario avere il percorso del language-configuration.json file e il percorso per la grammatica della lingua. I servizi linguistici, ad esempio LSP, richiedono il tipo di contenuto dell'editor e lo ottengono tramite Configurazione lingua. Queste informazioni forniscono l'intelligence specifica del linguaggio all'interno di un server in grado di comunicare con gli strumenti di sviluppo. Quando non esiste un servizio linguistico, il motore di configurazione della lingua esegue il fallback alla grammatica TextMate. Il .pkgdef file dovrebbe essere simile al seguente:

[$RootKey$\TextMate\Repositories]
"AspNetCoreRazor="$PackageFolder$\Grammars

// Defines where the language configuration file for a given
// grammar name is (value of the ScopeName tag in the tmlanguage file).
[$RootKey$\TextMate\LanguageConfiguration\GrammarMapping]
"text.aspnetcorerazor"="$PackageFolder$\language-configuration.json"

// Defines where the language configuration file for a given
// language name is (partial value of the content type name).
[$RootKey$\TextMate\LanguageConfiguration\ContentTypeMapping]
"RazorLSP"="$PackageFolder$\language-configuration.json"

[$RootKey$\TextMate\LanguageConfiguration\GrammarMapping]
"text.html.basic"="$PackageFolder$\html-language-configuration.json"
"source.js"="$PackageFolder$\javascript-language-configuration.json"
"source.css"="$PackageFolder$\css-language-configuration.json"
"source.cs"="$PackageFolder$\csharp-language-configuration.json

Assicurarsi che le proprietà del pkgdef file siano impostate nel modo seguente:

Build Action = Content
Include in VSIX = True
Copy to output = Copy always 

Per rendere accessibili le informazioni di configurazione della lingua per Visual Studio, includere il language-configuration file nel pacchetto VSIX. L'inclusione di questo file significa che viene fornita con l'estensione di Visual Studio. Il file indica a Visual Studio che è disponibile una configurazione della lingua per l'uso. Per aggiungere il file, modificare vsixmanifest per aggiungere il file PKGDEF def, ad esempio:

<Asset Type="Microsoft.VisualStudio.VsPackage" Path="Test.pkgdef"/>