@saptools/service-flow 0.1.67 → 0.1.69
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 +20 -0
- package/README.md +27 -9
- package/TECHNICAL-NOTE.md +36 -0
- package/dist/chunk-3N3B5KHV.js +19596 -0
- package/dist/chunk-3N3B5KHV.js.map +1 -0
- package/dist/cli.js +2645 -521
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +67 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/cli/001-index-summary.ts +22 -0
- package/src/cli/003-doctor-package-resolution.ts +68 -0
- package/src/cli/doctor.ts +25 -14
- package/src/cli.ts +151 -87
- package/src/db/000-call-fact-repository.ts +499 -340
- package/src/db/001-fact-lifecycle.ts +60 -30
- package/src/db/002-fact-json-inventory.ts +169 -0
- package/src/db/003-current-fact-semantics.ts +699 -0
- package/src/db/004-package-target-invalidation.ts +183 -0
- package/src/db/005-schema-structure.ts +201 -0
- package/src/db/006-relative-symbol-resolution.ts +464 -0
- package/src/db/007-package-fact-semantics.ts +573 -0
- package/src/db/008-relative-fact-semantics.ts +210 -0
- package/src/db/009-binding-fact-semantics.ts +352 -0
- package/src/db/010-package-symbol-surface-semantics.ts +320 -0
- package/src/db/011-symbol-call-semantics.ts +144 -0
- package/src/db/012-binding-reference-proof.ts +268 -0
- package/src/db/013-index-publication-failure.ts +91 -0
- package/src/db/014-binding-helper-provenance.ts +17 -0
- package/src/db/migrations.ts +16 -3
- package/src/db/repositories.ts +130 -6
- package/src/db/schema.ts +4 -2
- package/src/index.ts +12 -0
- package/src/indexer/cds-extension-resolver.ts +27 -3
- package/src/indexer/repository-indexer.ts +135 -13
- package/src/indexer/workspace-indexer.ts +237 -34
- package/src/linker/003-package-import-symbol-resolver.ts +363 -131
- package/src/linker/004-event-subscription-handler-linker.ts +34 -11
- package/src/linker/005-odata-path-structure.ts +371 -0
- package/src/linker/006-event-template-link.ts +72 -0
- package/src/linker/007-call-edge-insertion.ts +568 -0
- package/src/linker/cross-repo-linker.ts +4 -166
- package/src/linker/odata-path-normalizer.ts +273 -180
- package/src/linker/service-resolver.ts +197 -77
- package/src/parsers/000-direct-query-execution.ts +11 -0
- package/src/parsers/002-symbol-import-bindings.ts +516 -0
- package/src/parsers/003-package-public-surface.ts +661 -0
- package/src/parsers/004-fact-identity.ts +108 -0
- package/src/parsers/005-event-subscription-facts.ts +281 -0
- package/src/parsers/006-binding-identity.ts +348 -0
- package/src/parsers/007-source-fact-reconciliation.ts +105 -0
- package/src/parsers/008-package-surface-publication.ts +82 -0
- package/src/parsers/009-symbol-call-facts.ts +528 -0
- package/src/parsers/010-package-public-surface-analysis.ts +352 -0
- package/src/parsers/011-binding-lexical-scope.ts +583 -0
- package/src/parsers/012-package-fact-contract.ts +306 -0
- package/src/parsers/013-executable-body-eligibility.ts +35 -0
- package/src/parsers/014-service-binding-helper-flow.ts +306 -0
- package/src/parsers/015-service-binding-collector.ts +693 -0
- package/src/parsers/016-local-symbol-reference.ts +261 -0
- package/src/parsers/017-symbol-derived-contexts.ts +268 -0
- package/src/parsers/018-package-commonjs-syntax.ts +142 -0
- package/src/parsers/019-binding-assignment-targets.ts +76 -0
- package/src/parsers/020-stable-local-value.ts +217 -0
- package/src/parsers/021-binding-visibility.ts +168 -0
- package/src/parsers/022-outbound-expression-analysis.ts +700 -0
- package/src/parsers/023-outbound-call-classifier.ts +692 -0
- package/src/parsers/operation-path-analysis.ts +6 -1
- package/src/parsers/outbound-call-parser.ts +162 -512
- package/src/parsers/package-json-parser.ts +45 -3
- package/src/parsers/service-binding-parser-helpers.ts +86 -15
- package/src/parsers/service-binding-parser.ts +147 -597
- package/src/parsers/symbol-parser.ts +513 -352
- package/src/trace/002-trace-diagnostics.ts +36 -1
- package/src/trace/007-implementation-start-diagnostic.ts +1 -0
- package/src/trace/011-event-subscriber-traversal.ts +100 -8
- package/src/trace/013-trace-root-scopes.ts +2 -3
- package/src/trace/014-compact-contract.ts +6 -0
- package/src/trace/015-trace-edge-recorder.ts +61 -4
- package/src/trace/016-compact-projector.ts +15 -17
- package/src/trace/019-trace-edge-semantics.ts +6 -10
- package/src/trace/020-compact-field-projection.ts +122 -38
- package/src/trace/021-compact-decision-normalization.ts +171 -0
- package/src/trace/022-trace-fact-preflight.ts +21 -0
- package/src/trace/023-nested-event-scopes.ts +23 -0
- package/src/trace/024-compact-observation-decision.ts +81 -0
- package/src/trace/025-trace-implementation-scope.ts +123 -0
- package/src/trace/026-trace-start-scope.ts +336 -0
- package/src/trace/027-trace-scope-execution.ts +566 -0
- package/src/trace/028-trace-operation-execution.ts +336 -0
- package/src/trace/029-trace-start-implementation.ts +172 -0
- package/src/trace/030-event-runtime-resolution.ts +151 -0
- package/src/trace/031-local-call-expansion.ts +37 -0
- package/src/trace/implementation-hints.ts +9 -6
- package/src/trace/selectors.ts +1 -0
- package/src/trace/trace-engine.ts +122 -624
- package/src/types.ts +57 -0
- package/src/utils/001-placeholders.ts +188 -10
- package/src/version.ts +1 -1
- package/dist/chunk-ZQABU7MR.js +0 -12151
- package/dist/chunk-ZQABU7MR.js.map +0 -1
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
import type { Db } from './connection.js';
|
|
2
|
+
import type { CallType, RepoKind } from '../types.js';
|
|
3
|
+
import { ANALYZER_VERSION } from '../version.js';
|
|
4
|
+
import {
|
|
5
|
+
invalidPackageFactCategories,
|
|
6
|
+
} from './007-package-fact-semantics.js';
|
|
7
|
+
import {
|
|
8
|
+
invalidRelativeFactCategories,
|
|
9
|
+
} from './008-relative-fact-semantics.js';
|
|
10
|
+
import {
|
|
11
|
+
invalidBindingFactCategories,
|
|
12
|
+
} from './009-binding-fact-semantics.js';
|
|
13
|
+
import {
|
|
14
|
+
invalidSymbolFactCategories,
|
|
15
|
+
} from './011-symbol-call-semantics.js';
|
|
16
|
+
|
|
17
|
+
export type PackageFactPhase = 'pre_package' | 'terminal';
|
|
18
|
+
|
|
19
|
+
export interface FactSemanticCategoryCount {
|
|
20
|
+
category: string;
|
|
21
|
+
count: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const executableKindSql =
|
|
25
|
+
"'event_registration','callback','method','object_method','function'";
|
|
26
|
+
const callTypeAllowlist: Record<CallType, true> = {
|
|
27
|
+
remote_action: true,
|
|
28
|
+
remote_query: true,
|
|
29
|
+
remote_entity_read: true,
|
|
30
|
+
remote_entity_mutation: true,
|
|
31
|
+
remote_entity_delete: true,
|
|
32
|
+
remote_entity_media: true,
|
|
33
|
+
remote_entity_candidate: true,
|
|
34
|
+
local_db_query: true,
|
|
35
|
+
external_http: true,
|
|
36
|
+
async_emit: true,
|
|
37
|
+
async_subscribe: true,
|
|
38
|
+
local_service_call: true,
|
|
39
|
+
unknown: true,
|
|
40
|
+
};
|
|
41
|
+
const repositoryKindAllowlist: Record<RepoKind, true> = {
|
|
42
|
+
'cap-service': true,
|
|
43
|
+
'cap-db-model': true,
|
|
44
|
+
'helper-package': true,
|
|
45
|
+
mixed: true,
|
|
46
|
+
unknown: true,
|
|
47
|
+
};
|
|
48
|
+
const symbolStrategies = [
|
|
49
|
+
'same_file_exact',
|
|
50
|
+
'exported_exact',
|
|
51
|
+
'exact_symbol_match',
|
|
52
|
+
'relative_import_class_instance_method',
|
|
53
|
+
'relative_import_namespace_member',
|
|
54
|
+
'relative_import_static_accessor_instance_method',
|
|
55
|
+
'relative_import_path_disambiguated',
|
|
56
|
+
'relative_import_exported_exact',
|
|
57
|
+
'proxy_member_exported_object_map',
|
|
58
|
+
'proxy_member_no_global_name_fallback',
|
|
59
|
+
'package_import_pending',
|
|
60
|
+
'package_import_derived_member_unsupported',
|
|
61
|
+
'package_public_surface_exact',
|
|
62
|
+
'package_public_surface_ambiguous',
|
|
63
|
+
'package_public_surface_unresolved',
|
|
64
|
+
] as const;
|
|
65
|
+
const symbolReasons = [
|
|
66
|
+
'multiple_same_file_symbol_targets',
|
|
67
|
+
'multiple_exported_symbol_targets',
|
|
68
|
+
'no_local_symbol_target',
|
|
69
|
+
'symbol_target_has_no_executable_body',
|
|
70
|
+
'relative_import_provenance_missing',
|
|
71
|
+
'relative_import_type_only',
|
|
72
|
+
'relative_import_module_resolution_ambiguous',
|
|
73
|
+
'relative_import_requested_module_has_no_executable_body',
|
|
74
|
+
'relative_import_proxy_alias_targets_package_unsupported',
|
|
75
|
+
'relative_import_requested_module_has_no_target',
|
|
76
|
+
'multiple_relative_class_targets_in_requested_module',
|
|
77
|
+
'multiple_namespace_targets_in_requested_module',
|
|
78
|
+
'multiple_accessor_targets_in_requested_module',
|
|
79
|
+
'multiple_exported_targets_in_requested_module',
|
|
80
|
+
'multiple_proxy_targets_in_requested_module',
|
|
81
|
+
'package_resolution_pending',
|
|
82
|
+
'package_derived_member_provenance_insufficient',
|
|
83
|
+
'package_repository_scope_ambiguous',
|
|
84
|
+
'package_repository_not_indexed',
|
|
85
|
+
'package_public_surface_unsupported',
|
|
86
|
+
'public_surface_evidence_incomplete',
|
|
87
|
+
'package_binding_type_only',
|
|
88
|
+
'package_public_scope_duplicate',
|
|
89
|
+
'package_public_name_not_exposed',
|
|
90
|
+
'package_public_target_ambiguous',
|
|
91
|
+
'public_symbol_has_no_executable_body',
|
|
92
|
+
] as const;
|
|
93
|
+
const incompleteReasons = [
|
|
94
|
+
'relative_import_provenance_missing',
|
|
95
|
+
'relative_import_module_resolution_ambiguous',
|
|
96
|
+
'package_resolution_pending',
|
|
97
|
+
'package_repository_scope_ambiguous',
|
|
98
|
+
'package_public_surface_unsupported',
|
|
99
|
+
'public_surface_evidence_incomplete',
|
|
100
|
+
] as const;
|
|
101
|
+
const packageStrategies = [
|
|
102
|
+
'package_import_pending',
|
|
103
|
+
'package_public_surface_exact',
|
|
104
|
+
'package_public_surface_ambiguous',
|
|
105
|
+
'package_public_surface_unresolved',
|
|
106
|
+
] as const;
|
|
107
|
+
const relativeStrategies = [
|
|
108
|
+
'relative_import_class_instance_method',
|
|
109
|
+
'relative_import_namespace_member',
|
|
110
|
+
'relative_import_static_accessor_instance_method',
|
|
111
|
+
'relative_import_path_disambiguated',
|
|
112
|
+
'relative_import_exported_exact',
|
|
113
|
+
'proxy_member_exported_object_map',
|
|
114
|
+
'proxy_member_no_global_name_fallback',
|
|
115
|
+
] as const;
|
|
116
|
+
const simpleStrategies = [
|
|
117
|
+
'same_file_exact',
|
|
118
|
+
'exported_exact',
|
|
119
|
+
'exact_symbol_match',
|
|
120
|
+
] as const;
|
|
121
|
+
|
|
122
|
+
function sqlTextList(values: readonly string[]): string {
|
|
123
|
+
return values.map((value) => `'${value}'`).join(',');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function count(
|
|
127
|
+
db: Db,
|
|
128
|
+
sql: string,
|
|
129
|
+
workspaceId?: number,
|
|
130
|
+
predicateCount = 1,
|
|
131
|
+
): number {
|
|
132
|
+
const params = Array.from({ length: predicateCount }, () =>
|
|
133
|
+
[ANALYZER_VERSION, workspaceId, workspaceId]).flat();
|
|
134
|
+
const row = db.prepare(sql).get(...params);
|
|
135
|
+
return Number(row?.count ?? 0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function category(
|
|
139
|
+
categoryName: string,
|
|
140
|
+
categoryCount: number,
|
|
141
|
+
): FactSemanticCategoryCount[] {
|
|
142
|
+
return categoryCount > 0
|
|
143
|
+
? [{ category: categoryName, count: categoryCount }]
|
|
144
|
+
: [];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function currentRepositoryPredicate(alias = 'r'): string {
|
|
148
|
+
return `${alias}.fact_analyzer_version=?
|
|
149
|
+
AND (? IS NULL OR ${alias}.workspace_id=?)`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function repositoryCategories(
|
|
153
|
+
db: Db,
|
|
154
|
+
workspaceId?: number,
|
|
155
|
+
): FactSemanticCategoryCount[] {
|
|
156
|
+
const invalid = count(db, `SELECT COUNT(*) count FROM repositories r
|
|
157
|
+
WHERE ${currentRepositoryPredicate()}
|
|
158
|
+
AND (typeof(r.kind)<>'text' OR r.kind NOT IN (
|
|
159
|
+
${sqlTextList(Object.keys(repositoryKindAllowlist))}
|
|
160
|
+
))`, workspaceId);
|
|
161
|
+
return category('repository_kind_invalid', invalid);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function operationCategories(
|
|
165
|
+
db: Db,
|
|
166
|
+
workspaceId?: number,
|
|
167
|
+
): FactSemanticCategoryCount[] {
|
|
168
|
+
const invalid = count(db, `SELECT COUNT(*) count
|
|
169
|
+
FROM cds_operations fact
|
|
170
|
+
JOIN cds_services service ON service.id=fact.service_id
|
|
171
|
+
JOIN repositories r ON r.id=service.repo_id
|
|
172
|
+
LEFT JOIN cds_operations base ON base.id=fact.base_operation_id
|
|
173
|
+
LEFT JOIN cds_services base_service ON base_service.id=base.service_id
|
|
174
|
+
LEFT JOIN repositories base_repo ON base_repo.id=base_service.repo_id
|
|
175
|
+
WHERE ${currentRepositoryPredicate()}
|
|
176
|
+
AND (typeof(fact.operation_type)<>'text'
|
|
177
|
+
OR fact.operation_type NOT IN ('action','function','event')
|
|
178
|
+
OR typeof(fact.operation_name)<>'text'
|
|
179
|
+
OR length(fact.operation_name)=0
|
|
180
|
+
OR typeof(fact.operation_path)<>'text'
|
|
181
|
+
OR length(fact.operation_path)=0
|
|
182
|
+
OR typeof(fact.source_file)<>'text'
|
|
183
|
+
OR length(fact.source_file)=0
|
|
184
|
+
OR typeof(fact.source_line)<>'integer' OR fact.source_line<1
|
|
185
|
+
OR fact.provenance NOT IN ('direct','inherited')
|
|
186
|
+
OR (fact.provenance='direct' AND fact.base_operation_id IS NOT NULL)
|
|
187
|
+
OR (fact.provenance='inherited' AND (
|
|
188
|
+
base.id IS NULL OR COALESCE(service.is_extend,0)<>1
|
|
189
|
+
OR COALESCE(service.extension_base_status,'')<>'resolved'
|
|
190
|
+
OR service.extension_base_service_id IS NULL
|
|
191
|
+
OR service.extension_base_service_id<>base.service_id
|
|
192
|
+
OR COALESCE(base.provenance,'')<>'direct'
|
|
193
|
+
OR base.base_operation_id IS NOT NULL
|
|
194
|
+
OR base_repo.workspace_id IS NULL
|
|
195
|
+
OR base_repo.workspace_id<>r.workspace_id
|
|
196
|
+
OR fact.operation_type<>base.operation_type
|
|
197
|
+
OR fact.operation_name<>base.operation_name
|
|
198
|
+
OR fact.operation_path<>base.operation_path
|
|
199
|
+
OR fact.params_json<>base.params_json
|
|
200
|
+
OR fact.return_type IS NOT base.return_type
|
|
201
|
+
OR fact.source_file<>base.source_file
|
|
202
|
+
OR fact.source_line<>base.source_line)))`, workspaceId);
|
|
203
|
+
return category('cds_operation_semantics_invalid', invalid);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function callSpanCategories(
|
|
207
|
+
db: Db,
|
|
208
|
+
workspaceId?: number,
|
|
209
|
+
): FactSemanticCategoryCount[] {
|
|
210
|
+
const outbound = count(db, `SELECT COUNT(*) count
|
|
211
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
212
|
+
WHERE ${currentRepositoryPredicate()}
|
|
213
|
+
AND (typeof(fact.source_file)<>'text'
|
|
214
|
+
OR length(fact.source_file)=0
|
|
215
|
+
OR typeof(fact.call_site_start_offset)<>'integer'
|
|
216
|
+
OR typeof(fact.call_site_end_offset)<>'integer'
|
|
217
|
+
OR fact.call_site_start_offset<0
|
|
218
|
+
OR fact.call_site_end_offset<=fact.call_site_start_offset)`, workspaceId);
|
|
219
|
+
const callType = count(db, `SELECT COUNT(*) count
|
|
220
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
221
|
+
WHERE ${currentRepositoryPredicate()}
|
|
222
|
+
AND (typeof(fact.call_type)<>'text'
|
|
223
|
+
OR fact.call_type NOT IN (
|
|
224
|
+
${sqlTextList(Object.keys(callTypeAllowlist))}
|
|
225
|
+
))`, workspaceId);
|
|
226
|
+
const symbol = count(db, `SELECT COUNT(*) count
|
|
227
|
+
FROM symbol_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
228
|
+
WHERE ${currentRepositoryPredicate()}
|
|
229
|
+
AND (typeof(fact.source_file)<>'text'
|
|
230
|
+
OR length(fact.source_file)=0
|
|
231
|
+
OR typeof(fact.callee_expression)<>'text'
|
|
232
|
+
OR length(fact.callee_expression)=0
|
|
233
|
+
OR typeof(fact.call_site_start_offset)<>'integer'
|
|
234
|
+
OR typeof(fact.call_site_end_offset)<>'integer'
|
|
235
|
+
OR fact.call_site_start_offset<0
|
|
236
|
+
OR fact.call_site_end_offset<=fact.call_site_start_offset
|
|
237
|
+
OR fact.call_role NOT IN ('ordinary_call','event_subscribe_handler'))`, workspaceId);
|
|
238
|
+
return [
|
|
239
|
+
...category('outbound_call_span_invalid', outbound),
|
|
240
|
+
...category('outbound_call_type_invalid', callType),
|
|
241
|
+
...category('symbol_call_span_or_role_invalid', symbol),
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function duplicateSymbolCallCategories(
|
|
246
|
+
db: Db,
|
|
247
|
+
workspaceId?: number,
|
|
248
|
+
): FactSemanticCategoryCount[] {
|
|
249
|
+
const duplicate = count(db, `SELECT COUNT(*) count FROM (
|
|
250
|
+
SELECT fact.repo_id,fact.source_file,fact.call_site_start_offset,
|
|
251
|
+
fact.call_site_end_offset,fact.call_role,COUNT(*) duplicate_count
|
|
252
|
+
FROM symbol_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
253
|
+
WHERE ${currentRepositoryPredicate()}
|
|
254
|
+
GROUP BY fact.repo_id,fact.source_file,fact.call_site_start_offset,
|
|
255
|
+
fact.call_site_end_offset,fact.call_role
|
|
256
|
+
HAVING COUNT(*)<>1
|
|
257
|
+
)`, workspaceId);
|
|
258
|
+
return category('symbol_call_site_duplicate', duplicate);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function eventNameCategories(
|
|
262
|
+
db: Db,
|
|
263
|
+
workspaceId?: number,
|
|
264
|
+
): FactSemanticCategoryCount[] {
|
|
265
|
+
const invalid = count(db, `SELECT COUNT(*) count
|
|
266
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
267
|
+
WHERE ${currentRepositoryPredicate()}
|
|
268
|
+
AND fact.call_type IN ('async_emit','async_subscribe')
|
|
269
|
+
AND (typeof(fact.event_name_expr)<>'text'
|
|
270
|
+
OR length(fact.event_name_expr)=0)`, workspaceId);
|
|
271
|
+
const duplicate = count(db, `SELECT COUNT(*) count FROM (
|
|
272
|
+
SELECT fact.repo_id,fact.source_file,fact.call_site_start_offset,
|
|
273
|
+
fact.call_site_end_offset,COUNT(*) duplicate_count
|
|
274
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
275
|
+
WHERE ${currentRepositoryPredicate()}
|
|
276
|
+
AND fact.call_type='async_subscribe'
|
|
277
|
+
GROUP BY fact.repo_id,fact.source_file,fact.call_site_start_offset,
|
|
278
|
+
fact.call_site_end_offset HAVING COUNT(*)<>1
|
|
279
|
+
)`, workspaceId);
|
|
280
|
+
return [
|
|
281
|
+
...category('event_name_invalid', invalid),
|
|
282
|
+
...category('async_subscription_site_duplicate', duplicate),
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function outboundOwnerCount(db: Db, workspaceId?: number): number {
|
|
287
|
+
return count(db, `WITH eligible AS (
|
|
288
|
+
SELECT fact.id fact_id,s.id symbol_id,
|
|
289
|
+
DENSE_RANK() OVER (PARTITION BY fact.id ORDER BY
|
|
290
|
+
CASE WHEN fact.call_type='async_subscribe'
|
|
291
|
+
AND s.kind='event_registration'
|
|
292
|
+
AND s.start_offset=fact.call_site_start_offset
|
|
293
|
+
AND s.end_offset=fact.call_site_end_offset THEN 0 ELSE 1 END,
|
|
294
|
+
s.end_offset-s.start_offset,
|
|
295
|
+
CASE s.kind WHEN 'event_registration' THEN 0 WHEN 'callback' THEN 1
|
|
296
|
+
WHEN 'method' THEN 2 WHEN 'object_method' THEN 3 ELSE 4 END,
|
|
297
|
+
s.start_offset,s.end_offset,s.qualified_name COLLATE BINARY) owner_rank
|
|
298
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
299
|
+
JOIN symbols s ON s.repo_id=fact.repo_id
|
|
300
|
+
AND s.source_file=fact.source_file
|
|
301
|
+
AND s.kind IN (${executableKindSql})
|
|
302
|
+
AND s.start_offset<=fact.call_site_start_offset
|
|
303
|
+
AND s.end_offset>=fact.call_site_end_offset
|
|
304
|
+
AND (fact.call_type<>'async_subscribe'
|
|
305
|
+
OR (s.kind='event_registration'
|
|
306
|
+
AND s.start_offset=fact.call_site_start_offset
|
|
307
|
+
AND s.end_offset=fact.call_site_end_offset))
|
|
308
|
+
WHERE ${currentRepositoryPredicate()}
|
|
309
|
+
), best AS (
|
|
310
|
+
SELECT fact_id,COUNT(*) best_count,MAX(symbol_id) symbol_id
|
|
311
|
+
FROM eligible WHERE owner_rank=1 GROUP BY fact_id
|
|
312
|
+
)
|
|
313
|
+
SELECT COUNT(*) count FROM outbound_calls fact
|
|
314
|
+
JOIN repositories r ON r.id=fact.repo_id
|
|
315
|
+
LEFT JOIN best ON best.fact_id=fact.id
|
|
316
|
+
WHERE ${currentRepositoryPredicate()}
|
|
317
|
+
AND ((best.fact_id IS NULL AND (
|
|
318
|
+
fact.source_symbol_id IS NOT NULL
|
|
319
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
320
|
+
'$.sourceOwnerResolution'),'')
|
|
321
|
+
<>'ownerless_file_scope'))
|
|
322
|
+
OR (best.fact_id IS NOT NULL AND (
|
|
323
|
+
best.best_count<>1 OR fact.source_symbol_id IS NOT best.symbol_id
|
|
324
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
325
|
+
'$.sourceOwnerResolution'),'')<>'owned_exact')))`, workspaceId, 2);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function symbolOwnerCount(db: Db, workspaceId?: number): number {
|
|
329
|
+
return count(db, `WITH eligible AS (
|
|
330
|
+
SELECT fact.id fact_id,s.id symbol_id,
|
|
331
|
+
DENSE_RANK() OVER (PARTITION BY fact.id ORDER BY
|
|
332
|
+
CASE WHEN fact.call_role='event_subscribe_handler'
|
|
333
|
+
AND s.kind='event_registration'
|
|
334
|
+
AND s.start_offset=fact.call_site_start_offset
|
|
335
|
+
AND s.end_offset=fact.call_site_end_offset THEN 0 ELSE 1 END,
|
|
336
|
+
s.end_offset-s.start_offset,
|
|
337
|
+
CASE s.kind WHEN 'event_registration' THEN 0 WHEN 'callback' THEN 1
|
|
338
|
+
WHEN 'method' THEN 2 WHEN 'object_method' THEN 3 ELSE 4 END,
|
|
339
|
+
s.start_offset,s.end_offset,s.qualified_name COLLATE BINARY) owner_rank
|
|
340
|
+
FROM symbol_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
341
|
+
JOIN symbols s ON s.repo_id=fact.repo_id
|
|
342
|
+
AND s.source_file=fact.source_file
|
|
343
|
+
AND s.kind IN (${executableKindSql})
|
|
344
|
+
AND s.start_offset<=fact.call_site_start_offset
|
|
345
|
+
AND s.end_offset>=fact.call_site_end_offset
|
|
346
|
+
AND (fact.call_role<>'event_subscribe_handler'
|
|
347
|
+
OR (s.kind='event_registration'
|
|
348
|
+
AND s.start_offset=fact.call_site_start_offset
|
|
349
|
+
AND s.end_offset=fact.call_site_end_offset))
|
|
350
|
+
WHERE ${currentRepositoryPredicate()}
|
|
351
|
+
), best AS (
|
|
352
|
+
SELECT fact_id,COUNT(*) best_count,MAX(symbol_id) symbol_id
|
|
353
|
+
FROM eligible WHERE owner_rank=1 GROUP BY fact_id
|
|
354
|
+
)
|
|
355
|
+
SELECT COUNT(*) count FROM symbol_calls fact
|
|
356
|
+
JOIN repositories r ON r.id=fact.repo_id
|
|
357
|
+
LEFT JOIN best ON best.fact_id=fact.id
|
|
358
|
+
LEFT JOIN symbols selected ON selected.id=best.symbol_id
|
|
359
|
+
WHERE ${currentRepositoryPredicate()}
|
|
360
|
+
AND (best.fact_id IS NULL OR best.best_count<>1
|
|
361
|
+
OR fact.caller_symbol_id IS NOT best.symbol_id
|
|
362
|
+
OR typeof(json_extract(fact.evidence_json,'$.caller'))<>'text'
|
|
363
|
+
OR json_extract(fact.evidence_json,'$.caller') COLLATE BINARY
|
|
364
|
+
<>selected.qualified_name COLLATE BINARY)`, workspaceId, 2);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function ownerCategories(
|
|
368
|
+
db: Db,
|
|
369
|
+
workspaceId?: number,
|
|
370
|
+
): FactSemanticCategoryCount[] {
|
|
371
|
+
return [
|
|
372
|
+
...category('outbound_call_owner_invalid',
|
|
373
|
+
outboundOwnerCount(db, workspaceId)),
|
|
374
|
+
...category('symbol_call_owner_invalid',
|
|
375
|
+
symbolOwnerCount(db, workspaceId)),
|
|
376
|
+
];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function bindingSiteCount(db: Db, workspaceId?: number): number {
|
|
380
|
+
return count(db, `SELECT COUNT(*) count
|
|
381
|
+
FROM service_bindings fact JOIN repositories r ON r.id=fact.repo_id
|
|
382
|
+
LEFT JOIN symbols owner ON owner.id=fact.symbol_id
|
|
383
|
+
WHERE ${currentRepositoryPredicate()}
|
|
384
|
+
AND (typeof(fact.binding_site_start_offset)<>'integer'
|
|
385
|
+
OR typeof(fact.binding_site_end_offset)<>'integer'
|
|
386
|
+
OR typeof(fact.source_file)<>'text'
|
|
387
|
+
OR length(fact.source_file)=0
|
|
388
|
+
OR typeof(fact.variable_name)<>'text'
|
|
389
|
+
OR length(fact.variable_name)=0
|
|
390
|
+
OR fact.binding_site_start_offset<0
|
|
391
|
+
OR fact.binding_site_end_offset<=fact.binding_site_start_offset
|
|
392
|
+
OR fact.owner_resolution NOT IN
|
|
393
|
+
('owned_exact','ownerless_file_scope')
|
|
394
|
+
OR (fact.owner_resolution='owned_exact' AND (
|
|
395
|
+
owner.id IS NULL OR owner.repo_id<>fact.repo_id
|
|
396
|
+
OR owner.source_file<>fact.source_file
|
|
397
|
+
OR owner.kind NOT IN (${executableKindSql})
|
|
398
|
+
OR owner.start_offset>fact.binding_site_start_offset
|
|
399
|
+
OR owner.end_offset<fact.binding_site_end_offset))
|
|
400
|
+
OR (fact.owner_resolution='ownerless_file_scope'
|
|
401
|
+
AND fact.symbol_id IS NOT NULL))`, workspaceId);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function duplicateBindingSiteCount(db: Db, workspaceId?: number): number {
|
|
405
|
+
return count(db, `SELECT COUNT(*) count FROM (
|
|
406
|
+
SELECT fact.repo_id,fact.source_file,fact.variable_name,
|
|
407
|
+
fact.binding_site_start_offset,fact.binding_site_end_offset,COUNT(*) total
|
|
408
|
+
FROM service_bindings fact JOIN repositories r ON r.id=fact.repo_id
|
|
409
|
+
WHERE ${currentRepositoryPredicate()}
|
|
410
|
+
GROUP BY fact.repo_id,fact.source_file,fact.variable_name,
|
|
411
|
+
fact.binding_site_start_offset,fact.binding_site_end_offset
|
|
412
|
+
HAVING COUNT(*)<>1
|
|
413
|
+
)`, workspaceId);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function bindingCategories(
|
|
417
|
+
db: Db,
|
|
418
|
+
workspaceId?: number,
|
|
419
|
+
): FactSemanticCategoryCount[] {
|
|
420
|
+
return [
|
|
421
|
+
...category('service_binding_site_or_owner_invalid',
|
|
422
|
+
bindingSiteCount(db, workspaceId)),
|
|
423
|
+
...category('service_binding_exact_site_duplicate',
|
|
424
|
+
duplicateBindingSiteCount(db, workspaceId)),
|
|
425
|
+
...category('outbound_binding_reference_invalid',
|
|
426
|
+
bindingReferenceCount(db, workspaceId)),
|
|
427
|
+
];
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function bindingReferenceCount(db: Db, workspaceId?: number): number {
|
|
431
|
+
return count(db, `SELECT COUNT(*) count
|
|
432
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
433
|
+
LEFT JOIN service_bindings binding ON binding.id=fact.service_binding_id
|
|
434
|
+
WHERE ${currentRepositoryPredicate()}
|
|
435
|
+
AND (
|
|
436
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
437
|
+
'$.serviceBindingReference.status'),'')
|
|
438
|
+
NOT IN ('resolved_exact','ambiguous','unresolved','not_applicable')
|
|
439
|
+
OR (json_extract(fact.evidence_json,
|
|
440
|
+
'$.serviceBindingReference.status')='resolved_exact' AND (
|
|
441
|
+
binding.id IS NULL OR binding.repo_id<>fact.repo_id
|
|
442
|
+
OR binding.source_file IS NOT json_extract(fact.evidence_json,
|
|
443
|
+
'$.serviceBindingReference.bindingSourceFile')
|
|
444
|
+
OR binding.variable_name IS NOT json_extract(fact.evidence_json,
|
|
445
|
+
'$.serviceBindingReference.variableName')
|
|
446
|
+
OR binding.binding_site_start_offset IS NOT json_extract(
|
|
447
|
+
fact.evidence_json,
|
|
448
|
+
'$.serviceBindingReference.bindingSiteStartOffset')
|
|
449
|
+
OR binding.binding_site_end_offset IS NOT json_extract(
|
|
450
|
+
fact.evidence_json,
|
|
451
|
+
'$.serviceBindingReference.bindingSiteEndOffset')))
|
|
452
|
+
OR (json_extract(fact.evidence_json,
|
|
453
|
+
'$.serviceBindingReference.status') IN ('ambiguous','unresolved')
|
|
454
|
+
AND (fact.service_binding_id IS NOT NULL
|
|
455
|
+
OR typeof(json_extract(fact.evidence_json,
|
|
456
|
+
'$.serviceBindingReference.reason'))<>'text'))
|
|
457
|
+
OR (json_extract(fact.evidence_json,
|
|
458
|
+
'$.serviceBindingReference.status')='not_applicable'
|
|
459
|
+
AND (fact.service_binding_id IS NOT NULL
|
|
460
|
+
OR json_extract(fact.evidence_json,
|
|
461
|
+
'$.serviceBindingReference.variableName') IS NOT NULL))
|
|
462
|
+
)`, workspaceId);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function handlerStatusCount(db: Db, workspaceId?: number): number {
|
|
466
|
+
return count(db, `SELECT COUNT(*) count FROM outbound_calls fact
|
|
467
|
+
JOIN repositories r ON r.id=fact.repo_id
|
|
468
|
+
WHERE ${currentRepositoryPredicate()}
|
|
469
|
+
AND fact.call_type='async_subscribe'
|
|
470
|
+
AND (
|
|
471
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
472
|
+
'$.handlerReferenceStatus'),'')
|
|
473
|
+
NOT IN ('role_required','unsupported_inline','unsupported_wrapper',
|
|
474
|
+
'unsupported_reference_shape','missing_argument')
|
|
475
|
+
OR (json_extract(fact.evidence_json,
|
|
476
|
+
'$.handlerReferenceStatus')='role_required' AND (
|
|
477
|
+
json_extract(fact.evidence_json,
|
|
478
|
+
'$.handlerReferenceReason') IS NOT NULL
|
|
479
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
480
|
+
'$.handlerReferenceShape'),'') NOT IN (
|
|
481
|
+
'identifier','namespace_member','static_member','default_member',
|
|
482
|
+
'wrapped_identifier','wrapped_namespace_member',
|
|
483
|
+
'wrapped_static_member','wrapped_default_member')))
|
|
484
|
+
OR (json_extract(fact.evidence_json,
|
|
485
|
+
'$.handlerReferenceStatus')='unsupported_inline' AND (
|
|
486
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
487
|
+
'$.handlerReferenceReason'),'')<>'inline_handler_body_not_indexed'
|
|
488
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
489
|
+
'$.handlerReferenceShape'),'')<>'inline_callback'))
|
|
490
|
+
OR (json_extract(fact.evidence_json,
|
|
491
|
+
'$.handlerReferenceStatus')='unsupported_wrapper' AND (
|
|
492
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
493
|
+
'$.handlerReferenceReason'),'') NOT IN (
|
|
494
|
+
'wrapper_requires_one_reference',
|
|
495
|
+
'wrapper_reference_shape_unsupported')
|
|
496
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
497
|
+
'$.handlerReferenceShape'),'')<>'wrapper_call'))
|
|
498
|
+
OR (json_extract(fact.evidence_json,
|
|
499
|
+
'$.handlerReferenceStatus')='unsupported_reference_shape' AND (
|
|
500
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
501
|
+
'$.handlerReferenceReason'),'')
|
|
502
|
+
<>'handler_reference_shape_unsupported'
|
|
503
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
504
|
+
'$.handlerReferenceShape'),'')<>'unsupported_expression'))
|
|
505
|
+
OR (json_extract(fact.evidence_json,
|
|
506
|
+
'$.handlerReferenceStatus')='missing_argument' AND (
|
|
507
|
+
COALESCE(json_extract(fact.evidence_json,
|
|
508
|
+
'$.handlerReferenceReason'),'')<>'handler_argument_missing'
|
|
509
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
510
|
+
'$.handlerReferenceShape'),'')<>'missing'))
|
|
511
|
+
)`, workspaceId);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function handlerAssociationCount(db: Db, workspaceId?: number): number {
|
|
515
|
+
return count(db, `SELECT COUNT(*) count FROM (
|
|
516
|
+
SELECT fact.id,
|
|
517
|
+
json_extract(fact.evidence_json,
|
|
518
|
+
'$.handlerReferenceStatus') handler_status,
|
|
519
|
+
COUNT(role.id) role_count
|
|
520
|
+
FROM outbound_calls fact JOIN repositories r ON r.id=fact.repo_id
|
|
521
|
+
LEFT JOIN symbol_calls role ON role.repo_id=fact.repo_id
|
|
522
|
+
AND role.source_file=fact.source_file
|
|
523
|
+
AND role.call_site_start_offset=fact.call_site_start_offset
|
|
524
|
+
AND role.call_site_end_offset=fact.call_site_end_offset
|
|
525
|
+
AND role.call_role='event_subscribe_handler'
|
|
526
|
+
WHERE ${currentRepositoryPredicate()}
|
|
527
|
+
AND fact.call_type='async_subscribe'
|
|
528
|
+
GROUP BY fact.id HAVING
|
|
529
|
+
(handler_status='role_required' AND role_count<>1)
|
|
530
|
+
OR (handler_status<>'role_required' AND role_count<>0)
|
|
531
|
+
)`, workspaceId);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function handlerRoleCount(db: Db, workspaceId?: number): number {
|
|
535
|
+
return count(db, `SELECT COUNT(*) count FROM symbol_calls fact
|
|
536
|
+
JOIN repositories r ON r.id=fact.repo_id
|
|
537
|
+
LEFT JOIN outbound_calls subscription
|
|
538
|
+
ON subscription.repo_id=fact.repo_id
|
|
539
|
+
AND subscription.source_file=fact.source_file
|
|
540
|
+
AND subscription.call_site_start_offset=fact.call_site_start_offset
|
|
541
|
+
AND subscription.call_site_end_offset=fact.call_site_end_offset
|
|
542
|
+
AND subscription.call_type='async_subscribe'
|
|
543
|
+
WHERE ${currentRepositoryPredicate()}
|
|
544
|
+
AND fact.call_role='event_subscribe_handler'
|
|
545
|
+
AND (subscription.id IS NULL
|
|
546
|
+
OR subscription.source_line<>fact.source_line
|
|
547
|
+
OR subscription.source_symbol_id IS NOT fact.caller_symbol_id
|
|
548
|
+
OR COALESCE(json_extract(fact.evidence_json,'$.factOrigin'),'')
|
|
549
|
+
<>'event_subscribe_handler_reference'
|
|
550
|
+
OR typeof(json_extract(fact.evidence_json,'$.candidateStrategy'))
|
|
551
|
+
<>'text'
|
|
552
|
+
OR length(json_extract(fact.evidence_json,'$.candidateStrategy'))=0)`,
|
|
553
|
+
workspaceId);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function eventAssociationCategories(
|
|
557
|
+
db: Db,
|
|
558
|
+
workspaceId?: number,
|
|
559
|
+
): FactSemanticCategoryCount[] {
|
|
560
|
+
return [
|
|
561
|
+
...category('subscription_handler_status_invalid',
|
|
562
|
+
handlerStatusCount(db, workspaceId)),
|
|
563
|
+
...category('subscription_handler_cardinality_invalid',
|
|
564
|
+
handlerAssociationCount(db, workspaceId)),
|
|
565
|
+
...category('event_handler_role_provenance_invalid',
|
|
566
|
+
handlerRoleCount(db, workspaceId)),
|
|
567
|
+
];
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const symbolResolutionSql = `SELECT COUNT(*) count FROM symbol_calls fact
|
|
571
|
+
JOIN repositories r ON r.id=fact.repo_id
|
|
572
|
+
LEFT JOIN symbols target ON target.id=fact.callee_symbol_id
|
|
573
|
+
LEFT JOIN repositories target_repo ON target_repo.id=target.repo_id
|
|
574
|
+
WHERE ${currentRepositoryPredicate()}
|
|
575
|
+
AND (fact.status NOT IN ('resolved','ambiguous','unresolved')
|
|
576
|
+
OR typeof(json_extract(fact.evidence_json,'$.candidateStrategy'))
|
|
577
|
+
<>'text'
|
|
578
|
+
OR length(json_extract(fact.evidence_json,'$.candidateStrategy'))=0
|
|
579
|
+
OR json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
580
|
+
NOT IN (${sqlTextList(symbolStrategies)})
|
|
581
|
+
OR typeof(json_extract(fact.evidence_json,'$.candidateCount'))
|
|
582
|
+
<>'integer'
|
|
583
|
+
OR typeof(json_extract(fact.evidence_json,'$.eligibleCandidateCount'))
|
|
584
|
+
<>'integer'
|
|
585
|
+
OR typeof(json_extract(fact.evidence_json,'$.selectedCandidateCount'))
|
|
586
|
+
<>'integer'
|
|
587
|
+
OR COALESCE(json_type(
|
|
588
|
+
fact.evidence_json,'$.candidateSetComplete'),'missing')
|
|
589
|
+
NOT IN ('true','false')
|
|
590
|
+
OR json_extract(fact.evidence_json,'$.candidateCount')<0
|
|
591
|
+
OR json_extract(fact.evidence_json,'$.eligibleCandidateCount')<0
|
|
592
|
+
OR json_extract(fact.evidence_json,'$.selectedCandidateCount')
|
|
593
|
+
NOT IN (0,1)
|
|
594
|
+
OR json_extract(fact.evidence_json,'$.selectedCandidateCount')
|
|
595
|
+
>json_extract(fact.evidence_json,'$.eligibleCandidateCount')
|
|
596
|
+
OR json_extract(fact.evidence_json,'$.eligibleCandidateCount')
|
|
597
|
+
>json_extract(fact.evidence_json,'$.candidateCount')
|
|
598
|
+
OR fact.unresolved_reason IS NOT json_extract(
|
|
599
|
+
fact.evidence_json,'$.unresolvedReason')
|
|
600
|
+
OR (fact.status='resolved' AND (
|
|
601
|
+
fact.callee_symbol_id IS NULL OR target.id IS NULL
|
|
602
|
+
OR target_repo.workspace_id IS NOT r.workspace_id
|
|
603
|
+
OR json_extract(fact.evidence_json,'$.candidateSetComplete')<>1
|
|
604
|
+
OR json_extract(fact.evidence_json,'$.eligibleCandidateCount')<>1
|
|
605
|
+
OR json_extract(fact.evidence_json,'$.selectedCandidateCount')<>1
|
|
606
|
+
OR fact.unresolved_reason IS NOT NULL
|
|
607
|
+
OR COALESCE(json_type(
|
|
608
|
+
fact.evidence_json,'$.unresolvedReason'),'missing')<>'null'))
|
|
609
|
+
OR (fact.status='ambiguous' AND (
|
|
610
|
+
fact.callee_symbol_id IS NOT NULL
|
|
611
|
+
OR json_extract(fact.evidence_json,'$.candidateSetComplete')<>1
|
|
612
|
+
OR json_extract(fact.evidence_json,'$.eligibleCandidateCount')<2
|
|
613
|
+
OR json_extract(fact.evidence_json,'$.selectedCandidateCount')<>0
|
|
614
|
+
OR typeof(fact.unresolved_reason)<>'text'
|
|
615
|
+
OR length(fact.unresolved_reason)=0
|
|
616
|
+
OR COALESCE(json_type(
|
|
617
|
+
fact.evidence_json,'$.unresolvedReason'),'missing')<>'text'
|
|
618
|
+
OR fact.unresolved_reason NOT IN (${sqlTextList(symbolReasons)})))
|
|
619
|
+
OR (fact.status='unresolved' AND (
|
|
620
|
+
fact.callee_symbol_id IS NOT NULL
|
|
621
|
+
OR json_extract(fact.evidence_json,'$.selectedCandidateCount')<>0
|
|
622
|
+
OR typeof(fact.unresolved_reason)<>'text'
|
|
623
|
+
OR length(fact.unresolved_reason)=0
|
|
624
|
+
OR COALESCE(json_type(
|
|
625
|
+
fact.evidence_json,'$.unresolvedReason'),'missing')<>'text'
|
|
626
|
+
OR fact.unresolved_reason NOT IN (${sqlTextList(symbolReasons)})
|
|
627
|
+
OR (json_extract(fact.evidence_json,'$.candidateSetComplete')=1
|
|
628
|
+
AND json_extract(fact.evidence_json,
|
|
629
|
+
'$.eligibleCandidateCount')<>0)
|
|
630
|
+
OR (json_extract(fact.evidence_json,'$.candidateSetComplete')=0
|
|
631
|
+
AND fact.unresolved_reason NOT IN (
|
|
632
|
+
${sqlTextList(incompleteReasons)}))))
|
|
633
|
+
OR (json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
634
|
+
='package_import_pending'
|
|
635
|
+
AND (COALESCE(json_extract(fact.evidence_json,'$.relation'),'')
|
|
636
|
+
<>'package_import'
|
|
637
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
638
|
+
'$.importBinding.moduleKind'),'')<>'package'))
|
|
639
|
+
OR (json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
640
|
+
IN (${sqlTextList(packageStrategies)})
|
|
641
|
+
AND (COALESCE(json_extract(
|
|
642
|
+
fact.evidence_json,'$.relation'),'')<>'package_import'
|
|
643
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
644
|
+
'$.importBinding.moduleKind'),'')<>'package'))
|
|
645
|
+
OR (json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
646
|
+
='package_import_derived_member_unsupported'
|
|
647
|
+
AND (COALESCE(json_extract(fact.evidence_json,'$.relation'),'')
|
|
648
|
+
<>'package_import_derived_member'
|
|
649
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
650
|
+
'$.derivedImportBinding.moduleKind'),'')<>'package'))
|
|
651
|
+
OR (json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
652
|
+
IN (${sqlTextList(relativeStrategies)})
|
|
653
|
+
AND (COALESCE(json_extract(fact.evidence_json,
|
|
654
|
+
'$.importBinding.moduleKind'),'')<>'relative'
|
|
655
|
+
OR COALESCE(fact.import_source,'') NOT LIKE '.%'))
|
|
656
|
+
OR (json_extract(fact.evidence_json,'$.candidateStrategy')
|
|
657
|
+
IN (${sqlTextList(simpleStrategies)})
|
|
658
|
+
AND (fact.import_source IS NOT NULL
|
|
659
|
+
OR COALESCE(json_extract(fact.evidence_json,
|
|
660
|
+
'$.importBinding.moduleKind'),'') IN ('relative','package')
|
|
661
|
+
OR COALESCE(json_extract(fact.evidence_json,'$.relation'),'')
|
|
662
|
+
IN ('package_import','package_import_derived_member')))
|
|
663
|
+
__PACKAGE_PENDING_TERMINAL_CHECK__)`;
|
|
664
|
+
|
|
665
|
+
function symbolResolutionCount(
|
|
666
|
+
db: Db,
|
|
667
|
+
workspaceId: number | undefined,
|
|
668
|
+
phase: PackageFactPhase,
|
|
669
|
+
): number {
|
|
670
|
+
const pendingInvalid = phase === 'terminal'
|
|
671
|
+
? "OR json_extract(fact.evidence_json,'$.candidateStrategy')='package_import_pending'"
|
|
672
|
+
: '';
|
|
673
|
+
return count(db, symbolResolutionSql.replace(
|
|
674
|
+
'__PACKAGE_PENDING_TERMINAL_CHECK__', pendingInvalid,
|
|
675
|
+
), workspaceId);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
export function invalidFactSemanticCategories(
|
|
679
|
+
db: Db,
|
|
680
|
+
workspaceId?: number,
|
|
681
|
+
phase: PackageFactPhase = 'pre_package',
|
|
682
|
+
): FactSemanticCategoryCount[] {
|
|
683
|
+
return [
|
|
684
|
+
...repositoryCategories(db, workspaceId),
|
|
685
|
+
...operationCategories(db, workspaceId),
|
|
686
|
+
...callSpanCategories(db, workspaceId),
|
|
687
|
+
...duplicateSymbolCallCategories(db, workspaceId),
|
|
688
|
+
...eventNameCategories(db, workspaceId),
|
|
689
|
+
...ownerCategories(db, workspaceId),
|
|
690
|
+
...bindingCategories(db, workspaceId),
|
|
691
|
+
...invalidBindingFactCategories(db, workspaceId),
|
|
692
|
+
...eventAssociationCategories(db, workspaceId),
|
|
693
|
+
...invalidPackageFactCategories(db, workspaceId, phase),
|
|
694
|
+
...invalidRelativeFactCategories(db, workspaceId),
|
|
695
|
+
...invalidSymbolFactCategories(db, workspaceId),
|
|
696
|
+
...category('symbol_call_resolution_matrix_invalid',
|
|
697
|
+
symbolResolutionCount(db, workspaceId, phase)),
|
|
698
|
+
];
|
|
699
|
+
}
|