package p.studio.lsp; import p.studio.compiler.pbs.lexer.PbsToken; import p.studio.compiler.pbs.lexer.PbsTokenKind; import p.studio.lsp.dtos.LspDefinitionTargetDTO; import p.studio.lsp.dtos.LspSymbolDTO; import p.studio.lsp.messages.LspDefinitionRequest; import p.studio.lsp.messages.LspDefinitionResult; import p.studio.lsp.messages.SemanticSession; import java.nio.file.Path; import java.util.List; import static p.studio.lsp.LspSemanticUtilities.normalize; import static p.studio.lsp.LspSemanticUtilities.tokenAt; class LspSemanticDefinitionService { LspDefinitionResult definition( final SemanticSession session, final LspDefinitionRequest request) { final List targets = resolveDefinitionTargets(session, request); return new LspDefinitionResult(request.documentPath(), request.offset(), targets); } private List resolveDefinitionTargets( final SemanticSession session, final LspDefinitionRequest request) { final Path documentPath = normalize(request.documentPath()); final List tokens = session.tokensByDocument().getOrDefault(documentPath, List.of()); final PbsToken activeToken = tokenAt(tokens, request.offset()); if (activeToken == null || activeToken.kind() != PbsTokenKind.IDENTIFIER) { return List.of(); } final String lexeme = activeToken.lexeme(); final List sameDocumentMatches = session.symbolsByName().getOrDefault(lexeme, List.of()).stream() .filter(symbol -> symbol.documentPath().equals(documentPath)) .toList(); final List effectiveMatches = sameDocumentMatches.isEmpty() ? session.symbolsByName().getOrDefault(lexeme, List.of()) : sameDocumentMatches; return effectiveMatches.stream() .map(symbol -> new LspDefinitionTargetDTO(symbol.name(), symbol.documentPath(), symbol.range())) .toList(); } }