blob: 718f9436c83053018d676eab014088b891f35a88 [file] [log] [blame]
// 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> &amp;&amp;
* > 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> &amp; e<sub>2</sub></i>,
* > <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
* > e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; 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> &gt; e<sub>2</sub></i>,
* > <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
* > e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= 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.