--- id: AGD-0069 ticket: pbs-lsp-remaining-editor-surface title: PBS LSP Remaining Editor Surface status: accepted created: 2026-09-22 resolved: decision: tags: [studio, lsp, vscode, compiler-pbs, editor] --- ## Pain Domain owner: `studio` Nove agendas de LSP (AGD-0048 a AGD-0056, discussões DSC-0045 a DSC-0053) continuavam abertas como se cada tema partisse do zero. O servidor já anuncia hover, completion, signature help, definition, references, document symbols, workspace symbols, rename, quick fix e semantic tokens. Várias perguntas dessas agendas já foram respondidas pelo código, ou pedem trabalho cuja premissa deixou de existir. Decidir uma a uma repetiria debate vencido e produziria nove decisions para uma superfície só. ## Context Esta agenda substitui, sem herdar o texto como normativo: | Agenda aposentada | Discussão | O que o código já fez com o tema | | --- | --- | --- | | AGD-0048 formatting | DSC-0045 | Não há `documentFormattingProvider`, `rangeFormatting` nem `onTypeFormatting`. | | AGD-0049 import assistance | DSC-0046 | Não há auto-import nem organize imports. Imports existem como `ImportDecl` / `ModuleRef`. | | AGD-0050 semantic tokens | DSC-0047 | Tokens full-document já saem de `PBSSemanticTokenProvider`. | | AGD-0051 cache e snapshots | DSC-0048 | Cada pedido reconstrói análise. References e rename já existem sem cache. | | AGD-0052 completion depth | DSC-0049 | Completion já existe, eager, gatilho `.`, `resolveProvider` falso. | | AGD-0053 folding e selection | DSC-0050 | Não há folding nem selection range. Outline não é folding. | | AGD-0054 diagnostics UX | DSC-0051 | Diagnóstico já publica range, severity, message e code. Quick fix já casa code + range. | | AGD-0055 document links | DSC-0052 | Não há `documentLinkProvider`. Definition já recusa alvo que não seja arquivo físico. | | AGD-0056 call e type hierarchy | DSC-0053 | Não há call hierarchy nem type hierarchy. References não são grafo de chamadas. | O que o initialize anuncia hoje, em `Lsp4jProtocolMessageMapper`: sync full, hover, completion, signature help, definition, references, document symbol, workspace symbol, rename com prepare, code action só `quickfix`, semantic tokens full. Nada além disso. Fatos que esta agenda trata como fechados, porque o código já os fixou: 1. Análise de LSP é local ao pedido. `CompilerLanguageServiceBridge.analyzeDocument` monta um `AnalysisSnapshot` novo com overlay do documento aberto. Não há cache de projeto, cancelamento nem reanálise em background. References, rename e workspace symbols já foram entregues em cima desse modelo. Cache não é pré-requisito de mais nenhuma feature desta onda. 2. Semantic tokens não estão por fazer. `PBSSemanticTokenProvider` lexa o arquivo, classifica token léxico direto e classifica identificador por token vizinho, mapa de declaração do próprio arquivo e kinds importados da stdlib. A legenda é `PbsSemanticKind`. Não existem keys de field, local ou parameter. Arquivo quebrado continua tokenizável porque o lexer não depende do sucesso semântico. 3. Completion não está por fazer. `PbsEditorialSupportService.completion` faz duas coisas: se o token anterior é `.`, membros do tipo; senão keywords, parâmetros, locals, símbolos importados e top-level do arquivo. Documentação volta no próprio item. Não há snippets, não há `completionItem/resolve`, não há score de ranking. 4. Diagnóstico não carrega remediação. Spec 23 §8.3 e o quick fix já entregue exigem que o reparo não seja campo do diagnóstico nem venha de parse da mensagem. O mapper copia range, severity, message e code. O campo `source` está errado: `toBaselineIssue` grava o code estável também em `source` (ou `"Prometeu Studio"` quando o code vem vazio). Não há `relatedInformation`. 5. Não há um code de diagnóstico cujo significado seja "nome não importado". Os codes de nome não resolvido que existem são casos pontuais (`E_SEM_CONST_UNRESOLVED_REFERENCE`, `E_SEM_APPLY_UNRESOLVED_OVERLOAD`, `E_SEM_ASSIGN_TARGET_UNRESOLVED`, `E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE`). Inserir import em cima deles mistura typo com import faltando. 6. Definition, references e rename só apontam arquivo físico. Alvo virtual de stdlib não é destino de navegação. 7. A política de indentação em `LSN-0033` pertence ao editor embutido removido. Não é estilo canônico de PBS e não manda no formatter do LSP. 8. Outline, workspace symbols, rename e quick fix não absorvem folding, links, hierarquia nem organize imports. Fora desta onda, de propósito: - cache de snapshot, cancelamento e reanálise em background; - type hierarchy, implementações de contract e grafo de host/intrinsic como feature separada; - `completionItem/resolve`, snippets e modelo de ranking; - formatting por range ou on-type; - organize imports e quick fix de import faltando; - `relatedInformation`, fase do compilador dentro do diagnóstico, e campo de remediação; - keys novas de semantic token; - links para assets, addressables, docs ou URI virtual de stdlib. ## Open Questions - [x] **Q1. Qual pacote o plano único executa?** Travada em 2026-09-22: **A**. - **A.** Os sete passos da recomendação, nesta ordem, um commit cada. Inclui formatter e call hierarchy. - **B.** Os mesmos passos sem o 7 (call hierarchy fica fora). - **C.** Os mesmos passos sem o 4 (formatter fica fora até existir estilo aceito). - **D.** Só os passos que não escolhem estilo nem grafo novo: 1, 2, 3 e 6. - [x] **Q2. Se o passo 4 entrar, qual estilo o formatter aplica?** Travada em 2026-09-22: **A**. - **A.** Reimpressão do token stream. Não reordena declarações. Não junta nem parte linhas para embelezar. Indentação de 4 espaços só onde o aninhamento de chaves, parênteses ou bloco muda. Interior de text block `Doc` intocado. Comentário permanece na linha do token a que já estava preso. Documento inteiro apenas. - **B.** Não travar estilo. O passo 4 sai do plano mesmo se Q1 escolher A ou B. ## Options ### Option A - Uma onda, um plano, commits por passo - **Approach:** Uma decision e um plan. O plan copia os passos abaixo que Q1/Q2 deixarem vivos. Cada passo é um commit na mesma branch. Lesson e housekeep só depois do último passo. - **Pro:** O código atual vira o piso. Tema vencido não vira decision. A série continua um commit por entrega, sem nove discussões. - **Con:** Formatter e call hierarchy ainda são maiores que links ou o rótulo de `source`. - **Maintainability:** Forte se cada passo não reabrir cache, type hierarchy ou auto-import. ### Option B - Só o que já não tem escolha de produto - **Approach:** Mesma discussão única, mas o plano fica em diagnóstico `source`, document links físicos, folding/selection e completion de module ref. - **Pro:** Evita travar estilo e evita um grafo de chamadas novo. - **Con:** Formatting e call hierarchy continuam sem dono depois de aposentar as agendas velhas. - **Maintainability:** Boa, e menor. ## Tradeoffs Juntar as nove agendas num plano só é seguro porque o piso já está no código. O risco é enfiar de volta, como "passo pequeno", cache, contrato novo de diagnóstico ou auto-import. Esses três não cabem: o primeiro perdeu a premissa, o segundo quebra o quick fix já aceito, o terceiro não tem diagnóstico estável para se pendurar. Formatter é o único passo que ainda escolhe estilo. Por isso ele é um passo isolado: recusar Q2 tira só esse commit. Call hierarchy não pode reusar o índice de references; references são usos da mesma identidade, não chamadas. Ou entra como caminhada de `CallExpr` no último commit, ou fica de fora. ## Recommendation Aceitar Option A com Q1-A e Q2-A. Forma do plano, obrigatória: - uma decision e um plan desta discussão; - branch `dev/pbs-lsp-remaining-editor-surface`, não uma branch por passo e não commit em `master`; - cada passo vivo vira um commit `implements PLN-NNNN (k/N) `; - sem push; - spec 23 §8.3 só ganha parágrafo do passo que a superfície realmente passa a anunciar; - lesson e `discussion housekeep` só no commit do último passo. Passos, nesta ordem. Passo que Q1 ou Q2 tirar não é renumerado no meio da implementação: o plan lista só os que sobreviverem, em ordem. 1. **Diagnostic source.** `source` passa a ser o language id do frontend (`pbs`). `code` continua o code estável. Sem `relatedInformation`, sem fase, sem data de reparo. 2. **Document links.** Link só no span do `ModuleRef` de um import cujo destino já resolve para arquivo físico regular. Sem destino físico, sem link. Stdlib virtual, asset e doc ficam de fora. 3. **Folding e selection range.** Span de AST quando a árvore recuperada tem o nó: declaração top-level (`fn`, `struct`, `service`, `contract`, `enum`, `error`, `callback`, `host`), corpo, lista de parâmetros e text block `Doc`. Fallback de token só para chave, parêntese ou text block que a árvore não cobre. Selection, do interno para o externo: identificador, lista de argumento ou parâmetro, bloco ou text block, declaração. Lista vazia quando não houver range. Não reutilizar document symbols. 4. **Formatting de documento inteiro.** Só se Q2 travar estilo. Sem range e sem on-type. Preserva comentário e interior de text block `Doc`. Não é pretty-printer de AST. 5. **Overlay semântico em cima do token atual.** Não substituir `PBSSemanticTokenProvider`. Onde a mesma resolução de hover já nomeia o símbolo, trocar o kind fraco por um `PbsSemanticKind` que já existe. Falha, arquivo quebrado ou símbolo desconhecido mantém o token de hoje. Nenhuma key nova. 6. **Completion de module ref.** No cursor dentro de `ModuleRef`, candidatos que o resolver atual já sabe nomear, módulo de projeto e stdlib. Continua eager. `resolveProvider` continua falso. Sem snippets e sem score novo. Fora de module ref, o completion atual não muda. 7. **Call hierarchy.** Incoming e outgoing de função e método por caminhada de callsite na AST, não pelo índice de references. Cursor que não é callable devolve vazio. Sem type hierarchy e sem cache. ## Discussion As agendas AGD-0048 a AGD-0056 foram aposentadas a pedido, neste consolidado, antes de qualquer accept. O texto delas não é decisão. A CLI `discussion` não tem comando de abandon; a aposentadoria ficou no índice e no frontmatter, com a lacuna registrada para um comando futuro. Não aceitar esta agenda até Q1 e Q2 terem resposta explícita. A recomendação é o pacote, não um convite para preencher o resto na implementação. ## Resolution Q1-A e Q2-A travados pelo usuário em 2026-09-22. O pacote da recomendação é a escolha que a decision torna normativa. ## Next Step Decision aceita e plan desta discussão. Implementar os sete passos em série, um commit cada.