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

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

Issue 725473005: During resolution, record the target of break/continue statements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/element_resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 7de60e9568d09b689e995dd3e6ffdf1f52e964c6..2931a41d3065b4765ca738bd390ff347bb23f58e 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -176,7 +176,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
@override
Object visitBreakStatement(BreakStatement node) {
- _lookupLabel(node, node.label);
+ node.target = _lookupBreakOrContinueTarget(node, node.label, false);
return null;
}
@@ -367,7 +367,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
@override
Object visitContinueStatement(ContinueStatement node) {
- _lookupLabel(node, node.label);
+ node.target = _lookupBreakOrContinueTarget(node, node.label, true);
return null;
}
@@ -802,42 +802,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
@override
- Object visitPrefixExpression(PrefixExpression node) {
- sc.Token operator = node.operator;
- sc.TokenType operatorType = operator.type;
- if (operatorType.isUserDefinableOperator ||
- operatorType == sc.TokenType.PLUS_PLUS ||
- operatorType == sc.TokenType.MINUS_MINUS) {
- Expression operand = node.operand;
- String methodName = _getPrefixOperator(node);
- DartType staticType = _getStaticType(operand);
- MethodElement staticMethod =
- _lookUpMethod(operand, staticType, methodName);
- node.staticElement = staticMethod;
- DartType propagatedType = _getPropagatedType(operand);
- MethodElement propagatedMethod =
- _lookUpMethod(operand, propagatedType, methodName);
- node.propagatedElement = propagatedMethod;
- if (_shouldReportMissingMember(staticType, staticMethod)) {
- _recordUndefinedToken(
- staticType.element,
- StaticTypeWarningCode.UNDEFINED_OPERATOR,
- operator,
- [methodName, staticType.displayName]);
- } else if (_enableHints &&
- _shouldReportMissingMember(propagatedType, propagatedMethod) &&
- !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
- _recordUndefinedToken(
- propagatedType.element,
- HintCode.UNDEFINED_OPERATOR,
- operator,
- [methodName, propagatedType.displayName]);
- }
- }
- return null;
- }
-
- @override
Object visitPrefixedIdentifier(PrefixedIdentifier node) {
SimpleIdentifier prefix = node.prefix;
SimpleIdentifier identifier = node.identifier;
@@ -916,6 +880,42 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
@override
+ Object visitPrefixExpression(PrefixExpression node) {
+ sc.Token operator = node.operator;
+ sc.TokenType operatorType = operator.type;
+ if (operatorType.isUserDefinableOperator ||
+ operatorType == sc.TokenType.PLUS_PLUS ||
+ operatorType == sc.TokenType.MINUS_MINUS) {
+ Expression operand = node.operand;
+ String methodName = _getPrefixOperator(node);
+ DartType staticType = _getStaticType(operand);
+ MethodElement staticMethod =
+ _lookUpMethod(operand, staticType, methodName);
+ node.staticElement = staticMethod;
+ DartType propagatedType = _getPropagatedType(operand);
+ MethodElement propagatedMethod =
+ _lookUpMethod(operand, propagatedType, methodName);
+ node.propagatedElement = propagatedMethod;
+ if (_shouldReportMissingMember(staticType, staticMethod)) {
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ operator,
+ [methodName, staticType.displayName]);
+ } else if (_enableHints &&
+ _shouldReportMissingMember(propagatedType, propagatedMethod) &&
+ !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
+ _recordUndefinedToken(
+ propagatedType.element,
+ HintCode.UNDEFINED_OPERATOR,
+ operator,
+ [methodName, propagatedType.displayName]);
+ }
+ }
+ return null;
+ }
+
+ @override
Object visitPropertyAccess(PropertyAccess node) {
Expression target = node.realTarget;
if (target is SuperExpression && !_isSuperInValidContext(target)) {
@@ -1574,6 +1574,52 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
/**
+ * Return the target of a break or continue statement, and update the static
+ * element of its label (if any). [parentNode] is the AST node of the break
+ * or continue statement, [labelNode] is the label contained in that
+ * statement (if any), and [isContinue] is true if the node being visited is
+ * a continue statement.
+ */
+ AstNode _lookupBreakOrContinueTarget(AstNode parentNode,
+ SimpleIdentifier labelNode, bool isContinue) {
+ if (labelNode == null) {
+ return _resolver.getUnlabeledBreakOrContinueTarget(isContinue);
+ } else {
+ LabelScope labelScope = _resolver.labelScope;
+ if (labelScope == null) {
+ // There are no labels in scope, so by definition the label is
+ // undefined.
+ _resolver.reportErrorForNode(
+ CompileTimeErrorCode.LABEL_UNDEFINED,
+ labelNode,
+ [labelNode.name]);
+ return null;
+ }
+ LabelScope definingScope = labelScope.lookup(labelNode.name);
+ if (definingScope == null) {
+ // No definition of the given label name could be found in any
+ // enclosing scope.
+ _resolver.reportErrorForNode(
+ CompileTimeErrorCode.LABEL_UNDEFINED,
+ labelNode,
+ [labelNode.name]);
+ return null;
+ }
+ // The target has been found.
+ labelNode.staticElement = definingScope.element;
+ ExecutableElement labelContainer =
+ definingScope.element.getAncestor((element) => element is ExecutableElement);
+ if (!identical(labelContainer, _resolver.enclosingFunction)) {
+ _resolver.reportErrorForNode(
+ CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
+ labelNode,
+ [labelNode.name]);
+ }
+ return definingScope.node;
+ }
+ }
+
+ /**
* Look up the getter with the given name in the given type. Return the element representing the
* getter that was found, or `null` if there is no getter with the given name.
*
@@ -1662,6 +1708,37 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
/**
+ * Look up the method or getter with the given name in the given type. Return the element
+ * representing the method or getter that was found, or `null` if there is no method or
+ * getter with the given name.
+ *
+ * @param type the type in which the method or getter is defined
+ * @param memberName the name of the method or getter being looked up
+ * @return the element representing the method or getter that was found
+ */
+ ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) {
+ type = _resolveTypeParameter(type);
+ if (type is InterfaceType) {
+ InterfaceType interfaceType = type;
+ ExecutableElement member =
+ interfaceType.lookUpMethod(memberName, _definingLibrary);
+ if (member != null) {
+ return member;
+ }
+ member = interfaceType.lookUpGetter(memberName, _definingLibrary);
+ if (member != null) {
+ return member;
+ }
+ return _lookUpGetterOrMethodInInterfaces(
+ interfaceType,
+ false,
+ memberName,
+ new HashSet<ClassElement>());
+ }
+ return null;
+ }
+
+ /**
* Look up the method or getter with the given name in the interfaces implemented by the given
* type, either directly or indirectly. Return the element representing the method or getter that
* was found, or `null` if there is no method or getter with the given name.
@@ -1822,6 +1899,39 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
/**
+ * Look up all methods of a given name defined on a union type.
+ *
+ * @param target
+ * @param type
+ * @param methodName
+ * @return all methods named `methodName` defined on the union type `type`.
+ */
+ Set<ExecutableElement> _lookupMethods(Expression target, UnionType type,
+ String methodName) {
+ Set<ExecutableElement> methods = new HashSet<ExecutableElement>();
+ bool allElementsHaveMethod = true;
+ for (DartType t in type.elements) {
+ MethodElement m = _lookUpMethod(target, t, methodName);
+ if (m != null) {
+ methods.add(m);
+ } else {
+ allElementsHaveMethod = false;
+ }
+ }
+ // For strict union types we require that all types in the union define the
+ // method.
+ if (AnalysisEngine.instance.strictUnionTypes) {
+ if (allElementsHaveMethod) {
+ return methods;
+ } else {
+ return new Set<ExecutableElement>();
+ }
+ } else {
+ return methods;
+ }
+ }
+
+ /**
* Look up the setter with the given name in the given type. Return the element representing the
* setter that was found, or `null` if there is no setter with the given name.
*
@@ -1910,132 +2020,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
/**
- * Look up the method or getter with the given name in the given type. Return the element
- * representing the method or getter that was found, or `null` if there is no method or
- * getter with the given name.
- *
- * @param type the type in which the method or getter is defined
- * @param memberName the name of the method or getter being looked up
- * @return the element representing the method or getter that was found
- */
- ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) {
- type = _resolveTypeParameter(type);
- if (type is InterfaceType) {
- InterfaceType interfaceType = type;
- ExecutableElement member =
- interfaceType.lookUpMethod(memberName, _definingLibrary);
- if (member != null) {
- return member;
- }
- member = interfaceType.lookUpGetter(memberName, _definingLibrary);
- if (member != null) {
- return member;
- }
- return _lookUpGetterOrMethodInInterfaces(
- interfaceType,
- false,
- memberName,
- new HashSet<ClassElement>());
- }
- return null;
- }
-
- /**
- * Find the element corresponding to the given label node in the current label scope.
- *
- * @param parentNode the node containing the given label
- * @param labelNode the node representing the label being looked up
- * @return the element corresponding to the given label node in the current scope
- */
- LabelElementImpl _lookupLabel(AstNode parentNode,
- SimpleIdentifier labelNode) {
- LabelScope labelScope = _resolver.labelScope;
- LabelElementImpl labelElement = null;
- if (labelNode == null) {
- if (labelScope == null) {
- // TODO(brianwilkerson) Do we need to report this error, or is this
- // condition always caught in the parser?
- // reportError(ResolverErrorCode.BREAK_OUTSIDE_LOOP);
- } else {
- labelElement =
- labelScope.lookup(LabelScope.EMPTY_LABEL) as LabelElementImpl;
- if (labelElement == null) {
- // TODO(brianwilkerson) Do we need to report this error, or is this
- // condition always caught in the parser?
- // reportError(ResolverErrorCode.BREAK_OUTSIDE_LOOP);
- }
- //
- // The label element that was returned was a marker for look-up and
- // isn't stored in the element model.
- //
- labelElement = null;
- }
- } else {
- if (labelScope == null) {
- _resolver.reportErrorForNode(
- CompileTimeErrorCode.LABEL_UNDEFINED,
- labelNode,
- [labelNode.name]);
- } else {
- labelElement = labelScope.lookup(labelNode.name) as LabelElementImpl;
- if (labelElement == null) {
- _resolver.reportErrorForNode(
- CompileTimeErrorCode.LABEL_UNDEFINED,
- labelNode,
- [labelNode.name]);
- } else {
- labelNode.staticElement = labelElement;
- }
- }
- }
- if (labelElement != null) {
- ExecutableElement labelContainer =
- labelElement.getAncestor((element) => element is ExecutableElement);
- if (!identical(labelContainer, _resolver.enclosingFunction)) {
- _resolver.reportErrorForNode(
- CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
- labelNode,
- [labelNode.name]);
- labelElement = null;
- }
- }
- return labelElement;
- }
-
- /**
- * Look up all methods of a given name defined on a union type.
- *
- * @param target
- * @param type
- * @param methodName
- * @return all methods named `methodName` defined on the union type `type`.
- */
- Set<ExecutableElement> _lookupMethods(Expression target, UnionType type,
- String methodName) {
- Set<ExecutableElement> methods = new HashSet<ExecutableElement>();
- bool allElementsHaveMethod = true;
- for (DartType t in type.elements) {
- MethodElement m = _lookUpMethod(target, t, methodName);
- if (m != null) {
- methods.add(m);
- } else {
- allElementsHaveMethod = false;
- }
- }
- // For strict union types we require that all types in the union define the
- // method.
- if (AnalysisEngine.instance.strictUnionTypes) {
- if (allElementsHaveMethod) {
- return methods;
- } else {
- return new Set<ExecutableElement>();
- }
- } else {
- return methods;
- }
- }
-
- /**
* Given some class element, this method uses [subtypeManager] to find the set of all
* subtypes; the subtypes are then searched for a member (method, getter, or setter), that matches
* a passed

Powered by Google App Engine
This is Rietveld 408576698