@saptools/service-flow 0.1.68 → 0.1.70
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/CHANGELOG.md +14 -0
- package/README.md +11 -5
- package/TECHNICAL-NOTE.md +13 -0
- package/dist/{chunk-AEM4JY22.js → chunk-GSLFY6J2.js} +6986 -5503
- package/dist/chunk-GSLFY6J2.js.map +1 -0
- package/dist/cli.js +334 -122
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/cli/{002-doctor-lifecycle.ts → doctor-lifecycle.ts} +1 -1
- package/src/cli/{001-doctor-projection.ts → doctor-projection.ts} +1 -1
- package/src/cli/doctor.ts +5 -5
- package/src/cli/index-summary.ts +22 -0
- package/src/cli.ts +155 -91
- package/src/db/{009-binding-fact-semantics.ts → binding-fact-semantics.ts} +6 -1
- package/src/db/binding-helper-provenance.ts +17 -0
- package/src/db/{012-binding-reference-proof.ts → binding-reference-proof.ts} +4 -0
- package/src/db/{000-call-fact-repository.ts → call-fact-repository.ts} +49 -23
- package/src/db/{003-current-fact-semantics.ts → current-fact-semantics.ts} +5 -4
- package/src/db/{001-fact-lifecycle.ts → fact-lifecycle.ts} +3 -3
- package/src/db/index-publication-failure.ts +91 -0
- package/src/db/{007-package-fact-semantics.ts → package-fact-semantics.ts} +6 -6
- package/src/db/{010-package-symbol-surface-semantics.ts → package-symbol-surface-semantics.ts} +2 -2
- package/src/db/{004-package-target-invalidation.ts → package-target-invalidation.ts} +11 -1
- package/src/db/{008-relative-fact-semantics.ts → relative-fact-semantics.ts} +9 -6
- package/src/db/{006-relative-symbol-resolution.ts → relative-symbol-resolution.ts} +28 -7
- package/src/db/repositories.ts +24 -7
- package/src/db/{011-symbol-call-semantics.ts → symbol-call-semantics.ts} +1 -1
- package/src/index.ts +3 -3
- package/src/indexer/cds-extension-resolver.ts +27 -3
- package/src/indexer/repository-indexer.ts +70 -9
- package/src/indexer/workspace-indexer.ts +142 -30
- package/src/linker/call-edge-insertion.ts +568 -0
- package/src/linker/{002-call-evidence.ts → call-evidence.ts} +2 -2
- package/src/linker/cross-repo-linker.ts +6 -169
- package/src/linker/dynamic-edge-resolver.ts +1 -1
- package/src/linker/{004-event-subscription-handler-linker.ts → event-subscription-handler-linker.ts} +32 -11
- package/src/linker/event-template-link.ts +72 -0
- package/src/linker/external-http-target.ts +1 -1
- package/src/linker/helper-package-linker.ts +1 -1
- package/src/linker/{000-implementation-candidates.ts → implementation-candidates.ts} +1 -1
- package/src/linker/{001-implementation-evidence-projection.ts → implementation-evidence-projection.ts} +1 -1
- package/src/linker/odata-path-normalizer.ts +1 -1
- package/src/linker/{005-odata-path-structure.ts → odata-path-structure.ts} +1 -1
- package/src/linker/{003-package-import-symbol-resolver.ts → package-import-symbol-resolver.ts} +3 -3
- package/src/linker/service-resolver.ts +2 -2
- package/src/output/{001-compact-json-output.ts → compact-json-output.ts} +1 -1
- package/src/parsers/{006-binding-identity.ts → binding-identity.ts} +9 -4
- package/src/parsers/{011-binding-lexical-scope.ts → binding-lexical-scope.ts} +1 -1
- package/src/parsers/{021-binding-visibility.ts → binding-visibility.ts} +18 -2
- package/src/parsers/{000-direct-query-execution.ts → direct-query-execution.ts} +11 -0
- package/src/parsers/{005-event-subscription-facts.ts → event-subscription-facts.ts} +2 -2
- package/src/parsers/{016-local-symbol-reference.ts → local-symbol-reference.ts} +2 -2
- package/src/parsers/operation-path-analysis.ts +1 -1
- package/src/parsers/outbound-call-classifier.ts +692 -0
- package/src/parsers/outbound-call-parser.ts +146 -509
- package/src/parsers/outbound-expression-analysis.ts +700 -0
- package/src/parsers/{018-package-commonjs-syntax.ts → package-commonjs-syntax.ts} +1 -1
- package/src/parsers/{012-package-fact-contract.ts → package-fact-contract.ts} +3 -3
- package/src/parsers/{010-package-public-surface-analysis.ts → package-public-surface-analysis.ts} +2 -2
- package/src/parsers/{003-package-public-surface.ts → package-public-surface.ts} +3 -3
- package/src/parsers/{008-package-surface-publication.ts → package-surface-publication.ts} +1 -1
- package/src/parsers/{001-query-entity-resolution.ts → query-entity-resolution.ts} +1 -1
- package/src/parsers/{015-service-binding-collector.ts → service-binding-collector.ts} +3 -3
- package/src/parsers/{014-service-binding-helper-flow.ts → service-binding-helper-flow.ts} +72 -6
- package/src/parsers/service-binding-parser-helpers.ts +1 -1
- package/src/parsers/service-binding-parser.ts +2 -2
- package/src/parsers/{007-source-fact-reconciliation.ts → source-fact-reconciliation.ts} +3 -3
- package/src/parsers/{020-stable-local-value.ts → stable-local-value.ts} +2 -2
- package/src/parsers/{009-symbol-call-facts.ts → symbol-call-facts.ts} +3 -3
- package/src/parsers/{017-symbol-derived-contexts.ts → symbol-derived-contexts.ts} +2 -2
- package/src/parsers/symbol-parser.ts +43 -11
- package/src/trace/{014-compact-contract.ts → compact-contract.ts} +6 -0
- package/src/trace/{021-compact-decision-normalization.ts → compact-decision-normalization.ts} +77 -11
- package/src/trace/{020-compact-field-projection.ts → compact-field-projection.ts} +77 -4
- package/src/trace/{024-compact-observation-decision.ts → compact-observation-decision.ts} +10 -5
- package/src/trace/{016-compact-projector.ts → compact-projector.ts} +6 -7
- package/src/trace/{018-compact-trace.ts → compact-trace.ts} +3 -3
- package/src/trace/{006-contextual-projection.ts → contextual-projection.ts} +1 -1
- package/src/trace/{008-contextual-runtime-state.ts → contextual-runtime-state.ts} +1 -1
- package/src/trace/{001-dynamic-identity.ts → dynamic-identity.ts} +2 -2
- package/src/trace/{003-dynamic-references.ts → dynamic-references.ts} +2 -2
- package/src/trace/dynamic-targets.ts +6 -6
- package/src/trace/event-runtime-resolution.ts +151 -0
- package/src/trace/{011-event-subscriber-traversal.ts → event-subscriber-traversal.ts} +101 -9
- package/src/trace/evidence.ts +2 -2
- package/src/trace/implementation-hints.ts +10 -7
- package/src/trace/{005-implementation-selection.ts → implementation-selection.ts} +2 -2
- package/src/trace/{007-implementation-start-diagnostic.ts → implementation-start-diagnostic.ts} +1 -0
- package/src/trace/local-call-expansion.ts +37 -0
- package/src/trace/{009-selected-handler-provenance.ts → selected-handler-provenance.ts} +1 -1
- package/src/trace/selectors.ts +2 -1
- package/src/trace/{017-trace-context.ts → trace-context.ts} +2 -2
- package/src/trace/{015-trace-edge-recorder.ts → trace-edge-recorder.ts} +62 -5
- package/src/trace/{019-trace-edge-semantics.ts → trace-edge-semantics.ts} +9 -13
- package/src/trace/trace-engine.ts +10 -10
- package/src/trace/{022-trace-fact-preflight.ts → trace-fact-preflight.ts} +2 -2
- package/src/trace/{025-trace-implementation-scope.ts → trace-implementation-scope.ts} +1 -1
- package/src/trace/{028-trace-operation-execution.ts → trace-operation-execution.ts} +10 -10
- package/src/trace/{013-trace-root-scopes.ts → trace-root-scopes.ts} +5 -6
- package/src/trace/{027-trace-scope-execution.ts → trace-scope-execution.ts} +44 -44
- package/src/trace/{029-trace-start-implementation.ts → trace-start-implementation.ts} +7 -7
- package/src/trace/{026-trace-start-scope.ts → trace-start-scope.ts} +6 -5
- package/src/trace/{010-traversal-scope.ts → traversal-scope.ts} +1 -1
- package/src/types.ts +2 -1
- package/src/version.ts +1 -1
- package/dist/chunk-AEM4JY22.js.map +0 -1
- /package/src/cli/{000-clean.ts → clean.ts} +0 -0
- /package/src/cli/{003-doctor-package-resolution.ts → doctor-package-resolution.ts} +0 -0
- /package/src/db/{002-fact-json-inventory.ts → fact-json-inventory.ts} +0 -0
- /package/src/db/{005-schema-structure.ts → schema-structure.ts} +0 -0
- /package/src/output/{000-stdout-policy.ts → stdout-policy.ts} +0 -0
- /package/src/parsers/{019-binding-assignment-targets.ts → binding-assignment-targets.ts} +0 -0
- /package/src/parsers/{013-executable-body-eligibility.ts → executable-body-eligibility.ts} +0 -0
- /package/src/parsers/{004-fact-identity.ts → fact-identity.ts} +0 -0
- /package/src/parsers/{002-symbol-import-bindings.ts → symbol-import-bindings.ts} +0 -0
- /package/src/trace/{004-dynamic-candidate-sources.ts → dynamic-candidate-sources.ts} +0 -0
- /package/src/trace/{000-dynamic-target-types.ts → dynamic-target-types.ts} +0 -0
- /package/src/trace/{023-nested-event-scopes.ts → nested-event-scopes.ts} +0 -0
- /package/src/trace/{002-trace-diagnostics.ts → trace-diagnostics.ts} +0 -0
- /package/src/trace/{012-trace-graph-lookups.ts → trace-graph-lookups.ts} +0 -0
- /package/src/utils/{000-bounded-projection.ts → bounded-projection.ts} +0 -0
- /package/src/utils/{001-placeholders.ts → placeholders.ts} +0 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PACKAGE_PUBLIC_SURFACE_RECORD_CAP,
|
|
3
3
|
PACKAGE_PUBLIC_SURFACE_SCHEMA,
|
|
4
|
-
} from './
|
|
4
|
+
} from './package-public-surface.js';
|
|
5
5
|
import type {
|
|
6
6
|
ExecutableBodyEligibility,
|
|
7
7
|
PackagePublicEntry,
|
|
8
8
|
PackagePublicScope,
|
|
9
9
|
PackagePublicSurfaceFact,
|
|
10
10
|
PublicSurfaceTarget,
|
|
11
|
-
} from './
|
|
11
|
+
} from './package-public-surface.js';
|
|
12
12
|
import {
|
|
13
13
|
packageModuleRequest,
|
|
14
14
|
type SymbolImportBindingKind,
|
|
15
15
|
type SymbolImportReference,
|
|
16
16
|
type SymbolImportReferenceShape,
|
|
17
|
-
} from './
|
|
17
|
+
} from './symbol-import-bindings.js';
|
|
18
18
|
|
|
19
19
|
const bindingKinds = new Set<SymbolImportBindingKind>([
|
|
20
20
|
'esm_named', 'esm_default', 'esm_namespace',
|
package/src/parsers/{010-package-public-surface-analysis.ts → package-public-surface-analysis.ts}
RENAMED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
PACKAGE_PUBLIC_SURFACE_RECORD_CAP,
|
|
5
5
|
PACKAGE_PUBLIC_SURFACE_SCHEMA,
|
|
6
6
|
resolveModule,
|
|
7
|
-
} from './
|
|
7
|
+
} from './package-public-surface.js';
|
|
8
8
|
import type {
|
|
9
9
|
ModuleInfo,
|
|
10
10
|
ModuleResolution,
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
PackageSourceModule,
|
|
17
17
|
ResolvedExport,
|
|
18
18
|
SymbolPublicSurfaceEvidence,
|
|
19
|
-
} from './
|
|
19
|
+
} from './package-public-surface.js';
|
|
20
20
|
import type { PackageEntrypointManifest } from './package-json-parser.js';
|
|
21
21
|
|
|
22
22
|
interface EntryResolution {
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
hasNestedCommonJsMutation,
|
|
5
5
|
isUnshadowedCommonJsExportExpression,
|
|
6
6
|
unsupportedCommonJsMutation,
|
|
7
|
-
} from './
|
|
8
|
-
import { stableLocalValueReference } from './
|
|
7
|
+
} from './package-commonjs-syntax.js';
|
|
8
|
+
import { stableLocalValueReference } from './stable-local-value.js';
|
|
9
9
|
|
|
10
10
|
export const PACKAGE_PUBLIC_SURFACE_SCHEMA =
|
|
11
11
|
'service-flow/package-public-surface@1';
|
|
@@ -658,4 +658,4 @@ export function moduleInfoMap(
|
|
|
658
658
|
}
|
|
659
659
|
|
|
660
660
|
export { analyzePackagePublicSurface } from
|
|
661
|
-
'./
|
|
661
|
+
'./package-public-surface-analysis.js';
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
analyzePackagePublicSurface,
|
|
9
9
|
type PackagePublicSurfaceAnalysis,
|
|
10
10
|
type SymbolPublicSurfaceEvidence,
|
|
11
|
-
} from './
|
|
11
|
+
} from './package-public-surface.js';
|
|
12
12
|
import type { RepositorySourceContext } from './ts-project.js';
|
|
13
13
|
|
|
14
14
|
function symbolIdentity(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import { isCapQueryBuilderRootName } from './
|
|
2
|
+
import { isCapQueryBuilderRootName } from './direct-query-execution.js';
|
|
3
3
|
|
|
4
4
|
export interface BindingResolution {
|
|
5
5
|
declaration?: ts.VariableDeclaration | ts.ParameterDeclaration;
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
createBindingLexicalIndex,
|
|
16
16
|
type BindingLexicalIndex,
|
|
17
17
|
type BindingSiteCandidate,
|
|
18
|
-
} from './
|
|
19
|
-
import { selectVisibleBinding } from './
|
|
18
|
+
} from './binding-lexical-scope.js';
|
|
19
|
+
import { selectVisibleBinding } from './binding-visibility.js';
|
|
20
20
|
import {
|
|
21
21
|
arrayAssignmentName,
|
|
22
22
|
arrayBindingName,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
collectReturnedObjectBindings,
|
|
25
25
|
directConnectFactFromFunctionLike,
|
|
26
26
|
functionLikeInitializer,
|
|
27
|
-
} from './
|
|
27
|
+
} from './service-binding-helper-flow.js';
|
|
28
28
|
|
|
29
29
|
type ResolvedHelper = { helper: HelperBinding; imp?: ImportBinding };
|
|
30
30
|
type BindingEvent = {
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
type BindingLexicalIndex,
|
|
12
12
|
type BindingSiteCandidate,
|
|
13
13
|
type VisibleBinding,
|
|
14
|
-
} from './
|
|
15
|
-
import { selectVisibleBinding } from './
|
|
14
|
+
} from './binding-lexical-scope.js';
|
|
15
|
+
import { selectVisibleBinding } from './binding-visibility.js';
|
|
16
16
|
|
|
17
17
|
export type LocalBindingFact = Omit<
|
|
18
18
|
HelperBinding,
|
|
@@ -157,12 +157,58 @@ function returnedProperty(
|
|
|
157
157
|
return { propertyName, variableName: property.initializer.text };
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
function
|
|
160
|
+
function hazardousTryClause(
|
|
161
|
+
node: ts.Node | undefined,
|
|
162
|
+
fn: ts.FunctionLikeDeclaration,
|
|
163
|
+
anyReturn: boolean,
|
|
164
|
+
): boolean {
|
|
165
|
+
if (!node) return false;
|
|
166
|
+
let found = false;
|
|
167
|
+
const visit = (current: ts.Node): void => {
|
|
168
|
+
if (found || current !== fn && ts.isFunctionLike(current)) return;
|
|
169
|
+
if (ts.isReturnStatement(current)
|
|
170
|
+
&& (anyReturn || current.expression !== undefined)
|
|
171
|
+
|| ts.isCallExpression(current) && connectFactFromCall(current)) {
|
|
172
|
+
found = true;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
ts.forEachChild(current, visit);
|
|
176
|
+
};
|
|
177
|
+
visit(node);
|
|
178
|
+
return found;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function hasAncestor(node: ts.Node, ancestor: ts.Node): boolean {
|
|
182
|
+
let current: ts.Node | undefined = node.parent;
|
|
183
|
+
while (current) {
|
|
184
|
+
if (current === ancestor) return true;
|
|
185
|
+
current = current.parent;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function unsupportedTryAncestor(
|
|
191
|
+
statement: ts.TryStatement,
|
|
192
|
+
returned: ts.Node,
|
|
193
|
+
fn: ts.FunctionLikeDeclaration,
|
|
194
|
+
): boolean {
|
|
195
|
+
if (!hasAncestor(returned, statement.tryBlock)) return true;
|
|
196
|
+
if (hazardousTryClause(statement.catchClause?.block, fn, false))
|
|
197
|
+
return true;
|
|
198
|
+
return hazardousTryClause(statement.finallyBlock, fn, true);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function branchDependent(
|
|
202
|
+
node: ts.Node,
|
|
203
|
+
fn: ts.FunctionLikeDeclaration,
|
|
204
|
+
): boolean {
|
|
161
205
|
let current: ts.Node | undefined = node.parent;
|
|
162
206
|
while (current && current !== fn) {
|
|
163
207
|
if (ts.isIfStatement(current) || ts.isConditionalExpression(current)
|
|
164
|
-
|| ts.isSwitchStatement(current)
|
|
165
|
-
|| ts.
|
|
208
|
+
|| ts.isSwitchStatement(current)
|
|
209
|
+
|| ts.isIterationStatement(current, false)) return true;
|
|
210
|
+
if (ts.isTryStatement(current)
|
|
211
|
+
&& unsupportedTryAncestor(current, node, fn)) return true;
|
|
166
212
|
current = current.parent;
|
|
167
213
|
}
|
|
168
214
|
return false;
|
|
@@ -231,10 +277,30 @@ function directReturnConnectFact(
|
|
|
231
277
|
return directConnectFact(returned);
|
|
232
278
|
}
|
|
233
279
|
|
|
280
|
+
function hasTryAncestor(
|
|
281
|
+
returned: ts.ReturnStatement,
|
|
282
|
+
fn: ts.FunctionLikeDeclaration,
|
|
283
|
+
): boolean {
|
|
284
|
+
let current: ts.Node | undefined = returned.parent;
|
|
285
|
+
while (current && current !== fn) {
|
|
286
|
+
if (ts.isTryStatement(current)) return true;
|
|
287
|
+
current = current.parent;
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
234
292
|
export function directConnectFactFromFunctionLike(
|
|
235
293
|
fn: ts.FunctionLikeDeclaration,
|
|
236
294
|
): LocalBindingFact | undefined {
|
|
237
295
|
if (ts.isArrowFunction(fn) && fn.body && !ts.isBlock(fn.body))
|
|
238
296
|
return directConnectFact(fn.body);
|
|
239
|
-
|
|
297
|
+
const returned = singleReturn(fn);
|
|
298
|
+
const fact = directReturnConnectFact(fn);
|
|
299
|
+
if (!fact || !returned || !hasTryAncestor(returned, fn)) return fact;
|
|
300
|
+
return {
|
|
301
|
+
...fact,
|
|
302
|
+
helperChain: [...(fact.helperChain ?? []), {
|
|
303
|
+
bindingOrigin: 'single_hop_helper_return',
|
|
304
|
+
}],
|
|
305
|
+
};
|
|
240
306
|
}
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import ts from 'typescript';
|
|
4
4
|
import { normalizePath } from '../utils/path-utils.js';
|
|
5
|
-
import { extractPlaceholderKeys } from '../utils/
|
|
5
|
+
import { extractPlaceholderKeys } from '../utils/placeholders.js';
|
|
6
6
|
import type { RepositorySourceContext } from './ts-project.js';
|
|
7
7
|
|
|
8
8
|
export interface HelperBinding {
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
directConnectFactFromFunctionLike,
|
|
16
16
|
functionLikeInitializer,
|
|
17
17
|
type LocalBindingFact,
|
|
18
|
-
} from './
|
|
19
|
-
import { collectServiceBindings } from './
|
|
18
|
+
} from './service-binding-helper-flow.js';
|
|
19
|
+
import { collectServiceBindings } from './service-binding-collector.js';
|
|
20
20
|
import type { RepositorySourceContext } from './ts-project.js';
|
|
21
21
|
|
|
22
22
|
interface LocalHelperFact extends LocalBindingFact {
|
|
@@ -8,9 +8,9 @@ import type {
|
|
|
8
8
|
import {
|
|
9
9
|
executableSymbolCandidates,
|
|
10
10
|
selectCallOwner,
|
|
11
|
-
} from './
|
|
12
|
-
import { reconcileEventSubscriptions } from './
|
|
13
|
-
import { reconcileBindingAndCallIdentity } from './
|
|
11
|
+
} from './fact-identity.js';
|
|
12
|
+
import { reconcileEventSubscriptions } from './event-subscription-facts.js';
|
|
13
|
+
import { reconcileBindingAndCallIdentity } from './binding-identity.js';
|
|
14
14
|
import type { ClassifiedOutboundCall } from './outbound-call-parser.js';
|
|
15
15
|
|
|
16
16
|
export interface ReconciledSourceFacts {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import {
|
|
3
3
|
identifierMatchesDeclaration,
|
|
4
|
-
} from './
|
|
4
|
+
} from './symbol-import-bindings.js';
|
|
5
5
|
import {
|
|
6
6
|
isUnshadowedCommonJsExportExpression,
|
|
7
|
-
} from './
|
|
7
|
+
} from './package-commonjs-syntax.js';
|
|
8
8
|
|
|
9
9
|
function transparentUse(node: ts.Node): ts.Node {
|
|
10
10
|
const parent = node.parent;
|
|
@@ -6,18 +6,18 @@ import type {
|
|
|
6
6
|
import {
|
|
7
7
|
executableSymbolCandidates,
|
|
8
8
|
selectCallOwner,
|
|
9
|
-
} from './
|
|
9
|
+
} from './fact-identity.js';
|
|
10
10
|
import {
|
|
11
11
|
derivedMemberImportReference,
|
|
12
12
|
identifierMatchesDeclaration,
|
|
13
13
|
symbolImportReference,
|
|
14
14
|
type SymbolImportBinding,
|
|
15
15
|
type SymbolImportReference,
|
|
16
|
-
} from './
|
|
16
|
+
} from './symbol-import-bindings.js';
|
|
17
17
|
import {
|
|
18
18
|
localSymbolTarget,
|
|
19
19
|
type LocalSymbolTargetIdentity,
|
|
20
|
-
} from './
|
|
20
|
+
} from './local-symbol-reference.js';
|
|
21
21
|
|
|
22
22
|
export interface SymbolCallProxy {
|
|
23
23
|
importSource: string;
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
symbolCallName,
|
|
4
4
|
type SymbolCallProxy,
|
|
5
5
|
type SymbolClassInstance,
|
|
6
|
-
} from './
|
|
6
|
+
} from './symbol-call-facts.js';
|
|
7
7
|
import {
|
|
8
8
|
identifierMatchesDeclaration,
|
|
9
9
|
symbolImportReference,
|
|
10
10
|
type SymbolImportBinding,
|
|
11
|
-
} from './
|
|
11
|
+
} from './symbol-import-bindings.js';
|
|
12
12
|
|
|
13
13
|
interface DerivedContextCollection {
|
|
14
14
|
source: ts.SourceFile;
|
|
@@ -9,24 +9,24 @@ import {
|
|
|
9
9
|
} from './outbound-call-parser.js';
|
|
10
10
|
import type { RepositorySourceContext } from './ts-project.js';
|
|
11
11
|
import { normalizePath } from '../utils/path-utils.js';
|
|
12
|
-
import { reconcileEventSubscriptions } from './
|
|
13
|
-
import { reconcileSymbolCallOwners } from './
|
|
12
|
+
import { reconcileEventSubscriptions } from './event-subscription-facts.js';
|
|
13
|
+
import { reconcileSymbolCallOwners } from './source-fact-reconciliation.js';
|
|
14
14
|
import {
|
|
15
15
|
collectSymbolImportBindings,
|
|
16
16
|
type SymbolImportBinding,
|
|
17
|
-
} from './
|
|
17
|
+
} from './symbol-import-bindings.js';
|
|
18
18
|
import {
|
|
19
19
|
collectSymbolCallFacts,
|
|
20
20
|
symbolCallName,
|
|
21
21
|
type SymbolCallProxy,
|
|
22
22
|
type SymbolClassInstance,
|
|
23
|
-
} from './
|
|
23
|
+
} from './symbol-call-facts.js';
|
|
24
24
|
import {
|
|
25
25
|
executableBodyEligibility,
|
|
26
|
-
} from './
|
|
26
|
+
} from './executable-body-eligibility.js';
|
|
27
27
|
import {
|
|
28
28
|
collectDerivedSymbolContexts,
|
|
29
|
-
} from './
|
|
29
|
+
} from './symbol-derived-contexts.js';
|
|
30
30
|
|
|
31
31
|
function lineOf(source: ts.SourceFile, pos: number): number {
|
|
32
32
|
return source.getLineAndCharacterOfPosition(pos).line + 1;
|
|
@@ -42,6 +42,12 @@ function isFunctionLike(node: ts.Node): node is ts.FunctionLikeDeclaration {
|
|
|
42
42
|
function exported(node: ts.Node): boolean {
|
|
43
43
|
return Boolean(ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export);
|
|
44
44
|
}
|
|
45
|
+
function defaultExported(node: ts.Node): boolean {
|
|
46
|
+
return Boolean(
|
|
47
|
+
ts.getCombinedModifierFlags(node as ts.Declaration)
|
|
48
|
+
& ts.ModifierFlags.Default,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
45
51
|
function isPublicClassMethod(node: ts.MethodDeclaration): boolean {
|
|
46
52
|
const flags = ts.getCombinedModifierFlags(node);
|
|
47
53
|
return (flags & ts.ModifierFlags.Private) === 0 && (flags & ts.ModifierFlags.Protected) === 0;
|
|
@@ -141,6 +147,7 @@ interface SymbolCollection {
|
|
|
141
147
|
exportNames: Map<string, string>;
|
|
142
148
|
objectExports: Set<string>;
|
|
143
149
|
exportedClasses: Set<string>;
|
|
150
|
+
defaultExportedClasses: Set<string>;
|
|
144
151
|
declaredClasses: Set<string>;
|
|
145
152
|
proxies: Map<string, SymbolCallProxy[]>;
|
|
146
153
|
instances: Map<string, SymbolClassInstance[]>;
|
|
@@ -153,7 +160,8 @@ function symbolSourceEvidence(
|
|
|
153
160
|
parentRoot: string;
|
|
154
161
|
qualifiedName: string;
|
|
155
162
|
declaredExportName?: string;
|
|
156
|
-
classContainerExported: boolean;
|
|
163
|
+
classContainerExported: boolean; classContainerDefaultExported: boolean;
|
|
164
|
+
classMemberExported: boolean;
|
|
157
165
|
objectExported: boolean;
|
|
158
166
|
evidence?: Record<string, unknown>;
|
|
159
167
|
},
|
|
@@ -168,6 +176,8 @@ function symbolSourceEvidence(
|
|
|
168
176
|
if (options.classContainerExported && ts.isMethodDeclaration(node)
|
|
169
177
|
&& isPublicClassMethod(node)) return {
|
|
170
178
|
source: 'exported_class_instance_member', exportedClass: options.parentRoot,
|
|
179
|
+
exportedClassExportKind: options.classContainerDefaultExported
|
|
180
|
+
? 'default' : 'named',
|
|
171
181
|
memberKind: 'class_method',
|
|
172
182
|
};
|
|
173
183
|
if (options.declaredExportName) return {
|
|
@@ -201,6 +211,7 @@ interface SymbolNames {
|
|
|
201
211
|
declaredExportName?: string;
|
|
202
212
|
objectExported: boolean;
|
|
203
213
|
classContainerExported: boolean;
|
|
214
|
+
classContainerDefaultExported: boolean;
|
|
204
215
|
classMemberExported: boolean;
|
|
205
216
|
effectiveName?: string;
|
|
206
217
|
}
|
|
@@ -219,6 +230,24 @@ function exportedClassMember(
|
|
|
219
230
|
&& isPublicClassMethod(node);
|
|
220
231
|
}
|
|
221
232
|
|
|
233
|
+
function classExportState(
|
|
234
|
+
collection: SymbolCollection,
|
|
235
|
+
parentName: string | undefined,
|
|
236
|
+
parentRoot: string,
|
|
237
|
+
): {
|
|
238
|
+
classContainerExported: boolean;
|
|
239
|
+
classContainerDefaultExported: boolean;
|
|
240
|
+
} {
|
|
241
|
+
return {
|
|
242
|
+
classContainerExported: Boolean(
|
|
243
|
+
parentName && collection.exportedClasses.has(parentRoot),
|
|
244
|
+
),
|
|
245
|
+
classContainerDefaultExported: Boolean(
|
|
246
|
+
parentName && collection.defaultExportedClasses.has(parentRoot),
|
|
247
|
+
),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
222
251
|
function symbolNames(
|
|
223
252
|
collection: SymbolCollection,
|
|
224
253
|
kind: string,
|
|
@@ -238,12 +267,11 @@ function symbolNames(
|
|
|
238
267
|
const classMemberExported = exportedClassMember(
|
|
239
268
|
collection, kind, parentName, parentRoot, node,
|
|
240
269
|
);
|
|
241
|
-
const
|
|
242
|
-
parentName && collection.exportedClasses.has(parentRoot),
|
|
243
|
-
);
|
|
270
|
+
const classState = classExportState(collection, parentName, parentRoot);
|
|
244
271
|
return {
|
|
245
272
|
parentRoot, declaredExportName, qualifiedName,
|
|
246
|
-
objectExported,
|
|
273
|
+
objectExported, ...classState,
|
|
274
|
+
classMemberExported,
|
|
247
275
|
effectiveName: classMemberExported || objectExported
|
|
248
276
|
? qualifiedName : declaredExportName,
|
|
249
277
|
};
|
|
@@ -266,6 +294,7 @@ function addExecutableSymbol(
|
|
|
266
294
|
qualifiedName: names.qualifiedName,
|
|
267
295
|
declaredExportName: names.declaredExportName,
|
|
268
296
|
classContainerExported: names.classContainerExported,
|
|
297
|
+
classContainerDefaultExported: names.classContainerDefaultExported,
|
|
269
298
|
classMemberExported: names.classMemberExported,
|
|
270
299
|
objectExported: names.objectExported,
|
|
271
300
|
evidence,
|
|
@@ -457,6 +486,8 @@ function collectClassDeclaration(
|
|
|
457
486
|
collection.declaredClasses.add(node.name.text);
|
|
458
487
|
if (exported(node) || collection.exportNames.has(node.name.text))
|
|
459
488
|
collection.exportedClasses.add(node.name.text);
|
|
489
|
+
if (defaultExported(node))
|
|
490
|
+
collection.defaultExportedClasses.add(node.name.text);
|
|
460
491
|
for (const member of node.members)
|
|
461
492
|
visitDeclaredSymbol(collection, member, node.name.text);
|
|
462
493
|
return true;
|
|
@@ -553,6 +584,7 @@ function createCollection(
|
|
|
553
584
|
importBindings: collectSymbolImportBindings(source),
|
|
554
585
|
exportNames: exportDeclarations(source),
|
|
555
586
|
objectExports: new Set(), exportedClasses: new Set(),
|
|
587
|
+
defaultExportedClasses: new Set(),
|
|
556
588
|
declaredClasses: new Set(), proxies: new Map(), instances: new Map(),
|
|
557
589
|
};
|
|
558
590
|
}
|
|
@@ -82,6 +82,7 @@ export interface CompactDecisionInput {
|
|
|
82
82
|
implementationStrategy?: string;
|
|
83
83
|
implementationGuided?: boolean;
|
|
84
84
|
implementationContextual?: boolean;
|
|
85
|
+
tiedCandidateRepos?: CompactReferenceGroupV1;
|
|
85
86
|
reasonCode?: string;
|
|
86
87
|
eventMatchStrategy?: string;
|
|
87
88
|
dispatchCertainty?: string;
|
|
@@ -225,6 +226,7 @@ export interface CompactDecisionV1 {
|
|
|
225
226
|
implementationStrategy?: string;
|
|
226
227
|
implementationGuided?: boolean;
|
|
227
228
|
implementationContextual?: boolean;
|
|
229
|
+
tiedCandidateRepos?: CompactReferenceGroupV1;
|
|
228
230
|
eventMatchStrategy?: string;
|
|
229
231
|
dispatchCertainty?: string;
|
|
230
232
|
eventSubscriptionCount?: number;
|
|
@@ -247,6 +249,10 @@ export interface CompactEdgeDetailsV1 {
|
|
|
247
249
|
|
|
248
250
|
export interface CompactDiagnosticDetailsV1 {
|
|
249
251
|
reasonCode?: string;
|
|
252
|
+
tiedCandidateRepos?: CompactReferenceGroupV1;
|
|
253
|
+
selectorKind?: string;
|
|
254
|
+
selectorSuggestions?: CompactReferenceGroupV1;
|
|
255
|
+
invalidFactCategories?: CompactReferenceGroupV1;
|
|
250
256
|
missingVariableNames?: string[];
|
|
251
257
|
missingVariableCount?: number;
|
|
252
258
|
shownMissingVariableCount?: number;
|
package/src/trace/{021-compact-decision-normalization.ts → compact-decision-normalization.ts}
RENAMED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { compareBinary } from './
|
|
1
|
+
import { compareBinary } from './traversal-scope.js';
|
|
2
2
|
import type {
|
|
3
3
|
CompactDecisionV1,
|
|
4
|
+
CompactReferenceGroupV1,
|
|
4
5
|
CompactStatus,
|
|
5
|
-
} from './
|
|
6
|
+
} from './compact-contract.js';
|
|
6
7
|
|
|
7
8
|
export const COMPACT_MISSING_NAME_LIMIT = 8;
|
|
8
9
|
export const COMPACT_MISSING_NAME_MAX_LENGTH = 160;
|
|
10
|
+
export const COMPACT_REFERENCE_VALUE_LIMIT = 5;
|
|
11
|
+
const COMPACT_REFERENCE_VALUE_MAX_LENGTH = 240;
|
|
9
12
|
|
|
10
13
|
export interface CompactMissingNameProjection {
|
|
11
14
|
readonly names: string[];
|
|
@@ -23,11 +26,17 @@ export function projectCompactMissingNames(
|
|
|
23
26
|
values: readonly string[] | undefined,
|
|
24
27
|
authoritativeCount: unknown,
|
|
25
28
|
): CompactMissingNameProjection {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const candidates = new Map<string, boolean>();
|
|
30
|
+
for (const value of values ?? []) {
|
|
31
|
+
const normalized = value.trim();
|
|
32
|
+
if (!normalized) continue;
|
|
33
|
+
candidates.set(
|
|
34
|
+
normalized,
|
|
35
|
+
(candidates.get(normalized) ?? true) && isSafeCompactMissingName(value),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const raw = [...candidates.keys()].sort(compareBinary);
|
|
39
|
+
const safe = raw.filter((name) => candidates.get(name) === true);
|
|
31
40
|
const names = safe.slice(0, COMPACT_MISSING_NAME_LIMIT);
|
|
32
41
|
const total = Math.max(compactCount(authoritativeCount), raw.length);
|
|
33
42
|
return {
|
|
@@ -37,25 +46,58 @@ export function projectCompactMissingNames(
|
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
export function isSafeCompactMissingName(value: string): boolean {
|
|
49
|
+
if (hasControlCharacter(value)) return false;
|
|
40
50
|
const normalized = value.trim();
|
|
41
51
|
return normalized.length > 0
|
|
42
52
|
&& normalized.length <= COMPACT_MISSING_NAME_MAX_LENGTH
|
|
43
|
-
&& !hasControlCharacter(normalized)
|
|
44
53
|
&& safeMissingName.test(normalized);
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
export function projectCompactReferenceGroup(
|
|
57
|
+
values: readonly string[] | undefined,
|
|
58
|
+
authoritativeCount: unknown,
|
|
59
|
+
isSafe: (value: string) => boolean,
|
|
60
|
+
): CompactReferenceGroupV1 | undefined {
|
|
61
|
+
const candidates = normalizedReferenceValues(values, isSafe);
|
|
62
|
+
const unique = [...candidates.keys()].sort(compareBinary);
|
|
63
|
+
const safe = unique.filter((value) => candidates.get(value) === true);
|
|
64
|
+
const shown = safe.slice(0, COMPACT_REFERENCE_VALUE_LIMIT);
|
|
65
|
+
const total = Math.max(compactCount(authoritativeCount), unique.length);
|
|
66
|
+
if (total === 0) return undefined;
|
|
67
|
+
return {
|
|
68
|
+
values: shown,
|
|
69
|
+
total,
|
|
70
|
+
shown: shown.length,
|
|
71
|
+
omitted: Math.max(0, total - shown.length),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isSafeCompactReferenceName(value: string): boolean {
|
|
76
|
+
if (!safeReferenceText(value, 160)) return false;
|
|
77
|
+
return /^[@A-Za-z0-9_$][@A-Za-z0-9_$./:-]*$/.test(value.trim());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function isSafeCompactSelectorSuggestion(value: string): boolean {
|
|
81
|
+
if (!safeReferenceText(value, COMPACT_REFERENCE_VALUE_MAX_LENGTH))
|
|
82
|
+
return false;
|
|
83
|
+
return /^(?:--(?:repo|service|operation|path|handler) [@A-Za-z0-9_$./:-]+)(?: --(?:repo|service|operation|path|handler) [@A-Za-z0-9_$./:-]+)*$/
|
|
84
|
+
.test(value.trim());
|
|
85
|
+
}
|
|
86
|
+
|
|
47
87
|
export function normalizeCompactDecisionEquivalence(
|
|
48
88
|
decision: CompactDecisionV1,
|
|
49
89
|
status: CompactStatus,
|
|
50
90
|
canonicalTarget: string | undefined,
|
|
51
91
|
targetIdentityEqual = false,
|
|
52
92
|
persistedIdentityEqual = false,
|
|
93
|
+
rawPersistedStatus?: string,
|
|
53
94
|
): void {
|
|
95
|
+
if (decision.effectiveResolutionStatus === status)
|
|
96
|
+
delete decision.effectiveResolutionStatus;
|
|
54
97
|
removeEquivalentPersistedDecision(
|
|
55
98
|
decision, status, canonicalTarget, persistedIdentityEqual,
|
|
99
|
+
rawPersistedStatus,
|
|
56
100
|
);
|
|
57
|
-
if (decision.effectiveResolutionStatus === status)
|
|
58
|
-
delete decision.effectiveResolutionStatus;
|
|
59
101
|
if (targetIdentityEqual && canonicalTarget !== undefined
|
|
60
102
|
&& decision.effectiveTarget === canonicalTarget)
|
|
61
103
|
delete decision.effectiveTarget;
|
|
@@ -77,9 +119,10 @@ function removeEquivalentPersistedDecision(
|
|
|
77
119
|
status: CompactStatus,
|
|
78
120
|
canonicalTarget: string | undefined,
|
|
79
121
|
identityEqual: boolean,
|
|
122
|
+
rawPersistedStatus: string | undefined,
|
|
80
123
|
): void {
|
|
81
124
|
if (!identityEqual
|
|
82
|
-
||
|
|
125
|
+
|| rawPersistedStatus !== status
|
|
83
126
|
|| (decision.effectiveResolutionStatus !== undefined
|
|
84
127
|
&& decision.persistedResolutionStatus
|
|
85
128
|
!== decision.effectiveResolutionStatus))
|
|
@@ -96,6 +139,29 @@ function compactCount(value: unknown): number {
|
|
|
96
139
|
? Math.max(0, Math.floor(value)) : 0;
|
|
97
140
|
}
|
|
98
141
|
|
|
142
|
+
function normalizedReferenceValues(
|
|
143
|
+
values: readonly string[] | undefined,
|
|
144
|
+
isSafe: (value: string) => boolean,
|
|
145
|
+
): Map<string, boolean> {
|
|
146
|
+
const unique = new Map<string, boolean>();
|
|
147
|
+
for (const raw of values ?? []) {
|
|
148
|
+
const value = raw.trim();
|
|
149
|
+
if (!value) continue;
|
|
150
|
+
unique.set(value, (unique.get(value) ?? true) && isSafe(raw));
|
|
151
|
+
}
|
|
152
|
+
return unique;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function safeReferenceText(value: string, maxLength: number): boolean {
|
|
156
|
+
if (hasControlCharacter(value)) return false;
|
|
157
|
+
const normalized = value.trim();
|
|
158
|
+
return normalized.length > 0
|
|
159
|
+
&& normalized.length <= maxLength
|
|
160
|
+
&& !/^[a-z]+:\/\//i.test(normalized)
|
|
161
|
+
&& !/(?:^|[^A-Za-z0-9])(?:authorization|bearer|credential|destination|password|secret|token)(?:$|[^A-Za-z0-9])/i
|
|
162
|
+
.test(normalized);
|
|
163
|
+
}
|
|
164
|
+
|
|
99
165
|
function hasControlCharacter(value: string): boolean {
|
|
100
166
|
for (let index = 0; index < value.length; index += 1) {
|
|
101
167
|
const code = value.charCodeAt(index);
|