| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library analyzer2dart.semantic_visitor; |
| |
| import 'package:analyzer/analyzer.dart'; |
| import 'package:analyzer/src/generated/source.dart'; |
| |
| import 'util.dart'; |
| import 'identifier_semantics.dart'; |
| |
| /// An AST visitor which uses the [AccessSemantics] of invocations and accesses |
| /// to fine-grain visitor methods. |
| abstract class SemanticVisitor<R> extends RecursiveAstVisitor<R> { |
| |
| Source get currentSource; |
| |
| void reportMessage(AstNode node, String message) { |
| reportSourceMessage(currentSource, node, message); |
| } |
| |
| giveUp(AstNode node, String message) { |
| reportMessage(node, message); |
| throw new UnimplementedError(message); |
| } |
| |
| bool invariant(AstNode node, condition, String message) { |
| if (condition is Function) { |
| condition = condition(); |
| } |
| if (!condition) { |
| reportMessage(node, message); |
| return false; |
| } |
| return true; |
| } |
| |
| R visitDynamicInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitDynamicInvocation of $semantics'); |
| } |
| |
| R visitLocalFunctionInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalFunctionInvocation of $semantics'); |
| } |
| |
| R visitLocalVariableInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalVariableInvocation of $semantics'); |
| } |
| |
| R visitParameterInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitParameterInvocation of $semantics'); |
| } |
| |
| R visitStaticFieldInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticFieldInvocation of $semantics'); |
| } |
| |
| R visitStaticMethodInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticMethodInvocation of $semantics'); |
| } |
| |
| R visitStaticPropertyInvocation(MethodInvocation node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticPropertyInvocation of $semantics'); |
| } |
| |
| @override |
| R visitMethodInvocation(MethodInvocation node) { |
| if (node.target != null) { |
| node.target.accept(this); |
| } |
| node.argumentList.accept(this); |
| return handleMethodInvocation(node); |
| } |
| |
| R handleMethodInvocation(MethodInvocation node) { |
| AccessSemantics semantics = node.accept(ACCESS_SEMANTICS_VISITOR); |
| switch (semantics.kind) { |
| case AccessKind.DYNAMIC: |
| return visitDynamicInvocation(node, semantics); |
| case AccessKind.LOCAL_FUNCTION: |
| return visitLocalFunctionInvocation(node, semantics); |
| case AccessKind.LOCAL_VARIABLE: |
| return visitLocalVariableInvocation(node, semantics); |
| case AccessKind.PARAMETER: |
| return visitParameterInvocation(node, semantics); |
| case AccessKind.STATIC_FIELD: |
| return visitStaticFieldInvocation(node, semantics); |
| case AccessKind.STATIC_METHOD: |
| return visitStaticMethodInvocation(node, semantics); |
| case AccessKind.STATIC_PROPERTY: |
| return visitStaticPropertyInvocation(node, semantics); |
| default: |
| // Unexpected access kind. |
| return giveUp(node, |
| 'Unexpected ${semantics} in visitMethodInvocation.'); |
| } |
| } |
| |
| @override |
| R visitPropertyAccess(PropertyAccess node) { |
| if (node.target != null) { |
| node.target.accept(this); |
| } |
| return handlePropertyAccess(node); |
| } |
| |
| R handlePropertyAccess(PropertyAccess node) { |
| return _handlePropertyAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); |
| } |
| |
| @override |
| R visitPrefixedIdentifier(PrefixedIdentifier node) { |
| node.prefix.accept(this); |
| return handlePrefixedIdentifier(node); |
| } |
| |
| R handlePrefixedIdentifier(PrefixedIdentifier node) { |
| return _handlePropertyAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); |
| } |
| |
| @override |
| R visitSimpleIdentifier(SimpleIdentifier node) { |
| AccessSemantics semantics = node.accept(ACCESS_SEMANTICS_VISITOR); |
| if (semantics != null) { |
| return _handlePropertyAccess(node, semantics); |
| } else { |
| return null; |
| } |
| } |
| |
| R visitDynamicAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitDynamicAccess of $semantics'); |
| } |
| |
| R visitLocalFunctionAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalFunctionAccess of $semantics'); |
| } |
| |
| R visitLocalVariableAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalVariableAccess of $semantics'); |
| } |
| |
| R visitParameterAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitParameterAccess of $semantics'); |
| } |
| |
| R visitStaticFieldAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticFieldAccess of $semantics'); |
| } |
| |
| R visitStaticMethodAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticMethodAccess of $semantics'); |
| } |
| |
| R visitStaticPropertyAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticPropertyAccess of $semantics'); |
| } |
| |
| R visitToplevelClassAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitToplevelClassAccess of $semantics'); |
| } |
| |
| R visitTypeParameterAccess(AstNode node, AccessSemantics semantics) { |
| return giveUp(node, 'visitTypeParameterAccess of $semantics'); |
| } |
| |
| R _handlePropertyAccess(AstNode node, AccessSemantics semantics) { |
| switch (semantics.kind) { |
| case AccessKind.DYNAMIC: |
| return visitDynamicAccess(node, semantics); |
| case AccessKind.LOCAL_FUNCTION: |
| return visitLocalFunctionAccess(node, semantics); |
| case AccessKind.LOCAL_VARIABLE: |
| return visitLocalVariableAccess(node, semantics); |
| case AccessKind.PARAMETER: |
| return visitParameterAccess(node, semantics); |
| case AccessKind.STATIC_FIELD: |
| return visitStaticFieldAccess(node, semantics); |
| case AccessKind.STATIC_METHOD: |
| return visitStaticMethodAccess(node, semantics); |
| case AccessKind.STATIC_PROPERTY: |
| return visitStaticPropertyAccess(node, semantics); |
| case AccessKind.TOPLEVEL_TYPE: |
| return visitToplevelClassAccess(node, semantics); |
| case AccessKind.TYPE_PARAMETER: |
| return visitTypeParameterAccess(node, semantics); |
| default: |
| // Unexpected access kind. |
| return giveUp(node, |
| 'Unexpected ${semantics} in _handlePropertyAccess.'); |
| } |
| } |
| |
| R visitDynamicPropertyAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitDynamicPropertyAssignment of $semantics'); |
| } |
| |
| R visitLocalFunctionAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalFunctionAssignment of $semantics'); |
| } |
| |
| R visitLocalVariableAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitLocalVariableAssignment of $semantics'); |
| } |
| |
| R visitParameterAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitParameterAssignment of $semantics'); |
| } |
| |
| R visitStaticFieldAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticFieldAssignment of $semantics'); |
| } |
| |
| R visitStaticMethodAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticMethodAssignment of $semantics'); |
| } |
| |
| R visitStaticPropertyAssignment(AssignmentExpression node, |
| AccessSemantics semantics) { |
| return giveUp(node, 'visitStaticPropertyAssignment of $semantics'); |
| } |
| |
| @override |
| R visitAssignmentExpression(AssignmentExpression node) { |
| super.visitAssignmentExpression(node); |
| return handleAssignmentExpression(node); |
| } |
| |
| R handleAssignmentExpression(AssignmentExpression node) { |
| AccessSemantics semantics = |
| node.leftHandSide.accept(ACCESS_SEMANTICS_VISITOR); |
| if (semantics == null) { |
| return giveUp(node, 'handleAssignmentExpression with no AccessSemantics'); |
| } else { |
| switch (semantics.kind) { |
| case AccessKind.DYNAMIC: |
| return visitDynamicPropertyAssignment(node, semantics); |
| case AccessKind.LOCAL_FUNCTION: |
| return visitLocalFunctionAssignment(node, semantics); |
| case AccessKind.LOCAL_VARIABLE: |
| return visitLocalVariableAssignment(node, semantics); |
| case AccessKind.PARAMETER: |
| return visitParameterAssignment(node, semantics); |
| case AccessKind.STATIC_FIELD: |
| return visitStaticFieldAssignment(node, semantics); |
| case AccessKind.STATIC_METHOD: |
| return visitStaticMethodAssignment(node, semantics); |
| case AccessKind.STATIC_PROPERTY: |
| return visitStaticPropertyAssignment(node, semantics); |
| default: |
| // Unexpected access kind. |
| return giveUp(node, |
| 'Unexpected ${semantics} in _handlePropertyAccess.'); |
| } |
| } |
| } |
| } |