LINT ADVPL/TL++ — Offline Static Analysis for AdvPL/TL++Lint ADVPL/TL++ é uma extensão para VS Code que oferece análise estática offline de código-fonte ADVPL/TL++, identificando problemas comuns de escopo, nomenclatura, documentação e boas práticas — sem necessidade de dependência do ambiente TOTVS. Versão: 4.0.0 Release v2.0.0 (26 de janeiro de 2026)Release v3.0.2 (02 de fevereiro de 2026)
Release v3.0.1 (02 de fevereiro de 2026)
Release v4.0.0 (17 de fevereiro de 2026)
🆕 What's New (v1.0.0)
🎯 Visão Geral
📋 Regras Implementadas (11 regras implementadas)1. advpl/no-unused-local — Detecta declarações não utilizadasIdentifica variáveis declaradas como Heurísticas aplicadas:
Exemplo:
2. advpl/require-local — Força declaração de variáveis locaisDetecta quando uma variável recebe um valor (atribuição Heurísticas:
Exemplo:
3. advpl/hungarian-notation — Valida notação húngara de variáveisVerifica se as variáveis seguem a convenção de notação húngara (prefixo minúsculo + nome CamelCase) e propõe inicializadores apropriados baseados no prefixo. Prefixos e inicializadores sugeridos:
Heurísticas aplicadas:
Exemplo:
4. advpl/suggest-default-for-params — Sugere marcação de parâmetros padrãoPropõe adicionar a palavra-chave Heurísticas:
Exemplo:
5. advpl/require-explicit-private — Sugere declaração explícita de
|
| Comando ID | Label | Descrição |
|---|---|---|
lint-advpl.analyze |
Analisar arquivo | Força reanálise do arquivo ativo |
lint-advpl.exportTxt |
Exportar relatório (TXT) | Gera TXT com issues e sugestões |
lint-advpl.openView |
Abrir painel LINT | Abre/foca a aba lateral LINT |
lint-advpl.openConverterSettings |
Configurar conversores | Abre Settings filtrado para conversores |
Conversores SQL ↔ AdvPL
| Comando ID | Label | Descrição |
|---|---|---|
lint-advpl.convertBeginSQL |
BeginSQL → ADVPL/TL++ | Converte bloco BeginSQL em cQuery |
lint-advpl.convertSelectionToQuery |
SQL → ADVPL/TL++ | Converte seleção SQL em cQuery |
lint-advpl.convertAdvplToSql |
ADVPL/TL++ → SQL | Reconstrói SQL (copia para clipboard) |
Utilities e Refactoring
| Comando ID | Label | Descrição |
|---|---|---|
lint-advpl.sortVariables |
Ordenar Variáveis | Ordena declarações alfabeticamente |
lint-advpl.uppercaseTableFields |
Uppercase Tabela→Campo | Converte campos para MAIÚSCULAS |
lint-advpl.editDocHeaderTemplate |
Editar template de cabeçalho | Abre editor para customizar template |
lint-advpl.saveDocHeaderTemplate |
Salvar template de cabeçalho | Salva o template editado nas settings |
🛠️ Ferramentas/Utilities
Ordenar Variáveis — lint-advpl.sortVariables
Ordena declarações Local, Private, Static, Default alfabeticamente (case-insensitive) na seleção ou no bloco.
Características:
- ✅ Preserva indentação exata.
- ✅ Mantém inicializadores e tipos (
As Type). - ✅ Mantém comentários inline.
- ✅ Funciona com seleção (ordena dentro) ou arquivo inteiro.
Exemplo:
// Antes:
Local nCod := 0
Local cNome := ""
Local aItems := {}
Local lAtivo := .T.
// Depois (ordenado alfabeticamente):
Local aItems := {}
Local cNome := ""
Local lAtivo := .T.
Local nCod := 0
Uppercase Tabela→Campo — lint-advpl.uppercaseTableFields
Converte todas as referências tabela->campo para MAIÚSCULAS na seleção ou no arquivo inteiro.
Características:
- ✅ Preserva variáveis entre parênteses (ex.:
(cAlias)permanece minúscula). - ✅ Ignora strings e comentários.
- ✅ Converte tabelas explícitas e campos.
Exemplo:
// Antes:
cFilial := sa1->a1_filial
cNome := (cAlias)->a1_nome
// Depois:
cFilial := SA1->A1_FILIAL
cNome := (cAlias)->A1_NOME
Snippets de Cabeçalho Configurável
O quick-fix advpl/require-doc-header insere um snippet com placeholders que o analista preenche.
Template padrão (v0.0.12):
//--------------------------------------------------
/*/{Protheus.doc} ${FUNC_NAME}
${DESCRIPTION}
@author ${AUTHOR}
@since ${DATE}
/*/
//--------------------------------------------------
Placeholders suportados:
${FUNC_NAME}— preenchido automaticamente com nome da função.${DESCRIPTION}— tabstop para o analista editar.${AUTHOR}— tabstop com padrão delint-advpl.defaultAuthor.${DATE}— preenchido automaticamente com data atual (DD/MM/AAAA).${YEAR}— preenchido automaticamente com ano atual.
Personalização:
Edite lint-advpl.docHeaderTemplate em settings.json:
{
"lint-advpl.docHeaderTemplate": "//comment\n/*/{Protheus.doc} ${FUNC_NAME}\n${DESCRIPTION}\n\n@author ${AUTHOR}\n@since ${DATE}\n*/\n//comment\n",
"lint-advpl.defaultAuthor": "Seu Nome"
}
⚙️ Configuração
Opções Gerais
| Configuração | Tipo | Padrão | Descrição |
|---|---|---|---|
lint-advpl.showInProblems |
boolean | true |
Publica issues no painel Problems do VS Code |
lint-advpl.editorUnderline |
boolean | false |
Mostra squiggles/sublinhados no editor; false = apenas Problems |
lint-advpl.ignoredNames |
array | ["aRotina", "cCadastro", "INCLUI", "ALTERA","aGets","aTela"] |
Nomes a ignorar em todos as regras (case-insensitive) |
lint-advpl.hungarianSuggestInitializers |
boolean | true |
Sugere inicializadores baseado em prefixo húngaro |
lint-advpl.hungarianIgnoreAsType |
boolean | true |
Não sugere inicializadores se As <Type> está presente |
lint-advpl.database |
string | sqlserver |
Banco de dados do projeto; controla regras específicas (ex.: NOLOCK para sqlserver) |
lint-advpl.requireDocHeaderRequireName |
boolean | true |
Exige {Protheus.doc} <nome> no cabeçalho |
lint-advpl.requireDocHeaderIgnoreWsMethodInWsRestful |
boolean | true |
Ignora WSMETHOD dentro de WSRESTFUL para doc-header |
lint-advpl.enableRules |
boolean | true |
Master switch — ativa/desativa todas as regras |
lint-advpl.rules |
object | (todas true) |
Ativa/desativa regras individuais |
lint-advpl.fileExtensions |
array | [".prw", ".prx", ".tlpp"] |
Extensões de arquivo a analisar |
lint-advpl.databaseCompany |
string | "010" |
Sufixo de empresa para injetar em RetSQLName("XXX") → XXX010 |
lint-advpl.enableConvertBeginSQL |
boolean | true |
Ativa conversor BeginSQL → AdvPL |
lint-advpl.enableConvertSelection |
boolean | true |
Ativa conversor SQL → AdvPL (seleção) |
lint-advpl.docHeaderTemplate |
string | (veja abaixo) | Template customizável para quick-fix de cabeçalho (com placeholders) |
lint-advpl.defaultAuthor |
string | "" |
Autor padrão usado no template de cabeçalho |
Exemplo de settings.json (workspace)
Configuração básica:
{
"lint-advpl.ignoredNames": ["aRotina", "cCadastro", "INCLUI", "ALTERA"],
"lint-advpl.showInProblems": true,
"lint-advpl.editorUnderline": false
}
Configuração avançada (com heurísticas e toggles por-regra):
{
"lint-advpl.ignoredNames": ["aRotina", "cCadastro", "INCLUI", "ALTERA"],
"lint-advpl.showInProblems": true,
"lint-advpl.editorUnderline": false,
"lint-advpl.hungarianSuggestInitializers": true,
"lint-advpl.hungarianIgnoreAsType": true,
"lint-advpl.requireDocHeaderRequireName": true,
"lint-advpl.requireDocHeaderIgnoreWsMethodInWsRestful": true,
"lint-advpl.database": "sqlserver",
"lint-advpl.databaseCompany": "010",
"lint-advpl.enableConvertBeginSQL": true,
"lint-advpl.enableConvertSelection": true,
"lint-advpl.docHeaderTemplate": "//--------------------------------------------------\n/*/{Protheus.doc} ${FUNC_NAME}\n${DESCRIPTION}\n\n@author ${AUTHOR}\n@since ${DATE}\n*/\n//--------------------------------------------------\n",
"lint-advpl.defaultAuthor": "Seu Nome",
"lint-advpl.enableRules": true,
"lint-advpl.rules": {
"advpl/no-unused-local": true,
"advpl/require-doc-header": true,
"advpl/require-local": true,
"advpl/hungarian-notation": true,
"advpl/suggest-default-for-params": true,
"advpl/require-explicit-private": true,
"advpl/include-replace": true,
"advpl/require-with-nolock": true,
"advpl/use-crlf": true,
"advpl/require-field-reference": true,
"advpl/require-field-table": true
}
}
Desabilitar regras específicas:
{
"lint-advpl.rules": {
"advpl/hungarian-notation": false, // Desativa sugestões de notação
"advpl/require-doc-header": false // Desativa verificação de cabeçalho
}
}
Estrutura essencial
.
├── src/
│ ├── extension.ts # Ponto de entrada, registra comandos e eventos
│ ├── analyzer/
│ │ ├── index.ts # Orquestrador de regras
│ │ ├── types.ts # Tipos TypeScript (Issue, AnalysisResult)
│ │ └── rules/advpl/
│ │ ├── no-unused-local.ts # Detecta declarações não usadas
│ │ ├── require-local.ts # Força declaração de variáveis
│ │ ├── hungarian-notation.ts # Valida notação húngara e inicializadores
│ │ ├── suggest-default-params.ts # Sugere Default em parâmetros
│ │ ├── require-explicit-private.ts # Valida Private explícito
│ │ ├── require-doc-header.ts # Valida cabeçalho de documentação
│ │ └── include-replace.ts # Sugere atualização de includes
│ └── sidebar/
│ └── LintTreeProvider.ts # TreeDataProvider para visualização
├── tools/
│ ├── runFileTest.js # Executa analyzer em arquivo específico
│ └── (outros utilitários)
├── package.json # Manifest, configurações, dependências
├── tsconfig.json # Compilação TypeScript
└── README.md # Este arquivo
Requisitos
- VS Code:
^1.79.0(versão 1.79 ou superior) - Node.js:
22.x(para desenvolvimento e compilação) - Não requer nenhuma dependência externa em runtime (análise estática pura)
Desenvolvimento
Setup local
# Clone o repositório
git clone https://github.com/filhoirineu/lint-advpl-tlpp-by-filhoirineu
cd lint-advpl-tlpp-by-filhoirineu
# Instale dependências
npm install
# Compile uma vez
npm run compile
# Ou compile em modo watch (recompila ao salvar)
npm run watch
Testes
# Executar analyzer em arquivo específico
node tools/runFileTest.js fontestotvs/pcp/ws/ZPCPW30.prw
# Gera relatório JSON em out/reports/
Publicação
# Antes de publicar, verifique a versão em package.json (deve ser 0.0.12)
npm run compile
# Gerar o VSIX com nome contendo a versão:
npx vsce package --out lint-advpl-tlpp-0.0.12.vsix
# Publicar no Marketplace (requer Personal Access Token ou login do publisher):
# usando token em variável de ambiente (recomendado ao CI):
npx vsce publish --pat $VSCE_TOKEN
# Ou faça login interativo e publique:
# npx vsce login filhoirineu
# npx vsce publish
📊 Histórico de Versões
Versão 0.0.12 (atual) — 21 de janeiro de 2026
Novas Regras
- ✨ advpl/require-field-reference: Detecta campos não qualificados ou qualificados em minúsculas (ex.:
sa1->a1_cod→ sugestão:SA1->A1_COD). - ✨ advpl/require-field-table: Valida que prefixo de campo corresponde ao código da tabela (ex.:
SA1->A1_COD✅,SA1->B1_COD❌).
Melhorias em Regras Existentes
- 🔧 advpl/require-local: Detecta variáveis em
Aadd(...)cuja primeira argumento não está declarada; ignora assignment de propriedades indexadas (ex.:oBrowse:aColumns[1]:cTitle := ...). - 🔧 advpl/require-doc-header: Suporta quick-fix com snippet configurável (placeholders
${DESCRIPTION},${AUTHOR}).
Novos Conversores e Utilities
- 🔄 Conversor SQL → AdvPL (melhorado): Uppercases palavras-chave SQL e nomes de tabela/alias; preserva espaciamento.
- 🔄 Conversor BeginSQL → AdvPL (melhorado): Reconhece alias e gera chamadas
u_zParOpenQuery; trata tokens corretamente. - ✨ Comando: Uppercase Tabela→Campo —
lint-advpl.uppercaseTableFields: Converte todas as referências de campo para MAIÚSCULAS. - ✨ Snippets de Cabeçalho Configurável: Template editável via
lint-advpl.docHeaderTemplatecom placeholders${FUNC_NAME},${DESCRIPTION},${AUTHOR},${DATE}.
Novas Configurações
- ⚙️
lint-advpl.docHeaderTemplate— Template customizável para quick-fix de cabeçalho. - ⚙️
lint-advpl.defaultAuthor— Autor padrão usado no snippet. - ⚙️
lint-advpl.databaseCompany— Sufixo de empresa paraRetSQLName(). - ⚙️
lint-advpl.enableConvertBeginSQL— Toggle para conversor BeginSQL. - ⚙️
lint-advpl.enableConvertSelection— Toggle para conversor de seleção SQL.
Quick-fixes e CodeActions
- 💡 advpl/require-field-reference: "Uppercase field reference" — substitui automaticamente o campo.
- 💡 advpl/require-doc-header: "Inserir cabeçalho de documentação" — insere snippet com placeholders.
- 💡 advpl/require-with-nolock: "Replace (NOLOCK) with WITH(NOLOCK)" (já existia, melhorado).
Melhorias Gerais
- 📊 Documentação expandida: README.md agora inclui todas as regras, conversores, comandos, configurações e exemplos.
- 🎨 Menu de contexto: Adicionados comandos de conversão e utilities no menu editor/context.
- 🚀 Performance: Analyzer roda com debounce automático ao editar (250ms).
Versão 0.0.11 — 20 de janeiro de 2026
✨ Conversores bidirecionais entre SQL e ADVPL/TL++:
BeginSQL → ADVPL/TL++(in-place): converteBeginSQL...EndSQLemcQueryconcatenado com tokens.SQL → ADVPL/TL++(seleção): converte seleção SQL emcQuery, preservando linhas em branco e normalizandoNOLOCKparaWITH(NOLOCK).ADVPL/TL++ → SQL: reconstrói SQL legível a partir decQuerye copia o resultado para a área de transferência (não altera o arquivo quando a seleção écQuery).
🛠️ Melhorias e correções de robustez:
- Aceita variações de helpers
Ret*Name(...)(por exemploRetSqlName,RetSlqName) e aplica sufixo de empresa configurável vialint-advpl.databaseCompany. - Remoção de tokens de parsing (
%noparser%,%Exp:%,%notdel%) durante conversões quando aplicável. - Preservação de alias e
WITH(NOLOCK)após tokens de nome de tabela emFROM/JOIN. - Evita duplicação de aspas em placeholders e preserva literais
''corretamente.
- Aceita variações de helpers
Versão 0.0.7
- ✨ Ajustes na regra
advpl/require-doc-headerpara validação mais precisa - 🎯 Melhorias na detecção de blocos
ClasseWSRESTFULpara reduzir falsos-positivos
Versão 0.0.4 e anteriores
- Regras básicas: no-unused-local, require-local, hungarian-notation, suggest-default-for-params, require-explicit-private
- Painel lateral com Tree view
- Exportação para TXT
🤝 Contribuições
Contribuições são bem-vindas! Abra um Issue ou Pull Request para:
- Reportar bugs ou falsos-positivos
- Sugerir novas regras ou melhorias nas existentes
- Melhorar documentação e exemplos
Antes de submeter:
- Faça fork do repositório
- Crie uma branch para sua feature (
git checkout -b feature/minha-feature) - Commit suas mudanças (
git commit -m 'Adiciona minha feature') - Push para a branch (
git push origin feature/minha-feature) - Abra um Pull Request
📝 Licença
Este projeto é licenciado sob GPL-3.0 — veja LICENSE para detalhes.
🙋 Suporte
- 📧 Issues & Sugestões: GitHub Issues
- 💬 Discussões: GitHub Discussions
Desenvolvido com ❤️ por @filhoirineu
Versão atual: 0.0.12 | Última atualização: 21 de janeiro de 2026