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

Side by Side Diff: pkg/analyzer/lib/src/dart/element/element.dart

Issue 2469643003: Fix lookup of members (issue 27723) (Closed)
Patch Set: Created 4 years, 1 month 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/analyzer/test/generated/non_error_resolver_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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 analyzer.src.dart.element.element; 5 library analyzer.src.dart.element.element;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' show min; 8 import 'dart:math' show min;
9 9
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 if (accessor.isSetter && accessor.name == setterName) { 184 if (accessor.isSetter && accessor.name == setterName) {
185 return accessor; 185 return accessor;
186 } 186 }
187 } 187 }
188 return null; 188 return null;
189 } 189 }
190 190
191 @override 191 @override
192 MethodElement lookUpConcreteMethod( 192 MethodElement lookUpConcreteMethod(
193 String methodName, LibraryElement library) => 193 String methodName, LibraryElement library) =>
194 _internalLookUpConcreteMethod( 194 _first(_implementationsOfMethod(methodName).where(
195 methodName, library, true, new HashSet<ClassElement>()); 195 (MethodElement method) =>
196 !method.isAbstract && method.isAccessibleIn(library)));
196 197
197 @override 198 @override
198 PropertyAccessorElement lookUpGetter( 199 PropertyAccessorElement lookUpGetter(
199 String getterName, LibraryElement library) => 200 String getterName, LibraryElement library) =>
200 _internalLookUpGetter(getterName, library, true); 201 _first(_implementationsOfGetter(getterName).where(
202 (PropertyAccessorElement getter) => getter.isAccessibleIn(library)));
201 203
202 @override 204 @override
203 PropertyAccessorElement lookUpInheritedConcreteGetter( 205 PropertyAccessorElement lookUpInheritedConcreteGetter(
204 String getterName, LibraryElement library) => 206 String getterName, LibraryElement library) =>
205 _internalLookUpConcreteGetter(getterName, library, false); 207 _first(_implementationsOfGetter(getterName).where(
208 (PropertyAccessorElement getter) =>
209 !getter.isAbstract &&
210 getter.isAccessibleIn(library) &&
211 getter.enclosingElement != this));
206 212
207 @override 213 @override
208 MethodElement lookUpInheritedConcreteMethod( 214 MethodElement lookUpInheritedConcreteMethod(
209 String methodName, LibraryElement library) => 215 String methodName, LibraryElement library) =>
210 _internalLookUpConcreteMethod( 216 _first(_implementationsOfMethod(methodName).where(
211 methodName, library, false, new HashSet<ClassElement>()); 217 (MethodElement method) =>
218 !method.isAbstract &&
219 method.isAccessibleIn(library) &&
220 method.enclosingElement != this));
212 221
213 @override 222 @override
214 PropertyAccessorElement lookUpInheritedConcreteSetter( 223 PropertyAccessorElement lookUpInheritedConcreteSetter(
215 String setterName, LibraryElement library) => 224 String setterName, LibraryElement library) =>
216 _internalLookUpConcreteSetter(setterName, library, false); 225 _first(_implementationsOfSetter(setterName).where(
226 (PropertyAccessorElement setter) =>
227 !setter.isAbstract &&
228 setter.isAccessibleIn(library) &&
229 setter.enclosingElement != this));
217 230
218 @override 231 @override
219 MethodElement lookUpInheritedMethod( 232 MethodElement lookUpInheritedMethod(
220 String methodName, LibraryElement library) => 233 String methodName, LibraryElement library) =>
221 _internalLookUpMethod( 234 _first(_implementationsOfMethod(methodName).where(
222 methodName, library, false, new HashSet<ClassElement>()); 235 (MethodElement method) =>
236 method.isAccessibleIn(library) &&
237 method.enclosingElement != this));
223 238
224 @override 239 @override
225 MethodElement lookUpMethod(String methodName, LibraryElement library) => 240 MethodElement lookUpMethod(String methodName, LibraryElement library) =>
226 _internalLookUpMethod( 241 _first(_implementationsOfMethod(methodName)
227 methodName, library, true, new HashSet<ClassElement>()); 242 .where((MethodElement method) => method.isAccessibleIn(library)));
228 243
229 @override 244 @override
230 PropertyAccessorElement lookUpSetter( 245 PropertyAccessorElement lookUpSetter(
231 String setterName, LibraryElement library) => 246 String setterName, LibraryElement library) =>
232 _internalLookUpSetter(setterName, library, true); 247 _first(_implementationsOfSetter(setterName).where(
248 (PropertyAccessorElement setter) => setter.isAccessibleIn(library)));
233 249
234 @override 250 @override
235 void visitChildren(ElementVisitor visitor) { 251 void visitChildren(ElementVisitor visitor) {
236 super.visitChildren(visitor); 252 super.visitChildren(visitor);
237 safelyVisitChildren(accessors, visitor); 253 safelyVisitChildren(accessors, visitor);
238 safelyVisitChildren(fields, visitor); 254 safelyVisitChildren(fields, visitor);
239 } 255 }
240 256
241 PropertyAccessorElement _internalLookUpConcreteGetter( 257 /**
242 String getterName, LibraryElement library, bool includeThisClass) { 258 * Return the first element from the given [iterable], or `null` if the
243 PropertyAccessorElement getter = 259 * iterable is empty.
244 _internalLookUpGetter(getterName, library, includeThisClass); 260 */
245 while (getter != null && getter.isAbstract) { 261 Object/*=E*/ _first/*<E>*/(Iterable/*<E>*/ iterable) {
246 Element definingClass = getter.enclosingElement; 262 if (iterable.isEmpty) {
247 if (definingClass is! ClassElement) { 263 return null;
248 return null;
249 }
250 getter = getImpl(definingClass)
251 ._internalLookUpGetter(getterName, library, false);
252 } 264 }
253 return getter; 265 return iterable.first;
254 }
255
256 MethodElement _internalLookUpConcreteMethod(
257 String methodName,
258 LibraryElement library,
259 bool includeThisClass,
260 HashSet<ClassElement> visitedClasses) {
261 MethodElement method = _internalLookUpMethod(
262 methodName, library, includeThisClass, visitedClasses);
263 while (method != null && method.isAbstract) {
264 ClassElement definingClass = method.enclosingElement;
265 if (definingClass == null) {
266 return null;
267 }
268 method = getImpl(definingClass)
269 ._internalLookUpMethod(methodName, library, false, visitedClasses);
270 }
271 return method;
272 }
273
274 PropertyAccessorElement _internalLookUpConcreteSetter(
275 String setterName, LibraryElement library, bool includeThisClass) {
276 PropertyAccessorElement setter =
277 _internalLookUpSetter(setterName, library, includeThisClass);
278 while (setter != null && setter.isAbstract) {
279 Element definingClass = setter.enclosingElement;
280 if (definingClass is ClassElementImpl) {
281 setter =
282 definingClass._internalLookUpSetter(setterName, library, false);
283 } else {
284 return null;
285 }
286 }
287 return setter;
288 }
289
290 PropertyAccessorElement _internalLookUpGetter(
291 String getterName, LibraryElement library, bool includeThisClass) {
292 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
293 ClassElement currentElement = this;
294 if (includeThisClass) {
295 PropertyAccessorElement element = currentElement.getGetter(getterName);
296 if (element != null && element.isAccessibleIn(library)) {
297 return element;
298 }
299 }
300 while (currentElement != null && visitedClasses.add(currentElement)) {
301 for (InterfaceType mixin in currentElement.mixins.reversed) {
302 ClassElement mixinElement = mixin.element;
303 if (mixinElement != null) {
304 PropertyAccessorElement element = mixinElement.getGetter(getterName);
305 if (element != null && element.isAccessibleIn(library)) {
306 return element;
307 }
308 }
309 }
310 InterfaceType supertype = currentElement.supertype;
311 if (supertype == null) {
312 return null;
313 }
314 currentElement = supertype.element;
315 PropertyAccessorElement element = currentElement.getGetter(getterName);
316 if (element != null && element.isAccessibleIn(library)) {
317 return element;
318 }
319 }
320 return null;
321 }
322
323 MethodElement _internalLookUpMethod(String methodName, LibraryElement library,
324 bool includeThisClass, HashSet<ClassElement> visitedClasses) {
325 ClassElement currentElement = this;
326 if (includeThisClass) {
327 MethodElement element = currentElement.getMethod(methodName);
328 if (element != null && element.isAccessibleIn(library)) {
329 return element;
330 }
331 }
332 while (currentElement != null && visitedClasses.add(currentElement)) {
333 for (InterfaceType mixin in currentElement.mixins.reversed) {
334 ClassElement mixinElement = mixin.element;
335 if (mixinElement != null) {
336 MethodElement element = mixinElement.getMethod(methodName);
337 if (element != null && element.isAccessibleIn(library)) {
338 return element;
339 }
340 }
341 }
342 InterfaceType supertype = currentElement.supertype;
343 if (supertype == null) {
344 return null;
345 }
346 currentElement = supertype.element;
347 MethodElement element = currentElement.getMethod(methodName);
348 if (element != null && element.isAccessibleIn(library)) {
349 return element;
350 }
351 }
352 return null;
353 }
354
355 PropertyAccessorElement _internalLookUpSetter(
356 String setterName, LibraryElement library, bool includeThisClass) {
357 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
358 ClassElement currentElement = this;
359 if (includeThisClass) {
360 PropertyAccessorElement element = currentElement.getSetter(setterName);
361 if (element != null && element.isAccessibleIn(library)) {
362 return element;
363 }
364 }
365 while (currentElement != null && visitedClasses.add(currentElement)) {
366 for (InterfaceType mixin in currentElement.mixins.reversed) {
367 ClassElement mixinElement = mixin.element;
368 if (mixinElement != null) {
369 PropertyAccessorElement element = mixinElement.getSetter(setterName);
370 if (element != null && element.isAccessibleIn(library)) {
371 return element;
372 }
373 }
374 }
375 InterfaceType supertype = currentElement.supertype;
376 if (supertype == null) {
377 return null;
378 }
379 currentElement = supertype.element;
380 PropertyAccessorElement element = currentElement.getSetter(setterName);
381 if (element != null && element.isAccessibleIn(library)) {
382 return element;
383 }
384 }
385 return null;
386 } 266 }
387 267
388 /** 268 /**
269 * Return an iterable containing all of the implementations of a getter with
270 * the given [getterName] that are defined in this class any any superclass of
271 * this class (but not in interfaces).
272 *
273 * The getters that are returned are not filtered in any way. In particular,
274 * they can include getters that are not visible in some context. Clients must
275 * perform any necessary filtering.
276 *
277 * The getters are returned based on the depth of their defining class; if
278 * this class contains a definition of the getter it will occur first, if
279 * Object contains a definition of the getter it will occur last.
280 */
281 Iterable<PropertyAccessorElement> _implementationsOfGetter(
282 String getterName) sync* {
283 ClassElement classElement = this;
284 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
285 while (classElement != null && visitedClasses.add(classElement)) {
286 PropertyAccessorElement getter = classElement.getGetter(getterName);
287 if (getter != null) {
288 yield getter;
289 }
290 for (InterfaceType mixin in classElement.mixins.reversed) {
291 getter = mixin.element?.getGetter(getterName);
292 if (getter != null) {
293 yield getter;
294 }
295 }
296 classElement = classElement.supertype?.element;
297 }
298 }
299
300 /**
301 * Return an iterable containing all of the implementations of a method with
302 * the given [methodName] that are defined in this class any any superclass of
303 * this class (but not in interfaces).
304 *
305 * The methods that are returned are not filtered in any way. In particular,
306 * they can include methods that are not visible in some context. Clients must
307 * perform any necessary filtering.
308 *
309 * The methods are returned based on the depth of their defining class; if
310 * this class contains a definition of the method it will occur first, if
311 * Object contains a definition of the method it will occur last.
312 */
313 Iterable<MethodElement> _implementationsOfMethod(String methodName) sync* {
314 ClassElement classElement = this;
315 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
316 while (classElement != null && visitedClasses.add(classElement)) {
317 MethodElement method = classElement.getMethod(methodName);
318 if (method != null) {
319 yield method;
320 }
321 for (InterfaceType mixin in classElement.mixins.reversed) {
322 method = mixin.element?.getMethod(methodName);
323 if (method != null) {
324 yield method;
325 }
326 }
327 classElement = classElement.supertype?.element;
328 }
329 }
330
331 /**
332 * Return an iterable containing all of the implementations of a setter with
333 * the given [setterName] that are defined in this class any any superclass of
334 * this class (but not in interfaces).
335 *
336 * The setters that are returned are not filtered in any way. In particular,
337 * they can include setters that are not visible in some context. Clients must
338 * perform any necessary filtering.
339 *
340 * The setters are returned based on the depth of their defining class; if
341 * this class contains a definition of the setter it will occur first, if
342 * Object contains a definition of the setter it will occur last.
343 */
344 Iterable<PropertyAccessorElement> _implementationsOfSetter(
345 String setterName) sync* {
346 ClassElement classElement = this;
347 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
348 while (classElement != null && visitedClasses.add(classElement)) {
349 PropertyAccessorElement setter = classElement.getSetter(setterName);
350 if (setter != null) {
351 yield setter;
352 }
353 for (InterfaceType mixin in classElement.mixins.reversed) {
354 setter = mixin.element?.getSetter(setterName);
355 if (setter != null) {
356 yield setter;
357 }
358 }
359 classElement = classElement.supertype?.element;
360 }
361 }
362
363 /**
389 * Return the [AbstractClassElementImpl] of the given [classElement]. May 364 * Return the [AbstractClassElementImpl] of the given [classElement]. May
390 * throw an exception if the [AbstractClassElementImpl] cannot be provided 365 * throw an exception if the [AbstractClassElementImpl] cannot be provided
391 * (should not happen though). 366 * (should not happen though).
392 */ 367 */
393 static AbstractClassElementImpl getImpl(ClassElement classElement) { 368 static AbstractClassElementImpl getImpl(ClassElement classElement) {
394 if (classElement is ClassElementHandle) { 369 if (classElement is ClassElementHandle) {
395 return getImpl(classElement.actualElement); 370 return getImpl(classElement.actualElement);
396 } 371 }
397 return classElement as AbstractClassElementImpl; 372 return classElement as AbstractClassElementImpl;
398 } 373 }
(...skipping 8080 matching lines...) Expand 10 before | Expand all | Expand 10 after
8479 8454
8480 @override 8455 @override
8481 void visitElement(Element element) { 8456 void visitElement(Element element) {
8482 int offset = element.nameOffset; 8457 int offset = element.nameOffset;
8483 if (offset != -1) { 8458 if (offset != -1) {
8484 map[offset] = element; 8459 map[offset] = element;
8485 } 8460 }
8486 super.visitElement(element); 8461 super.visitElement(element);
8487 } 8462 }
8488 } 8463 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/non_error_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698