gitnexus 1.6.5-rc.40 → 1.6.5-rc.41
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.
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
*
|
|
16
16
|
* ## Current boundary
|
|
17
17
|
*
|
|
18
|
-
* The current implementation covers
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* `
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
18
|
+
* The current implementation covers class-typed arguments (value, pointer,
|
|
19
|
+
* and reference) and template specializations with explicit type arguments:
|
|
20
|
+
* - `audit::Event e`, `audit::Event* p`, `audit::Event** pp`
|
|
21
|
+
* - `audit::Event& r`, `audit::Event&& rr`
|
|
22
|
+
* - `std::vector<audit::Event>` (template namespace + template-arg namespaces)
|
|
23
|
+
*
|
|
24
|
+
* Function-pointer arguments, base-class associated namespaces, and the rest
|
|
25
|
+
* of the full closure are still deliberately excluded.
|
|
26
26
|
*
|
|
27
27
|
* The current implementation also short-circuits to ADL only when ordinary lookup is empty
|
|
28
28
|
* (`findCallableBindingInScope` returned undefined). ISO C++ would
|
|
@@ -61,8 +61,20 @@ import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexe
|
|
|
61
61
|
*/
|
|
62
62
|
export interface CppAdlArgInfo {
|
|
63
63
|
/** Simple class-like type name (last segment of qualified name); empty
|
|
64
|
-
* for primitives, literals, function pointers,
|
|
64
|
+
* for primitives, literals, function pointers, etc. */
|
|
65
65
|
readonly simpleClassName: string;
|
|
66
|
+
/** Template's own simple class-like name (e.g. `vector` for
|
|
67
|
+
* `std::vector<N::T>`), empty when arg type is not a template spec. */
|
|
68
|
+
readonly templateSimpleClassName: string;
|
|
69
|
+
/** Template's own enclosing namespace (dot-qualified, e.g. `std`), empty
|
|
70
|
+
* when unavailable / unqualified. */
|
|
71
|
+
readonly templateNamespace: string;
|
|
72
|
+
/** Class-like names extracted from explicit type template arguments,
|
|
73
|
+
* recursively bounded. */
|
|
74
|
+
readonly templateArgClassNames: readonly string[];
|
|
75
|
+
/** Enclosing namespaces extracted from explicit type template arguments,
|
|
76
|
+
* recursively bounded. */
|
|
77
|
+
readonly templateArgNamespaces: readonly string[];
|
|
66
78
|
}
|
|
67
79
|
/** Sentinel returned by `pickCppAdlCandidates` when ADL surfaces multiple
|
|
68
80
|
* candidates that share normalized parameter types — the caller MUST
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
*
|
|
16
16
|
* ## Current boundary
|
|
17
17
|
*
|
|
18
|
-
* The current implementation covers
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* `
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
18
|
+
* The current implementation covers class-typed arguments (value, pointer,
|
|
19
|
+
* and reference) and template specializations with explicit type arguments:
|
|
20
|
+
* - `audit::Event e`, `audit::Event* p`, `audit::Event** pp`
|
|
21
|
+
* - `audit::Event& r`, `audit::Event&& rr`
|
|
22
|
+
* - `std::vector<audit::Event>` (template namespace + template-arg namespaces)
|
|
23
|
+
*
|
|
24
|
+
* Function-pointer arguments, base-class associated namespaces, and the rest
|
|
25
|
+
* of the full closure are still deliberately excluded.
|
|
26
26
|
*
|
|
27
27
|
* The current implementation also short-circuits to ADL only when ordinary lookup is empty
|
|
28
28
|
* (`findCallableBindingInScope` returned undefined). ISO C++ would
|
|
@@ -132,14 +132,7 @@ export function pickCppAdlCandidates(site, callerParsed, scopes, parsedFiles) {
|
|
|
132
132
|
// Collect associated namespace QNames from every participating class-typed arg.
|
|
133
133
|
const associatedNamespaces = new Set();
|
|
134
134
|
for (const arg of args) {
|
|
135
|
-
|
|
136
|
-
continue;
|
|
137
|
-
const classDef = findCppClassDefBySimpleName(arg.simpleClassName, scopes);
|
|
138
|
-
if (classDef === undefined)
|
|
139
|
-
continue;
|
|
140
|
-
const nsQName = classToNamespaceQualifiedName.get(classDef.nodeId);
|
|
141
|
-
if (nsQName !== undefined)
|
|
142
|
-
associatedNamespaces.add(nsQName);
|
|
135
|
+
collectAssociatedNamespacesForAdlArg(arg, scopes, associatedNamespaces);
|
|
143
136
|
}
|
|
144
137
|
if (associatedNamespaces.size === 0)
|
|
145
138
|
return undefined;
|
|
@@ -196,6 +189,34 @@ export function pickCppAdlCandidates(site, callerParsed, scopes, parsedFiles) {
|
|
|
196
189
|
// unique-survivor requirement (see `pick-implicit-this-overload.test.ts`).
|
|
197
190
|
return ADL_AMBIGUOUS;
|
|
198
191
|
}
|
|
192
|
+
function collectAssociatedNamespacesForAdlArg(arg, scopes, associatedNamespaces) {
|
|
193
|
+
// For template args this may be the template name itself (e.g. `vector`);
|
|
194
|
+
// simple-name lookup can match project classes with the same name (known
|
|
195
|
+
// V1/V2 simplification).
|
|
196
|
+
addAssociatedNamespaceForClassName(arg.simpleClassName, scopes, associatedNamespaces);
|
|
197
|
+
// Includes template-owner namespaces (e.g. `std` in std::vector<T>). If
|
|
198
|
+
// that surfaces extra candidates, ADL_AMBIGUOUS suppression below prevents
|
|
199
|
+
// arbitrary edge emission.
|
|
200
|
+
if (arg.templateNamespace.length > 0)
|
|
201
|
+
associatedNamespaces.add(arg.templateNamespace);
|
|
202
|
+
for (const ns of arg.templateArgNamespaces) {
|
|
203
|
+
if (ns.length > 0)
|
|
204
|
+
associatedNamespaces.add(ns);
|
|
205
|
+
}
|
|
206
|
+
for (const className of arg.templateArgClassNames) {
|
|
207
|
+
addAssociatedNamespaceForClassName(className, scopes, associatedNamespaces);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function addAssociatedNamespaceForClassName(simpleClassName, scopes, associatedNamespaces) {
|
|
211
|
+
if (simpleClassName.length === 0)
|
|
212
|
+
return;
|
|
213
|
+
const classDef = findCppClassDefBySimpleName(simpleClassName, scopes);
|
|
214
|
+
if (classDef === undefined)
|
|
215
|
+
return;
|
|
216
|
+
const nsQName = classToNamespaceQualifiedName.get(classDef.nodeId);
|
|
217
|
+
if (nsQName !== undefined)
|
|
218
|
+
associatedNamespaces.add(nsQName);
|
|
219
|
+
}
|
|
199
220
|
/** Walk upward from a Class scope, finding the innermost enclosing
|
|
200
221
|
* Namespace scope, and return that namespace's qualified name (dot-
|
|
201
222
|
* joined, outermost-first). Returns '' when the class has no enclosing
|
|
@@ -657,12 +657,14 @@ function isParenthesizedFunctionCall(callNode) {
|
|
|
657
657
|
}
|
|
658
658
|
/**
|
|
659
659
|
* Per-argument ADL classification: walk each argument of a free call and
|
|
660
|
-
*
|
|
661
|
-
* type (ADL fires) or to an excluded shape such as a reference, function
|
|
662
|
-
* pointer, primitive, literal, or template specialization.
|
|
660
|
+
* classify its declared type for associated-namespace lookup.
|
|
663
661
|
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
662
|
+
* Value/pointer/reference class-typed args and template specializations
|
|
663
|
+
* with explicit type arguments contribute; function pointers, primitives,
|
|
664
|
+
* literals, and other unsupported shapes produce an empty result.
|
|
665
|
+
*
|
|
666
|
+
* Class-typed values/pointers/references (`N::S`, `N::S*`, `N::S&`) all
|
|
667
|
+
* preserve the class name for associated-namespace lookup.
|
|
666
668
|
* Function pointers remain excluded even when their return type names a
|
|
667
669
|
* class, because the associated entity is the pointed-to function type,
|
|
668
670
|
* not the return type.
|
|
@@ -682,7 +684,14 @@ function inferCppCallAdlArgs(callNode) {
|
|
|
682
684
|
}
|
|
683
685
|
return out;
|
|
684
686
|
}
|
|
685
|
-
const
|
|
687
|
+
const ADL_TEMPLATE_RECURSION_MAX_DEPTH = 8;
|
|
688
|
+
const EMPTY_ADL_ARG = {
|
|
689
|
+
simpleClassName: '',
|
|
690
|
+
templateSimpleClassName: '',
|
|
691
|
+
templateNamespace: '',
|
|
692
|
+
templateArgClassNames: [],
|
|
693
|
+
templateArgNamespaces: [],
|
|
694
|
+
};
|
|
686
695
|
function classifyAdlArg(argNode) {
|
|
687
696
|
// Literals and primitive-shaped expressions never have associated namespaces.
|
|
688
697
|
if (argNode.type === 'number_literal' ||
|
|
@@ -783,21 +792,51 @@ function lookupAdlIdentifierType(identNode) {
|
|
|
783
792
|
if (isFunctionPointer || nameText !== varName)
|
|
784
793
|
continue;
|
|
785
794
|
const simpleClassName = extractAdlSimpleTypeName(typeNode);
|
|
786
|
-
|
|
795
|
+
const { templateSimpleClassName, templateNamespace, templateArgClassNames, templateArgNamespaces, } = extractAdlTemplateInfo(typeNode);
|
|
796
|
+
return {
|
|
797
|
+
simpleClassName,
|
|
798
|
+
templateSimpleClassName,
|
|
799
|
+
templateNamespace,
|
|
800
|
+
templateArgClassNames,
|
|
801
|
+
templateArgNamespaces,
|
|
802
|
+
};
|
|
787
803
|
}
|
|
788
804
|
return EMPTY_ADL_ARG;
|
|
789
805
|
}
|
|
790
806
|
/** Extract the simple class-like type name from a `type:` field node.
|
|
791
|
-
* Returns '' for primitives
|
|
807
|
+
* Returns '' for primitives and any other
|
|
792
808
|
* unsupported type-only shape. Function pointers are filtered at the
|
|
793
809
|
* declarator level in `lookupAdlIdentifierType`. */
|
|
794
810
|
function extractAdlSimpleTypeName(typeNode) {
|
|
811
|
+
if (typeNode.type === 'type_descriptor') {
|
|
812
|
+
const innerType = typeNode.childForFieldName('type');
|
|
813
|
+
if (innerType !== null)
|
|
814
|
+
return extractAdlSimpleTypeName(innerType);
|
|
815
|
+
for (let i = 0; i < typeNode.childCount; i++) {
|
|
816
|
+
const child = typeNode.child(i);
|
|
817
|
+
if (child === null)
|
|
818
|
+
continue;
|
|
819
|
+
if (child.type === 'type_identifier' ||
|
|
820
|
+
child.type === 'qualified_identifier' ||
|
|
821
|
+
child.type === 'template_type') {
|
|
822
|
+
return extractAdlSimpleTypeName(child);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return '';
|
|
826
|
+
}
|
|
795
827
|
if (typeNode.type === 'primitive_type')
|
|
796
828
|
return '';
|
|
797
829
|
if (typeNode.type === 'sized_type_specifier')
|
|
798
830
|
return '';
|
|
799
831
|
if (typeNode.type === 'type_identifier')
|
|
800
832
|
return typeNode.text;
|
|
833
|
+
if (typeNode.type === 'template_type') {
|
|
834
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
835
|
+
if (nameNode !== null)
|
|
836
|
+
return extractAdlSimpleTypeName(nameNode);
|
|
837
|
+
const id = findFirstDescendantOfType(typeNode, 'type_identifier');
|
|
838
|
+
return id !== null ? id.text : '';
|
|
839
|
+
}
|
|
801
840
|
if (typeNode.type === 'qualified_identifier') {
|
|
802
841
|
const nameNode = typeNode.childForFieldName('name');
|
|
803
842
|
if (nameNode !== null)
|
|
@@ -805,9 +844,112 @@ function extractAdlSimpleTypeName(typeNode) {
|
|
|
805
844
|
const id = findFirstDescendantOfType(typeNode, 'type_identifier');
|
|
806
845
|
return id !== null ? id.text : '';
|
|
807
846
|
}
|
|
808
|
-
//
|
|
847
|
+
// Function pointers, decltype, etc — unsupported for ADL participation.
|
|
848
|
+
return '';
|
|
849
|
+
}
|
|
850
|
+
function extractAdlTypeNamespace(typeNode) {
|
|
851
|
+
if (typeNode.type === 'type_descriptor') {
|
|
852
|
+
const innerType = typeNode.childForFieldName('type');
|
|
853
|
+
if (innerType !== null)
|
|
854
|
+
return extractAdlTypeNamespace(innerType);
|
|
855
|
+
for (let i = 0; i < typeNode.childCount; i++) {
|
|
856
|
+
const child = typeNode.child(i);
|
|
857
|
+
if (child === null)
|
|
858
|
+
continue;
|
|
859
|
+
if (child.type === 'qualified_identifier' ||
|
|
860
|
+
child.type === 'template_type' ||
|
|
861
|
+
child.type === 'type_identifier') {
|
|
862
|
+
return extractAdlTypeNamespace(child);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return '';
|
|
866
|
+
}
|
|
867
|
+
if (typeNode.type === 'template_type') {
|
|
868
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
869
|
+
return nameNode !== null ? extractAdlTypeNamespace(nameNode) : '';
|
|
870
|
+
}
|
|
871
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
872
|
+
const scope = typeNode.childForFieldName('scope');
|
|
873
|
+
if (scope !== null)
|
|
874
|
+
return normalizeCppNamespaceQName(scope.text);
|
|
875
|
+
return extractNamespaceFromQualifiedText(typeNode.text);
|
|
876
|
+
}
|
|
809
877
|
return '';
|
|
810
878
|
}
|
|
879
|
+
function extractAdlTemplateInfo(typeNode) {
|
|
880
|
+
const templateTypeNode = findTemplateTypeNode(typeNode);
|
|
881
|
+
if (templateTypeNode === null) {
|
|
882
|
+
return {
|
|
883
|
+
templateSimpleClassName: '',
|
|
884
|
+
templateNamespace: '',
|
|
885
|
+
templateArgClassNames: [],
|
|
886
|
+
templateArgNamespaces: [],
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
const templateArgClassNames = [];
|
|
890
|
+
const templateArgNamespaces = [];
|
|
891
|
+
collectAdlTemplateArgs(templateTypeNode, 0, templateArgClassNames, templateArgNamespaces);
|
|
892
|
+
return {
|
|
893
|
+
templateSimpleClassName: extractAdlSimpleTypeName(templateTypeNode),
|
|
894
|
+
templateNamespace: extractAdlTypeNamespace(typeNode),
|
|
895
|
+
templateArgClassNames,
|
|
896
|
+
templateArgNamespaces,
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function collectAdlTemplateArgs(templateTypeNode, depth, outClassNames, outNamespaces) {
|
|
900
|
+
if (depth >= ADL_TEMPLATE_RECURSION_MAX_DEPTH)
|
|
901
|
+
return;
|
|
902
|
+
if (templateTypeNode.type !== 'template_type')
|
|
903
|
+
return;
|
|
904
|
+
const argList = templateTypeNode.childForFieldName('arguments') ??
|
|
905
|
+
findChildOfType(templateTypeNode, ['template_argument_list']);
|
|
906
|
+
if (argList === null)
|
|
907
|
+
return;
|
|
908
|
+
for (let i = 0; i < argList.namedChildCount; i++) {
|
|
909
|
+
const arg = argList.namedChild(i);
|
|
910
|
+
if (arg === null || arg.type !== 'type_descriptor')
|
|
911
|
+
continue;
|
|
912
|
+
const simpleClassName = extractAdlSimpleTypeName(arg);
|
|
913
|
+
if (simpleClassName.length > 0)
|
|
914
|
+
outClassNames.push(simpleClassName);
|
|
915
|
+
const ns = extractAdlTypeNamespace(arg);
|
|
916
|
+
if (ns.length > 0)
|
|
917
|
+
outNamespaces.push(ns);
|
|
918
|
+
const nestedType = arg.childForFieldName('type');
|
|
919
|
+
const nestedTemplate = nestedType !== null ? findTemplateTypeNode(nestedType) : null;
|
|
920
|
+
if (nestedTemplate !== null) {
|
|
921
|
+
collectAdlTemplateArgs(nestedTemplate, depth + 1, outClassNames, outNamespaces);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function findTemplateTypeNode(typeNode) {
|
|
926
|
+
if (typeNode.type === 'template_type')
|
|
927
|
+
return typeNode;
|
|
928
|
+
if (typeNode.type === 'type_descriptor') {
|
|
929
|
+
const innerType = typeNode.childForFieldName('type');
|
|
930
|
+
if (innerType !== null)
|
|
931
|
+
return findTemplateTypeNode(innerType);
|
|
932
|
+
return null;
|
|
933
|
+
}
|
|
934
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
935
|
+
const nameNode = typeNode.childForFieldName('name');
|
|
936
|
+
if (nameNode !== null)
|
|
937
|
+
return findTemplateTypeNode(nameNode);
|
|
938
|
+
return null;
|
|
939
|
+
}
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
function normalizeCppNamespaceQName(text) {
|
|
943
|
+
const normalized = text.replace(/^::/, '').replace(/::$/, '').replace(/::/g, '.');
|
|
944
|
+
return normalized;
|
|
945
|
+
}
|
|
946
|
+
function extractNamespaceFromQualifiedText(text) {
|
|
947
|
+
const cleaned = text.replace(/\s+/g, '');
|
|
948
|
+
const idx = cleaned.lastIndexOf('::');
|
|
949
|
+
if (idx <= 0)
|
|
950
|
+
return '';
|
|
951
|
+
return normalizeCppNamespaceQName(cleaned.slice(0, idx));
|
|
952
|
+
}
|
|
811
953
|
/**
|
|
812
954
|
* Check if a C++ function_definition or declaration has `static` storage class.
|
|
813
955
|
*/
|
|
@@ -188,8 +188,10 @@ export const cppScopeResolver = {
|
|
|
188
188
|
// C++ argument-dependent / Koenig lookup (U2 of plan 2026-05-13-001).
|
|
189
189
|
// Fires after `findCallableBindingInScope` returns undefined; surfaces
|
|
190
190
|
// candidates from the associated namespaces of class-typed arguments.
|
|
191
|
-
//
|
|
192
|
-
//
|
|
191
|
+
// Current boundary: class-typed value/pointer/reference args and template
|
|
192
|
+
// specializations with explicit type arguments contribute associated
|
|
193
|
+
// namespaces. Function-pointer args, base-class associated namespaces,
|
|
194
|
+
// and full ordinary+ADL merge remain excluded.
|
|
193
195
|
resolveAdlCandidates: (site, callerParsed, scopes, parsedFiles) => {
|
|
194
196
|
// `using ns::name;` introduces `name` into ordinary unqualified lookup.
|
|
195
197
|
// For template-class method bodies, lexical scope walks can miss this
|
package/package.json
CHANGED