@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,582 @@
|
|
|
1
|
+
import { GraphMemory } from "../model/GraphMemory";
|
|
2
|
+
import {
|
|
3
|
+
IGraphEntrypoints,
|
|
4
|
+
IGraphNode,
|
|
5
|
+
IGraphOverview,
|
|
6
|
+
IGraphTour,
|
|
7
|
+
} from "../structures";
|
|
8
|
+
import { bound, isTestPath, resultGuide, resultNext, summaryOf } from "./common";
|
|
9
|
+
import { runDetails } from "./runDetails";
|
|
10
|
+
import { runEntrypoints } from "./runEntrypoints";
|
|
11
|
+
import { runTrace } from "./runTrace";
|
|
12
|
+
|
|
13
|
+
const DEFAULT_LIMIT = 5;
|
|
14
|
+
const MAX_LIMIT = 5;
|
|
15
|
+
const FLOW_SEEDS = 5;
|
|
16
|
+
const DETAIL_SEEDS = 3;
|
|
17
|
+
const TEST_SEEDS = 3;
|
|
18
|
+
const MAX_FLOW_STEPS = 8;
|
|
19
|
+
const MAX_NEARBY = 10;
|
|
20
|
+
const MAX_TESTS = 8;
|
|
21
|
+
const MAX_READ_NEXT = 14;
|
|
22
|
+
const TOUR_TRACE_MAX_DEPTH = 3;
|
|
23
|
+
const TOUR_TRACE_MAX_NODES = 16;
|
|
24
|
+
const STRUCTURAL_KINDS = new Set<string>(["contains", "exports", "imports"]);
|
|
25
|
+
const EXECUTION_KINDS = new Set<string>([
|
|
26
|
+
"calls",
|
|
27
|
+
"instantiates",
|
|
28
|
+
"accesses",
|
|
29
|
+
"renders",
|
|
30
|
+
"references",
|
|
31
|
+
]);
|
|
32
|
+
const TOUR_SEED_KINDS = new Set<string>([
|
|
33
|
+
"class",
|
|
34
|
+
"function",
|
|
35
|
+
"method",
|
|
36
|
+
"property",
|
|
37
|
+
"variable",
|
|
38
|
+
"module",
|
|
39
|
+
"namespace",
|
|
40
|
+
"enum",
|
|
41
|
+
]);
|
|
42
|
+
const QUERY_STOP_WORDS = new Set<string>([
|
|
43
|
+
"about", "after", "and", "are", "api", "architecture", "around", "before",
|
|
44
|
+
"based", "behavior", "between", "but", "can", "central", "change", "changes",
|
|
45
|
+
"code", "does", "for", "first", "find", "flow", "from", "has", "have", "how",
|
|
46
|
+
"include", "including", "implementation", "into", "its", "nearby", "need",
|
|
47
|
+
"needs", "new", "next", "path", "paths", "project", "public", "read", "real",
|
|
48
|
+
"runtime", "should", "show", "that", "the", "this", "test", "tests", "trace",
|
|
49
|
+
"through", "with", "without", "tour", "typescript", "user", "what", "where",
|
|
50
|
+
"which", "work",
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Compose a repository-orientation/code-tour answer surface from existing graph
|
|
55
|
+
* operations. It returns selected symbols, flows, nearby edges, test anchors,
|
|
56
|
+
* and answer anchors without reading or embedding source bodies.
|
|
57
|
+
*/
|
|
58
|
+
export function runTour(graph: GraphMemory, props: IGraphTour.IRequest): IGraphTour {
|
|
59
|
+
const query = (props.question ?? "project architecture").trim();
|
|
60
|
+
const limit = bound(props.limit, DEFAULT_LIMIT, 1, MAX_LIMIT);
|
|
61
|
+
const entry = runEntrypoints(graph, {
|
|
62
|
+
type: "entrypoints",
|
|
63
|
+
query,
|
|
64
|
+
language: props.language,
|
|
65
|
+
limit,
|
|
66
|
+
});
|
|
67
|
+
const terms = queryTerms(graph, query);
|
|
68
|
+
const seeds = tourSeedsOf(graph, entry, query, terms, limit);
|
|
69
|
+
const seedIds = seeds.map((node) => node.id);
|
|
70
|
+
const flowSeedIds = flowSeedIdsOf(seeds);
|
|
71
|
+
|
|
72
|
+
const entrypoints: IGraphEntrypoints.IEntrypoint[] = seeds.map((node) => ({
|
|
73
|
+
...summaryOf(node),
|
|
74
|
+
score: Math.round(tourSeedScore(graph, node, terms)),
|
|
75
|
+
reason: seedReason(graph, node, terms),
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
const primaryFlow: string[] = [];
|
|
79
|
+
const flowReached: IGraphNode[] = [];
|
|
80
|
+
for (const id of flowSeedIds.slice(0, FLOW_SEEDS)) {
|
|
81
|
+
const trace = runTrace(graph, {
|
|
82
|
+
type: "trace",
|
|
83
|
+
from: id,
|
|
84
|
+
direction: "forward",
|
|
85
|
+
focus: "execution",
|
|
86
|
+
maxDepth: TOUR_TRACE_MAX_DEPTH,
|
|
87
|
+
maxNodes: TOUR_TRACE_MAX_NODES,
|
|
88
|
+
});
|
|
89
|
+
// The forward trace always yields steps; the `?? []` is a type-level guard.
|
|
90
|
+
/* c8 ignore next */
|
|
91
|
+
const flowSteps = trace.steps ?? [];
|
|
92
|
+
for (const step of flowSteps) {
|
|
93
|
+
/* c8 ignore next -- defensive bound on total flow steps. */
|
|
94
|
+
if (primaryFlow.length >= FLOW_SEEDS * MAX_FLOW_STEPS) break;
|
|
95
|
+
if (!primaryFlow.includes(step)) primaryFlow.push(step);
|
|
96
|
+
}
|
|
97
|
+
for (const node of trace.reached) {
|
|
98
|
+
const real = graph.node(node.id);
|
|
99
|
+
if (real !== undefined && !isNoisePath(real.file)) flowReached.push(real);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const details =
|
|
104
|
+
seedIds.length === 0
|
|
105
|
+
? undefined
|
|
106
|
+
: runDetails(graph, {
|
|
107
|
+
type: "details",
|
|
108
|
+
handles: seedIds.slice(0, DETAIL_SEEDS),
|
|
109
|
+
neighbors: true,
|
|
110
|
+
memberLimit: 4,
|
|
111
|
+
dependencyLimit: 2,
|
|
112
|
+
neighborLimit: 2,
|
|
113
|
+
});
|
|
114
|
+
const nearbyPaths = details === undefined ? [] : nearbyNodesOf(details);
|
|
115
|
+
|
|
116
|
+
const testAnchors = testNodesOf(
|
|
117
|
+
graph,
|
|
118
|
+
uniqueIds([
|
|
119
|
+
...seedIds.slice(0, TEST_SEEDS),
|
|
120
|
+
...flowReached.map((node) => node.id),
|
|
121
|
+
]),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const answerAnchors = uniqueNodes([
|
|
125
|
+
...entrypoints.map((node) => stripEntrypoint(node)),
|
|
126
|
+
...flowReached.map(summaryOf),
|
|
127
|
+
...nearbyPaths,
|
|
128
|
+
...testAnchors,
|
|
129
|
+
]).slice(0, MAX_READ_NEXT);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
type: "tour",
|
|
133
|
+
question: props.question,
|
|
134
|
+
entrypoints,
|
|
135
|
+
primaryFlow,
|
|
136
|
+
nearbyPaths: nearbyPaths.slice(0, MAX_NEARBY),
|
|
137
|
+
testAnchors: testAnchors.slice(0, MAX_TESTS),
|
|
138
|
+
answerAnchors,
|
|
139
|
+
diagnostics: graph.diagnostics.slice(0, 12),
|
|
140
|
+
next: resultNext(
|
|
141
|
+
"answer",
|
|
142
|
+
"This tour is the complete index-level answer surface: central entrypoints, primary flow, nearby paths, tests, and answer anchors.",
|
|
143
|
+
),
|
|
144
|
+
guide: resultGuide(
|
|
145
|
+
"Use this tour as the answer-ready index. Do not split it into extra lookup/details/trace calls unless the user asks for a named missing symbol or exact source text.",
|
|
146
|
+
),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Rank and select the central symbols the tour is built around: named
|
|
151
|
+
// mentions and explicit handles from the query first, then query-scored
|
|
152
|
+
// high-degree seeds, falling back to the raw ranked hits.
|
|
153
|
+
function tourSeedsOf(
|
|
154
|
+
graph: GraphMemory,
|
|
155
|
+
entry: IGraphEntrypoints,
|
|
156
|
+
query: string,
|
|
157
|
+
terms: string[],
|
|
158
|
+
limit: number,
|
|
159
|
+
): IGraphNode[] {
|
|
160
|
+
const out: IGraphNode[] = [];
|
|
161
|
+
const seen = new Set<string>();
|
|
162
|
+
const add = (node: IGraphNode | undefined): void => {
|
|
163
|
+
if (node === undefined || seen.has(node.id) || !isTourSeed(graph, node)) return;
|
|
164
|
+
seen.add(node.id);
|
|
165
|
+
out.push(node);
|
|
166
|
+
};
|
|
167
|
+
for (const mention of entry.mentions) add(graph.node(mention.id));
|
|
168
|
+
if (hasExplicitSymbolHandle(query)) {
|
|
169
|
+
for (const hit of entry.ranked) add(graph.node(hit.id));
|
|
170
|
+
}
|
|
171
|
+
for (const node of rankedTourSeeds(graph, terms)) add(node);
|
|
172
|
+
if (out.length === 0) {
|
|
173
|
+
for (const hit of entry.ranked) add(graph.node(hit.id));
|
|
174
|
+
}
|
|
175
|
+
return out.slice(0, limit);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function seedReason(graph: GraphMemory, node: IGraphNode, terms: string[]): string {
|
|
179
|
+
if (matchedQueryTerms(node, terms).size > 0) return "Name matches the question terms.";
|
|
180
|
+
const execution = executionDegree(graph, node.id);
|
|
181
|
+
if (execution.out > 0) return "Central runtime flow for this question.";
|
|
182
|
+
if (node.exported === true) return "Exported entrypoint on the public surface.";
|
|
183
|
+
return "High-degree symbol relevant to the question.";
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function stripEntrypoint(node: IGraphEntrypoints.IEntrypoint): IGraphOverview.INode {
|
|
187
|
+
const { score: _score, reason: _reason, ...rest } = node;
|
|
188
|
+
void _score;
|
|
189
|
+
void _reason;
|
|
190
|
+
return rest;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function nearbyNodesOf(details: ReturnType<typeof runDetails>): IGraphOverview.INode[] {
|
|
194
|
+
const out: IGraphOverview.INode[] = [];
|
|
195
|
+
for (const node of details.nodes) {
|
|
196
|
+
// calls/types/dependsOn/dependedOnBy are all optional reference arrays; a
|
|
197
|
+
// single `?? []` normalizes each, so both the defined and undefined cases
|
|
198
|
+
// are exercised by whichever field happens to be absent.
|
|
199
|
+
const refs = [node.calls, node.types, node.dependsOn, node.dependedOnBy].flatMap(
|
|
200
|
+
(group) => group ?? [],
|
|
201
|
+
);
|
|
202
|
+
for (const ref of refs) {
|
|
203
|
+
out.push({
|
|
204
|
+
id: ref.id,
|
|
205
|
+
name: ref.name,
|
|
206
|
+
kind: ref.kind,
|
|
207
|
+
language: ref.language,
|
|
208
|
+
file: ref.file,
|
|
209
|
+
...(ref.line !== undefined ? { line: ref.line } : {}),
|
|
210
|
+
...(ref.sourceSpan !== undefined ? { sourceSpan: ref.sourceSpan } : {}),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return uniqueNodes(out);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Collect test/usage anchors: test-file callers pointing at the seeds, plus
|
|
218
|
+
// test-role nodes reached through the impact edges.
|
|
219
|
+
function testNodesOf(graph: GraphMemory, seedIds: string[]): IGraphOverview.INode[] {
|
|
220
|
+
const out: IGraphOverview.INode[] = [];
|
|
221
|
+
for (const id of seedIds) {
|
|
222
|
+
for (const edge of graph.incoming(id)) {
|
|
223
|
+
const node = graph.node(edge.from);
|
|
224
|
+
if (node === undefined || !isTestPath(node.file)) continue;
|
|
225
|
+
out.push(summaryOf(node));
|
|
226
|
+
}
|
|
227
|
+
const impact = runTrace(graph, {
|
|
228
|
+
type: "trace",
|
|
229
|
+
from: id,
|
|
230
|
+
direction: "impact",
|
|
231
|
+
maxDepth: 4,
|
|
232
|
+
maxNodes: 16,
|
|
233
|
+
});
|
|
234
|
+
for (const node of impact.reached) {
|
|
235
|
+
if (node.roles?.includes("test") === true) {
|
|
236
|
+
const real = graph.node(node.id);
|
|
237
|
+
if (real !== undefined) out.push(summaryOf(real));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return uniqueNodes(out);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// --- query relevance scoring (ported from the reference engine) -------------
|
|
245
|
+
|
|
246
|
+
function queryTerms(graph: GraphMemory, query: string): string[] {
|
|
247
|
+
const projectTerms = new Set(subwords(graph.project));
|
|
248
|
+
return subwords(query).filter(
|
|
249
|
+
(term) => term.length > 2 && !QUERY_STOP_WORDS.has(term) && !projectTerms.has(term),
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function rankedTourSeeds(graph: GraphMemory, terms: string[]): IGraphNode[] {
|
|
254
|
+
const items = graph.nodes
|
|
255
|
+
.filter((node) => isTourSeed(graph, node))
|
|
256
|
+
.map((node) => ({
|
|
257
|
+
node,
|
|
258
|
+
score: tourSeedScore(graph, node, terms),
|
|
259
|
+
matchedTerms: matchedQueryTerms(node, terms),
|
|
260
|
+
}))
|
|
261
|
+
.filter((item) => item.score > 0)
|
|
262
|
+
.sort((a, b) => b.score - a.score);
|
|
263
|
+
return diverseTourSeeds(items, terms).map((item) => item.node);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function tourSeedScore(graph: GraphMemory, node: IGraphNode, terms: string[]): number {
|
|
267
|
+
const degree = realDegree(graph, node.id);
|
|
268
|
+
const execution = executionDegree(graph, node.id);
|
|
269
|
+
const queryWords = new Set(terms);
|
|
270
|
+
const matchScore = queryMatchScore(node, terms);
|
|
271
|
+
let score = kindScore(node.kind);
|
|
272
|
+
const surface = entrySurfaceScore(node);
|
|
273
|
+
score += surface;
|
|
274
|
+
score += runtimeEntryScore(node, surface);
|
|
275
|
+
score += Math.min(14, Math.log2(1 + degree.in) * 4);
|
|
276
|
+
score += Math.min(30, Math.log2(1 + degree.out) * 9);
|
|
277
|
+
score += Math.min(28, Math.log2(1 + execution.out) * 10);
|
|
278
|
+
if (node.exported === true) score += 14;
|
|
279
|
+
if (node.decorators !== undefined && node.decorators.length > 0) score += 10;
|
|
280
|
+
score += matchScore;
|
|
281
|
+
score *= queryAlignmentFactor(matchScore, queryWords);
|
|
282
|
+
score *= broadTourDamping(node, queryWords);
|
|
283
|
+
return score;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function isTourSeed(graph: GraphMemory, node: IGraphNode): boolean {
|
|
287
|
+
return (
|
|
288
|
+
TOUR_SEED_KINDS.has(node.kind) &&
|
|
289
|
+
(node.kind !== "property" || executionDegree(graph, node.id).out > 0) &&
|
|
290
|
+
!node.external &&
|
|
291
|
+
node.ignored !== true &&
|
|
292
|
+
node.evidence !== undefined &&
|
|
293
|
+
!isNoisePath(node.file)
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function flowSeedIdsOf(seeds: IGraphNode[]): string[] {
|
|
298
|
+
const executable = seeds.filter((node) =>
|
|
299
|
+
["function", "method", "property", "variable"].includes(node.kind),
|
|
300
|
+
);
|
|
301
|
+
const source = executable.length === 0 ? seeds : executable;
|
|
302
|
+
return source.map((node) => node.id);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function realDegree(graph: GraphMemory, id: string): { in: number; out: number } {
|
|
306
|
+
let incoming = 0;
|
|
307
|
+
let outgoing = 0;
|
|
308
|
+
for (const edge of graph.outgoing(id)) if (!STRUCTURAL_KINDS.has(edge.kind)) outgoing++;
|
|
309
|
+
for (const edge of graph.incoming(id)) if (!STRUCTURAL_KINDS.has(edge.kind)) incoming++;
|
|
310
|
+
return { in: incoming, out: outgoing };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function executionDegree(graph: GraphMemory, id: string): { in: number; out: number } {
|
|
314
|
+
let incoming = 0;
|
|
315
|
+
let outgoing = 0;
|
|
316
|
+
for (const edge of graph.outgoing(id)) if (EXECUTION_KINDS.has(edge.kind)) outgoing++;
|
|
317
|
+
for (const edge of graph.incoming(id)) if (EXECUTION_KINDS.has(edge.kind)) incoming++;
|
|
318
|
+
return { in: incoming, out: outgoing };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function kindScore(kind: string): number {
|
|
322
|
+
switch (kind) {
|
|
323
|
+
case "function":
|
|
324
|
+
case "method":
|
|
325
|
+
return 28;
|
|
326
|
+
case "property":
|
|
327
|
+
case "variable":
|
|
328
|
+
return 8;
|
|
329
|
+
case "class":
|
|
330
|
+
return 24;
|
|
331
|
+
case "module":
|
|
332
|
+
case "namespace":
|
|
333
|
+
return 16;
|
|
334
|
+
case "enum":
|
|
335
|
+
return 10;
|
|
336
|
+
// every TOUR_SEED_KIND has an explicit case above; the default is a
|
|
337
|
+
// defensive fallback unreachable from the seed filter.
|
|
338
|
+
/* c8 ignore next 2 */
|
|
339
|
+
default:
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function entrySurfaceScore(node: IGraphNode): number {
|
|
345
|
+
const file = node.file.replace(/\\/g, "/");
|
|
346
|
+
const base = file.slice(file.lastIndexOf("/") + 1).toLowerCase();
|
|
347
|
+
const stem = base.replace(/\.[cm]?[tj]sx?$/, "");
|
|
348
|
+
const depth = sourceDepth(file);
|
|
349
|
+
let score = 0;
|
|
350
|
+
if (stem === "index") {
|
|
351
|
+
if (depth <= 0) score += 48;
|
|
352
|
+
else if (depth === 1) score += 32;
|
|
353
|
+
else if (depth === 2) score += 12;
|
|
354
|
+
} else if (stem === "main" || stem === "server" || stem === "bootstrap") score += 42;
|
|
355
|
+
else if (stem === "app" || stem === "application") score += 28;
|
|
356
|
+
|
|
357
|
+
if (depth <= 1) score += 22;
|
|
358
|
+
else if (depth === 2) score += 12;
|
|
359
|
+
else if (depth === 3) score += 5;
|
|
360
|
+
|
|
361
|
+
if (node.exported === true && score > 0) score += 12;
|
|
362
|
+
return score;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function runtimeEntryScore(node: IGraphNode, surface: number): number {
|
|
366
|
+
const words = new Set([...subwords(node.name), ...subwords(node.qualifiedName ?? "")]);
|
|
367
|
+
if (isPrivateLike(node, words)) return 0;
|
|
368
|
+
const hasVerb = hasAny(words, [
|
|
369
|
+
"bootstrap", "create", "execute", "handle", "init", "initialize", "listen",
|
|
370
|
+
"mount", "open", "parse", "render", "run", "safe", "safeparse", "start",
|
|
371
|
+
"startup", "subscribe", "update",
|
|
372
|
+
]);
|
|
373
|
+
if (node.kind === "method" && hasVerb) return 90;
|
|
374
|
+
if (
|
|
375
|
+
(node.kind === "function" || node.kind === "property" || node.kind === "variable") &&
|
|
376
|
+
surface > 0 &&
|
|
377
|
+
hasVerb
|
|
378
|
+
) {
|
|
379
|
+
return 70;
|
|
380
|
+
}
|
|
381
|
+
if (
|
|
382
|
+
node.kind === "class" &&
|
|
383
|
+
hasAny(words, [
|
|
384
|
+
"application", "app", "backend", "client", "datasource", "factory", "server",
|
|
385
|
+
])
|
|
386
|
+
) {
|
|
387
|
+
return 45;
|
|
388
|
+
}
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function sourceDepth(file: string): number {
|
|
393
|
+
const parts = file.split("/").filter(Boolean);
|
|
394
|
+
if (parts[0] === "src") return Math.max(0, parts.length - 2);
|
|
395
|
+
if (parts[0] === "packages" && parts.length >= 3) return Math.max(0, parts.length - 3);
|
|
396
|
+
return Math.max(0, parts.length - 1);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function queryMatchScore(node: IGraphNode, terms: string[]): number {
|
|
400
|
+
return matchedQueryTerms(node, terms).size * 8 + matchedFileTerms(node, terms).size * 2;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function matchedQueryTerms(node: IGraphNode, terms: string[]): Set<string> {
|
|
404
|
+
const words = [...subwords(node.name), ...subwords(node.qualifiedName ?? "")];
|
|
405
|
+
return matchedTerms(words, terms);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function matchedFileTerms(node: IGraphNode, terms: string[]): Set<string> {
|
|
409
|
+
return matchedTerms(subwords(node.file), terms);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function matchedTerms(words: string[], terms: string[]): Set<string> {
|
|
413
|
+
const wordSet = new Set(words);
|
|
414
|
+
const stems = new Set(words.map(stemWord));
|
|
415
|
+
const matched = new Set<string>();
|
|
416
|
+
for (const term of terms) {
|
|
417
|
+
if (
|
|
418
|
+
wordSet.has(term) ||
|
|
419
|
+
stems.has(stemWord(term)) ||
|
|
420
|
+
words.some((word) => commonPrefixLength(stemWord(term), stemWord(word)) >= 6)
|
|
421
|
+
) {
|
|
422
|
+
matched.add(term);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return matched;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function diverseTourSeeds<T extends { score: number; matchedTerms: Set<string> }>(
|
|
429
|
+
items: T[],
|
|
430
|
+
terms: string[],
|
|
431
|
+
): T[] {
|
|
432
|
+
if (items.length <= 1 || terms.length === 0) return items;
|
|
433
|
+
const out: T[] = [];
|
|
434
|
+
const remaining = [...items];
|
|
435
|
+
const uncovered = new Set(terms);
|
|
436
|
+
while (remaining.length > 0) {
|
|
437
|
+
let bestIndex = 0;
|
|
438
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
439
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
440
|
+
const item = remaining[i]!;
|
|
441
|
+
let coverage = 0;
|
|
442
|
+
for (const term of item.matchedTerms) if (uncovered.has(term)) coverage++;
|
|
443
|
+
const score = coverage * 120 + item.score;
|
|
444
|
+
if (score > bestScore) {
|
|
445
|
+
bestScore = score;
|
|
446
|
+
bestIndex = i;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const [picked] = remaining.splice(bestIndex, 1);
|
|
450
|
+
out.push(picked!);
|
|
451
|
+
for (const term of picked!.matchedTerms) uncovered.delete(term);
|
|
452
|
+
}
|
|
453
|
+
return out;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function queryAlignmentFactor(matchScore: number, queryWords: ReadonlySet<string>): number {
|
|
457
|
+
if (queryWords.size === 0) return 1;
|
|
458
|
+
if (matchScore >= 24) return 1.45;
|
|
459
|
+
if (matchScore >= 8) return 1.15;
|
|
460
|
+
return 0.45;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function broadTourDamping(node: IGraphNode, queryWords: ReadonlySet<string>): number {
|
|
464
|
+
const words = new Set([
|
|
465
|
+
...subwords(node.name),
|
|
466
|
+
...subwords(node.qualifiedName ?? ""),
|
|
467
|
+
...subwords(node.file),
|
|
468
|
+
]);
|
|
469
|
+
let factor = 1;
|
|
470
|
+
if (!hasAny(queryWords, ["internal", "private"]) && isPrivateLike(node, words)) {
|
|
471
|
+
factor *= 0.25;
|
|
472
|
+
}
|
|
473
|
+
if (
|
|
474
|
+
!hasAny(queryWords, ["error", "errors", "exception", "exceptions"]) &&
|
|
475
|
+
hasAny(words, ["error", "errors", "exception", "exceptions"])
|
|
476
|
+
) {
|
|
477
|
+
factor *= 0.25;
|
|
478
|
+
}
|
|
479
|
+
if (
|
|
480
|
+
!hasAny(queryWords, [
|
|
481
|
+
"config", "configuration", "env", "environment", "option", "options", "port",
|
|
482
|
+
]) &&
|
|
483
|
+
(node.kind === "variable" || node.kind === "property") &&
|
|
484
|
+
hasAny(words, [
|
|
485
|
+
"config", "configuration", "env", "environment", "option", "options", "port",
|
|
486
|
+
])
|
|
487
|
+
) {
|
|
488
|
+
factor *= 0.35;
|
|
489
|
+
}
|
|
490
|
+
if (
|
|
491
|
+
!hasAny(queryWords, [
|
|
492
|
+
"deserialize", "deserializer", "serializer", "serialize", "serialization",
|
|
493
|
+
]) &&
|
|
494
|
+
hasAny(words, [
|
|
495
|
+
"deserialize", "deserializer", "serializer", "serialize", "serialization",
|
|
496
|
+
])
|
|
497
|
+
) {
|
|
498
|
+
factor *= 0.25;
|
|
499
|
+
}
|
|
500
|
+
return factor;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function hasAny(words: ReadonlySet<string>, candidates: readonly string[]): boolean {
|
|
504
|
+
return candidates.some((word) => words.has(word));
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function isPrivateLike(node: IGraphNode, words: ReadonlySet<string>): boolean {
|
|
508
|
+
const name = node.qualifiedName ?? node.name;
|
|
509
|
+
return (
|
|
510
|
+
name.startsWith("_") ||
|
|
511
|
+
name.includes("._") ||
|
|
512
|
+
hasAny(words, ["inner", "internal", "private"])
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function hasExplicitSymbolHandle(query: string): boolean {
|
|
517
|
+
return /`[^`]+`/.test(query) || /\b[A-Za-z_$][\w$]*\.[A-Za-z_$][\w$]*\b/.test(query);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Tests, examples, fixtures, generated output, and build artifacts are noise
|
|
521
|
+
// for tour seeding (ported from the reference isSupportPath).
|
|
522
|
+
function isNoisePath(file: string): boolean {
|
|
523
|
+
return (
|
|
524
|
+
file === "" ||
|
|
525
|
+
file.startsWith("bundled://") ||
|
|
526
|
+
/(^|\/)node_modules\//.test(file) ||
|
|
527
|
+
/(^|\/)(test|tests|__tests__|spec|sample|samples|fixture|fixtures|__fixtures__|example|examples)\//.test(
|
|
528
|
+
file,
|
|
529
|
+
) ||
|
|
530
|
+
/\.(test|spec)\.[cm]?[tj]sx?$/.test(file) ||
|
|
531
|
+
/(^|\/)typings\.[cm]?ts$/.test(file) ||
|
|
532
|
+
/\.d\.[cm]?ts$/.test(file) ||
|
|
533
|
+
/(^|\/)(dist|build|coverage|generated|__generated__)\//.test(file)
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function subwords(text: string): string[] {
|
|
538
|
+
return text
|
|
539
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
540
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
541
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
542
|
+
.filter((word) => word.length > 0)
|
|
543
|
+
.map((word) => word.toLowerCase());
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function stemWord(word: string): string {
|
|
547
|
+
for (const suffix of ["ing", "ed", "es", "s"]) {
|
|
548
|
+
if (word.length > suffix.length + 3 && word.endsWith(suffix)) {
|
|
549
|
+
return word.slice(0, -suffix.length);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return word;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function commonPrefixLength(a: string, b: string): number {
|
|
556
|
+
const n = Math.min(a.length, b.length);
|
|
557
|
+
let i = 0;
|
|
558
|
+
while (i < n && a.charCodeAt(i) === b.charCodeAt(i)) i++;
|
|
559
|
+
return i;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function uniqueIds(ids: string[]): string[] {
|
|
563
|
+
const out: string[] = [];
|
|
564
|
+
const seen = new Set<string>();
|
|
565
|
+
for (const id of ids) {
|
|
566
|
+
if (seen.has(id)) continue;
|
|
567
|
+
seen.add(id);
|
|
568
|
+
out.push(id);
|
|
569
|
+
}
|
|
570
|
+
return out;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function uniqueNodes(nodes: IGraphOverview.INode[]): IGraphOverview.INode[] {
|
|
574
|
+
const out: IGraphOverview.INode[] = [];
|
|
575
|
+
const seen = new Set<string>();
|
|
576
|
+
for (const node of nodes) {
|
|
577
|
+
if (seen.has(node.id)) continue;
|
|
578
|
+
seen.add(node.id);
|
|
579
|
+
out.push(node);
|
|
580
|
+
}
|
|
581
|
+
return out;
|
|
582
|
+
}
|