mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
JS(extractor): support optional chaining
This commit is contained in:
@@ -215,6 +215,7 @@ public class AST2JSON extends DefaultVisitor<Void, JsonElement> {
|
||||
JsonObject result = this.mkNode(nd);
|
||||
result.add("callee", visit(nd.getCallee()));
|
||||
result.add("arguments", visit(nd.getArguments()));
|
||||
result.add("optional", new JsonPrimitive(nd.isOptional()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -424,6 +425,7 @@ public class AST2JSON extends DefaultVisitor<Void, JsonElement> {
|
||||
result.add("object", visit(nd.getObject()));
|
||||
result.add("property", visit(nd.getProperty()));
|
||||
result.add("computed", new JsonPrimitive(nd.isComputed()));
|
||||
result.add("optional", new JsonPrimitive(nd.isOptional()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import com.semmle.ts.ast.ITypeExpression;
|
||||
* A function call expression such as <code>f(1, 1)</code>.
|
||||
*/
|
||||
public class CallExpression extends InvokeExpression {
|
||||
public CallExpression(SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments, List<Expression> arguments) {
|
||||
super("CallExpression", loc, callee, typeArguments, arguments);
|
||||
public CallExpression(SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments, List<Expression> arguments, Boolean optional, Boolean onOptionalChain) {
|
||||
super("CallExpression", loc, callee, typeArguments, arguments, optional, onOptionalChain);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
16
javascript/extractor/src/com/semmle/js/ast/Chainable.java
Normal file
16
javascript/extractor/src/com/semmle/js/ast/Chainable.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.semmle.js.ast;
|
||||
|
||||
/**
|
||||
* A chainable expression, such as a member access or function call.
|
||||
*/
|
||||
public interface Chainable {
|
||||
/**
|
||||
* Is this step of the chain optional?
|
||||
*/
|
||||
abstract boolean isOptional();
|
||||
|
||||
/**
|
||||
* Is this on an optional chain?
|
||||
*/
|
||||
abstract boolean isOnOptionalChain();
|
||||
}
|
||||
@@ -8,20 +8,24 @@ import com.semmle.ts.ast.ITypeExpression;
|
||||
/**
|
||||
* An invocation, that is, either a {@link CallExpression} or a {@link NewExpression}.
|
||||
*/
|
||||
public abstract class InvokeExpression extends Expression implements INodeWithSymbol {
|
||||
public abstract class InvokeExpression extends Expression implements INodeWithSymbol, Chainable {
|
||||
private final Expression callee;
|
||||
private final List<ITypeExpression> typeArguments;
|
||||
private final List<Expression> arguments;
|
||||
private final boolean optional;
|
||||
private final boolean onOptionalChain;
|
||||
private int resolvedSignatureId = -1;
|
||||
private int overloadIndex = -1;
|
||||
private int symbol = -1;
|
||||
|
||||
public InvokeExpression(String type, SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments,
|
||||
List<Expression> arguments) {
|
||||
List<Expression> arguments, Boolean optional, Boolean onOptionalChain) {
|
||||
super(type, loc);
|
||||
this.callee = callee;
|
||||
this.typeArguments = typeArguments;
|
||||
this.arguments = arguments;
|
||||
this.optional = optional == Boolean.TRUE;
|
||||
this.onOptionalChain = onOptionalChain == Boolean.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,6 +49,16 @@ public abstract class InvokeExpression extends Expression implements INodeWithSy
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnOptionalChain() {
|
||||
return onOptionalChain;
|
||||
}
|
||||
|
||||
public int getResolvedSignatureId() {
|
||||
return resolvedSignatureId;
|
||||
}
|
||||
@@ -70,4 +84,4 @@ public abstract class InvokeExpression extends Expression implements INodeWithSy
|
||||
public void setSymbol(int symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,20 @@ import com.semmle.ts.ast.ITypeExpression;
|
||||
/**
|
||||
* A member expression, either computed (<code>e[f]</code>) or static (<code>e.f</code>).
|
||||
*/
|
||||
public class MemberExpression extends Expression implements ITypeExpression, INodeWithSymbol {
|
||||
public class MemberExpression extends Expression implements ITypeExpression, INodeWithSymbol, Chainable {
|
||||
private final Expression object, property;
|
||||
private final boolean computed;
|
||||
private final boolean optional;
|
||||
private final boolean onOptionalChain;
|
||||
private int symbol = -1;
|
||||
|
||||
public MemberExpression(SourceLocation loc, Expression object, Expression property, Boolean computed) {
|
||||
public MemberExpression(SourceLocation loc, Expression object, Expression property, Boolean computed, Boolean optional, Boolean onOptionalChain) {
|
||||
super("MemberExpression", loc);
|
||||
this.object = object;
|
||||
this.property = property;
|
||||
this.computed = computed == Boolean.TRUE;
|
||||
this.optional = optional == Boolean.TRUE;
|
||||
this.onOptionalChain = onOptionalChain == Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,6 +49,16 @@ public class MemberExpression extends Expression implements ITypeExpression, INo
|
||||
return computed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnOptionalChain() {
|
||||
return onOptionalChain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return symbol;
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.semmle.ts.ast.ITypeExpression;
|
||||
*/
|
||||
public class NewExpression extends InvokeExpression {
|
||||
public NewExpression(SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments, List<Expression> arguments) {
|
||||
super("NewExpression", loc, callee, typeArguments, arguments);
|
||||
super("NewExpression", loc, callee, typeArguments, arguments, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -97,7 +97,7 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
|
||||
@Override
|
||||
public CallExpression visit(CallExpression nd, Void q) {
|
||||
return new CallExpression(visit(nd.getLoc()), copy(nd.getCallee()), copy(nd.getTypeArguments()), copy(nd.getArguments()));
|
||||
return new CallExpression(visit(nd.getLoc()), copy(nd.getCallee()), copy(nd.getTypeArguments()), copy(nd.getArguments()), nd.isOptional(), nd.isOnOptionalChain());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,7 +140,7 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
|
||||
@Override
|
||||
public MemberExpression visit(MemberExpression nd, Void q) {
|
||||
return new MemberExpression(visit(nd.getLoc()), copy(nd.getObject()), copy(nd.getProperty()), nd.isComputed());
|
||||
return new MemberExpression(visit(nd.getLoc()), copy(nd.getObject()), copy(nd.getProperty()), nd.isComputed(), nd.isOptional(), nd.isOnOptionalChain());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user