new special parent scope for cases where JavaScript redefines a variable using a reference to the existing definition
This commit is contained in:
parent
32f8672068
commit
e58ec4dba8
|
@ -106,6 +106,9 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
|||
import com.ibm.wala.cast.tree.CAstType;
|
||||
import com.ibm.wala.cast.tree.impl.CAstOperator;
|
||||
import com.ibm.wala.cast.tree.impl.CAstSymbolImpl;
|
||||
import com.ibm.wala.cast.tree.visit.CAstVisitor;
|
||||
import com.ibm.wala.cast.tree.visit.CAstVisitor.Context;
|
||||
import com.ibm.wala.cast.util.CAstPattern;
|
||||
import com.ibm.wala.classLoader.SourceModule;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
@ -511,8 +514,11 @@ public class RhinoToAstTranslator {
|
|||
// new first statement will be a block declaring all names.
|
||||
CAstNode[] newStmts = new CAstNode[stmts.length + 1];
|
||||
|
||||
newStmts[0] = Ast.makeNode(CAstNode.BLOCK_STMT, child.getNameDecls().toArray(new CAstNode[child.getNameDecls().size()]));
|
||||
|
||||
if (child.getNameDecls().size() == 1) {
|
||||
newStmts[0] = child.getNameDecls().iterator().next();
|
||||
} else {
|
||||
newStmts[0] = Ast.makeNode(CAstNode.BLOCK_STMT, child.getNameDecls().toArray(new CAstNode[child.getNameDecls().size()]));
|
||||
}
|
||||
System.arraycopy(stmts, 0, newStmts, 1, stmts.length);
|
||||
|
||||
stmts = newStmts;
|
||||
|
@ -1385,14 +1391,37 @@ public class RhinoToAstTranslator {
|
|||
if (init.getInitializer() == null) {
|
||||
children[i++] = Ast.makeNode(CAstNode.EMPTY);
|
||||
} else {
|
||||
CAstNode initCode = visit(init, arg);
|
||||
|
||||
CAstPattern nameVarPattern = CAstPattern.parse("VAR(\"" + init.getTarget().getString() + "\")");
|
||||
if (! nameVarPattern.new Matcher() {
|
||||
@Override
|
||||
protected boolean enterEntity(CAstEntity n, Context context, CAstVisitor<Context> visitor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doVisit(CAstNode n, Context context, CAstVisitor<Context> visitor) {
|
||||
return true;
|
||||
}
|
||||
}.findAll(null, initCode).isEmpty()) {
|
||||
initCode =
|
||||
Ast.makeNode(CAstNode.SPECIAL_PARENT_SCOPE,
|
||||
Ast.makeConstant(init.getTarget().getString()),
|
||||
initCode);
|
||||
|
||||
}
|
||||
|
||||
children[i++] =
|
||||
Ast.makeNode(CAstNode.ASSIGN,
|
||||
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(init.getTarget().getString())),
|
||||
visit(init, arg));
|
||||
Ast.makeNode(CAstNode.ASSIGN, readName(arg, null, init.getTarget().getString()),initCode);
|
||||
}
|
||||
}
|
||||
|
||||
return Ast.makeNode(CAstNode.BLOCK_STMT, children);
|
||||
if (i == 1) {
|
||||
return children[0];
|
||||
} else {
|
||||
return Ast.makeNode(CAstNode.BLOCK_STMT, children);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -163,6 +163,7 @@ public interface CAstNode {
|
|||
|
||||
// explicit lexical scopes
|
||||
public static final int LOCAL_SCOPE = 200;
|
||||
public static final int SPECIAL_PARENT_SCOPE = 201;
|
||||
|
||||
// literal expression kinds
|
||||
public static final int CONSTANT = 300;
|
||||
|
|
|
@ -416,7 +416,7 @@ public abstract class CAstVisitor<C extends CAstVisitor.Context> {
|
|||
*/
|
||||
public final void visit(final CAstNode n, C context, CAstVisitor<C> visitor) {
|
||||
Position restore = currentPosition;
|
||||
if (context.getSourceMap() != null) {
|
||||
if (context != null && context.getSourceMap() != null) {
|
||||
Position p = context.getSourceMap().getPosition(n);
|
||||
if (p != null) {
|
||||
currentPosition = p;
|
||||
|
@ -451,6 +451,15 @@ public abstract class CAstVisitor<C extends CAstVisitor.Context> {
|
|||
break;
|
||||
}
|
||||
|
||||
case CAstNode.SPECIAL_PARENT_SCOPE: {
|
||||
if (visitor.visitSpecialParentScope(n, context, visitor))
|
||||
break;
|
||||
C localContext = visitor.makeSpecialParentContext(context, n);
|
||||
visitor.visit(n.getChild(1), localContext, visitor);
|
||||
visitor.leaveSpecialParentScope(n, context, visitor);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAstNode.BLOCK_EXPR: {
|
||||
if (visitor.visitBlockExpr(n, context, visitor))
|
||||
break;
|
||||
|
@ -818,7 +827,7 @@ public abstract class CAstVisitor<C extends CAstVisitor.Context> {
|
|||
visitor.leaveTypeLiteralExpr(n, context, visitor);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CAstNode.IS_DEFINED_EXPR: {
|
||||
if (visitor.visitIsDefinedExpr(n, context, visitor)) {
|
||||
break;
|
||||
|
@ -875,6 +884,18 @@ public abstract class CAstVisitor<C extends CAstVisitor.Context> {
|
|||
currentPosition = restore;
|
||||
}
|
||||
|
||||
protected void leaveSpecialParentScope(CAstNode n, C context, CAstVisitor<C> visitor) {
|
||||
visitor.leaveNode(n, context, visitor);
|
||||
}
|
||||
|
||||
protected C makeSpecialParentContext(C context, CAstNode n) {
|
||||
return context;
|
||||
}
|
||||
|
||||
protected boolean visitSpecialParentScope(CAstNode n, C context, CAstVisitor<C> visitor) {
|
||||
return visitor.visitNode(n, context, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given array reference node. Factored out so that derived languages can reuse this
|
||||
* code for specially-marked types of array references (as in X10, for which different instruction
|
||||
|
|
|
@ -1314,4 +1314,25 @@ public abstract class DelegatingCAstVisitor<C extends CAstVisitor.Context> exten
|
|||
protected void leaveInstanceOf(CAstNode n, C c, CAstVisitor<C> visitor) {
|
||||
delegate.leaveInstanceOf(n, c, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a LocalScope node.
|
||||
* @param n the node to process
|
||||
* @param c a visitor-specific context
|
||||
* @return true if no further processing is needed
|
||||
*/
|
||||
@Override
|
||||
protected boolean visitSpecialParentScope(CAstNode n, C c, CAstVisitor<C> visitor) {
|
||||
return delegate.visitSpecialParentScope(n, c, visitor);
|
||||
}
|
||||
/**
|
||||
* Leave a LocalScope node.
|
||||
* @param n the node to process
|
||||
* @param c a visitor-specific context
|
||||
*/
|
||||
@Override
|
||||
protected void leaveSpecialParentScope(CAstNode n, C c, CAstVisitor<C> visitor) {
|
||||
delegate.leaveSpecialParentScope(n, c, visitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,8 @@ public class CAstPrinter {
|
|||
|
||||
// explicit lexical scopes
|
||||
case CAstNode.LOCAL_SCOPE: return "SCOPE";
|
||||
|
||||
case CAstNode.SPECIAL_PARENT_SCOPE: return "SPECIAL PARENT SCOPE";
|
||||
|
||||
// literal expression kinds
|
||||
case CAstNode.CONSTANT: return "CONSTANT";
|
||||
case CAstNode.OPERATOR: return "OPERATOR";
|
||||
|
|
Loading…
Reference in New Issue