This commit is contained in:
Asger Feldthaus 2020-12-09 13:01:36 +00:00
Родитель 928a382ad5
Коммит 16a2a60b9a
9 изменённых файлов: 79 добавлений и 3 удалений

Просмотреть файл

@ -3,8 +3,10 @@ package com.semmle.jcorn;
import java.util.ArrayList;
import java.util.List;
import com.semmle.js.ast.AngularPipeRef;
import com.semmle.js.ast.CallExpression;
import com.semmle.js.ast.Expression;
import com.semmle.js.ast.Identifier;
import com.semmle.js.ast.Position;
import com.semmle.js.ast.SourceLocation;
@ -38,6 +40,9 @@ public class AngularExpressionParser extends Parser {
arguments.add(parseExprOp(arg, argStartPos, argStartLocation, TokenType.plusMin.binop, true));
}
SourceLocation loc = new SourceLocation(startLoc);
if (right instanceof Identifier) {
right = new AngularPipeRef(right.getLoc(), (Identifier)right);
}
return this.finishNode(new CallExpression(loc, right, null, arguments, false, false));
}
return super.buildBinary(startPos, startLoc, left, right, op, logical);

Просмотреть файл

@ -0,0 +1,27 @@
package com.semmle.js.ast;
/**
* An identifier occurring as the right operand of an Angular pipe expression,
* which has been desugared to a function call with this expression as the callee.
* <p>
* For example, <code>x | f:y</code> is desugared to <code>f(x, y)</code> where the
* <code>f</code> is an instance of {@link AngularPipeRef}, and evaluates to the function
* being invoked.
*/
public class AngularPipeRef extends Expression {
private final Identifier identifier;
public AngularPipeRef(SourceLocation loc, Identifier identifier) {
super("AngularPipeRef", loc);
this.identifier = identifier;
}
@Override
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
return v.visit(this, q);
}
public Identifier getIdentifier() {
return identifier;
}
}

Просмотреть файл

@ -93,6 +93,11 @@ public class DefaultVisitor<C, R> implements Visitor<C, R> {
else return visit((Expression) nd, c);
}
@Override
public R visit(AngularPipeRef nd, C c) {
return visit((Expression) nd, c);
}
@Override
public R visit(AssignmentExpression nd, C c) {
return visit((Expression) nd, c);

Просмотреть файл

@ -1,5 +1,8 @@
package com.semmle.js.ast;
import java.util.ArrayList;
import java.util.List;
import com.semmle.js.ast.jsx.JSXAttribute;
import com.semmle.js.ast.jsx.JSXClosingElement;
import com.semmle.js.ast.jsx.JSXElement;
@ -48,8 +51,6 @@ import com.semmle.ts.ast.TypeofTypeExpr;
import com.semmle.ts.ast.UnaryTypeExpr;
import com.semmle.ts.ast.UnionTypeExpr;
import com.semmle.util.data.IntList;
import java.util.ArrayList;
import java.util.List;
/** Deep cloning of AST nodes. */
public class NodeCopier implements Visitor<Void, INode> {
@ -77,6 +78,11 @@ public class NodeCopier implements Visitor<Void, INode> {
return new IntList(list);
}
@Override
public INode visit(AngularPipeRef nd, Void q) {
return new AngularPipeRef(nd.getLoc(), copy(nd.getIdentifier()));
}
@Override
public AssignmentExpression visit(AssignmentExpression nd, Void q) {
return new AssignmentExpression(

Просмотреть файл

@ -54,6 +54,8 @@ import com.semmle.ts.ast.UnionTypeExpr;
* <p>Visit methods take a context argument of type {@link C} and return a result of type {@link R}.
*/
public interface Visitor<C, R> {
public R visit(AngularPipeRef nd, C q);
public R visit(AssignmentExpression nd, C q);
public R visit(AssignmentPattern nd, C q);

Просмотреть файл

@ -9,6 +9,7 @@ import java.util.Stack;
import com.semmle.js.ast.AClass;
import com.semmle.js.ast.AFunction;
import com.semmle.js.ast.AFunctionExpression;
import com.semmle.js.ast.AngularPipeRef;
import com.semmle.js.ast.ArrayExpression;
import com.semmle.js.ast.ArrayPattern;
import com.semmle.js.ast.ArrowFunctionExpression;
@ -2126,6 +2127,13 @@ public class ASTExtractor {
new ParseError("Unexpected assignment pattern.", nd.getLoc().getStart()));
return super.visit(nd, c);
}
@Override
public Label visit(AngularPipeRef nd, Context c) {
Label key = super.visit(nd, c);
visit(nd.getIdentifier(), key, 0, IdContext.label);
return key;
}
}
public List<ParseError> extract(

Просмотреть файл

@ -148,6 +148,7 @@ public class ExprKinds {
exprKinds.put("BindExpression", 97);
exprKinds.put("ExternalModuleReference", 98);
exprKinds.put("NonNullAssertion", 105);
exprKinds.put("AngularPipeRef", 119);
}
private static final Map<IdContext, Integer> idKinds =

Просмотреть файл

@ -218,4 +218,25 @@ module Angular2 {
private class DomAdapterLocation extends DOM::LocationSource::Range {
DomAdapterLocation() { this = domAdapter().getAMethodCall("getLocation") }
}
/**
* A reference to a pipe function, occurring in an Angular pipe expression
* that has been desugared to a function call.
*
* For example, the expression `x | f: y` is desugared to `f(x, y)` where
* `f` is a `PipeRefExpr`.
*/
class PipeRefExpr extends Expr, @angular_pipe_ref {
/** Gets the identifier node naming the pipe. */
Identifier getIdentifier() {
result = getChildExpr(0)
}
/** Gets the name of the pipe being referenced. */
string getName() { result = getIdentifier().getName() }
override string getAPrimaryQlClass() {
result = "Angular2::PipeRefExpr"
}
}
}

Просмотреть файл

@ -354,6 +354,7 @@ case @expr.kind of
| 116 = @assignlogandexpr
| 117 = @assignlogorexpr
| 118 = @assignnullishcoalescingexpr
| 119 = @angular_pipe_ref
;
@varaccess = @proper_varaccess | @export_varaccess;