Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: pkg/analysis_server/lib/src/services/search/search_engine_internal2.dart

Issue 1760243004: Implement search for local elements. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/search/search_engine2_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library services.src.search.search_engine2; 5 library services.src.search.search_engine2;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analysis_server/src/services/index2/index2.dart'; 9 import 'package:analysis_server/src/services/index2/index2.dart';
10 import 'package:analysis_server/src/services/search/search_engine.dart'; 10 import 'package:analysis_server/src/services/search/search_engine.dart';
11 import 'package:analyzer/dart/ast/ast.dart';
12 import 'package:analyzer/dart/ast/visitor.dart';
11 import 'package:analyzer/dart/element/element.dart'; 13 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/src/dart/element/member.dart'; 14 import 'package:analyzer/src/dart/element/member.dart';
13 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; 15 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/generated/source.dart' show SourceRange; 16 import 'package:analyzer/src/generated/source.dart';
15 import 'package:analyzer/src/summary/idl.dart'; 17 import 'package:analyzer/src/summary/idl.dart';
16 18
17 /** 19 /**
18 * A [SearchEngine] implementation. 20 * A [SearchEngine] implementation.
19 */ 21 */
20 class SearchEngineImpl2 implements SearchEngine { 22 class SearchEngineImpl2 implements SearchEngine {
21 final AnalysisContext context; 23 final AnalysisContext context;
22 final Index2 _index; 24 final Index2 _index;
23 25
24 SearchEngineImpl2(this.context, this._index); 26 SearchEngineImpl2(this.context, this._index);
(...skipping 29 matching lines...) Expand all
54 kind == ElementKind.COMPILATION_UNIT || 56 kind == ElementKind.COMPILATION_UNIT ||
55 kind == ElementKind.CONSTRUCTOR || 57 kind == ElementKind.CONSTRUCTOR ||
56 kind == ElementKind.FUNCTION_TYPE_ALIAS || 58 kind == ElementKind.FUNCTION_TYPE_ALIAS ||
57 kind == ElementKind.GETTER || 59 kind == ElementKind.GETTER ||
58 kind == ElementKind.SETTER) { 60 kind == ElementKind.SETTER) {
59 return _searchReferences(element); 61 return _searchReferences(element);
60 } else if (kind == ElementKind.FIELD || 62 } else if (kind == ElementKind.FIELD ||
61 kind == ElementKind.TOP_LEVEL_VARIABLE) { 63 kind == ElementKind.TOP_LEVEL_VARIABLE) {
62 return _searchReferences_Field(element as PropertyInducingElement); 64 return _searchReferences_Field(element as PropertyInducingElement);
63 } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) { 65 } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
66 if (element.enclosingElement is ExecutableElement) {
67 return _searchReferences_Local(element, (n) => n is Block);
68 }
64 return _searchReferences_Function(element); 69 return _searchReferences_Function(element);
65 } else if (kind == ElementKind.IMPORT) { 70 } else if (kind == ElementKind.IMPORT) {
71 // TODO(scheglov) implement whole library search
66 return _searchReferences(element); 72 return _searchReferences(element);
67 } else if (kind == ElementKind.LABEL) { 73 } else if (kind == ElementKind.LABEL ||
74 kind == ElementKind.LOCAL_VARIABLE) {
75 return _searchReferences_Local(element, (n) => n is Block);
76 } else if (kind == ElementKind.LIBRARY) {
77 // TODO(scheglov) implement whole library search
68 return _searchReferences(element); 78 return _searchReferences(element);
69 } else if (kind == ElementKind.LIBRARY) {
70 return _searchReferences(element);
71 } else if (kind == ElementKind.LOCAL_VARIABLE) {
72 return _searchReferences_LocalVariable(element as LocalVariableElement);
73 } else if (kind == ElementKind.PARAMETER) { 79 } else if (kind == ElementKind.PARAMETER) {
74 return _searchReferences_Parameter(element as ParameterElement); 80 return _searchReferences_Parameter(element);
75 } else if (kind == ElementKind.PREFIX) { 81 } else if (kind == ElementKind.PREFIX) {
82 // TODO(scheglov) implement whole library search
76 return _searchReferences(element); 83 return _searchReferences(element);
77 } else if (kind == ElementKind.TYPE_PARAMETER) { 84 } else if (kind == ElementKind.TYPE_PARAMETER) {
78 return _searchReferences_TypeParameter(element); 85 return _searchReferences_Local(element, (n) => n is ClassDeclaration);
79 } 86 }
80 return new Future.value(<SearchMatch>[]); 87 return new Future.value(<SearchMatch>[]);
81 } 88 }
82 89
83 @override 90 @override
84 Future<List<SearchMatch>> searchSubtypes(ClassElement type) { 91 Future<List<SearchMatch>> searchSubtypes(ClassElement type) {
85 // TODO: implement searchSubtypes 92 // TODO: implement searchSubtypes
86 throw new UnimplementedError(); 93 throw new UnimplementedError();
87 } 94 }
88 95
89 @override 96 @override
90 Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) { 97 Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) {
91 // TODO: implement searchTopLevelDeclarations 98 // TODO: implement searchTopLevelDeclarations
92 throw new UnimplementedError(); 99 throw new UnimplementedError();
93 } 100 }
94 101
95 Future<List<SearchMatch>> _searchReferences(Element element) { 102 _addMatches(List<SearchMatch> matches, Element element,
96 _Requestor requestor = new _Requestor(context, _index); 103 IndexRelationKind relationKind, MatchKind kind) async {
97 requestor.addElement( 104 List<Location> locations = await _index.getRelations(element, relationKind);
98 element, IndexRelationKind.IS_REFERENCED_BY, MatchKind.REFERENCE); 105 for (Location location in locations) {
99 return requestor.merge(); 106 matches.add(new SearchMatch(
107 context,
108 location.libraryUri,
109 location.unitUri,
110 kind,
111 new SourceRange(location.offset, location.length),
112 true,
113 location.isQualified));
114 }
115 }
116
117 Future<List<SearchMatch>> _searchReferences(Element element) async {
118 List<SearchMatch> matches = <SearchMatch>[];
119 await _addMatches(matches, element, IndexRelationKind.IS_REFERENCED_BY,
120 MatchKind.REFERENCE);
121 return matches;
100 } 122 }
101 123
102 Future<List<SearchMatch>> _searchReferences_Field( 124 Future<List<SearchMatch>> _searchReferences_Field(
103 PropertyInducingElement field) { 125 PropertyInducingElement field) async {
126 List<SearchMatch> matches = <SearchMatch>[];
104 PropertyAccessorElement getter = field.getter; 127 PropertyAccessorElement getter = field.getter;
105 PropertyAccessorElement setter = field.setter; 128 PropertyAccessorElement setter = field.setter;
106 _Requestor requestor = new _Requestor(context, _index);
107 // field itself 129 // field itself
108 requestor.addElement( 130 await _addMatches(matches, field, IndexRelationKind.IS_REFERENCED_BY,
109 field, IndexRelationKind.IS_REFERENCED_BY, MatchKind.REFERENCE); 131 MatchKind.REFERENCE);
110 // getter 132 // getter
111 if (getter != null) { 133 if (getter != null) {
112 requestor.addElement( 134 await _addMatches(
113 getter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.READ); 135 matches, getter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.READ);
114 requestor.addElement( 136 await _addMatches(matches, getter, IndexRelationKind.IS_INVOKED_BY,
115 getter, IndexRelationKind.IS_INVOKED_BY, MatchKind.INVOCATION); 137 MatchKind.INVOCATION);
116 } 138 }
117 // setter 139 // setter
118 if (setter != null) { 140 if (setter != null) {
119 requestor.addElement( 141 await _addMatches(
120 setter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.WRITE); 142 matches, setter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.WRITE);
121 } 143 }
122 // done 144 // done
123 return requestor.merge(); 145 return matches;
124 } 146 }
125 147
126 Future<List<SearchMatch>> _searchReferences_Function(Element element) { 148 Future<List<SearchMatch>> _searchReferences_Function(Element element) async {
127 if (element is Member) { 149 if (element is Member) {
128 element = (element as Member).baseElement; 150 element = (element as Member).baseElement;
129 } 151 }
130 _Requestor requestor = new _Requestor(context, _index); 152 List<SearchMatch> matches = <SearchMatch>[];
131 requestor.addElement( 153 await _addMatches(matches, element, IndexRelationKind.IS_REFERENCED_BY,
132 element, IndexRelationKind.IS_REFERENCED_BY, MatchKind.REFERENCE); 154 MatchKind.REFERENCE);
133 requestor.addElement( 155 await _addMatches(matches, element, IndexRelationKind.IS_INVOKED_BY,
134 element, IndexRelationKind.IS_INVOKED_BY, MatchKind.INVOCATION); 156 MatchKind.INVOCATION);
135 return requestor.merge(); 157 return matches;
136 } 158 }
137 159
138 Future<List<SearchMatch>> _searchReferences_LocalVariable( 160 Future<List<SearchMatch>> _searchReferences_Local(
139 LocalVariableElement variable) { 161 Element element, bool isRootNode(AstNode n)) async {
140 // TODO(scheglov) implement using AST visitor 162 AstNode node = element.computeNode();
141 throw new UnimplementedError(); 163 AstNode enclosingNode = node.getAncestor(isRootNode);
142 // _Requestor requestor = new _Requestor(context, _index); 164 _LocalReferencesVisitor visitor = new _LocalReferencesVisitor(element);
143 // requestor.addElement(variable, IndexRelationKind.IS_READ_BY, MatchKind.REA D); 165 enclosingNode.accept(visitor);
144 // requestor.addElement( 166 return visitor.matches;
145 // variable, IndexRelationKind.IS_READ_WRITTEN_BY, MatchKind.READ_WRITE);
146 // requestor.addElement(
147 // variable, IndexRelationKind.IS_WRITTEN_BY, MatchKind.WRITE);
148 // requestor.addElement(
149 // variable, IndexRelationKind.IS_INVOKED_BY, MatchKind.INVOCATION);
150 // return requestor.merge();
151 } 167 }
152 168
153 Future<List<SearchMatch>> _searchReferences_Parameter( 169 Future<List<SearchMatch>> _searchReferences_Parameter(
154 ParameterElement parameter) { 170 ParameterElement parameter) async {
155 // TODO(scheglov) implement using AST visitor 171 List<SearchMatch> matches = <SearchMatch>[];
156 throw new UnimplementedError(); 172 matches.addAll(await _searchReferences(parameter));
157 // _Requestor requestor = new _Requestor(context, _index); 173 matches.addAll(await _searchReferences_Local(
158 // requestor.addElement(parameter, IndexRelationKind.IS_READ_BY, MatchKind.RE AD); 174 parameter, (n) => n is MethodDeclaration || n is FunctionExpression));
159 // requestor.addElement( 175 return matches;
160 // parameter, IndexRelationKind.IS_READ_WRITTEN_BY, MatchKind.READ_WRITE) ;
161 // requestor.addElement(
162 // parameter, IndexRelationKind.IS_WRITTEN_BY, MatchKind.WRITE);
163 // requestor.addElement(
164 // parameter, IndexRelationKind.IS_REFERENCED_BY, MatchKind.REFERENCE);
165 // requestor.addElement(
166 // parameter, IndexRelationKind.IS_INVOKED_BY, MatchKind.INVOCATION);
167 // return requestor.merge();
168 }
169
170 Future<List<SearchMatch>> _searchReferences_TypeParameter(
171 ParameterElement parameter) {
172 // TODO(scheglov) implement using AST visitor
173 throw new UnimplementedError();
174 } 176 }
175 } 177 }
176 178
177 class _Requestor { 179 /**
180 * Visitor that adds [SearchMatch]es for local elements - labels, local
181 * functions, local variables and parameters.
182 */
183 class _LocalReferencesVisitor extends RecursiveAstVisitor {
184 final List<SearchMatch> matches = <SearchMatch>[];
185
186 final Element element;
178 final AnalysisContext context; 187 final AnalysisContext context;
179 final Index2 index; 188 final String libraryUri;
180 final List<Future<List<SearchMatch>>> futures = <Future<List<SearchMatch>>>[]; 189 final String unitUri;
181 190
182 _Requestor(this.context, this.index); 191 _LocalReferencesVisitor(Element element)
192 : element = element,
193 context = element.context,
194 libraryUri = element.library.source.uri.toString(),
195 unitUri = element.source.uri.toString();
183 196
184 void addElement( 197 @override
185 Element element, IndexRelationKind relationKind, MatchKind kind) { 198 visitSimpleIdentifier(SimpleIdentifier node) {
186 Future relationsFuture = index.getRelations(element, relationKind); 199 if (node.inDeclarationContext()) {
187 Future matchesFuture = relationsFuture.then((List<Location> locations) { 200 return;
188 List<SearchMatch> matches = <SearchMatch>[]; 201 }
189 for (Location location in locations) { 202 if (node.bestElement == element) {
190 matches.add(_convertLocation(location, kind)); 203 AstNode parent = node.parent;
204 MatchKind kind = MatchKind.REFERENCE;
205 if (element is FunctionElement) {
206 if (parent is MethodInvocation && parent.methodName == node) {
207 kind = MatchKind.INVOCATION;
208 }
209 } else if (element is VariableElement) {
210 bool isGet = node.inGetterContext();
211 bool isSet = node.inSetterContext();
212 if (isGet && isSet) {
213 kind = MatchKind.READ_WRITE;
214 } else if (isGet) {
215 if (parent is MethodInvocation && parent.methodName == node) {
216 kind = MatchKind.INVOCATION;
217 } else {
218 kind = MatchKind.READ;
219 }
220 } else if (isSet) {
221 kind = MatchKind.WRITE;
222 }
191 } 223 }
192 return matches; 224 _addMatch(node, kind);
193 }); 225 }
194 futures.add(matchesFuture);
195 } 226 }
196 227
197 // void addElement( 228 void _addMatch(SimpleIdentifier node, MatchKind kind) {
198 // Element element, RelationshipImpl relationship, MatchKind kind) { 229 matches.add(new SearchMatch(context, libraryUri, unitUri, kind,
199 // IndexableElement indexable = new IndexableElement(element); 230 new SourceRange(node.offset, node.length), true, node.isQualified));
200 // add(indexable, relationship, kind);
201 // }
202
203 Future<List<SearchMatch>> merge() {
204 return Future.wait(futures).then((List<List<SearchMatch>> matchesList) {
205 return matchesList.expand((matches) => matches).toList();
206 });
207 }
208
209 SearchMatch _convertLocation(Location location, MatchKind kind) {
210 return new SearchMatch(
211 context,
212 location.libraryUri,
213 location.unitUri,
214 kind,
215 new SourceRange(location.offset, location.length),
216 true,
217 location.isQualified);
218 } 231 }
219 } 232 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/search/search_engine2_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698