diff --git a/discussion/index.ndjson b/discussion/index.ndjson index ea64ce91..e8d051ab 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -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":[]} diff --git a/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md b/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md index 7ddba508..e669051e 100644 --- a/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md +++ b/discussion/workflow/plans/PLN-0116-remove-pbs-imports-from-common-lsp-and-add-boundary-coverage.md @@ -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. diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java index 6f6b39dd..f91fbc08 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/PBSFrontendLanguageService.java @@ -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 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 completion( final String sourceText, final PbsAst.File ast, diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java index 6ea8fef5..03428814 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/FrontendProviderBoundaryTest.java @@ -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(); diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java index e2fd21ce..cad07baa 100644 --- a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/services/FrontendLanguageService.java @@ -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 prepareEditorialContext( + final FrontendPhaseContext phaseContext, + final FileId fileId) { + return Optional.empty(); + } + default List semanticTokens(final FrontendDocumentRequest request) { return List.of(); } diff --git a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java index 8e94fb82..1129b92d 100644 --- a/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java +++ b/prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/CompilerLanguageServiceBridge.java @@ -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 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 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 supplementalTopDecls, - p.studio.compiler.messages.FESurfaceContext feSurfaceContext) { + FrontendEditorialContext editorialContext) { } }