| Index: pkg/analyzer2dart/lib/src/identifier_semantics.dart
|
| diff --git a/pkg/analyzer2dart/lib/src/identifier_semantics.dart b/pkg/analyzer2dart/lib/src/identifier_semantics.dart
|
| index ccfd78f25f58943ea31946ad6f4ccd8a01225275..026e00aef7a9dab3d5ec4b424bb560ebe473c256 100644
|
| --- a/pkg/analyzer2dart/lib/src/identifier_semantics.dart
|
| +++ b/pkg/analyzer2dart/lib/src/identifier_semantics.dart
|
| @@ -69,6 +69,7 @@ class AccessKind {
|
| * Data structure used to classify the semantics of a property access or method
|
| * or function invocation.
|
| */
|
| +// TODO(paulberry,johnniwinther): Support index operations in AccessSemantics.
|
| class AccessSemantics {
|
| /**
|
| * The kind of access.
|
| @@ -199,253 +200,264 @@ class AccessSemantics {
|
| }
|
| }
|
|
|
| -/**
|
| - * Return the semantics for [node].
|
| - */
|
| -AccessSemantics classifyMethodInvocation(MethodInvocation node) {
|
| - Expression target = node.realTarget;
|
| - Element staticElement = node.methodName.staticElement;
|
| - if (target == null) {
|
| - if (staticElement is FunctionElement) {
|
| - if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticMethod(
|
| - node.methodName,
|
| - staticElement,
|
| - null,
|
| - isInvoke: true);
|
| - } else {
|
| - return new AccessSemantics.localFunction(
|
| - node.methodName,
|
| - staticElement,
|
| - isInvoke: true);
|
| - }
|
| - } else if (staticElement is MethodElement && staticElement.isStatic) {
|
| - return new AccessSemantics.staticMethod(
|
| - node.methodName,
|
| - staticElement,
|
| - staticElement.enclosingElement,
|
| - isInvoke: true);
|
| - } else if (staticElement is PropertyAccessorElement) {
|
| - if (staticElement.isSynthetic) {
|
| - if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticField(
|
| - node.methodName,
|
| - staticElement.variable,
|
| - null,
|
| - isInvoke: true);
|
| - } else if (staticElement.isStatic) {
|
| - return new AccessSemantics.staticField(
|
| - node.methodName,
|
| - staticElement.variable,
|
| - staticElement.enclosingElement,
|
| - isInvoke: true);
|
| - }
|
| - } else {
|
| +// TODO(johnniwinther,paulberry): This should be a constant.
|
| +final AccessSemanticsVisitor ACCESS_SEMANTICS_VISITOR =
|
| + new AccessSemanticsVisitor();
|
| +
|
| +// TODO(johnniwinther,paulberry): This should extend a non-recursive visitor.
|
| +class AccessSemanticsVisitor extends RecursiveAstVisitor<AccessSemantics> {
|
| + /**
|
| + * Return the semantics for [node].
|
| + */
|
| + @override
|
| + AccessSemantics visitMethodInvocation(MethodInvocation node) {
|
| + Expression target = node.realTarget;
|
| + Element staticElement = node.methodName.staticElement;
|
| + if (target == null) {
|
| + if (staticElement is FunctionElement) {
|
| if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticProperty(
|
| + return new AccessSemantics.staticMethod(
|
| node.methodName,
|
| staticElement,
|
| null,
|
| isInvoke: true);
|
| - } else if (staticElement.isStatic) {
|
| - return new AccessSemantics.staticProperty(
|
| + } else {
|
| + return new AccessSemantics.localFunction(
|
| node.methodName,
|
| staticElement,
|
| - staticElement.enclosingElement,
|
| isInvoke: true);
|
| }
|
| - }
|
| - } else if (staticElement is LocalVariableElement) {
|
| - return new AccessSemantics.localVariable(
|
| - node.methodName,
|
| - staticElement,
|
| - isInvoke: true);
|
| - } else if (staticElement is ParameterElement) {
|
| - return new AccessSemantics.parameter(
|
| - node.methodName,
|
| - staticElement,
|
| - isInvoke: true);
|
| - }
|
| - } else if (target is Identifier) {
|
| - Element targetStaticElement = target.staticElement;
|
| - if (targetStaticElement is PrefixElement) {
|
| - if (staticElement == null) {
|
| - return new AccessSemantics.dynamic(
|
| + } else if (staticElement is MethodElement && staticElement.isStatic) {
|
| + return new AccessSemantics.staticMethod(
|
| node.methodName,
|
| - null,
|
| + staticElement,
|
| + staticElement.enclosingElement,
|
| isInvoke: true);
|
| } else if (staticElement is PropertyAccessorElement) {
|
| if (staticElement.isSynthetic) {
|
| - return new AccessSemantics.staticField(
|
| + if (staticElement.enclosingElement is CompilationUnitElement) {
|
| + return new AccessSemantics.staticField(
|
| + node.methodName,
|
| + staticElement.variable,
|
| + null,
|
| + isInvoke: true);
|
| + } else if (staticElement.isStatic) {
|
| + return new AccessSemantics.staticField(
|
| + node.methodName,
|
| + staticElement.variable,
|
| + staticElement.enclosingElement,
|
| + isInvoke: true);
|
| + }
|
| + } else {
|
| + if (staticElement.enclosingElement is CompilationUnitElement) {
|
| + return new AccessSemantics.staticProperty(
|
| + node.methodName,
|
| + staticElement,
|
| + null,
|
| + isInvoke: true);
|
| + } else if (staticElement.isStatic) {
|
| + return new AccessSemantics.staticProperty(
|
| + node.methodName,
|
| + staticElement,
|
| + staticElement.enclosingElement,
|
| + isInvoke: true);
|
| + }
|
| + }
|
| + } else if (staticElement is LocalVariableElement) {
|
| + return new AccessSemantics.localVariable(
|
| + node.methodName,
|
| + staticElement,
|
| + isInvoke: true);
|
| + } else if (staticElement is ParameterElement) {
|
| + return new AccessSemantics.parameter(
|
| + node.methodName,
|
| + staticElement,
|
| + isInvoke: true);
|
| + }
|
| + } else if (target is Identifier) {
|
| + Element targetStaticElement = target.staticElement;
|
| + if (targetStaticElement is PrefixElement) {
|
| + if (staticElement == null) {
|
| + return new AccessSemantics.dynamic(
|
| node.methodName,
|
| - staticElement.variable,
|
| null,
|
| isInvoke: true);
|
| + } else if (staticElement is PropertyAccessorElement) {
|
| + if (staticElement.isSynthetic) {
|
| + return new AccessSemantics.staticField(
|
| + node.methodName,
|
| + staticElement.variable,
|
| + null,
|
| + isInvoke: true);
|
| + } else {
|
| + return new AccessSemantics.staticProperty(
|
| + node.methodName,
|
| + staticElement,
|
| + null,
|
| + isInvoke: true);
|
| + }
|
| } else {
|
| - return new AccessSemantics.staticProperty(
|
| + return new AccessSemantics.staticMethod(
|
| node.methodName,
|
| staticElement,
|
| null,
|
| isInvoke: true);
|
| }
|
| - } else {
|
| - return new AccessSemantics.staticMethod(
|
| - node.methodName,
|
| - staticElement,
|
| - null,
|
| - isInvoke: true);
|
| - }
|
| - } else if (targetStaticElement is ClassElement) {
|
| - if (staticElement is PropertyAccessorElement) {
|
| - if (staticElement.isSynthetic) {
|
| - return new AccessSemantics.staticField(
|
| - node.methodName,
|
| - staticElement.variable,
|
| - targetStaticElement,
|
| - isInvoke: true);
|
| + } else if (targetStaticElement is ClassElement) {
|
| + if (staticElement is PropertyAccessorElement) {
|
| + if (staticElement.isSynthetic) {
|
| + return new AccessSemantics.staticField(
|
| + node.methodName,
|
| + staticElement.variable,
|
| + targetStaticElement,
|
| + isInvoke: true);
|
| + } else {
|
| + return new AccessSemantics.staticProperty(
|
| + node.methodName,
|
| + staticElement,
|
| + targetStaticElement,
|
| + isInvoke: true);
|
| + }
|
| } else {
|
| - return new AccessSemantics.staticProperty(
|
| + return new AccessSemantics.staticMethod(
|
| node.methodName,
|
| staticElement,
|
| targetStaticElement,
|
| isInvoke: true);
|
| }
|
| - } else {
|
| - return new AccessSemantics.staticMethod(
|
| - node.methodName,
|
| - staticElement,
|
| - targetStaticElement,
|
| - isInvoke: true);
|
| }
|
| }
|
| + return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
|
| }
|
| - return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
|
| -}
|
|
|
| -/**
|
| - * Return the access semantics for [node].
|
| - */
|
| -AccessSemantics classifyPrefixedIdentifier(PrefixedIdentifier node) {
|
| - return _classifyPrefixed(node.prefix, node.identifier);
|
| -}
|
| + /**
|
| + * Return the access semantics for [node].
|
| + */
|
| + @override
|
| + AccessSemantics visitPrefixedIdentifier(PrefixedIdentifier node) {
|
| + return _classifyPrefixed(node.prefix, node.identifier);
|
| + }
|
|
|
| -/**
|
| - * Helper function for classifying an expression of type
|
| - * Identifier.SimpleIdentifier.
|
| - */
|
| -AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
|
| - Element lhsElement = lhs.staticElement;
|
| - Element rhsElement = rhs.staticElement;
|
| - if (lhsElement is PrefixElement) {
|
| - if (rhsElement is PropertyAccessorElement) {
|
| - if (rhsElement.isSynthetic) {
|
| - return new AccessSemantics.staticField(rhs, rhsElement.variable, null);
|
| + /**
|
| + * Helper function for classifying an expression of type
|
| + * Identifier.SimpleIdentifier.
|
| + */
|
| + AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
|
| + Element lhsElement = lhs.staticElement;
|
| + Element rhsElement = rhs.staticElement;
|
| + if (lhsElement is PrefixElement) {
|
| + if (rhsElement is PropertyAccessorElement) {
|
| + if (rhsElement.isSynthetic) {
|
| + return new AccessSemantics.staticField(rhs, rhsElement.variable, null);
|
| + } else {
|
| + return new AccessSemantics.staticProperty(rhs, rhsElement, null);
|
| + }
|
| + } else if (rhsElement is FunctionElement) {
|
| + return new AccessSemantics.staticMethod(rhs, rhsElement, null);
|
| } else {
|
| - return new AccessSemantics.staticProperty(rhs, rhsElement, null);
|
| + return new AccessSemantics.dynamic(rhs, null);
|
| + }
|
| + } else if (lhsElement is ClassElement) {
|
| + if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
|
| + return new AccessSemantics.staticField(
|
| + rhs,
|
| + rhsElement.variable,
|
| + lhsElement);
|
| + } else if (rhsElement is MethodElement) {
|
| + return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
|
| + } else {
|
| + return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
|
| }
|
| - } else if (rhsElement is FunctionElement) {
|
| - return new AccessSemantics.staticMethod(rhs, rhsElement, null);
|
| - } else {
|
| - return new AccessSemantics.dynamic(rhs, null);
|
| - }
|
| - } else if (lhsElement is ClassElement) {
|
| - if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
|
| - return new AccessSemantics.staticField(
|
| - rhs,
|
| - rhsElement.variable,
|
| - lhsElement);
|
| - } else if (rhsElement is MethodElement) {
|
| - return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
|
| } else {
|
| - return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
|
| + return new AccessSemantics.dynamic(rhs, lhs);
|
| }
|
| - } else {
|
| - return new AccessSemantics.dynamic(rhs, lhs);
|
| }
|
| -}
|
|
|
| -/**
|
| - * Return the access semantics for [node].
|
| - */
|
| -AccessSemantics classifyPropertyAccess(PropertyAccess node) {
|
| - if (node.target is Identifier) {
|
| - return _classifyPrefixed(node.target, node.propertyName);
|
| - } else {
|
| - return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
|
| + /**
|
| + * Return the access semantics for [node].
|
| + */
|
| + @override
|
| + AccessSemantics visitPropertyAccess(PropertyAccess node) {
|
| + if (node.target is Identifier) {
|
| + return _classifyPrefixed(node.target, node.propertyName);
|
| + } else {
|
| + return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
|
| + }
|
| }
|
| -}
|
|
|
| -/**
|
| - * Return the access semantics for [node].
|
| - *
|
| - * Note: if [node] is the right hand side of a [PropertyAccess] or
|
| - * [PrefixedIdentifier], or the method name of a [MethodInvocation], the return
|
| - * value is null, since the semantics are determined by the parent. In
|
| - * practice these cases should never arise because the parent will visit the
|
| - * parent node before visiting this one.
|
| - */
|
| -AccessSemantics classifySimpleIdentifier(SimpleIdentifier node) {
|
| - AstNode parent = node.parent;
|
| - if (node.inDeclarationContext()) {
|
| - // This identifier is a declaration, not a use.
|
| - return null;
|
| - }
|
| - if (parent is TypeName) {
|
| - // TODO(paulberry): handle this case. Or, perhaps it would be better to
|
| - // require clients not to visit the children of a TypeName when visiting
|
| - // the AST structure.
|
| - //
|
| - // TODO(paulberry): be sure to consider type literals, e.g.:
|
| - // class A {}
|
| - // var a = A;
|
| - return null;
|
| - }
|
| - if ((parent is PropertyAccess && parent.propertyName == node) ||
|
| - (parent is PrefixedIdentifier && parent.identifier == node) ||
|
| - (parent is MethodInvocation && parent.methodName == node)) {
|
| - // The access semantics are determined by the parent.
|
| - return null;
|
| - }
|
| - // TODO(paulberry): handle PrefixElement.
|
| - Element staticElement = node.staticElement;
|
| - if (staticElement is PropertyAccessorElement) {
|
| - if (staticElement.isSynthetic) {
|
| - if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticField(
|
| - node,
|
| - staticElement.variable,
|
| - null);
|
| - } else if (staticElement.isStatic) {
|
| - return new AccessSemantics.staticField(
|
| - node,
|
| - staticElement.variable,
|
| - staticElement.enclosingElement);
|
| + /**
|
| + * Return the access semantics for [node].
|
| + *
|
| + * Note: if [node] is the right hand side of a [PropertyAccess] or
|
| + * [PrefixedIdentifier], or the method name of a [MethodInvocation], the return
|
| + * value is null, since the semantics are determined by the parent. In
|
| + * practice these cases should never arise because the parent will visit the
|
| + * parent node before visiting this one.
|
| + */
|
| + @override
|
| + AccessSemantics visitSimpleIdentifier(SimpleIdentifier node) {
|
| + AstNode parent = node.parent;
|
| + if (node.inDeclarationContext()) {
|
| + // This identifier is a declaration, not a use.
|
| + return null;
|
| + }
|
| + if (parent is TypeName) {
|
| + // TODO(paulberry): handle this case. Or, perhaps it would be better to
|
| + // require clients not to visit the children of a TypeName when visiting
|
| + // the AST structure.
|
| + //
|
| + // TODO(paulberry): be sure to consider type literals, e.g.:
|
| + // class A {}
|
| + // var a = A;
|
| + return null;
|
| + }
|
| + if ((parent is PropertyAccess && parent.propertyName == node) ||
|
| + (parent is PrefixedIdentifier && parent.identifier == node) ||
|
| + (parent is MethodInvocation && parent.methodName == node)) {
|
| + // The access semantics are determined by the parent.
|
| + return null;
|
| + }
|
| + // TODO(paulberry): handle PrefixElement.
|
| + Element staticElement = node.staticElement;
|
| + if (staticElement is PropertyAccessorElement) {
|
| + if (staticElement.isSynthetic) {
|
| + if (staticElement.enclosingElement is CompilationUnitElement) {
|
| + return new AccessSemantics.staticField(
|
| + node,
|
| + staticElement.variable,
|
| + null);
|
| + } else if (staticElement.isStatic) {
|
| + return new AccessSemantics.staticField(
|
| + node,
|
| + staticElement.variable,
|
| + staticElement.enclosingElement);
|
| + }
|
| + } else {
|
| + if (staticElement.enclosingElement is CompilationUnitElement) {
|
| + return new AccessSemantics.staticProperty(node, staticElement, null);
|
| + } else if (staticElement.isStatic) {
|
| + return new AccessSemantics.staticProperty(
|
| + node,
|
| + staticElement,
|
| + staticElement.enclosingElement);
|
| + }
|
| }
|
| - } else {
|
| + } else if (staticElement is LocalVariableElement) {
|
| + return new AccessSemantics.localVariable(node, staticElement);
|
| + } else if (staticElement is ParameterElement) {
|
| + return new AccessSemantics.parameter(node, staticElement);
|
| + } else if (staticElement is FunctionElement) {
|
| if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticProperty(node, staticElement, null);
|
| - } else if (staticElement.isStatic) {
|
| - return new AccessSemantics.staticProperty(
|
| - node,
|
| - staticElement,
|
| - staticElement.enclosingElement);
|
| + return new AccessSemantics.staticMethod(node, staticElement, null);
|
| + } else {
|
| + return new AccessSemantics.localFunction(node, staticElement);
|
| }
|
| + } else if (staticElement is MethodElement && staticElement.isStatic) {
|
| + return new AccessSemantics.staticMethod(
|
| + node,
|
| + staticElement,
|
| + staticElement.enclosingElement);
|
| }
|
| - } else if (staticElement is LocalVariableElement) {
|
| - return new AccessSemantics.localVariable(node, staticElement);
|
| - } else if (staticElement is ParameterElement) {
|
| - return new AccessSemantics.parameter(node, staticElement);
|
| - } else if (staticElement is FunctionElement) {
|
| - if (staticElement.enclosingElement is CompilationUnitElement) {
|
| - return new AccessSemantics.staticMethod(node, staticElement, null);
|
| - } else {
|
| - return new AccessSemantics.localFunction(node, staticElement);
|
| - }
|
| - } else if (staticElement is MethodElement && staticElement.isStatic) {
|
| - return new AccessSemantics.staticMethod(
|
| - node,
|
| - staticElement,
|
| - staticElement.enclosingElement);
|
| + return new AccessSemantics.dynamic(node, null);
|
| }
|
| - return new AccessSemantics.dynamic(node, null);
|
| -}
|
| +}
|
|
|