mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
JavaScript: Open-source extractor.
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An array type, such as <tt>number[]</tt>, or in general <tt>T[]</tt> where
|
||||
* <tt>T</tt> is a type.
|
||||
*/
|
||||
public class ArrayTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression elementType;
|
||||
|
||||
public ArrayTypeExpr(SourceLocation loc, ITypeExpression elementType) {
|
||||
super("ArrayTypeExpr", loc);
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public ITypeExpression getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A conditional type annotation, such as <tt>T extends any[] ? A : B</tt>.
|
||||
*/
|
||||
public class ConditionalTypeExpr extends TypeExpression {
|
||||
private ITypeExpression checkType;
|
||||
private ITypeExpression extendsType;
|
||||
private ITypeExpression trueType;
|
||||
private ITypeExpression falseType;
|
||||
|
||||
public ConditionalTypeExpr(SourceLocation loc, ITypeExpression checkType, ITypeExpression extendsType,
|
||||
ITypeExpression trueType, ITypeExpression falseType) {
|
||||
super("ConditionalTypeExpr", loc);
|
||||
this.checkType = checkType;
|
||||
this.extendsType = extendsType;
|
||||
this.trueType = trueType;
|
||||
this.falseType = falseType;
|
||||
}
|
||||
|
||||
public ITypeExpression getCheckType() {
|
||||
return checkType;
|
||||
}
|
||||
|
||||
public ITypeExpression getExtendsType() {
|
||||
return extendsType;
|
||||
}
|
||||
|
||||
public ITypeExpression getTrueType() {
|
||||
return trueType;
|
||||
}
|
||||
|
||||
public ITypeExpression getFalseType() {
|
||||
return falseType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Decorator;
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class DecoratorList extends Expression {
|
||||
private final List<Decorator> decorators;
|
||||
|
||||
public DecoratorList(SourceLocation loc, List<Decorator> decorators) {
|
||||
super("DecoratorList", loc);
|
||||
this.decorators = decorators;
|
||||
}
|
||||
|
||||
public List<Decorator> getDecorators() {
|
||||
return decorators;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Decorator;
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class EnumDeclaration extends Statement implements INodeWithSymbol {
|
||||
private final boolean isConst;
|
||||
private final boolean hasDeclareKeyword;
|
||||
private final List<Decorator> decorators;
|
||||
private final Identifier id;
|
||||
private List<EnumMember> members;
|
||||
private int typeSymbol = -1;
|
||||
|
||||
public EnumDeclaration(SourceLocation loc, boolean isConst, boolean hasDeclareKeyword, List<Decorator> decorators, Identifier id,
|
||||
List<EnumMember> members) {
|
||||
super("EnumDeclaration", loc);
|
||||
this.isConst = isConst;
|
||||
this.hasDeclareKeyword = hasDeclareKeyword;
|
||||
this.decorators = decorators;
|
||||
this.id = id;
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
public boolean isConst() {
|
||||
return isConst;
|
||||
}
|
||||
|
||||
public boolean hasDeclareKeyword() {
|
||||
return hasDeclareKeyword;
|
||||
}
|
||||
|
||||
public List<Decorator> getDecorators() {
|
||||
return decorators;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<EnumMember> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return typeSymbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSymbol(int symbol) {
|
||||
this.typeSymbol = symbol;
|
||||
}
|
||||
}
|
||||
46
javascript/extractor/src/com/semmle/ts/ast/EnumMember.java
Normal file
46
javascript/extractor/src/com/semmle/ts/ast/EnumMember.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.Node;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class EnumMember extends Node implements INodeWithSymbol {
|
||||
private final Identifier id;
|
||||
private final Expression initializer;
|
||||
private int typeSymbol = -1;
|
||||
|
||||
public EnumMember(SourceLocation loc, Identifier id, Expression initializer) {
|
||||
super("EnumMember", loc);
|
||||
this.id = id;
|
||||
this.initializer = initializer;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initializer expression, or {@code null} if this enum member has
|
||||
* no explicit initializer.
|
||||
*/
|
||||
public Expression getInitializer() {
|
||||
return initializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return typeSymbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSymbol(int symbol) {
|
||||
this.typeSymbol = symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A statement of form <tt>export as namespace X</tt> where <tt>X</tt> is an
|
||||
* identifier.
|
||||
*/
|
||||
public class ExportAsNamespaceDeclaration extends Statement {
|
||||
private Identifier id;
|
||||
|
||||
public ExportAsNamespaceDeclaration(SourceLocation loc, Identifier id) {
|
||||
super("ExportAsNamespaceDeclaration", loc);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class ExportWholeDeclaration extends Statement {
|
||||
private final Expression rhs;
|
||||
|
||||
public ExportWholeDeclaration(SourceLocation loc, Expression rhs) {
|
||||
super("ExportWholeDeclaration", loc);
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
public Expression getRhs() {
|
||||
return rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An expression with type arguments, occurring as the super-class expression of
|
||||
* a class. For example:
|
||||
*
|
||||
* <pre>
|
||||
* class StringList extends List<string> {}
|
||||
* </pre>
|
||||
*
|
||||
* Above, <tt>List</tt> is a concrete expression whereas its type argument is a
|
||||
* type.
|
||||
*/
|
||||
public class ExpressionWithTypeArguments extends Expression {
|
||||
private final Expression expression;
|
||||
private final List<ITypeExpression> typeArguments;
|
||||
|
||||
public ExpressionWithTypeArguments(SourceLocation loc, Expression expression, List<ITypeExpression> typeArguments) {
|
||||
super("ExpressionWithTypeArguments", loc);
|
||||
this.expression = expression;
|
||||
this.typeArguments = typeArguments;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public List<ITypeExpression> getTypeArguments() {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Literal;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A statement of form <tt>declare module "X" {...}</tt>.
|
||||
*/
|
||||
public class ExternalModuleDeclaration extends Statement {
|
||||
private final Literal name;
|
||||
private final List<Statement> body;
|
||||
|
||||
public ExternalModuleDeclaration(SourceLocation loc, Literal name, List<Statement> body) {
|
||||
super("ExternalModuleDeclaration", loc);
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
public Literal getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Statement> getBody() {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class ExternalModuleReference extends Expression {
|
||||
private final Expression expression;
|
||||
|
||||
public ExternalModuleReference(SourceLocation loc, Expression expression) {
|
||||
super("ExternalModuleReference", loc);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.FunctionExpression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class FunctionTypeExpr extends TypeExpression {
|
||||
private final FunctionExpression function;
|
||||
private final boolean isConstructor;
|
||||
|
||||
public FunctionTypeExpr(SourceLocation loc, FunctionExpression function, boolean isConstructor) {
|
||||
super("FunctionTypeExpr", loc);
|
||||
this.function = function;
|
||||
this.isConstructor = isConstructor;
|
||||
}
|
||||
|
||||
public FunctionExpression getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public boolean isConstructor() {
|
||||
return isConstructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An instantiation of a named type, such as <tt>Array<number></tt>
|
||||
*/
|
||||
public class GenericTypeExpr extends TypeExpression {
|
||||
final private ITypeExpression typeName; // Always Identifier or MemberExpression
|
||||
final private List<ITypeExpression> typeArguments;
|
||||
|
||||
public GenericTypeExpr(SourceLocation loc, ITypeExpression typeName, List<ITypeExpression> typeArguments) {
|
||||
super("GenericTypeExpr", loc);
|
||||
this.typeName = typeName;
|
||||
this.typeArguments = typeArguments;
|
||||
}
|
||||
|
||||
public ITypeExpression getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public List<ITypeExpression> getTypeArguments() {
|
||||
return typeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A statement of form: <tt>declare global { ... }</tt>
|
||||
*/
|
||||
public class GlobalAugmentationDeclaration extends Statement {
|
||||
private final List<Statement> body;
|
||||
|
||||
public GlobalAugmentationDeclaration(SourceLocation loc, List<Statement> body) {
|
||||
super("GlobalAugmentationDeclaration", loc);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public List<Statement> getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
/**
|
||||
* An AST node that is associated with a TypeScript compiler symbol.
|
||||
*
|
||||
* This can be the symbol for the type defined by this node, of it this is a
|
||||
* module top-level, the symbol for that module.
|
||||
*/
|
||||
public interface INodeWithSymbol {
|
||||
/**
|
||||
* Gets a number identifying the symbol associated with this AST node, or
|
||||
* <tt>-1</tt> if there is no such symbol.
|
||||
*/
|
||||
int getSymbol();
|
||||
|
||||
void setSymbol(int symbol);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.INode;
|
||||
import com.semmle.js.ast.Literal;
|
||||
|
||||
/**
|
||||
* An AST node that may occur as part of a TypeScript type annotation.
|
||||
* <p>
|
||||
* At the QL level, expressions and type annotations are completely separate. In
|
||||
* the extractor, however, some expressions such as {@link Literal} type may
|
||||
* occur in a type annotation because the TypeScript AST does not distinguish
|
||||
* <tt>null</tt> literals from the <tt>null</tt> type.
|
||||
*/
|
||||
public interface ITypeExpression extends INode, ITypedAstNode {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
/**
|
||||
* An AST node with an associated static type.
|
||||
*/
|
||||
public interface ITypedAstNode {
|
||||
/**
|
||||
* Gets the static type of this node as determined by the TypeScript compiler,
|
||||
* or -1 if no type was determined.
|
||||
* <p>
|
||||
* The ID refers to a type in a table that is extracted on a per-project basis,
|
||||
* and the meaning of this type ID is not available at the AST level.
|
||||
*/
|
||||
int getStaticTypeId();
|
||||
|
||||
void setStaticTypeId(int id);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An import type such as in <tt>import("http").ServerRequest</tt>.
|
||||
*/
|
||||
public class ImportTypeExpr extends Expression implements ITypeExpression {
|
||||
private final ITypeExpression path;
|
||||
|
||||
public ImportTypeExpr(SourceLocation loc, ITypeExpression path) {
|
||||
super("ImportTypeExpr", loc);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
public ITypeExpression getPath() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An import of form <tt>import a = E</tt>.
|
||||
*/
|
||||
public class ImportWholeDeclaration extends Statement {
|
||||
private final Identifier lhs;
|
||||
private final Expression rhs;
|
||||
|
||||
public ImportWholeDeclaration(SourceLocation loc, Identifier lhs, Expression rhs) {
|
||||
super("ImportWholeDeclaration", loc);
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
public Identifier getLhs() {
|
||||
return lhs;
|
||||
}
|
||||
|
||||
public Expression getRhs() {
|
||||
return rhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type of form <tt>T[K]</tt> where <tt>T</tt> and <tt>K</tt> are types.
|
||||
*/
|
||||
public class IndexedAccessTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression objectType;
|
||||
private final ITypeExpression indexType;
|
||||
|
||||
public IndexedAccessTypeExpr(SourceLocation loc, ITypeExpression objectType, ITypeExpression indexType) {
|
||||
super("IndexedAccessTypeExpr", loc);
|
||||
this.objectType = objectType;
|
||||
this.indexType = indexType;
|
||||
}
|
||||
|
||||
public ITypeExpression getObjectType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
public ITypeExpression getIndexType() {
|
||||
return indexType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type annotation of form <tt>infer R</tt>
|
||||
*/
|
||||
public class InferTypeExpr extends TypeExpression {
|
||||
private TypeParameter typeParameter;
|
||||
|
||||
public InferTypeExpr(SourceLocation loc, TypeParameter typeParameter) {
|
||||
super("InferTypeExpr", loc);
|
||||
this.typeParameter = typeParameter;
|
||||
}
|
||||
|
||||
public TypeParameter getTypeParameter() {
|
||||
return typeParameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.MemberDefinition;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A TypeScript interface declaration.
|
||||
*/
|
||||
public class InterfaceDeclaration extends Statement implements INodeWithSymbol {
|
||||
private final Identifier name;
|
||||
private final List<TypeParameter> typeParameters;
|
||||
private final List<ITypeExpression> superInterfaces;
|
||||
private final List<MemberDefinition<?>> body;
|
||||
private int typeSymbol = -1;
|
||||
|
||||
public InterfaceDeclaration(SourceLocation loc, Identifier name, List<TypeParameter> typeParameters,
|
||||
List<ITypeExpression> superInterfaces,
|
||||
List<MemberDefinition<?>> body) {
|
||||
super("InterfaceDeclaration", loc);
|
||||
this.name = name;
|
||||
this.typeParameters = typeParameters;
|
||||
this.superInterfaces = superInterfaces;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<TypeParameter> getTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public boolean hasTypeParameters() {
|
||||
return !typeParameters.isEmpty();
|
||||
}
|
||||
|
||||
public List<MemberDefinition<?>> getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public List<ITypeExpression> getSuperInterfaces() {
|
||||
return superInterfaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return typeSymbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSymbol(int symbol) {
|
||||
this.typeSymbol = symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.MemberDefinition;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An inline interface type, such as <tt>{x: number; y: number}</tt>.
|
||||
*/
|
||||
public class InterfaceTypeExpr extends TypeExpression {
|
||||
private final List<MemberDefinition<?>> body;
|
||||
|
||||
public InterfaceTypeExpr(SourceLocation loc, List<MemberDefinition<?>> body) {
|
||||
super("InterfaceTypeExpr", loc);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public List<MemberDefinition<?>> getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An intersection type such as <tt>T&S</tt>, denoting the intersection of
|
||||
* type <tt>T</tt> and type <tt>S</tt>.
|
||||
*/
|
||||
public class IntersectionTypeExpr extends TypeExpression {
|
||||
private final List<ITypeExpression> elementTypes;
|
||||
|
||||
public IntersectionTypeExpr(SourceLocation loc, List<ITypeExpression> elementTypes) {
|
||||
super("IntersectionTypeExpr", loc);
|
||||
this.elementTypes = elementTypes;
|
||||
}
|
||||
|
||||
/** The members of the intersection type; always contains at least two types. */
|
||||
public List<ITypeExpression> getElementTypes() {
|
||||
return elementTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
32
javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java
Normal file
32
javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type of form <tt>E is T</tt> where <tt>E</tt> is a parameter name or
|
||||
* <tt>this</tt> and <tt>T</tt> is a type.
|
||||
*/
|
||||
public class IsTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression left; // Always Identifier or KeywordTypeExpr (in case of 'this')
|
||||
private final ITypeExpression right;
|
||||
|
||||
public IsTypeExpr(SourceLocation loc, ITypeExpression left, ITypeExpression right) {
|
||||
super("IsTypeExpr", loc);
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public ITypeExpression getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public ITypeExpression getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type of form <tt>keyof T</tt> where <tt>T</tt> is a type.
|
||||
*/
|
||||
public class KeyofTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression elementType;
|
||||
|
||||
public KeyofTypeExpr(SourceLocation loc, ITypeExpression elementType) {
|
||||
super("KeyofTypeExpr", loc);
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public ITypeExpression getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* One of the TypeScript keyword types, such as <tt>string</tt> or <tt>any</tt>.
|
||||
* <p>
|
||||
* This includes the type <tt>unique symbol</tt> which consists of two keywords
|
||||
* but is represented as a keyword single type expression.
|
||||
* <p>
|
||||
* At the QL level, the <tt>null</tt> type is also a keyword type. In the
|
||||
* extractor, however, this is represented by a Literal, because the TypeScript
|
||||
* AST does not distinguish those two uses of <tt>null</tt>.
|
||||
*/
|
||||
public class KeywordTypeExpr extends TypeExpression {
|
||||
private final String keyword;
|
||||
|
||||
public KeywordTypeExpr(SourceLocation loc, String keyword) {
|
||||
super("KeywordTypeExpr", loc);
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type of form <tt>{ [K in C]: T }</tt>, where <tt>T</tt> is a type that may
|
||||
* refer to <tt>K</tt>.
|
||||
* <p>
|
||||
* As with the TypeScript AST, the <tt>K in C</tt> part is represented as a type
|
||||
* parameter with <tt>C</tt> as its upper bound.
|
||||
*/
|
||||
public class MappedTypeExpr extends TypeExpression {
|
||||
private final TypeParameter typeParameter;
|
||||
private final ITypeExpression elementType;
|
||||
|
||||
public MappedTypeExpr(SourceLocation loc, TypeParameter typeParameter, ITypeExpression elementType) {
|
||||
super("MappedTypeExpr", loc);
|
||||
this.typeParameter = typeParameter;
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public TypeParameter getTypeParameter() {
|
||||
return typeParameter;
|
||||
}
|
||||
|
||||
public ITypeExpression getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class NamespaceDeclaration extends Statement implements INodeWithSymbol {
|
||||
private final Identifier name;
|
||||
private final List<Statement> body;
|
||||
private final boolean isInstantiated;
|
||||
private final boolean hasDeclareKeyword;
|
||||
private int symbol = -1;
|
||||
|
||||
public NamespaceDeclaration(SourceLocation loc, Identifier name, List<Statement> body, boolean isInstantiated, boolean hasDeclareKeyword) {
|
||||
super("NamespaceDeclaration", loc);
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.isInstantiated = isInstantiated;
|
||||
this.hasDeclareKeyword = hasDeclareKeyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
public Identifier getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Statement> getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this is an instantiated namespace.
|
||||
*
|
||||
* Non-instantiated namespaces only contain interface types, type aliases, and
|
||||
* other non-instantiated namespaces. The TypeScript compiler does not emit
|
||||
* code for non-instantiated namespaces.
|
||||
*/
|
||||
public boolean isInstantiated() {
|
||||
return isInstantiated;
|
||||
}
|
||||
|
||||
public boolean hasDeclareKeyword() {
|
||||
return hasDeclareKeyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSymbol(int symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A TypeScript expression of form <tt>E!</tt>, asserting that <tt>E</tt> is not null.
|
||||
*/
|
||||
public class NonNullAssertion extends Expression {
|
||||
private final Expression expression;
|
||||
|
||||
public NonNullAssertion(SourceLocation loc, Expression expression) {
|
||||
super("NonNullAssertion", loc);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An optional type in a tuple type, such as <tt>number?</tt> in
|
||||
* <tt>[string, number?]</tt>.
|
||||
*/
|
||||
public class OptionalTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression elementType;
|
||||
|
||||
public OptionalTypeExpr(SourceLocation loc, ITypeExpression elementType) {
|
||||
super("OptionalTypeExpr", loc);
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public ITypeExpression getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type expression in parentheses, such as <tt>("foo" | "bar")</tt>.
|
||||
*/
|
||||
public class ParenthesizedTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression elementType;
|
||||
|
||||
public ParenthesizedTypeExpr(SourceLocation loc, ITypeExpression elementType) {
|
||||
super("ParenthesizedTypeExpr", loc);
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public ITypeExpression getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
26
javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java
Normal file
26
javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A rest type in a tuple type, such as <tt>number[]</tt> in
|
||||
* <tt>[string, ...number[]]</tt>.
|
||||
*/
|
||||
public class RestTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression arrayType;
|
||||
|
||||
public RestTypeExpr(SourceLocation loc, ITypeExpression arrayType) {
|
||||
super("RestTypeExpr", loc);
|
||||
this.arrayType = arrayType;
|
||||
}
|
||||
|
||||
public ITypeExpression getArrayType() {
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A tuple type, such as <tt>[number, string]</tt>.
|
||||
*/
|
||||
public class TupleTypeExpr extends TypeExpression {
|
||||
private final List<ITypeExpression> elementTypes;
|
||||
|
||||
public TupleTypeExpr(SourceLocation loc, List<ITypeExpression> elementTypes) {
|
||||
super("TupleTypeExpr", loc);
|
||||
this.elementTypes = elementTypes;
|
||||
}
|
||||
|
||||
public List<ITypeExpression> getElementTypes() {
|
||||
return elementTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Statement;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
public class TypeAliasDeclaration extends Statement implements INodeWithSymbol {
|
||||
private final Identifier name;
|
||||
private final List<TypeParameter> typeParameters;
|
||||
private final ITypeExpression definition;
|
||||
private int typeSymbol = -1;
|
||||
|
||||
public TypeAliasDeclaration(SourceLocation loc, Identifier name, List<TypeParameter> typeParameters, ITypeExpression definition) {
|
||||
super("TypeAliasDeclaration", loc);
|
||||
this.name = name;
|
||||
this.typeParameters = typeParameters;
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<TypeParameter> getTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public boolean hasTypeParameters() {
|
||||
return !typeParameters.isEmpty();
|
||||
}
|
||||
|
||||
public ITypeExpression getDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSymbol() {
|
||||
return typeSymbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSymbol(int symbol) {
|
||||
this.typeSymbol = symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Expression;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* An expression of form <code>E as T</code> or <code><T> E</code>.
|
||||
*/
|
||||
public class TypeAssertion extends Expression {
|
||||
private final Expression expression;
|
||||
private final ITypeExpression typeAnnotation;
|
||||
private final boolean isAsExpression;
|
||||
|
||||
public TypeAssertion(SourceLocation loc, Expression expression, ITypeExpression typeAnnotation, boolean isAsExpression) {
|
||||
super("TypeAssertion", loc);
|
||||
this.expression = expression;
|
||||
this.typeAnnotation = typeAnnotation;
|
||||
this.isAsExpression = isAsExpression;
|
||||
}
|
||||
|
||||
public Expression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public ITypeExpression getTypeAnnotation() {
|
||||
return typeAnnotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this is an assertion of form <tt>E as T</tt>, as opposed to the old
|
||||
* syntax <code><T> E</code>.
|
||||
*/
|
||||
public boolean isAsExpression() {
|
||||
return isAsExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Node;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
|
||||
/**
|
||||
* An AST node that may occur as part of a TypeScript type annotation and is not
|
||||
* also an expression.
|
||||
*/
|
||||
public abstract class TypeExpression extends Node implements ITypeExpression {
|
||||
private int staticTypeId = -1;
|
||||
|
||||
public TypeExpression(String type, SourceLocation loc) {
|
||||
super(type, loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStaticTypeId() {
|
||||
return staticTypeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStaticTypeId(int staticTypeId) {
|
||||
this.staticTypeId = staticTypeId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.Identifier;
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type parameter declared on a class, interface, function, or type alias.
|
||||
* <p>
|
||||
* The general form of a type parameter is: <tt>S extends T = U</tt>.
|
||||
*/
|
||||
public class TypeParameter extends TypeExpression {
|
||||
private final Identifier id;
|
||||
private final ITypeExpression bound;
|
||||
private final ITypeExpression default_;
|
||||
|
||||
public TypeParameter(SourceLocation loc, Identifier id, ITypeExpression bound, ITypeExpression default_) {
|
||||
super("TypeParameter", loc);
|
||||
this.id = id;
|
||||
this.bound = bound;
|
||||
this.default_ = default_;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bound on the type parameter, or {@code null} if there is no
|
||||
* bound.
|
||||
* <p>
|
||||
* For example, in <tt>T extends Array = number[]</tt> the bound is
|
||||
* <tt>Array</tt>.
|
||||
*/
|
||||
public ITypeExpression getBound() {
|
||||
return bound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type parameter default, or {@code null} if there is no default,
|
||||
* <p>
|
||||
* For example, in <tt>T extends Array = number[]</tt> the default is
|
||||
* <tt>number[]</tt>.
|
||||
*/
|
||||
public ITypeExpression getDefault() {
|
||||
return default_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/**
|
||||
* A type of form <tt>typeof E</tt> where <tt>E</tt> is an expression that takes
|
||||
* the form of a qualified name.
|
||||
*/
|
||||
public class TypeofTypeExpr extends TypeExpression {
|
||||
private final ITypeExpression expression; // Always Identifier or MemberExpression.
|
||||
|
||||
public TypeofTypeExpr(SourceLocation loc, ITypeExpression expression) {
|
||||
super("TypeofTypeExpr", loc);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public ITypeExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.semmle.ts.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.semmle.js.ast.SourceLocation;
|
||||
import com.semmle.js.ast.Visitor;
|
||||
|
||||
/** A union type such as <tt>number | string | boolean</tt>. */
|
||||
public class UnionTypeExpr extends TypeExpression {
|
||||
private final List<ITypeExpression> elementTypes;
|
||||
|
||||
public UnionTypeExpr(SourceLocation loc, List<ITypeExpression> elementTypes) {
|
||||
super("UnionTypeExpr", loc);
|
||||
this.elementTypes = elementTypes;
|
||||
}
|
||||
|
||||
/** The members of the union; always contains at least two types. */
|
||||
public List<ITypeExpression> getElementTypes() {
|
||||
return elementTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||
return v.visit(this, c);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
package com.semmle.ts.extractor;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.semmle.util.trap.TrapWriter;
|
||||
import com.semmle.util.trap.TrapWriter.Label;
|
||||
|
||||
/**
|
||||
* Extracts type and symbol information into TRAP files.
|
||||
* <p>
|
||||
* This is closely coupled with the <tt>type_table.ts</tt> file in the
|
||||
* parser-wrapper. Type strings and symbol strings generated in that file are
|
||||
* parsed here. See that file for reference and documentation.
|
||||
*/
|
||||
public class TypeExtractor {
|
||||
private final TrapWriter trapWriter;
|
||||
private final TypeTable table;
|
||||
|
||||
private static final Map<String, Integer> tagToKind = new LinkedHashMap<String, Integer>();
|
||||
|
||||
private static final int referenceKind = 6;
|
||||
private static final int objectKind = 7;
|
||||
private static final int typevarKind = 8;
|
||||
private static final int typeofKind = 9;
|
||||
private static final int uniqueSymbolKind = 15;
|
||||
private static final int tupleKind = 18;
|
||||
private static final int lexicalTypevarKind = 19;
|
||||
private static final int thisKind = 20;
|
||||
private static final int numberLiteralTypeKind = 21;
|
||||
private static final int stringLiteralTypeKind = 22;
|
||||
|
||||
static {
|
||||
tagToKind.put("any", 0);
|
||||
tagToKind.put("string", 1);
|
||||
tagToKind.put("number", 2);
|
||||
tagToKind.put("union", 3);
|
||||
tagToKind.put("true", 4);
|
||||
tagToKind.put("false", 5);
|
||||
tagToKind.put("reference", referenceKind);
|
||||
tagToKind.put("object", objectKind);
|
||||
tagToKind.put("typevar", typevarKind);
|
||||
tagToKind.put("typeof", typeofKind);
|
||||
tagToKind.put("void", 10);
|
||||
tagToKind.put("undefined", 11);
|
||||
tagToKind.put("null", 12);
|
||||
tagToKind.put("never", 13);
|
||||
tagToKind.put("plainsymbol", 14);
|
||||
tagToKind.put("uniquesymbol", uniqueSymbolKind);
|
||||
tagToKind.put("objectkeyword", 16);
|
||||
tagToKind.put("intersection", 17);
|
||||
tagToKind.put("tuple", tupleKind);
|
||||
tagToKind.put("lextypevar", lexicalTypevarKind);
|
||||
tagToKind.put("this", thisKind);
|
||||
tagToKind.put("numlit", numberLiteralTypeKind);
|
||||
tagToKind.put("strlit", stringLiteralTypeKind);
|
||||
tagToKind.put("unknown", 23);
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> symbolKind = new LinkedHashMap<String, Integer>();
|
||||
|
||||
static {
|
||||
symbolKind.put("root", 0);
|
||||
symbolKind.put("member", 1);
|
||||
symbolKind.put("other", 2);
|
||||
}
|
||||
|
||||
public TypeExtractor(TrapWriter trapWriter, TypeTable table) {
|
||||
this.trapWriter = trapWriter;
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
public void extract() {
|
||||
for (int i = 0; i < table.getNumberOfTypes(); ++i) {
|
||||
extractType(i);
|
||||
}
|
||||
extractPropertyLookups(table.getPropertyLookups());
|
||||
for (int i = 0; i < table.getNumberOfSymbols(); ++i) {
|
||||
extractSymbol(i);
|
||||
}
|
||||
extractSymbolNameMapping("symbol_module", table.getModuleMappings());
|
||||
extractSymbolNameMapping("symbol_global", table.getGlobalMappings());
|
||||
extractSignatureMappings(table.getSignatureMappings());
|
||||
for (int i = 0; i < table.getNumberOfSignatures(); ++i) {
|
||||
extractSignature(i);
|
||||
}
|
||||
extractIndexTypeTable(table.getNumberIndexTypes(), "number_index_type");
|
||||
extractIndexTypeTable(table.getStringIndexTypes(), "string_index_type");
|
||||
extractBaseTypes(table.getBaseTypes());
|
||||
extractSelfTypes(table.getSelfTypes());
|
||||
}
|
||||
|
||||
private void extractType(int id) {
|
||||
Label lbl = trapWriter.globalID("type;" + id);
|
||||
String contents = table.getTypeString(id);
|
||||
String[] parts = contents.split(";");
|
||||
int kind = tagToKind.get(parts[0]);
|
||||
trapWriter.addTuple("types", lbl, kind, table.getTypeToStringValue(id));
|
||||
int firstChild = 1;
|
||||
switch (kind) {
|
||||
case referenceKind:
|
||||
case typevarKind:
|
||||
case typeofKind:
|
||||
case uniqueSymbolKind: {
|
||||
// The first part of a reference is the symbol for name binding.
|
||||
Label symbol = trapWriter.globalID("symbol;" + parts[1]);
|
||||
trapWriter.addTuple("type_symbol", lbl, symbol);
|
||||
++firstChild;
|
||||
break;
|
||||
}
|
||||
case tupleKind: {
|
||||
// The first two parts denote minimum length and presence of rest element.
|
||||
trapWriter.addTuple("tuple_type_min_length", lbl, Integer.parseInt(parts[1]));
|
||||
if (parts[2].equals("t")) {
|
||||
trapWriter.addTuple("tuple_type_rest", lbl);
|
||||
}
|
||||
firstChild += 2;
|
||||
break;
|
||||
}
|
||||
case objectKind:
|
||||
case lexicalTypevarKind:
|
||||
firstChild = parts.length; // No children.
|
||||
break;
|
||||
|
||||
case numberLiteralTypeKind:
|
||||
case stringLiteralTypeKind:
|
||||
firstChild = parts.length; // No children.
|
||||
// The string value may contain `;` so don't use the split().
|
||||
String value = contents.substring(parts[0].length() + 1);
|
||||
trapWriter.addTuple("type_literal_value", lbl, value);
|
||||
break;
|
||||
}
|
||||
for (int i = firstChild; i < parts.length; ++i) {
|
||||
Label childLabel = trapWriter.globalID("type;" + parts[i]);
|
||||
trapWriter.addTuple("type_child", childLabel, lbl, i - firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractPropertyLookups(JsonObject lookups) {
|
||||
JsonArray baseTypes = lookups.get("baseTypes").getAsJsonArray();
|
||||
JsonArray names = lookups.get("names").getAsJsonArray();
|
||||
JsonArray propertyTypes = lookups.get("propertyTypes").getAsJsonArray();
|
||||
for (int i = 0; i < baseTypes.size(); ++i) {
|
||||
int baseType = baseTypes.get(i).getAsInt();
|
||||
String name = names.get(i).getAsString();
|
||||
int propertyType = propertyTypes.get(i).getAsInt();
|
||||
trapWriter.addTuple("type_property", trapWriter.globalID("type;" + baseType), name,
|
||||
trapWriter.globalID("type;" + propertyType));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbol(int index) {
|
||||
// Format is: kind;decl;name[;parent]
|
||||
String[] parts = table.getSymbolString(index).split(";");
|
||||
int kind = symbolKind.get(parts[0]);
|
||||
String name = parts[2];
|
||||
Label label = trapWriter.globalID("symbol;" + index);
|
||||
trapWriter.addTuple("symbols", label, kind, name);
|
||||
if (parts.length == 4) {
|
||||
Label parentLabel = trapWriter.globalID("symbol;" + parts[3]);
|
||||
trapWriter.addTuple("symbol_parent", label, parentLabel);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbolNameMapping(String relationName, JsonObject mappings) {
|
||||
JsonArray symbols = mappings.get("symbols").getAsJsonArray();
|
||||
JsonArray names = mappings.get("names").getAsJsonArray();
|
||||
for (int i = 0; i < symbols.size(); ++i) {
|
||||
Label symbol = trapWriter.globalID("symbol;" + symbols.get(i).getAsInt());
|
||||
String moduleName = names.get(i).getAsString();
|
||||
trapWriter.addTuple(relationName, symbol, moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSignature(int index) {
|
||||
// Format is:
|
||||
// kind;numTypeParams;requiredParams;returnType(;paramName;paramType)*
|
||||
String[] parts = table.getSignatureString(index).split(";");
|
||||
Label label = trapWriter.globalID("signature;" + index);
|
||||
int kind = Integer.parseInt(parts[0]);
|
||||
int numberOfTypeParameters = Integer.parseInt(parts[1]);
|
||||
int requiredParameters = Integer.parseInt(parts[2]);
|
||||
Label returnType = trapWriter.globalID("type;" + parts[3]);
|
||||
trapWriter.addTuple("signature_types", label, kind, table.getSignatureToStringValue(index), numberOfTypeParameters,
|
||||
requiredParameters);
|
||||
trapWriter.addTuple("signature_contains_type", returnType, label, -1);
|
||||
int numberOfParameters = (parts.length - 4) / 2; // includes type parameters
|
||||
for (int i = 0; i < numberOfParameters; ++i) {
|
||||
int partIndex = 4 + (2 * i);
|
||||
String paramName = parts[partIndex];
|
||||
String paramTypeId = parts[partIndex + 1];
|
||||
if (paramTypeId.length() > 0) { // Unconstrained type parameters have an empty type ID.
|
||||
Label paramType = trapWriter.globalID("type;" + parts[partIndex + 1]);
|
||||
trapWriter.addTuple("signature_contains_type", paramType, label, i);
|
||||
}
|
||||
trapWriter.addTuple("signature_parameter_name", label, i, paramName);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSignatureMappings(JsonObject mappings) {
|
||||
JsonArray baseTypes = mappings.get("baseTypes").getAsJsonArray();
|
||||
JsonArray kinds = mappings.get("kinds").getAsJsonArray();
|
||||
JsonArray indices = mappings.get("indices").getAsJsonArray();
|
||||
JsonArray signatures = mappings.get("signatures").getAsJsonArray();
|
||||
for (int i = 0; i < baseTypes.size(); ++i) {
|
||||
int baseType = baseTypes.get(i).getAsInt();
|
||||
int kind = kinds.get(i).getAsInt();
|
||||
int index = indices.get(i).getAsInt();
|
||||
int signatureId = signatures.get(i).getAsInt();
|
||||
trapWriter.addTuple("type_contains_signature", trapWriter.globalID("type;" + baseType), kind, index,
|
||||
trapWriter.globalID("signature;" + signatureId));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractIndexTypeTable(JsonObject table, String relationName) {
|
||||
JsonArray baseTypes = table.get("baseTypes").getAsJsonArray();
|
||||
JsonArray propertyTypes = table.get("propertyTypes").getAsJsonArray();
|
||||
for (int i = 0; i < baseTypes.size(); ++i) {
|
||||
int baseType = baseTypes.get(i).getAsInt();
|
||||
int propertyType = propertyTypes.get(i).getAsInt();
|
||||
trapWriter.addTuple(relationName, trapWriter.globalID("type;" + baseType), trapWriter.globalID("type;" + propertyType));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractBaseTypes(JsonObject table) {
|
||||
JsonArray symbols = table.get("symbols").getAsJsonArray();
|
||||
JsonArray baseTypeSymbols = table.get("baseTypeSymbols").getAsJsonArray();
|
||||
for (int i = 0; i < symbols.size(); ++i) {
|
||||
int symbolId = symbols.get(i).getAsInt();
|
||||
int baseTypeSymbolId = baseTypeSymbols.get(i).getAsInt();
|
||||
trapWriter.addTuple("base_type_names", trapWriter.globalID("symbol;" + symbolId),
|
||||
trapWriter.globalID("symbol;" + baseTypeSymbolId));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSelfTypes(JsonObject table) {
|
||||
JsonArray symbols = table.get("symbols").getAsJsonArray();
|
||||
JsonArray selfTypes = table.get("selfTypes").getAsJsonArray();
|
||||
for (int i = 0; i < symbols.size(); ++i) {
|
||||
int symbolId = symbols.get(i).getAsInt();
|
||||
int typeId = selfTypes.get(i).getAsInt();
|
||||
trapWriter.addTuple("self_types", trapWriter.globalID("symbol;" + symbolId), trapWriter.globalID("type;" + typeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
113
javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java
Normal file
113
javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package com.semmle.ts.extractor;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Holds the output of the <tt>get-type-table</tt> command.
|
||||
* <p>
|
||||
* See documentation in <tt>parser-wrapper/src/type_table.ts</tt>.
|
||||
*/
|
||||
public class TypeTable {
|
||||
private final JsonArray typeStrings;
|
||||
private final JsonArray typeToStringValues;
|
||||
private final JsonObject propertyLookups;
|
||||
private final JsonArray symbolStrings;
|
||||
private final JsonObject moduleMappings;
|
||||
private final JsonObject globalMappings;
|
||||
private final JsonArray signatureStrings;
|
||||
private final JsonObject signatureMappings;
|
||||
private final JsonArray signatureToStringValues;
|
||||
private final JsonObject stringIndexTypes;
|
||||
private final JsonObject numberIndexTypes;
|
||||
private final JsonObject baseTypes;
|
||||
private final JsonObject selfTypes;
|
||||
|
||||
public TypeTable(JsonObject typeTable) {
|
||||
this.typeStrings = typeTable.get("typeStrings").getAsJsonArray();
|
||||
this.typeToStringValues = typeTable.get("typeToStringValues").getAsJsonArray();
|
||||
this.propertyLookups = typeTable.get("propertyLookups").getAsJsonObject();
|
||||
this.symbolStrings = typeTable.get("symbolStrings").getAsJsonArray();
|
||||
this.moduleMappings = typeTable.get("moduleMappings").getAsJsonObject();
|
||||
this.globalMappings = typeTable.get("globalMappings").getAsJsonObject();
|
||||
this.signatureStrings = typeTable.get("signatureStrings").getAsJsonArray();
|
||||
this.signatureMappings = typeTable.get("signatureMappings").getAsJsonObject();
|
||||
this.signatureToStringValues = typeTable.get("signatureToStringValues").getAsJsonArray();
|
||||
this.numberIndexTypes = typeTable.get("numberIndexTypes").getAsJsonObject();
|
||||
this.stringIndexTypes = typeTable.get("stringIndexTypes").getAsJsonObject();
|
||||
this.baseTypes = typeTable.get("baseTypes").getAsJsonObject();
|
||||
this.selfTypes = typeTable.get("selfTypes").getAsJsonObject();
|
||||
}
|
||||
|
||||
public String getTypeString(int index) {
|
||||
return typeStrings.get(index).getAsString();
|
||||
}
|
||||
|
||||
public String getTypeToStringValue(int index) {
|
||||
return typeToStringValues.get(index).getAsString();
|
||||
}
|
||||
|
||||
public JsonObject getPropertyLookups() {
|
||||
return propertyLookups;
|
||||
}
|
||||
|
||||
public int getNumberOfTypes() {
|
||||
return typeStrings.size();
|
||||
}
|
||||
|
||||
public String getSymbolString(int index) {
|
||||
return symbolStrings.get(index).getAsString();
|
||||
}
|
||||
|
||||
public int getNumberOfSymbols() {
|
||||
return symbolStrings.size();
|
||||
}
|
||||
|
||||
public JsonObject getModuleMappings() {
|
||||
return moduleMappings;
|
||||
}
|
||||
|
||||
public JsonObject getGlobalMappings() {
|
||||
return globalMappings;
|
||||
}
|
||||
|
||||
public JsonArray getSignatureStrings() {
|
||||
return signatureStrings;
|
||||
}
|
||||
|
||||
public int getNumberOfSignatures() {
|
||||
return signatureStrings.size();
|
||||
}
|
||||
|
||||
public String getSignatureString(int i) {
|
||||
return signatureStrings.get(i).getAsString();
|
||||
}
|
||||
|
||||
public JsonObject getSignatureMappings() {
|
||||
return signatureMappings;
|
||||
}
|
||||
|
||||
public JsonArray getSignatureToStringValues() {
|
||||
return signatureToStringValues;
|
||||
}
|
||||
|
||||
public String getSignatureToStringValue(int i) {
|
||||
return signatureToStringValues.get(i).getAsString();
|
||||
}
|
||||
|
||||
public JsonObject getNumberIndexTypes() {
|
||||
return numberIndexTypes;
|
||||
}
|
||||
|
||||
public JsonObject getStringIndexTypes() {
|
||||
return stringIndexTypes;
|
||||
}
|
||||
|
||||
public JsonObject getBaseTypes() {
|
||||
return baseTypes;
|
||||
}
|
||||
|
||||
public JsonObject getSelfTypes() {
|
||||
return selfTypes;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user