gitnexus 1.6.13-rc.64 → 1.6.13-rc.66

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.
@@ -0,0 +1,9 @@
1
+ import type { ParsedFile, ScopeId, SymbolDefinition } from '../../../../_shared/index.js';
2
+ import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
3
+ export declare function swiftIsCallableVisibleFromCaller(ctx: {
4
+ readonly candidate: SymbolDefinition;
5
+ readonly callerParsed?: ParsedFile;
6
+ readonly callArity?: number;
7
+ readonly callerScope?: ScopeId;
8
+ readonly scopes?: ScopeResolutionIndexes;
9
+ }): boolean;
@@ -0,0 +1,57 @@
1
+ import { findClassBindingInScope } from '../../scope-resolution/scope/walkers.js';
2
+ export function swiftIsCallableVisibleFromCaller(ctx) {
3
+ const indexes = ctx.scopes;
4
+ if (ctx.callerScope === undefined || indexes === undefined || ctx.callArity !== 0)
5
+ return true;
6
+ const name = ctx.candidate.qualifiedName?.split('.').at(-1);
7
+ if (name === undefined)
8
+ return true;
9
+ let scopeId = ctx.callerScope;
10
+ let selfType;
11
+ while (scopeId !== null) {
12
+ const scope = indexes.scopeTree.getScope(scopeId);
13
+ if (scope === undefined)
14
+ break;
15
+ // A local function selected inside the caller wins before member lookup.
16
+ if (scope.kind !== 'Class' &&
17
+ scope.ownedDefs.some((def) => def.nodeId === ctx.candidate.nodeId))
18
+ return true;
19
+ selfType ??= scope.typeBindings.get('self');
20
+ if (scope.kind === 'Class') {
21
+ const classDef = scope.ownedDefs.find((def) => def.type === 'Class') ??
22
+ (selfType === undefined
23
+ ? undefined
24
+ : findClassBindingInScope(ctx.callerScope, selfType.rawName, indexes, undefined, {
25
+ uniqueQualifiedNameFallback: false,
26
+ }));
27
+ const propertyOnOwner = (ownerId, ownerName) => indexes.qualifiedNames.get(`${ownerName}.${name}`).some((defId) => {
28
+ const def = indexes.defs.get(defId);
29
+ return def?.type === 'Property' && def.ownerId === ownerId;
30
+ });
31
+ const ownProperty = scope.ownedDefs.some((def) => def.type === 'Property' && def.qualifiedName?.split('.').at(-1) === name) ||
32
+ (classDef !== undefined &&
33
+ classDef.qualifiedName !== undefined &&
34
+ propertyOnOwner(classDef.nodeId, classDef.qualifiedName));
35
+ const inheritedProperty = classDef !== undefined &&
36
+ indexes.methodDispatch.mroFor(classDef.nodeId).some((ownerId) => {
37
+ const ownerName = indexes.defs.get(ownerId)?.qualifiedName;
38
+ return ownerName !== undefined && propertyOnOwner(ownerId, ownerName);
39
+ });
40
+ if (!ownProperty && !inheritedProperty)
41
+ return true;
42
+ // Swift's nested function is owned by its own Function scope. A
43
+ // same-file sibling must not count as a nearer lexical binding.
44
+ const declarationScope = ctx.callerParsed?.scopes.find((candidateScope) => candidateScope.ownedDefs.some((def) => def.nodeId === ctx.candidate.nodeId));
45
+ if (declarationScope !== undefined &&
46
+ declarationScope.kind === 'Function' &&
47
+ (declarationScope.id === ctx.callerScope ||
48
+ indexes.scopeTree.getAncestors(declarationScope.id).includes(ctx.callerScope)))
49
+ return true;
50
+ // Scope defs do not carry Swift access modifiers. A method positively
51
+ // selected on this type must not be vetoed by an uncertain ancestor.
52
+ return classDef !== undefined && ctx.candidate.ownerId === classDef.nodeId;
53
+ }
54
+ scopeId = scope.parent;
55
+ }
56
+ return true;
57
+ }
@@ -56,6 +56,7 @@ import { swiftArityCompatibility, swiftMergeBindings, interpretSwiftImport, reso
56
56
  import { stripSwiftTypePreservingDecoration } from './interpret.js';
57
57
  import { groupSwiftFilesByModule } from './target-grouping.js';
58
58
  import { swiftIsGlobalNameFallbackPlausible } from './name-fallback-visibility.js';
59
+ import { swiftIsCallableVisibleFromCaller } from './callable-visibility.js';
59
60
  const ZERO_RANGE = { startLine: 0, startCol: 0, endLine: 0, endCol: 0 };
60
61
  const swiftScopeResolver = {
61
62
  language: SupportedLanguages.Swift,
@@ -123,6 +124,7 @@ const swiftScopeResolver = {
123
124
  // no-`new` constructor + cross-file free-call shape).
124
125
  allowGlobalFreeCallFallback: true,
125
126
  isGlobalNameFallbackPlausible: swiftIsGlobalNameFallbackPlausible,
127
+ isCallableVisibleFromCaller: swiftIsCallableVisibleFromCaller,
126
128
  // Swift's call graph models `Type(...)` as a reference to the type
127
129
  // itself, not its `init` — both the legacy DAG and this test suite link
128
130
  // `Foo()` to the Class node even when an explicit `init` exists.
@@ -1112,6 +1112,9 @@ export interface ScopeResolver {
1112
1112
  readonly isCallableVisibleFromCaller?: (ctx: {
1113
1113
  readonly callerParsed: ParsedFile;
1114
1114
  readonly candidate: SymbolDefinition;
1115
+ /** Arity of the actual call, when known. A visibility veto must not
1116
+ * infer applicability from a name match alone. */
1117
+ readonly callArity?: number;
1115
1118
  /** Caller's enclosing scope id. Languages that gate visibility on
1116
1119
  * caller scope (e.g. C++ two-phase template lookup) consult it;
1117
1120
  * others ignore. Optional so existing implementations stay valid. */
@@ -47,12 +47,7 @@ export declare function emitFreeCallFallback(graph: KnowledgeGraph, scopes: Scop
47
47
  * appended to its reason. See `ScopeResolver.markConstructionSites`. */
48
48
  readonly markConstructionSites?: boolean;
49
49
  readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
50
- readonly isCallableVisibleFromCaller?: (ctx: {
51
- readonly callerParsed: ParsedFile;
52
- readonly candidate: SymbolDefinition;
53
- readonly callerScope?: ScopeId;
54
- readonly scopes?: ScopeResolutionIndexes;
55
- }) => boolean;
50
+ readonly isCallableVisibleFromCaller?: ScopeResolver['isCallableVisibleFromCaller'];
56
51
  readonly resolveAdlCandidates?: (site: {
57
52
  readonly name: string;
58
53
  readonly arity?: number;
@@ -447,6 +447,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
447
447
  ? (candidate) => options.isCallableVisibleFromCaller({
448
448
  callerParsed: parsed,
449
449
  candidate,
450
+ callArity: site.arity,
450
451
  callerScope: site.inScope,
451
452
  scopes,
452
453
  })
@@ -514,6 +515,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
514
515
  !options.isCallableVisibleFromCaller({
515
516
  callerParsed: parsed,
516
517
  candidate: fnDef,
518
+ callArity: site.arity,
517
519
  callerScope: site.inScope,
518
520
  scopes,
519
521
  })) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.13-rc.64",
3
+ "version": "1.6.13-rc.66",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",