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

Unified Diff: pkg/analyzer/lib/src/generated/error_verifier.dart

Issue 2306223002: Move more error detection out of Scope (Closed)
Patch Set: clean-up Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/error_verifier.dart
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index abf47ca9ce73580466b2de0f6a13854fe26e50e1..80d001c3721bc3ec6702ccf4d5bf4a6b6e4fa36a 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -276,6 +276,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
new HashSet<String>();
/**
+ * The elements that will be defined later in the current scope, but right
+ * now are not declared.
+ */
+ HiddenElements _hiddenElements = null;
+
+ /**
* A list of types used by the [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]
* and [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS] error codes.
*/
@@ -388,8 +394,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitBlock(Block node) {
- _checkDuplicateDeclarationInStatements(node.statements);
- return super.visitBlock(node);
+ _hiddenElements = new HiddenElements(_hiddenElements, node);
+ try {
+ _checkDuplicateDeclarationInStatements(node.statements);
+ return super.visitBlock(node);
+ } finally {
+ _hiddenElements = _hiddenElements.outerElements;
+ }
}
@override
@@ -747,6 +758,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitFunctionDeclaration(FunctionDeclaration node) {
+ ExecutableElement functionElement = node.element;
+ if (functionElement != null &&
+ functionElement.enclosingElement is! CompilationUnitElement) {
+ _hiddenElements.declare(functionElement);
+ }
ExecutableElement outerFunction = _enclosingFunction;
try {
SimpleIdentifier identifier = node.name;
@@ -754,7 +770,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (identifier != null) {
methodName = identifier.name;
}
- _enclosingFunction = node.element;
+ _enclosingFunction = functionElement;
TypeName returnType = node.returnType;
if (node.isSetter || node.isGetter) {
_checkForMismatchedAccessorTypes(node, methodName);
@@ -1111,6 +1127,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitSimpleIdentifier(SimpleIdentifier node) {
+ _checkForReferenceBeforeDeclaration(node);
_checkForImplicitThisReferenceInInitializer(node);
if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) {
_checkForUnqualifiedReferenceToNonLocalStaticMember(node);
@@ -1220,6 +1237,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_isInInstanceVariableInitializer = wasInInstanceVariableInitializer;
_namesForReferenceToDeclaredVariableInInitializer.remove(name);
}
+ // declare the variable
+ AstNode grandparent = node.parent.parent;
+ if (grandparent is! TopLevelVariableDeclaration &&
+ grandparent is! FieldDeclaration) {
+ VariableElement element = node.element;
+ if (element != null) {
+ _hiddenElements.declare(element);
+ }
+ }
// done
return null;
}
@@ -5420,6 +5446,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
redirectedConstructorNode);
}
+ void _checkForReferenceBeforeDeclaration(SimpleIdentifier node) {
+ if (!node.inDeclarationContext() &&
+ _hiddenElements != null &&
+ _hiddenElements.contains(node.staticElement)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
+ node,
+ [node.name]);
+ }
+ }
+
/**
* Check that the given rethrow [expression] is inside of a catch clause.
*
@@ -6609,6 +6646,63 @@ class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference
}
/**
+ * A record of the elements that will be declared in some scope (block), but are
+ * not yet declared.
+ */
+class HiddenElements {
+ /**
+ * The elements hidden in outer scopes, or `null` if this is the outermost
+ * scope.
+ */
+ final HiddenElements outerElements;
+
+ /**
+ * A set containing the elements that will be declared in this scope, but are
+ * not yet declared.
+ */
+ Set<Element> _elements = new HashSet<Element>();
+
+ /**
+ * Initialize a newly created set of hidden elements to include all of the
+ * elements defined in the set of [outerElements] and all of the elements
+ * declared in the given [block].
+ */
+ HiddenElements(this.outerElements, Block block) {
+ _initializeElements(block);
+ }
+
+ /**
+ * Return `true` if this set of elements contains the given [element].
+ */
+ bool contains(Element element) {
+ if (_elements.contains(element)) {
+ return true;
+ } else if (outerElements != null) {
+ return outerElements.contains(element);
+ }
+ return false;
+ }
+
+ /**
+ * Record that the given [element] has been declared, so it is no longer
+ * hidden.
+ */
+ void declare(Element element) {
+ _elements.remove(element);
+ }
+
+ /**
+ * Initialize the list of elements that are not yet declared to be all of the
+ * elements declared somewhere in the given [block].
+ */
+ void _initializeElements(Block block) {
+ for (var element in BlockScope.elementsInBlock(block)) {
+ _elements.add(element);
+ }
scheglov 2016/09/02 23:46:50 I think here it also could be written more concise
Brian Wilkerson 2016/09/03 17:12:37 I went with "_elements.addAll(BlockScope.elementsI
+ }
+}
+
+/**
* A class used to compute a list of the constants whose value needs to be
* computed before errors can be computed by the [VerifyUnitTask].
*/

Powered by Google App Engine
This is Rietveld 408576698