Index: pkg/analyzer/lib/src/task/strong_mode.dart |
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart |
index 823319893f36c3e1831fe4786ed144c8a8f823e0..728a45fe16efc6494dda2ca9cab85cd44c24cb18 100644 |
--- a/pkg/analyzer/lib/src/task/strong_mode.dart |
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart |
@@ -8,10 +8,71 @@ import 'dart:collection'; |
import 'package:analyzer/src/generated/ast.dart'; |
import 'package:analyzer/src/generated/element.dart'; |
+import 'package:analyzer/src/generated/engine.dart'; |
+import 'package:analyzer/src/generated/java_engine.dart'; |
import 'package:analyzer/src/generated/resolver.dart'; |
import 'package:analyzer/src/generated/utilities_dart.dart'; |
/** |
+ * A function that returns `true` if the given [variable] passes the filter. |
+ */ |
+typedef bool VariableFilter(VariableElement element); |
+ |
+/** |
+ * A visitor that will locate the declaration of a specific variable within an |
+ * AST structure. |
+ */ |
+class DeclarationFinder extends RecursiveAstVisitor { |
Paul Berry
2015/08/27 18:56:07
I'm concerned about the execution speed of this cl
Brian Wilkerson
2015/08/27 20:43:54
Because I didn't think of it. You're right, it wou
|
+ /** |
+ * The element representing the variable whose declaration is to be found. |
+ */ |
+ final VariableElement targetElement; |
+ |
+ /** |
+ * The declaration of the variable, or `null` if the AST structure did not |
+ * contain a declaration of the variable. |
+ */ |
+ VariableDeclaration declaration = null; |
+ |
+ /** |
+ * Initialize a newly created finder to search for the given [targetElement]. |
+ */ |
+ DeclarationFinder(this.targetElement); |
+ |
+ @override |
+ void visitVariableDeclaration(VariableDeclaration node) { |
+ if (node.name.staticElement == targetElement) { |
+ declaration = node; |
+ } |
Paul Berry
2015/08/27 18:56:07
Were you intending to add:
throw new DeclarationF
Brian Wilkerson
2015/08/27 20:43:54
moot
|
+ } |
+ |
+ /** |
+ * Search inside the given AST [node] for the declaration of the variable with |
+ * the given [element]. |
+ */ |
+ static VariableDeclaration find(AstNode node, VariableElement element) { |
Paul Berry
2015/08/27 18:56:08
I'm not comfortable with the way this function is
Brian Wilkerson
2015/08/27 20:43:54
moot
|
+ DeclarationFinder finder = new DeclarationFinder(element); |
+ try { |
+ node.accept(finder); |
+ } on DeclarationFoundException { |
+ // A declaration of the element was found |
+ } catch (exception, stackTrace) { |
+ AnalysisEngine.instance.logger.logInformation( |
+ "Unable to locate declaration of $element", |
+ new CaughtException(exception, stackTrace)); |
+ return null; |
+ } |
+ return finder.declaration; |
+ } |
+} |
+ |
+/** |
+ * An exception used by a [DeclarationFinder] to cancel visiting after a |
+ * declaration has been found. |
+ */ |
+class DeclarationFoundException extends Error {} |
+ |
+/** |
* An object used to find static variables whose types should be inferred and |
* classes whose members should have types inferred. Clients are expected to |
* visit a [CompilationUnit]. |
@@ -79,7 +140,10 @@ class InferrenceFinder extends SimpleAstVisitor { |
void _addVariables(NodeList<VariableDeclaration> variables) { |
for (VariableDeclaration variable in variables) { |
if (variable.initializer != null) { |
- staticVariables.add(variable.element); |
+ VariableElement element = variable.element; |
+ if (element.hasImplicitType) { |
+ staticVariables.add(element); |
+ } |
} |
} |
} |
@@ -529,6 +593,43 @@ class InstanceMemberInferrer { |
} |
/** |
+ * A visitor that will gather all of the variables referenced within a given |
+ * AST structure. The collection can be restricted to contain only those |
+ * variables that pass a specified filter. |
+ */ |
+class VariableGatherer extends RecursiveAstVisitor { |
+ /** |
+ * The filter used to limit which variables are gathered, or `null` if no |
+ * filtering is to be performed. |
+ */ |
+ final VariableFilter filter; |
+ |
+ /** |
+ * The variables that were found. |
+ */ |
+ final Set<VariableElement> results = new HashSet<VariableElement>(); |
+ |
+ /** |
+ * Initialize a newly created gatherer to gather all of the variables that |
+ * pass the given [filter] (or all variables if no filter is provided). |
+ */ |
+ VariableGatherer([this.filter = null]); |
+ |
+ @override |
+ void visitSimpleIdentifier(SimpleIdentifier node) { |
+ if (!node.inDeclarationContext()) { |
+ Element element = node.staticElement; |
+ if (element is PropertyAccessorElement && element.isSynthetic) { |
+ element = (element as PropertyAccessorElement).variable; |
+ } |
+ if (element is VariableElement && (filter == null || filter(element))) { |
+ results.add(element); |
+ } |
+ } |
+ } |
+} |
+ |
+/** |
* A class of exception that is not used anywhere else. |
*/ |
class _CycleException implements Exception {} |