prometeu-studio/discussion/workflow/agendas/AGD-0017-studio-editor-scope-guides-and-brace-anchoring.md
2026-04-03 09:52:04 +01:00

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
studio
editor
scope-guides
braces
semantic-read
frontend-contract

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:

  • EditorWorkspace monta os guides a partir de analysis.documentSymbols() e repassa o modelo para a paragraph graphic factory em prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java;
  • EditorDocumentScopeGuideModel projeta guias por linha com depth e GuideSegmentKind, mas nao carrega coluna nem offset estrutural do brace em prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java;
  • EditorDocumentScopeGuideGraphicFactory desenha START e END a partir do centro vertical da linha, nao de um token estrutural real, em prometeu-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 scope deve ser sempre o menor range estrutural que contem o caret.
  • Como o Studio escolhe o active container quando o caret esta em blocos aninhados: funcao owner, tipo owner, ou simplesmente o menor ancestor acima do active scope? Fechado: active container deve ser o ancestor estrutural imediato acima do active 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 anchors genericos, nao em braces como primitivo normativo.
  • O schema atual de documentSymbols deve 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 inflar documentSymbols.

Options

Option A - Heuristica local no Studio sobre os ranges atuais

  • Approach: Manter o contrato atual de documentSymbols e 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 container e active 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 container e 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 CodeArea ja 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 container e active 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/endOffset do 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:

  1. active container e active scope como comportamento visual local, minimalista, restrito ao gutter e derivado dos ranges atuais;
  2. brace anchoring como 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:

  1. a primeira wave deve manter o scope indicator no gutter, de forma minimalista e sem poluicao visual;
  2. a primeira wave pode renderizar no maximo duas linhas no gutter: active container e active scope, sem ancestry arbitraria e sem mapa completo de guides;
  3. active scope deve ser o menor range estrutural que contem o caret;
  4. active container deve ser o ancestor estrutural imediato acima do active scope;
  5. 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;
  6. 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;
  7. a ancoragem exata do guide nao deve ser resolvida por heuristica textual como contrato final;
  8. a precisao estrutural deve ser exposta por metadata frontend-owned;
  9. essa metadata deve falar em structural anchors genericos, nao em braces como primitivo normativo;
  10. 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.