JS: added type parameter to JsContext

This commit is contained in:
Alexey Tsvetkov
2015-03-27 15:58:39 +03:00
parent efba2a2372
commit e94c79f838
13 changed files with 50 additions and 52 deletions
@@ -11,21 +11,21 @@ import org.jetbrains.annotations.Nullable;
* possible operations a JsVisitor subclass can perform on the currently visited * possible operations a JsVisitor subclass can perform on the currently visited
* node. * node.
*/ */
public interface JsContext { public abstract class JsContext<T extends JsNode> {
boolean canInsert(); public abstract boolean canInsert();
boolean canRemove(); public abstract boolean canRemove();
void insertAfter(JsNode node); public abstract <R extends T> void insertAfter(R node);
void insertBefore(JsNode node); public abstract <R extends T> void insertBefore(R node);
boolean isLvalue(); public abstract boolean isLvalue();
void removeMe(); public abstract void removeMe();
void replaceMe(JsNode node); public abstract <R extends T> void replaceMe(R node);
@Nullable @Nullable
JsNode getCurrentNode(); public abstract T getCurrentNode();
} }
@@ -10,7 +10,7 @@ public object JsEmpty : SourceInfoAwareJsNode(), JsStatement {
v.visitEmpty(this) v.visitEmpty(this)
} }
override fun traverse(v: JsVisitorWithContext, ctx: JsContext) { override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) {
v.visit(this, ctx) v.visit(this, ctx)
v.endVisit(this, ctx) v.endVisit(this, ctx)
} }
@@ -47,7 +47,7 @@ public abstract class JsVisitorWithContext {
return (T) doAcceptStatement(statement); return (T) doAcceptStatement(statement);
} }
public final <T extends JsStatement> void acceptStatementList(List<T> statements) { public final void acceptStatementList(List<JsStatement> statements) {
doAcceptStatementList(statements); doAcceptStatementList(statements);
} }
@@ -360,7 +360,7 @@ public abstract class JsVisitorWithContext {
protected abstract <T extends JsStatement> JsStatement doAcceptStatement(T statement); protected abstract <T extends JsStatement> JsStatement doAcceptStatement(T statement);
protected abstract <T extends JsStatement> void doAcceptStatementList(List<T> statements); protected abstract void doAcceptStatementList(List<JsStatement> statements);
protected abstract <T extends JsNode> void doTraverse(T node, JsContext ctx) ; protected abstract <T extends JsNode> void doTraverse(T node, JsContext ctx) ;
} }
@@ -34,9 +34,9 @@ import java.util.Stack;
*/ */
public class JsVisitorWithContextImpl extends JsVisitorWithContext { public class JsVisitorWithContextImpl extends JsVisitorWithContext {
private final Stack<JsContext> statementContexts = new Stack<JsContext>(); private final Stack<JsContext<JsStatement>> statementContexts = new Stack<JsContext<JsStatement>>();
public class ListContext<T extends JsNode> implements JsContext { public class ListContext<T extends JsNode> extends JsContext<T> {
private List<T> collection; private List<T> collection;
private int index; private int index;
@@ -51,13 +51,13 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@Override @Override
public void insertAfter(JsNode node) { public <R extends T> void insertAfter(R node) {
//noinspection unchecked //noinspection unchecked
collection.add(index + 1, (T) node); collection.add(index + 1, (T) node);
} }
@Override @Override
public void insertBefore(JsNode node) { public <R extends T> void insertBefore(R node) {
//noinspection unchecked //noinspection unchecked
collection.add(index++, (T) node); collection.add(index++, (T) node);
} }
@@ -73,15 +73,14 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@Override @Override
public void replaceMe(JsNode node) { public <R extends T> void replaceMe(R node) {
checkReplacement(collection.get(index), node); checkReplacement(collection.get(index), node);
//noinspection unchecked collection.set(index, node);
collection.set(index, (T) node);
} }
@Nullable @Nullable
@Override @Override
public JsNode getCurrentNode() { public T getCurrentNode() {
if (index < collection.size()) { if (index < collection.size()) {
return collection.get(index); return collection.get(index);
} }
@@ -105,8 +104,7 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
} }
@SuppressWarnings("unchecked") private class NodeContext<T extends JsNode> extends JsContext<T> {
private class NodeContext<T extends JsNode> implements JsContext {
protected T node; protected T node;
@Override @Override
@@ -120,12 +118,12 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@Override @Override
public void insertAfter(JsNode node) { public <R extends T> void insertAfter(R node) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void insertBefore(JsNode node) { public <R extends T> void insertBefore(R node) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@@ -140,14 +138,14 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@Override @Override
public void replaceMe(JsNode node) { public <R extends T> void replaceMe(R node) {
checkReplacement(this.node, node); checkReplacement(this.node, node);
this.node = (T) node; this.node = node;
} }
@Nullable @Nullable
@Override @Override
public JsNode getCurrentNode() { public T getCurrentNode() {
return node; return node;
} }
@@ -185,8 +183,8 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@Override @Override
protected <T extends JsStatement> void doAcceptStatementList(List<T> statements) { protected void doAcceptStatementList(List<JsStatement> statements) {
ListContext<T> context = new ListContext<T>(); ListContext<JsStatement> context = new ListContext<JsStatement>();
statementContexts.push(context); statementContexts.push(context);
context.traverse(statements); context.traverse(statements);
statementContexts.pop(); statementContexts.pop();
@@ -198,7 +196,7 @@ public class JsVisitorWithContextImpl extends JsVisitorWithContext {
} }
@NotNull @NotNull
protected JsContext getLastStatementLevelContext() { protected JsContext<JsStatement> getLastStatementLevelContext() {
return statementContexts.peek(); return statementContexts.peek();
} }
@@ -149,7 +149,7 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) {
} }
val visitor = object: JsVisitorWithContextImpl() { val visitor = object: JsVisitorWithContextImpl() {
override fun endVisit(x: JsInvocation?, ctx: JsContext?) { override fun endVisit(x: JsInvocation?, ctx: JsContext<*>?) {
if (x == null || ctx == null) return if (x == null || ctx == null) return
val qualifier: JsExpression? val qualifier: JsExpression?
@@ -180,7 +180,7 @@ private fun replaceExternalNames(function: JsFunction, externalReplacements: Map
if (replacements.isEmpty()) return if (replacements.isEmpty()) return
val visitor = object: JsVisitorWithContextImpl() { val visitor = object: JsVisitorWithContextImpl() {
override fun endVisit(x: JsNameRef?, ctx: JsContext?) { override fun endVisit(x: JsNameRef?, ctx: JsContext<*>?) {
if (x == null || x.getQualifier() != null) return if (x == null || x.getQualifier() != null) return
replacements[x.getIdent()]?.let { replacements[x.getIdent()]?.let {
@@ -22,7 +22,7 @@ import com.google.dart.compiler.backend.js.ast.JsContext
private class NodeRemover<T>(val klass: Class<T>, val predicate: (T) -> Boolean): JsVisitorWithContextImpl() { private class NodeRemover<T>(val klass: Class<T>, val predicate: (T) -> Boolean): JsVisitorWithContextImpl() {
override fun <T : JsNode?> doTraverse(node: T?, ctx: JsContext?) { override fun <T : JsNode?> doTraverse(node: T?, ctx: JsContext<*>?) {
if (node == null || ctx == null) return if (node == null || ctx == null) return
if (klass.isInstance(node)) { if (klass.isInstance(node)) {
@@ -66,7 +66,7 @@ private class UnusedLocalFunctionsCollector(functions: Map<JsName, JsFunction>)
} }
} }
override fun visit(x: JsPropertyInitializer?, ctx: JsContext?): Boolean { override fun visit(x: JsPropertyInitializer?, ctx: JsContext<*>?): Boolean {
val value = x?.getValueExpr() val value = x?.getValueExpr()
return when (value) { return when (value) {
@@ -75,17 +75,17 @@ private class UnusedLocalFunctionsCollector(functions: Map<JsName, JsFunction>)
} }
} }
override fun visit(x: JsFunction?, ctx: JsContext?): Boolean { override fun visit(x: JsFunction?, ctx: JsContext<*>?): Boolean {
return !(wasProcessed(x)) return !(wasProcessed(x))
} }
override fun endVisit(x: JsFunction?, ctx: JsContext?) { override fun endVisit(x: JsFunction?, ctx: JsContext<*>?) {
if (x == null) return if (x == null) return
processed.add(x) processed.add(x)
} }
override fun endVisit(x: JsNameRef?, ctx: JsContext?) { override fun endVisit(x: JsNameRef?, ctx: JsContext<*>?) {
val name = x?.getName() val name = x?.getName()
if (isFunctionReference(x) && name != null) { if (isFunctionReference(x) && name != null) {
tracker.markReachable(name) tracker.markReachable(name)
@@ -45,7 +45,7 @@ private class UnusedInstanceCollector : JsVisitorWithContextImpl() {
public val removableDeclarations: List<JsStatement> public val removableDeclarations: List<JsStatement>
get() = tracker.removable get() = tracker.removable
override fun visit(x: JsVars.JsVar?, ctx: JsContext?): Boolean { override fun visit(x: JsVars.JsVar?, ctx: JsContext<*>?): Boolean {
if (x == null) return false if (x == null) return false
if (!isLocalFunctionDeclaration(x)) return super.visit(x, ctx) if (!isLocalFunctionDeclaration(x)) return super.visit(x, ctx)
@@ -64,7 +64,7 @@ private class UnusedInstanceCollector : JsVisitorWithContextImpl() {
return false return false
} }
override fun visit(x: JsNameRef?, ctx: JsContext?): Boolean { override fun visit(x: JsNameRef?, ctx: JsContext<*>?): Boolean {
val name = x?.getName() val name = x?.getName()
if (name != null) { if (name != null) {
@@ -28,7 +28,7 @@ class ReferenceNameCollector : JsVisitorWithContextImpl() {
public val references: List<JsName> public val references: List<JsName>
get() = referenceSet.toList() get() = referenceSet.toList()
override fun endVisit(x: JsNameRef?, ctx: JsContext?) { override fun endVisit(x: JsNameRef?, ctx: JsContext<*>?) {
val name = x?.getName() val name = x?.getName()
if (name != null) { if (name != null) {
referenceSet.add(name) referenceSet.add(name)
@@ -24,9 +24,9 @@ import com.google.dart.compiler.backend.js.ast.JsContext
import com.google.dart.compiler.backend.js.ast.JsLabel import com.google.dart.compiler.backend.js.ast.JsLabel
class LabelNameRefreshingVisitor(val context: NamingContext, val functionScope: JsFunctionScope) : JsVisitorWithContextImpl() { class LabelNameRefreshingVisitor(val context: NamingContext, val functionScope: JsFunctionScope) : JsVisitorWithContextImpl() {
override fun visit(x: JsFunction?, ctx: JsContext?): Boolean = false override fun visit(x: JsFunction?, ctx: JsContext<*>?): Boolean = false
override fun visit(x: JsLabel?, ctx: JsContext?): Boolean { override fun visit(x: JsLabel?, ctx: JsContext<*>?): Boolean {
val labelName = x!!.getName() val labelName = x!!.getName()
val freshName = functionScope.enterLabel(labelName.getIdent()) val freshName = functionScope.enterLabel(labelName.getIdent())
@@ -37,7 +37,7 @@ class LabelNameRefreshingVisitor(val context: NamingContext, val functionScope:
return super.visit(x, ctx) return super.visit(x, ctx)
} }
override fun endVisit(x: JsLabel?, ctx: JsContext?) { override fun endVisit(x: JsLabel?, ctx: JsContext<*>?) {
super.endVisit(x, ctx) super.endVisit(x, ctx)
functionScope.exitLabel() functionScope.exitLabel()
} }
@@ -27,7 +27,7 @@ import com.google.dart.compiler.backend.js.ast.JsLabel
class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) : JsVisitorWithContextImpl() { class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) : JsVisitorWithContextImpl() {
override fun endVisit(x: JsNameRef?, ctx: JsContext?) { override fun endVisit(x: JsNameRef?, ctx: JsContext<*>?) {
if (x == null || ctx == null) return if (x == null || ctx == null) return
val replacement = replaceMap[x.getName()] val replacement = replaceMap[x.getName()]
@@ -36,7 +36,7 @@ class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) :
ctx.replaceMe(replacement) ctx.replaceMe(replacement)
} }
override fun endVisit(x: JsVars.JsVar?, ctx: JsContext?) { override fun endVisit(x: JsVars.JsVar?, ctx: JsContext<*>?) {
if (x == null || ctx == null) return if (x == null || ctx == null) return
val replacement = replaceMap[x.getName()] val replacement = replaceMap[x.getName()]
@@ -46,7 +46,7 @@ class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) :
} }
} }
override fun endVisit(x: JsLabel?, ctx: JsContext?) { override fun endVisit(x: JsLabel?, ctx: JsContext<*>?) {
if (x == null || ctx == null) return if (x == null || ctx == null) return
val replacement = replaceMap[x.getName()] val replacement = replaceMap[x.getName()]
@@ -33,14 +33,14 @@ class ReturnReplacingVisitor(private val resultRef: JsNameRef?, private val brea
/** /**
* Prevents replacing returns in object literal * Prevents replacing returns in object literal
*/ */
override fun visit(x: JsObjectLiteral?, ctx: JsContext?): Boolean = false override fun visit(x: JsObjectLiteral?, ctx: JsContext<*>?): Boolean = false
/** /**
* Prevents replacing returns in inner function * Prevents replacing returns in inner function
*/ */
override fun visit(x: JsFunction?, ctx: JsContext?): Boolean = false override fun visit(x: JsFunction?, ctx: JsContext<*>?): Boolean = false
override fun endVisit(x: JsReturn?, ctx: JsContext?) { override fun endVisit(x: JsReturn?, ctx: JsContext<*>?) {
if (x == null || ctx == null) return if (x == null || ctx == null) return
if (breakLabel != null) { if (breakLabel != null) {
@@ -24,11 +24,11 @@ import com.google.dart.compiler.backend.js.ast.JsObjectLiteral
import com.google.dart.compiler.backend.js.ast.JsVisitorWithContextImpl import com.google.dart.compiler.backend.js.ast.JsVisitorWithContextImpl
class ThisReplacingVisitor(private val thisReplacement: JsExpression) : JsVisitorWithContextImpl() { class ThisReplacingVisitor(private val thisReplacement: JsExpression) : JsVisitorWithContextImpl() {
override fun endVisit(x: JsLiteral.JsThisRef?, ctx: JsContext?) { override fun endVisit(x: JsLiteral.JsThisRef?, ctx: JsContext<*>?) {
ctx?.replaceMe(thisReplacement) ctx?.replaceMe(thisReplacement)
} }
override fun visit(x: JsFunction?, ctx: JsContext?) = false override fun visit(x: JsFunction?, ctx: JsContext<*>?) = false
override fun visit(x: JsObjectLiteral?, ctx: JsContext?) = false override fun visit(x: JsObjectLiteral?, ctx: JsContext<*>?) = false
} }