| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |