/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.utilities.ast; import com.google.dart.engine.ast.*; import com.google.dart.engine.scanner.Token; import com.google.dart.engine.utilities.collection.TokenMap; import java.util.ArrayList; import java.util.List; /** * Instances of the class {@code IncrementalAstCloner} implement 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. */ public class IncrementalAstCloner implements AstVisitor<AstNode> { /** * The node to be replaced during the cloning process. */ private AstNode oldNode; /** * The replacement node used during the cloning process. */ private AstNode newNode; /** * A mapping of old tokens to new tokens used during the cloning process. */ private TokenMap tokenMap; /** * Construct a new instance that will replace {@code oldNode} with {@code newNode} in the process * of cloning an existing AST structure. * * @param oldNode the node to be replaced * @param newNode the replacement node * @param tokenMap a mapping of old tokens to new tokens (not {@code null}) */ public IncrementalAstCloner(AstNode oldNode, AstNode newNode, TokenMap tokenMap) { this.oldNode = oldNode; this.newNode = newNode; this.tokenMap = tokenMap; } @Override public AdjacentStrings visitAdjacentStrings(AdjacentStrings node) { return new AdjacentStrings(cloneNodeList(node.getStrings())); } @Override public Annotation visitAnnotation(Annotation node) { Annotation copy = new Annotation( mapToken(node.getAtSign()), cloneNode(node.getName()), mapToken(node.getPeriod()), cloneNode(node.getConstructorName()), cloneNode(node.getArguments())); copy.setElement(node.getElement()); return copy; } @Override public ArgumentList visitArgumentList(ArgumentList node) { return new ArgumentList( mapToken(node.getLeftParenthesis()), cloneNodeList(node.getArguments()), mapToken(node.getRightParenthesis())); } @Override public AsExpression visitAsExpression(AsExpression node) { AsExpression copy = new AsExpression( cloneNode(node.getExpression()), mapToken(node.getAsOperator()), cloneNode(node.getType())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public AstNode visitAssertStatement(AssertStatement node) { return new AssertStatement( mapToken(node.getKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getCondition()), mapToken(node.getRightParenthesis()), mapToken(node.getSemicolon())); } @Override public AssignmentExpression visitAssignmentExpression(AssignmentExpression node) { AssignmentExpression copy = new AssignmentExpression( cloneNode(node.getLeftHandSide()), mapToken(node.getOperator()), cloneNode(node.getRightHandSide())); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public AwaitExpression visitAwaitExpression(AwaitExpression node) { return new AwaitExpression(mapToken(node.getAwaitKeyword()), cloneNode(node.getExpression())); } @Override public BinaryExpression visitBinaryExpression(BinaryExpression node) { BinaryExpression copy = new BinaryExpression( cloneNode(node.getLeftOperand()), mapToken(node.getOperator()), cloneNode(node.getRightOperand())); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public Block visitBlock(Block node) { return new Block( mapToken(node.getLeftBracket()), cloneNodeList(node.getStatements()), mapToken(node.getRightBracket())); } @Override public BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) { return new BlockFunctionBody( mapToken(node.getKeyword()), mapToken(node.getStar()), cloneNode(node.getBlock())); } @Override public BooleanLiteral visitBooleanLiteral(BooleanLiteral node) { BooleanLiteral copy = new BooleanLiteral(mapToken(node.getLiteral()), node.getValue()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public BreakStatement visitBreakStatement(BreakStatement node) { return new BreakStatement( mapToken(node.getKeyword()), cloneNode(node.getLabel()), mapToken(node.getSemicolon())); } @Override public CascadeExpression visitCascadeExpression(CascadeExpression node) { CascadeExpression copy = new CascadeExpression( cloneNode(node.getTarget()), cloneNodeList(node.getCascadeSections())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public CatchClause visitCatchClause(CatchClause node) { return new CatchClause( mapToken(node.getOnKeyword()), cloneNode(node.getExceptionType()), mapToken(node.getCatchKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getExceptionParameter()), mapToken(node.getComma()), cloneNode(node.getStackTraceParameter()), mapToken(node.getRightParenthesis()), cloneNode(node.getBody())); } @Override public ClassDeclaration visitClassDeclaration(ClassDeclaration node) { ClassDeclaration copy = new ClassDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getAbstractKeyword()), mapToken(node.getClassKeyword()), cloneNode(node.getName()), cloneNode(node.getTypeParameters()), cloneNode(node.getExtendsClause()), cloneNode(node.getWithClause()), cloneNode(node.getImplementsClause()), mapToken(node.getLeftBracket()), cloneNodeList(node.getMembers()), mapToken(node.getRightBracket())); copy.setNativeClause(cloneNode(node.getNativeClause())); return copy; } @Override public ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) { return new ClassTypeAlias( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getName()), cloneNode(node.getTypeParameters()), mapToken(node.getEquals()), mapToken(node.getAbstractKeyword()), cloneNode(node.getSuperclass()), cloneNode(node.getWithClause()), cloneNode(node.getImplementsClause()), mapToken(node.getSemicolon())); } @Override public Comment visitComment(Comment node) { if (node.isDocumentation()) { return Comment.createDocumentationCommentWithReferences( mapTokens(node.getTokens()), cloneNodeList(node.getReferences())); } else if (node.isBlock()) { return Comment.createBlockComment(mapTokens(node.getTokens())); } return Comment.createEndOfLineComment(mapTokens(node.getTokens())); } @Override public CommentReference visitCommentReference(CommentReference node) { return new CommentReference(mapToken(node.getNewKeyword()), cloneNode(node.getIdentifier())); } @Override public CompilationUnit visitCompilationUnit(CompilationUnit node) { CompilationUnit copy = new CompilationUnit( mapToken(node.getBeginToken()), cloneNode(node.getScriptTag()), cloneNodeList(node.getDirectives()), cloneNodeList(node.getDeclarations()), mapToken(node.getEndToken())); copy.setLineInfo(node.getLineInfo()); copy.setElement(node.getElement()); return copy; } @Override public ConditionalExpression visitConditionalExpression(ConditionalExpression node) { ConditionalExpression copy = new ConditionalExpression( cloneNode(node.getCondition()), mapToken(node.getQuestion()), cloneNode(node.getThenExpression()), mapToken(node.getColon()), cloneNode(node.getElseExpression())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ConstructorDeclaration visitConstructorDeclaration(ConstructorDeclaration node) { ConstructorDeclaration copy = new ConstructorDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getExternalKeyword()), mapToken(node.getConstKeyword()), mapToken(node.getFactoryKeyword()), cloneNode(node.getReturnType()), mapToken(node.getPeriod()), cloneNode(node.getName()), cloneNode(node.getParameters()), mapToken(node.getSeparator()), cloneNodeList(node.getInitializers()), cloneNode(node.getRedirectedConstructor()), cloneNode(node.getBody())); copy.setElement(node.getElement()); return copy; } @Override public ConstructorFieldInitializer visitConstructorFieldInitializer( ConstructorFieldInitializer node) { return new ConstructorFieldInitializer( mapToken(node.getKeyword()), mapToken(node.getPeriod()), cloneNode(node.getFieldName()), mapToken(node.getEquals()), cloneNode(node.getExpression())); } @Override public ConstructorName visitConstructorName(ConstructorName node) { ConstructorName copy = new ConstructorName( cloneNode(node.getType()), mapToken(node.getPeriod()), cloneNode(node.getName())); copy.setStaticElement(node.getStaticElement()); return copy; } @Override public ContinueStatement visitContinueStatement(ContinueStatement node) { return new ContinueStatement( mapToken(node.getKeyword()), cloneNode(node.getLabel()), mapToken(node.getSemicolon())); } @Override public DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) { return new DeclaredIdentifier( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getType()), cloneNode(node.getIdentifier())); } @Override public DefaultFormalParameter visitDefaultFormalParameter(DefaultFormalParameter node) { return new DefaultFormalParameter( cloneNode(node.getParameter()), node.getKind(), mapToken(node.getSeparator()), cloneNode(node.getDefaultValue())); } @Override public DoStatement visitDoStatement(DoStatement node) { return new DoStatement( mapToken(node.getDoKeyword()), cloneNode(node.getBody()), mapToken(node.getWhileKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getCondition()), mapToken(node.getRightParenthesis()), mapToken(node.getSemicolon())); } @Override public DoubleLiteral visitDoubleLiteral(DoubleLiteral node) { DoubleLiteral copy = new DoubleLiteral(mapToken(node.getLiteral()), node.getValue()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) { return new EmptyFunctionBody(mapToken(node.getSemicolon())); } @Override public EmptyStatement visitEmptyStatement(EmptyStatement node) { return new EmptyStatement(mapToken(node.getSemicolon())); } @Override public AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) { return new EnumConstantDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), cloneNode(node.getName())); } @Override public AstNode visitEnumDeclaration(EnumDeclaration node) { return new EnumDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getName()), mapToken(node.getLeftBracket()), cloneNodeList(node.getConstants()), mapToken(node.getRightBracket())); } @Override public ExportDirective visitExportDirective(ExportDirective node) { ExportDirective copy = new ExportDirective( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getUri()), cloneNodeList(node.getCombinators()), mapToken(node.getSemicolon())); copy.setElement(node.getElement()); return copy; } @Override public ExpressionFunctionBody visitExpressionFunctionBody(ExpressionFunctionBody node) { return new ExpressionFunctionBody( mapToken(node.getKeyword()), mapToken(node.getFunctionDefinition()), cloneNode(node.getExpression()), mapToken(node.getSemicolon())); } @Override public ExpressionStatement visitExpressionStatement(ExpressionStatement node) { return new ExpressionStatement(cloneNode(node.getExpression()), mapToken(node.getSemicolon())); } @Override public ExtendsClause visitExtendsClause(ExtendsClause node) { return new ExtendsClause(mapToken(node.getKeyword()), cloneNode(node.getSuperclass())); } @Override public FieldDeclaration visitFieldDeclaration(FieldDeclaration node) { return new FieldDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getStaticKeyword()), cloneNode(node.getFields()), mapToken(node.getSemicolon())); } @Override public FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) { return new FieldFormalParameter( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getType()), mapToken(node.getThisToken()), mapToken(node.getPeriod()), cloneNode(node.getIdentifier()), cloneNode(node.getParameters())); } @Override public ForEachStatement visitForEachStatement(ForEachStatement node) { DeclaredIdentifier loopVariable = node.getLoopVariable(); if (loopVariable == null) { return new ForEachStatement( mapToken(node.getAwaitKeyword()), mapToken(node.getForKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getIdentifier()), mapToken(node.getInKeyword()), cloneNode(node.getIterator()), mapToken(node.getRightParenthesis()), cloneNode(node.getBody())); } return new ForEachStatement( mapToken(node.getAwaitKeyword()), mapToken(node.getForKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(loopVariable), mapToken(node.getInKeyword()), cloneNode(node.getIterator()), mapToken(node.getRightParenthesis()), cloneNode(node.getBody())); } @Override public FormalParameterList visitFormalParameterList(FormalParameterList node) { return new FormalParameterList( mapToken(node.getLeftParenthesis()), cloneNodeList(node.getParameters()), mapToken(node.getLeftDelimiter()), mapToken(node.getRightDelimiter()), mapToken(node.getRightParenthesis())); } @Override public ForStatement visitForStatement(ForStatement node) { return new ForStatement( mapToken(node.getForKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getVariables()), cloneNode(node.getInitialization()), mapToken(node.getLeftSeparator()), cloneNode(node.getCondition()), mapToken(node.getRightSeparator()), cloneNodeList(node.getUpdaters()), mapToken(node.getRightParenthesis()), cloneNode(node.getBody())); } @Override public FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) { return new FunctionDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getExternalKeyword()), cloneNode(node.getReturnType()), mapToken(node.getPropertyKeyword()), cloneNode(node.getName()), cloneNode(node.getFunctionExpression())); } @Override public FunctionDeclarationStatement visitFunctionDeclarationStatement( FunctionDeclarationStatement node) { return new FunctionDeclarationStatement(cloneNode(node.getFunctionDeclaration())); } @Override public FunctionExpression visitFunctionExpression(FunctionExpression node) { FunctionExpression copy = new FunctionExpression( cloneNode(node.getParameters()), cloneNode(node.getBody())); copy.setElement(node.getElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public FunctionExpressionInvocation visitFunctionExpressionInvocation( FunctionExpressionInvocation node) { FunctionExpressionInvocation copy = new FunctionExpressionInvocation( cloneNode(node.getFunction()), cloneNode(node.getArgumentList())); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) { return new FunctionTypeAlias( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getReturnType()), cloneNode(node.getName()), cloneNode(node.getTypeParameters()), cloneNode(node.getParameters()), mapToken(node.getSemicolon())); } @Override public FunctionTypedFormalParameter visitFunctionTypedFormalParameter( FunctionTypedFormalParameter node) { return new FunctionTypedFormalParameter( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), cloneNode(node.getReturnType()), cloneNode(node.getIdentifier()), cloneNode(node.getParameters())); } @Override public HideCombinator visitHideCombinator(HideCombinator node) { return new HideCombinator(mapToken(node.getKeyword()), cloneNodeList(node.getHiddenNames())); } @Override public IfStatement visitIfStatement(IfStatement node) { return new IfStatement( mapToken(node.getIfKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getCondition()), mapToken(node.getRightParenthesis()), cloneNode(node.getThenStatement()), mapToken(node.getElseKeyword()), cloneNode(node.getElseStatement())); } @Override public ImplementsClause visitImplementsClause(ImplementsClause node) { return new ImplementsClause(mapToken(node.getKeyword()), cloneNodeList(node.getInterfaces())); } @Override public ImportDirective visitImportDirective(ImportDirective node) { return new ImportDirective( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getUri()), mapToken(node.getDeferredToken()), mapToken(node.getAsToken()), cloneNode(node.getPrefix()), cloneNodeList(node.getCombinators()), mapToken(node.getSemicolon())); } @Override public IndexExpression visitIndexExpression(IndexExpression node) { Token period = mapToken(node.getPeriod()); IndexExpression copy; if (period == null) { copy = new IndexExpression( cloneNode(node.getTarget()), mapToken(node.getLeftBracket()), cloneNode(node.getIndex()), mapToken(node.getRightBracket())); } else { copy = new IndexExpression( period, mapToken(node.getLeftBracket()), cloneNode(node.getIndex()), mapToken(node.getRightBracket())); } copy.setAuxiliaryElements(node.getAuxiliaryElements()); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public InstanceCreationExpression visitInstanceCreationExpression(InstanceCreationExpression node) { InstanceCreationExpression copy = new InstanceCreationExpression( mapToken(node.getKeyword()), cloneNode(node.getConstructorName()), cloneNode(node.getArgumentList())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public IntegerLiteral visitIntegerLiteral(IntegerLiteral node) { IntegerLiteral copy = new IntegerLiteral(mapToken(node.getLiteral()), node.getValue()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public InterpolationExpression visitInterpolationExpression(InterpolationExpression node) { return new InterpolationExpression( mapToken(node.getLeftBracket()), cloneNode(node.getExpression()), mapToken(node.getRightBracket())); } @Override public InterpolationString visitInterpolationString(InterpolationString node) { return new InterpolationString(mapToken(node.getContents()), node.getValue()); } @Override public IsExpression visitIsExpression(IsExpression node) { IsExpression copy = new IsExpression( cloneNode(node.getExpression()), mapToken(node.getIsOperator()), mapToken(node.getNotOperator()), cloneNode(node.getType())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public Label visitLabel(Label node) { return new Label(cloneNode(node.getLabel()), mapToken(node.getColon())); } @Override public LabeledStatement visitLabeledStatement(LabeledStatement node) { return new LabeledStatement(cloneNodeList(node.getLabels()), cloneNode(node.getStatement())); } @Override public LibraryDirective visitLibraryDirective(LibraryDirective node) { return new LibraryDirective( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getLibraryToken()), cloneNode(node.getName()), mapToken(node.getSemicolon())); } @Override public LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) { LibraryIdentifier copy = new LibraryIdentifier(cloneNodeList(node.getComponents())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ListLiteral visitListLiteral(ListLiteral node) { ListLiteral copy = new ListLiteral( mapToken(node.getConstKeyword()), cloneNode(node.getTypeArguments()), mapToken(node.getLeftBracket()), cloneNodeList(node.getElements()), mapToken(node.getRightBracket())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public MapLiteral visitMapLiteral(MapLiteral node) { MapLiteral copy = new MapLiteral( mapToken(node.getConstKeyword()), cloneNode(node.getTypeArguments()), mapToken(node.getLeftBracket()), cloneNodeList(node.getEntries()), mapToken(node.getRightBracket())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) { return new MapLiteralEntry( cloneNode(node.getKey()), mapToken(node.getSeparator()), cloneNode(node.getValue())); } @Override public MethodDeclaration visitMethodDeclaration(MethodDeclaration node) { return new MethodDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getExternalKeyword()), mapToken(node.getModifierKeyword()), cloneNode(node.getReturnType()), mapToken(node.getPropertyKeyword()), mapToken(node.getOperatorKeyword()), cloneNode(node.getName()), cloneNode(node.getParameters()), cloneNode(node.getBody())); } @Override public MethodInvocation visitMethodInvocation(MethodInvocation node) { MethodInvocation copy = new MethodInvocation( cloneNode(node.getTarget()), mapToken(node.getPeriod()), cloneNode(node.getMethodName()), cloneNode(node.getArgumentList())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public NamedExpression visitNamedExpression(NamedExpression node) { NamedExpression copy = new NamedExpression( cloneNode(node.getName()), cloneNode(node.getExpression())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public AstNode visitNativeClause(NativeClause node) { return new NativeClause(mapToken(node.getKeyword()), cloneNode(node.getName())); } @Override public NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) { return new NativeFunctionBody( mapToken(node.getNativeToken()), cloneNode(node.getStringLiteral()), mapToken(node.getSemicolon())); } @Override public NullLiteral visitNullLiteral(NullLiteral node) { NullLiteral copy = new NullLiteral(mapToken(node.getLiteral())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ParenthesizedExpression visitParenthesizedExpression(ParenthesizedExpression node) { ParenthesizedExpression copy = new ParenthesizedExpression( mapToken(node.getLeftParenthesis()), cloneNode(node.getExpression()), mapToken(node.getRightParenthesis())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public PartDirective visitPartDirective(PartDirective node) { PartDirective copy = new PartDirective( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getPartToken()), cloneNode(node.getUri()), mapToken(node.getSemicolon())); copy.setElement(node.getElement()); return copy; } @Override public PartOfDirective visitPartOfDirective(PartOfDirective node) { PartOfDirective copy = new PartOfDirective( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getPartToken()), mapToken(node.getOfToken()), cloneNode(node.getLibraryName()), mapToken(node.getSemicolon())); copy.setElement(node.getElement()); return copy; } @Override public PostfixExpression visitPostfixExpression(PostfixExpression node) { PostfixExpression copy = new PostfixExpression( cloneNode(node.getOperand()), mapToken(node.getOperator())); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) { PrefixedIdentifier copy = new PrefixedIdentifier( cloneNode(node.getPrefix()), mapToken(node.getPeriod()), cloneNode(node.getIdentifier())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public PrefixExpression visitPrefixExpression(PrefixExpression node) { PrefixExpression copy = new PrefixExpression( mapToken(node.getOperator()), cloneNode(node.getOperand())); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public PropertyAccess visitPropertyAccess(PropertyAccess node) { PropertyAccess copy = new PropertyAccess( cloneNode(node.getTarget()), mapToken(node.getOperator()), cloneNode(node.getPropertyName())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public RedirectingConstructorInvocation visitRedirectingConstructorInvocation( RedirectingConstructorInvocation node) { RedirectingConstructorInvocation copy = new RedirectingConstructorInvocation( mapToken(node.getKeyword()), mapToken(node.getPeriod()), cloneNode(node.getConstructorName()), cloneNode(node.getArgumentList())); copy.setStaticElement(node.getStaticElement()); return copy; } @Override public RethrowExpression visitRethrowExpression(RethrowExpression node) { RethrowExpression copy = new RethrowExpression(mapToken(node.getKeyword())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ReturnStatement visitReturnStatement(ReturnStatement node) { return new ReturnStatement( mapToken(node.getKeyword()), cloneNode(node.getExpression()), mapToken(node.getSemicolon())); } @Override public ScriptTag visitScriptTag(ScriptTag node) { return new ScriptTag(mapToken(node.getScriptTag())); } @Override public ShowCombinator visitShowCombinator(ShowCombinator node) { return new ShowCombinator(mapToken(node.getKeyword()), cloneNodeList(node.getShownNames())); } @Override public SimpleFormalParameter visitSimpleFormalParameter(SimpleFormalParameter node) { return new SimpleFormalParameter( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getType()), cloneNode(node.getIdentifier())); } @Override public SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) { Token mappedToken = mapToken(node.getToken()); if (mappedToken == null) { // This only happens for SimpleIdentifiers created by the parser as part of scanning // documentation comments (the tokens for those identifiers are not in the original token // stream and hence do not get copied). This extra check can be removed if the scanner is // changed to scan documentation comments for the parser. mappedToken = node.getToken(); } SimpleIdentifier copy = new SimpleIdentifier(mappedToken); copy.setAuxiliaryElements(node.getAuxiliaryElements()); copy.setPropagatedElement(node.getPropagatedElement()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticElement(node.getStaticElement()); copy.setStaticType(node.getStaticType()); return copy; } @Override public SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) { SimpleStringLiteral copy = new SimpleStringLiteral(mapToken(node.getLiteral()), node.getValue()); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public StringInterpolation visitStringInterpolation(StringInterpolation node) { StringInterpolation copy = new StringInterpolation(cloneNodeList(node.getElements())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public SuperConstructorInvocation visitSuperConstructorInvocation(SuperConstructorInvocation node) { SuperConstructorInvocation copy = new SuperConstructorInvocation( mapToken(node.getKeyword()), mapToken(node.getPeriod()), cloneNode(node.getConstructorName()), cloneNode(node.getArgumentList())); copy.setStaticElement(node.getStaticElement()); return copy; } @Override public SuperExpression visitSuperExpression(SuperExpression node) { SuperExpression copy = new SuperExpression(mapToken(node.getKeyword())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public SwitchCase visitSwitchCase(SwitchCase node) { return new SwitchCase( cloneNodeList(node.getLabels()), mapToken(node.getKeyword()), cloneNode(node.getExpression()), mapToken(node.getColon()), cloneNodeList(node.getStatements())); } @Override public SwitchDefault visitSwitchDefault(SwitchDefault node) { return new SwitchDefault( cloneNodeList(node.getLabels()), mapToken(node.getKeyword()), mapToken(node.getColon()), cloneNodeList(node.getStatements())); } @Override public SwitchStatement visitSwitchStatement(SwitchStatement node) { return new SwitchStatement( mapToken(node.getKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getExpression()), mapToken(node.getRightParenthesis()), mapToken(node.getLeftBracket()), cloneNodeList(node.getMembers()), mapToken(node.getRightBracket())); } @Override public AstNode visitSymbolLiteral(SymbolLiteral node) { SymbolLiteral copy = new SymbolLiteral( mapToken(node.getPoundSign()), mapTokens(node.getComponents())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ThisExpression visitThisExpression(ThisExpression node) { ThisExpression copy = new ThisExpression(mapToken(node.getKeyword())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public ThrowExpression visitThrowExpression(ThrowExpression node) { ThrowExpression copy = new ThrowExpression( mapToken(node.getKeyword()), cloneNode(node.getExpression())); copy.setPropagatedType(node.getPropagatedType()); copy.setStaticType(node.getStaticType()); return copy; } @Override public TopLevelVariableDeclaration visitTopLevelVariableDeclaration( TopLevelVariableDeclaration node) { return new TopLevelVariableDeclaration( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), cloneNode(node.getVariables()), mapToken(node.getSemicolon())); } @Override public TryStatement visitTryStatement(TryStatement node) { return new TryStatement( mapToken(node.getTryKeyword()), cloneNode(node.getBody()), cloneNodeList(node.getCatchClauses()), mapToken(node.getFinallyKeyword()), cloneNode(node.getFinallyBlock())); } @Override public TypeArgumentList visitTypeArgumentList(TypeArgumentList node) { return new TypeArgumentList( mapToken(node.getLeftBracket()), cloneNodeList(node.getArguments()), mapToken(node.getRightBracket())); } @Override public TypeName visitTypeName(TypeName node) { TypeName copy = new TypeName(cloneNode(node.getName()), cloneNode(node.getTypeArguments())); copy.setType(node.getType()); return copy; } @Override public TypeParameter visitTypeParameter(TypeParameter node) { return new TypeParameter( cloneNode(node.getDocumentationComment()), cloneNodeList(node.getMetadata()), cloneNode(node.getName()), mapToken(node.getKeyword()), cloneNode(node.getBound())); } @Override public TypeParameterList visitTypeParameterList(TypeParameterList node) { return new TypeParameterList( mapToken(node.getLeftBracket()), cloneNodeList(node.getTypeParameters()), mapToken(node.getRightBracket())); } @Override public VariableDeclaration visitVariableDeclaration(VariableDeclaration node) { return new VariableDeclaration( null, cloneNodeList(node.getMetadata()), cloneNode(node.getName()), mapToken(node.getEquals()), cloneNode(node.getInitializer())); } @Override public VariableDeclarationList visitVariableDeclarationList(VariableDeclarationList node) { return new VariableDeclarationList( null, cloneNodeList(node.getMetadata()), mapToken(node.getKeyword()), cloneNode(node.getType()), cloneNodeList(node.getVariables())); } @Override public VariableDeclarationStatement visitVariableDeclarationStatement( VariableDeclarationStatement node) { return new VariableDeclarationStatement( cloneNode(node.getVariables()), mapToken(node.getSemicolon())); } @Override public WhileStatement visitWhileStatement(WhileStatement node) { return new WhileStatement( mapToken(node.getKeyword()), mapToken(node.getLeftParenthesis()), cloneNode(node.getCondition()), mapToken(node.getRightParenthesis()), cloneNode(node.getBody())); } @Override public WithClause visitWithClause(WithClause node) { return new WithClause(mapToken(node.getWithKeyword()), cloneNodeList(node.getMixinTypes())); } @Override public YieldStatement visitYieldStatement(YieldStatement node) { return new YieldStatement( mapToken(node.getYieldKeyword()), mapToken(node.getStar()), cloneNode(node.getExpression()), mapToken(node.getSemicolon())); } @SuppressWarnings("unchecked") private <E extends AstNode> E cloneNode(E node) { if (node == null) { return null; } if (node == oldNode) { return (E) newNode; } return (E) node.accept(this); } private <E extends AstNode> List<E> cloneNodeList(NodeList<E> nodes) { ArrayList<E> clonedNodes = new ArrayList<E>(); for (E node : nodes) { clonedNodes.add(cloneNode(node)); } return clonedNodes; } private Token mapToken(Token oldToken) { if (oldToken == null) { return null; } return tokenMap.get(oldToken); } private Token[] mapTokens(Token[] oldTokens) { Token[] newTokens = new Token[oldTokens.length]; for (int index = 0; index < newTokens.length; index++) { newTokens[index] = mapToken(oldTokens[index]); } return newTokens; } }