A extensão do editor
Cores, erros enquanto se digita, autocompletar, depurador com breakpoints, Big-O acima de cada ação, 60 comandos e o painel de bancos. O que cada coisa faz, e por quê.
A extensão não reimplementa nada da linguagem: ela chama a CLI e desenha o resultado. É isso que garante que o sublinhado no editor, a saída do terminal e o que quebra o CI sejam sempre a mesma coisa — a alternativa seria um analisador no editor divergindo do analisador de verdade, e um editor que diz "tudo certo" sobre código que o CI recusa.
O que ela acrescenta é o que só faz sentido dentro do editor: complexidade acima de cada ação, custo ao lado de cada import, breakpoints na margem, e um painel para os bancos do projeto.
Instalar#
dataforge editorIsso copia a extensão para todos os editores compatíveis que encontrar: VS Code, VS Code Insiders, VSCodium, Cursor e Windsurf. Reinicie o editor e abra um .df.
dataforge editor status # onde está instalada
dataforge editor remove # desinstala de todosErros enquanto você digita#
O sublinhado vem do mesmo dataforge check que roda no CI, servido pelo servidor de linguagem — que reanalisa a cada tecla, e não só ao salvar.
| O que ele acha | Exemplo |
|---|---|
| nome que não existe, com sugestão | p.clientte → did you mean 'cliente'? |
| aridade errada | criar(1, 2, 3) numa ação de dois parâmetros |
| tipo incompatível | x: Integer := "texto" |
| membro que o objeto não tem | inclusive vindo de outro arquivo |
| ciclo de import | com a cadeia inteira: a.df → b.df → c.df → a.df |
| código inalcançável | depois de um yield |
membro de enum esquecido num match | exaustividade |
Autocompletar, hover, ir-para-definição#
O servidor de linguagem (dataforge lsp) é servido do mesmo typechecker. O que ele dá:
| Recurso | O que faz |
|---|---|
| autocompletar | sensível a contexto, disparado por ., : e @ |
| hover | a assinatura e o resumo, incluindo os símbolos da stdlib |
| ir-para-definição | F12 — atravessa arquivos |
| achar referências | Shift+F12 |
| esquema do arquivo | Ctrl+Shift+O — ações, blueprints, records |
| ajuda de assinatura | os parâmetros enquanto se escreve a chamada |
| renomear | F2, com verificação antes |
| formatar | o mesmo dataforge fmt |
| correção rápida | onde há uma sugestão a aplicar |
| realçar ocorrências | o nome sob o cursor, nas outras posições |
Os nomes do próprio arquivo vêm antes dos 1873 símbolos da stdlib — é o que se procura em nove de cada dez vezes.
Depurar: F5#
Clique na margem para pôr um breakpoint e aperte F5. Não é preciso escrever launch.json.
| No painel | O que se vê |
|---|---|
| Variáveis | o escopo onde você parou, do mais próximo ao global — vault e cluster abrem em árvore |
| Pilha de chamadas | quem chamou quem; clicar leva ao lugar certo do arquivo certo |
| Console de depuração | qualquer expressão DataForge, avaliada no quadro escolhido |
| Entrar / Passar / Sair | F11, F10, Shift+F11 |
// Pare na linha do 'yield' e escreva no console:
total * 2 + len(nome)
cliente.saldo
[n * n cycle n in itens]As variáveis embutidas — 228 delas — não aparecem no painel. Elas vivem no escopo global, e despejá-las enterra as três variáveis que você parou para ver.
Depurar no terminal#
O comando Depurar no terminal roda dataforge debug, que é passo a passo em texto. Serve onde interface gráfica nenhuma chega — por ssh, num container, num servidor.
dataforge debug conta.df --parar=42Dentro dele: p passo, n próximo, f sai da ação, c continua, vars lista o escopo, pilha mostra quem chamou quem, e qualquer expressão é avaliada no quadro onde você parou.
Parar quando um valor muda#
Uma parada por linha responde "o programa passou aqui?". Quem depura um valor errado quer saber outra coisa: quem mudou isto? A vigia responde. Ela é conferida depois de cada instrução, e a parada mostra a linha que mudou o valor, com o antes e o depois.
dataforge debug conta.df --vigiar=total --vigiar='pedido.itens'
# ou, já parado:
w total vigia no quadro onde você está
vigias lista, com o valor e quantas mudanças
desvigiar 1 tira a vigia 1A mutação no lugar conta — xs.append(1) muda a lista sem trocar a referência —, e o campo mudado dentro de um método também, com a parada na linha do método. Uma vigia criada dentro de uma ação olha aquela ação: o mesmo nome lá fora é outra variável.
No editor, clique com o botão direito numa variável do painel e escolha Break on Value Change. É o data breakpoint do protocolo: o painel mostra o motivo data breakpoint e, na descrição, de quanto para quanto o valor foi.
Parar quando um valor é LIDO#
A vigia de mudança responde quem mudou isto?. Há uma pergunta irmã, e ela aparece quando o valor está certo e chega a um lugar errado: quem está consultando isto? Um valor que nunca mudou não dispara nenhuma vigia de mudança.
dataforge debug conta.df --vigiar-leitura=saldo
# ou, ja parado:
r saldo para quando 'saldo' for LIDO
r self.saldo para na leitura do campo, de dentro ou de fora
acessos lista, com quantas leituras cada uma tevew / --vigiar | r / --vigiar-leitura | |
|---|---|---|
| a pergunta | quem mudou isto? | quem está consultando isto? |
| quando confere | depois de cada instrução, comparando uma foto estrutural | no momento da leitura |
| como | execute sombreado | eval_Identifier e _ler_membro sombreados |
| custo quando não há nenhuma | nenhum — o execute sombreado devolve na hora | nenhum — as sombras só existem enquanto há vigia |
No editor é o mesmo data breakpoint, com Break on Value Read: dataBreakpointInfo passou a anunciar accessTypes: ["write", "read"], e o painel escolhe qual.
Big-O acima de cada ação#
Uma lente sobre a declaração, com a complexidade estimada — e um aviso quando ela passa do limite que você configurou.
// O(n²) — dois laços aninhados sobre a mesma entrada
action duplicados(itens):
saida := []
cycle a in itens:
cycle b in itens:
given a is b:
saida.append(a)
yield saidaClique na lente para ver por quê: qual laço, qual chamada, e o que domina. dataforge.complexidade.avisarAcimaDe controla o limite (padrão O(n log n)).
Custo de cada import#
Ao lado de cada adopt, quantos nomes ele traz ao escopo. O módulo inteiro traz tudo que ele tem; a forma seletiva traz o que você nomeou.
adopt Arcane.Math as Math // o módulo inteiro
adopt Arcane.Math.{sqrt, floor} // dois nomesA barra de status#
Antes havia um botão de rodar, e mais nada. Os 60 comandos viviam na paleta — e a paleta só serve a quem já sabe que o comando existe.
| Item | Pergunta que ele responde |
|---|---|
🔥 DataForge 1.0.0 | qual interpretador está sendo usado? |
▷ | rodar este arquivo |
✓ sem erros · ⊗ 2 ⚠ 5 | este arquivo está limpo? |
📈 O(n²) | a ação onde o cursor está custa quanto? |
🧪 12/12 | os testes passam? |
O item principal abre um menu, e não um comando. Ele é o índice do que a extensão faz — o lugar onde se descobre. São seis grupos: Rodar, Conferir, Testar, Entender, Projeto e Ajuda.
A complexidade é a da ação do cursor, e não do arquivo. "Este arquivo tem um O(n²) em algum lugar" não ajuda ninguém; "a ação onde você está é O(n²)" muda o que se escreve na linha seguinte.
Os testes no painel do editor#
O dataforge test já existia e já era bom. O que faltava era ele aparecer onde se olha: o painel de testes, com o triângulo ao lado de cada trial e o erro na linha que falhou.
- Um item por `trial`, e não por arquivo. "1 de 2 falhou" sem dizer qual não serve para nada.
- A descoberta é por leitura, e não por execução. Um painel que precisa rodar a suíte para saber o que existe não serve: rodar é o que se quer decidir depois de ver a lista.
- Um processo por arquivo. O corredor já roda o arquivo inteiro, e subir um processo por teste custaria mais que os testes.
Um arquivo sem nenhum trial não vira item — um painel com trinta arquivos vazios esconde os que importam.
Os 60 comandos#
Aprender — abrir a documentação do símbolo sob o cursor (Shift+F1), as 100 palavras da linguagem com o exemplo que roda, os dois temas de cor e o idioma das mensagens. O hover dizia o que uma palavra faz; o que faltava era o passo seguinte, que é ir ler — e quem precisa sair do editor para isso três vezes para de fazer.
Tudo na paleta (Ctrl+Shift+P) sob DataForge, e na árvore Ferramentas da barra lateral.
Rodar e medir#
| Comando | O que faz | Atalho |
|---|---|---|
| Rodar arquivo | no terminal | Ctrl+F5 |
| Rodar e medir o tempo | com cronômetro | Ctrl+Shift+F5 |
Rodar com --debug | tokens, AST e traceback | — |
| Medir várias execuções | média, mediana e p95 — uma execução só mede o ruído | — |
| Medir o desempenho | a carga de referência | — |
| Perfilar | tempo próprio por ação (o acumulado somaria mais de 100%) | — |
| Observar e reexecutar ao salvar | para quem itera | — |
| Abrir o REPL | com :type, :ast, :load | — |
| Avaliar expressão | sem criar arquivo | — |
Qualidade#
| Comando | O que faz | Atalho |
|---|---|---|
| Verificar erros | o check neste arquivo | — |
| Lint | estilo e higiene | — |
| Formatar | o fmt | — |
| Corrigir o que dá | formata e aponta o que exige julgamento | — |
| Rodar os testes | o Crucible | Ctrl+Alt+T |
| Cobertura | quais linhas os testes rodaram | — |
| Cobertura: exigir um mínimo | o que reprova no CI | — |
Entender#
| Comando | O que faz | Atalho |
|---|---|---|
| Analisar complexidade | a estimativa, com o caminho | Ctrl+Alt+O |
| Big-O: a tabela de referência | a escala, com números reais | — |
| Por que isto é assim? | a decisão de projeto atrás do que está sob o cursor | — |
| Ver os tokens | a saída do lexer | — |
| Ver a árvore sintática | a AST | — |
| Inventário do projeto | ações, blueprints, o arquivo e a ação mais longos | — |
| Explicar um código de erro | DF0601 em texto inteiro | — |
| Todos os códigos de erro | o catálogo | — |
Projeto e pacotes#
| Comando | O que faz |
|---|---|
| Novo projeto… | os 9 modelos; o projeto criado passa nos próprios testes |
Ver o forge.toml | o manifesto |
| Instalar as dependências | resolve o manifesto inteiro |
| Acrescentar um pacote… | com semver e lockfile |
| Procurar no registro… | por termo |
| Pacotes instalados | o que está lá |
| Pacotes desatualizados | o que subiu de versão |
| Árvore de dependências | quem pediu o quê |
| Gerar a documentação | Markdown a partir dos comentários |
| Limpar caches e artefatos | — |
Vitrine e DevOps#
| Comando | O que faz |
|---|---|
| Vitrine: subir recarregando ao salvar | o dev, com hot reload |
| Vitrine: por que não sobe? | o doctor — a resposta é quase sempre --host=0.0.0.0 |
| DevOps: gerar artefatos… | Dockerfile, compose, CI, k8s, Helm, Terraform, nginx, SBOM |
| DevOps: o que falta para subir? | o doctor, que funciona mesmo num projeto que não compila |
O painel de bancos de dados#
Na barra lateral, a árvore Bancos de dados lista as conexões do projeto. Cada uma pode ser testada, atualizada, removida — e inserida como código no editor, o que evita escrever a string de conexão à mão.
Ela lê o mesmo lugar de onde o Arcane.Forge lê: não há uma segunda configuração para manter em sincronia.
Os snippets#
Vinte e três atalhos, para as construções em que digitar o esqueleto custa mais que pensar nele:
| Digite | Vira |
|---|---|
action | uma ação com corpo |
blueprint | uma classe com método |
record | um record com campos |
match | match com um point e o default |
pipe | um pipeline sift/morph |
server | uma aplicação Kiln completa, com ignite |
crud | as cinco rotas RESTful de um recurso |
routeparam | rota com parâmetro e o 404 |
xlsx | gravar uma planilha |
istr | uma string interpolada |
Cores, ícones e indentação#
A gramática de cores é gerada de tokens.py — as 81 palavras reservadas, os operadores, a interpolação $"…{…}", e a diferença entre // (comentário) e ~/ (divisão inteira).
Junto vêm o tema de ícone de arquivo (o .df com a marca), 4 espaços de indentação forçados (insertSpaces, tabSize: 4, detectIndentation: false — tab é erro de sintaxe na linguagem), dobra de blocos, e os snippets das construções mais longas.
Configuração#
| Chave | Padrão | O que faz |
|---|---|---|
dataforge.caminho | (vazio) | o executável, quando ele não está no PATH |
dataforge.verificar | true | sublinha erros e avisos |
dataforge.servidor.ativo | true | o servidor de linguagem |
dataforge.servidor.log | (vazio) | um arquivo onde ele grava o que acontece |
dataforge.complexidade.mostrar | true | a lente de Big-O |
dataforge.complexidade.avisarAcimaDe | O(n log n) | de onde vem o aviso |
dataforge.custoDeImport | true | o custo ao lado do adopt |
dataforge.formatarAoSalvar | false | roda o fmt ao salvar |
Tarefas e o matcher de problemas#
A extensão registra o tipo de tarefa dataforge e um problem matcher de mesmo nome: a saída de check, lint e test vira item clicável no painel de problemas — inclusive quando você roda por uma tarefa própria.
{
"version": "2.0.0",
"tasks": [{
"type": "dataforge",
"comando": "check",
"problemMatcher": ["$dataforge"],
"group": { "kind": "build", "isDefault": true }
}]
}Outros editores#
A gramática é TextMate padrão, em editor/vscode/syntaxes/dataforge.tmLanguage.json — Sublime Text e compatíveis leem o mesmo arquivo, e para Vim, Emacs ou Zed ela serve de referência: a lista de palavras por grupo de cor está toda ali.
O servidor de linguagem e o depurador são processos que falam protocolo padrão, e por isso servem qualquer editor:
dataforge lsp # Language Server Protocol, no stdio
dataforge dap # Debug Adapter Protocol, no stdioÉ por isso que a máquina dos dois mora na linguagem, e não na extensão: escrevê-la em TypeScript a amarraria ao VS Code. A extensão só diz ao editor qual processo iniciar.
Para pular a instalação da extensão ao instalar a linguagem, defina DATAFORGE_SEM_EDITOR=1.