Personalizando o comportamento do editor usando a Configuração de linguagem

Você pode implementar a sintaxe específica da linguagem personalizada no editor do Visual Studio usando a Configuração de linguagem para possibilitar operações de sintaxe específicas da linguagem. Em comparação com o uso de um Servidor de linguagem, o uso da Configuração de linguagem pode melhorar o desempenho, já que todas as suas operações são locais.

O que é Configuração de linguagem

O Visual Studio oferece recursos de edição inteligente para várias linguagens de programação por meio de extensões de linguagem. A Configuração de linguagem complementa os servidores que usam o Language Server Protocol (LSP) e fornece dados declarativos que permitem que o editor do Visual Studio tome decisões sobre formatação, colorização e conclusão sem o atraso de fazer uma consulta assíncrona ao servidor LSP. Os recursos de linguagem declarativa são definidos nos arquivos de configuração. Por exemplo, HTML, CSS e extensões typescript-basic compactadas com o Visual Studio oferecem um subconjunto dos seguintes recursos de linguagem declarativa:

  • Realce de sintaxe
  • Conclusão do trecho
  • Correspondência entre colchetes
  • Fechamento automático de colchetes
  • Alternância de comentários
  • Recuo automático

O Visual Studio possibilita o uso de extensões para definir uma configuração de linguagem para qualquer linguagem de programação. O arquivo de configuração de linguagem controla recursos fundamentais de edição, como alternância de comentários e correspondência e fechamento de colchetes.

O uso da Configuração de linguagem ajuda a:

  • Fazer o trabalho síncrono na digitação do usuário
  • Simplificar: arquivos JSON curtos com expressões regulares são mais fáceis de manter do que algoritmos complexos
  • Ter portabilidade: exige pouca ou nenhuma alteração entre o Visual Studio Code e o Visual Studio

Além disso, os arquivos de configuração de linguagem facilitam estender o Visual Studio para oferecer suporte a alguns recursos básicos de refatoração por meio de um arquivo JSON fácil de ler.

Adicionar suporte de configuração de linguagem a uma extensão do Visual Studio

Há três partes para adicionar suporte de configuração de linguagem a uma extensão do Visual Studio:

  1. Criar um projeto de VSIX
  2. Criar um arquivo de configuração de linguagem
  3. Adicionar um arquivo de gramática
  4. Atualizar o arquivo pkgdef

Para conhecer um exemplo prático, consulte Exemplo de configuração de linguagem.

Criar um projeto de VSIX

Para criar uma extensão de serviço de linguagem usando a configuração de linguagem, primeiro verifique se você tem a carga de trabalho de desenvolvimento de extensão do Visual Studio instalada para sua instância do VS.

Em seguida, crie um projeto VSIX navegando até Arquivo>Novo Projeto, procure "vsix" e procure Projeto VSIX:

Screenshot showing how to create a VSIX project.

Criar um arquivo de configuração de linguagem

Ao criar seu próprio arquivo de configuração de linguagem, você pode escolher quais aspectos integrar no arquivo JSON. Por exemplo, você pode optar por oferecer suporte à alternância de comentários, ao fechamento automático de chaves ou a qualquer combinação de funcionalidades disponíveis desta seção.

Para adicionar suporte à sua extensão, primeiro crie um arquivo de configuração de linguagem. O nome do arquivo deve seguir um padrão: use hifens para separar as palavras no nome do arquivo e veja se ele termina com language-configuration.json.

O seguinte código mostra um exemplo de arquivo de configuração de linguagem.

{
    "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*[\\)\\}\\]].*$"
    }
  }

Definições de configuração

As seções a seguir descrevem as configurações disponíveis no arquivo de configuração de linguagem.

Alternância de comentários

Os arquivos de configuração de linguagem oferecem dois comandos para alternar comentários. Toggle Line Comment e Toggle Block Comment. Você pode especificar comments.blockComment e comments.lineComment para controlar como o Visual Studio deve comentar em linhas/blocos.

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

Essa configuração afeta o comportamento do editor de texto do Visual Studio quando você pressiona Ctrl+K, Ctrl+C.

Definição de colchetes

Quando você move o cursor para um colchete definido aqui, o Visual Studio realça esse colchete junto com seu par correspondente.

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

A configuração relevante na caixa de diálogo Ferramentas > Opções do Visual Studio, em Editor de Texto, Geral, Exibição, é a caixa de seleção Habilitar colorização de par de chaves.

Fechamento automático

Quando você digita ', o Visual Studio cria um par de aspas simples e coloca o cursor no meio: '|'. Esta seção define esses pares.

{
  "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"] }
  ]
}

A chave notIn desabilita esse recurso em determinados intervalos de código. Por exemplo, quando você está escrevendo o seguinte código:

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

A aspa simples não é fechada automaticamente.

Os pares que não exigem uma propriedade notIn também podem usar uma sintaxe mais simples:

{
  "autoClosingPairs": [ ["{", "}"], ["[", "]"] ]
}
Fechamento automático antes

Por padrão, o Visual Studio só fecha automaticamente pares se houver espaço em branco logo após o cursor. Portanto, quando você digita { no seguinte código JSX, você não tem o fechamento automático:

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

No entanto, essa definição substitui esse comportamento:

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

Agora, quando você digita { logo antes de >, o Visual Studio o fecha automaticamente com }.

Cercamento automático

Quando você seleciona um intervalo no Visual Studio e insere um colchete de abertura, o Visual Studio cerca o conteúdo selecionado com um par de colchetes. Esse recurso é chamado de Autosurrounding, ou cercamento automático, por onde você define os pares para uma linguagem específica:

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

A configuração relevante em Ferramentas > Opções do Visual Studio Tools está na caixa de seleção Editor de Texto, Geral, ExibiçãoAuto surround de seleções ao digitar aspas ou colchetes.

Padrão de palavras

wordPattern define o que é considerado como uma palavra na linguagem de programação. Os recursos de sugestão de código usam essa configuração para determinar os limites de palavras, se wordPattern estiver definido.

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

Regras de recuo

indentationRules define como o editor deve ajustar o recuo da linha atual ou da próxima linha quando você digita, cola e move linhas, ou quando formata texto com Ctrl+K, Ctrl+D (Formatar documento) e Ctrl+K, Ctrl+F (Formatar seleção).

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

Por exemplo, if (true) { corresponde a increaseIndentPattern, então, se você pressionar Enter após o colchete aberto {, o editor recuará automaticamente uma vez, e seu código terminará como:

if (true) {
  console.log();

Além de increaseIndentPattern e decreaseIndentPatter, existem duas outras regras de recuo:

  • indentNextLinePattern - Se uma linha corresponder a esse padrão, somente a próxima linha depois dela deverá ser recuada uma vez.
  • unIndentedLinePattern - Se uma linha corresponder a esse padrão, seu recuo não deverá ser alterado nem avaliado em relação às outras regras.

Se não houver nenhuma regra de recuo definida para a linguagem de programação, o editor recuará quando a linha terminar com um colchete aberto e recuará quando você digitar um colchete de fechamento. O colchete aqui é definido por brackets.

Pressionar Enter

onEnterRules define uma lista de regras para avaliar quando Enter é pressionado no editor.

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

Ao pressionar Enter, o texto antes, depois ou uma linha acima do cursor são verificados em relação às seguintes propriedades:

  • beforeText (obrigatório). Uma expressão regular que corresponde ao texto antes do cursor (limitado à linha atual).
  • afterText. Uma expressão regular que corresponde ao texto depois do cursor (limitado à linha atual).
  • previousLineText. Uma expressão regular que corresponde ao texto uma linha acima do cursor.

Se todas as propriedades especificadas corresponderem, a regra será considerada correspondente e nenhuma outra onEnterRules será avaliada. onEnterRule pode especificar as seguintes ações:

  • indent (obrigatório). Um de none, indent, outdent, indentOutdent.
    • none significa que a nova linha herda o recuo da linha atual.
    • indent significa que a nova linha é recuada em relação à linha atual.
    • outdent significa que a nova linha tem o recuo cancelado em relação à linha atual.
    • indentOutdent significa que duas novas linhas são inseridas, uma recuada e a segunda sem recuo.
  • appendText. Uma cadeia de caracteres que é anexada após a nova linha e após o recuo.
  • removeText. O número de caracteres a serem removidos do recuo da nova linha.

Configurações de propriedades

No projeto de extensão, verifique se o arquivo language-configuration.json tem as seguintes configurações de propriedade:

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

(opcional) Adicionar um arquivo de gramática

Além disso, você pode adicionar um arquivo de gramática do TextMate para colorir sintaticamente a linguagem. As gramáticas do TextMate são uma coleção estruturada de expressões regulares e são escritas como arquivos plist (XML) ou JSON. Consulte Gramáticas de linguagem. Se você não fornecer um arquivo gramatical específico da linguagem, uma configuração padrão interna será usada.

Para adicionar arquivos de tema ou gramática personalizada do TextMate, siga estas etapas:

  1. Crie uma pasta chamada "Grammars" dentro da sua extensão (ou pode ser qualquer nome que você escolher).

  2. Dentro da pasta Grammars, inclua qualquer arquivo *.tmlanguage, *.plist, *.tmtheme ou *.json que deseja colorir de forma personalizada.

    Dica

    Um arquivo .tmtheme define como os escopos são mapeados para classificações do Visual Studio (chamadas chaves coloridas). Para obter orientação, você pode fazer referência ao arquivo .tmtheme na versão %ProgramFiles(x86)%\Microsoft Visual Studio\< do diretório>\<SKU>\Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg.

Criar um arquivo pkgdef

Em seguida, crie um arquivo .pkgdef. Um arquivo .pkgdef contém todas as informações de registro que, de outra forma, seriam adicionadas ao registro do sistema. Para obter mais informações sobre arquivos pkgdef, consulte Registrando VSPackages e O que é um arquivo pkgdef? E por quê?. No arquivo pkgdef, você deve ter o caminho para o arquivo language-configuration.json e o caminho para a gramática da linguagem. Os serviços de linguagem, como o LSP, solicitam o tipo de conteúdo do editor e o conseguem por meio da Configuração de linguagem. Essas informações fornecem a inteligência específica da linguagem dentro de um servidor que pode se comunicar com as ferramentas de desenvolvimento. Quando um serviço de linguagem não existe, o mecanismo de Configuração de linguagem retorna à gramática do TextMate. O arquivo .pkgdef deve ter esta aparência:

[$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

Verifique se as propriedades do arquivo pkgdef estão definidas da seguinte maneira:

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

Para tornar as informações de configuração de idioma acessíveis para o Visual Studio, inclua o arquivo language-configuration no pacote VSIX. Incluir esse arquivo significa que ele acompanha a extensão do Visual Studio. O arquivo permite que o Visual Studio saiba que uma Configuração de linguagem está disponível para uso. Para adicionar o arquivo, edite vsixmanifest e adicione o arquivo PKGDEF def, por exemplo:

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