55import 'package:analysis_server/plugin/analysis/occurrences/occurrences_core.dart' ;
66import 'package:analysis_server/src/protocol_server.dart' as protocol;
77import 'package:analyzer/dart/ast/ast.dart' ;
8+ import 'package:analyzer/dart/ast/token.dart' ;
89import 'package:analyzer/dart/ast/visitor.dart' ;
910import 'package:analyzer/dart/element/element2.dart' ;
1011import 'package:analyzer/src/dart/ast/extensions.dart' ;
1112import 'package:analyzer/src/dart/element/element.dart' ;
1213
1314void addDartOccurrences (OccurrencesCollector collector, CompilationUnit unit) {
14- var visitor = _DartUnitOccurrencesComputerVisitor ();
15+ var visitor = DartUnitOccurrencesComputerVisitor ();
1516 unit.accept (visitor);
16- visitor.elementsOffsets.forEach ((engineElement, offsets) {
17- var length = engineElement.name3? .length ?? 0 ;
17+ visitor.elementsOffsetLengths.forEach ((engineElement, offsetLengths) {
18+ // For legacy protocol, we only support occurrences with the same
19+ // length, so we must filter the offset to only those that match the length
20+ // from the element.
1821 var serverElement = protocol.convertElement2 (engineElement);
22+ // Prefer the length from the mapped element over the element directly,
23+ // because 'name3' may contain 'new' for constructors which doesn't match
24+ // what is in the source.
25+ var length =
26+ serverElement.location? .length ?? engineElement.name3? .length ?? 0 ;
27+ var offsets =
28+ offsetLengths
29+ .where ((offsetLength) => offsetLength.$2 == length)
30+ .map ((offsetLength) => offsetLength.$1)
31+ .toList ();
32+
1933 var occurrences = protocol.Occurrences (serverElement, offsets, length);
2034 collector.addOccurrences (occurrences);
2135 });
2236}
2337
24- class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor <void > {
25- final Map <Element2 , List <int >> elementsOffsets = {};
38+ class DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor <void > {
39+ final Map <Element2 , List <( int , int ) >> elementsOffsetLengths = {};
2640
2741 @override
2842 void visitAssignedVariablePattern (AssignedVariablePattern node) {
2943 var element = node.element2;
3044 if (element != null ) {
31- _addOccurrence (element, node.name.offset );
45+ _addOccurrence (element, node.name);
3246 }
3347
3448 super .visitAssignedVariablePattern (node);
3549 }
3650
3751 @override
3852 void visitClassDeclaration (ClassDeclaration node) {
39- _addOccurrence (node.declaredFragment! .element, node.name.offset );
53+ _addOccurrence (node.declaredFragment! .element, node.name);
4054
4155 super .visitClassDeclaration (node);
4256 }
4357
4458 @override
4559 void visitClassTypeAlias (ClassTypeAlias node) {
46- _addOccurrence (node.declaredFragment! .element, node.name.offset );
60+ _addOccurrence (node.declaredFragment! .element, node.name);
4761
4862 super .visitClassTypeAlias (node);
4963 }
5064
5165 @override
5266 void visitConstructorDeclaration (ConstructorDeclaration node) {
5367 if (node.name case var name? ) {
54- _addOccurrence (node.declaredFragment! .element, name.offset);
68+ _addOccurrence (node.declaredFragment! .element, name);
69+ } else {
70+ _addOccurrenceAt (
71+ node.declaredFragment! .element,
72+ node.returnType.offset,
73+ node.returnType.length,
74+ );
5575 }
5676
5777 super .visitConstructorDeclaration (node);
5878 }
5979
80+ @override
81+ void visitConstructorName (ConstructorName node) {
82+ // For unnamed constructors, we add an occurence for the constructor at
83+ // the location of the returnType.
84+ if (node.name == null ) {
85+ var element = node.element;
86+ if (element != null ) {
87+ _addOccurrence (element, node.type.name2);
88+ }
89+ return ; // skip visitNamedType.
90+ }
91+
92+ super .visitConstructorName (node);
93+ }
94+
6095 @override
6196 void visitDeclaredIdentifier (DeclaredIdentifier node) {
62- _addOccurrence (node.declaredFragment! .element, node.name.offset );
97+ _addOccurrence (node.declaredFragment! .element, node.name);
6398
6499 super .visitDeclaredIdentifier (node);
65100 }
66101
67102 @override
68103 void visitDeclaredVariablePattern (DeclaredVariablePattern node) {
69- _addOccurrence (node.declaredElement2! , node.name.offset );
104+ _addOccurrence (node.declaredElement2! , node.name);
70105
71106 super .visitDeclaredVariablePattern (node);
72107 }
73108
74109 @override
75110 void visitEnumConstantDeclaration (EnumConstantDeclaration node) {
76- _addOccurrence (node.declaredFragment! .element, node.name.offset );
111+ _addOccurrence (node.declaredFragment! .element, node.name);
77112
78113 super .visitEnumConstantDeclaration (node);
79114 }
80115
81116 @override
82117 void visitEnumDeclaration (EnumDeclaration node) {
83- _addOccurrence (node.declaredFragment! .element, node.name.offset );
118+ _addOccurrence (node.declaredFragment! .element, node.name);
84119
85120 super .visitEnumDeclaration (node);
86121 }
87122
88123 @override
89124 void visitExtensionTypeDeclaration (ExtensionTypeDeclaration node) {
90- _addOccurrence (node.declaredFragment! .element, node.name.offset );
125+ _addOccurrence (node.declaredFragment! .element, node.name);
91126
92127 super .visitExtensionTypeDeclaration (node);
93128 }
@@ -98,7 +133,7 @@ class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor<void> {
98133 if (declaredElement is FieldFormalParameterElement2 ) {
99134 var field = declaredElement.field2;
100135 if (field != null ) {
101- _addOccurrence (field, node.name.offset );
136+ _addOccurrence (field, node.name);
102137 }
103138 }
104139
@@ -107,40 +142,40 @@ class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor<void> {
107142
108143 @override
109144 void visitFunctionDeclaration (FunctionDeclaration node) {
110- _addOccurrence (node.declaredFragment! .element, node.name.offset );
145+ _addOccurrence (node.declaredFragment! .element, node.name);
111146 super .visitFunctionDeclaration (node);
112147 }
113148
114149 @override
115150 void visitFunctionTypeAlias (FunctionTypeAlias node) {
116- _addOccurrence (node.declaredFragment! .element, node.name.offset );
151+ _addOccurrence (node.declaredFragment! .element, node.name);
117152
118153 super .visitFunctionTypeAlias (node);
119154 }
120155
121156 @override
122157 void visitGenericTypeAlias (GenericTypeAlias node) {
123- _addOccurrence (node.declaredFragment! .element, node.name.offset );
158+ _addOccurrence (node.declaredFragment! .element, node.name);
124159
125160 super .visitGenericTypeAlias (node);
126161 }
127162
128163 @override
129164 void visitImportPrefixReference (ImportPrefixReference node) {
130- _addOccurrence (node.element2! , node.offset );
165+ _addOccurrence (node.element2! , node.name );
131166
132167 super .visitImportPrefixReference (node);
133168 }
134169
135170 @override
136171 void visitMethodDeclaration (MethodDeclaration node) {
137- _addOccurrence (node.declaredFragment! .element, node.name.offset );
172+ _addOccurrence (node.declaredFragment! .element, node.name);
138173 super .visitMethodDeclaration (node);
139174 }
140175
141176 @override
142177 void visitMixinDeclaration (MixinDeclaration node) {
143- _addOccurrence (node.declaredFragment! .element, node.name.offset );
178+ _addOccurrence (node.declaredFragment! .element, node.name);
144179
145180 super .visitMixinDeclaration (node);
146181 }
@@ -149,7 +184,7 @@ class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor<void> {
149184 void visitNamedType (NamedType node) {
150185 var element = node.element2;
151186 if (element != null ) {
152- _addOccurrence (element, node.name2.offset );
187+ _addOccurrence (element, node.name2);
153188 }
154189
155190 super .visitNamedType (node);
@@ -165,18 +200,15 @@ class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor<void> {
165200 ? pattern.name
166201 : node.name? .name;
167202 if (element != null && name != null ) {
168- _addOccurrence (element, name.offset );
203+ _addOccurrence (element, name);
169204 }
170205 super .visitPatternField (node);
171206 }
172207
173208 @override
174209 void visitRepresentationDeclaration (RepresentationDeclaration node) {
175210 if (node.constructorName case var constructorName? ) {
176- _addOccurrence (
177- node.constructorFragment! .element,
178- constructorName.name.offset,
179- );
211+ _addOccurrence (node.constructorFragment! .element, constructorName.name);
180212 }
181213
182214 super .visitRepresentationDeclaration (node);
@@ -186,44 +218,58 @@ class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor<void> {
186218 void visitSimpleFormalParameter (SimpleFormalParameter node) {
187219 var nameToken = node.name;
188220 if (nameToken != null ) {
189- _addOccurrence (node.declaredFragment! .element, nameToken.offset );
221+ _addOccurrence (node.declaredFragment! .element, nameToken);
190222 }
191223
192224 super .visitSimpleFormalParameter (node);
193225 }
194226
195227 @override
196228 void visitSimpleIdentifier (SimpleIdentifier node) {
229+ // For unnamed constructors, we don't want to add an occurrence for the
230+ // class name here because visitConstructorDeclaration will have added one
231+ // for the constructor (not the type).
232+ if (node.parent case ConstructorDeclaration (
233+ : var name,
234+ : var returnType,
235+ ) when name == null && node == returnType) {
236+ return ;
237+ }
238+
197239 var element = node.writeOrReadElement2;
198240 if (element != null ) {
199- _addOccurrence (element, node.offset );
241+ _addOccurrence (element, node.token );
200242 }
201243 return super .visitSimpleIdentifier (node);
202244 }
203245
204246 @override
205247 void visitSuperFormalParameter (SuperFormalParameter node) {
206- _addOccurrence (node.declaredFragment! .element, node.name.offset );
248+ _addOccurrence (node.declaredFragment! .element, node.name);
207249 super .visitSuperFormalParameter (node);
208250 }
209251
210252 @override
211253 void visitVariableDeclaration (VariableDeclaration node) {
212- _addOccurrence (node.declaredFragment! .element, node.name.offset );
254+ _addOccurrence (node.declaredFragment! .element, node.name);
213255 super .visitVariableDeclaration (node);
214256 }
215257
216- void _addOccurrence (Element2 element, int offset) {
258+ void _addOccurrence (Element2 element, Token token) {
259+ _addOccurrenceAt (element, token.offset, token.length);
260+ }
261+
262+ void _addOccurrenceAt (Element2 element, int offset, int length) {
217263 var canonicalElement = _canonicalizeElement (element);
218264 if (canonicalElement == null || element == DynamicElementImpl .instance) {
219265 return ;
220266 }
221- var offsets = elementsOffsets [canonicalElement];
222- if (offsets == null ) {
223- offsets = < int > [];
224- elementsOffsets [canonicalElement] = offsets ;
267+ var offsetLengths = elementsOffsetLengths [canonicalElement];
268+ if (offsetLengths == null ) {
269+ offsetLengths = < ( int , int ) > [];
270+ elementsOffsetLengths [canonicalElement] = offsetLengths ;
225271 }
226- offsets .add (offset);
272+ offsetLengths .add (( offset, length) );
227273 }
228274
229275 Element2 ? _canonicalizeElement (Element2 element) {
0 commit comments