From 915f8734c5f79962f12460bb91166c904ce01183 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Thu, 14 Aug 2014 15:29:03 +0400 Subject: [PATCH] JS backend: added visitors with context --- .../backend/js/ast/ChameleonJsExpression.java | 5 + .../backend/js/ast/JsArrayAccess.java | 9 + .../backend/js/ast/JsArrayLiteral.java | 8 + .../backend/js/ast/JsBinaryOperation.java | 13 + .../dart/compiler/backend/js/ast/JsBlock.java | 10 +- .../dart/compiler/backend/js/ast/JsBreak.java | 6 + .../dart/compiler/backend/js/ast/JsCase.java | 9 + .../dart/compiler/backend/js/ast/JsCatch.java | 12 + .../backend/js/ast/JsConditional.java | 10 + .../compiler/backend/js/ast/JsContext.java | 5 + .../compiler/backend/js/ast/JsContinue.java | 6 + .../compiler/backend/js/ast/JsDebugger.java | 6 + .../compiler/backend/js/ast/JsDefault.java | 8 + .../compiler/backend/js/ast/JsDoWhile.java | 9 + .../compiler/backend/js/ast/JsDocComment.java | 4 + .../dart/compiler/backend/js/ast/JsEmpty.java | 6 + .../backend/js/ast/JsEmptyExpression.java | 5 + .../backend/js/ast/JsExpressionStatement.java | 8 + .../dart/compiler/backend/js/ast/JsFor.java | 23 ++ .../dart/compiler/backend/js/ast/JsForIn.java | 12 + .../compiler/backend/js/ast/JsFunction.java | 11 +- .../dart/compiler/backend/js/ast/JsIf.java | 12 + .../compiler/backend/js/ast/JsInvocation.java | 10 +- .../dart/compiler/backend/js/ast/JsLabel.java | 8 + .../compiler/backend/js/ast/JsLiteral.java | 24 +- .../compiler/backend/js/ast/JsNameRef.java | 10 + .../dart/compiler/backend/js/ast/JsNew.java | 9 + .../dart/compiler/backend/js/ast/JsNode.java | 8 + .../backend/js/ast/JsNullLiteral.java | 6 + .../backend/js/ast/JsNumberLiteral.java | 12 + .../backend/js/ast/JsObjectLiteral.java | 8 + .../compiler/backend/js/ast/JsParameter.java | 6 + .../backend/js/ast/JsPostfixOperation.java | 8 + .../backend/js/ast/JsPrefixOperation.java | 8 + .../compiler/backend/js/ast/JsProgram.java | 10 + .../backend/js/ast/JsProgramFragment.java | 8 + .../backend/js/ast/JsPropertyInitializer.java | 9 + .../compiler/backend/js/ast/JsRegExp.java | 6 + .../compiler/backend/js/ast/JsReturn.java | 10 + .../backend/js/ast/JsStringLiteral.java | 14 +- .../compiler/backend/js/ast/JsSwitch.java | 9 + .../dart/compiler/backend/js/ast/JsThrow.java | 8 + .../dart/compiler/backend/js/ast/JsTry.java | 12 + .../backend/js/ast/JsUnaryOperation.java | 13 + .../dart/compiler/backend/js/ast/JsVars.java | 18 + .../backend/js/ast/JsVisitorWithContext.java | 366 ++++++++++++++++++ .../js/ast/JsVisitorWithContextImpl.java | 210 ++++++++++ .../dart/compiler/backend/js/ast/JsWhile.java | 9 + 48 files changed, 1002 insertions(+), 14 deletions(-) create mode 100644 js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContext.java create mode 100644 js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContextImpl.java diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java index df2171ce1aa..c6494317329 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java @@ -51,4 +51,9 @@ public class ChameleonJsExpression implements JsExpression { public JsExpression source(Object info) { return expression.source(info); } + + @Override + public void traverse(JsVisitorWithContext visitor, JsContext ctx) { + expression.traverse(visitor, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayAccess.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayAccess.java index 4a0475f224a..95bd6afc081 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayAccess.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayAccess.java @@ -46,4 +46,13 @@ public final class JsArrayAccess extends JsExpressionImpl { visitor.accept(arrayExpression); visitor.accept(indexExpression); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + arrayExpression = v.accept(arrayExpression); + indexExpression = v.accept(indexExpression); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayLiteral.java index 3398d8ee345..e6f2a2612ca 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsArrayLiteral.java @@ -35,4 +35,12 @@ public final class JsArrayLiteral extends JsLiteral { public void acceptChildren(JsVisitor visitor) { visitor.acceptWithInsertRemove(expressions); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptList(expressions); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBinaryOperation.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBinaryOperation.java index d13cd077aab..681100fe92c 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBinaryOperation.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBinaryOperation.java @@ -48,4 +48,17 @@ public final class JsBinaryOperation extends JsExpressionImpl { } visitor.accept(arg2); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + if (op.isAssignment()) { + arg1 = v.acceptLvalue(arg1); + } else { + arg1 = v.accept(arg1); + } + arg2 = v.accept(arg2); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBlock.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBlock.java index 2193cccbca0..fce705014aa 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBlock.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBlock.java @@ -7,8 +7,6 @@ package com.google.dart.compiler.backend.js.ast; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; /** @@ -56,4 +54,12 @@ public class JsBlock extends SourceInfoAwareJsNode implements JsStatement { public void acceptChildren(JsVisitor visitor) { visitor.acceptWithInsertRemove(statements); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptStatementList(statements); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBreak.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBreak.java index 82f53548696..e046b2b2695 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBreak.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsBreak.java @@ -20,4 +20,10 @@ public final class JsBreak extends JsContinue { public void accept(JsVisitor v) { v.visitBreak(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCase.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCase.java index 0f9cf3270de..d459e480c56 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCase.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCase.java @@ -32,4 +32,13 @@ public final class JsCase extends JsSwitchMember { visitor.accept(caseExpression); super.acceptChildren(visitor); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + caseExpression = v.accept(caseExpression); + v.acceptStatementList(statements); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCatch.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCatch.java index 41d431cb2d3..7ed65734801 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCatch.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsCatch.java @@ -60,4 +60,16 @@ public class JsCatch extends SourceInfoAwareJsNode implements HasCondition { } visitor.accept(body); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + param = v.accept(param); + if (condition != null) { + condition = v.accept(condition); + } + body = v.accept(body); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsConditional.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsConditional.java index 597891e1e7d..97fb3b890fb 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsConditional.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsConditional.java @@ -53,4 +53,14 @@ public final class JsConditional extends JsExpressionImpl { visitor.accept(thenExpression); visitor.accept(elseExpression); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + testExpression = v.accept(testExpression); + thenExpression = v.accept(thenExpression); + elseExpression = v.accept(elseExpression); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContext.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContext.java index 35b8c74769e..ae859fc93d4 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContext.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContext.java @@ -4,6 +4,8 @@ package com.google.dart.compiler.backend.js.ast; +import org.jetbrains.annotations.Nullable; + /** * The context in which a JsNode visitation occurs. This represents the set of * possible operations a JsVisitor subclass can perform on the currently visited @@ -23,4 +25,7 @@ public interface JsContext { void removeMe(); void replaceMe(JsNode node); + + @Nullable + JsNode getCurrentNode(); } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContinue.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContinue.java index d5b5d60ab60..d3705244642 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContinue.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsContinue.java @@ -26,4 +26,10 @@ public class JsContinue extends SourceInfoAwareJsNode implements JsStatement { public void accept(JsVisitor v) { v.visitContinue(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDebugger.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDebugger.java index cbf6063e986..eeecf1e8a68 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDebugger.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDebugger.java @@ -20,4 +20,10 @@ public class JsDebugger extends SourceInfoAwareJsNode implements JsStatement { public void acceptChildren(JsVisitor visitor) { } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDefault.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDefault.java index 330005ddd57..f9e85515556 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDefault.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDefault.java @@ -12,4 +12,12 @@ public final class JsDefault extends JsSwitchMember { public void accept(JsVisitor v) { v.visitDefault(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptStatementList(statements); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDoWhile.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDoWhile.java index f23b08c26e4..4007ea30dc0 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDoWhile.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDoWhile.java @@ -19,4 +19,13 @@ public class JsDoWhile extends JsWhile { public void accept(JsVisitor v) { v.visitDoWhile(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + body = v.acceptStatement(body); + condition = v.accept(condition); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDocComment.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDocComment.java index 292c9070ab8..8a9aea83762 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDocComment.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsDocComment.java @@ -26,4 +26,8 @@ public class JsDocComment extends JsExpressionImpl { public void accept(JsVisitor v) { v.visitDocComment(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmpty.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmpty.java index 602e1e63308..8d852e41049 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmpty.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmpty.java @@ -12,4 +12,10 @@ public class JsEmpty extends SourceInfoAwareJsNode implements JsStatement { public void accept(JsVisitor v) { v.visitEmpty(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmptyExpression.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmptyExpression.java index c8aa2bc8cff..43d84b7622a 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmptyExpression.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsEmptyExpression.java @@ -33,4 +33,9 @@ public class JsEmptyExpression extends JsExpressionImpl { public void accept(JsVisitor visitor) { throw new IllegalArgumentException("empty expression should not be here during generating Javascript code"); } + + @Override + public void traverse(JsVisitorWithContext visitor, JsContext ctx) { + throw new IllegalArgumentException("empty expression should not be here during generating Javascript code"); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsExpressionStatement.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsExpressionStatement.java index 85a7fe6bee4..f2421da1154 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsExpressionStatement.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsExpressionStatement.java @@ -39,4 +39,12 @@ public final class JsExpressionStatement extends AbstractNode implements JsState public JsNode source(Object info) { throw new IllegalStateException("You must not set source info for JsExpressionStatement, set for expression"); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + expression = v.accept(expression); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java index b7387ec0101..76e25578aba 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java @@ -95,4 +95,27 @@ public class JsFor extends SourceInfoAwareJsNode implements JsStatement { } visitor.accept(body); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + assert (!(initExpression != null && initVars != null)); + + if (initExpression != null) { + initExpression = v.accept(initExpression); + } else if (initVars != null) { + initVars = v.accept(initVars); + } + + if (condition != null) { + condition = v.accept(condition); + } + + if (incrementExpression != null) { + incrementExpression = v.accept(incrementExpression); + } + body = v.acceptStatement(body); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java index 3fc4a915abf..167d9068a18 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java @@ -61,4 +61,16 @@ public class JsForIn extends SourceInfoAwareJsNode implements JsStatement { visitor.accept(objectExpression); visitor.accept(body); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + if (iterExpression != null) { + iterExpression = v.acceptLvalue(iterExpression); + } + objectExpression = v.accept(objectExpression); + body = v.acceptStatement(body); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java index 58fcbff7444..917fb801a25 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java @@ -76,7 +76,16 @@ public final class JsFunction extends JsLiteral implements HasName { @Override public void acceptChildren(JsVisitor visitor) { - visitor.acceptWithInsertRemove(params); + visitor.acceptWithInsertRemove(getParameters()); visitor.accept(body); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptList(getParameters()); + body = v.accept(body); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsIf.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsIf.java index 18af5ffb414..1fbfcb437ad 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsIf.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsIf.java @@ -63,4 +63,16 @@ public final class JsIf extends SourceInfoAwareJsNode implements JsStatement { visitor.accept(elseStatement); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + ifExpression = v.accept(ifExpression); + thenStatement = v.acceptStatement(thenStatement); + if (elseStatement != null) { + elseStatement = v.acceptStatement(elseStatement); + } + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java index 233c0b22bc7..fd595f0364b 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsInvocation.java @@ -8,7 +8,6 @@ import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -import java.util.Collections; import java.util.List; public final class JsInvocation extends JsExpressionImpl.JsExpressionHasArguments { @@ -60,4 +59,13 @@ public final class JsInvocation extends JsExpressionImpl.JsExpressionHasArgument visitor.accept(qualifier); visitor.acceptList(arguments); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + qualifier = v.accept(qualifier); + v.acceptList(arguments); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLabel.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLabel.java index a3abb3392bc..6dd5fa2bdb8 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLabel.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLabel.java @@ -50,4 +50,12 @@ public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasNa public void acceptChildren(JsVisitor visitor) { visitor.accept(statement); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + statement = v.acceptStatement(statement); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLiteral.java index 8823d12b557..1385457bdeb 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsLiteral.java @@ -26,24 +26,36 @@ public abstract class JsLiteral extends JsExpressionImpl { public void accept(JsVisitor v) { v.visitThis(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } public static final class JsBooleanLiteral extends JsValueLiteral { - private final boolean value; + private final boolean value; - // Should be interned by JsProgram - private JsBooleanLiteral(boolean value) { + // Should be interned by JsProgram + private JsBooleanLiteral(boolean value) { this.value = value; } - public boolean getValue() { + public boolean getValue() { return value; } - @Override - public void accept(JsVisitor v) { + @Override + public void accept(JsVisitor v) { v.visitBoolean(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } /** diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNameRef.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNameRef.java index 6fb7bc3e5ae..8cf549b79c2 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNameRef.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNameRef.java @@ -79,4 +79,14 @@ public final class JsNameRef extends JsExpressionImpl implements HasName { visitor.accept(qualifier); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + if (qualifier != null) { + qualifier = v.accept(qualifier); + } + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNew.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNew.java index a5283f284c0..3c7597059ff 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNew.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNew.java @@ -34,4 +34,13 @@ public final class JsNew extends JsExpressionImpl.JsExpressionHasArguments { visitor.accept(constructorExpression); visitor.acceptList(arguments); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + constructorExpression = v.accept(constructorExpression); + v.acceptList(arguments); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNode.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNode.java index 6d2ad279985..d6abdf60976 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNode.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNode.java @@ -27,4 +27,12 @@ public interface JsNode { void setSource(Object info); JsNode source(Object info); + + /** + * Causes this object to have the visitor visit itself and its children. + * + * @param visitor the visitor that should traverse this node + * @param ctx the context of an existing traversal + */ + void traverse(JsVisitorWithContext visitor, JsContext ctx); } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNullLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNullLiteral.java index 8aec6b41e16..8ae1b0ebed7 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNullLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNullLiteral.java @@ -12,4 +12,10 @@ public final class JsNullLiteral extends JsLiteral.JsValueLiteral { public void accept(JsVisitor v) { v.visitNull(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNumberLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNumberLiteral.java index 0021adcd33a..cc881eb6fb6 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNumberLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsNumberLiteral.java @@ -22,6 +22,12 @@ public abstract class JsNumberLiteral extends JsLiteral.JsValueLiteral { public String toString() { return String.valueOf(value); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } public static final class JsIntLiteral extends JsNumberLiteral { @@ -39,5 +45,11 @@ public abstract class JsNumberLiteral extends JsLiteral.JsValueLiteral { public String toString() { return String.valueOf(value); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsObjectLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsObjectLiteral.java index efa53053914..cf0288f0a39 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsObjectLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsObjectLiteral.java @@ -47,4 +47,12 @@ public final class JsObjectLiteral extends JsLiteral { public void acceptChildren(JsVisitor visitor) { visitor.acceptWithInsertRemove(properties); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptList(properties); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsParameter.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsParameter.java index 3a73c5108e3..3893c8290ad 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsParameter.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsParameter.java @@ -34,4 +34,10 @@ public final class JsParameter extends SourceInfoAwareJsNode implements HasName public void accept(JsVisitor v) { v.visitParameter(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPostfixOperation.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPostfixOperation.java index df59b0d1f5a..3e6ff5a804a 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPostfixOperation.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPostfixOperation.java @@ -17,4 +17,12 @@ public final class JsPostfixOperation extends JsUnaryOperation { public void accept(JsVisitor v) { v.visitPostfixOperation(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + super.traverse(v, ctx); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPrefixOperation.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPrefixOperation.java index 552d2e9eec2..4ffac01d0a4 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPrefixOperation.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPrefixOperation.java @@ -17,4 +17,12 @@ public final class JsPrefixOperation extends JsUnaryOperation { public void accept(JsVisitor v) { v.visitPrefixOperation(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + super.traverse(v, ctx); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgram.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgram.java index 359ff6a59e0..5a709d7576b 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgram.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgram.java @@ -129,4 +129,14 @@ public final class JsProgram extends SourceInfoAwareJsNode { visitor.accept(fragment); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + for (JsProgramFragment fragment : fragments) { + v.accept(fragment); + } + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgramFragment.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgramFragment.java index e9691878c11..fe871bbc78e 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgramFragment.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsProgramFragment.java @@ -27,4 +27,12 @@ public class JsProgramFragment extends SourceInfoAwareJsNode { public void acceptChildren(JsVisitor visitor) { visitor.accept(globalBlock); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.accept(globalBlock); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPropertyInitializer.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPropertyInitializer.java index f38885b7316..2acfea7243c 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPropertyInitializer.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsPropertyInitializer.java @@ -44,4 +44,13 @@ public class JsPropertyInitializer extends SourceInfoAwareJsNode { visitor.accept(labelExpr); visitor.accept(valueExpr); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + labelExpr = v.accept(labelExpr); + valueExpr = v.accept(valueExpr); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsRegExp.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsRegExp.java index e958b368f39..822707919b3 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsRegExp.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsRegExp.java @@ -31,4 +31,10 @@ public final class JsRegExp extends JsLiteral.JsValueLiteral { public void accept(JsVisitor v) { v.visitRegExp(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsReturn.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsReturn.java index 93c0106d802..0632fd84bbb 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsReturn.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsReturn.java @@ -36,4 +36,14 @@ public final class JsReturn extends SourceInfoAwareJsNode implements JsStatement visitor.accept(expression); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + if (expression != null) { + expression = v.accept(expression); + } + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java index 08d9d40fbf7..0a80d7d0ddb 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java @@ -6,14 +6,14 @@ package com.google.dart.compiler.backend.js.ast; public final class JsStringLiteral extends JsLiteral.JsValueLiteral { - private final String value; + private final String value; - // These only get created by JsProgram so that they can be interned. - JsStringLiteral(String value) { + // These only get created by JsProgram so that they can be interned. + JsStringLiteral(String value) { this.value = value; } - public String getValue() { + public String getValue() { return value; } @@ -21,4 +21,10 @@ public final class JsStringLiteral extends JsLiteral.JsValueLiteral { public void accept(JsVisitor v) { v.visitString(this); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + v.visit(this, ctx); + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java index 763c6c1feeb..5459f880ee5 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java @@ -41,4 +41,13 @@ public class JsSwitch extends SourceInfoAwareJsNode implements JsStatement { visitor.accept(expression); visitor.acceptWithInsertRemove(cases); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + expression = v.accept(expression); + v.acceptList(cases); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsThrow.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsThrow.java index c7814d73c58..2648f4a4cbc 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsThrow.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsThrow.java @@ -31,4 +31,12 @@ public class JsThrow extends SourceInfoAwareJsNode implements JsStatement { public void acceptChildren(JsVisitor visitor) { visitor.accept(expression); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + expression = v.accept(expression); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsTry.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsTry.java index f559b340fd6..568b49861a0 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsTry.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsTry.java @@ -60,4 +60,16 @@ public class JsTry extends SourceInfoAwareJsNode implements JsStatement { visitor.accept(finallyBlock); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + tryBlock = v.accept(tryBlock); + v.acceptList(catches); + if (finallyBlock != null) { + finallyBlock = v.accept(finallyBlock); + } + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsUnaryOperation.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsUnaryOperation.java index 9e5d1b360c3..d5d4d971734 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsUnaryOperation.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsUnaryOperation.java @@ -43,4 +43,17 @@ public abstract class JsUnaryOperation extends JsExpressionImpl { visitor.accept(arg); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (op.isModifying()) { + /* + * The delete operator is practically like an assignment of undefined, so for practical + * purposes we're treating it as an lvalue. + */ + arg = v.acceptLvalue(arg); + } else { + arg = v.accept(arg); + } + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVars.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVars.java index b13ed1acede..cdf4461c768 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVars.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVars.java @@ -88,6 +88,16 @@ public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterab visitor.accept(initExpression); } } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + if (initExpression != null) { + initExpression = v.accept(initExpression); + } + } + v.endVisit(this, ctx); + } } public void add(JsVar var) { @@ -126,4 +136,12 @@ public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterab public void acceptChildren(JsVisitor visitor) { visitor.acceptWithInsertRemove(vars); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + v.acceptList(vars); + } + v.endVisit(this, ctx); + } } diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContext.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContext.java new file mode 100644 index 00000000000..6ff6b7d1c75 --- /dev/null +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContext.java @@ -0,0 +1,366 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.compiler.backend.js.ast; + +/** + * Taken from GWT project with modifications. + * Original: + * repository: https://gwt.googlesource.com/gwt + * revision: e32bf0a95029165d9e6ab457c7ee7ca8b07b908c + * file: dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java + */ + +import java.util.List; + +/** + * Implemented by nodes that will visit child nodes. + */ +@SuppressWarnings("UnusedParameters") +public abstract class JsVisitorWithContext { + + public final T accept(T node) { + return doAccept(node); + } + + public JsExpression acceptLvalue(JsExpression expr) { + return doAcceptLvalue(expr); + } + + public final void acceptList(List collection) { + doAcceptList(collection); + } + + public final T acceptStatement(T statement) { + //noinspection unchecked + return (T) doAcceptStatement(statement); + } + + public final void acceptStatementList(List statements) { + doAcceptStatementList(statements); + } + + public void endVisit(JsArrayAccess x, JsContext ctx) { + } + + public void endVisit(JsArrayLiteral x, JsContext ctx) { + } + + public void endVisit(JsBinaryOperation x, JsContext ctx) { + } + + public void endVisit(JsBlock x, JsContext ctx) { + } + + public void endVisit(JsLiteral.JsBooleanLiteral x, JsContext ctx) { + } + + public void endVisit(JsBreak x, JsContext ctx) { + } + + public void endVisit(JsCase x, JsContext ctx) { + } + + public void endVisit(JsCatch x, JsContext ctx) { + } + + public void endVisit(JsConditional x, JsContext ctx) { + } + + public void endVisit(JsContinue x, JsContext ctx) { + } + + public void endVisit(JsDebugger x, JsContext ctx) { + } + + public void endVisit(JsDefault x, JsContext ctx) { + } + + public void endVisit(JsDoWhile x, JsContext ctx) { + } + + public void endVisit(JsEmpty x, JsContext ctx) { + } + + public void endVisit(JsExpressionStatement x, JsContext ctx) { + } + + public void endVisit(JsFor x, JsContext ctx) { + } + + public void endVisit(JsForIn x, JsContext ctx) { + } + + public void endVisit(JsFunction x, JsContext ctx) { + } + + public void endVisit(JsIf x, JsContext ctx) { + } + + public void endVisit(JsInvocation x, JsContext ctx) { + } + + public void endVisit(JsLabel x, JsContext ctx) { + } + + public void endVisit(JsName x, JsContext ctx) { + } + + public void endVisit(JsNameRef x, JsContext ctx) { + } + + public void endVisit(JsNew x, JsContext ctx) { + } + + public void endVisit(JsNullLiteral x, JsContext ctx) { + } + + public void endVisit(JsNumberLiteral x, JsContext ctx) { + } + + public void endVisit(JsObjectLiteral x, JsContext ctx) { + } + + public void endVisit(JsParameter x, JsContext ctx) { + } + + public void endVisit(JsPostfixOperation x, JsContext ctx) { + } + + public void endVisit(JsPrefixOperation x, JsContext ctx) { + } + + public void endVisit(JsProgram x, JsContext ctx) { + } + + public void endVisit(JsProgramFragment x, JsContext ctx) { + } + + public void endVisit(JsPropertyInitializer x, JsContext ctx) { + } + + public void endVisit(JsRegExp x, JsContext ctx) { + } + + public void endVisit(JsReturn x, JsContext ctx) { + } + + public void endVisit(JsStringLiteral x, JsContext ctx) { + } + + public void endVisit(JsSwitch x, JsContext ctx) { + } + + public void endVisit(JsLiteral.JsThisRef x, JsContext ctx) { + } + + public void endVisit(JsThrow x, JsContext ctx) { + } + + public void endVisit(JsTry x, JsContext ctx) { + } + + public void endVisit(JsVars.JsVar x, JsContext ctx) { + } + + public void endVisit(JsVars x, JsContext ctx) { + } + + public void endVisit(JsWhile x, JsContext ctx) { + } + + public boolean visit(JsArrayAccess x, JsContext ctx) { + return true; + } + + public boolean visit(JsArrayLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsBinaryOperation x, JsContext ctx) { + return true; + } + + public boolean visit(JsBlock x, JsContext ctx) { + return true; + } + + public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsBreak x, JsContext ctx) { + return true; + } + + public boolean visit(JsCase x, JsContext ctx) { + return true; + } + + public boolean visit(JsCatch x, JsContext ctx) { + return true; + } + + public boolean visit(JsConditional x, JsContext ctx) { + return true; + } + + public boolean visit(JsContinue x, JsContext ctx) { + return true; + } + + public boolean visit(JsDebugger x, JsContext ctx) { + return true; + } + + public boolean visit(JsDefault x, JsContext ctx) { + return true; + } + + public boolean visit(JsDoWhile x, JsContext ctx) { + return true; + } + + public boolean visit(JsEmpty x, JsContext ctx) { + return true; + } + + public boolean visit(JsExpressionStatement x, JsContext ctx) { + return true; + } + + public boolean visit(JsFor x, JsContext ctx) { + return true; + } + + public boolean visit(JsForIn x, JsContext ctx) { + return true; + } + + public boolean visit(JsFunction x, JsContext ctx) { + return true; + } + + public boolean visit(JsIf x, JsContext ctx) { + return true; + } + + public boolean visit(JsInvocation x, JsContext ctx) { + return true; + } + + public boolean visit(JsLabel x, JsContext ctx) { + return true; + } + + public boolean visit(JsName x, JsContext ctx) { + return true; + } + + public boolean visit(JsNameRef x, JsContext ctx) { + return true; + } + + public boolean visit(JsNew x, JsContext ctx) { + return true; + } + + public boolean visit(JsNullLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsNumberLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsObjectLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsParameter x, JsContext ctx) { + return true; + } + + public boolean visit(JsPostfixOperation x, JsContext ctx) { + return true; + } + + public boolean visit(JsPrefixOperation x, JsContext ctx) { + return true; + } + + public boolean visit(JsProgram x, JsContext ctx) { + return true; + } + + public boolean visit(JsProgramFragment x, JsContext ctx) { + return true; + } + + public boolean visit(JsPropertyInitializer x, JsContext ctx) { + return true; + } + + public boolean visit(JsRegExp x, JsContext ctx) { + return true; + } + + public boolean visit(JsReturn x, JsContext ctx) { + return true; + } + + public boolean visit(JsStringLiteral x, JsContext ctx) { + return true; + } + + public boolean visit(JsSwitch x, JsContext ctx) { + return true; + } + + public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) { + return true; + } + + public boolean visit(JsThrow x, JsContext ctx) { + return true; + } + + public boolean visit(JsTry x, JsContext ctx) { + return true; + } + + public boolean visit(JsVars.JsVar x, JsContext ctx) { + return true; + } + + public boolean visit(JsVars x, JsContext ctx) { + return true; + } + + public boolean visit(JsWhile x, JsContext ctx) { + return true; + } + + protected abstract T doAccept(T node); + + protected abstract JsExpression doAcceptLvalue(JsExpression expr); + + protected abstract void doAcceptList(List collection); + + protected abstract JsStatement doAcceptStatement(T statement); + + protected abstract void doAcceptStatementList(List statements); + + protected abstract void doTraverse(T node, JsContext ctx) ; +} diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContextImpl.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContextImpl.java new file mode 100644 index 00000000000..2114ac86054 --- /dev/null +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsVisitorWithContextImpl.java @@ -0,0 +1,210 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.compiler.backend.js.ast; + +/** + * Taken from GWT project with modifications. + * Original: + * repository: https://gwt.googlesource.com/gwt + * revision: e32bf0a95029165d9e6ab457c7ee7ca8b07b908c + * file: dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java + */ + +import com.intellij.util.SmartList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Stack; + +/** + * A visitor for iterating through and modifying an AST. + */ +public class JsVisitorWithContextImpl extends JsVisitorWithContext { + + private final Stack statementContexts = new Stack(); + + public class ListContext implements JsContext { + private List collection; + private int index; + + @Override + public boolean canInsert() { + return true; + } + + @Override + public boolean canRemove() { + return true; + } + + @Override + public void insertAfter(JsNode node) { + //noinspection unchecked + collection.add(index + 1, (T) node); + } + + @Override + public void insertBefore(JsNode node) { + //noinspection unchecked + collection.add(index++, (T) node); + } + + @Override + public boolean isLvalue() { + return false; + } + + @Override + public void removeMe() { + collection.remove(index--); + } + + @Override + public void replaceMe(JsNode node) { + checkReplacement(collection.get(index), node); + //noinspection unchecked + collection.set(index, (T) node); + } + + @Nullable + @Override + public JsNode getCurrentNode() { + if (index < collection.size()) { + return collection.get(index); + } + + return null; + } + + protected void traverse(List collection) { + this.collection = collection; + for (index = 0; index < collection.size(); ++index) { + T node = collection.get(index); + doTraverse(node, this); + } + } + } + + private class LvalueContext extends NodeContext { + @Override + public boolean isLvalue() { + return true; + } + } + + @SuppressWarnings("unchecked") + private class NodeContext implements JsContext { + protected T node; + + @Override + public boolean canInsert() { + return false; + } + + @Override + public boolean canRemove() { + return false; + } + + @Override + public void insertAfter(JsNode node) { + throw new UnsupportedOperationException(); + } + + @Override + public void insertBefore(JsNode node) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLvalue() { + return false; + } + + @Override + public void removeMe() { + throw new UnsupportedOperationException(); + } + + @Override + public void replaceMe(JsNode node) { + checkReplacement(this.node, node); + this.node = (T) node; + } + + @Nullable + @Override + public JsNode getCurrentNode() { + return node; + } + + protected T traverse(T node) { + this.node = node; + doTraverse(node, this); + return this.node; + } + } + + protected static void checkReplacement(@SuppressWarnings("UnusedParameters") JsNode origNode, JsNode newNode) { + if (newNode == null) throw new RuntimeException("Cannot replace with null"); + } + + @Override + protected T doAccept(T node) { + return new NodeContext().traverse(node); + } + + @Override + protected JsExpression doAcceptLvalue(JsExpression expr) { + return new LvalueContext().traverse(expr); + } + + @Override + protected JsStatement doAcceptStatement(T statement) { + List statements = new SmartList(statement); + doAcceptStatementList(statements); + + if (statements.size() == 1) { + return statements.get(0); + } + + return new JsBlock(statements); + } + + @Override + protected void doAcceptStatementList(List statements) { + ListContext context = new ListContext(); + statementContexts.push(context); + context.traverse(statements); + statementContexts.pop(); + } + + @Override + protected void doAcceptList(List collection) { + new ListContext().traverse(collection); + } + + @NotNull + protected JsContext getLastStatementLevelContext() { + return statementContexts.peek(); + } + + @Override + protected void doTraverse(T node, JsContext ctx) { + node.traverse(this, ctx); + } + +} diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsWhile.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsWhile.java index aeaba3921e7..0e4c2a845fd 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsWhile.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsWhile.java @@ -45,4 +45,13 @@ public class JsWhile extends SourceInfoAwareJsNode implements JsStatement { visitor.accept(condition); visitor.accept(body); } + + @Override + public void traverse(JsVisitorWithContext v, JsContext ctx) { + if (v.visit(this, ctx)) { + condition = v.accept(condition); + body = v.acceptStatement(body); + } + v.endVisit(this, ctx); + } } \ No newline at end of file