9.3 KiB
| id | ticket | title | status | created | resolved | decision | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| AGD-0017 | studio-editor-scope-guides-and-brace-anchoring | Scope guides do Code Editor com active container, active scope e ancoragem estrutural | accepted | 2026-04-03 | 2026-04-03 |
|
Pain
Os scope guides do Code Editor hoje comunicam hierarquia de escopo, mas ainda falham em dois pontos visuais importantes:
- o guide nao comeca no
{real do bloco; ele nasce aproximadamente no meio da linha inicial do simbolo; - o editor nao destaca o escopo em que o cursor esta, entao o usuario nao recebe feedback imediato de qual bloco esta ativo.
Isso deixa a feature util, mas incompleta. Em blocos aninhados, a leitura espacial do editor perde precisao justamente no momento em que o guide deveria ajudar mais.
Context
Domain owner: studio
Owner surfaces: docs/specs/studio/5. Code Editor Workspace Specification.md, docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md
Cross-domain input: frontends que produzem documentSymbols() para o Studio
Superficies relevantes hoje:
EditorWorkspacemonta os guides a partir deanalysis.documentSymbols()e repassa o modelo para a paragraph graphic factory emprometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java;EditorDocumentScopeGuideModelprojeta guias por linha comdeptheGuideSegmentKind, mas nao carrega coluna nem offset estrutural do brace emprometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java;EditorDocumentScopeGuideGraphicFactorydesenhaSTARTeENDa partir do centro vertical da linha, nao de um token estrutural real, emprometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java;- os testes atuais do modelo validam apenas shape por linha, nao ancoragem precisa de brace nem estado ativo por cursor, em
prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java.
Hoje o schema semantico exposto ao Studio entrega documentSymbols com LspRangeDTO(startOffset, endOffset), o que e suficiente para inferir linhas de escopo, mas nao suficiente para afirmar onde o { de abertura e o } de fechamento realmente estao quando:
- o brace esta em outra coluna da mesma linha;
- o header do simbolo se estende por mais de uma linha;
- a linguagem tem formas de bloco em que o range do simbolo nao coincide com o token estrutural que queremos destacar.
Open Questions
- O escopo ativo deve ser definido sempre como o menor range estrutural que contem o caret, ou existem casos em que o Studio deve promover o parent em vez do bloco mais interno?
Fechado:
active scopedeve ser sempre o menor range estrutural que contem o caret. - Como o Studio escolhe o
active containerquando o caret esta em blocos aninhados: funcao owner, tipo owner, ou simplesmente o menor ancestor acima doactive scope? Fechado:active containerdeve ser o ancestor estrutural imediato acima doactive scope, sem excecoes semanticas especiais para funcao, tipo ou outro owner. - O guide deve ancorar no token estrutural real (
{/}), ou basta uma heuristica local no editor que encontre o primeiro brace plausivel dentro do range do simbolo? Fechado: a ancoragem exata nao deve depender de heuristica textual local como contrato final; o objetivo correto e um anchor estrutural real. - O contrato correto para essa precisao estrutural pertence ao frontend/LSP semantic read, ou o Studio deve derivar isso localmente a partir do texto do documento? Fechado: a precisao estrutural pertence ao frontend e deve ser exposta ao Studio como metadata semanticamente owned pelo produtor da linguagem.
- Como tratar linguagens que nao usam braces ou usam formas mistas de delimitacao, sem acoplar o Studio a PBS?
Fechado: o contrato deve falar em
structural anchorsgenericos, nao em braces como primitivo normativo. - O schema atual de
documentSymbolsdeve ser enriquecido, ou devemos introduzir uma surface estrutural paralela dedicada a guides/brackets? Fechado: devemos introduzir uma surface semantica propria para guides/anchors em vez de inflardocumentSymbols.
Options
Option A - Heuristica local no Studio sobre os ranges atuais
- Approach: Manter o contrato atual de
documentSymbolse fazer o Studio procurar braces plausiveis dentro do texto/range de cada simbolo, alem de calcular o escopo ativo localmente pelo caret. - Pro: Menor custo inicial e pouca mudanca de contrato entre frontend e Studio.
- Con: A heuristica tende a ser fragil para headers multiline, linguagens sem braces, ranges amplos demais e futuras linguagens com sintaxe diferente de PBS.
- Maintainability: Media para baixa. Resolve rapido, mas cristaliza logica estrutural no host visual em vez de no owner da linguagem.
Option B - Metadata estrutural explicita fornecida pelo frontend
- Approach: Enriquecer o payload semantico consumido pelo Studio com posicoes estruturais explicitas para abertura/fechamento de blocos, ou com uma surface propria para scope/bracket guides; o editor usa esse contrato para ancoragem exata e para determinar o escopo ativo.
- Pro: Fecha ownership correto no frontend, preserva neutralidade do Studio em relacao a sintaxe e permite ancoragem precisa sem heuristica textual fraca.
- Con: Exige mudar o contrato entre semantic read e Studio, propagar implementacao para o frontend e decidir um schema que nao fique PBS-especifico.
- Maintainability: Forte. A precisao estrutural fica no produtor semantico, onde o parse e o conhecimento de linguagem ja existem.
Option C - Abordagem hibrida em duas waves
- Approach: Implementar primeiro um gutter minimalista com no maximo duas linhas visiveis:
active containereactive scope, ambos calculados localmente a partir dos ranges atuais; tratar a ancoragem exata no{como uma extensao posterior baseada em metadata estrutural explicita. - Pro: Entrega contexto e foco ao mesmo tempo, com pouco ruido, sem bloquear na extensao de contrato e sem puxar o Studio para heuristica sintatica como solucao final.
- Con: Exige definir semanticamente o que conta como
active containere pode exigir retrabalho pequeno no modelo do editor quando a metadata estrutural chegar. - Maintainability: Boa, se a primeira wave permanecer estritamente limitada a duas linhas sem ancestry aberta.
Discussion
Os dois sintomas nao tem o mesmo peso arquitetural.
Destacar o escopo ativo parece um problema majoritariamente local do editor, especialmente se a primeira wave for minimalista e restrita ao gutter:
- o
CodeAreaja conhece caret/paragrafo atual; - o modelo atual ja conhece os ranges de escopo por linha;
- em primeira aproximacao, o editor consegue descobrir qual range contem o cursor sem precisar saber a coluna exata do
{; - renderizar no maximo duas linhas (
active containereactive scope) preserva contexto sem voltar ao mapa completo de ancestry.
Ja a ancoragem precisa do guide no brace parece um problema de contrato estrutural:
- o modelo atual nao sabe onde o brace real esta;
- usar apenas
startOffset/endOffsetdo simbolo empurra heuristica sintatica para dentro do Studio; - isso fica especialmente fraco num editor que ja foi desenhado para ser multi-frontend.
Por isso, vale separar claramente:
active containereactive scopecomo comportamento visual local, minimalista, restrito ao gutter e derivado dos ranges atuais;brace anchoringcomo capacidade estrutural que talvez exija metadata adicional do frontend.
O risco de tentar resolver tudo localmente no Studio e transformar o host visual em pseudo-parser por linguagem. O risco oposto e bloquear uma melhoria visual simples do cursor enquanto esperamos um contrato estrutural maior ficar pronto.
Resolution
Recommended direction: seguir com Option C.
A agenda deve convergir para uma decisao com os seguintes fechamentos:
- a primeira wave deve manter o scope indicator no gutter, de forma minimalista e sem poluicao visual;
- a primeira wave pode renderizar no maximo duas linhas no gutter:
active containereactive scope, sem ancestry arbitraria e sem mapa completo de guides; active scopedeve ser o menor range estrutural que contem o caret;active containerdeve ser o ancestor estrutural imediato acima doactive scope;- o destaque desses estados pelo cursor deve ser tratado como capacidade local do editor, usando os ranges semanticos ja disponiveis, desde que a regra fique language-agnostic;
- a apresentacao visual concreta desses indicadores deve continuar frontend-owned; o contrato do Studio nao deve fixar cores, tracos ou estilos especificos como regra normativa;
- a ancoragem exata do guide nao deve ser resolvida por heuristica textual como contrato final;
- a precisao estrutural deve ser exposta por metadata frontend-owned;
- essa metadata deve falar em
structural anchorsgenericos, nao em braces como primitivo normativo; - guides/anchors devem viver em uma surface semantica propria, em vez de estender
documentSymbols.
Next step suggestion: converter esta agenda em uma decision que feche o boundary entre Studio e frontend para structural scope metadata, diferencie formalmente active scope de brace anchor, e declare a wave inicial aceitavel para o Code Editor.