| // 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 analyzer.src.dart.ast.utilities; |
| |
| import 'dart:collection'; |
| |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/ast/standard_ast_factory.dart'; |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/dart/ast/visitor.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/exception/exception.dart'; |
| import 'package:analyzer/src/dart/ast/ast.dart'; |
| import 'package:analyzer/src/dart/ast/token.dart'; |
| import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine; |
| import 'package:analyzer/src/generated/java_core.dart'; |
| import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:meta/meta.dart'; |
| |
| /** |
| * A function used to handle exceptions that are thrown by delegates while using |
| * an [ExceptionHandlingDelegatingAstVisitor]. |
| */ |
| typedef void ExceptionInDelegateHandler( |
| AstNode node, AstVisitor visitor, dynamic exception, StackTrace stackTrace); |
| |
| /** |
| * An AST visitor that will clone any AST structure that it visits. The cloner |
| * will only clone the structure, it will not preserve any resolution results or |
| * properties associated with the nodes. |
| */ |
| class AstCloner implements AstVisitor<AstNode> { |
| /** |
| * A flag indicating whether tokens should be cloned while cloning an AST |
| * structure. |
| */ |
| final bool cloneTokens; |
| |
| /** |
| * Mapping from original tokes to cloned. |
| */ |
| final Map<Token, Token> _clonedTokens = new Map<Token, Token>.identity(); |
| |
| /** |
| * The next original token to clone. |
| */ |
| Token _nextToClone; |
| |
| /** |
| * The last cloned token. |
| */ |
| Token _lastCloned; |
| |
| /** |
| * The offset of the last cloned token. |
| */ |
| int _lastClonedOffset = -1; |
| |
| /** |
| * Initialize a newly created AST cloner to optionally clone tokens while |
| * cloning AST nodes if [cloneTokens] is `true`. |
| * |
| * TODO(brianwilkerson) Change this to be a named parameter. |
| */ |
| AstCloner([this.cloneTokens = false]); |
| |
| /** |
| * Return a clone of the given [node]. |
| */ |
| AstNode/*=E*/ cloneNode/*<E extends AstNode>*/(AstNode/*=E*/ node) { |
| if (node == null) { |
| return null; |
| } |
| return node.accept(this) as AstNode/*=E*/; |
| } |
| |
| /** |
| * Return a list containing cloned versions of the nodes in the given list of |
| * [nodes]. |
| */ |
| List<AstNode/*=E*/ > cloneNodeList/*<E extends AstNode>*/(List/*<E>*/ nodes) { |
| int count = nodes.length; |
| List/*<E>*/ clonedNodes = new List/*<E>*/(); |
| for (int i = 0; i < count; i++) { |
| clonedNodes.add((nodes[i]).accept(this) as AstNode/*=E*/); |
| } |
| return clonedNodes; |
| } |
| |
| /** |
| * Clone the given [token] if tokens are supposed to be cloned. |
| */ |
| Token cloneToken(Token token) { |
| if (cloneTokens) { |
| if (token == null) { |
| return null; |
| } |
| if (_lastClonedOffset <= token.offset) { |
| _cloneTokens(_nextToClone ?? token, token.offset); |
| } |
| Token clone = _clonedTokens[token]; |
| assert(clone != null); |
| return clone; |
| } else { |
| return token; |
| } |
| } |
| |
| /** |
| * Clone the given [tokens] if tokens are supposed to be cloned. |
| */ |
| List<Token> cloneTokenList(List<Token> tokens) { |
| if (cloneTokens) { |
| return tokens.map(cloneToken).toList(); |
| } |
| return tokens; |
| } |
| |
| @override |
| AdjacentStrings visitAdjacentStrings(AdjacentStrings node) => |
| astFactory.adjacentStrings(cloneNodeList(node.strings)); |
| |
| @override |
| Annotation visitAnnotation(Annotation node) => astFactory.annotation( |
| cloneToken(node.atSign), |
| cloneNode(node.name), |
| cloneToken(node.period), |
| cloneNode(node.constructorName), |
| cloneNode(node.arguments)); |
| |
| @override |
| ArgumentList visitArgumentList(ArgumentList node) => astFactory.argumentList( |
| cloneToken(node.leftParenthesis), |
| cloneNodeList(node.arguments), |
| cloneToken(node.rightParenthesis)); |
| |
| @override |
| AsExpression visitAsExpression(AsExpression node) => astFactory.asExpression( |
| cloneNode(node.expression), |
| cloneToken(node.asOperator), |
| cloneNode(node.type)); |
| |
| @override |
| AstNode visitAssertInitializer(AssertInitializer node) => |
| astFactory.assertInitializer( |
| cloneToken(node.assertKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.condition), |
| cloneToken(node.comma), |
| cloneNode(node.message), |
| cloneToken(node.rightParenthesis)); |
| |
| @override |
| AstNode visitAssertStatement(AssertStatement node) => |
| astFactory.assertStatement( |
| cloneToken(node.assertKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.condition), |
| cloneToken(node.comma), |
| cloneNode(node.message), |
| cloneToken(node.rightParenthesis), |
| cloneToken(node.semicolon)); |
| |
| @override |
| AssignmentExpression visitAssignmentExpression(AssignmentExpression node) => |
| astFactory.assignmentExpression(cloneNode(node.leftHandSide), |
| cloneToken(node.operator), cloneNode(node.rightHandSide)); |
| |
| @override |
| AwaitExpression visitAwaitExpression(AwaitExpression node) => |
| astFactory.awaitExpression( |
| cloneToken(node.awaitKeyword), cloneNode(node.expression)); |
| |
| @override |
| BinaryExpression visitBinaryExpression(BinaryExpression node) => |
| astFactory.binaryExpression(cloneNode(node.leftOperand), |
| cloneToken(node.operator), cloneNode(node.rightOperand)); |
| |
| @override |
| Block visitBlock(Block node) => astFactory.block(cloneToken(node.leftBracket), |
| cloneNodeList(node.statements), cloneToken(node.rightBracket)); |
| |
| @override |
| BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) => |
| astFactory.blockFunctionBody(cloneToken(node.keyword), |
| cloneToken(node.star), cloneNode(node.block)); |
| |
| @override |
| BooleanLiteral visitBooleanLiteral(BooleanLiteral node) => |
| astFactory.booleanLiteral(cloneToken(node.literal), node.value); |
| |
| @override |
| BreakStatement visitBreakStatement(BreakStatement node) => |
| astFactory.breakStatement(cloneToken(node.breakKeyword), |
| cloneNode(node.label), cloneToken(node.semicolon)); |
| |
| @override |
| CascadeExpression visitCascadeExpression(CascadeExpression node) => |
| astFactory.cascadeExpression( |
| cloneNode(node.target), cloneNodeList(node.cascadeSections)); |
| |
| @override |
| CatchClause visitCatchClause(CatchClause node) => astFactory.catchClause( |
| cloneToken(node.onKeyword), |
| cloneNode(node.exceptionType), |
| cloneToken(node.catchKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.exceptionParameter), |
| cloneToken(node.comma), |
| cloneNode(node.stackTraceParameter), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.body)); |
| |
| @override |
| ClassDeclaration visitClassDeclaration(ClassDeclaration node) { |
| ClassDeclaration copy = astFactory.classDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.abstractKeyword), |
| cloneToken(node.classKeyword), |
| cloneNode(node.name), |
| cloneNode(node.typeParameters), |
| cloneNode(node.extendsClause), |
| cloneNode(node.withClause), |
| cloneNode(node.implementsClause), |
| cloneToken(node.leftBracket), |
| cloneNodeList(node.members), |
| cloneToken(node.rightBracket)); |
| copy.nativeClause = cloneNode(node.nativeClause); |
| return copy; |
| } |
| |
| @override |
| ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) { |
| cloneToken(node.abstractKeyword); |
| return astFactory.classTypeAlias( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.typedefKeyword), |
| cloneNode(node.name), |
| cloneNode(node.typeParameters), |
| cloneToken(node.equals), |
| cloneToken(node.abstractKeyword), |
| cloneNode(node.superclass), |
| cloneNode(node.withClause), |
| cloneNode(node.implementsClause), |
| cloneToken(node.semicolon)); |
| } |
| |
| @override |
| Comment visitComment(Comment node) { |
| if (node.isDocumentation) { |
| return astFactory.documentationComment( |
| cloneTokenList(node.tokens), cloneNodeList(node.references)); |
| } else if (node.isBlock) { |
| return astFactory.blockComment(cloneTokenList(node.tokens)); |
| } |
| return astFactory.endOfLineComment(cloneTokenList(node.tokens)); |
| } |
| |
| @override |
| CommentReference visitCommentReference(CommentReference node) => |
| astFactory.commentReference( |
| cloneToken(node.newKeyword), cloneNode(node.identifier)); |
| |
| @override |
| CompilationUnit visitCompilationUnit(CompilationUnit node) { |
| CompilationUnit clone = astFactory.compilationUnit( |
| cloneToken(node.beginToken), |
| cloneNode(node.scriptTag), |
| cloneNodeList(node.directives), |
| cloneNodeList(node.declarations), |
| cloneToken(node.endToken)); |
| clone.lineInfo = node.lineInfo; |
| return clone; |
| } |
| |
| @override |
| ConditionalExpression visitConditionalExpression( |
| ConditionalExpression node) => |
| astFactory.conditionalExpression( |
| cloneNode(node.condition), |
| cloneToken(node.question), |
| cloneNode(node.thenExpression), |
| cloneToken(node.colon), |
| cloneNode(node.elseExpression)); |
| |
| @override |
| Configuration visitConfiguration(Configuration node) => |
| astFactory.configuration( |
| cloneToken(node.ifKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.name), |
| cloneToken(node.equalToken), |
| cloneNode(node.value), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.uri)); |
| |
| @override |
| ConstructorDeclaration visitConstructorDeclaration( |
| ConstructorDeclaration node) => |
| astFactory.constructorDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.externalKeyword), |
| cloneToken(node.constKeyword), |
| cloneToken(node.factoryKeyword), |
| cloneNode(node.returnType), |
| cloneToken(node.period), |
| cloneNode(node.name), |
| cloneNode(node.parameters), |
| cloneToken(node.separator), |
| cloneNodeList(node.initializers), |
| cloneNode(node.redirectedConstructor), |
| cloneNode(node.body)); |
| |
| @override |
| ConstructorFieldInitializer visitConstructorFieldInitializer( |
| ConstructorFieldInitializer node) => |
| astFactory.constructorFieldInitializer( |
| cloneToken(node.thisKeyword), |
| cloneToken(node.period), |
| cloneNode(node.fieldName), |
| cloneToken(node.equals), |
| cloneNode(node.expression)); |
| |
| @override |
| ConstructorName visitConstructorName(ConstructorName node) => |
| astFactory.constructorName( |
| cloneNode(node.type), cloneToken(node.period), cloneNode(node.name)); |
| |
| @override |
| ContinueStatement visitContinueStatement(ContinueStatement node) => |
| astFactory.continueStatement(cloneToken(node.continueKeyword), |
| cloneNode(node.label), cloneToken(node.semicolon)); |
| |
| @override |
| DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) => |
| astFactory.declaredIdentifier( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.keyword), |
| cloneNode(node.type), |
| cloneNode(node.identifier)); |
| |
| @override |
| DefaultFormalParameter visitDefaultFormalParameter( |
| DefaultFormalParameter node) => |
| astFactory.defaultFormalParameter(cloneNode(node.parameter), node.kind, |
| cloneToken(node.separator), cloneNode(node.defaultValue)); |
| |
| @override |
| DoStatement visitDoStatement(DoStatement node) => astFactory.doStatement( |
| cloneToken(node.doKeyword), |
| cloneNode(node.body), |
| cloneToken(node.whileKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.condition), |
| cloneToken(node.rightParenthesis), |
| cloneToken(node.semicolon)); |
| |
| @override |
| DottedName visitDottedName(DottedName node) => |
| astFactory.dottedName(cloneNodeList(node.components)); |
| |
| @override |
| DoubleLiteral visitDoubleLiteral(DoubleLiteral node) => |
| astFactory.doubleLiteral(cloneToken(node.literal), node.value); |
| |
| @override |
| EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) => |
| astFactory.emptyFunctionBody(cloneToken(node.semicolon)); |
| |
| @override |
| EmptyStatement visitEmptyStatement(EmptyStatement node) => |
| astFactory.emptyStatement(cloneToken(node.semicolon)); |
| |
| @override |
| AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) => |
| astFactory.enumConstantDeclaration(cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), cloneNode(node.name)); |
| |
| @override |
| EnumDeclaration visitEnumDeclaration(EnumDeclaration node) => |
| astFactory.enumDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.enumKeyword), |
| cloneNode(node.name), |
| cloneToken(node.leftBracket), |
| cloneNodeList(node.constants), |
| cloneToken(node.rightBracket)); |
| |
| @override |
| ExportDirective visitExportDirective(ExportDirective node) { |
| ExportDirectiveImpl directive = astFactory.exportDirective( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.keyword), |
| cloneNode(node.uri), |
| cloneNodeList(node.configurations), |
| cloneNodeList(node.combinators), |
| cloneToken(node.semicolon)); |
| directive.selectedUriContent = node.selectedUriContent; |
| directive.selectedSource = node.selectedSource; |
| directive.uriSource = node.uriSource; |
| directive.uriContent = node.uriContent; |
| return directive; |
| } |
| |
| @override |
| ExpressionFunctionBody visitExpressionFunctionBody( |
| ExpressionFunctionBody node) => |
| astFactory.expressionFunctionBody( |
| cloneToken(node.keyword), |
| cloneToken(node.functionDefinition), |
| cloneNode(node.expression), |
| cloneToken(node.semicolon)); |
| |
| @override |
| ExpressionStatement visitExpressionStatement(ExpressionStatement node) => |
| astFactory.expressionStatement( |
| cloneNode(node.expression), cloneToken(node.semicolon)); |
| |
| @override |
| ExtendsClause visitExtendsClause(ExtendsClause node) => |
| astFactory.extendsClause( |
| cloneToken(node.extendsKeyword), cloneNode(node.superclass)); |
| |
| @override |
| FieldDeclaration visitFieldDeclaration(FieldDeclaration node) => |
| astFactory.fieldDeclaration2( |
| comment: cloneNode(node.documentationComment), |
| metadata: cloneNodeList(node.metadata), |
| covariantKeyword: cloneToken(node.covariantKeyword), |
| staticKeyword: cloneToken(node.staticKeyword), |
| fieldList: cloneNode(node.fields), |
| semicolon: cloneToken(node.semicolon)); |
| |
| @override |
| FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) => |
| astFactory.fieldFormalParameter2( |
| comment: cloneNode(node.documentationComment), |
| metadata: cloneNodeList(node.metadata), |
| covariantKeyword: cloneToken(node.covariantKeyword), |
| keyword: cloneToken(node.keyword), |
| type: cloneNode(node.type), |
| thisKeyword: cloneToken(node.thisKeyword), |
| period: cloneToken(node.period), |
| identifier: cloneNode(node.identifier), |
| typeParameters: cloneNode(node.typeParameters), |
| parameters: cloneNode(node.parameters)); |
| |
| @override |
| ForEachStatement visitForEachStatement(ForEachStatement node) { |
| DeclaredIdentifier loopVariable = node.loopVariable; |
| if (loopVariable == null) { |
| return astFactory.forEachStatementWithReference( |
| cloneToken(node.awaitKeyword), |
| cloneToken(node.forKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.identifier), |
| cloneToken(node.inKeyword), |
| cloneNode(node.iterable), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.body)); |
| } |
| return astFactory.forEachStatementWithDeclaration( |
| cloneToken(node.awaitKeyword), |
| cloneToken(node.forKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(loopVariable), |
| cloneToken(node.inKeyword), |
| cloneNode(node.iterable), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.body)); |
| } |
| |
| @override |
| FormalParameterList visitFormalParameterList(FormalParameterList node) => |
| astFactory.formalParameterList( |
| cloneToken(node.leftParenthesis), |
| cloneNodeList(node.parameters), |
| cloneToken(node.leftDelimiter), |
| cloneToken(node.rightDelimiter), |
| cloneToken(node.rightParenthesis)); |
| |
| @override |
| ForStatement visitForStatement(ForStatement node) => astFactory.forStatement( |
| cloneToken(node.forKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.variables), |
| cloneNode(node.initialization), |
| cloneToken(node.leftSeparator), |
| cloneNode(node.condition), |
| cloneToken(node.rightSeparator), |
| cloneNodeList(node.updaters), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.body)); |
| |
| @override |
| FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) => |
| astFactory.functionDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.externalKeyword), |
| cloneNode(node.returnType), |
| cloneToken(node.propertyKeyword), |
| cloneNode(node.name), |
| cloneNode(node.functionExpression)); |
| |
| @override |
| FunctionDeclarationStatement visitFunctionDeclarationStatement( |
| FunctionDeclarationStatement node) => |
| astFactory |
| .functionDeclarationStatement(cloneNode(node.functionDeclaration)); |
| |
| @override |
| FunctionExpression visitFunctionExpression(FunctionExpression node) => |
| astFactory.functionExpression(cloneNode(node.typeParameters), |
| cloneNode(node.parameters), cloneNode(node.body)); |
| |
| @override |
| FunctionExpressionInvocation visitFunctionExpressionInvocation( |
| FunctionExpressionInvocation node) => |
| astFactory.functionExpressionInvocation(cloneNode(node.function), |
| cloneNode(node.typeArguments), cloneNode(node.argumentList)); |
| |
| @override |
| FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) => |
| astFactory.functionTypeAlias( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.typedefKeyword), |
| cloneNode(node.returnType), |
| cloneNode(node.name), |
| cloneNode(node.typeParameters), |
| cloneNode(node.parameters), |
| cloneToken(node.semicolon)); |
| |
| @override |
| FunctionTypedFormalParameter visitFunctionTypedFormalParameter( |
| FunctionTypedFormalParameter node) => |
| astFactory.functionTypedFormalParameter2( |
| comment: cloneNode(node.documentationComment), |
| metadata: cloneNodeList(node.metadata), |
| covariantKeyword: cloneToken(node.covariantKeyword), |
| returnType: cloneNode(node.returnType), |
| identifier: cloneNode(node.identifier), |
| typeParameters: cloneNode(node.typeParameters), |
| parameters: cloneNode(node.parameters)); |
| |
| @override |
| AstNode visitGenericFunctionType(GenericFunctionType node) => |
| astFactory.genericFunctionType( |
| cloneNode(node.returnType), |
| cloneToken(node.functionKeyword), |
| cloneNode(node.typeParameters), |
| cloneNode(node.parameters)); |
| |
| @override |
| AstNode visitGenericTypeAlias(GenericTypeAlias node) => |
| astFactory.genericTypeAlias( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.typedefKeyword), |
| cloneNode(node.name), |
| cloneNode(node.typeParameters), |
| cloneToken(node.equals), |
| cloneNode(node.functionType), |
| cloneToken(node.semicolon)); |
| |
| @override |
| HideCombinator visitHideCombinator(HideCombinator node) => |
| astFactory.hideCombinator( |
| cloneToken(node.keyword), cloneNodeList(node.hiddenNames)); |
| |
| @override |
| IfStatement visitIfStatement(IfStatement node) => astFactory.ifStatement( |
| cloneToken(node.ifKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.condition), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.thenStatement), |
| cloneToken(node.elseKeyword), |
| cloneNode(node.elseStatement)); |
| |
| @override |
| ImplementsClause visitImplementsClause(ImplementsClause node) => |
| astFactory.implementsClause( |
| cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces)); |
| |
| @override |
| ImportDirective visitImportDirective(ImportDirective node) { |
| ImportDirectiveImpl directive = astFactory.importDirective( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.keyword), |
| cloneNode(node.uri), |
| cloneNodeList(node.configurations), |
| cloneToken(node.deferredKeyword), |
| cloneToken(node.asKeyword), |
| cloneNode(node.prefix), |
| cloneNodeList(node.combinators), |
| cloneToken(node.semicolon)); |
| directive.selectedUriContent = node.selectedUriContent; |
| directive.selectedSource = node.selectedSource; |
| directive.uriSource = node.uriSource; |
| directive.uriContent = node.uriContent; |
| return directive; |
| } |
| |
| @override |
| IndexExpression visitIndexExpression(IndexExpression node) { |
| Token period = node.period; |
| if (period == null) { |
| return astFactory.indexExpressionForTarget( |
| cloneNode(node.target), |
| cloneToken(node.leftBracket), |
| cloneNode(node.index), |
| cloneToken(node.rightBracket)); |
| } else { |
| return astFactory.indexExpressionForCascade( |
| cloneToken(period), |
| cloneToken(node.leftBracket), |
| cloneNode(node.index), |
| cloneToken(node.rightBracket)); |
| } |
| } |
| |
| @override |
| InstanceCreationExpression visitInstanceCreationExpression( |
| InstanceCreationExpression node) => |
| astFactory.instanceCreationExpression(cloneToken(node.keyword), |
| cloneNode(node.constructorName), cloneNode(node.argumentList)); |
| |
| @override |
| IntegerLiteral visitIntegerLiteral(IntegerLiteral node) => |
| astFactory.integerLiteral(cloneToken(node.literal), node.value); |
| |
| @override |
| InterpolationExpression visitInterpolationExpression( |
| InterpolationExpression node) => |
| astFactory.interpolationExpression(cloneToken(node.leftBracket), |
| cloneNode(node.expression), cloneToken(node.rightBracket)); |
| |
| @override |
| InterpolationString visitInterpolationString(InterpolationString node) => |
| astFactory.interpolationString(cloneToken(node.contents), node.value); |
| |
| @override |
| IsExpression visitIsExpression(IsExpression node) => astFactory.isExpression( |
| cloneNode(node.expression), |
| cloneToken(node.isOperator), |
| cloneToken(node.notOperator), |
| cloneNode(node.type)); |
| |
| @override |
| Label visitLabel(Label node) => |
| astFactory.label(cloneNode(node.label), cloneToken(node.colon)); |
| |
| @override |
| LabeledStatement visitLabeledStatement(LabeledStatement node) => astFactory |
| .labeledStatement(cloneNodeList(node.labels), cloneNode(node.statement)); |
| |
| @override |
| LibraryDirective visitLibraryDirective(LibraryDirective node) => |
| astFactory.libraryDirective( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.libraryKeyword), |
| cloneNode(node.name), |
| cloneToken(node.semicolon)); |
| |
| @override |
| LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) => |
| astFactory.libraryIdentifier(cloneNodeList(node.components)); |
| |
| @override |
| ListLiteral visitListLiteral(ListLiteral node) => astFactory.listLiteral( |
| cloneToken(node.constKeyword), |
| cloneNode(node.typeArguments), |
| cloneToken(node.leftBracket), |
| cloneNodeList(node.elements), |
| cloneToken(node.rightBracket)); |
| |
| @override |
| MapLiteral visitMapLiteral(MapLiteral node) => astFactory.mapLiteral( |
| cloneToken(node.constKeyword), |
| cloneNode(node.typeArguments), |
| cloneToken(node.leftBracket), |
| cloneNodeList(node.entries), |
| cloneToken(node.rightBracket)); |
| |
| @override |
| MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) => |
| astFactory.mapLiteralEntry(cloneNode(node.key), |
| cloneToken(node.separator), cloneNode(node.value)); |
| |
| @override |
| MethodDeclaration visitMethodDeclaration(MethodDeclaration node) => |
| astFactory.methodDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.externalKeyword), |
| cloneToken(node.modifierKeyword), |
| cloneNode(node.returnType), |
| cloneToken(node.propertyKeyword), |
| cloneToken(node.operatorKeyword), |
| cloneNode(node.name), |
| cloneNode(node.typeParameters), |
| cloneNode(node.parameters), |
| cloneNode(node.body)); |
| |
| @override |
| MethodInvocation visitMethodInvocation(MethodInvocation node) => |
| astFactory.methodInvocation( |
| cloneNode(node.target), |
| cloneToken(node.operator), |
| cloneNode(node.methodName), |
| cloneNode(node.typeArguments), |
| cloneNode(node.argumentList)); |
| |
| @override |
| NamedExpression visitNamedExpression(NamedExpression node) => astFactory |
| .namedExpression(cloneNode(node.name), cloneNode(node.expression)); |
| |
| @override |
| AstNode visitNativeClause(NativeClause node) => astFactory.nativeClause( |
| cloneToken(node.nativeKeyword), cloneNode(node.name)); |
| |
| @override |
| NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) => |
| astFactory.nativeFunctionBody(cloneToken(node.nativeKeyword), |
| cloneNode(node.stringLiteral), cloneToken(node.semicolon)); |
| |
| @override |
| NullLiteral visitNullLiteral(NullLiteral node) => |
| astFactory.nullLiteral(cloneToken(node.literal)); |
| |
| @override |
| ParenthesizedExpression visitParenthesizedExpression( |
| ParenthesizedExpression node) => |
| astFactory.parenthesizedExpression(cloneToken(node.leftParenthesis), |
| cloneNode(node.expression), cloneToken(node.rightParenthesis)); |
| |
| @override |
| PartDirective visitPartDirective(PartDirective node) { |
| PartDirective directive = astFactory.partDirective( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.partKeyword), |
| cloneNode(node.uri), |
| cloneToken(node.semicolon)); |
| directive.uriSource = node.uriSource; |
| directive.uriContent = node.uriContent; |
| return directive; |
| } |
| |
| @override |
| PartOfDirective visitPartOfDirective(PartOfDirective node) => |
| astFactory.partOfDirective( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.partKeyword), |
| cloneToken(node.ofKeyword), |
| cloneNode(node.uri), |
| cloneNode(node.libraryName), |
| cloneToken(node.semicolon)); |
| |
| @override |
| PostfixExpression visitPostfixExpression(PostfixExpression node) => astFactory |
| .postfixExpression(cloneNode(node.operand), cloneToken(node.operator)); |
| |
| @override |
| PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) => |
| astFactory.prefixedIdentifier(cloneNode(node.prefix), |
| cloneToken(node.period), cloneNode(node.identifier)); |
| |
| @override |
| PrefixExpression visitPrefixExpression(PrefixExpression node) => astFactory |
| .prefixExpression(cloneToken(node.operator), cloneNode(node.operand)); |
| |
| @override |
| PropertyAccess visitPropertyAccess(PropertyAccess node) => |
| astFactory.propertyAccess(cloneNode(node.target), |
| cloneToken(node.operator), cloneNode(node.propertyName)); |
| |
| @override |
| RedirectingConstructorInvocation visitRedirectingConstructorInvocation( |
| RedirectingConstructorInvocation node) => |
| astFactory.redirectingConstructorInvocation( |
| cloneToken(node.thisKeyword), |
| cloneToken(node.period), |
| cloneNode(node.constructorName), |
| cloneNode(node.argumentList)); |
| |
| @override |
| RethrowExpression visitRethrowExpression(RethrowExpression node) => |
| astFactory.rethrowExpression(cloneToken(node.rethrowKeyword)); |
| |
| @override |
| ReturnStatement visitReturnStatement(ReturnStatement node) => |
| astFactory.returnStatement(cloneToken(node.returnKeyword), |
| cloneNode(node.expression), cloneToken(node.semicolon)); |
| |
| @override |
| ScriptTag visitScriptTag(ScriptTag node) => |
| astFactory.scriptTag(cloneToken(node.scriptTag)); |
| |
| @override |
| ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory |
| .showCombinator(cloneToken(node.keyword), cloneNodeList(node.shownNames)); |
| |
| @override |
| SimpleFormalParameter visitSimpleFormalParameter( |
| SimpleFormalParameter node) => |
| astFactory.simpleFormalParameter2( |
| comment: cloneNode(node.documentationComment), |
| metadata: cloneNodeList(node.metadata), |
| covariantKeyword: cloneToken(node.covariantKeyword), |
| keyword: cloneToken(node.keyword), |
| type: cloneNode(node.type), |
| identifier: cloneNode(node.identifier)); |
| |
| @override |
| SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) => |
| astFactory.simpleIdentifier(cloneToken(node.token), |
| isDeclaration: node.inDeclarationContext()); |
| |
| @override |
| SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) => |
| astFactory.simpleStringLiteral(cloneToken(node.literal), node.value); |
| |
| @override |
| StringInterpolation visitStringInterpolation(StringInterpolation node) => |
| astFactory.stringInterpolation(cloneNodeList(node.elements)); |
| |
| @override |
| SuperConstructorInvocation visitSuperConstructorInvocation( |
| SuperConstructorInvocation node) => |
| astFactory.superConstructorInvocation( |
| cloneToken(node.superKeyword), |
| cloneToken(node.period), |
| cloneNode(node.constructorName), |
| cloneNode(node.argumentList)); |
| |
| @override |
| SuperExpression visitSuperExpression(SuperExpression node) => |
| astFactory.superExpression(cloneToken(node.superKeyword)); |
| |
| @override |
| SwitchCase visitSwitchCase(SwitchCase node) => astFactory.switchCase( |
| cloneNodeList(node.labels), |
| cloneToken(node.keyword), |
| cloneNode(node.expression), |
| cloneToken(node.colon), |
| cloneNodeList(node.statements)); |
| |
| @override |
| SwitchDefault visitSwitchDefault(SwitchDefault node) => |
| astFactory.switchDefault( |
| cloneNodeList(node.labels), |
| cloneToken(node.keyword), |
| cloneToken(node.colon), |
| cloneNodeList(node.statements)); |
| |
| @override |
| SwitchStatement visitSwitchStatement(SwitchStatement node) => |
| astFactory.switchStatement( |
| cloneToken(node.switchKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.expression), |
| cloneToken(node.rightParenthesis), |
| cloneToken(node.leftBracket), |
| cloneNodeList(node.members), |
| cloneToken(node.rightBracket)); |
| |
| @override |
| SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => |
| astFactory.symbolLiteral( |
| cloneToken(node.poundSign), cloneTokenList(node.components)); |
| |
| @override |
| ThisExpression visitThisExpression(ThisExpression node) => |
| astFactory.thisExpression(cloneToken(node.thisKeyword)); |
| |
| @override |
| ThrowExpression visitThrowExpression(ThrowExpression node) => |
| astFactory.throwExpression( |
| cloneToken(node.throwKeyword), cloneNode(node.expression)); |
| |
| @override |
| TopLevelVariableDeclaration visitTopLevelVariableDeclaration( |
| TopLevelVariableDeclaration node) => |
| astFactory.topLevelVariableDeclaration( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneNode(node.variables), |
| cloneToken(node.semicolon)); |
| |
| @override |
| TryStatement visitTryStatement(TryStatement node) => astFactory.tryStatement( |
| cloneToken(node.tryKeyword), |
| cloneNode(node.body), |
| cloneNodeList(node.catchClauses), |
| cloneToken(node.finallyKeyword), |
| cloneNode(node.finallyBlock)); |
| |
| @override |
| TypeArgumentList visitTypeArgumentList(TypeArgumentList node) => |
| astFactory.typeArgumentList(cloneToken(node.leftBracket), |
| cloneNodeList(node.arguments), cloneToken(node.rightBracket)); |
| |
| @override |
| TypeName visitTypeName(TypeName node) => |
| astFactory.typeName(cloneNode(node.name), cloneNode(node.typeArguments)); |
| |
| @override |
| TypeParameter visitTypeParameter(TypeParameter node) => |
| astFactory.typeParameter( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneNode(node.name), |
| cloneToken(node.extendsKeyword), |
| cloneNode(node.bound)); |
| |
| @override |
| TypeParameterList visitTypeParameterList(TypeParameterList node) => |
| astFactory.typeParameterList(cloneToken(node.leftBracket), |
| cloneNodeList(node.typeParameters), cloneToken(node.rightBracket)); |
| |
| @override |
| VariableDeclaration visitVariableDeclaration(VariableDeclaration node) => |
| astFactory.variableDeclaration(cloneNode(node.name), |
| cloneToken(node.equals), cloneNode(node.initializer)); |
| |
| @override |
| VariableDeclarationList visitVariableDeclarationList( |
| VariableDeclarationList node) => |
| astFactory.variableDeclarationList( |
| cloneNode(node.documentationComment), |
| cloneNodeList(node.metadata), |
| cloneToken(node.keyword), |
| cloneNode(node.type), |
| cloneNodeList(node.variables)); |
| |
| @override |
| VariableDeclarationStatement visitVariableDeclarationStatement( |
| VariableDeclarationStatement node) => |
| astFactory.variableDeclarationStatement( |
| cloneNode(node.variables), cloneToken(node.semicolon)); |
| |
| @override |
| WhileStatement visitWhileStatement(WhileStatement node) => |
| astFactory.whileStatement( |
| cloneToken(node.whileKeyword), |
| cloneToken(node.leftParenthesis), |
| cloneNode(node.condition), |
| cloneToken(node.rightParenthesis), |
| cloneNode(node.body)); |
| |
| @override |
| WithClause visitWithClause(WithClause node) => astFactory.withClause( |
| cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes)); |
| |
| @override |
| YieldStatement visitYieldStatement(YieldStatement node) => |
| astFactory.yieldStatement( |
| cloneToken(node.yieldKeyword), |
| cloneToken(node.star), |
| cloneNode(node.expression), |
| cloneToken(node.semicolon)); |
| |
| /** |
| * Clone all token starting from the given [token] up to a token that has |
| * offset greater then [stopAfter], and put mapping from originals to clones |
| * into [_clonedTokens]. |
| * |
| * We cannot clone tokens as we visit nodes because not every token is a part |
| * of a node, E.g. commas in argument lists are not represented in AST. But |
| * we need to the sequence of tokens that is identical to the original one. |
| */ |
| void _cloneTokens(Token token, int stopAfter) { |
| if (token == null) { |
| return; |
| } |
| Token nonComment(Token token) { |
| return token is CommentToken ? token.parent : token; |
| } |
| |
| token = nonComment(token); |
| if (_lastCloned == null) { |
| _lastCloned = new Token(TokenType.EOF, -1); |
| _lastCloned.setNext(_lastCloned); |
| } |
| while (token != null) { |
| Token clone = token.copy(); |
| { |
| CommentToken c1 = token.precedingComments; |
| CommentToken c2 = clone.precedingComments; |
| while (c1 != null && c2 != null) { |
| _clonedTokens[c1] = c2; |
| if (c1 is DocumentationCommentToken && |
| c2 is DocumentationCommentToken) { |
| for (int i = 0; i < c1.references.length; i++) { |
| _clonedTokens[c1.references[i]] = c2.references[i]; |
| } |
| } |
| c1 = c1.next; |
| c2 = c2.next; |
| } |
| } |
| _clonedTokens[token] = clone; |
| _lastCloned.setNext(clone); |
| _lastCloned = clone; |
| if (token.type == TokenType.EOF) { |
| break; |
| } |
| if (token.offset > stopAfter) { |
| _nextToClone = token.next; |
| _lastClonedOffset = token.offset; |
| break; |
| } |
| token = token.next; |
| } |
| } |
| |
| /** |
| * Return a clone of the given [node]. |
| */ |
| static AstNode clone(AstNode node) { |
| return node.accept(new AstCloner()); |
| } |
| } |
| |
| /** |
| * An AstVisitor that compares the structure of two AstNodes to see whether they |
| * are equal. |
| */ |
| class AstComparator implements AstVisitor<bool> { |
| /** |
| * The AST node with which the node being visited is to be compared. This is |
| * only valid at the beginning of each visit method (until [isEqualNodes] is |
| * invoked). |
| */ |
| AstNode _other; |
| |
| /** |
| * Notify that [first] and second have different length. |
| * This implementation returns `false`. Subclasses can override and throw. |
| */ |
| bool failDifferentLength(List first, List second) { |
| return false; |
| } |
| |
| /** |
| * Check whether [second] is null. Subclasses can override to throw. |
| */ |
| bool failIfNotNull(Object first, Object second) { |
| return second == null; |
| } |
| |
| /** |
| * Notify that [first] is not `null` while [second] one is `null`. |
| * This implementation returns `false`. Subclasses can override and throw. |
| */ |
| bool failIsNull(Object first, Object second) { |
| return false; |
| } |
| |
| /** |
| * Notify that [first] and [second] have different types. |
| * This implementation returns `false`. Subclasses can override and throw. |
| */ |
| bool failRuntimeType(Object first, Object second) { |
| return false; |
| } |
| |
| /** |
| * Return `true` if the [first] node and the [second] node have the same |
| * structure. |
| * |
| * *Note:* This method is only visible for testing purposes and should not be |
| * used by clients. |
| */ |
| bool isEqualNodes(AstNode first, AstNode second) { |
| if (first == null) { |
| return failIfNotNull(first, second); |
| } else if (second == null) { |
| return failIsNull(first, second); |
| } else if (first.runtimeType != second.runtimeType) { |
| return failRuntimeType(first, second); |
| } |
| _other = second; |
| return first.accept(this); |
| } |
| |
| /** |
| * Return `true` if the [first] token and the [second] token have the same |
| * structure. |
| * |
| * *Note:* This method is only visible for testing purposes and should not be |
| * used by clients. |
| */ |
| bool isEqualTokens(Token first, Token second) { |
| if (first == null) { |
| return failIfNotNull(first, second); |
| } else if (second == null) { |
| return failIsNull(first, second); |
| } else if (identical(first, second)) { |
| return true; |
| } |
| return isEqualTokensNotNull(first, second); |
| } |
| |
| /** |
| * Return `true` if the [first] token and the [second] token have the same |
| * structure. Both [first] and [second] are not `null`. |
| */ |
| bool isEqualTokensNotNull(Token first, Token second) => |
| first.offset == second.offset && |
| first.length == second.length && |
| first.lexeme == second.lexeme; |
| |
| @override |
| bool visitAdjacentStrings(AdjacentStrings node) { |
| AdjacentStrings other = _other as AdjacentStrings; |
| return _isEqualNodeLists(node.strings, other.strings); |
| } |
| |
| @override |
| bool visitAnnotation(Annotation node) { |
| Annotation other = _other as Annotation; |
| return isEqualTokens(node.atSign, other.atSign) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.constructorName, other.constructorName) && |
| isEqualNodes(node.arguments, other.arguments); |
| } |
| |
| @override |
| bool visitArgumentList(ArgumentList node) { |
| ArgumentList other = _other as ArgumentList; |
| return isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| _isEqualNodeLists(node.arguments, other.arguments) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis); |
| } |
| |
| @override |
| bool visitAsExpression(AsExpression node) { |
| AsExpression other = _other as AsExpression; |
| return isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.asOperator, other.asOperator) && |
| isEqualNodes(node.type, other.type); |
| } |
| |
| @override |
| bool visitAssertInitializer(AssertInitializer node) { |
| AssertStatement other = _other as AssertStatement; |
| return isEqualTokens(node.assertKeyword, other.assertKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.comma, other.comma) && |
| isEqualNodes(node.message, other.message) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis); |
| } |
| |
| @override |
| bool visitAssertStatement(AssertStatement node) { |
| AssertStatement other = _other as AssertStatement; |
| return isEqualTokens(node.assertKeyword, other.assertKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.comma, other.comma) && |
| isEqualNodes(node.message, other.message) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitAssignmentExpression(AssignmentExpression node) { |
| AssignmentExpression other = _other as AssignmentExpression; |
| return isEqualNodes(node.leftHandSide, other.leftHandSide) && |
| isEqualTokens(node.operator, other.operator) && |
| isEqualNodes(node.rightHandSide, other.rightHandSide); |
| } |
| |
| @override |
| bool visitAwaitExpression(AwaitExpression node) { |
| AwaitExpression other = _other as AwaitExpression; |
| return isEqualTokens(node.awaitKeyword, other.awaitKeyword) && |
| isEqualNodes(node.expression, other.expression); |
| } |
| |
| @override |
| bool visitBinaryExpression(BinaryExpression node) { |
| BinaryExpression other = _other as BinaryExpression; |
| return isEqualNodes(node.leftOperand, other.leftOperand) && |
| isEqualTokens(node.operator, other.operator) && |
| isEqualNodes(node.rightOperand, other.rightOperand); |
| } |
| |
| @override |
| bool visitBlock(Block node) { |
| Block other = _other as Block; |
| return isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.statements, other.statements) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitBlockFunctionBody(BlockFunctionBody node) { |
| BlockFunctionBody other = _other as BlockFunctionBody; |
| return isEqualNodes(node.block, other.block); |
| } |
| |
| @override |
| bool visitBooleanLiteral(BooleanLiteral node) { |
| BooleanLiteral other = _other as BooleanLiteral; |
| return isEqualTokens(node.literal, other.literal) && |
| node.value == other.value; |
| } |
| |
| @override |
| bool visitBreakStatement(BreakStatement node) { |
| BreakStatement other = _other as BreakStatement; |
| return isEqualTokens(node.breakKeyword, other.breakKeyword) && |
| isEqualNodes(node.label, other.label) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitCascadeExpression(CascadeExpression node) { |
| CascadeExpression other = _other as CascadeExpression; |
| return isEqualNodes(node.target, other.target) && |
| _isEqualNodeLists(node.cascadeSections, other.cascadeSections); |
| } |
| |
| @override |
| bool visitCatchClause(CatchClause node) { |
| CatchClause other = _other as CatchClause; |
| return isEqualTokens(node.onKeyword, other.onKeyword) && |
| isEqualNodes(node.exceptionType, other.exceptionType) && |
| isEqualTokens(node.catchKeyword, other.catchKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.exceptionParameter, other.exceptionParameter) && |
| isEqualTokens(node.comma, other.comma) && |
| isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitClassDeclaration(ClassDeclaration node) { |
| ClassDeclaration other = _other as ClassDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.abstractKeyword, other.abstractKeyword) && |
| isEqualTokens(node.classKeyword, other.classKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.typeParameters, other.typeParameters) && |
| isEqualNodes(node.extendsClause, other.extendsClause) && |
| isEqualNodes(node.withClause, other.withClause) && |
| isEqualNodes(node.implementsClause, other.implementsClause) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.members, other.members) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitClassTypeAlias(ClassTypeAlias node) { |
| ClassTypeAlias other = _other as ClassTypeAlias; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.typedefKeyword, other.typedefKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.typeParameters, other.typeParameters) && |
| isEqualTokens(node.equals, other.equals) && |
| isEqualTokens(node.abstractKeyword, other.abstractKeyword) && |
| isEqualNodes(node.superclass, other.superclass) && |
| isEqualNodes(node.withClause, other.withClause) && |
| isEqualNodes(node.implementsClause, other.implementsClause) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitComment(Comment node) { |
| Comment other = _other as Comment; |
| return _isEqualNodeLists(node.references, other.references); |
| } |
| |
| @override |
| bool visitCommentReference(CommentReference node) { |
| CommentReference other = _other as CommentReference; |
| return isEqualTokens(node.newKeyword, other.newKeyword) && |
| isEqualNodes(node.identifier, other.identifier); |
| } |
| |
| @override |
| bool visitCompilationUnit(CompilationUnit node) { |
| CompilationUnit other = _other as CompilationUnit; |
| return isEqualTokens(node.beginToken, other.beginToken) && |
| isEqualNodes(node.scriptTag, other.scriptTag) && |
| _isEqualNodeLists(node.directives, other.directives) && |
| _isEqualNodeLists(node.declarations, other.declarations) && |
| isEqualTokens(node.endToken, other.endToken); |
| } |
| |
| @override |
| bool visitConditionalExpression(ConditionalExpression node) { |
| ConditionalExpression other = _other as ConditionalExpression; |
| return isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.question, other.question) && |
| isEqualNodes(node.thenExpression, other.thenExpression) && |
| isEqualTokens(node.colon, other.colon) && |
| isEqualNodes(node.elseExpression, other.elseExpression); |
| } |
| |
| @override |
| bool visitConfiguration(Configuration node) { |
| Configuration other = _other as Configuration; |
| return isEqualTokens(node.ifKeyword, other.ifKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.equalToken, other.equalToken) && |
| isEqualNodes(node.value, other.value) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.uri, other.uri); |
| } |
| |
| @override |
| bool visitConstructorDeclaration(ConstructorDeclaration node) { |
| ConstructorDeclaration other = _other as ConstructorDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.externalKeyword, other.externalKeyword) && |
| isEqualTokens(node.constKeyword, other.constKeyword) && |
| isEqualTokens(node.factoryKeyword, other.factoryKeyword) && |
| isEqualNodes(node.returnType, other.returnType) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.parameters, other.parameters) && |
| isEqualTokens(node.separator, other.separator) && |
| _isEqualNodeLists(node.initializers, other.initializers) && |
| isEqualNodes(node.redirectedConstructor, other.redirectedConstructor) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| ConstructorFieldInitializer other = _other as ConstructorFieldInitializer; |
| return isEqualTokens(node.thisKeyword, other.thisKeyword) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.fieldName, other.fieldName) && |
| isEqualTokens(node.equals, other.equals) && |
| isEqualNodes(node.expression, other.expression); |
| } |
| |
| @override |
| bool visitConstructorName(ConstructorName node) { |
| ConstructorName other = _other as ConstructorName; |
| return isEqualNodes(node.type, other.type) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.name, other.name); |
| } |
| |
| @override |
| bool visitContinueStatement(ContinueStatement node) { |
| ContinueStatement other = _other as ContinueStatement; |
| return isEqualTokens(node.continueKeyword, other.continueKeyword) && |
| isEqualNodes(node.label, other.label) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitDeclaredIdentifier(DeclaredIdentifier node) { |
| DeclaredIdentifier other = _other as DeclaredIdentifier; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.type, other.type) && |
| isEqualNodes(node.identifier, other.identifier); |
| } |
| |
| @override |
| bool visitDefaultFormalParameter(DefaultFormalParameter node) { |
| DefaultFormalParameter other = _other as DefaultFormalParameter; |
| return isEqualNodes(node.parameter, other.parameter) && |
| node.kind == other.kind && |
| isEqualTokens(node.separator, other.separator) && |
| isEqualNodes(node.defaultValue, other.defaultValue); |
| } |
| |
| @override |
| bool visitDoStatement(DoStatement node) { |
| DoStatement other = _other as DoStatement; |
| return isEqualTokens(node.doKeyword, other.doKeyword) && |
| isEqualNodes(node.body, other.body) && |
| isEqualTokens(node.whileKeyword, other.whileKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitDottedName(DottedName node) { |
| DottedName other = _other as DottedName; |
| return _isEqualNodeLists(node.components, other.components); |
| } |
| |
| @override |
| bool visitDoubleLiteral(DoubleLiteral node) { |
| DoubleLiteral other = _other as DoubleLiteral; |
| return isEqualTokens(node.literal, other.literal) && |
| node.value == other.value; |
| } |
| |
| @override |
| bool visitEmptyFunctionBody(EmptyFunctionBody node) { |
| EmptyFunctionBody other = _other as EmptyFunctionBody; |
| return isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitEmptyStatement(EmptyStatement node) { |
| EmptyStatement other = _other as EmptyStatement; |
| return isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitEnumConstantDeclaration(EnumConstantDeclaration node) { |
| EnumConstantDeclaration other = _other as EnumConstantDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualNodes(node.name, other.name); |
| } |
| |
| @override |
| bool visitEnumDeclaration(EnumDeclaration node) { |
| EnumDeclaration other = _other as EnumDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.enumKeyword, other.enumKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.constants, other.constants) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitExportDirective(ExportDirective node) { |
| ExportDirective other = _other as ExportDirective; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.uri, other.uri) && |
| _isEqualNodeLists(node.combinators, other.combinators) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| ExpressionFunctionBody other = _other as ExpressionFunctionBody; |
| return isEqualTokens(node.functionDefinition, other.functionDefinition) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitExpressionStatement(ExpressionStatement node) { |
| ExpressionStatement other = _other as ExpressionStatement; |
| return isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitExtendsClause(ExtendsClause node) { |
| ExtendsClause other = _other as ExtendsClause; |
| return isEqualTokens(node.extendsKeyword, other.extendsKeyword) && |
| isEqualNodes(node.superclass, other.superclass); |
| } |
| |
| @override |
| bool visitFieldDeclaration(FieldDeclaration node) { |
| FieldDeclaration other = _other as FieldDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.staticKeyword, other.staticKeyword) && |
| isEqualNodes(node.fields, other.fields) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitFieldFormalParameter(FieldFormalParameter node) { |
| FieldFormalParameter other = _other as FieldFormalParameter; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.type, other.type) && |
| isEqualTokens(node.thisKeyword, other.thisKeyword) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.identifier, other.identifier); |
| } |
| |
| @override |
| bool visitForEachStatement(ForEachStatement node) { |
| ForEachStatement other = _other as ForEachStatement; |
| return isEqualTokens(node.forKeyword, other.forKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.loopVariable, other.loopVariable) && |
| isEqualTokens(node.inKeyword, other.inKeyword) && |
| isEqualNodes(node.iterable, other.iterable) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitFormalParameterList(FormalParameterList node) { |
| FormalParameterList other = _other as FormalParameterList; |
| return isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| _isEqualNodeLists(node.parameters, other.parameters) && |
| isEqualTokens(node.leftDelimiter, other.leftDelimiter) && |
| isEqualTokens(node.rightDelimiter, other.rightDelimiter) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis); |
| } |
| |
| @override |
| bool visitForStatement(ForStatement node) { |
| ForStatement other = _other as ForStatement; |
| return isEqualTokens(node.forKeyword, other.forKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.variables, other.variables) && |
| isEqualNodes(node.initialization, other.initialization) && |
| isEqualTokens(node.leftSeparator, other.leftSeparator) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.rightSeparator, other.rightSeparator) && |
| _isEqualNodeLists(node.updaters, other.updaters) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitFunctionDeclaration(FunctionDeclaration node) { |
| FunctionDeclaration other = _other as FunctionDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.externalKeyword, other.externalKeyword) && |
| isEqualNodes(node.returnType, other.returnType) && |
| isEqualTokens(node.propertyKeyword, other.propertyKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.functionExpression, other.functionExpression); |
| } |
| |
| @override |
| bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { |
| FunctionDeclarationStatement other = _other as FunctionDeclarationStatement; |
| return isEqualNodes(node.functionDeclaration, other.functionDeclaration); |
| } |
| |
| @override |
| bool visitFunctionExpression(FunctionExpression node) { |
| FunctionExpression other = _other as FunctionExpression; |
| return isEqualNodes(node.parameters, other.parameters) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| FunctionExpressionInvocation other = _other as FunctionExpressionInvocation; |
| return isEqualNodes(node.function, other.function) && |
| isEqualNodes(node.argumentList, other.argumentList); |
| } |
| |
| @override |
| bool visitFunctionTypeAlias(FunctionTypeAlias node) { |
| FunctionTypeAlias other = _other as FunctionTypeAlias; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.typedefKeyword, other.typedefKeyword) && |
| isEqualNodes(node.returnType, other.returnType) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.typeParameters, other.typeParameters) && |
| isEqualNodes(node.parameters, other.parameters) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| FunctionTypedFormalParameter other = _other as FunctionTypedFormalParameter; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualNodes(node.returnType, other.returnType) && |
| isEqualNodes(node.identifier, other.identifier) && |
| isEqualNodes(node.parameters, other.parameters); |
| } |
| |
| @override |
| bool visitGenericFunctionType(GenericFunctionType node) { |
| GenericFunctionType other = _other as GenericFunctionType; |
| return isEqualNodes(node.returnType, other.returnType) && |
| isEqualTokens(node.functionKeyword, other.functionKeyword) && |
| isEqualNodes(node.typeParameters, other.typeParameters) && |
| isEqualNodes(node.parameters, other.parameters); |
| } |
| |
| @override |
| bool visitGenericTypeAlias(GenericTypeAlias node) { |
| GenericTypeAlias other = _other as GenericTypeAlias; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.typedefKeyword, other.typedefKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.typeParameters, other.typeParameters) && |
| isEqualTokens(node.equals, other.equals) && |
| isEqualNodes(node.functionType, other.functionType); |
| } |
| |
| @override |
| bool visitHideCombinator(HideCombinator node) { |
| HideCombinator other = _other as HideCombinator; |
| return isEqualTokens(node.keyword, other.keyword) && |
| _isEqualNodeLists(node.hiddenNames, other.hiddenNames); |
| } |
| |
| @override |
| bool visitIfStatement(IfStatement node) { |
| IfStatement other = _other as IfStatement; |
| return isEqualTokens(node.ifKeyword, other.ifKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.thenStatement, other.thenStatement) && |
| isEqualTokens(node.elseKeyword, other.elseKeyword) && |
| isEqualNodes(node.elseStatement, other.elseStatement); |
| } |
| |
| @override |
| bool visitImplementsClause(ImplementsClause node) { |
| ImplementsClause other = _other as ImplementsClause; |
| return isEqualTokens(node.implementsKeyword, other.implementsKeyword) && |
| _isEqualNodeLists(node.interfaces, other.interfaces); |
| } |
| |
| @override |
| bool visitImportDirective(ImportDirective node) { |
| ImportDirective other = _other as ImportDirective; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.uri, other.uri) && |
| isEqualTokens(node.deferredKeyword, other.deferredKeyword) && |
| isEqualTokens(node.asKeyword, other.asKeyword) && |
| isEqualNodes(node.prefix, other.prefix) && |
| _isEqualNodeLists(node.combinators, other.combinators) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitIndexExpression(IndexExpression node) { |
| IndexExpression other = _other as IndexExpression; |
| return isEqualNodes(node.target, other.target) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| isEqualNodes(node.index, other.index) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitInstanceCreationExpression(InstanceCreationExpression node) { |
| InstanceCreationExpression other = _other as InstanceCreationExpression; |
| return isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.constructorName, other.constructorName) && |
| isEqualNodes(node.argumentList, other.argumentList); |
| } |
| |
| @override |
| bool visitIntegerLiteral(IntegerLiteral node) { |
| IntegerLiteral other = _other as IntegerLiteral; |
| return isEqualTokens(node.literal, other.literal) && |
| (node.value == other.value); |
| } |
| |
| @override |
| bool visitInterpolationExpression(InterpolationExpression node) { |
| InterpolationExpression other = _other as InterpolationExpression; |
| return isEqualTokens(node.leftBracket, other.leftBracket) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitInterpolationString(InterpolationString node) { |
| InterpolationString other = _other as InterpolationString; |
| return isEqualTokens(node.contents, other.contents) && |
| node.value == other.value; |
| } |
| |
| @override |
| bool visitIsExpression(IsExpression node) { |
| IsExpression other = _other as IsExpression; |
| return isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.isOperator, other.isOperator) && |
| isEqualTokens(node.notOperator, other.notOperator) && |
| isEqualNodes(node.type, other.type); |
| } |
| |
| @override |
| bool visitLabel(Label node) { |
| Label other = _other as Label; |
| return isEqualNodes(node.label, other.label) && |
| isEqualTokens(node.colon, other.colon); |
| } |
| |
| @override |
| bool visitLabeledStatement(LabeledStatement node) { |
| LabeledStatement other = _other as LabeledStatement; |
| return _isEqualNodeLists(node.labels, other.labels) && |
| isEqualNodes(node.statement, other.statement); |
| } |
| |
| @override |
| bool visitLibraryDirective(LibraryDirective node) { |
| LibraryDirective other = _other as LibraryDirective; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.libraryKeyword, other.libraryKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitLibraryIdentifier(LibraryIdentifier node) { |
| LibraryIdentifier other = _other as LibraryIdentifier; |
| return _isEqualNodeLists(node.components, other.components); |
| } |
| |
| @override |
| bool visitListLiteral(ListLiteral node) { |
| ListLiteral other = _other as ListLiteral; |
| return isEqualTokens(node.constKeyword, other.constKeyword) && |
| isEqualNodes(node.typeArguments, other.typeArguments) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.elements, other.elements) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitMapLiteral(MapLiteral node) { |
| MapLiteral other = _other as MapLiteral; |
| return isEqualTokens(node.constKeyword, other.constKeyword) && |
| isEqualNodes(node.typeArguments, other.typeArguments) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.entries, other.entries) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitMapLiteralEntry(MapLiteralEntry node) { |
| MapLiteralEntry other = _other as MapLiteralEntry; |
| return isEqualNodes(node.key, other.key) && |
| isEqualTokens(node.separator, other.separator) && |
| isEqualNodes(node.value, other.value); |
| } |
| |
| @override |
| bool visitMethodDeclaration(MethodDeclaration node) { |
| MethodDeclaration other = _other as MethodDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.externalKeyword, other.externalKeyword) && |
| isEqualTokens(node.modifierKeyword, other.modifierKeyword) && |
| isEqualNodes(node.returnType, other.returnType) && |
| isEqualTokens(node.propertyKeyword, other.propertyKeyword) && |
| isEqualTokens(node.propertyKeyword, other.propertyKeyword) && |
| isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.parameters, other.parameters) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitMethodInvocation(MethodInvocation node) { |
| MethodInvocation other = _other as MethodInvocation; |
| return isEqualNodes(node.target, other.target) && |
| isEqualTokens(node.operator, other.operator) && |
| isEqualNodes(node.methodName, other.methodName) && |
| isEqualNodes(node.argumentList, other.argumentList); |
| } |
| |
| @override |
| bool visitNamedExpression(NamedExpression node) { |
| NamedExpression other = _other as NamedExpression; |
| return isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.expression, other.expression); |
| } |
| |
| @override |
| bool visitNativeClause(NativeClause node) { |
| NativeClause other = _other as NativeClause; |
| return isEqualTokens(node.nativeKeyword, other.nativeKeyword) && |
| isEqualNodes(node.name, other.name); |
| } |
| |
| @override |
| bool visitNativeFunctionBody(NativeFunctionBody node) { |
| NativeFunctionBody other = _other as NativeFunctionBody; |
| return isEqualTokens(node.nativeKeyword, other.nativeKeyword) && |
| isEqualNodes(node.stringLiteral, other.stringLiteral) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitNullLiteral(NullLiteral node) { |
| NullLiteral other = _other as NullLiteral; |
| return isEqualTokens(node.literal, other.literal); |
| } |
| |
| @override |
| bool visitParenthesizedExpression(ParenthesizedExpression node) { |
| ParenthesizedExpression other = _other as ParenthesizedExpression; |
| return isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis); |
| } |
| |
| @override |
| bool visitPartDirective(PartDirective node) { |
| PartDirective other = _other as PartDirective; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.partKeyword, other.partKeyword) && |
| isEqualNodes(node.uri, other.uri) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitPartOfDirective(PartOfDirective node) { |
| PartOfDirective other = _other as PartOfDirective; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.partKeyword, other.partKeyword) && |
| isEqualTokens(node.ofKeyword, other.ofKeyword) && |
| isEqualNodes(node.libraryName, other.libraryName) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitPostfixExpression(PostfixExpression node) { |
| PostfixExpression other = _other as PostfixExpression; |
| return isEqualNodes(node.operand, other.operand) && |
| isEqualTokens(node.operator, other.operator); |
| } |
| |
| @override |
| bool visitPrefixedIdentifier(PrefixedIdentifier node) { |
| PrefixedIdentifier other = _other as PrefixedIdentifier; |
| return isEqualNodes(node.prefix, other.prefix) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.identifier, other.identifier); |
| } |
| |
| @override |
| bool visitPrefixExpression(PrefixExpression node) { |
| PrefixExpression other = _other as PrefixExpression; |
| return isEqualTokens(node.operator, other.operator) && |
| isEqualNodes(node.operand, other.operand); |
| } |
| |
| @override |
| bool visitPropertyAccess(PropertyAccess node) { |
| PropertyAccess other = _other as PropertyAccess; |
| return isEqualNodes(node.target, other.target) && |
| isEqualTokens(node.operator, other.operator) && |
| isEqualNodes(node.propertyName, other.propertyName); |
| } |
| |
| @override |
| bool visitRedirectingConstructorInvocation( |
| RedirectingConstructorInvocation node) { |
| RedirectingConstructorInvocation other = |
| _other as RedirectingConstructorInvocation; |
| return isEqualTokens(node.thisKeyword, other.thisKeyword) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.constructorName, other.constructorName) && |
| isEqualNodes(node.argumentList, other.argumentList); |
| } |
| |
| @override |
| bool visitRethrowExpression(RethrowExpression node) { |
| RethrowExpression other = _other as RethrowExpression; |
| return isEqualTokens(node.rethrowKeyword, other.rethrowKeyword); |
| } |
| |
| @override |
| bool visitReturnStatement(ReturnStatement node) { |
| ReturnStatement other = _other as ReturnStatement; |
| return isEqualTokens(node.returnKeyword, other.returnKeyword) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitScriptTag(ScriptTag node) { |
| ScriptTag other = _other as ScriptTag; |
| return isEqualTokens(node.scriptTag, other.scriptTag); |
| } |
| |
| @override |
| bool visitShowCombinator(ShowCombinator node) { |
| ShowCombinator other = _other as ShowCombinator; |
| return isEqualTokens(node.keyword, other.keyword) && |
| _isEqualNodeLists(node.shownNames, other.shownNames); |
| } |
| |
| @override |
| bool visitSimpleFormalParameter(SimpleFormalParameter node) { |
| SimpleFormalParameter other = _other as SimpleFormalParameter; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.type, other.type) && |
| isEqualNodes(node.identifier, other.identifier); |
| } |
| |
| @override |
| bool visitSimpleIdentifier(SimpleIdentifier node) { |
| SimpleIdentifier other = _other as SimpleIdentifier; |
| return isEqualTokens(node.token, other.token); |
| } |
| |
| @override |
| bool visitSimpleStringLiteral(SimpleStringLiteral node) { |
| SimpleStringLiteral other = _other as SimpleStringLiteral; |
| return isEqualTokens(node.literal, other.literal) && |
| (node.value == other.value); |
| } |
| |
| @override |
| bool visitStringInterpolation(StringInterpolation node) { |
| StringInterpolation other = _other as StringInterpolation; |
| return _isEqualNodeLists(node.elements, other.elements); |
| } |
| |
| @override |
| bool visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| SuperConstructorInvocation other = _other as SuperConstructorInvocation; |
| return isEqualTokens(node.superKeyword, other.superKeyword) && |
| isEqualTokens(node.period, other.period) && |
| isEqualNodes(node.constructorName, other.constructorName) && |
| isEqualNodes(node.argumentList, other.argumentList); |
| } |
| |
| @override |
| bool visitSuperExpression(SuperExpression node) { |
| SuperExpression other = _other as SuperExpression; |
| return isEqualTokens(node.superKeyword, other.superKeyword); |
| } |
| |
| @override |
| bool visitSwitchCase(SwitchCase node) { |
| SwitchCase other = _other as SwitchCase; |
| return _isEqualNodeLists(node.labels, other.labels) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.colon, other.colon) && |
| _isEqualNodeLists(node.statements, other.statements); |
| } |
| |
| @override |
| bool visitSwitchDefault(SwitchDefault node) { |
| SwitchDefault other = _other as SwitchDefault; |
| return _isEqualNodeLists(node.labels, other.labels) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualTokens(node.colon, other.colon) && |
| _isEqualNodeLists(node.statements, other.statements); |
| } |
| |
| @override |
| bool visitSwitchStatement(SwitchStatement node) { |
| SwitchStatement other = _other as SwitchStatement; |
| return isEqualTokens(node.switchKeyword, other.switchKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.members, other.members) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitSymbolLiteral(SymbolLiteral node) { |
| SymbolLiteral other = _other as SymbolLiteral; |
| return isEqualTokens(node.poundSign, other.poundSign) && |
| _isEqualTokenLists(node.components, other.components); |
| } |
| |
| @override |
| bool visitThisExpression(ThisExpression node) { |
| ThisExpression other = _other as ThisExpression; |
| return isEqualTokens(node.thisKeyword, other.thisKeyword); |
| } |
| |
| @override |
| bool visitThrowExpression(ThrowExpression node) { |
| ThrowExpression other = _other as ThrowExpression; |
| return isEqualTokens(node.throwKeyword, other.throwKeyword) && |
| isEqualNodes(node.expression, other.expression); |
| } |
| |
| @override |
| bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| TopLevelVariableDeclaration other = _other as TopLevelVariableDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualNodes(node.variables, other.variables) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitTryStatement(TryStatement node) { |
| TryStatement other = _other as TryStatement; |
| return isEqualTokens(node.tryKeyword, other.tryKeyword) && |
| isEqualNodes(node.body, other.body) && |
| _isEqualNodeLists(node.catchClauses, other.catchClauses) && |
| isEqualTokens(node.finallyKeyword, other.finallyKeyword) && |
| isEqualNodes(node.finallyBlock, other.finallyBlock); |
| } |
| |
| @override |
| bool visitTypeArgumentList(TypeArgumentList node) { |
| TypeArgumentList other = _other as TypeArgumentList; |
| return isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.arguments, other.arguments) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitTypeName(TypeName node) { |
| TypeName other = _other as TypeName; |
| return isEqualNodes(node.name, other.name) && |
| isEqualNodes(node.typeArguments, other.typeArguments); |
| } |
| |
| @override |
| bool visitTypeParameter(TypeParameter node) { |
| TypeParameter other = _other as TypeParameter; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.extendsKeyword, other.extendsKeyword) && |
| isEqualNodes(node.bound, other.bound); |
| } |
| |
| @override |
| bool visitTypeParameterList(TypeParameterList node) { |
| TypeParameterList other = _other as TypeParameterList; |
| return isEqualTokens(node.leftBracket, other.leftBracket) && |
| _isEqualNodeLists(node.typeParameters, other.typeParameters) && |
| isEqualTokens(node.rightBracket, other.rightBracket); |
| } |
| |
| @override |
| bool visitVariableDeclaration(VariableDeclaration node) { |
| VariableDeclaration other = _other as VariableDeclaration; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualNodes(node.name, other.name) && |
| isEqualTokens(node.equals, other.equals) && |
| isEqualNodes(node.initializer, other.initializer); |
| } |
| |
| @override |
| bool visitVariableDeclarationList(VariableDeclarationList node) { |
| VariableDeclarationList other = _other as VariableDeclarationList; |
| return isEqualNodes( |
| node.documentationComment, other.documentationComment) && |
| _isEqualNodeLists(node.metadata, other.metadata) && |
| isEqualTokens(node.keyword, other.keyword) && |
| isEqualNodes(node.type, other.type) && |
| _isEqualNodeLists(node.variables, other.variables); |
| } |
| |
| @override |
| bool visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| VariableDeclarationStatement other = _other as VariableDeclarationStatement; |
| return isEqualNodes(node.variables, other.variables) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| @override |
| bool visitWhileStatement(WhileStatement node) { |
| WhileStatement other = _other as WhileStatement; |
| return isEqualTokens(node.whileKeyword, other.whileKeyword) && |
| isEqualTokens(node.leftParenthesis, other.leftParenthesis) && |
| isEqualNodes(node.condition, other.condition) && |
| isEqualTokens(node.rightParenthesis, other.rightParenthesis) && |
| isEqualNodes(node.body, other.body); |
| } |
| |
| @override |
| bool visitWithClause(WithClause node) { |
| WithClause other = _other as WithClause; |
| return isEqualTokens(node.withKeyword, other.withKeyword) && |
| _isEqualNodeLists(node.mixinTypes, other.mixinTypes); |
| } |
| |
| @override |
| bool visitYieldStatement(YieldStatement node) { |
| YieldStatement other = _other as YieldStatement; |
| return isEqualTokens(node.yieldKeyword, other.yieldKeyword) && |
| isEqualNodes(node.expression, other.expression) && |
| isEqualTokens(node.semicolon, other.semicolon); |
| } |
| |
| /** |
| * Return `true` if the [first] and [second] lists of AST nodes have the same |
| * size and corresponding elements are equal. |
| */ |
| bool _isEqualNodeLists(NodeList first, NodeList second) { |
| if (first == null) { |
| return failIfNotNull(first, second); |
| } else if (second == null) { |
| return failIsNull(first, second); |
| } |
| int size = first.length; |
| if (second.length != size) { |
| return failDifferentLength(first, second); |
| } |
| for (int i = 0; i < size; i++) { |
| if (!isEqualNodes(first[i], second[i])) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Return `true` if the [first] and [second] lists of tokens have the same |
| * length and corresponding elements are equal. |
| */ |
| bool _isEqualTokenLists(List<Token> first, List<Token> second) { |
| int length = first.length; |
| if (second.length != length) { |
| return failDifferentLength(first, second); |
| } |
| for (int i = 0; i < length; i++) { |
| if (!isEqualTokens(first[i], second[i])) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Return `true` if the [first] and [second] nodes are equal. |
| */ |
| static bool equalNodes(AstNode first, AstNode second) { |
| AstComparator comparator = new AstComparator(); |
| return comparator.isEqualNodes(first, second); |
| } |
| } |
| |
| /** |
| * Instances of the class [ConstantEvaluator] evaluate constant expressions to |
| * produce their compile-time value. |
| * |
| * According to the Dart Language Specification: |
| * |
| * > A constant expression is one of the following: |
| * > |
| * > * A literal number. |
| * > * A literal boolean. |
| * > * A literal string where any interpolated expression is a compile-time |
| * > constant that evaluates to a numeric, string or boolean value or to |
| * > **null**. |
| * > * A literal symbol. |
| * > * **null**. |
| * > * A qualified reference to a static constant variable. |
| * > * An identifier expression that denotes a constant variable, class or type |
| * > alias. |
| * > * A constant constructor invocation. |
| * > * A constant list literal. |
| * > * A constant map literal. |
| * > * A simple or qualified identifier denoting a top-level function or a |
| * > static method. |
| * > * A parenthesized expression _(e)_ where _e_ is a constant expression. |
| * > * <span> |
| * > An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> |
| * > where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant |
| * > expressions and <i>identical()</i> is statically bound to the predefined |
| * > dart function <i>identical()</i> discussed above. |
| * > </span> |
| * > * <span> |
| * > An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> |
| * > or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and |
| * > <i>e<sub>2</sub></i> are constant expressions that evaluate to a |
| * > numeric, string or boolean value. |
| * > </span> |
| * > * <span> |
| * > An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> && |
| * > e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where |
| * > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant |
| * > expressions that evaluate to a boolean value. |
| * > </span> |
| * > * <span> |
| * > An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ |
| * > e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>, |
| * > <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >> |
| * > e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where |
| * > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant |
| * > expressions that evaluate to an integer value or to <b>null</b>. |
| * > </span> |
| * > * <span> |
| * > An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> |
| * > -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, |
| * > <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ |
| * > e<sub>2</sub></i>, <i>e<sub>1</sub> > e<sub>2</sub></i>, |
| * > <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >= |
| * > e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or |
| * > <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, |
| * > <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions |
| * > that evaluate to a numeric value or to <b>null</b>. |
| * > </span> |
| * > * <span> |
| * > An expression of one the form <i>e<sub>1</sub> + e<sub>2</sub></i>, |
| * > <i>e<sub>1</sub> -e<sub>2</sub></i> where <i>e<sub>1</sub> and |
| * > e<sub>2</sub></i> are constant expressions that evaluate to a numeric or |
| * > string value or to <b>null</b>. |
| * > </span> |
| * > * <span> |
| * > An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : |
| * > e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and |
| * > <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i> |
| * > evaluates to a boolean value. |
| * > </span> |
| * |
| * However, this comment is now at least a little bit out of sync with the spec. |
| * |
| * The values returned by instances of this class are therefore `null` and |
| * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and |
| * `DartObject`. |
| * |
| * In addition, this class defines several values that can be returned to |
| * indicate various conditions encountered during evaluation. These are |
| * documented with the static fields that define those values. |
| */ |
| class ConstantEvaluator extends GeneralizingAstVisitor<Object> { |
| /** |
| * The value returned for expressions (or non-expression nodes) that are not |
| * compile-time constant expressions. |
| */ |
| static Object NOT_A_CONSTANT = new Object(); |
| |
| @override |
| Object visitAdjacentStrings(AdjacentStrings node) { |
| StringBuffer buffer = new StringBuffer(); |
| for (StringLiteral string in node.strings) { |
| Object value = string.accept(this); |
| if (identical(value, NOT_A_CONSTANT)) { |
| return value; |
| } |
| buffer.write(value); |
| } |
| return buffer.toString(); |
| } |
| |
| @override |
| Object visitBinaryExpression(BinaryExpression node) { |
| Object leftOperand = node.leftOperand.accept(this); |
| if (identical(leftOperand, NOT_A_CONSTANT)) { |
| return leftOperand; |
| } |
| Object rightOperand = node.rightOperand.accept(this); |
| if (identical(rightOperand, NOT_A_CONSTANT)) { |
| return rightOperand; |
| } |
| while (true) { |
| if (node.operator.type == TokenType.AMPERSAND) { |
| // integer or {@code null} |
| if (leftOperand is int && rightOperand is int) { |
| return leftOperand & rightOperand; |
| } |
| } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) { |
| // boolean or {@code null} |
| if (leftOperand is bool && rightOperand is bool) { |
| return leftOperand && rightOperand; |
| } |
| } else if (node.operator.type == TokenType.BANG_EQ) { |
| // numeric, string, boolean, or {@code null} |
| if (leftOperand is bool && rightOperand is bool) { |
| return leftOperand != rightOperand; |
| } else if (leftOperand is num && rightOperand is num) { |
| return leftOperand != rightOperand; |
| } else if (leftOperand is String && rightOperand is String) { |
| return leftOperand != rightOperand; |
| } |
| } else if (node.operator.type == TokenType.BAR) { |
| // integer or {@code null} |
| if (leftOperand is int && rightOperand is int) { |
| return leftOperand | rightOperand; |
| } |
| } else if (node.operator.type == TokenType.BAR_BAR) { |
| // boolean or {@code null} |
| if (leftOperand is bool && rightOperand is bool) { |
| return leftOperand || rightOperand; |
| } |
| } else if (node.operator.type == TokenType.CARET) { |
| // integer or {@code null} |
| if (leftOperand is int && rightOperand is int) { |
| return leftOperand ^ rightOperand; |
| } |
| } else if (node.operator.type == TokenType.EQ_EQ) { |
| // numeric, string, boolean, or {@code null} |
| if (leftOperand is bool && rightOperand is bool) { |
| return leftOperand == rightOperand; |
| } else if (leftOperand is num && rightOperand is num) { |
| return leftOperand == rightOperand; |
| } else if (leftOperand is String && rightOperand is String) { |
| return leftOperand == rightOperand; |
| } |
| } else if (node.operator.type == TokenType.GT) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand.compareTo(rightOperand) > 0; |
| } |
| } else if (node.operator.type == TokenType.GT_EQ) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand.compareTo(rightOperand) >= 0; |
| } |
| } else if (node.operator.type == TokenType.GT_GT) { |
| // integer or {@code null} |
| if (leftOperand is int && rightOperand is int) { |
| return leftOperand >> rightOperand; |
| } |
| } else if (node.operator.type == TokenType.LT) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand.compareTo(rightOperand) < 0; |
| } |
| } else if (node.operator.type == TokenType.LT_EQ) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand.compareTo(rightOperand) <= 0; |
| } |
| } else if (node.operator.type == TokenType.LT_LT) { |
| // integer or {@code null} |
| if (leftOperand is int && rightOperand is int) { |
| return leftOperand << rightOperand; |
| } |
| } else if (node.operator.type == TokenType.MINUS) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand - rightOperand; |
| } |
| } else if (node.operator.type == TokenType.PERCENT) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand.remainder(rightOperand); |
| } |
| } else if (node.operator.type == TokenType.PLUS) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand + rightOperand; |
| } |
| if (leftOperand is String && rightOperand is String) { |
| return leftOperand + rightOperand; |
| } |
| } else if (node.operator.type == TokenType.STAR) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand * rightOperand; |
| } |
| } else if (node.operator.type == TokenType.SLASH) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand / rightOperand; |
| } |
| } else if (node.operator.type == TokenType.TILDE_SLASH) { |
| // numeric or {@code null} |
| if (leftOperand is num && rightOperand is num) { |
| return leftOperand ~/ rightOperand; |
| } |
| } |
| break; |
| } |
| // TODO(brianwilkerson) This doesn't handle numeric conversions. |
| return visitExpression(node); |
| } |
| |
| @override |
| Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false; |
| |
| @override |
| Object visitDoubleLiteral(DoubleLiteral node) => node.value; |
| |
| @override |
| Object visitIntegerLiteral(IntegerLiteral node) => node.value; |
| |
| @override |
| Object visitInterpolationExpression(InterpolationExpression node) { |
| Object value = node.expression.accept(this); |
| if (value == null || value is bool || value is String || value is num) { |
| return value; |
| } |
| return NOT_A_CONSTANT; |
| } |
| |
| @override |
| Object visitInterpolationString(InterpolationString node) => node.value; |
| |
| @override |
| Object visitListLiteral(ListLiteral node) { |
| List<Object> list = new List<Object>(); |
| for (Expression element in node.elements) { |
| Object value = element.accept(this); |
| if (identical(value, NOT_A_CONSTANT)) { |
| return value; |
| } |
| list.add(value); |
| } |
| return list; |
| } |
| |
| @override |
| Object visitMapLiteral(MapLiteral node) { |
| HashMap<String, Object> map = new HashMap<String, Object>(); |
| for (MapLiteralEntry entry in node.entries) { |
| Object key = entry.key.accept(this); |
| Object value = entry.value.accept(this); |
| if (key is String && !identical(value, NOT_A_CONSTANT)) { |
| map[key] = value; |
| } else { |
| return NOT_A_CONSTANT; |
| } |
| } |
| return map; |
| } |
| |
| @override |
| Object visitMethodInvocation(MethodInvocation node) => visitNode(node); |
| |
| @override |
| Object visitNode(AstNode node) => NOT_A_CONSTANT; |
| |
| @override |
| Object visitNullLiteral(NullLiteral node) => null; |
| |
| @override |
| Object visitParenthesizedExpression(ParenthesizedExpression node) => |
| node.expression.accept(this); |
| |
| @override |
| Object visitPrefixedIdentifier(PrefixedIdentifier node) => |
| _getConstantValue(null); |
| |
| @override |
| Object visitPrefixExpression(PrefixExpression node) { |
| Object operand = node.operand.accept(this); |
| if (identical(operand, NOT_A_CONSTANT)) { |
| return operand; |
| } |
| while (true) { |
| if (node.operator.type == TokenType.BANG) { |
| if (identical(operand, true)) { |
| return false; |
| } else if (identical(operand, false)) { |
| return true; |
| } |
| } else if (node.operator.type == TokenType.TILDE) { |
| if (operand is int) { |
| return ~operand; |
| } |
| } else if (node.operator.type == TokenType.MINUS) { |
| if (operand == null) { |
| return null; |
| } else if (operand is num) { |
| return -operand; |
| } |
| } else {} |
| break; |
| } |
| return NOT_A_CONSTANT; |
| } |
| |
| @override |
| Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null); |
| |
| @override |
| Object visitSimpleIdentifier(SimpleIdentifier node) => |
| _getConstantValue(null); |
| |
| @override |
| Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value; |
| |
| @override |
| Object visitStringInterpolation(StringInterpolation node) { |
| StringBuffer buffer = new StringBuffer(); |
| for (InterpolationElement element in node.elements) { |
| Object value = element.accept(this); |
| if (identical(value, NOT_A_CONSTANT)) { |
| return value; |
| } |
| buffer.write(value); |
| } |
| return buffer.toString(); |
| } |
| |
| @override |
| Object visitSymbolLiteral(SymbolLiteral node) { |
| // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String. |
| StringBuffer buffer = new StringBuffer(); |
| for (Token component in node.components) { |
| if (buffer.length > 0) { |
| buffer.writeCharCode(0x2E); |
| } |
| buffer.write(component.lexeme); |
| } |
| return buffer.toString(); |
| } |
| |
| /** |
| * Return the constant value of the static constant represented by the given |
| * [element]. |
| */ |
| Object _getConstantValue(Element element) { |
| // TODO(brianwilkerson) Implement this |
| // if (element is FieldElement) { |
| // FieldElement field = element; |
| // if (field.isStatic && field.isConst) { |
| // //field.getConstantValue(); |
| // } |
| // // } else if (element instanceof VariableElement) { |
| // // VariableElement variable = (VariableElement) element; |
| // // if (variable.isStatic() && variable.isConst()) { |
| // // //variable.getConstantValue(); |
| // // } |
| // } |
| return NOT_A_CONSTANT; |
| } |
| } |
| |
| /** |
| * A recursive AST visitor that is used to run over [Expression]s to determine |
| * whether the expression is composed by at least one deferred |
| * [PrefixedIdentifier]. |
| * |
| * See [PrefixedIdentifier.isDeferred]. |
| */ |
| class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> { |
| /** |
| * A flag indicating whether an identifier from a deferred library has been |
| * found. |
| */ |
| bool _result = false; |
| |
| /** |
| * Return `true` if the visitor found a [PrefixedIdentifier] that returned |
| * `true` to the [PrefixedIdentifier.isDeferred] query. |
| */ |
| bool get result => _result; |
| |
| @override |
| Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| if (!_result) { |
| if (node.isDeferred) { |
| _result = true; |
| } |
| } |
| return null; |
| } |
| } |
| |
| /** |
| * An object used to locate the [Element] associated with a given [AstNode]. |
| */ |
| class ElementLocator { |
| /** |
| * Return the element associated with the given [node], or `null` if there is |
| * no element associated with the node. |
| */ |
| static Element locate(AstNode node) { |
| if (node == null) { |
| return null; |
| } |
| ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper(); |
| return node.accept(mapper); |
| } |
| } |
| |
| /** |
| * Visitor that maps nodes to elements. |
| */ |
| class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> { |
| @override |
| Element visitAnnotation(Annotation node) => node.element; |
| |
| @override |
| Element visitAssignmentExpression(AssignmentExpression node) => |
| node.bestElement; |
| |
| @override |
| Element visitBinaryExpression(BinaryExpression node) => node.bestElement; |
| |
| @override |
| Element visitClassDeclaration(ClassDeclaration node) => node.element; |
| |
| @override |
| Element visitCompilationUnit(CompilationUnit node) => node.element; |
| |
| @override |
| Element visitConstructorDeclaration(ConstructorDeclaration node) => |
| node.element; |
| |
| @override |
| Element visitExportDirective(ExportDirective node) => node.element; |
| |
| @override |
| Element visitFunctionDeclaration(FunctionDeclaration node) => node.element; |
| |
| @override |
| Element visitIdentifier(Identifier node) { |
| AstNode parent = node.parent; |
| if (parent is Annotation) { |
| // Type name in Annotation |
| if (identical(parent.name, node) && parent.constructorName == null) { |
| return parent.element; |
| } |
| } else if (parent is ConstructorDeclaration) { |
| // Extra work to map Constructor Declarations to their associated |
| // Constructor Elements |
| Identifier returnType = parent.returnType; |
| if (identical(returnType, node)) { |
| SimpleIdentifier name = parent.name; |
| if (name != null) { |
| return name.bestElement; |
| } |
| Element element = node.bestElement; |
| if (element is ClassElement) { |
| return element.unnamedConstructor; |
| } |
| } |
| } else if (parent is LibraryIdentifier) { |
| AstNode grandParent = parent.parent; |
| if (grandParent is PartOfDirective) { |
| Element element = grandParent.element; |
| if (element is LibraryElement) { |
| return element.definingCompilationUnit; |
| } |
| } else if (grandParent is LibraryDirective) { |
| return grandParent.element; |
| } |
| } |
| return node.bestElement; |
| } |
| |
| @override |
| Element visitImportDirective(ImportDirective node) => node.element; |
| |
| @override |
| Element visitIndexExpression(IndexExpression node) => node.bestElement; |
| |
| @override |
| Element visitInstanceCreationExpression(InstanceCreationExpression node) => |
| node.staticElement; |
| |
| @override |
| Element visitLibraryDirective(LibraryDirective node) => node.element; |
| |
| @override |
| Element visitMethodDeclaration(MethodDeclaration node) => node.element; |
| |
| @override |
| Element visitMethodInvocation(MethodInvocation node) => |
| node.methodName.bestElement; |
| |
| @override |
| Element visitPartOfDirective(PartOfDirective node) => node.element; |
| |
| @override |
| Element visitPostfixExpression(PostfixExpression node) => node.bestElement; |
| |
| @override |
| Element visitPrefixedIdentifier(PrefixedIdentifier node) => node.bestElement; |
| |
| @override |
| Element visitPrefixExpression(PrefixExpression node) => node.bestElement; |
| |
| @override |
| Element visitStringLiteral(StringLiteral node) { |
| AstNode parent = node.parent; |
| if (parent is UriBasedDirective) { |
| return parent.uriElement; |
| } |
| return null; |
| } |
| |
| @override |
| Element visitVariableDeclaration(VariableDeclaration node) => node.element; |
| } |
| |
| /** |
| * A [DelegatingAstVisitor] that will additionally catch all exceptions from the |
| * delegates without stopping the visiting. A function must be provided that |
| * will be invoked for each such exception. |
| * |
| * Clients may not extend, implement or mix-in this class. |
| */ |
| class ExceptionHandlingDelegatingAstVisitor<T> extends DelegatingAstVisitor<T> { |
| /** |
| * The function that will be executed for each exception that is thrown by one |
| * of the visit methods on the delegate. |
| */ |
| final ExceptionInDelegateHandler handler; |
| |
| /** |
| * Initialize a newly created visitor to use each of the given delegate |
| * visitors to visit the nodes of an AST structure. |
| */ |
| ExceptionHandlingDelegatingAstVisitor( |
| Iterable<AstVisitor<T>> delegates, this.handler) |
| : super(delegates) { |
| if (handler == null) { |
| throw new ArgumentError('A handler must be provided'); |
| } |
| } |
| |
| @override |
| T visitNode(AstNode node) { |
| delegates.forEach((delegate) { |
| try { |
| node.accept(delegate); |
| } catch (exception, stackTrace) { |
| handler(node, delegate, exception, stackTrace); |
| } |
| }); |
| node.visitChildren(this); |
| return null; |
| } |
| |
| /** |
| * A function that can be used with instances of this class to log and then |
| * ignore any exceptions that are thrown by any of the delegates. |
| */ |
| static void logException(AstNode node, AstVisitor visitor, dynamic exception, |
| StackTrace stackTrace) { |
| StringBuffer buffer = new StringBuffer(); |
| buffer.write('Exception while using a ${visitor.runtimeType} to visit a '); |
| AstNode currentNode = node; |
| bool first = true; |
| while (currentNode != null) { |
| if (first) { |
| first = false; |
| } else { |
| buffer.write('in '); |
| } |
| buffer.write(currentNode.runtimeType); |
| currentNode = currentNode.parent; |
| } |
| AnalysisEngine.instance.logger.logError( |
| buffer.toString(), new CaughtException(exception, stackTrace)); |
| } |
| } |
| |
| /** |
| * An object that will clone any AST structure that it visits. The cloner will |
| * clone the structure, replacing the specified ASTNode with a new ASTNode, |
| * mapping the old token stream to a new token stream, and preserving resolution |
| * results. |
| */ |
| @deprecated |
| class IncrementalAstCloner implements AstVisitor<AstNode> { |
| /** |
| * The node to be replaced during the cloning process. |
| */ |
| final AstNode _oldNode; |
| |
| /** |
| * The replacement node used during the cloning process. |
| */ |
| final AstNode _newNode; |
| |
| /** |
| * A mapping of old tokens to new tokens used during the cloning process. |
| */ |
| final TokenMap _tokenMap; |
| |
| /** |
| * Construct a new instance that will replace the [oldNode] with the [newNode] |
| * in the process of cloning an existing AST structure. The [tokenMap] is a |
| * mapping of old tokens to new tokens. |
| */ |
| IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap); |
| |
| @override |
| AdjacentStrings visitAdjacentStrings(AdjacentStrings node) => |
| astFactory.adjacentStrings(_cloneNodeList(node.strings)); |
| |
| @override |
| Annotation visitAnnotation(Annotation node) { |
| Annotation copy = astFactory.annotation( |
| _mapToken(node.atSign), |
| _cloneNode(node.name), |
| _mapToken(node.period), |
| _cloneNode(node.constructorName), |
| _cloneNode(node.arguments)); |
| copy.element = node.element; |
| return copy; |
| } |
| |
| @override |
| ArgumentList visitArgumentList(ArgumentList node) => astFactory.argumentList( |
| _mapToken(node.leftParenthesis), |
| _cloneNodeList(node.arguments), |
| _mapToken(node.rightParenthesis)); |
| |
| @override |
| AsExpression visitAsExpression(AsExpression node) { |
| AsExpression copy = astFactory.asExpression(_cloneNode(node.expression), |
| _mapToken(node.asOperator), _cloneNode(node.type)); |
| copy.propagatedType = node.propagatedType; |
| copy.staticType = node.staticType; |
| return copy; |
| } |
| |
| @override |
| AstNode visitAssertInitializer(AssertInitializer node) => |
| astFactory.assertInitializer( |
| _mapToken(node.assertKeyword), |
| _mapToken(node.leftParenthesis), |
| _cloneNode(node.condition), |
| _mapToken(node.comma), |
| _cloneNode(node. |