implements PLN-0116

This commit is contained in:
bQUARKz 2026-07-15 11:33:43 +01:00
parent 3ca58dcc24
commit 79e4a64ff2
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
6 changed files with 79 additions and 70 deletions

View File

@ -8,7 +8,7 @@
{"type":"discussion","id":"DSC-0059","status":"open","ticket":"multi-frontend-common-lifecycle","title":"Extrair lifecycle comum das responsabilidades do frontend PBS","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","lifecycle","backend","multi-frontend"],"agendas":[{"id":"AGD-0062","file":"AGD-0062-multi-frontend-common-lifecycle.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0058","status":"open","ticket":"multi-frontend-serializable-ir","title":"Manter a IR comum serializavel por design","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","ir","backend","serialization","multi-frontend"],"agendas":[{"id":"AGD-0061","file":"AGD-0061-multi-frontend-serializable-ir.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0057","status":"open","ticket":"multi-frontend-frontend-backend-contract","title":"Estabilizar contrato entre frontend e backend comum","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","ir","backend","multi-frontend"],"agendas":[{"id":"AGD-0060","file":"AGD-0060-multi-frontend-frontend-backend-contract.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0056","status":"in_progress","ticket":"multi-frontend-remove-pbs-branches","title":"Generalizar o contrato LSP/editorial para frontends","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","studio","frontend","coupling","multi-frontend"],"agendas":[{"id":"AGD-0059","file":"AGD-0059-multi-frontend-remove-pbs-branches.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0042","file":"DEC-0042-frontend-editorial-language-service-contract-for-lsp.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0059"}],"plans":[{"id":"PLN-0111","file":"PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0112","file":"PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0113","file":"PLN-0113-migrate-completion-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0114","file":"PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0115","file":"PLN-0115-migrate-signature-help-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0116","file":"PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0056","status":"in_progress","ticket":"multi-frontend-remove-pbs-branches","title":"Generalizar o contrato LSP/editorial para frontends","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","compiler-pbs","studio","frontend","coupling","multi-frontend"],"agendas":[{"id":"AGD-0059","file":"AGD-0059-multi-frontend-remove-pbs-branches.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0042","file":"DEC-0042-frontend-editorial-language-service-contract-for-lsp.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0059"}],"plans":[{"id":"PLN-0111","file":"PLN-0111-define-generic-frontend-editorial-dtos-and-capability-surface.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0112","file":"PLN-0112-migrate-semantic-tokens-to-generic-frontend-language-service.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0113","file":"PLN-0113-migrate-completion-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0114","file":"PLN-0114-migrate-hover-and-documentation-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0115","file":"PLN-0115-migrate-signature-help-to-generic-frontend-models.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]},{"id":"PLN-0116","file":"PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0055","status":"done","ticket":"multi-frontend-compiler-vs-language-services","title":"Separar compilacao de servicos editoriais de frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","lsp","editor","frontend","multi-frontend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0056","file":"discussion/lessons/DSC-0055-multi-frontend-compiler-vs-language-services/LSN-0056-compile-first-frontends-with-optional-editorial-capabilities.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]}
{"type":"discussion","id":"DSC-0054","status":"done","ticket":"multi-frontend-provider-contract","title":"Introduzir provider completo de frontend","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["compiler","compiler-general","studio","frontend","registry","multi-frontend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0055","file":"discussion/lessons/DSC-0054-multi-frontend-provider-contract/LSN-0055-static-frontend-providers-before-plugin-architecture.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]}
{"type":"discussion","id":"DSC-0053","status":"open","ticket":"pbs-lsp-call-and-type-hierarchy","title":"PBS LSP Call and Type Hierarchy","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["studio","lsp","vscode","compiler-pbs","editor","call-hierarchy","type-hierarchy"],"agendas":[{"id":"AGD-0056","file":"AGD-0056-pbs-lsp-call-and-type-hierarchy.md","status":"open","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[],"plans":[],"lessons":[]}

View File

@ -2,8 +2,9 @@
id: PLN-0116
ticket: multi-frontend-remove-pbs-branches
title: Remove PBS imports from common LSP and add boundary coverage
status: open
status: done
created: 2026-07-15
completed: 2026-07-15
ref_decisions: [DEC-0042]
tags: [compiler, compiler-general, compiler-pbs, studio, frontend, coupling, multi-frontend]
---
@ -65,37 +66,3 @@ Remove remaining PBS implementation imports from common LSP code and add regress
- `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java`
- `prometeu-lsp/prometeu-lsp-v1/src/test/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridgeTest.java`
- Architectural-test discussion or future plan from `AGD-0067`
TBD.
## Objective
TBD.
## Dependencies
TBD.
## Scope
TBD.
## Non-Goals
TBD.
## Execution Method
TBD.
## Acceptance Criteria
TBD.
## Tests
TBD.
## Affected Artifacts
TBD.

View File

@ -1,6 +1,8 @@
package p.studio.compiler;
import p.studio.compiler.messages.FESurfaceContext;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.semantics.PbsEditorialCompletionCandidate;
@ -17,6 +19,9 @@ import p.studio.compiler.services.FrontendLanguageService;
import p.studio.compiler.services.FrontendSignature;
import p.studio.compiler.services.FrontendSignatureHelp;
import p.studio.compiler.services.FrontendSymbolKind;
import p.studio.compiler.services.PBSFrontendPhaseService;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.List;
@ -38,6 +43,27 @@ public final class PBSFrontendLanguageService implements FrontendLanguageService
this.semanticTokenProvider = Objects.requireNonNull(semanticTokenProvider, "semanticTokenProvider");
}
@Override
public Optional<FrontendEditorialContext> prepareEditorialContext(
final FrontendPhaseContext phaseContext,
final FileId fileId) {
if (phaseContext == null || fileId == null) {
return Optional.empty();
}
final var semanticReadSurface = PBSFrontendPhaseService.semanticReadSurface(
phaseContext,
DiagnosticSink.empty(),
BuildingIssueSink.empty());
final var ast = semanticReadSurface.astByFile().get(fileId);
if (ast == null) {
return Optional.empty();
}
return Optional.of(new FrontendEditorialContext(
ast,
semanticReadSurface.supplementalTopDeclsByFile().getOrDefault(fileId, ReadOnlyList.empty()),
phaseContext.feSurfaceContext()));
}
public List<PbsEditorialCompletionCandidate> completion(
final String sourceText,
final PbsAst.File ast,

View File

@ -75,6 +75,29 @@ class FrontendProviderBoundaryTest {
}
}
@Test
void commonLspMustNotImportPbsImplementationPackages() throws IOException {
final var repoRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize());
final var sourceRoot = repoRoot.resolve("prometeu-lsp/prometeu-lsp-v1/src/main/java");
final var prohibitedNeedles = List.of(
"p.studio.compiler.PBSFrontendLanguageService",
"p.studio.compiler.services.PBSFrontendPhaseService",
"p.studio.compiler.pbs",
"PbsAst",
"PbsEditorial");
try (final var files = Files.walk(sourceRoot)) {
final var violations = files
.filter(path -> path.toString().endsWith(".java"))
.filter(path -> prohibitedNeedles.stream().anyMatch(needle -> contains(path, needle)))
.toList();
if (!violations.isEmpty()) {
fail("common LSP code must consume generic frontend language-service contracts instead of PBS implementation packages: "
+ violations);
}
}
}
@Test
void compileOnlyFrontendProviderMayOmitLanguageService() {
final FrontendProvider provider = new CompileOnlyFrontendProvider();

View File

@ -1,6 +1,8 @@
package p.studio.compiler.services;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.source.identifiers.FileId;
import java.util.List;
import java.util.Optional;
@ -9,6 +11,12 @@ import java.util.Optional;
* Optional frontend-owned editor services.
*/
public interface FrontendLanguageService {
default Optional<FrontendEditorialContext> prepareEditorialContext(
final FrontendPhaseContext phaseContext,
final FileId fileId) {
return Optional.empty();
}
default List<FrontendSemanticToken> semanticTokens(final FrontendDocumentRequest request) {
return List.of();
}

View File

@ -2,7 +2,6 @@ package p.studio.lsp.services.compiler;
import org.apache.commons.lang3.StringUtils;
import p.studio.compiler.FrontendRegistryService;
import p.studio.compiler.PBSFrontendLanguageService;
import p.studio.compiler.messages.*;
import p.studio.compiler.models.*;
import p.studio.compiler.services.FrontendCompletionCandidate;
@ -13,7 +12,6 @@ import p.studio.compiler.services.FrontendProvider;
import p.studio.compiler.services.FrontendSignature;
import p.studio.compiler.services.FrontendSignatureHelp;
import p.studio.compiler.services.FrontendSymbolKind;
import p.studio.compiler.services.PBSFrontendPhaseService;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.compiler.utilities.SourceProviderFactory;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
@ -21,7 +19,6 @@ import p.studio.compiler.workspaces.BuilderPipelineService;
import p.studio.lsp.messages.*;
import p.studio.lsp.services.LanguageServiceBridge;
import p.studio.utilities.logs.LogAggregator;
import p.studio.utilities.structures.ReadOnlyList;
import java.net.URI;
import java.nio.file.Path;
@ -91,9 +88,9 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
normalizeDocumentPath(documentUri),
document.text());
final FrontendEditorialContext editorialContext = new FrontendEditorialContext(
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext());
document.editorialContext().syntaxTree(),
document.editorialContext().supplementalDeclarations(),
document.editorialContext().semanticContext());
final List<FrontendCompletionCandidate> candidates = languageService.orElseThrow().completion(
request,
editorialContext,
@ -126,9 +123,9 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
normalizeDocumentPath(documentUri),
document.text());
final FrontendEditorialContext editorialContext = new FrontendEditorialContext(
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext());
document.editorialContext().syntaxTree(),
document.editorialContext().supplementalDeclarations(),
document.editorialContext().semanticContext());
return languageService.orElseThrow().hover(
request,
editorialContext,
@ -159,9 +156,9 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
normalizeDocumentPath(documentUri),
document.text());
final FrontendEditorialContext editorialContext = new FrontendEditorialContext(
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext());
document.editorialContext().syntaxTree(),
document.editorialContext().supplementalDeclarations(),
document.editorialContext().semanticContext());
return languageService.orElseThrow().signatureHelp(
request,
editorialContext,
@ -230,6 +227,10 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
final LspProjectContext context,
final String documentUri,
final String text) {
final var languageService = frontendProvider(context).languageService();
if (languageService.isEmpty()) {
return Optional.empty();
}
final Path documentPath = normalizeDocumentPath(documentUri);
final BuilderPipelineContext pipelineContext = BuilderPipelineContext.fromConfig(
new BuilderPipelineConfig(
@ -250,19 +251,11 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
pipelineContext.resolvedWorkspace.target(),
HostAdmissionContext.permissiveDefault(),
assetSurfaceContextLoader.load(pipelineContext.resolvedWorkspace.mainProject().getRootPath()));
final var semanticReadSurface = PBSFrontendPhaseService.semanticReadSurface(
frontendPhaseContext,
p.studio.compiler.source.diagnostics.DiagnosticSink.empty(),
BuildingIssueSink.empty());
final var ast = semanticReadSurface.astByFile().get(fileId);
if (ast == null) {
return Optional.empty();
}
return Optional.of(new EditorialDocument(
text == null ? readCurrentText(pipelineContext, fileId) : text,
ast,
semanticReadSurface.supplementalTopDeclsByFile().getOrDefault(fileId, ReadOnlyList.empty()),
frontendPhaseContext.feSurfaceContext()));
return languageService.orElseThrow()
.prepareEditorialContext(frontendPhaseContext, fileId)
.map(editorialContext -> new EditorialDocument(
text == null ? readCurrentText(pipelineContext, fileId) : text,
editorialContext));
}
private FileId findFileId(
@ -404,12 +397,6 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
return frontendProviderResolver.apply(context.languageId());
}
private Optional<PBSFrontendLanguageService> pbsLanguageService(final LspProjectContext context) {
return frontendProvider(context).languageService()
.filter(PBSFrontendLanguageService.class::isInstance)
.map(PBSFrontendLanguageService.class::cast);
}
private BaselineCompletionItemKind mapCompletionKind(final FrontendSymbolKind kind) {
return switch (kind) {
case KEYWORD -> BaselineCompletionItemKind.KEYWORD;
@ -466,8 +453,6 @@ public final class CompilerLanguageServiceBridge implements LanguageServiceBridg
private record EditorialDocument(
String text,
p.studio.compiler.pbs.ast.PbsAst.File ast,
ReadOnlyList<p.studio.compiler.pbs.ast.PbsAst.TopDecl> supplementalTopDecls,
p.studio.compiler.messages.FESurfaceContext feSurfaceContext) {
FrontendEditorialContext editorialContext) {
}
}