@samchon/graph 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/lib/AsyncSamchonGraphSource.d.ts +2 -0
- package/lib/AsyncSamchonGraphSource.js +3 -0
- package/lib/AsyncSamchonGraphSource.js.map +1 -0
- package/lib/SamchonGraphApplication.d.ts +10 -0
- package/lib/SamchonGraphApplication.js +64 -0
- package/lib/SamchonGraphApplication.js.map +1 -0
- package/lib/SamchonGraphSource.d.ts +2 -0
- package/lib/SamchonGraphSource.js +3 -0
- package/lib/SamchonGraphSource.js.map +1 -0
- package/lib/application.d.ts +3 -0
- package/lib/application.js +20 -0
- package/lib/application.js.map +1 -0
- package/lib/bin.d.ts +2 -0
- package/lib/bin.js +8 -0
- package/lib/bin.js.map +1 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +30 -0
- package/lib/index.js.map +1 -0
- package/lib/indexer/IBuildGraphOptions.d.ts +41 -0
- package/lib/indexer/IBuildGraphOptions.js +3 -0
- package/lib/indexer/IBuildGraphOptions.js.map +1 -0
- package/lib/indexer/IIndexerResult.d.ts +5 -0
- package/lib/indexer/IIndexerResult.js +3 -0
- package/lib/indexer/IIndexerResult.js.map +1 -0
- package/lib/indexer/ILanguageSpec.d.ts +10 -0
- package/lib/indexer/ILanguageSpec.js +3 -0
- package/lib/indexer/ILanguageSpec.js.map +1 -0
- package/lib/indexer/LANGUAGE_SPECS.d.ts +2 -0
- package/lib/indexer/LANGUAGE_SPECS.js +114 -0
- package/lib/indexer/LANGUAGE_SPECS.js.map +1 -0
- package/lib/indexer/allExtensions.d.ts +2 -0
- package/lib/indexer/allExtensions.js +16 -0
- package/lib/indexer/allExtensions.js.map +1 -0
- package/lib/indexer/buildGraph.d.ts +3 -0
- package/lib/indexer/buildGraph.js +10 -0
- package/lib/indexer/buildGraph.js.map +1 -0
- package/lib/indexer/buildGraphDump.d.ts +3 -0
- package/lib/indexer/buildGraphDump.js +394 -0
- package/lib/indexer/buildGraphDump.js.map +1 -0
- package/lib/indexer/buildLspGraph.d.ts +3 -0
- package/lib/indexer/buildLspGraph.js +617 -0
- package/lib/indexer/buildLspGraph.js.map +1 -0
- package/lib/indexer/buildStaticGraph.d.ts +3 -0
- package/lib/indexer/buildStaticGraph.js +479 -0
- package/lib/indexer/buildStaticGraph.js.map +1 -0
- package/lib/indexer/decoratorsAbove.d.ts +1 -0
- package/lib/indexer/decoratorsAbove.js +14 -0
- package/lib/indexer/decoratorsAbove.js.map +1 -0
- package/lib/indexer/languageOf.d.ts +2 -0
- package/lib/indexer/languageOf.js +19 -0
- package/lib/indexer/languageOf.js.map +1 -0
- package/lib/indexer/languages.d.ts +5 -0
- package/lib/indexer/languages.js +22 -0
- package/lib/indexer/languages.js.map +1 -0
- package/lib/indexer/lspIndexer.d.ts +1 -0
- package/lib/indexer/lspIndexer.js +18 -0
- package/lib/indexer/lspIndexer.js.map +1 -0
- package/lib/indexer/overrideEdges.d.ts +2 -0
- package/lib/indexer/overrideEdges.js +45 -0
- package/lib/indexer/overrideEdges.js.map +1 -0
- package/lib/indexer/resolveType.d.ts +2 -0
- package/lib/indexer/resolveType.js +11 -0
- package/lib/indexer/resolveType.js.map +1 -0
- package/lib/indexer/specOf.d.ts +3 -0
- package/lib/indexer/specOf.js +8 -0
- package/lib/indexer/specOf.js.map +1 -0
- package/lib/indexer/staticIndexer.d.ts +1 -0
- package/lib/indexer/staticIndexer.js +18 -0
- package/lib/indexer/staticIndexer.js.map +1 -0
- package/lib/indexer/supertypesOf.d.ts +4 -0
- package/lib/indexer/supertypesOf.js +48 -0
- package/lib/indexer/supertypesOf.js.map +1 -0
- package/lib/lsp/DocumentSymbolResult.d.ts +3 -0
- package/lib/lsp/DocumentSymbolResult.js +3 -0
- package/lib/lsp/DocumentSymbolResult.js.map +1 -0
- package/lib/lsp/IDiagnostic.d.ts +8 -0
- package/lib/lsp/IDiagnostic.js +3 -0
- package/lib/lsp/IDiagnostic.js.map +1 -0
- package/lib/lsp/IDocumentSymbol.d.ts +9 -0
- package/lib/lsp/IDocumentSymbol.js +3 -0
- package/lib/lsp/IDocumentSymbol.js.map +1 -0
- package/lib/lsp/ILocation.d.ts +5 -0
- package/lib/lsp/ILocation.js +3 -0
- package/lib/lsp/ILocation.js.map +1 -0
- package/lib/lsp/IPosition.d.ts +4 -0
- package/lib/lsp/IPosition.js +3 -0
- package/lib/lsp/IPosition.js.map +1 -0
- package/lib/lsp/IRange.d.ts +5 -0
- package/lib/lsp/IRange.js +3 -0
- package/lib/lsp/IRange.js.map +1 -0
- package/lib/lsp/ISymbolInformation.d.ts +7 -0
- package/lib/lsp/ISymbolInformation.js +3 -0
- package/lib/lsp/ISymbolInformation.js.map +1 -0
- package/lib/lsp/LspClient.d.ts +17 -0
- package/lib/lsp/LspClient.js +140 -0
- package/lib/lsp/LspClient.js.map +1 -0
- package/lib/lsp/isDocumentSymbol.d.ts +3 -0
- package/lib/lsp/isDocumentSymbol.js +7 -0
- package/lib/lsp/isDocumentSymbol.js.map +1 -0
- package/lib/lsp/types.d.ts +8 -0
- package/lib/lsp/types.js +25 -0
- package/lib/lsp/types.js.map +1 -0
- package/lib/mcp/createServer.d.ts +3 -0
- package/lib/mcp/createServer.js +1947 -0
- package/lib/mcp/createServer.js.map +1 -0
- package/lib/mcp/startServer.d.ts +5 -0
- package/lib/mcp/startServer.js +23 -0
- package/lib/mcp/startServer.js.map +1 -0
- package/lib/model/GraphMemory.d.ts +25 -0
- package/lib/model/GraphMemory.js +141 -0
- package/lib/model/GraphMemory.js.map +1 -0
- package/lib/operations/bound.d.ts +1 -0
- package/lib/operations/bound.js +8 -0
- package/lib/operations/bound.js.map +1 -0
- package/lib/operations/common.d.ts +15 -0
- package/lib/operations/common.js +32 -0
- package/lib/operations/common.js.map +1 -0
- package/lib/operations/compareEdges.d.ts +2 -0
- package/lib/operations/compareEdges.js +10 -0
- package/lib/operations/compareEdges.js.map +1 -0
- package/lib/operations/edgeRank.d.ts +1 -0
- package/lib/operations/edgeRank.js +25 -0
- package/lib/operations/edgeRank.js.map +1 -0
- package/lib/operations/isExecution.d.ts +1 -0
- package/lib/operations/isExecution.js +11 -0
- package/lib/operations/isExecution.js.map +1 -0
- package/lib/operations/isPublicApiNoisePath.d.ts +2 -0
- package/lib/operations/isPublicApiNoisePath.js +11 -0
- package/lib/operations/isPublicApiNoisePath.js.map +1 -0
- package/lib/operations/isStructural.d.ts +1 -0
- package/lib/operations/isStructural.js +7 -0
- package/lib/operations/isStructural.js.map +1 -0
- package/lib/operations/isSupportPath.d.ts +2 -0
- package/lib/operations/isSupportPath.js +16 -0
- package/lib/operations/isSupportPath.js.map +1 -0
- package/lib/operations/isTestPath.d.ts +1 -0
- package/lib/operations/isTestPath.js +9 -0
- package/lib/operations/isTestPath.js.map +1 -0
- package/lib/operations/isTypeEdge.d.ts +1 -0
- package/lib/operations/isTypeEdge.js +11 -0
- package/lib/operations/isTypeEdge.js.map +1 -0
- package/lib/operations/publicEvidence.d.ts +2 -0
- package/lib/operations/publicEvidence.js +13 -0
- package/lib/operations/publicEvidence.js.map +1 -0
- package/lib/operations/referencesFromEdges.d.ts +3 -0
- package/lib/operations/referencesFromEdges.js +38 -0
- package/lib/operations/referencesFromEdges.js.map +1 -0
- package/lib/operations/resolveHandle.d.ts +6 -0
- package/lib/operations/resolveHandle.js +28 -0
- package/lib/operations/resolveHandle.js.map +1 -0
- package/lib/operations/resultGuide.d.ts +1 -0
- package/lib/operations/resultGuide.js +7 -0
- package/lib/operations/resultGuide.js.map +1 -0
- package/lib/operations/resultNext.d.ts +2 -0
- package/lib/operations/resultNext.js +7 -0
- package/lib/operations/resultNext.js.map +1 -0
- package/lib/operations/runDetails.d.ts +8 -0
- package/lib/operations/runDetails.js +190 -0
- package/lib/operations/runDetails.js.map +1 -0
- package/lib/operations/runEntrypoints.d.ts +9 -0
- package/lib/operations/runEntrypoints.js +122 -0
- package/lib/operations/runEntrypoints.js.map +1 -0
- package/lib/operations/runLookup.d.ts +10 -0
- package/lib/operations/runLookup.js +229 -0
- package/lib/operations/runLookup.js.map +1 -0
- package/lib/operations/runOverview.d.ts +10 -0
- package/lib/operations/runOverview.js +142 -0
- package/lib/operations/runOverview.js.map +1 -0
- package/lib/operations/runTour.d.ts +8 -0
- package/lib/operations/runTour.js +539 -0
- package/lib/operations/runTour.js.map +1 -0
- package/lib/operations/runTrace.d.ts +10 -0
- package/lib/operations/runTrace.js +283 -0
- package/lib/operations/runTrace.js.map +1 -0
- package/lib/operations/signatureOf.d.ts +2 -0
- package/lib/operations/signatureOf.js +45 -0
- package/lib/operations/signatureOf.js.map +1 -0
- package/lib/operations/subwords.d.ts +1 -0
- package/lib/operations/subwords.js +12 -0
- package/lib/operations/subwords.js.map +1 -0
- package/lib/operations/summaryOf.d.ts +2 -0
- package/lib/operations/summaryOf.js +24 -0
- package/lib/operations/summaryOf.js.map +1 -0
- package/lib/runGraph.d.ts +1 -0
- package/lib/runGraph.js +165 -0
- package/lib/runGraph.js.map +1 -0
- package/lib/structures/GraphEdgeKind.d.ts +10 -0
- package/lib/structures/GraphEdgeKind.js +3 -0
- package/lib/structures/GraphEdgeKind.js.map +1 -0
- package/lib/structures/GraphLanguage.d.ts +2 -0
- package/lib/structures/GraphLanguage.js +3 -0
- package/lib/structures/GraphLanguage.js.map +1 -0
- package/lib/structures/GraphNodeKind.d.ts +11 -0
- package/lib/structures/GraphNodeKind.js +3 -0
- package/lib/structures/GraphNodeKind.js.map +1 -0
- package/lib/structures/IGraphDecorator.d.ts +22 -0
- package/lib/structures/IGraphDecorator.js +3 -0
- package/lib/structures/IGraphDecorator.js.map +1 -0
- package/lib/structures/IGraphDetails.d.ts +126 -0
- package/lib/structures/IGraphDetails.js +3 -0
- package/lib/structures/IGraphDetails.js.map +1 -0
- package/lib/structures/IGraphDiagnostic.d.ts +23 -0
- package/lib/structures/IGraphDiagnostic.js +3 -0
- package/lib/structures/IGraphDiagnostic.js.map +1 -0
- package/lib/structures/IGraphDump.d.ts +37 -0
- package/lib/structures/IGraphDump.js +3 -0
- package/lib/structures/IGraphDump.js.map +1 -0
- package/lib/structures/IGraphEdge.d.ts +20 -0
- package/lib/structures/IGraphEdge.js +3 -0
- package/lib/structures/IGraphEdge.js.map +1 -0
- package/lib/structures/IGraphEntrypoints.d.ts +57 -0
- package/lib/structures/IGraphEntrypoints.js +3 -0
- package/lib/structures/IGraphEntrypoints.js.map +1 -0
- package/lib/structures/IGraphEscape.d.ts +40 -0
- package/lib/structures/IGraphEscape.js +3 -0
- package/lib/structures/IGraphEscape.js.map +1 -0
- package/lib/structures/IGraphEvidence.d.ts +24 -0
- package/lib/structures/IGraphEvidence.js +3 -0
- package/lib/structures/IGraphEvidence.js.map +1 -0
- package/lib/structures/IGraphLookup.d.ts +66 -0
- package/lib/structures/IGraphLookup.js +3 -0
- package/lib/structures/IGraphLookup.js.map +1 -0
- package/lib/structures/IGraphNext.d.ts +15 -0
- package/lib/structures/IGraphNext.js +3 -0
- package/lib/structures/IGraphNext.js.map +1 -0
- package/lib/structures/IGraphNode.d.ts +62 -0
- package/lib/structures/IGraphNode.js +3 -0
- package/lib/structures/IGraphNode.js.map +1 -0
- package/lib/structures/IGraphOverview.d.ts +100 -0
- package/lib/structures/IGraphOverview.js +3 -0
- package/lib/structures/IGraphOverview.js.map +1 -0
- package/lib/structures/IGraphTour.d.ts +54 -0
- package/lib/structures/IGraphTour.js +3 -0
- package/lib/structures/IGraphTour.js.map +1 -0
- package/lib/structures/IGraphTrace.d.ts +126 -0
- package/lib/structures/IGraphTrace.js +3 -0
- package/lib/structures/IGraphTrace.js.map +1 -0
- package/lib/structures/ISamchonGraphApplication.d.ts +162 -0
- package/lib/structures/ISamchonGraphApplication.js +3 -0
- package/lib/structures/ISamchonGraphApplication.js.map +1 -0
- package/lib/structures/index.d.ts +18 -0
- package/lib/structures/index.js +35 -0
- package/lib/structures/index.js.map +1 -0
- package/lib/structures.d.ts +1 -0
- package/lib/structures.js +18 -0
- package/lib/structures.js.map +1 -0
- package/lib/utils/DEFAULT_IGNORES.d.ts +1 -0
- package/lib/utils/DEFAULT_IGNORES.js +39 -0
- package/lib/utils/DEFAULT_IGNORES.js.map +1 -0
- package/lib/utils/IWalkOptions.d.ts +5 -0
- package/lib/utils/IWalkOptions.js +3 -0
- package/lib/utils/IWalkOptions.js.map +1 -0
- package/lib/utils/basename.d.ts +1 -0
- package/lib/utils/basename.js +10 -0
- package/lib/utils/basename.js.map +1 -0
- package/lib/utils/dirname.d.ts +1 -0
- package/lib/utils/dirname.js +10 -0
- package/lib/utils/dirname.js.map +1 -0
- package/lib/utils/fileFromUri.d.ts +1 -0
- package/lib/utils/fileFromUri.js +20 -0
- package/lib/utils/fileFromUri.js.map +1 -0
- package/lib/utils/fileUri.d.ts +1 -0
- package/lib/utils/fileUri.js +19 -0
- package/lib/utils/fileUri.js.map +1 -0
- package/lib/utils/fs.d.ts +6 -0
- package/lib/utils/fs.js +23 -0
- package/lib/utils/fs.js.map +1 -0
- package/lib/utils/isSubPath.d.ts +1 -0
- package/lib/utils/isSubPath.js +15 -0
- package/lib/utils/isSubPath.js.map +1 -0
- package/lib/utils/normalizePath.d.ts +1 -0
- package/lib/utils/normalizePath.js +7 -0
- package/lib/utils/normalizePath.js.map +1 -0
- package/lib/utils/path.d.ts +7 -0
- package/lib/utils/path.js +24 -0
- package/lib/utils/path.js.map +1 -0
- package/lib/utils/projectRelative.d.ts +1 -0
- package/lib/utils/projectRelative.js +9 -0
- package/lib/utils/projectRelative.js.map +1 -0
- package/lib/utils/readLines.d.ts +1 -0
- package/lib/utils/readLines.js +8 -0
- package/lib/utils/readLines.js.map +1 -0
- package/lib/utils/readText.d.ts +1 -0
- package/lib/utils/readText.js +17 -0
- package/lib/utils/readText.js.map +1 -0
- package/lib/utils/relativePath.d.ts +1 -0
- package/lib/utils/relativePath.js +12 -0
- package/lib/utils/relativePath.js.map +1 -0
- package/lib/utils/walkSourceFiles.d.ts +2 -0
- package/lib/utils/walkSourceFiles.js +44 -0
- package/lib/utils/walkSourceFiles.js.map +1 -0
- package/package.json +55 -0
- package/src/AsyncSamchonGraphSource.ts +5 -0
- package/src/SamchonGraphApplication.ts +74 -0
- package/src/SamchonGraphSource.ts +3 -0
- package/src/application.ts +3 -0
- package/src/bin.ts +6 -0
- package/src/index.ts +13 -0
- package/src/indexer/IBuildGraphOptions.ts +42 -0
- package/src/indexer/IIndexerResult.ts +6 -0
- package/src/indexer/ILanguageSpec.ts +11 -0
- package/src/indexer/LANGUAGE_SPECS.ts +112 -0
- package/src/indexer/allExtensions.ts +12 -0
- package/src/indexer/buildGraph.ts +10 -0
- package/src/indexer/buildGraphDump.ts +29 -0
- package/src/indexer/buildLspGraph.ts +710 -0
- package/src/indexer/buildStaticGraph.ts +507 -0
- package/src/indexer/decoratorsAbove.ts +9 -0
- package/src/indexer/languageOf.ts +13 -0
- package/src/indexer/languages.ts +5 -0
- package/src/indexer/lspIndexer.ts +1 -0
- package/src/indexer/overrideEdges.ts +42 -0
- package/src/indexer/resolveType.ts +14 -0
- package/src/indexer/specOf.ts +7 -0
- package/src/indexer/staticIndexer.ts +1 -0
- package/src/indexer/supertypesOf.ts +43 -0
- package/src/lsp/DocumentSymbolResult.ts +4 -0
- package/src/lsp/IDiagnostic.ts +9 -0
- package/src/lsp/IDocumentSymbol.ts +10 -0
- package/src/lsp/ILocation.ts +6 -0
- package/src/lsp/IPosition.ts +4 -0
- package/src/lsp/IRange.ts +6 -0
- package/src/lsp/ISymbolInformation.ts +8 -0
- package/src/lsp/LspClient.ts +165 -0
- package/src/lsp/isDocumentSymbol.ts +8 -0
- package/src/lsp/types.ts +8 -0
- package/src/mcp/createServer.ts +23 -0
- package/src/mcp/startServer.ts +23 -0
- package/src/model/GraphMemory.ts +165 -0
- package/src/operations/bound.ts +9 -0
- package/src/operations/common.ts +15 -0
- package/src/operations/compareEdges.ts +10 -0
- package/src/operations/edgeRank.ts +23 -0
- package/src/operations/isExecution.ts +9 -0
- package/src/operations/isPublicApiNoisePath.ts +10 -0
- package/src/operations/isStructural.ts +3 -0
- package/src/operations/isSupportPath.ts +16 -0
- package/src/operations/isTestPath.ts +7 -0
- package/src/operations/isTypeEdge.ts +9 -0
- package/src/operations/publicEvidence.ts +11 -0
- package/src/operations/referencesFromEdges.ts +37 -0
- package/src/operations/resolveHandle.ts +27 -0
- package/src/operations/resultGuide.ts +3 -0
- package/src/operations/resultNext.ts +9 -0
- package/src/operations/runDetails.ts +240 -0
- package/src/operations/runEntrypoints.ts +153 -0
- package/src/operations/runLookup.ts +269 -0
- package/src/operations/runOverview.ts +158 -0
- package/src/operations/runTour.ts +582 -0
- package/src/operations/runTrace.ts +339 -0
- package/src/operations/signatureOf.ts +40 -0
- package/src/operations/subwords.ts +8 -0
- package/src/operations/summaryOf.ts +21 -0
- package/src/runGraph.ts +144 -0
- package/src/structures/GraphEdgeKind.ts +24 -0
- package/src/structures/GraphLanguage.ts +21 -0
- package/src/structures/GraphNodeKind.ts +27 -0
- package/src/structures/IGraphDecorator.ts +25 -0
- package/src/structures/IGraphDetails.ts +153 -0
- package/src/structures/IGraphDiagnostic.ts +29 -0
- package/src/structures/IGraphDump.ts +45 -0
- package/src/structures/IGraphEdge.ts +24 -0
- package/src/structures/IGraphEntrypoints.ts +70 -0
- package/src/structures/IGraphEscape.ts +49 -0
- package/src/structures/IGraphEvidence.ts +29 -0
- package/src/structures/IGraphLookup.ts +80 -0
- package/src/structures/IGraphNext.ts +23 -0
- package/src/structures/IGraphNode.ts +76 -0
- package/src/structures/IGraphOverview.ts +121 -0
- package/src/structures/IGraphTour.ts +68 -0
- package/src/structures/IGraphTrace.ts +154 -0
- package/src/structures/ISamchonGraphApplication.ts +186 -0
- package/src/structures/index.ts +18 -0
- package/src/structures.ts +1 -0
- package/src/utils/DEFAULT_IGNORES.ts +35 -0
- package/src/utils/IWalkOptions.ts +5 -0
- package/src/utils/basename.ts +7 -0
- package/src/utils/dirname.ts +7 -0
- package/src/utils/fileFromUri.ts +14 -0
- package/src/utils/fileUri.ts +13 -0
- package/src/utils/fs.ts +6 -0
- package/src/utils/isSubPath.ts +9 -0
- package/src/utils/normalizePath.ts +3 -0
- package/src/utils/path.ts +7 -0
- package/src/utils/projectRelative.ts +6 -0
- package/src/utils/readLines.ts +5 -0
- package/src/utils/readText.ts +10 -0
- package/src/utils/relativePath.ts +7 -0
- package/src/utils/walkSourceFiles.ts +35 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { ChildProcessWithoutNullStreams, spawn } from "node:child_process";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
|
|
4
|
+
interface IRequest {
|
|
5
|
+
resolve: (value: unknown) => void;
|
|
6
|
+
reject: (error: Error) => void;
|
|
7
|
+
timer: NodeJS.Timeout;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class LspClient {
|
|
11
|
+
private readonly process: ChildProcessWithoutNullStreams;
|
|
12
|
+
private readonly pending = new Map<number, IRequest>();
|
|
13
|
+
private readonly events = new EventEmitter();
|
|
14
|
+
private buffer = Buffer.alloc(0);
|
|
15
|
+
private nextId = 1;
|
|
16
|
+
|
|
17
|
+
public constructor(
|
|
18
|
+
command: string,
|
|
19
|
+
args: readonly string[],
|
|
20
|
+
private readonly timeoutMs: number,
|
|
21
|
+
) {
|
|
22
|
+
this.process = spawn(command, [...args], {
|
|
23
|
+
stdio: "pipe",
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
});
|
|
26
|
+
this.process.stdout.on("data", (chunk: Buffer) => this.onData(chunk));
|
|
27
|
+
this.process.stderr.on("data", () => {
|
|
28
|
+
// Language servers often log noisy progress to stderr.
|
|
29
|
+
});
|
|
30
|
+
this.process.on("error", (error) => this.rejectAll(error));
|
|
31
|
+
this.process.on("exit", (code, signal) => {
|
|
32
|
+
this.rejectAll(
|
|
33
|
+
new Error(`Language server exited (${code ?? "null"}, ${signal ?? "null"}).`),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async request<T>(
|
|
39
|
+
method: string,
|
|
40
|
+
params: unknown,
|
|
41
|
+
timeoutMs?: number,
|
|
42
|
+
): Promise<T> {
|
|
43
|
+
const id = this.nextId++;
|
|
44
|
+
const payload = { jsonrpc: "2.0", id, method, params };
|
|
45
|
+
const promise = new Promise<T>((resolve, reject) => {
|
|
46
|
+
const timer = setTimeout(() => {
|
|
47
|
+
this.pending.delete(id);
|
|
48
|
+
reject(new Error(`LSP request timed out: ${method}`));
|
|
49
|
+
}, timeoutMs ?? this.timeoutMs);
|
|
50
|
+
this.pending.set(id, {
|
|
51
|
+
resolve: (value) => resolve(value as T),
|
|
52
|
+
reject,
|
|
53
|
+
timer,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
this.write(payload);
|
|
57
|
+
return promise;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public notify(method: string, params: unknown): void {
|
|
61
|
+
this.write({ jsonrpc: "2.0", method, params });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public onNotification(
|
|
65
|
+
method: string,
|
|
66
|
+
listener: (params: unknown) => void,
|
|
67
|
+
): void {
|
|
68
|
+
this.events.on(method, listener);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public async close(): Promise<void> {
|
|
72
|
+
try {
|
|
73
|
+
await this.request("shutdown", null);
|
|
74
|
+
} catch {
|
|
75
|
+
// Some servers exit before answering shutdown.
|
|
76
|
+
}
|
|
77
|
+
/* c8 ignore start */
|
|
78
|
+
try {
|
|
79
|
+
this.notify("exit", null);
|
|
80
|
+
} catch {
|
|
81
|
+
// Ignore close errors.
|
|
82
|
+
}
|
|
83
|
+
/* c8 ignore stop */
|
|
84
|
+
if (!this.process.killed) this.process.kill();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private write(payload: unknown): void {
|
|
88
|
+
const body = Buffer.from(JSON.stringify(payload), "utf8");
|
|
89
|
+
const header = Buffer.from(`Content-Length: ${body.length}\r\n\r\n`, "ascii");
|
|
90
|
+
this.process.stdin.write(Buffer.concat([header, body]));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private onData(chunk: Buffer): void {
|
|
94
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
95
|
+
for (;;) {
|
|
96
|
+
const headerEnd = this.buffer.indexOf("\r\n\r\n");
|
|
97
|
+
if (headerEnd < 0) return;
|
|
98
|
+
const header = this.buffer.slice(0, headerEnd).toString("ascii");
|
|
99
|
+
const match = /Content-Length:\s*(\d+)/i.exec(header);
|
|
100
|
+
if (match === null) {
|
|
101
|
+
this.buffer = this.buffer.slice(headerEnd + 4);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const length = Number(match[1]);
|
|
105
|
+
const bodyStart = headerEnd + 4;
|
|
106
|
+
const bodyEnd = bodyStart + length;
|
|
107
|
+
if (this.buffer.length < bodyEnd) return;
|
|
108
|
+
const body = this.buffer.slice(bodyStart, bodyEnd).toString("utf8");
|
|
109
|
+
this.buffer = this.buffer.slice(bodyEnd);
|
|
110
|
+
// A malformed frame must not throw out of the stdout `data` listener as an
|
|
111
|
+
// uncaught exception; drop it and keep draining the buffer.
|
|
112
|
+
let message;
|
|
113
|
+
try {
|
|
114
|
+
message = JSON.parse(body) as {
|
|
115
|
+
id?: number;
|
|
116
|
+
method?: string;
|
|
117
|
+
params?: unknown;
|
|
118
|
+
result?: unknown;
|
|
119
|
+
error?: { message?: string };
|
|
120
|
+
};
|
|
121
|
+
} catch {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
this.handleMessage(message);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private handleMessage(message: {
|
|
129
|
+
id?: number;
|
|
130
|
+
method?: string;
|
|
131
|
+
params?: unknown;
|
|
132
|
+
result?: unknown;
|
|
133
|
+
error?: { message?: string };
|
|
134
|
+
}): void {
|
|
135
|
+
// A server-initiated request carries both an id and a method. It must be
|
|
136
|
+
// answered or some servers block: gopls, for instance, withholds
|
|
137
|
+
// documentSymbol until its `window/workDoneProgress/create` request is
|
|
138
|
+
// acknowledged. A null result satisfies the acknowledgements we advertise.
|
|
139
|
+
if (message.id !== undefined && message.method !== undefined) {
|
|
140
|
+
this.write({ jsonrpc: "2.0", id: message.id, result: null });
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (message.id !== undefined) {
|
|
144
|
+
const pending = this.pending.get(message.id);
|
|
145
|
+
if (pending === undefined) return;
|
|
146
|
+
this.pending.delete(message.id);
|
|
147
|
+
clearTimeout(pending.timer);
|
|
148
|
+
if (message.error !== undefined) {
|
|
149
|
+
pending.reject(new Error(message.error.message ?? "LSP request failed."));
|
|
150
|
+
} else {
|
|
151
|
+
pending.resolve(message.result);
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (message.method !== undefined) this.events.emit(message.method, message.params);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private rejectAll(error: Error): void {
|
|
159
|
+
for (const [id, request] of this.pending) {
|
|
160
|
+
this.pending.delete(id);
|
|
161
|
+
clearTimeout(request.timer);
|
|
162
|
+
request.reject(error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IDocumentSymbol } from "./IDocumentSymbol";
|
|
2
|
+
import { ISymbolInformation } from "./ISymbolInformation";
|
|
3
|
+
|
|
4
|
+
export function isDocumentSymbol(
|
|
5
|
+
value: IDocumentSymbol | ISymbolInformation,
|
|
6
|
+
): value is IDocumentSymbol {
|
|
7
|
+
return "selectionRange" in value;
|
|
8
|
+
}
|
package/src/lsp/types.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./DocumentSymbolResult";
|
|
2
|
+
export * from "./IDiagnostic";
|
|
3
|
+
export * from "./IDocumentSymbol";
|
|
4
|
+
export * from "./ILocation";
|
|
5
|
+
export * from "./IPosition";
|
|
6
|
+
export * from "./IRange";
|
|
7
|
+
export * from "./ISymbolInformation";
|
|
8
|
+
export * from "./isDocumentSymbol";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { createMcpServer } from "@typia/mcp";
|
|
3
|
+
import type { ILlmController } from "@typia/interface";
|
|
4
|
+
import typia from "typia";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
AsyncSamchonGraphSource,
|
|
8
|
+
SamchonGraphApplication,
|
|
9
|
+
} from "../application";
|
|
10
|
+
import { ISamchonGraphApplication } from "../structures";
|
|
11
|
+
|
|
12
|
+
export function createServer(
|
|
13
|
+
graph: AsyncSamchonGraphSource,
|
|
14
|
+
version: string,
|
|
15
|
+
): McpServer {
|
|
16
|
+
const controller: ILlmController<ISamchonGraphApplication> = {
|
|
17
|
+
protocol: "class",
|
|
18
|
+
name: "samchon-graph",
|
|
19
|
+
application: typia.llm.application<ISamchonGraphApplication>(),
|
|
20
|
+
execute: new SamchonGraphApplication(graph),
|
|
21
|
+
};
|
|
22
|
+
return createMcpServer(controller, version);
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
|
|
4
|
+
import { buildGraph } from "../indexer/buildGraph";
|
|
5
|
+
import { IBuildGraphOptions } from "../indexer/IBuildGraphOptions";
|
|
6
|
+
import { GraphMemory } from "../model/GraphMemory";
|
|
7
|
+
import { IGraphDump } from "../structures";
|
|
8
|
+
import { createServer } from "./createServer";
|
|
9
|
+
|
|
10
|
+
export async function startServer(
|
|
11
|
+
options: IBuildGraphOptions & { version: string; graphFile?: string },
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
// A pre-built dump (`--graph-file`) serves immediately — the expensive index
|
|
14
|
+
// was paid once, outside this process, the same way comparator tools pay
|
|
15
|
+
// their `init`. Without it the resident graph builds lazily on first use.
|
|
16
|
+
const source =
|
|
17
|
+
options.graphFile !== undefined
|
|
18
|
+
? () => GraphMemory.from(JSON.parse(fs.readFileSync(options.graphFile!, "utf8")) as IGraphDump)
|
|
19
|
+
: () => buildGraph(options);
|
|
20
|
+
const server = createServer(source, options.version);
|
|
21
|
+
const transport = new StdioServerTransport();
|
|
22
|
+
await server.connect(transport);
|
|
23
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphEdgeKind,
|
|
3
|
+
IGraphDiagnostic,
|
|
4
|
+
IGraphDump,
|
|
5
|
+
IGraphEdge,
|
|
6
|
+
IGraphNode,
|
|
7
|
+
} from "../structures";
|
|
8
|
+
import { basename } from "../utils/path";
|
|
9
|
+
|
|
10
|
+
export class GraphMemory {
|
|
11
|
+
private readonly byId: Map<string, IGraphNode>;
|
|
12
|
+
private readonly outEdges: Map<string, IGraphEdge[]>;
|
|
13
|
+
private readonly inEdges: Map<string, IGraphEdge[]>;
|
|
14
|
+
private readonly byNameIndex: Map<string, IGraphNode[]>;
|
|
15
|
+
private readonly bySymbolIndex: Map<string, IGraphNode[]>;
|
|
16
|
+
private readonly diagnosticsByFile: Map<string, IGraphDiagnostic[]>;
|
|
17
|
+
|
|
18
|
+
public readonly project: string;
|
|
19
|
+
public readonly languages: readonly string[];
|
|
20
|
+
public readonly indexer: IGraphDump["indexer"];
|
|
21
|
+
public readonly nodes: readonly IGraphNode[];
|
|
22
|
+
public readonly edges: readonly IGraphEdge[];
|
|
23
|
+
public readonly diagnostics: readonly IGraphDiagnostic[];
|
|
24
|
+
public readonly warnings: readonly string[];
|
|
25
|
+
|
|
26
|
+
private constructor(dump: IGraphDump, nodes: IGraphNode[], edges: IGraphEdge[]) {
|
|
27
|
+
this.project = dump.project;
|
|
28
|
+
this.languages = dump.languages;
|
|
29
|
+
this.indexer = dump.indexer;
|
|
30
|
+
this.nodes = nodes;
|
|
31
|
+
this.edges = edges;
|
|
32
|
+
this.diagnostics = dump.diagnostics ?? [];
|
|
33
|
+
this.warnings = dump.warnings ?? [];
|
|
34
|
+
|
|
35
|
+
this.byId = new Map(nodes.map((node) => [node.id, node]));
|
|
36
|
+
this.outEdges = new Map();
|
|
37
|
+
this.inEdges = new Map();
|
|
38
|
+
this.byNameIndex = new Map();
|
|
39
|
+
this.bySymbolIndex = new Map();
|
|
40
|
+
this.diagnosticsByFile = new Map();
|
|
41
|
+
|
|
42
|
+
for (const node of nodes) {
|
|
43
|
+
push(this.byNameIndex, node.name, node);
|
|
44
|
+
if (node.kind !== "file") {
|
|
45
|
+
push(this.bySymbolIndex, node.name, node);
|
|
46
|
+
if (node.qualifiedName !== undefined) {
|
|
47
|
+
push(this.bySymbolIndex, node.qualifiedName, node);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const edge of edges) {
|
|
52
|
+
push(this.outEdges, edge.from, edge);
|
|
53
|
+
push(this.inEdges, edge.to, edge);
|
|
54
|
+
}
|
|
55
|
+
for (const diagnostic of this.diagnostics) {
|
|
56
|
+
push(this.diagnosticsByFile, diagnostic.file, diagnostic);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static from(dump: IGraphDump): GraphMemory {
|
|
61
|
+
const { nodes, edges } = synthesize(dump.nodes, dump.edges);
|
|
62
|
+
return new GraphMemory(dump, nodes, edges);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public node(id: string): IGraphNode | undefined {
|
|
66
|
+
return this.byId.get(id);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public outgoing(id: string): readonly IGraphEdge[] {
|
|
70
|
+
return this.outEdges.get(id) ?? [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public incoming(id: string): readonly IGraphEdge[] {
|
|
74
|
+
return this.inEdges.get(id) ?? [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public named(name: string): readonly IGraphNode[] {
|
|
78
|
+
return this.byNameIndex.get(name) ?? [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public symbols(handle: string): readonly IGraphNode[] {
|
|
82
|
+
return this.bySymbolIndex.get(handle) ?? [];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public exported(): IGraphNode[] {
|
|
86
|
+
return this.nodes.filter((node) => node.exported && !node.external);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public diagnosticsFor(file: string): readonly IGraphDiagnostic[] {
|
|
90
|
+
return this.diagnosticsByFile.get(file) ?? [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function push<K, V>(map: Map<K, V[]>, key: K, value: V): void {
|
|
95
|
+
const bucket = map.get(key);
|
|
96
|
+
if (bucket === undefined) map.set(key, [value]);
|
|
97
|
+
else bucket.push(value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function keyOf(node: IGraphNode): string {
|
|
101
|
+
return node.qualifiedName ?? node.name;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function ownerKey(key: string): string {
|
|
105
|
+
const dot = key.lastIndexOf(".");
|
|
106
|
+
return dot >= 0 ? key.slice(0, dot) : "";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function synthesize(
|
|
110
|
+
rawNodes: readonly IGraphNode[],
|
|
111
|
+
rawEdges: readonly IGraphEdge[],
|
|
112
|
+
): { nodes: IGraphNode[]; edges: IGraphEdge[] } {
|
|
113
|
+
const nodes = rawNodes.map((node) => ({ ...node }));
|
|
114
|
+
const edges = rawEdges.map((edge) => ({ ...edge }));
|
|
115
|
+
const byFileKey = new Map<string, IGraphNode>();
|
|
116
|
+
const files = new Map<string, IGraphNode>();
|
|
117
|
+
|
|
118
|
+
for (const node of nodes) {
|
|
119
|
+
if (!node.external) byFileKey.set(`${node.file}\0${keyOf(node)}`, node);
|
|
120
|
+
if (!node.external && node.file !== "" && !files.has(node.file)) {
|
|
121
|
+
files.set(node.file, {
|
|
122
|
+
id: node.file,
|
|
123
|
+
kind: "file",
|
|
124
|
+
language: node.language,
|
|
125
|
+
name: basename(node.file),
|
|
126
|
+
file: node.file,
|
|
127
|
+
external: false,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const edgeKeys = new Set(
|
|
133
|
+
edges.map((edge) => `${edge.kind}\0${edge.from}\0${edge.to}`),
|
|
134
|
+
);
|
|
135
|
+
const addEdge = (edge: IGraphEdge): void => {
|
|
136
|
+
const key = `${edge.kind}\0${edge.from}\0${edge.to}`;
|
|
137
|
+
if (edgeKeys.has(key)) return;
|
|
138
|
+
edgeKeys.add(key);
|
|
139
|
+
edges.push(edge);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
for (const node of nodes) {
|
|
143
|
+
if (node.external || node.file === "") continue;
|
|
144
|
+
const parentKey = ownerKey(keyOf(node));
|
|
145
|
+
const parent =
|
|
146
|
+
parentKey === "" ? undefined : byFileKey.get(`${node.file}\0${parentKey}`);
|
|
147
|
+
addEdge({
|
|
148
|
+
from: parent?.id ?? node.file,
|
|
149
|
+
to: node.id,
|
|
150
|
+
kind: "contains",
|
|
151
|
+
});
|
|
152
|
+
if (node.exported) {
|
|
153
|
+
addEdge({
|
|
154
|
+
from: node.file,
|
|
155
|
+
to: node.id,
|
|
156
|
+
kind: "exports" satisfies GraphEdgeKind,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
nodes: [...nodes, ...files.values()],
|
|
163
|
+
edges,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./bound";
|
|
2
|
+
export * from "./compareEdges";
|
|
3
|
+
export * from "./edgeRank";
|
|
4
|
+
export * from "./isExecution";
|
|
5
|
+
export * from "./isStructural";
|
|
6
|
+
export * from "./isTestPath";
|
|
7
|
+
export * from "./isTypeEdge";
|
|
8
|
+
export * from "./publicEvidence";
|
|
9
|
+
export * from "./referencesFromEdges";
|
|
10
|
+
export * from "./resolveHandle";
|
|
11
|
+
export * from "./resultGuide";
|
|
12
|
+
export * from "./resultNext";
|
|
13
|
+
export * from "./signatureOf";
|
|
14
|
+
export * from "./subwords";
|
|
15
|
+
export * from "./summaryOf";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IGraphEdge } from "../structures";
|
|
2
|
+
import { edgeRank } from "./edgeRank";
|
|
3
|
+
|
|
4
|
+
export function compareEdges(a: IGraphEdge, b: IGraphEdge): number {
|
|
5
|
+
return (
|
|
6
|
+
edgeRank(a.kind) - edgeRank(b.kind) ||
|
|
7
|
+
(a.evidence?.startLine ?? 999_999) - (b.evidence?.startLine ?? 999_999) ||
|
|
8
|
+
(a.evidence?.startCol ?? 999) - (b.evidence?.startCol ?? 999)
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { GraphEdgeKind } from "../structures";
|
|
2
|
+
|
|
3
|
+
export function edgeRank(kind: string): number {
|
|
4
|
+
switch (kind satisfies string as GraphEdgeKind | string) {
|
|
5
|
+
case "calls":
|
|
6
|
+
return 0;
|
|
7
|
+
case "instantiates":
|
|
8
|
+
return 1;
|
|
9
|
+
case "references":
|
|
10
|
+
case "accesses":
|
|
11
|
+
return 2;
|
|
12
|
+
case "type_ref":
|
|
13
|
+
return 3;
|
|
14
|
+
case "extends":
|
|
15
|
+
case "implements":
|
|
16
|
+
case "overrides":
|
|
17
|
+
return 4;
|
|
18
|
+
case "tests":
|
|
19
|
+
return 5;
|
|
20
|
+
default:
|
|
21
|
+
return 10;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isSupportPath } from "./isSupportPath";
|
|
2
|
+
|
|
3
|
+
/** True when exported symbols are unlikely to be authored public API. */
|
|
4
|
+
export function isPublicApiNoisePath(file: string): boolean {
|
|
5
|
+
return (
|
|
6
|
+
isSupportPath(file) ||
|
|
7
|
+
/(^|\/|\.)typings\.[cm]?ts$/.test(file) ||
|
|
8
|
+
/(^|\/)internal\//.test(file)
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** True for tests, examples, fixtures, generated output, and build artifacts. */
|
|
2
|
+
export function isSupportPath(file: string): boolean {
|
|
3
|
+
return (
|
|
4
|
+
file === "" ||
|
|
5
|
+
file.startsWith("bundled://") ||
|
|
6
|
+
/(^|\/)(node_modules|vendor|site-packages)\//.test(file) ||
|
|
7
|
+
/(^|\/)(test|tests|__tests__|spec|specs|sample|samples|fixture|fixtures|__fixtures__|example|examples)\//.test(
|
|
8
|
+
file,
|
|
9
|
+
) ||
|
|
10
|
+
/\.(test|spec)\.[^/]+$/.test(file) ||
|
|
11
|
+
/_test\.[^/]+$/.test(file) ||
|
|
12
|
+
/(^|\/)typings\.[cm]?ts$/.test(file) ||
|
|
13
|
+
/\.d\.[cm]?ts$/.test(file) ||
|
|
14
|
+
/(^|\/)(dist|build|coverage|generated|__generated__|gen)\//.test(file)
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IGraphEvidence } from "../structures";
|
|
2
|
+
|
|
3
|
+
export function publicEvidence(evidence: IGraphEvidence): IGraphEvidence {
|
|
4
|
+
return {
|
|
5
|
+
file: evidence.file,
|
|
6
|
+
startLine: evidence.startLine,
|
|
7
|
+
...(evidence.startCol !== undefined ? { startCol: evidence.startCol } : {}),
|
|
8
|
+
...(evidence.endLine !== undefined ? { endLine: evidence.endLine } : {}),
|
|
9
|
+
...(evidence.endCol !== undefined ? { endCol: evidence.endCol } : {}),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { GraphMemory } from "../model/GraphMemory";
|
|
2
|
+
import { IGraphDetails, IGraphEdge } from "../structures";
|
|
3
|
+
import { compareEdges } from "./compareEdges";
|
|
4
|
+
import { isStructural } from "./isStructural";
|
|
5
|
+
import { publicEvidence } from "./publicEvidence";
|
|
6
|
+
import { summaryOf } from "./summaryOf";
|
|
7
|
+
|
|
8
|
+
export function referencesFromEdges(
|
|
9
|
+
graph: GraphMemory,
|
|
10
|
+
edges: readonly IGraphEdge[],
|
|
11
|
+
end: "from" | "to",
|
|
12
|
+
limit: number,
|
|
13
|
+
includeExternal: boolean,
|
|
14
|
+
kinds?: ReadonlySet<string>,
|
|
15
|
+
): IGraphDetails.IReference[] {
|
|
16
|
+
const out: IGraphDetails.IReference[] = [];
|
|
17
|
+
const seen = new Set<string>();
|
|
18
|
+
for (const edge of [...edges].sort(compareEdges)) {
|
|
19
|
+
if (kinds !== undefined && !kinds.has(edge.kind)) continue;
|
|
20
|
+
if (isStructural(edge.kind)) continue;
|
|
21
|
+
const node = graph.node(end === "from" ? edge.from : edge.to);
|
|
22
|
+
if (node === undefined) continue;
|
|
23
|
+
if (!includeExternal && node.external) continue;
|
|
24
|
+
// One entry per node; edges are pre-sorted by compareEdges, so the first
|
|
25
|
+
// (highest-ranked) relation to a node wins.
|
|
26
|
+
if (seen.has(node.id)) continue;
|
|
27
|
+
seen.add(node.id);
|
|
28
|
+
const ref: IGraphDetails.IReference = {
|
|
29
|
+
...summaryOf(node),
|
|
30
|
+
relation: edge.kind,
|
|
31
|
+
};
|
|
32
|
+
if (edge.evidence !== undefined) ref.evidence = publicEvidence(edge.evidence);
|
|
33
|
+
out.push(ref);
|
|
34
|
+
if (out.length >= limit) break;
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GraphMemory } from "../model/GraphMemory";
|
|
2
|
+
import { IGraphNode } from "../structures";
|
|
3
|
+
|
|
4
|
+
export function resolveHandle(
|
|
5
|
+
graph: GraphMemory,
|
|
6
|
+
handle: string,
|
|
7
|
+
): { node?: IGraphNode; candidates?: IGraphNode[] } {
|
|
8
|
+
const trimmed = handle.trim();
|
|
9
|
+
if (trimmed === "") return {};
|
|
10
|
+
const exact = graph.node(trimmed);
|
|
11
|
+
if (exact !== undefined) return { node: exact };
|
|
12
|
+
const symbolMatches = graph.symbols(trimmed);
|
|
13
|
+
if (symbolMatches.length === 1) return { node: symbolMatches[0] };
|
|
14
|
+
if (symbolMatches.length > 1) return { candidates: symbolMatches.slice(0, 8) };
|
|
15
|
+
const lowered = trimmed.toLowerCase();
|
|
16
|
+
const fuzzy = graph.nodes
|
|
17
|
+
.filter(
|
|
18
|
+
(node) =>
|
|
19
|
+
node.kind !== "file" &&
|
|
20
|
+
((node.qualifiedName ?? node.name).toLowerCase().endsWith(lowered) ||
|
|
21
|
+
node.file.toLowerCase().endsWith(lowered)),
|
|
22
|
+
)
|
|
23
|
+
.slice(0, 8);
|
|
24
|
+
if (fuzzy.length === 1) return { node: fuzzy[0] };
|
|
25
|
+
if (fuzzy.length > 1) return { candidates: fuzzy };
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IGraphNext } from "../structures";
|
|
2
|
+
|
|
3
|
+
export function resultNext(
|
|
4
|
+
action: IGraphNext["action"],
|
|
5
|
+
reason: string,
|
|
6
|
+
request?: IGraphNext["request"],
|
|
7
|
+
): IGraphNext {
|
|
8
|
+
return request === undefined ? { action, reason } : { action, request, reason };
|
|
9
|
+
}
|