mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
JavaScript: Autoformat extractor sources using google-java-format.
No special settings; command: find javascript/extractor/src -name "*.java" | xargs java -jar /path/to/google-java-format-1.7-all-deps.jar --replace
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,5 @@
|
|||||||
package com.semmle.jcorn;
|
package com.semmle.jcorn;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.semmle.jcorn.TokenType.Properties;
|
import com.semmle.jcorn.TokenType.Properties;
|
||||||
import com.semmle.jcorn.jsx.JSXParser;
|
import com.semmle.jcorn.jsx.JSXParser;
|
||||||
import com.semmle.js.ast.BindExpression;
|
import com.semmle.js.ast.BindExpression;
|
||||||
@@ -42,457 +37,460 @@ import com.semmle.js.ast.Statement;
|
|||||||
import com.semmle.js.ast.Token;
|
import com.semmle.js.ast.Token;
|
||||||
import com.semmle.util.collections.CollectionUtil;
|
import com.semmle.util.collections.CollectionUtil;
|
||||||
import com.semmle.util.data.Pair;
|
import com.semmle.util.data.Pair;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An extension of the {@link JSXParser} with support for various
|
* An extension of the {@link JSXParser} with support for various unfinished ECMAScript proposals
|
||||||
* unfinished ECMAScript proposals that are not supported by
|
* that are not supported by Acorn/jcorn yet.
|
||||||
* Acorn/jcorn yet.
|
|
||||||
*
|
*
|
||||||
* Once support becomes available, they should be removed from
|
* <p>Once support becomes available, they should be removed from this class.
|
||||||
* this class.
|
|
||||||
*/
|
*/
|
||||||
public class ESNextParser extends JSXParser {
|
public class ESNextParser extends JSXParser {
|
||||||
public ESNextParser(Options options, String input, int startPos) {
|
public ESNextParser(Options options, String input, int startPos) {
|
||||||
super(options.allowImportExportEverywhere(true), input, startPos);
|
super(options.allowImportExportEverywhere(true), input, startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Object Rest/Spread Properties"
|
* Support for proposed language feature "Object Rest/Spread Properties"
|
||||||
* (http://sebmarkbage.github.io/ecmascript-rest-spread/).
|
* (http://sebmarkbage.github.io/ecmascript-rest-spread/).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Property parseProperty(boolean isPattern, DestructuringErrors refDestructuringErrors,
|
protected Property parseProperty(
|
||||||
Map<String, PropInfo> propHash) {
|
boolean isPattern,
|
||||||
Position start = this.startLoc;
|
DestructuringErrors refDestructuringErrors,
|
||||||
|
Map<String, PropInfo> propHash) {
|
||||||
|
Position start = this.startLoc;
|
||||||
|
|
||||||
List<Decorator> decorators = parseDecorators();
|
List<Decorator> decorators = parseDecorators();
|
||||||
|
|
||||||
Property prop = null;
|
Property prop = null;
|
||||||
if (this.type == TokenType.ellipsis) {
|
if (this.type == TokenType.ellipsis) {
|
||||||
SpreadElement spread = this.parseSpread(null);
|
SpreadElement spread = this.parseSpread(null);
|
||||||
Expression val;
|
Expression val;
|
||||||
if (isPattern)
|
if (isPattern) val = new RestElement(spread.getLoc(), spread.getArgument());
|
||||||
val = new RestElement(spread.getLoc(), spread.getArgument());
|
else val = spread;
|
||||||
else
|
prop =
|
||||||
val = spread;
|
this.finishNode(
|
||||||
prop = this.finishNode(new Property(new SourceLocation(start), null, val, Property.Kind.INIT.name(), false, false));
|
new Property(
|
||||||
}
|
new SourceLocation(start), null, val, Property.Kind.INIT.name(), false, false));
|
||||||
|
}
|
||||||
|
|
||||||
if (prop == null)
|
if (prop == null) prop = super.parseProperty(isPattern, refDestructuringErrors, propHash);
|
||||||
prop = super.parseProperty(isPattern, refDestructuringErrors, propHash);
|
|
||||||
|
|
||||||
prop.addDecorators(decorators);
|
prop.addDecorators(decorators);
|
||||||
|
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected INode toAssignable(INode node, boolean isBinding) {
|
protected INode toAssignable(INode node, boolean isBinding) {
|
||||||
if (node instanceof SpreadElement)
|
if (node instanceof SpreadElement)
|
||||||
return new RestElement(node.getLoc(), ((SpreadElement) node).getArgument());
|
return new RestElement(node.getLoc(), ((SpreadElement) node).getArgument());
|
||||||
return super.toAssignable(node, isBinding);
|
return super.toAssignable(node, isBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkLVal(INode expr, boolean isBinding, Set<String> checkClashes) {
|
protected void checkLVal(INode expr, boolean isBinding, Set<String> checkClashes) {
|
||||||
super.checkLVal(expr, isBinding, checkClashes);
|
super.checkLVal(expr, isBinding, checkClashes);
|
||||||
if (expr instanceof ObjectPattern) {
|
if (expr instanceof ObjectPattern) {
|
||||||
ObjectPattern op = (ObjectPattern) expr;
|
ObjectPattern op = (ObjectPattern) expr;
|
||||||
if (op.hasRest())
|
if (op.hasRest()) checkLVal(op.getRest(), isBinding, checkClashes);
|
||||||
checkLVal(op.getRest(), isBinding, checkClashes);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Public Class Fields"
|
* Support for proposed language feature "Public Class Fields"
|
||||||
* (http://jeffmo.github.io/es-class-public-fields/).
|
* (http://jeffmo.github.io/es-class-public-fields/).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private boolean classProperties() {
|
private boolean classProperties() {
|
||||||
return options.esnext();
|
return options.esnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemberDefinition<?> parseClassPropertyBody(PropertyInfo pi,
|
protected MemberDefinition<?> parseClassPropertyBody(
|
||||||
boolean hadConstructor, boolean isStatic) {
|
PropertyInfo pi, boolean hadConstructor, boolean isStatic) {
|
||||||
if (classProperties() && !pi.isGenerator && this.isClassProperty())
|
if (classProperties() && !pi.isGenerator && this.isClassProperty())
|
||||||
return this.parseFieldDefinition(pi, isStatic);
|
return this.parseFieldDefinition(pi, isStatic);
|
||||||
return super.parseClassPropertyBody(pi, hadConstructor, isStatic);
|
return super.parseClassPropertyBody(pi, hadConstructor, isStatic);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isClassProperty() {
|
protected boolean isClassProperty() {
|
||||||
return this.type == TokenType.eq || this.type == TokenType.semi || this.canInsertSemicolon();
|
return this.type == TokenType.eq || this.type == TokenType.semi || this.canInsertSemicolon();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FieldDefinition parseFieldDefinition(PropertyInfo pi, boolean isStatic) {
|
protected FieldDefinition parseFieldDefinition(PropertyInfo pi, boolean isStatic) {
|
||||||
Expression value = null;
|
Expression value = null;
|
||||||
if (this.type == TokenType.eq) {
|
if (this.type == TokenType.eq) {
|
||||||
this.next();
|
this.next();
|
||||||
boolean oldInFunc = this.inFunction;
|
boolean oldInFunc = this.inFunction;
|
||||||
this.inFunction = true;
|
this.inFunction = true;
|
||||||
value = parseMaybeAssign(false, null, null);
|
value = parseMaybeAssign(false, null, null);
|
||||||
this.inFunction = oldInFunc;
|
this.inFunction = oldInFunc;
|
||||||
}
|
}
|
||||||
this.semicolon();
|
this.semicolon();
|
||||||
int flags = DeclarationFlags.getStatic(isStatic) | DeclarationFlags.getComputed(pi.computed);
|
int flags = DeclarationFlags.getStatic(isStatic) | DeclarationFlags.getComputed(pi.computed);
|
||||||
return this.finishNode(new FieldDefinition(new SourceLocation(pi.startLoc), flags, pi.key, value));
|
return this.finishNode(
|
||||||
}
|
new FieldDefinition(new SourceLocation(pi.startLoc), flags, pi.key, value));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Generator function.sent Meta Property"
|
* Support for proposed language feature "Generator function.sent Meta Property"
|
||||||
* (https://github.com/allenwb/ESideas/blob/master/Generator%20metaproperty.md)
|
* (https://github.com/allenwb/ESideas/blob/master/Generator%20metaproperty.md)
|
||||||
*/
|
*/
|
||||||
private boolean functionSent() {
|
private boolean functionSent() {
|
||||||
return options.esnext();
|
return options.esnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected INode parseFunction(Position startLoc, boolean isStatement,
|
protected INode parseFunction(
|
||||||
boolean allowExpressionBody, boolean isAsync) {
|
Position startLoc, boolean isStatement, boolean allowExpressionBody, boolean isAsync) {
|
||||||
if (isFunctionSent(isStatement)) {
|
if (isFunctionSent(isStatement)) {
|
||||||
Identifier meta = this.finishNode(new Identifier(new SourceLocation(startLoc), "function"));
|
Identifier meta = this.finishNode(new Identifier(new SourceLocation(startLoc), "function"));
|
||||||
this.next();
|
this.next();
|
||||||
Identifier property = parseIdent(true);
|
Identifier property = parseIdent(true);
|
||||||
if (!property.getName().equals("sent"))
|
if (!property.getName().equals("sent"))
|
||||||
this.raiseRecoverable(property, "The only valid meta property for function is function.sent");
|
this.raiseRecoverable(
|
||||||
return this.finishNode(new MetaProperty(new SourceLocation(startLoc), meta, property));
|
property, "The only valid meta property for function is function.sent");
|
||||||
}
|
return this.finishNode(new MetaProperty(new SourceLocation(startLoc), meta, property));
|
||||||
|
}
|
||||||
|
|
||||||
return super.parseFunction(startLoc, isStatement, allowExpressionBody, isAsync);
|
return super.parseFunction(startLoc, isStatement, allowExpressionBody, isAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isFunctionSent(boolean isStatement) {
|
protected boolean isFunctionSent(boolean isStatement) {
|
||||||
return functionSent() && !isStatement && inGenerator && !inAsync && this.type == TokenType.dot;
|
return functionSent() && !isStatement && inGenerator && !inAsync && this.type == TokenType.dot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Class and Property Decorators"
|
* Support for proposed language feature "Class and Property Decorators"
|
||||||
* (https://github.com/wycats/javascript-decorators)
|
* (https://github.com/wycats/javascript-decorators)
|
||||||
*/
|
*/
|
||||||
private boolean decorators() {
|
private boolean decorators() {
|
||||||
return options.esnext();
|
return options.esnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TokenType at = new TokenType(new Properties("@").beforeExpr());
|
protected TokenType at = new TokenType(new Properties("@").beforeExpr());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Token getTokenFromCode(int code) {
|
protected Token getTokenFromCode(int code) {
|
||||||
if (decorators() && code == 64) {
|
if (decorators() && code == 64) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
return this.finishToken(at);
|
return this.finishToken(at);
|
||||||
}
|
}
|
||||||
if (functionBind() && code == 58 && charAt(this.pos+1) == 58) {
|
if (functionBind() && code == 58 && charAt(this.pos + 1) == 58) {
|
||||||
this.pos += 2;
|
this.pos += 2;
|
||||||
return this.finishToken(doubleColon);
|
return this.finishToken(doubleColon);
|
||||||
}
|
}
|
||||||
return super.getTokenFromCode(code);
|
return super.getTokenFromCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Statement parseStatement(boolean declaration, boolean topLevel,
|
protected Statement parseStatement(boolean declaration, boolean topLevel, Set<String> exports) {
|
||||||
Set<String> exports) {
|
List<Decorator> decorators = this.parseDecorators();
|
||||||
List<Decorator> decorators = this.parseDecorators();
|
Statement stmt = super.parseStatement(declaration, topLevel, exports);
|
||||||
Statement stmt = super.parseStatement(declaration, topLevel, exports);
|
|
||||||
|
|
||||||
if (!decorators.isEmpty()) {
|
if (!decorators.isEmpty()) {
|
||||||
if (stmt instanceof ExportDeclaration) {
|
if (stmt instanceof ExportDeclaration) {
|
||||||
Node exported = null;
|
Node exported = null;
|
||||||
if (stmt instanceof ExportDefaultDeclaration) {
|
if (stmt instanceof ExportDefaultDeclaration) {
|
||||||
exported = ((ExportDefaultDeclaration) stmt).getDeclaration();
|
exported = ((ExportDefaultDeclaration) stmt).getDeclaration();
|
||||||
} else if (stmt instanceof ExportNamedDeclaration) {
|
} else if (stmt instanceof ExportNamedDeclaration) {
|
||||||
exported = ((ExportNamedDeclaration) stmt).getDeclaration();
|
exported = ((ExportNamedDeclaration) stmt).getDeclaration();
|
||||||
}
|
}
|
||||||
if (exported instanceof ClassDeclaration) {
|
if (exported instanceof ClassDeclaration) {
|
||||||
((ClassDeclaration) exported).addDecorators(decorators);
|
((ClassDeclaration) exported).addDecorators(decorators);
|
||||||
} else if (exported instanceof ClassExpression) {
|
} else if (exported instanceof ClassExpression) {
|
||||||
((ClassExpression) exported).addDecorators(decorators);
|
((ClassExpression) exported).addDecorators(decorators);
|
||||||
} else {
|
} else {
|
||||||
this.raise(stmt, "Decorators can only be attached to class exports");
|
this.raise(stmt, "Decorators can only be attached to class exports");
|
||||||
}
|
}
|
||||||
} else if (stmt instanceof ClassDeclaration) {
|
} else if (stmt instanceof ClassDeclaration) {
|
||||||
((ClassDeclaration) stmt).addDecorators(decorators);
|
((ClassDeclaration) stmt).addDecorators(decorators);
|
||||||
} else if (stmt != null) {
|
} else if (stmt != null) {
|
||||||
this.raise(stmt, "Leading decorators must be attached to a class declaration");
|
this.raise(stmt, "Leading decorators must be attached to a class declaration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
|
protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
|
||||||
if (this.type == at) {
|
if (this.type == at) {
|
||||||
List<Decorator> decorators = parseDecorators();
|
List<Decorator> decorators = parseDecorators();
|
||||||
ClassExpression ce = (ClassExpression) this.parseClass(startLoc, false);
|
ClassExpression ce = (ClassExpression) this.parseClass(startLoc, false);
|
||||||
ce.addDecorators(decorators);
|
ce.addDecorators(decorators);
|
||||||
return ce;
|
return ce;
|
||||||
}
|
}
|
||||||
if (this.type == doubleColon) {
|
if (this.type == doubleColon) {
|
||||||
SourceLocation startLoc = new SourceLocation(this.startLoc);
|
SourceLocation startLoc = new SourceLocation(this.startLoc);
|
||||||
this.next();
|
this.next();
|
||||||
int innerStart = this.start;
|
int innerStart = this.start;
|
||||||
Position innerStartLoc = this.startLoc;
|
Position innerStartLoc = this.startLoc;
|
||||||
Expression callee = parseSubscripts(parseExprAtom(null), innerStart, innerStartLoc, true);
|
Expression callee = parseSubscripts(parseExprAtom(null), innerStart, innerStartLoc, true);
|
||||||
if (!(callee instanceof MemberExpression))
|
if (!(callee instanceof MemberExpression))
|
||||||
this.raiseRecoverable(callee, "Binding should be performed on a member expression.");
|
this.raiseRecoverable(callee, "Binding should be performed on a member expression.");
|
||||||
return this.finishNode(new BindExpression(startLoc, null, callee));
|
return this.finishNode(new BindExpression(startLoc, null, callee));
|
||||||
}
|
}
|
||||||
if (this.type == TokenType._import) {
|
if (this.type == TokenType._import) {
|
||||||
Position startLoc = this.startLoc;
|
Position startLoc = this.startLoc;
|
||||||
this.next();
|
this.next();
|
||||||
this.expect(TokenType.parenL);
|
this.expect(TokenType.parenL);
|
||||||
return parseDynamicImport(startLoc);
|
return parseDynamicImport(startLoc);
|
||||||
}
|
}
|
||||||
return super.parseExprAtom(refDestructuringErrors);
|
return super.parseExprAtom(refDestructuringErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemberDefinition<?> parseClassMember(boolean hadConstructor) {
|
protected MemberDefinition<?> parseClassMember(boolean hadConstructor) {
|
||||||
List<Decorator> decorators = parseDecorators();
|
List<Decorator> decorators = parseDecorators();
|
||||||
MemberDefinition<?> member = super.parseClassMember(hadConstructor);
|
MemberDefinition<?> member = super.parseClassMember(hadConstructor);
|
||||||
if (!decorators.isEmpty() && member.isConstructor())
|
if (!decorators.isEmpty() && member.isConstructor())
|
||||||
this.raiseRecoverable(member, "Decorators cannot be attached to class constructors.");
|
this.raiseRecoverable(member, "Decorators cannot be attached to class constructors.");
|
||||||
member.addDecorators(decorators);
|
member.addDecorators(decorators);
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Decorator> parseDecorators() {
|
public List<Decorator> parseDecorators() {
|
||||||
List<Decorator> result = new ArrayList<Decorator>();
|
List<Decorator> result = new ArrayList<Decorator>();
|
||||||
while (this.type == at)
|
while (this.type == at) result.add(this.parseDecorator());
|
||||||
result.add(this.parseDecorator());
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Decorator parseDecorator() {
|
private Decorator parseDecorator() {
|
||||||
Position start = startLoc;
|
Position start = startLoc;
|
||||||
this.next();
|
this.next();
|
||||||
Expression body = parseDecoratorBody();
|
Expression body = parseDecoratorBody();
|
||||||
Decorator decorator = new Decorator(new SourceLocation(start), body);
|
Decorator decorator = new Decorator(new SourceLocation(start), body);
|
||||||
return this.finishNode(decorator);
|
return this.finishNode(decorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Expression parseDecoratorBody() {
|
protected Expression parseDecoratorBody() {
|
||||||
Expression base;
|
Expression base;
|
||||||
int startPos = this.start;
|
int startPos = this.start;
|
||||||
Position startLoc = this.startLoc;
|
Position startLoc = this.startLoc;
|
||||||
if (this.type == TokenType.parenL) {
|
if (this.type == TokenType.parenL) {
|
||||||
base = parseParenExpression();
|
base = parseParenExpression();
|
||||||
} else {
|
} else {
|
||||||
base = parseIdent(true);
|
base = parseIdent(true);
|
||||||
}
|
}
|
||||||
return parseSubscripts(base, startPos, startLoc, false);
|
return parseSubscripts(base, startPos, startLoc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed extensions to `export`
|
* Support for proposed extensions to `export`
|
||||||
* (http://leebyron.com/ecmascript-export-ns-from and http://leebyron.com/ecmascript-export-default-from)
|
* (http://leebyron.com/ecmascript-export-ns-from and http://leebyron.com/ecmascript-export-default-from)
|
||||||
*/
|
*/
|
||||||
private boolean exportExtensions() {
|
private boolean exportExtensions() {
|
||||||
return options.esnext();
|
return options.esnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ExportDeclaration parseExportRest(SourceLocation exportStart, Set<String> exports) {
|
protected ExportDeclaration parseExportRest(SourceLocation exportStart, Set<String> exports) {
|
||||||
if (exportExtensions() && this.isExportDefaultSpecifier()) {
|
if (exportExtensions() && this.isExportDefaultSpecifier()) {
|
||||||
Position specStart = this.startLoc;
|
Position specStart = this.startLoc;
|
||||||
Identifier exported = this.parseIdent(true);
|
Identifier exported = this.parseIdent(true);
|
||||||
ExportDefaultSpecifier defaultSpec = this.finishNode(new ExportDefaultSpecifier(new SourceLocation(specStart), exported));
|
ExportDefaultSpecifier defaultSpec =
|
||||||
List<ExportSpecifier> specifiers = CollectionUtil.makeList(defaultSpec);
|
this.finishNode(new ExportDefaultSpecifier(new SourceLocation(specStart), exported));
|
||||||
if (this.type == TokenType.comma && this.lookahead(1, true).equals("*")) {
|
List<ExportSpecifier> specifiers = CollectionUtil.makeList(defaultSpec);
|
||||||
this.next();
|
if (this.type == TokenType.comma && this.lookahead(1, true).equals("*")) {
|
||||||
specStart = this.startLoc;
|
this.next();
|
||||||
this.expect(TokenType.star);
|
specStart = this.startLoc;
|
||||||
this.expectContextual("as");
|
this.expect(TokenType.star);
|
||||||
exported = this.parseIdent(false);
|
this.expectContextual("as");
|
||||||
ExportNamespaceSpecifier nsSpec = this.finishNode(new ExportNamespaceSpecifier(new SourceLocation(specStart), exported));
|
exported = this.parseIdent(false);
|
||||||
specifiers.add(nsSpec);
|
ExportNamespaceSpecifier nsSpec =
|
||||||
} else {
|
this.finishNode(new ExportNamespaceSpecifier(new SourceLocation(specStart), exported));
|
||||||
this.parseExportSpecifiersMaybe(specifiers, exports);
|
specifiers.add(nsSpec);
|
||||||
}
|
} else {
|
||||||
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
|
this.parseExportSpecifiersMaybe(specifiers, exports);
|
||||||
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
|
}
|
||||||
}
|
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
|
||||||
|
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
|
||||||
|
}
|
||||||
|
|
||||||
return super.parseExportRest(exportStart, exports);
|
return super.parseExportRest(exportStart, exports);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ExportDeclaration parseExportAll(SourceLocation exportStart, Position starLoc, Set<String> exports) {
|
protected ExportDeclaration parseExportAll(
|
||||||
if (exportExtensions() && this.eatContextual("as")) {
|
SourceLocation exportStart, Position starLoc, Set<String> exports) {
|
||||||
Identifier exported = this.parseIdent(false);
|
if (exportExtensions() && this.eatContextual("as")) {
|
||||||
ExportNamespaceSpecifier nsSpec = this.finishNode(new ExportNamespaceSpecifier(new SourceLocation(starLoc), exported));
|
Identifier exported = this.parseIdent(false);
|
||||||
List<ExportSpecifier> specifiers = CollectionUtil.makeList(nsSpec);
|
ExportNamespaceSpecifier nsSpec =
|
||||||
this.parseExportSpecifiersMaybe(specifiers, exports);
|
this.finishNode(new ExportNamespaceSpecifier(new SourceLocation(starLoc), exported));
|
||||||
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
|
List<ExportSpecifier> specifiers = CollectionUtil.makeList(nsSpec);
|
||||||
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
|
this.parseExportSpecifiersMaybe(specifiers, exports);
|
||||||
}
|
Literal source = (Literal) this.parseExportFrom(specifiers, null, true);
|
||||||
|
return this.finishNode(new ExportNamedDeclaration(exportStart, null, specifiers, source));
|
||||||
|
}
|
||||||
|
|
||||||
return super.parseExportAll(exportStart, starLoc, exports);
|
return super.parseExportAll(exportStart, starLoc, exports);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExportDefaultSpecifier() {
|
private boolean isExportDefaultSpecifier() {
|
||||||
if (this.type == TokenType.name) {
|
if (this.type == TokenType.name) {
|
||||||
return !this.value.equals("type") &&
|
return !this.value.equals("type")
|
||||||
!this.value.equals("async") &&
|
&& !this.value.equals("async")
|
||||||
!this.value.equals("interface") &&
|
&& !this.value.equals("interface")
|
||||||
!this.value.equals("let");
|
&& !this.value.equals("let");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.type != TokenType._default)
|
if (this.type != TokenType._default) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
return this.lookahead(1, true).equals(",") || this.lookaheadIsIdent("from", true);
|
return this.lookahead(1, true).equals(",") || this.lookaheadIsIdent("from", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseExportSpecifiersMaybe(List<ExportSpecifier> specifiers, Set<String> exports) {
|
private void parseExportSpecifiersMaybe(List<ExportSpecifier> specifiers, Set<String> exports) {
|
||||||
if (this.eat(TokenType.comma)) {
|
if (this.eat(TokenType.comma)) {
|
||||||
specifiers.addAll(this.parseExportSpecifiers(exports));
|
specifiers.addAll(this.parseExportSpecifiers(exports));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Function Bind Syntax"
|
* Support for proposed language feature "Function Bind Syntax"
|
||||||
* (https://github.com/tc39/proposal-bind-operator)
|
* (https://github.com/tc39/proposal-bind-operator)
|
||||||
*/
|
*/
|
||||||
private boolean functionBind() {
|
private boolean functionBind() {
|
||||||
return options.esnext();
|
return options.esnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TokenType doubleColon = new TokenType(new Properties("::").beforeExpr());
|
protected TokenType doubleColon = new TokenType(new Properties("::").beforeExpr());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pair<Expression, Boolean> parseSubscript(Expression base, Position startLoc, boolean noCalls) {
|
protected Pair<Expression, Boolean> parseSubscript(
|
||||||
if (!noCalls && this.eat(doubleColon)) {
|
Expression base, Position startLoc, boolean noCalls) {
|
||||||
Expression callee = parseSubscripts(parseExprAtom(null), this.start, this.startLoc, true);
|
if (!noCalls && this.eat(doubleColon)) {
|
||||||
BindExpression bind = new BindExpression(new SourceLocation(startLoc), base, callee);
|
Expression callee = parseSubscripts(parseExprAtom(null), this.start, this.startLoc, true);
|
||||||
return Pair.make(this.finishNode(bind), true);
|
BindExpression bind = new BindExpression(new SourceLocation(startLoc), base, callee);
|
||||||
}
|
return Pair.make(this.finishNode(bind), true);
|
||||||
return super.parseSubscript(base, startLoc, noCalls);
|
}
|
||||||
}
|
return super.parseSubscript(base, startLoc, noCalls);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Optional Catch Binding"
|
* Support for proposed language feature "Optional Catch Binding"
|
||||||
* (https://github.com/tc39/proposal-optional-catch-binding)
|
* (https://github.com/tc39/proposal-optional-catch-binding)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected CatchClause parseCatchClause(Position startLoc) {
|
protected CatchClause parseCatchClause(Position startLoc) {
|
||||||
this.next();
|
this.next();
|
||||||
Expression param = null;
|
Expression param = null;
|
||||||
if (this.eat(TokenType.parenL)) {
|
if (this.eat(TokenType.parenL)) {
|
||||||
param = this.parseBindingAtom();
|
param = this.parseBindingAtom();
|
||||||
this.checkLVal(param, true, null);
|
this.checkLVal(param, true, null);
|
||||||
this.expect(TokenType.parenR);
|
this.expect(TokenType.parenR);
|
||||||
} else if (!options.esnext()) {
|
} else if (!options.esnext()) {
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
BlockStatement catchBody = this.parseBlock(false);
|
BlockStatement catchBody = this.parseBlock(false);
|
||||||
return this.finishNode(new CatchClause(new SourceLocation(startLoc), (IPattern)param, null, catchBody));
|
return this.finishNode(
|
||||||
}
|
new CatchClause(new SourceLocation(startLoc), (IPattern) param, null, catchBody));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Dynamic import"
|
* Support for proposed language feature "Dynamic import"
|
||||||
* (https://github.com/tc39/proposal-dynamic-import).
|
* (https://github.com/tc39/proposal-dynamic-import).
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Statement parseImport(Position startLoc) {
|
protected Statement parseImport(Position startLoc) {
|
||||||
if (!options.esnext())
|
if (!options.esnext()) return super.parseImport(startLoc);
|
||||||
return super.parseImport(startLoc);
|
|
||||||
|
|
||||||
int startPos = this.start;
|
int startPos = this.start;
|
||||||
SourceLocation loc = new SourceLocation(startLoc);
|
SourceLocation loc = new SourceLocation(startLoc);
|
||||||
this.next();
|
this.next();
|
||||||
if (this.eat(TokenType.parenL)) {
|
if (this.eat(TokenType.parenL)) {
|
||||||
DynamicImport di = parseDynamicImport(startLoc);
|
DynamicImport di = parseDynamicImport(startLoc);
|
||||||
Expression expr = parseSubscripts(di, startPos, startLoc, false);
|
Expression expr = parseSubscripts(di, startPos, startLoc, false);
|
||||||
return parseExpressionStatement(false, startLoc, expr);
|
return parseExpressionStatement(false, startLoc, expr);
|
||||||
} else {
|
} else {
|
||||||
return super.parseImportRest(loc);
|
return super.parseImportRest(loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a dynamic import, assuming that the keyword `import` and the
|
* Parses a dynamic import, assuming that the keyword `import` and the opening parenthesis have
|
||||||
* opening parenthesis have already been consumed.
|
* already been consumed.
|
||||||
*/
|
*/
|
||||||
private DynamicImport parseDynamicImport(Position startLoc) {
|
private DynamicImport parseDynamicImport(Position startLoc) {
|
||||||
Expression source = parseMaybeAssign(false, null, null);
|
Expression source = parseMaybeAssign(false, null, null);
|
||||||
this.expect(TokenType.parenR);
|
this.expect(TokenType.parenR);
|
||||||
DynamicImport di = this.finishNode(new DynamicImport(new SourceLocation(startLoc), source));
|
DynamicImport di = this.finishNode(new DynamicImport(new SourceLocation(startLoc), source));
|
||||||
return di;
|
return di;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Asynchronous iteration"
|
* Support for proposed language feature "Asynchronous iteration"
|
||||||
* (https://github.com/tc39/proposal-async-iteration)
|
* (https://github.com/tc39/proposal-async-iteration)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Statement parseForStatement(Position startLoc) {
|
protected Statement parseForStatement(Position startLoc) {
|
||||||
int startPos = this.start;
|
int startPos = this.start;
|
||||||
boolean isAwait = false;
|
boolean isAwait = false;
|
||||||
if (this.inAsync && this.eatContextual("await"))
|
if (this.inAsync && this.eatContextual("await")) isAwait = true;
|
||||||
isAwait = true;
|
Statement forStmt = super.parseForStatement(startLoc);
|
||||||
Statement forStmt = super.parseForStatement(startLoc);
|
if (isAwait) {
|
||||||
if (isAwait) {
|
if (forStmt instanceof ForOfStatement) ((ForOfStatement) forStmt).setAwait(true);
|
||||||
if (forStmt instanceof ForOfStatement)
|
else this.raiseRecoverable(startPos, "Only for-of statements can be annotated with 'await'.");
|
||||||
((ForOfStatement) forStmt).setAwait(true);
|
}
|
||||||
else
|
return forStmt;
|
||||||
this.raiseRecoverable(startPos, "Only for-of statements can be annotated with 'await'.");
|
}
|
||||||
}
|
|
||||||
return forStmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean parseGeneratorMarker(boolean isAsync) {
|
protected boolean parseGeneratorMarker(boolean isAsync) {
|
||||||
// always allow `*`, even if `isAsync` is true
|
// always allow `*`, even if `isAsync` is true
|
||||||
return this.eat(TokenType.star);
|
return this.eat(TokenType.star);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support for proposed language feature "Numeric separators"
|
* Support for proposed language feature "Numeric separators"
|
||||||
* (https://github.com/tc39/proposal-numeric-separator)
|
* (https://github.com/tc39/proposal-numeric-separator)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Number readInt(int radix, Integer len) {
|
protected Number readInt(int radix, Integer len) {
|
||||||
// implementation mostly copied from super class
|
// implementation mostly copied from super class
|
||||||
int start = this.pos, code = -1;
|
int start = this.pos, code = -1;
|
||||||
double total = 0;
|
double total = 0;
|
||||||
// no leading underscore
|
// no leading underscore
|
||||||
boolean underscoreAllowed = false;
|
boolean underscoreAllowed = false;
|
||||||
|
|
||||||
for (int i = 0, e = len == null ? Integer.MAX_VALUE : len; i < e; ++i) {
|
for (int i = 0, e = len == null ? Integer.MAX_VALUE : len; i < e; ++i) {
|
||||||
if (this.pos >= this.input.length())
|
if (this.pos >= this.input.length()) break;
|
||||||
break;
|
code = this.input.charAt(this.pos);
|
||||||
code = this.input.charAt(this.pos);
|
|
||||||
|
|
||||||
if (code == '_') {
|
if (code == '_') {
|
||||||
if (underscoreAllowed) {
|
if (underscoreAllowed) {
|
||||||
// no adjacent underscores
|
// no adjacent underscores
|
||||||
underscoreAllowed = false;
|
underscoreAllowed = false;
|
||||||
++this.pos;
|
++this.pos;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
underscoreAllowed = true;
|
underscoreAllowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int val;
|
int val;
|
||||||
if (code >= 97) val = code - 97 + 10; // a
|
if (code >= 97) val = code - 97 + 10; // a
|
||||||
else if (code >= 65) val = code - 65 + 10; // A
|
else if (code >= 65) val = code - 65 + 10; // A
|
||||||
else if (code >= 48 && code <= 57) val = code - 48; // 0-9
|
else if (code >= 48 && code <= 57) val = code - 48; // 0-9
|
||||||
else val = Integer.MAX_VALUE;
|
else val = Integer.MAX_VALUE;
|
||||||
if (val >= radix) break;
|
if (val >= radix) break;
|
||||||
|
|
||||||
++this.pos;
|
++this.pos;
|
||||||
total = total * radix + val;
|
total = total * radix + val;
|
||||||
}
|
}
|
||||||
if (this.pos == start || len != null && this.pos - start != len) return null;
|
if (this.pos == start || len != null && this.pos - start != len) return null;
|
||||||
|
|
||||||
if (code == '_')
|
if (code == '_')
|
||||||
// no trailing underscore
|
// no trailing underscore
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,110 +8,149 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/// identifier.js
|
/// identifier.js
|
||||||
public class Identifiers {
|
public class Identifiers {
|
||||||
public static enum Dialect {
|
public static enum Dialect {
|
||||||
ECMA_3, ECMA_5, ECMA_6, ECMA_7, ECMA_8, STRICT, STRICT_BIND
|
ECMA_3,
|
||||||
}
|
ECMA_5,
|
||||||
|
ECMA_6,
|
||||||
|
ECMA_7,
|
||||||
|
ECMA_8,
|
||||||
|
STRICT,
|
||||||
|
STRICT_BIND
|
||||||
|
}
|
||||||
|
|
||||||
// Reserved word lists for various dialects of the language
|
// Reserved word lists for various dialects of the language
|
||||||
public static final Map<Dialect, Set<String>> reservedWords = new LinkedHashMap<>();
|
public static final Map<Dialect, Set<String>> reservedWords = new LinkedHashMap<>();
|
||||||
static {
|
|
||||||
reservedWords.put(Dialect.ECMA_3, stringSet("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"));
|
|
||||||
reservedWords.put(Dialect.ECMA_5, stringSet("class enum extends super const export import"));
|
|
||||||
reservedWords.put(Dialect.ECMA_6, stringSet("enum"));
|
|
||||||
reservedWords.put(Dialect.ECMA_7, stringSet("enum"));
|
|
||||||
reservedWords.put(Dialect.ECMA_8, stringSet("enum"));
|
|
||||||
reservedWords.put(Dialect.STRICT, stringSet("implements interface let package private protected public static yield"));
|
|
||||||
reservedWords.put(Dialect.STRICT_BIND, stringSet("eval arguments"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// And the keywords
|
static {
|
||||||
private static final String ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
|
reservedWords.put(
|
||||||
private static final String ecma6Keywords = ecma5AndLessKeywords + " const class extends export import super";
|
Dialect.ECMA_3,
|
||||||
|
stringSet(
|
||||||
|
"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"));
|
||||||
|
reservedWords.put(Dialect.ECMA_5, stringSet("class enum extends super const export import"));
|
||||||
|
reservedWords.put(Dialect.ECMA_6, stringSet("enum"));
|
||||||
|
reservedWords.put(Dialect.ECMA_7, stringSet("enum"));
|
||||||
|
reservedWords.put(Dialect.ECMA_8, stringSet("enum"));
|
||||||
|
reservedWords.put(
|
||||||
|
Dialect.STRICT,
|
||||||
|
stringSet("implements interface let package private protected public static yield"));
|
||||||
|
reservedWords.put(Dialect.STRICT_BIND, stringSet("eval arguments"));
|
||||||
|
}
|
||||||
|
|
||||||
public static final Map<Dialect, Set<String>> keywords = new LinkedHashMap<>();
|
// And the keywords
|
||||||
static {
|
private static final String ecma5AndLessKeywords =
|
||||||
keywords.put(Dialect.ECMA_5, stringSet(ecma5AndLessKeywords));
|
"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
|
||||||
keywords.put(Dialect.ECMA_6, stringSet(ecma6Keywords));
|
private static final String ecma6Keywords =
|
||||||
}
|
ecma5AndLessKeywords + " const class extends export import super";
|
||||||
|
|
||||||
private static Set<String> stringSet(String words) {
|
public static final Map<Dialect, Set<String>> keywords = new LinkedHashMap<>();
|
||||||
Set<String> result = new LinkedHashSet<String>();
|
|
||||||
for (String word : words.split(" "))
|
|
||||||
result.add(word);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ## Character categories
|
static {
|
||||||
|
keywords.put(Dialect.ECMA_5, stringSet(ecma5AndLessKeywords));
|
||||||
|
keywords.put(Dialect.ECMA_6, stringSet(ecma6Keywords));
|
||||||
|
}
|
||||||
|
|
||||||
private static final String nonASCIIidentifierStartChars =
|
private static Set<String> stringSet(String words) {
|
||||||
"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u037f\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u052f\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0-\\u08b4\\u08b6-\\u08bd\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0af9\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c39\\u0c3d\\u0c58-\\u0c5a\\u0c60\\u0c61\\u0c80\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d54-\\u0d56\\u0d5f-\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f5\\u13f8-\\u13fd\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f8\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191e\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19b0-\\u19c9\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1c80-\\u1c88\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2118-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309b-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fd5\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua69d\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua7ae\\ua7b0-\\ua7b7\\ua7f7-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua8fd\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\ua9e0-\\ua9e4\\ua9e6-\\ua9ef\\ua9fa-\\ua9fe\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa7e-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uab30-\\uab5a\\uab5c-\\uab65\\uab70-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc";
|
Set<String> result = new LinkedHashSet<String>();
|
||||||
private static final String nonASCIIidentifierChars =
|
for (String word : words.split(" ")) result.add(word);
|
||||||
"\\u200c\\u200d\\xb7\\u0300-\\u036f\\u0387\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u0669\\u0670\\u06d6-\\u06dc\\u06df-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u06f0-\\u06f9\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07c0-\\u07c9\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0859-\\u085b\\u08d4-\\u08e1\\u08e3-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09cb-\\u09cd\\u09d7\\u09e2\\u09e3\\u09e6-\\u09ef\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c00-\\u0c03\\u0c3e-\\u0c44\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0c66-\\u0c6f\\u0c81-\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0ce6-\\u0cef\\u0d01-\\u0d03\\u0d3e-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4d\\u0d57\\u0d62\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0de6-\\u0def\\u0df2\\u0df3\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0e50-\\u0e59\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f3e\\u0f3f\\u0f71-\\u0f84\\u0f86\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102b-\\u103e\\u1040-\\u1049\\u1056-\\u1059\\u105e-\\u1060\\u1062-\\u1064\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u1369-\\u1371\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b4-\\u17d3\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u18a9\\u1920-\\u192b\\u1930-\\u193b\\u1946-\\u194f\\u19d0-\\u19da\\u1a17-\\u1a1b\\u1a55-\\u1a5e\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1ab0-\\u1abd\\u1b00-\\u1b04\\u1b34-\\u1b44\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1b82\\u1ba1-\\u1bad\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c24-\\u1c37\\u1c40-\\u1c49\\u1c50-\\u1c59\\u1cd0-\\u1cd2\\u1cd4-\\u1ce8\\u1ced\\u1cf2-\\u1cf4\\u1cf8\\u1cf9\\u1dc0-\\u1df5\\u1dfb-\\u1dff\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2cef-\\u2cf1\\u2d7f\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua620-\\ua629\\ua66f\\ua674-\\ua67d\\ua69e\\ua69f\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua823-\\ua827\\ua880\\ua881\\ua8b4-\\ua8c5\\ua8d0-\\ua8d9\\ua8e0-\\ua8f1\\ua900-\\ua909\\ua926-\\ua92d\\ua947-\\ua953\\ua980-\\ua983\\ua9b3-\\ua9c0\\ua9d0-\\ua9d9\\ua9e5\\ua9f0-\\ua9f9\\uaa29-\\uaa36\\uaa43\\uaa4c\\uaa4d\\uaa50-\\uaa59\\uaa7b-\\uaa7d\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uaaeb-\\uaaef\\uaaf5\\uaaf6\\uabe3-\\uabea\\uabec\\uabed\\uabf0-\\uabf9\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe2f\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f";
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static Pattern nonASCIIidentifierStartPattern;
|
// ## Character categories
|
||||||
private static Pattern nonASCIIidentifierPattern;
|
|
||||||
|
|
||||||
private static Pattern nonASCIIidentifierStart() {
|
private static final String nonASCIIidentifierStartChars =
|
||||||
if (nonASCIIidentifierStartPattern == null)
|
"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u037f\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u052f\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0-\\u08b4\\u08b6-\\u08bd\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0af9\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c39\\u0c3d\\u0c58-\\u0c5a\\u0c60\\u0c61\\u0c80\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d54-\\u0d56\\u0d5f-\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f5\\u13f8-\\u13fd\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f8\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191e\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19b0-\\u19c9\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1c80-\\u1c88\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2118-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309b-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fd5\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua69d\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua7ae\\ua7b0-\\ua7b7\\ua7f7-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua8fd\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\ua9e0-\\ua9e4\\ua9e6-\\ua9ef\\ua9fa-\\ua9fe\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa7e-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uab30-\\uab5a\\uab5c-\\uab65\\uab70-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc";
|
||||||
nonASCIIidentifierStartPattern = Pattern.compile("[" + nonASCIIidentifierStartChars + "]");
|
private static final String nonASCIIidentifierChars =
|
||||||
return nonASCIIidentifierStartPattern;
|
"\\u200c\\u200d\\xb7\\u0300-\\u036f\\u0387\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u0669\\u0670\\u06d6-\\u06dc\\u06df-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u06f0-\\u06f9\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07c0-\\u07c9\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0859-\\u085b\\u08d4-\\u08e1\\u08e3-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09cb-\\u09cd\\u09d7\\u09e2\\u09e3\\u09e6-\\u09ef\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c00-\\u0c03\\u0c3e-\\u0c44\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0c66-\\u0c6f\\u0c81-\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0ce6-\\u0cef\\u0d01-\\u0d03\\u0d3e-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4d\\u0d57\\u0d62\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0de6-\\u0def\\u0df2\\u0df3\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0e50-\\u0e59\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f3e\\u0f3f\\u0f71-\\u0f84\\u0f86\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102b-\\u103e\\u1040-\\u1049\\u1056-\\u1059\\u105e-\\u1060\\u1062-\\u1064\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u1369-\\u1371\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b4-\\u17d3\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u18a9\\u1920-\\u192b\\u1930-\\u193b\\u1946-\\u194f\\u19d0-\\u19da\\u1a17-\\u1a1b\\u1a55-\\u1a5e\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1ab0-\\u1abd\\u1b00-\\u1b04\\u1b34-\\u1b44\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1b82\\u1ba1-\\u1bad\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c24-\\u1c37\\u1c40-\\u1c49\\u1c50-\\u1c59\\u1cd0-\\u1cd2\\u1cd4-\\u1ce8\\u1ced\\u1cf2-\\u1cf4\\u1cf8\\u1cf9\\u1dc0-\\u1df5\\u1dfb-\\u1dff\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2cef-\\u2cf1\\u2d7f\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua620-\\ua629\\ua66f\\ua674-\\ua67d\\ua69e\\ua69f\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua823-\\ua827\\ua880\\ua881\\ua8b4-\\ua8c5\\ua8d0-\\ua8d9\\ua8e0-\\ua8f1\\ua900-\\ua909\\ua926-\\ua92d\\ua947-\\ua953\\ua980-\\ua983\\ua9b3-\\ua9c0\\ua9d0-\\ua9d9\\ua9e5\\ua9f0-\\ua9f9\\uaa29-\\uaa36\\uaa43\\uaa4c\\uaa4d\\uaa50-\\uaa59\\uaa7b-\\uaa7d\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uaaeb-\\uaaef\\uaaf5\\uaaf6\\uabe3-\\uabea\\uabec\\uabed\\uabf0-\\uabf9\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe2f\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f";
|
||||||
}
|
|
||||||
|
|
||||||
private static Pattern nonASCIIidentifier() {
|
private static Pattern nonASCIIidentifierStartPattern;
|
||||||
if (nonASCIIidentifierPattern == null)
|
private static Pattern nonASCIIidentifierPattern;
|
||||||
nonASCIIidentifierPattern = Pattern.compile("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
||||||
return nonASCIIidentifierPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are a run-length and offset encoded representation of the
|
private static Pattern nonASCIIidentifierStart() {
|
||||||
// >0xffff code points that are a valid part of identifiers. The
|
if (nonASCIIidentifierStartPattern == null)
|
||||||
// offset starts at 0x10000, and each pair of numbers represents an
|
nonASCIIidentifierStartPattern = Pattern.compile("[" + nonASCIIidentifierStartChars + "]");
|
||||||
// offset to the next range, and then a size of the range. They were
|
return nonASCIIidentifierStartPattern;
|
||||||
// generated by bin/generate-identifier-regex.js
|
}
|
||||||
private static final int[] astralIdentifierStartCodes = {0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541};
|
|
||||||
private static final int[] astralIdentifierCodes = {509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239};
|
|
||||||
|
|
||||||
// This has a complexity linear to the value of the code. The
|
private static Pattern nonASCIIidentifier() {
|
||||||
// assumption is that looking up astral identifier characters is
|
if (nonASCIIidentifierPattern == null)
|
||||||
// rare.
|
nonASCIIidentifierPattern =
|
||||||
private static boolean isInAstralSet(int code, int[] set) {
|
Pattern.compile("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
||||||
int pos = 0x10000;
|
return nonASCIIidentifierPattern;
|
||||||
for (int i = 0; i < set.length; i += 2) {
|
}
|
||||||
pos += set[i];
|
|
||||||
if (pos > code)
|
|
||||||
return false;
|
|
||||||
pos += set[i + 1];
|
|
||||||
if (pos >= code)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test whether a given character code starts an identifier.
|
// These are a run-length and offset encoded representation of the
|
||||||
|
// >0xffff code points that are a valid part of identifiers. The
|
||||||
|
// offset starts at 0x10000, and each pair of numbers represents an
|
||||||
|
// offset to the next range, and then a size of the range. They were
|
||||||
|
// generated by bin/generate-identifier-regex.js
|
||||||
|
private static final int[] astralIdentifierStartCodes = {
|
||||||
|
0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37,
|
||||||
|
11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153,
|
||||||
|
5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1,
|
||||||
|
65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72,
|
||||||
|
56, 50, 14, 50, 785, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36,
|
||||||
|
17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0,
|
||||||
|
19, 0, 13, 4, 159, 52, 19, 3, 54, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 86,
|
||||||
|
25, 391, 63, 32, 0, 449, 56, 264, 8, 2, 36, 18, 0, 50, 29, 881, 921, 103, 110, 18, 195, 2749,
|
||||||
|
1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67,
|
||||||
|
12, 65, 0, 32, 6124, 20, 754, 9486, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3,
|
||||||
|
0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2,
|
||||||
|
339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 60,
|
||||||
|
67, 1213, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2,
|
||||||
|
1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6,
|
||||||
|
2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 3, 5761, 10591, 541
|
||||||
|
};
|
||||||
|
private static final int[] astralIdentifierCodes = {
|
||||||
|
509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32,
|
||||||
|
9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 10, 2, 4, 9, 83, 11, 7, 0,
|
||||||
|
161, 11, 6, 9, 7, 3, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 87, 19,
|
||||||
|
13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 423, 9, 838, 7, 2, 7, 17,
|
||||||
|
9, 57, 21, 2, 13, 19882, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9,
|
||||||
|
7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3,
|
||||||
|
6, 2, 1, 2, 4, 2214, 6, 110, 6, 6, 9, 792487, 239
|
||||||
|
};
|
||||||
|
|
||||||
public static boolean isIdentifierStart(int code, boolean astral) {
|
// This has a complexity linear to the value of the code. The
|
||||||
if (code < 65) return code == 36;
|
// assumption is that looking up astral identifier characters is
|
||||||
if (code < 91) return true;
|
// rare.
|
||||||
if (code < 97) return code == 95;
|
private static boolean isInAstralSet(int code, int[] set) {
|
||||||
if (code < 123) return true;
|
int pos = 0x10000;
|
||||||
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart().matcher(str(code)).matches();
|
for (int i = 0; i < set.length; i += 2) {
|
||||||
if (!astral) return false;
|
pos += set[i];
|
||||||
return isInAstralSet(code, astralIdentifierStartCodes);
|
if (pos > code) return false;
|
||||||
}
|
pos += set[i + 1];
|
||||||
|
if (pos >= code) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isIdentifierChar(int code, boolean astral) {
|
// Test whether a given character code starts an identifier.
|
||||||
if (code < 48) return code == 36;
|
|
||||||
if (code < 58) return true;
|
|
||||||
if (code < 65) return false;
|
|
||||||
if (code < 91) return true;
|
|
||||||
if (code < 97) return code == 95;
|
|
||||||
if (code < 123) return true;
|
|
||||||
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier().matcher(str(code)).matches();
|
|
||||||
if (!astral) return false;
|
|
||||||
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String str(int i) {
|
public static boolean isIdentifierStart(int code, boolean astral) {
|
||||||
return new String(Character.toChars(i));
|
if (code < 65) return code == 36;
|
||||||
}
|
if (code < 91) return true;
|
||||||
|
if (code < 97) return code == 95;
|
||||||
|
if (code < 123) return true;
|
||||||
|
if (code <= 0xffff)
|
||||||
|
return code >= 0xaa && nonASCIIidentifierStart().matcher(str(code)).matches();
|
||||||
|
if (!astral) return false;
|
||||||
|
return isInAstralSet(code, astralIdentifierStartCodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isIdentifierChar(int code, boolean astral) {
|
||||||
|
if (code < 48) return code == 36;
|
||||||
|
if (code < 58) return true;
|
||||||
|
if (code < 65) return false;
|
||||||
|
if (code < 91) return true;
|
||||||
|
if (code < 97) return code == 95;
|
||||||
|
if (code < 123) return true;
|
||||||
|
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier().matcher(str(code)).matches();
|
||||||
|
if (!astral) return false;
|
||||||
|
return isInAstralSet(code, astralIdentifierStartCodes)
|
||||||
|
|| isInAstralSet(code, astralIdentifierCodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String str(int i) {
|
||||||
|
return new String(Character.toChars(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
package com.semmle.jcorn;
|
package com.semmle.jcorn;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
|
|
||||||
import com.semmle.js.ast.Position;
|
import com.semmle.js.ast.Position;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
/// locutil.js
|
/// locutil.js
|
||||||
public class Locutil {
|
public class Locutil {
|
||||||
/**
|
/**
|
||||||
* The `getLineInfo` function is mostly useful when the
|
* The `getLineInfo` function is mostly useful when the `locations` option is off (for performance
|
||||||
* `locations` option is off (for performance reasons) and you
|
* reasons) and you want to find the line/column position for a given character offset. `input`
|
||||||
* want to find the line/column position for a given character
|
* should be the code string that the offset refers into.
|
||||||
* offset. `input` should be the code string that the offset refers
|
*/
|
||||||
* into.
|
public static Position getLineInfo(String input, int offset) {
|
||||||
*/
|
Matcher lineBreakG = Whitespace.lineBreakG.matcher(input);
|
||||||
public static Position getLineInfo(String input, int offset) {
|
for (int line = 1, cur = 0; ; ) {
|
||||||
Matcher lineBreakG = Whitespace.lineBreakG.matcher(input);
|
if (lineBreakG.find(cur) && lineBreakG.start() < offset) {
|
||||||
for (int line = 1, cur = 0;;) {
|
++line;
|
||||||
if (lineBreakG.find(cur) && lineBreakG.start() < offset) {
|
cur = lineBreakG.end();
|
||||||
++line;
|
} else {
|
||||||
cur = lineBreakG.end();
|
return new Position(line, offset - cur, offset);
|
||||||
} else {
|
}
|
||||||
return new Position(line, offset - cur, offset);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,248 +1,259 @@
|
|||||||
package com.semmle.jcorn;
|
package com.semmle.jcorn;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.semmle.jcorn.Identifiers.Dialect;
|
import com.semmle.jcorn.Identifiers.Dialect;
|
||||||
import com.semmle.js.ast.Comment;
|
import com.semmle.js.ast.Comment;
|
||||||
import com.semmle.js.ast.Position;
|
import com.semmle.js.ast.Position;
|
||||||
import com.semmle.js.ast.Program;
|
import com.semmle.js.ast.Program;
|
||||||
import com.semmle.js.ast.SourceLocation;
|
import com.semmle.js.ast.SourceLocation;
|
||||||
import com.semmle.js.ast.Token;
|
import com.semmle.js.ast.Token;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/// options.js
|
/// options.js
|
||||||
public class Options {
|
public class Options {
|
||||||
public enum AllowReserved {
|
public enum AllowReserved {
|
||||||
YES(true), NO(false), NEVER(false);
|
YES(true),
|
||||||
|
NO(false),
|
||||||
|
NEVER(false);
|
||||||
|
|
||||||
private final boolean isTrue;
|
private final boolean isTrue;
|
||||||
|
|
||||||
private AllowReserved(boolean isTrue) {
|
private AllowReserved(boolean isTrue) {
|
||||||
this.isTrue = isTrue;
|
this.isTrue = isTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTrue() {
|
public boolean isTrue() {
|
||||||
return isTrue;
|
return isTrue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnCommentCallback {
|
public interface OnCommentCallback {
|
||||||
public void call(boolean block, String input, String text, int start, int end, Position startLoc, Position endLoc);
|
public void call(
|
||||||
}
|
boolean block,
|
||||||
|
String input,
|
||||||
|
String text,
|
||||||
|
int start,
|
||||||
|
int end,
|
||||||
|
Position startLoc,
|
||||||
|
Position endLoc);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere;
|
private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere;
|
||||||
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x;
|
private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x;
|
||||||
private int ecmaVersion;
|
private int ecmaVersion;
|
||||||
private AllowReserved allowReserved;
|
private AllowReserved allowReserved;
|
||||||
private String sourceType;
|
private String sourceType;
|
||||||
private BiFunction<Integer, Position, Void> onInsertedSemicolon, onTrailingComma;
|
private BiFunction<Integer, Position, Void> onInsertedSemicolon, onTrailingComma;
|
||||||
private Function<Token, Void> onToken;
|
private Function<Token, Void> onToken;
|
||||||
private OnCommentCallback onComment;
|
private OnCommentCallback onComment;
|
||||||
private Program program;
|
private Program program;
|
||||||
private Function<SyntaxError, ?> onRecoverableError;
|
private Function<SyntaxError, ?> onRecoverableError;
|
||||||
|
|
||||||
public Options() {
|
public Options() {
|
||||||
this.ecmaVersion = 7;
|
this.ecmaVersion = 7;
|
||||||
this.sourceType = "script";
|
this.sourceType = "script";
|
||||||
this.onInsertedSemicolon = null;
|
this.onInsertedSemicolon = null;
|
||||||
this.onTrailingComma = null;
|
this.onTrailingComma = null;
|
||||||
this.allowReserved = AllowReserved.YES;
|
this.allowReserved = AllowReserved.YES;
|
||||||
this.allowReturnOutsideFunction = false;
|
this.allowReturnOutsideFunction = false;
|
||||||
this.allowImportExportEverywhere = false;
|
this.allowImportExportEverywhere = false;
|
||||||
this.allowHashBang = false;
|
this.allowHashBang = false;
|
||||||
this.onToken = null;
|
this.onToken = null;
|
||||||
this.onComment = null;
|
this.onComment = null;
|
||||||
this.program = null;
|
this.program = null;
|
||||||
this.preserveParens = false;
|
this.preserveParens = false;
|
||||||
this.mozExtensions = false;
|
this.mozExtensions = false;
|
||||||
this.jscript = false;
|
this.jscript = false;
|
||||||
this.esnext = false;
|
this.esnext = false;
|
||||||
this.v8Extensions = false;
|
this.v8Extensions = false;
|
||||||
this.e4x = false;
|
this.e4x = false;
|
||||||
this.onRecoverableError = null;
|
this.onRecoverableError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options(Options that) {
|
public Options(Options that) {
|
||||||
this.allowHashBang = that.allowHashBang;
|
this.allowHashBang = that.allowHashBang;
|
||||||
this.allowReturnOutsideFunction = that.allowReturnOutsideFunction;
|
this.allowReturnOutsideFunction = that.allowReturnOutsideFunction;
|
||||||
this.allowImportExportEverywhere = that.allowImportExportEverywhere;
|
this.allowImportExportEverywhere = that.allowImportExportEverywhere;
|
||||||
this.preserveParens = that.preserveParens;
|
this.preserveParens = that.preserveParens;
|
||||||
this.mozExtensions = that.mozExtensions;
|
this.mozExtensions = that.mozExtensions;
|
||||||
this.jscript = that.jscript;
|
this.jscript = that.jscript;
|
||||||
this.esnext = that.esnext;
|
this.esnext = that.esnext;
|
||||||
this.v8Extensions = that.v8Extensions;
|
this.v8Extensions = that.v8Extensions;
|
||||||
this.e4x = that.e4x;
|
this.e4x = that.e4x;
|
||||||
this.ecmaVersion = that.ecmaVersion;
|
this.ecmaVersion = that.ecmaVersion;
|
||||||
this.allowReserved = that.allowReserved;
|
this.allowReserved = that.allowReserved;
|
||||||
this.sourceType = that.sourceType;
|
this.sourceType = that.sourceType;
|
||||||
this.onInsertedSemicolon = that.onInsertedSemicolon;
|
this.onInsertedSemicolon = that.onInsertedSemicolon;
|
||||||
this.onTrailingComma = that.onTrailingComma;
|
this.onTrailingComma = that.onTrailingComma;
|
||||||
this.onToken = that.onToken;
|
this.onToken = that.onToken;
|
||||||
this.onComment = that.onComment;
|
this.onComment = that.onComment;
|
||||||
this.program = that.program;
|
this.program = that.program;
|
||||||
this.onRecoverableError = that.onRecoverableError;
|
this.onRecoverableError = that.onRecoverableError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allowHashBang() {
|
public boolean allowHashBang() {
|
||||||
return allowHashBang;
|
return allowHashBang;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allowReturnOutsideFunction() {
|
public boolean allowReturnOutsideFunction() {
|
||||||
return allowReturnOutsideFunction;
|
return allowReturnOutsideFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allowImportExportEverywhere() {
|
public boolean allowImportExportEverywhere() {
|
||||||
return allowImportExportEverywhere;
|
return allowImportExportEverywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean preserveParens() {
|
public boolean preserveParens() {
|
||||||
return preserveParens;
|
return preserveParens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mozExtensions() {
|
public boolean mozExtensions() {
|
||||||
return mozExtensions;
|
return mozExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean jscript() {
|
public boolean jscript() {
|
||||||
return jscript;
|
return jscript;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean esnext() {
|
public boolean esnext() {
|
||||||
return esnext;
|
return esnext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean v8Extensions() {
|
public boolean v8Extensions() {
|
||||||
return v8Extensions;
|
return v8Extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean e4x() {
|
public boolean e4x() {
|
||||||
return e4x;
|
return e4x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifiers.Dialect getDialect() {
|
public Identifiers.Dialect getDialect() {
|
||||||
switch (ecmaVersion) {
|
switch (ecmaVersion) {
|
||||||
case 3:
|
case 3:
|
||||||
return Dialect.ECMA_3;
|
return Dialect.ECMA_3;
|
||||||
case 5:
|
case 5:
|
||||||
return Dialect.ECMA_5;
|
return Dialect.ECMA_5;
|
||||||
case 6:
|
case 6:
|
||||||
return Dialect.ECMA_6;
|
return Dialect.ECMA_6;
|
||||||
case 8:
|
case 8:
|
||||||
return Dialect.ECMA_8;
|
return Dialect.ECMA_8;
|
||||||
default:
|
default:
|
||||||
return Dialect.ECMA_7;
|
return Dialect.ECMA_7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ecmaVersion() {
|
public int ecmaVersion() {
|
||||||
return ecmaVersion;
|
return ecmaVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options ecmaVersion(int ecmaVersion) {
|
public Options ecmaVersion(int ecmaVersion) {
|
||||||
if (ecmaVersion >= 2015)
|
if (ecmaVersion >= 2015) ecmaVersion -= 2009;
|
||||||
ecmaVersion -= 2009;
|
|
||||||
|
|
||||||
this.ecmaVersion = ecmaVersion;
|
this.ecmaVersion = ecmaVersion;
|
||||||
if (ecmaVersion >= 5)
|
if (ecmaVersion >= 5) this.allowReserved = AllowReserved.NO;
|
||||||
this.allowReserved = AllowReserved.NO;
|
return this;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public AllowReserved allowReserved() {
|
public AllowReserved allowReserved() {
|
||||||
return allowReserved;
|
return allowReserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options onComment(List<Comment> comments) {
|
public Options onComment(List<Comment> comments) {
|
||||||
this.onComment = (block, input, text, start, end, startLoc, endLoc) -> {
|
this.onComment =
|
||||||
String src = input.substring(start, end);
|
(block, input, text, start, end, startLoc, endLoc) -> {
|
||||||
comments.add(new Comment(new SourceLocation(src, startLoc, endLoc), text));
|
String src = input.substring(start, end);
|
||||||
};
|
comments.add(new Comment(new SourceLocation(src, startLoc, endLoc), text));
|
||||||
return this;
|
};
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String sourceType() {
|
public String sourceType() {
|
||||||
return sourceType;
|
return sourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options sourceType(String sourceType) {
|
public Options sourceType(String sourceType) {
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options mozExtensions(boolean mozExtensions) {
|
public Options mozExtensions(boolean mozExtensions) {
|
||||||
this.mozExtensions = mozExtensions;
|
this.mozExtensions = mozExtensions;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options jscript(boolean jscript) {
|
public Options jscript(boolean jscript) {
|
||||||
this.jscript = jscript;
|
this.jscript = jscript;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options esnext(boolean esnext) {
|
public Options esnext(boolean esnext) {
|
||||||
this.esnext = esnext;
|
this.esnext = esnext;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void v8Extensions(boolean v8Extensions) {
|
public void v8Extensions(boolean v8Extensions) {
|
||||||
this.v8Extensions = v8Extensions;
|
this.v8Extensions = v8Extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void e4x(boolean e4x) {
|
public void e4x(boolean e4x) {
|
||||||
this.e4x = e4x;
|
this.e4x = e4x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options preserveParens(boolean preserveParens) {
|
public Options preserveParens(boolean preserveParens) {
|
||||||
this.preserveParens = preserveParens;
|
this.preserveParens = preserveParens;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options allowReturnOutsideFunction(boolean allowReturnOutsideFunction) {
|
public Options allowReturnOutsideFunction(boolean allowReturnOutsideFunction) {
|
||||||
this.allowReturnOutsideFunction = allowReturnOutsideFunction;
|
this.allowReturnOutsideFunction = allowReturnOutsideFunction;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options allowImportExportEverywhere(boolean allowImportExportEverywhere) {
|
public Options allowImportExportEverywhere(boolean allowImportExportEverywhere) {
|
||||||
this.allowImportExportEverywhere = allowImportExportEverywhere;
|
this.allowImportExportEverywhere = allowImportExportEverywhere;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BiFunction<Integer, Position, Void> onInsertedSemicolon() {
|
public BiFunction<Integer, Position, Void> onInsertedSemicolon() {
|
||||||
return onInsertedSemicolon;
|
return onInsertedSemicolon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BiFunction<Integer, Position, Void> onTrailingComma() {
|
public BiFunction<Integer, Position, Void> onTrailingComma() {
|
||||||
return onTrailingComma;
|
return onTrailingComma;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Function<Token, Void> onToken() {
|
public Function<Token, Void> onToken() {
|
||||||
return onToken;
|
return onToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options onToken(List<Token> tokens) {
|
public Options onToken(List<Token> tokens) {
|
||||||
return onToken((tk) -> { tokens.add(tk); return null; });
|
return onToken(
|
||||||
}
|
(tk) -> {
|
||||||
|
tokens.add(tk);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public Options onToken(Function<Token, Void> tmp) {
|
public Options onToken(Function<Token, Void> tmp) {
|
||||||
this.onToken = tmp;
|
this.onToken = tmp;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnCommentCallback onComment() {
|
public OnCommentCallback onComment() {
|
||||||
return onComment;
|
return onComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Program program() {
|
public Program program() {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Options onRecoverableError(Function<SyntaxError, ?> onRecoverableError) {
|
public Options onRecoverableError(Function<SyntaxError, ?> onRecoverableError) {
|
||||||
this.onRecoverableError = onRecoverableError;
|
this.onRecoverableError = onRecoverableError;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Function<SyntaxError, ?> onRecoverableError() {
|
public Function<SyntaxError, ?> onRecoverableError() {
|
||||||
return onRecoverableError;
|
return onRecoverableError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,16 +3,16 @@ package com.semmle.jcorn;
|
|||||||
import com.semmle.js.ast.Position;
|
import com.semmle.js.ast.Position;
|
||||||
|
|
||||||
public class SyntaxError extends RuntimeException {
|
public class SyntaxError extends RuntimeException {
|
||||||
private static final long serialVersionUID = -4883173648492364902L;
|
private static final long serialVersionUID = -4883173648492364902L;
|
||||||
|
|
||||||
private final Position position;
|
private final Position position;
|
||||||
|
|
||||||
public SyntaxError(String msg, Position loc, int raisedAt) {
|
public SyntaxError(String msg, Position loc, int raisedAt) {
|
||||||
super(msg);
|
super(msg);
|
||||||
this.position = loc;
|
this.position = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Position getPosition() {
|
public Position getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.semmle.jcorn;
|
package com.semmle.jcorn;
|
||||||
|
|
||||||
|
import com.semmle.jcorn.Parser.TokContext;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.semmle.jcorn.Parser.TokContext;
|
|
||||||
|
|
||||||
/// tokentype.js
|
/// tokentype.js
|
||||||
|
|
||||||
// ## Token types
|
// ## Token types
|
||||||
@@ -31,251 +30,262 @@ import com.semmle.jcorn.Parser.TokContext;
|
|||||||
// continue jumps to that label.
|
// continue jumps to that label.
|
||||||
|
|
||||||
public class TokenType {
|
public class TokenType {
|
||||||
// Map keyword names to token types.
|
// Map keyword names to token types.
|
||||||
public static final Map<String, TokenType> keywords = new LinkedHashMap<>();
|
public static final Map<String, TokenType> keywords = new LinkedHashMap<>();
|
||||||
|
|
||||||
public static final TokenType
|
public static final TokenType num = new TokenType(new Properties("num").startsExpr()),
|
||||||
num = new TokenType(new Properties("num").startsExpr()),
|
bigint = new TokenType(new Properties("bigint").startsExpr()),
|
||||||
bigint = new TokenType(new Properties("bigint").startsExpr()),
|
regexp = new TokenType(new Properties("regexp").startsExpr()),
|
||||||
regexp = new TokenType(new Properties("regexp").startsExpr()),
|
string = new TokenType(new Properties("string").startsExpr()),
|
||||||
string = new TokenType(new Properties("string").startsExpr()),
|
name = new TokenType(new Properties("name").startsExpr()),
|
||||||
name = new TokenType(new Properties("name").startsExpr()),
|
eof = new TokenType(new Properties("eof")),
|
||||||
eof = new TokenType(new Properties("eof")),
|
|
||||||
|
|
||||||
// Punctuation token types.
|
// Punctuation token types.
|
||||||
bracketL = new TokenType(new Properties("[").beforeExpr().startsExpr()),
|
bracketL = new TokenType(new Properties("[").beforeExpr().startsExpr()),
|
||||||
bracketR = new TokenType(new Properties("]")),
|
bracketR = new TokenType(new Properties("]")),
|
||||||
braceL = new TokenType(new Properties("{").beforeExpr().startsExpr()) {
|
braceL =
|
||||||
@Override
|
new TokenType(new Properties("{").beforeExpr().startsExpr()) {
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
@Override
|
||||||
parser.context.push(parser.braceIsBlock(prevType) ? TokContext.b_stat : TokContext.b_expr);
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parser.exprAllowed = true;
|
parser.context.push(
|
||||||
}
|
parser.braceIsBlock(prevType) ? TokContext.b_stat : TokContext.b_expr);
|
||||||
},
|
parser.exprAllowed = true;
|
||||||
braceR = new TokenType(new Properties("}")) {
|
}
|
||||||
@Override
|
},
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
braceR =
|
||||||
updateParenBraceRContext(parser);
|
new TokenType(new Properties("}")) {
|
||||||
}
|
@Override
|
||||||
},
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parenL = new TokenType(new Properties("(").beforeExpr().startsExpr()) {
|
updateParenBraceRContext(parser);
|
||||||
@Override
|
}
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
},
|
||||||
boolean statementParens = prevType == TokenType._if || prevType == TokenType._for || prevType == TokenType._with || prevType == TokenType._while;
|
parenL =
|
||||||
parser.context.push(statementParens ? TokContext.p_stat : TokContext.p_expr);
|
new TokenType(new Properties("(").beforeExpr().startsExpr()) {
|
||||||
parser.exprAllowed = true;
|
@Override
|
||||||
}
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
},
|
boolean statementParens =
|
||||||
parenR = new TokenType(new Properties(")")) {
|
prevType == TokenType._if
|
||||||
@Override
|
|| prevType == TokenType._for
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
|| prevType == TokenType._with
|
||||||
updateParenBraceRContext(parser);
|
|| prevType == TokenType._while;
|
||||||
}
|
parser.context.push(statementParens ? TokContext.p_stat : TokContext.p_expr);
|
||||||
},
|
parser.exprAllowed = true;
|
||||||
comma = new TokenType(new Properties(",").beforeExpr()),
|
}
|
||||||
semi = new TokenType(new Properties(";").beforeExpr()),
|
},
|
||||||
colon = new TokenType(new Properties(":").beforeExpr()),
|
parenR =
|
||||||
dot = new TokenType(new Properties(".")),
|
new TokenType(new Properties(")")) {
|
||||||
questiondot = new TokenType(new Properties("?.")),
|
@Override
|
||||||
question = new TokenType(new Properties("?").beforeExpr()),
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
arrow = new TokenType(new Properties("=>").beforeExpr()),
|
updateParenBraceRContext(parser);
|
||||||
template = new TokenType(new Properties("template")),
|
}
|
||||||
invalidTemplate = new TokenType(new Properties("invalidTemplate")),
|
},
|
||||||
ellipsis = new TokenType(new Properties("...").beforeExpr()),
|
comma = new TokenType(new Properties(",").beforeExpr()),
|
||||||
backQuote = new TokenType(new Properties("`").startsExpr()) {
|
semi = new TokenType(new Properties(";").beforeExpr()),
|
||||||
@Override
|
colon = new TokenType(new Properties(":").beforeExpr()),
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
dot = new TokenType(new Properties(".")),
|
||||||
if (parser.curContext() == TokContext.q_tmpl)
|
questiondot = new TokenType(new Properties("?.")),
|
||||||
parser.context.pop();
|
question = new TokenType(new Properties("?").beforeExpr()),
|
||||||
else
|
arrow = new TokenType(new Properties("=>").beforeExpr()),
|
||||||
parser.context.push(TokContext.q_tmpl);
|
template = new TokenType(new Properties("template")),
|
||||||
parser.exprAllowed = false;
|
invalidTemplate = new TokenType(new Properties("invalidTemplate")),
|
||||||
}
|
ellipsis = new TokenType(new Properties("...").beforeExpr()),
|
||||||
},
|
backQuote =
|
||||||
dollarBraceL = new TokenType(new Properties("${").beforeExpr().startsExpr()) {
|
new TokenType(new Properties("`").startsExpr()) {
|
||||||
@Override
|
@Override
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parser.context.push(TokContext.b_tmpl);
|
if (parser.curContext() == TokContext.q_tmpl) parser.context.pop();
|
||||||
parser.exprAllowed = true;
|
else parser.context.push(TokContext.q_tmpl);
|
||||||
}
|
parser.exprAllowed = false;
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
dollarBraceL =
|
||||||
|
new TokenType(new Properties("${").beforeExpr().startsExpr()) {
|
||||||
|
@Override
|
||||||
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
|
parser.context.push(TokContext.b_tmpl);
|
||||||
|
parser.exprAllowed = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Operators. These carry several kinds of properties to help the
|
// Operators. These carry several kinds of properties to help the
|
||||||
// parser use them properly (the presence of these properties is
|
// parser use them properly (the presence of these properties is
|
||||||
// what categorizes them as operators).
|
// what categorizes them as operators).
|
||||||
//
|
//
|
||||||
// `binop`, when present, specifies that this operator is a binary
|
// `binop`, when present, specifies that this operator is a binary
|
||||||
// operator, and will refer to its precedence.
|
// operator, and will refer to its precedence.
|
||||||
//
|
//
|
||||||
// `prefix` and `postfix` mark the operator as a prefix or postfix
|
// `prefix` and `postfix` mark the operator as a prefix or postfix
|
||||||
// unary operator.
|
// unary operator.
|
||||||
//
|
//
|
||||||
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
|
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
|
||||||
// binary operators with a very low precedence, that should result
|
// binary operators with a very low precedence, that should result
|
||||||
// in AssignmentExpression nodes.
|
// in AssignmentExpression nodes.
|
||||||
|
|
||||||
eq = new TokenType(new Properties("=").beforeExpr().isAssign()),
|
eq = new TokenType(new Properties("=").beforeExpr().isAssign()),
|
||||||
assign = new TokenType(new Properties("_=").beforeExpr().isAssign()),
|
assign = new TokenType(new Properties("_=").beforeExpr().isAssign()),
|
||||||
incDec = new TokenType(new Properties("++/--").prefix().postfix().startsExpr()) {
|
incDec =
|
||||||
@Override
|
new TokenType(new Properties("++/--").prefix().postfix().startsExpr()) {
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
@Override
|
||||||
// exprAllowed stays unchanged
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
}
|
// exprAllowed stays unchanged
|
||||||
},
|
}
|
||||||
prefix = new TokenType(new Properties("prefix").beforeExpr().prefix().startsExpr()),
|
},
|
||||||
questionquestion = new TokenType(binop("??", 1)),
|
prefix = new TokenType(new Properties("prefix").beforeExpr().prefix().startsExpr()),
|
||||||
logicalOR = new TokenType(binop("||", 1)),
|
questionquestion = new TokenType(binop("??", 1)),
|
||||||
logicalAND = new TokenType(binop("&&", 2)),
|
logicalOR = new TokenType(binop("||", 1)),
|
||||||
bitwiseOR = new TokenType(binop("|", 3)),
|
logicalAND = new TokenType(binop("&&", 2)),
|
||||||
bitwiseXOR = new TokenType(binop("^", 4)),
|
bitwiseOR = new TokenType(binop("|", 3)),
|
||||||
bitwiseAND = new TokenType(binop("&", 5)),
|
bitwiseXOR = new TokenType(binop("^", 4)),
|
||||||
equality = new TokenType(binop("==/!=", 6)),
|
bitwiseAND = new TokenType(binop("&", 5)),
|
||||||
relational = new TokenType(binop("</>", 7)),
|
equality = new TokenType(binop("==/!=", 6)),
|
||||||
bitShift = new TokenType(binop("<</>>", 8)),
|
relational = new TokenType(binop("</>", 7)),
|
||||||
plusMin = new TokenType(new Properties("+/-").beforeExpr().binop(9).prefix().startsExpr()),
|
bitShift = new TokenType(binop("<</>>", 8)),
|
||||||
modulo= new TokenType(binop("%", 10)),
|
plusMin = new TokenType(new Properties("+/-").beforeExpr().binop(9).prefix().startsExpr()),
|
||||||
star= new TokenType(binop("*", 10)),
|
modulo = new TokenType(binop("%", 10)),
|
||||||
slash= new TokenType(binop("/", 10)),
|
star = new TokenType(binop("*", 10)),
|
||||||
starstar = new TokenType(new Properties("**").beforeExpr()),
|
slash = new TokenType(binop("/", 10)),
|
||||||
_break = new TokenType(kw("break")),
|
starstar = new TokenType(new Properties("**").beforeExpr()),
|
||||||
_case = new TokenType(kw("case").beforeExpr()),
|
_break = new TokenType(kw("break")),
|
||||||
_catch = new TokenType(kw("catch")),
|
_case = new TokenType(kw("case").beforeExpr()),
|
||||||
_continue = new TokenType(kw("continue")),
|
_catch = new TokenType(kw("catch")),
|
||||||
_debugger = new TokenType(kw("debugger")),
|
_continue = new TokenType(kw("continue")),
|
||||||
_default = new TokenType(kw("default").beforeExpr()),
|
_debugger = new TokenType(kw("debugger")),
|
||||||
_do = new TokenType(kw("do").isLoop().beforeExpr()),
|
_default = new TokenType(kw("default").beforeExpr()),
|
||||||
_else = new TokenType(kw("else").beforeExpr()),
|
_do = new TokenType(kw("do").isLoop().beforeExpr()),
|
||||||
_finally = new TokenType(kw("finally")),
|
_else = new TokenType(kw("else").beforeExpr()),
|
||||||
_for = new TokenType(kw("for").isLoop()),
|
_finally = new TokenType(kw("finally")),
|
||||||
_function = new TokenType(kw("function").startsExpr()) {
|
_for = new TokenType(kw("for").isLoop()),
|
||||||
@Override
|
_function =
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
new TokenType(kw("function").startsExpr()) {
|
||||||
if (prevType.beforeExpr && prevType != TokenType.semi && prevType != TokenType._else &&
|
@Override
|
||||||
!((prevType == TokenType.colon || prevType == TokenType.braceL) && parser.curContext() == TokContext.b_stat))
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parser.context.push(TokContext.f_expr);
|
if (prevType.beforeExpr
|
||||||
parser.exprAllowed = false;
|
&& prevType != TokenType.semi
|
||||||
}
|
&& prevType != TokenType._else
|
||||||
},
|
&& !((prevType == TokenType.colon || prevType == TokenType.braceL)
|
||||||
_if = new TokenType(kw("if")),
|
&& parser.curContext() == TokContext.b_stat))
|
||||||
_return = new TokenType(kw("return").beforeExpr()),
|
parser.context.push(TokContext.f_expr);
|
||||||
_switch = new TokenType(kw("switch")),
|
parser.exprAllowed = false;
|
||||||
_throw = new TokenType(kw("throw").beforeExpr()),
|
}
|
||||||
_try = new TokenType(kw("try")),
|
},
|
||||||
_var = new TokenType(kw("var")),
|
_if = new TokenType(kw("if")),
|
||||||
_const = new TokenType(kw("const")),
|
_return = new TokenType(kw("return").beforeExpr()),
|
||||||
_while = new TokenType(kw("while").isLoop()),
|
_switch = new TokenType(kw("switch")),
|
||||||
_with = new TokenType(kw("with")),
|
_throw = new TokenType(kw("throw").beforeExpr()),
|
||||||
_new = new TokenType(kw("new").beforeExpr().startsExpr()),
|
_try = new TokenType(kw("try")),
|
||||||
_this = new TokenType(kw("this").startsExpr()),
|
_var = new TokenType(kw("var")),
|
||||||
_super = new TokenType(kw("super").startsExpr()),
|
_const = new TokenType(kw("const")),
|
||||||
_class = new TokenType(kw("class")),
|
_while = new TokenType(kw("while").isLoop()),
|
||||||
_extends = new TokenType(kw("extends").beforeExpr()),
|
_with = new TokenType(kw("with")),
|
||||||
_export = new TokenType(kw("export")),
|
_new = new TokenType(kw("new").beforeExpr().startsExpr()),
|
||||||
_import = new TokenType(kw("import")),
|
_this = new TokenType(kw("this").startsExpr()),
|
||||||
_null = new TokenType(kw("null").startsExpr()),
|
_super = new TokenType(kw("super").startsExpr()),
|
||||||
_true = new TokenType(kw("true").startsExpr()),
|
_class = new TokenType(kw("class")),
|
||||||
_false = new TokenType(kw("false").startsExpr()),
|
_extends = new TokenType(kw("extends").beforeExpr()),
|
||||||
_in = new TokenType(kw("in").beforeExpr().binop(7)),
|
_export = new TokenType(kw("export")),
|
||||||
_instanceof = new TokenType(kw("instanceof").beforeExpr().binop(7)),
|
_import = new TokenType(kw("import")),
|
||||||
_typeof = new TokenType(kw("typeof").beforeExpr().prefix().startsExpr()),
|
_null = new TokenType(kw("null").startsExpr()),
|
||||||
_void = new TokenType(kw("void").beforeExpr().prefix().startsExpr()),
|
_true = new TokenType(kw("true").startsExpr()),
|
||||||
_delete = new TokenType(kw("delete").beforeExpr().prefix().startsExpr());
|
_false = new TokenType(kw("false").startsExpr()),
|
||||||
|
_in = new TokenType(kw("in").beforeExpr().binop(7)),
|
||||||
|
_instanceof = new TokenType(kw("instanceof").beforeExpr().binop(7)),
|
||||||
|
_typeof = new TokenType(kw("typeof").beforeExpr().prefix().startsExpr()),
|
||||||
|
_void = new TokenType(kw("void").beforeExpr().prefix().startsExpr()),
|
||||||
|
_delete = new TokenType(kw("delete").beforeExpr().prefix().startsExpr());
|
||||||
|
public final String label, keyword;
|
||||||
|
public final boolean beforeExpr, startsExpr, isLoop, isAssign, isPrefix, isPostfix;
|
||||||
|
public final int binop;
|
||||||
|
|
||||||
public final String label, keyword;
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
public final boolean beforeExpr, startsExpr, isLoop, isAssign, isPrefix, isPostfix;
|
parser.exprAllowed = this.beforeExpr;
|
||||||
public final int binop;
|
}
|
||||||
|
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
// Token-specific context update code
|
||||||
parser.exprAllowed = this.beforeExpr;
|
protected void updateParenBraceRContext(Parser parser) {
|
||||||
}
|
if (parser.context.size() == 1) {
|
||||||
|
parser.exprAllowed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TokContext out = parser.context.pop();
|
||||||
|
if (out == TokContext.b_stat && parser.curContext() == TokContext.f_expr) {
|
||||||
|
parser.context.pop();
|
||||||
|
parser.exprAllowed = false;
|
||||||
|
} else if (out == TokContext.b_tmpl) {
|
||||||
|
parser.exprAllowed = true;
|
||||||
|
} else {
|
||||||
|
parser.exprAllowed = !out.isExpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Token-specific context update code
|
public TokenType(Properties prop) {
|
||||||
protected void updateParenBraceRContext(Parser parser) {
|
this.label = prop.label;
|
||||||
if (parser.context.size() == 1) {
|
this.keyword = prop.keyword;
|
||||||
parser.exprAllowed = true;
|
this.beforeExpr = prop.beforeExpr;
|
||||||
return;
|
this.startsExpr = prop.startsExpr;
|
||||||
}
|
this.isLoop = prop.isLoop;
|
||||||
TokContext out = parser.context.pop();
|
this.isAssign = prop.isAssign;
|
||||||
if (out == TokContext.b_stat && parser.curContext() == TokContext.f_expr) {
|
this.isPrefix = prop.prefix;
|
||||||
parser.context.pop();
|
this.isPostfix = prop.postfix;
|
||||||
parser.exprAllowed = false;
|
this.binop = prop.binop;
|
||||||
} else if (out == TokContext.b_tmpl) {
|
if (this.keyword != null) keywords.put(this.keyword, this);
|
||||||
parser.exprAllowed = true;
|
}
|
||||||
} else {
|
|
||||||
parser.exprAllowed = !out.isExpr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TokenType(Properties prop) {
|
public static class Properties {
|
||||||
this.label = prop.label;
|
public String label, keyword;
|
||||||
this.keyword = prop.keyword;
|
public boolean beforeExpr, startsExpr, isLoop, isAssign, prefix, postfix;
|
||||||
this.beforeExpr = prop.beforeExpr;
|
public int binop;
|
||||||
this.startsExpr = prop.startsExpr;
|
|
||||||
this.isLoop = prop.isLoop;
|
|
||||||
this.isAssign = prop.isAssign;
|
|
||||||
this.isPrefix = prop.prefix;
|
|
||||||
this.isPostfix = prop.postfix;
|
|
||||||
this.binop = prop.binop;
|
|
||||||
if (this.keyword != null)
|
|
||||||
keywords.put(this.keyword, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Properties {
|
public Properties(String label, String keyword) {
|
||||||
public String label, keyword;
|
this.label = label;
|
||||||
public boolean beforeExpr, startsExpr, isLoop, isAssign, prefix, postfix;
|
this.keyword = keyword;
|
||||||
public int binop;
|
}
|
||||||
|
|
||||||
public Properties(String label, String keyword) {
|
public Properties(String label) {
|
||||||
this.label = label;
|
this(label, null);
|
||||||
this.keyword = keyword;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Properties(String label) {
|
public Properties beforeExpr() {
|
||||||
this(label, null);
|
this.beforeExpr = true;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Properties beforeExpr() {
|
public Properties startsExpr() {
|
||||||
this.beforeExpr = true;
|
this.startsExpr = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties startsExpr() {
|
public Properties isLoop() {
|
||||||
this.startsExpr = true;
|
this.isLoop = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties isLoop() {
|
public Properties isAssign() {
|
||||||
this.isLoop = true;
|
this.isAssign = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties isAssign() {
|
public Properties prefix() {
|
||||||
this.isAssign = true;
|
this.prefix = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties prefix() {
|
public Properties postfix() {
|
||||||
this.prefix = true;
|
this.postfix = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties postfix() {
|
public Properties binop(int prec) {
|
||||||
this.postfix = true;
|
this.binop = prec;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Properties binop(int prec) {
|
private static Properties binop(String name, int prec) {
|
||||||
this.binop = prec;
|
return new Properties(name, null).binop(prec).beforeExpr();
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties binop(String name, int prec) {
|
// Succinct definitions of keyword token types
|
||||||
return new Properties(name, null).binop(prec).beforeExpr();
|
private static Properties kw(String name) {
|
||||||
}
|
return new Properties(name, name);
|
||||||
|
}
|
||||||
// Succinct definitions of keyword token types
|
|
||||||
private static Properties kw(String name) {
|
|
||||||
return new Properties(name, name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,18 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/// whitespace.js
|
/// whitespace.js
|
||||||
public class Whitespace {
|
public class Whitespace {
|
||||||
public static final String lineBreak = "\r\n?|\n|\u2028|\u2029";
|
public static final String lineBreak = "\r\n?|\n|\u2028|\u2029";
|
||||||
public static final Pattern lineBreakG = Pattern.compile(lineBreak); // global
|
public static final Pattern lineBreakG = Pattern.compile(lineBreak); // global
|
||||||
|
|
||||||
public static boolean isNewLine(int code) {
|
public static boolean isNewLine(int code) {
|
||||||
return code == 10 || code == 13 || code == 0x2028 || code == 0x2029;
|
return code == 10 || code == 13 || code == 0x2028 || code == 0x2029;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String nonASCIIwhitespace = "\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff";
|
public static final String nonASCIIwhitespace =
|
||||||
|
"\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff";
|
||||||
|
|
||||||
public static final Pattern skipWhiteSpace = Pattern.compile("(?:\\s|//.*|/\\*([^*]|\\*(?!/))*\\*/)*"); // global
|
public static final Pattern skipWhiteSpace =
|
||||||
public static final Pattern skipWhiteSpaceNoNewline = Pattern.compile("(?:[ \\t\\x0B\\f]|//.*|/\\*([^*]|\\*(?!/))*\\*/)*");
|
Pattern.compile("(?:\\s|//.*|/\\*([^*]|\\*(?!/))*\\*/)*"); // global
|
||||||
|
public static final Pattern skipWhiteSpaceNoNewline =
|
||||||
|
Pattern.compile("(?:[ \\t\\x0B\\f]|//.*|/\\*([^*]|\\*(?!/))*\\*/)*");
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,22 +3,21 @@ package com.semmle.jcorn.jsx;
|
|||||||
import com.semmle.jcorn.Options;
|
import com.semmle.jcorn.Options;
|
||||||
|
|
||||||
public class JSXOptions extends Options {
|
public class JSXOptions extends Options {
|
||||||
public boolean allowNamespacedObjects = true, allowNamespaces = true;
|
public boolean allowNamespacedObjects = true, allowNamespaces = true;
|
||||||
|
|
||||||
public JSXOptions() {
|
public JSXOptions() {}
|
||||||
}
|
|
||||||
|
|
||||||
public JSXOptions(Options options) {
|
public JSXOptions(Options options) {
|
||||||
super(options);
|
super(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSXOptions allowNamespacedObjects(boolean allowNamespacedObjects) {
|
public JSXOptions allowNamespacedObjects(boolean allowNamespacedObjects) {
|
||||||
this.allowNamespacedObjects = allowNamespacedObjects;
|
this.allowNamespacedObjects = allowNamespacedObjects;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSXOptions allowNamespaces(boolean allowNamespaces) {
|
public JSXOptions allowNamespaces(boolean allowNamespaces) {
|
||||||
this.allowNamespaces = allowNamespaces;
|
this.allowNamespaces = allowNamespaces;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ import static com.semmle.jcorn.TokenType.slash;
|
|||||||
import static com.semmle.jcorn.TokenType.string;
|
import static com.semmle.jcorn.TokenType.string;
|
||||||
import static com.semmle.jcorn.Whitespace.isNewLine;
|
import static com.semmle.jcorn.Whitespace.isNewLine;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import com.semmle.jcorn.Identifiers;
|
import com.semmle.jcorn.Identifiers;
|
||||||
import com.semmle.jcorn.Options;
|
import com.semmle.jcorn.Options;
|
||||||
import com.semmle.jcorn.Parser;
|
import com.semmle.jcorn.Parser;
|
||||||
@@ -41,428 +36,416 @@ import com.semmle.js.ast.jsx.JSXNamespacedName;
|
|||||||
import com.semmle.js.ast.jsx.JSXOpeningElement;
|
import com.semmle.js.ast.jsx.JSXOpeningElement;
|
||||||
import com.semmle.js.ast.jsx.JSXSpreadAttribute;
|
import com.semmle.js.ast.jsx.JSXSpreadAttribute;
|
||||||
import com.semmle.util.data.Either;
|
import com.semmle.util.data.Either;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java port of <a href="https://github.com/RReverser/acorn-jsx">Acorn-JSX</a> as of version
|
* Java port of <a href="https://github.com/RReverser/acorn-jsx">Acorn-JSX</a> as of version <a
|
||||||
* <a href="https://github.com/RReverser/acorn-jsx/commit/05852d8ae9476b7f8a25e417665e2265528d5fb9">3.0.1</a>.
|
* href="https://github.com/RReverser/acorn-jsx/commit/05852d8ae9476b7f8a25e417665e2265528d5fb9">3.0.1</a>.
|
||||||
*
|
*
|
||||||
* Like the plain JavaScript {@link Parser}, the JSX parser is parameterized by an {@link Options}
|
* <p>Like the plain JavaScript {@link Parser}, the JSX parser is parameterized by an {@link
|
||||||
* object. To enable JSX parsing, pass in a {@link JSXOptions} object.
|
* Options} object. To enable JSX parsing, pass in a {@link JSXOptions} object.
|
||||||
*/
|
*/
|
||||||
public class JSXParser extends Parser {
|
public class JSXParser extends Parser {
|
||||||
private static final Pattern hexNumber = Pattern.compile("^[\\da-fA-F]+$");
|
private static final Pattern hexNumber = Pattern.compile("^[\\da-fA-F]+$");
|
||||||
private static final Pattern decimalNumber = Pattern.compile("^\\d+$");
|
private static final Pattern decimalNumber = Pattern.compile("^\\d+$");
|
||||||
|
|
||||||
public JSXParser(Options options, String input, int startPos) {
|
public JSXParser(Options options, String input, int startPos) {
|
||||||
super(options, input, startPos);
|
super(options, input, startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final TokContext j_oTag = new TokContext("<tag", false);
|
private static final TokContext j_oTag = new TokContext("<tag", false);
|
||||||
private static final TokContext j_cTag = new TokContext("</tag", false);
|
private static final TokContext j_cTag = new TokContext("</tag", false);
|
||||||
private static final TokContext j_expr = new TokContext("<tag>..</tag>", true, true, null);
|
private static final TokContext j_expr = new TokContext("<tag>..</tag>", true, true, null);
|
||||||
|
|
||||||
private static final TokenType jsxName = new TokenType(new Properties("jsxName"));
|
private static final TokenType jsxName = new TokenType(new Properties("jsxName"));
|
||||||
public static final TokenType jsxText = new TokenType(new Properties("jsxText").beforeExpr());
|
public static final TokenType jsxText = new TokenType(new Properties("jsxText").beforeExpr());
|
||||||
protected static final TokenType jsxTagStart = new TokenType(new Properties("jsxTagStart")) {
|
protected static final TokenType jsxTagStart =
|
||||||
@Override
|
new TokenType(new Properties("jsxTagStart")) {
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
@Override
|
||||||
parser.pushTokenContext(j_expr); // treat as beginning of JSX expression
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parser.pushTokenContext(j_oTag); // start opening tag context
|
parser.pushTokenContext(j_expr); // treat as beginning of JSX expression
|
||||||
parser.exprAllowed(false);
|
parser.pushTokenContext(j_oTag); // start opening tag context
|
||||||
}
|
parser.exprAllowed(false);
|
||||||
};
|
}
|
||||||
private static final TokenType jsxTagEnd = new TokenType(new Properties("jsxTagEnd")) {
|
};
|
||||||
@Override
|
private static final TokenType jsxTagEnd =
|
||||||
public void updateContext(Parser parser, TokenType prevType) {
|
new TokenType(new Properties("jsxTagEnd")) {
|
||||||
TokContext out = parser.popTokenContext();
|
@Override
|
||||||
if (out == j_oTag && prevType == slash || out == j_cTag) {
|
public void updateContext(Parser parser, TokenType prevType) {
|
||||||
parser.popTokenContext();
|
TokContext out = parser.popTokenContext();
|
||||||
parser.exprAllowed(parser.curContext() == j_expr);
|
if (out == j_oTag && prevType == slash || out == j_cTag) {
|
||||||
} else {
|
parser.popTokenContext();
|
||||||
parser.exprAllowed(true);
|
parser.exprAllowed(parser.curContext() == j_expr);
|
||||||
}
|
} else {
|
||||||
}
|
parser.exprAllowed(true);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/** Reads inline JSX contents token. */
|
||||||
* Reads inline JSX contents token.
|
private Token jsx_readToken() {
|
||||||
*/
|
StringBuilder out = new StringBuilder();
|
||||||
private Token jsx_readToken() {
|
int chunkStart = this.pos;
|
||||||
StringBuilder out = new StringBuilder();
|
for (; ; ) {
|
||||||
int chunkStart = this.pos;
|
if (this.pos >= this.input.length()) this.raise(this.start, "Unterminated JSX contents");
|
||||||
for (;;) {
|
Either<Integer, Token> chunk = jsx_readChunk(out, chunkStart, this.charAt(this.pos));
|
||||||
if (this.pos >= this.input.length())
|
if (chunk.isRight()) return chunk.getRight();
|
||||||
this.raise(this.start, "Unterminated JSX contents");
|
chunkStart = chunk.getLeft();
|
||||||
Either<Integer, Token> chunk = jsx_readChunk(out, chunkStart, this.charAt(this.pos));
|
}
|
||||||
if (chunk.isRight())
|
}
|
||||||
return chunk.getRight();
|
|
||||||
chunkStart = chunk.getLeft();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a chunk of inline JSX content, returning either the start of the next chunk
|
* Reads a chunk of inline JSX content, returning either the start of the next chunk or the
|
||||||
* or the completed content token.
|
* completed content token.
|
||||||
*/
|
*/
|
||||||
protected Either<Integer, Token> jsx_readChunk(StringBuilder out, int chunkStart, int ch) {
|
protected Either<Integer, Token> jsx_readChunk(StringBuilder out, int chunkStart, int ch) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 60: // '<'
|
case 60: // '<'
|
||||||
case 123: // '{'
|
case 123: // '{'
|
||||||
if (this.pos == this.start) {
|
if (this.pos == this.start) {
|
||||||
if (ch == 60 && this.exprAllowed) {
|
if (ch == 60 && this.exprAllowed) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
return Either.right(this.finishToken(jsxTagStart));
|
return Either.right(this.finishToken(jsxTagStart));
|
||||||
}
|
}
|
||||||
return Either.right(this.getTokenFromCode(ch));
|
return Either.right(this.getTokenFromCode(ch));
|
||||||
}
|
}
|
||||||
out.append(inputSubstring(chunkStart, this.pos));
|
out.append(inputSubstring(chunkStart, this.pos));
|
||||||
return Either.right(this.finishToken(jsxText, out.toString()));
|
return Either.right(this.finishToken(jsxText, out.toString()));
|
||||||
|
|
||||||
case 38: // '&'
|
case 38: // '&'
|
||||||
out.append(inputSubstring(chunkStart, this.pos));
|
out.append(inputSubstring(chunkStart, this.pos));
|
||||||
out.append(this.jsx_readEntity());
|
out.append(this.jsx_readEntity());
|
||||||
chunkStart = this.pos;
|
chunkStart = this.pos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isNewLine(ch)) {
|
if (isNewLine(ch)) {
|
||||||
out.append(inputSubstring(chunkStart, this.pos));
|
out.append(inputSubstring(chunkStart, this.pos));
|
||||||
out.append(this.jsx_readNewLine(true));
|
out.append(this.jsx_readNewLine(true));
|
||||||
chunkStart = this.pos;
|
chunkStart = this.pos;
|
||||||
} else {
|
} else {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Either.left(chunkStart);
|
return Either.left(chunkStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String jsx_readNewLine(boolean normalizeCRLF) {
|
private String jsx_readNewLine(boolean normalizeCRLF) {
|
||||||
int ch = this.charAt(this.pos);
|
int ch = this.charAt(this.pos);
|
||||||
String out;
|
String out;
|
||||||
++this.pos;
|
++this.pos;
|
||||||
if (ch == 13 && this.charAt(this.pos) == 10) {
|
if (ch == 13 && this.charAt(this.pos) == 10) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
out = normalizeCRLF ? "\n" : "\r\n";
|
out = normalizeCRLF ? "\n" : "\r\n";
|
||||||
} else {
|
} else {
|
||||||
out = String.valueOf((char)ch);
|
out = String.valueOf((char) ch);
|
||||||
}
|
}
|
||||||
++this.curLine;
|
++this.curLine;
|
||||||
this.lineStart = this.pos;
|
this.lineStart = this.pos;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token jsx_readString(char quote) {
|
private Token jsx_readString(char quote) {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
int chunkStart = ++this.pos;
|
int chunkStart = ++this.pos;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (this.pos >= this.input.length())
|
if (this.pos >= this.input.length()) this.raise(this.start, "Unterminated string constant");
|
||||||
this.raise(this.start, "Unterminated string constant");
|
int ch = this.charAt(this.pos);
|
||||||
int ch = this.charAt(this.pos);
|
if (ch == quote) break;
|
||||||
if (ch == quote) break;
|
if (ch == 38) { // '&'
|
||||||
if (ch == 38) { // '&'
|
out.append(inputSubstring(chunkStart, this.pos));
|
||||||
out.append(inputSubstring(chunkStart, this.pos));
|
out.append(this.jsx_readEntity());
|
||||||
out.append(this.jsx_readEntity());
|
chunkStart = this.pos;
|
||||||
chunkStart = this.pos;
|
} else if (isNewLine(ch)) {
|
||||||
} else if (isNewLine(ch)) {
|
out.append(inputSubstring(chunkStart, this.pos));
|
||||||
out.append(inputSubstring(chunkStart, this.pos));
|
out.append(this.jsx_readNewLine(false));
|
||||||
out.append(this.jsx_readNewLine(false));
|
chunkStart = this.pos;
|
||||||
chunkStart = this.pos;
|
} else {
|
||||||
} else {
|
++this.pos;
|
||||||
++this.pos;
|
}
|
||||||
}
|
}
|
||||||
}
|
out.append(inputSubstring(chunkStart, this.pos++));
|
||||||
out.append(inputSubstring(chunkStart, this.pos++));
|
return this.finishToken(string, out.toString());
|
||||||
return this.finishToken(string, out.toString());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private String jsx_readEntity() {
|
private String jsx_readEntity() {
|
||||||
int ch = this.charAt(this.pos);
|
int ch = this.charAt(this.pos);
|
||||||
if (ch != '&')
|
if (ch != '&') this.raise(this.pos, "Entity must start with an ampersand");
|
||||||
this.raise(this.pos, "Entity must start with an ampersand");
|
int startPos = ++this.pos;
|
||||||
int startPos = ++this.pos;
|
String entity = null;
|
||||||
String entity = null;
|
int semi = this.input.indexOf(';', startPos);
|
||||||
int semi = this.input.indexOf(';', startPos);
|
if (semi != -1) {
|
||||||
if (semi != -1) {
|
String entityName = inputSubstring(startPos, semi);
|
||||||
String entityName = inputSubstring(startPos, semi);
|
if (entityName.startsWith("#x")) {
|
||||||
if (entityName.startsWith("#x")) {
|
entityName = entityName.substring(2);
|
||||||
entityName = entityName.substring(2);
|
if (hexNumber.matcher(entityName).matches())
|
||||||
if (hexNumber.matcher(entityName).matches())
|
entity = codePointToString(parseInt(entityName, 16).intValue());
|
||||||
entity = codePointToString(parseInt(entityName, 16).intValue());
|
} else if (entityName.startsWith("#")) {
|
||||||
} else if (entityName.startsWith("#")) {
|
entityName = entityName.substring(1);
|
||||||
entityName = entityName.substring(1);
|
if (decimalNumber.matcher(entityName).matches())
|
||||||
if (decimalNumber.matcher(entityName).matches())
|
entity = codePointToString(parseInt(entityName, 10).intValue());
|
||||||
entity = codePointToString(parseInt(entityName, 10).intValue());
|
} else {
|
||||||
} else {
|
Character entityChar = XHTMLEntities.ENTITIES.get(entityName);
|
||||||
Character entityChar = XHTMLEntities.ENTITIES.get(entityName);
|
if (entityChar != null) entity = String.valueOf(entityChar);
|
||||||
if (entityChar != null)
|
}
|
||||||
entity = String.valueOf(entityChar);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
this.pos = startPos;
|
this.pos = startPos;
|
||||||
return "&";
|
return "&";
|
||||||
} else {
|
} else {
|
||||||
this.pos = semi+1;
|
this.pos = semi + 1;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a JSX identifier (valid tag or attribute name).
|
* Read a JSX identifier (valid tag or attribute name).
|
||||||
*
|
*
|
||||||
* Optimized version since JSX identifiers can't contain
|
* <p>Optimized version since JSX identifiers can't contain escape characters and so can be read
|
||||||
* escape characters and so can be read as single slice.
|
* as single slice. Also assumes that first character was already checked by isIdentifierStart in
|
||||||
* Also assumes that first character was already checked
|
* readToken.
|
||||||
* by isIdentifierStart in readToken.
|
*/
|
||||||
*/
|
private Token jsx_readWord() {
|
||||||
private Token jsx_readWord() {
|
int ch, start = this.pos;
|
||||||
int ch, start = this.pos;
|
do {
|
||||||
do {
|
ch = this.charAt(++this.pos);
|
||||||
ch = this.charAt(++this.pos);
|
} while (Identifiers.isIdentifierChar(ch, true) || ch == 45); // '-'
|
||||||
} while (Identifiers.isIdentifierChar(ch, true) || ch == 45); // '-'
|
return this.finishToken(jsxName, inputSubstring(start, this.pos));
|
||||||
return this.finishToken(jsxName, inputSubstring(start, this.pos));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Transforms JSX element name to string; {@code null} is transformed to {@code null}. */
|
/** Transforms JSX element name to string; {@code null} is transformed to {@code null}. */
|
||||||
private String getQualifiedJSXName(Object object) {
|
private String getQualifiedJSXName(Object object) {
|
||||||
if (object == null)
|
if (object == null) return null;
|
||||||
return null;
|
return ((IJSXName) object).getQualifiedName();
|
||||||
return ((IJSXName) object).getQualifiedName();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse next token as JSX identifier */
|
/** Parse next token as JSX identifier */
|
||||||
private JSXIdentifier jsx_parseIdentifier() {
|
private JSXIdentifier jsx_parseIdentifier() {
|
||||||
SourceLocation loc = new SourceLocation(this.startLoc);
|
SourceLocation loc = new SourceLocation(this.startLoc);
|
||||||
String name = null;
|
String name = null;
|
||||||
if (this.type == jsxName)
|
if (this.type == jsxName) name = String.valueOf(this.value);
|
||||||
name = String.valueOf(this.value);
|
else if (this.type.keyword != null) name = this.type.keyword;
|
||||||
else if (this.type.keyword != null)
|
else this.unexpected();
|
||||||
name = this.type.keyword;
|
this.next();
|
||||||
else
|
return this.finishNode(new JSXIdentifier(loc, name));
|
||||||
this.unexpected();
|
}
|
||||||
this.next();
|
|
||||||
return this.finishNode(new JSXIdentifier(loc, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse namespaced identifier. */
|
/** Parse namespaced identifier. */
|
||||||
private IJSXName jsx_parseNamespacedName() {
|
private IJSXName jsx_parseNamespacedName() {
|
||||||
SourceLocation loc = new SourceLocation(this.startLoc);
|
SourceLocation loc = new SourceLocation(this.startLoc);
|
||||||
JSXIdentifier namespace = this.jsx_parseIdentifier();
|
JSXIdentifier namespace = this.jsx_parseIdentifier();
|
||||||
if (!((JSXOptions)options).allowNamespaces || !this.eat(colon))
|
if (!((JSXOptions) options).allowNamespaces || !this.eat(colon)) return namespace;
|
||||||
return namespace;
|
return this.finishNode(new JSXNamespacedName(loc, namespace, this.jsx_parseIdentifier()));
|
||||||
return this.finishNode(new JSXNamespacedName(loc, namespace, this.jsx_parseIdentifier()));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses element name in any form - namespaced, member
|
* Parses element name in any form - namespaced, member or single identifier. If the next token is
|
||||||
* or single identifier. If the next token is a tag-end token,
|
* a tag-end token, {@code null} is returned; this happens with fragments.
|
||||||
* {@code null} is returned; this happens with fragments.
|
*/
|
||||||
*/
|
private IJSXName jsx_parseElementName() {
|
||||||
private IJSXName jsx_parseElementName () {
|
if (this.type == jsxTagEnd) return null;
|
||||||
if (this.type == jsxTagEnd)
|
Position startPos = this.startLoc;
|
||||||
return null;
|
IJSXName node = this.jsx_parseNamespacedName();
|
||||||
Position startPos = this.startLoc;
|
if (this.type == dot
|
||||||
IJSXName node = this.jsx_parseNamespacedName();
|
&& node instanceof JSXNamespacedName
|
||||||
if (this.type == dot && node instanceof JSXNamespacedName && !((JSXOptions)options).allowNamespacedObjects) {
|
&& !((JSXOptions) options).allowNamespacedObjects) {
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
while (this.eat(dot)) {
|
while (this.eat(dot)) {
|
||||||
SourceLocation loc = new SourceLocation(startPos);
|
SourceLocation loc = new SourceLocation(startPos);
|
||||||
node = this.finishNode(new JSXMemberExpression(loc, node, this.jsx_parseIdentifier()));
|
node = this.finishNode(new JSXMemberExpression(loc, node, this.jsx_parseIdentifier()));
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parses any type of JSX attribute value. */
|
/** Parses any type of JSX attribute value. */
|
||||||
private INode jsx_parseAttributeValue() {
|
private INode jsx_parseAttributeValue() {
|
||||||
if (type == braceL) {
|
if (type == braceL) {
|
||||||
JSXExpressionContainer node = this.jsx_parseExpressionContainer();
|
JSXExpressionContainer node = this.jsx_parseExpressionContainer();
|
||||||
if (node.getExpression() instanceof JSXEmptyExpression)
|
if (node.getExpression() instanceof JSXEmptyExpression)
|
||||||
this.raise(node, "JSX attributes must only be assigned a non-empty expression");
|
this.raise(node, "JSX attributes must only be assigned a non-empty expression");
|
||||||
return node;
|
return node;
|
||||||
} else if (type == jsxTagStart || type == string) {
|
} else if (type == jsxTagStart || type == string) {
|
||||||
return this.parseExprAtom(null);
|
return this.parseExprAtom(null);
|
||||||
} else {
|
} else {
|
||||||
this.raise(this.start, "JSX value should be either an expression or a quoted JSX text");
|
this.raise(this.start, "JSX value should be either an expression or a quoted JSX text");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSXEmptyExpression is unique type since it doesn't actually parse anything,
|
* JSXEmptyExpression is unique type since it doesn't actually parse anything, and so it should
|
||||||
* and so it should start at the end of last read token (left brace) and finish
|
* start at the end of last read token (left brace) and finish at the beginning of the next one
|
||||||
* at the beginning of the next one (right brace).
|
* (right brace).
|
||||||
*/
|
*/
|
||||||
private JSXEmptyExpression jsx_parseEmptyExpression() {
|
private JSXEmptyExpression jsx_parseEmptyExpression() {
|
||||||
return new JSXEmptyExpression(new SourceLocation("", lastTokEndLoc, startLoc));
|
return new JSXEmptyExpression(new SourceLocation("", lastTokEndLoc, startLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parses JSX expression enclosed into curly brackets. */
|
/** Parses JSX expression enclosed into curly brackets. */
|
||||||
private JSXExpressionContainer jsx_parseExpressionContainer() {
|
private JSXExpressionContainer jsx_parseExpressionContainer() {
|
||||||
SourceLocation loc = new SourceLocation(this.startLoc);
|
SourceLocation loc = new SourceLocation(this.startLoc);
|
||||||
this.next();
|
this.next();
|
||||||
INode expression;
|
INode expression;
|
||||||
if (this.type == braceR)
|
if (this.type == braceR) expression = this.jsx_parseEmptyExpression();
|
||||||
expression = this.jsx_parseEmptyExpression();
|
else expression = this.parseExpression(false, null);
|
||||||
else
|
this.expect(braceR);
|
||||||
expression = this.parseExpression(false, null);
|
return this.finishNode(new JSXExpressionContainer(loc, expression));
|
||||||
this.expect(braceR);
|
}
|
||||||
return this.finishNode(new JSXExpressionContainer(loc, expression));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parses following JSX attribute name-value pair. */
|
/** Parses following JSX attribute name-value pair. */
|
||||||
private IJSXAttribute jsx_parseAttribute() {
|
private IJSXAttribute jsx_parseAttribute() {
|
||||||
SourceLocation loc = new SourceLocation(this.startLoc);
|
SourceLocation loc = new SourceLocation(this.startLoc);
|
||||||
if (this.eat(braceL)) {
|
if (this.eat(braceL)) {
|
||||||
this.expect(ellipsis);
|
this.expect(ellipsis);
|
||||||
Expression argument = this.parseMaybeAssign(false, null, null);
|
Expression argument = this.parseMaybeAssign(false, null, null);
|
||||||
this.expect(braceR);
|
this.expect(braceR);
|
||||||
return this.finishNode(new JSXSpreadAttribute(loc, argument));
|
return this.finishNode(new JSXSpreadAttribute(loc, argument));
|
||||||
}
|
}
|
||||||
IJSXName name = this.jsx_parseNamespacedName();
|
IJSXName name = this.jsx_parseNamespacedName();
|
||||||
INode value = this.eat(eq) ? this.jsx_parseAttributeValue() : null;
|
INode value = this.eat(eq) ? this.jsx_parseAttributeValue() : null;
|
||||||
return this.finishNode(new JSXAttribute(loc, name, value));
|
return this.finishNode(new JSXAttribute(loc, name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parses JSX opening tag starting after '<'. */
|
/** Parses JSX opening tag starting after '<'. */
|
||||||
private JSXOpeningElement jsx_parseOpeningElementAt(Position startLoc) {
|
private JSXOpeningElement jsx_parseOpeningElementAt(Position startLoc) {
|
||||||
SourceLocation loc = new SourceLocation(startLoc);
|
SourceLocation loc = new SourceLocation(startLoc);
|
||||||
List<IJSXAttribute> attributes = new ArrayList<>();
|
List<IJSXAttribute> attributes = new ArrayList<>();
|
||||||
IJSXName name = this.jsx_parseElementName();
|
IJSXName name = this.jsx_parseElementName();
|
||||||
while (this.type != slash && this.type != jsxTagEnd)
|
while (this.type != slash && this.type != jsxTagEnd) attributes.add(this.jsx_parseAttribute());
|
||||||
attributes.add(this.jsx_parseAttribute());
|
boolean selfClosing = this.eat(slash);
|
||||||
boolean selfClosing = this.eat(slash);
|
this.expect(jsxTagEnd);
|
||||||
this.expect(jsxTagEnd);
|
return this.finishNode(new JSXOpeningElement(loc, name, attributes, selfClosing));
|
||||||
return this.finishNode(new JSXOpeningElement(loc, name, attributes, selfClosing));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Parses JSX closing tag starting after '</'. */
|
/** Parses JSX closing tag starting after '</'. */
|
||||||
private JSXClosingElement jsx_parseClosingElementAt(Position startLoc) {
|
private JSXClosingElement jsx_parseClosingElementAt(Position startLoc) {
|
||||||
SourceLocation loc = new SourceLocation(startLoc);
|
SourceLocation loc = new SourceLocation(startLoc);
|
||||||
IJSXName name = this.jsx_parseElementName();
|
IJSXName name = this.jsx_parseElementName();
|
||||||
this.expect(jsxTagEnd);
|
this.expect(jsxTagEnd);
|
||||||
return this.finishNode(new JSXClosingElement(loc, name));
|
return this.finishNode(new JSXClosingElement(loc, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses entire JSX element, including its opening tag
|
* Parses entire JSX element, including its opening tag (starting after '<'), attributes,
|
||||||
* (starting after '<'), attributes, contents and closing tag.
|
* contents and closing tag.
|
||||||
*/
|
*/
|
||||||
private JSXElement jsx_parseElementAt(Position startLoc) {
|
private JSXElement jsx_parseElementAt(Position startLoc) {
|
||||||
SourceLocation loc = new SourceLocation(startLoc);
|
SourceLocation loc = new SourceLocation(startLoc);
|
||||||
List<INode> children = new ArrayList<INode>();
|
List<INode> children = new ArrayList<INode>();
|
||||||
JSXOpeningElement openingElement = this.jsx_parseOpeningElementAt(startLoc);
|
JSXOpeningElement openingElement = this.jsx_parseOpeningElementAt(startLoc);
|
||||||
JSXClosingElement closingElement = null;
|
JSXClosingElement closingElement = null;
|
||||||
|
|
||||||
if (!openingElement.isSelfClosing()) {
|
if (!openingElement.isSelfClosing()) {
|
||||||
contents:
|
contents:
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (type == jsxTagStart) {
|
if (type == jsxTagStart) {
|
||||||
startLoc = this.startLoc;
|
startLoc = this.startLoc;
|
||||||
this.next();
|
this.next();
|
||||||
if (this.eat(slash)) {
|
if (this.eat(slash)) {
|
||||||
closingElement = this.jsx_parseClosingElementAt(startLoc);
|
closingElement = this.jsx_parseClosingElementAt(startLoc);
|
||||||
break contents;
|
break contents;
|
||||||
}
|
}
|
||||||
children.add(this.jsx_parseElementAt(startLoc));
|
children.add(this.jsx_parseElementAt(startLoc));
|
||||||
} else if (type == jsxText) {
|
} else if (type == jsxText) {
|
||||||
children.add(this.parseExprAtom(null));
|
children.add(this.parseExprAtom(null));
|
||||||
} else if (type == braceL) {
|
} else if (type == braceL) {
|
||||||
children.add(this.jsx_parseExpressionContainer());
|
children.add(this.jsx_parseExpressionContainer());
|
||||||
} else {
|
} else {
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String closingQualName = getQualifiedJSXName(openingElement.getName());
|
String closingQualName = getQualifiedJSXName(openingElement.getName());
|
||||||
if (!Objects.equals(getQualifiedJSXName(closingElement.getName()), closingQualName)) {
|
if (!Objects.equals(getQualifiedJSXName(closingElement.getName()), closingQualName)) {
|
||||||
// prettify for error message
|
// prettify for error message
|
||||||
if (closingQualName == null)
|
if (closingQualName == null) closingQualName = "";
|
||||||
closingQualName = "";
|
this.raise(
|
||||||
this.raise(
|
closingElement, "Expected corresponding JSX closing tag for <" + closingQualName + ">");
|
||||||
closingElement,
|
}
|
||||||
"Expected corresponding JSX closing tag for <" + closingQualName + ">");
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.type == relational && "<".equals(this.value)) {
|
if (this.type == relational && "<".equals(this.value)) {
|
||||||
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
|
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
|
||||||
}
|
}
|
||||||
return this.finishNode(new JSXElement(loc, openingElement, children, closingElement));
|
return this.finishNode(new JSXElement(loc, openingElement, children, closingElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parses entire JSX element from current position. */
|
/** Parses entire JSX element from current position. */
|
||||||
private JSXElement jsx_parseElement() {
|
private JSXElement jsx_parseElement() {
|
||||||
Position startLoc = this.startLoc;
|
Position startLoc = this.startLoc;
|
||||||
this.next();
|
this.next();
|
||||||
return this.jsx_parseElementAt(startLoc);
|
return this.jsx_parseElementAt(startLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
|
protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
|
||||||
if (this.type == jsxText) {
|
if (this.type == jsxText) {
|
||||||
return this.parseLiteral(this.type, this.value);
|
return this.parseLiteral(this.type, this.value);
|
||||||
} else if (this.type == jsxTagStart) {
|
} else if (this.type == jsxTagStart) {
|
||||||
return this.jsx_parseElement();
|
return this.jsx_parseElement();
|
||||||
} else {
|
} else {
|
||||||
return super.parseExprAtom(refDestructuringErrors);
|
return super.parseExprAtom(refDestructuringErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Token readToken(int code) {
|
protected Token readToken(int code) {
|
||||||
TokContext context = this.curContext();
|
TokContext context = this.curContext();
|
||||||
|
|
||||||
if (context == j_expr)
|
|
||||||
return this.jsx_readToken();
|
|
||||||
|
|
||||||
if (context == j_oTag || context == j_cTag) {
|
|
||||||
if (Identifiers.isIdentifierStart(code, true))
|
|
||||||
return this.jsx_readWord();
|
|
||||||
|
|
||||||
if (code == 62) {
|
|
||||||
++this.pos;
|
|
||||||
return this.finishToken(jsxTagEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((code == 34 || code == 39) && context == j_oTag)
|
|
||||||
return this.jsx_readString((char)code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options instanceof JSXOptions && code == 60 && this.exprAllowed &&
|
|
||||||
// avoid getting confused on HTML comments
|
|
||||||
this.charAt(this.pos+1) != '!') {
|
|
||||||
++this.pos;
|
|
||||||
return this.finishToken(jsxTagStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.readToken(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (context == j_expr) return this.jsx_readToken();
|
||||||
protected void updateContext(TokenType prevType) {
|
|
||||||
if (options instanceof JSXOptions) {
|
if (context == j_oTag || context == j_cTag) {
|
||||||
if (type == braceL) {
|
if (Identifiers.isIdentifierStart(code, true)) return this.jsx_readWord();
|
||||||
TokContext curContext = this.curContext();
|
|
||||||
if (curContext == j_oTag) {
|
if (code == 62) {
|
||||||
this.context.push(b_expr);
|
++this.pos;
|
||||||
} else if (curContext == j_expr) {
|
return this.finishToken(jsxTagEnd);
|
||||||
this.context.push(b_tmpl);
|
}
|
||||||
} else {
|
|
||||||
type.updateContext(this, prevType);
|
if ((code == 34 || code == 39) && context == j_oTag) return this.jsx_readString((char) code);
|
||||||
}
|
}
|
||||||
this.exprAllowed = true;
|
|
||||||
return;
|
if (options instanceof JSXOptions
|
||||||
} else if (type == slash && prevType == jsxTagStart) {
|
&& code == 60
|
||||||
this.context.pop();
|
&& this.exprAllowed
|
||||||
this.context.pop(); // do not consider JSX expr -> JSX open tag -> ... anymore
|
&&
|
||||||
this.context.push(j_cTag);
|
// avoid getting confused on HTML comments
|
||||||
this.exprAllowed = false;
|
this.charAt(this.pos + 1) != '!') {
|
||||||
return;
|
++this.pos;
|
||||||
}
|
return this.finishToken(jsxTagStart);
|
||||||
}
|
}
|
||||||
super.updateContext(prevType);
|
|
||||||
}
|
return super.readToken(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateContext(TokenType prevType) {
|
||||||
|
if (options instanceof JSXOptions) {
|
||||||
|
if (type == braceL) {
|
||||||
|
TokContext curContext = this.curContext();
|
||||||
|
if (curContext == j_oTag) {
|
||||||
|
this.context.push(b_expr);
|
||||||
|
} else if (curContext == j_expr) {
|
||||||
|
this.context.push(b_tmpl);
|
||||||
|
} else {
|
||||||
|
type.updateContext(this, prevType);
|
||||||
|
}
|
||||||
|
this.exprAllowed = true;
|
||||||
|
return;
|
||||||
|
} else if (type == slash && prevType == jsxTagStart) {
|
||||||
|
this.context.pop();
|
||||||
|
this.context.pop(); // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||||
|
this.context.push(j_cTag);
|
||||||
|
this.exprAllowed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.updateContext(prevType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,260 +4,261 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class XHTMLEntities {
|
public class XHTMLEntities {
|
||||||
public static final Map<String, Character> ENTITIES = new LinkedHashMap<>();
|
public static final Map<String, Character> ENTITIES = new LinkedHashMap<>();
|
||||||
static {
|
|
||||||
ENTITIES.put("quot", '\u0022');
|
static {
|
||||||
ENTITIES.put("amp", '&');
|
ENTITIES.put("quot", '\u0022');
|
||||||
ENTITIES.put("apos", '\'');
|
ENTITIES.put("amp", '&');
|
||||||
ENTITIES.put("lt", '<');
|
ENTITIES.put("apos", '\'');
|
||||||
ENTITIES.put("gt", '>');
|
ENTITIES.put("lt", '<');
|
||||||
ENTITIES.put("nbsp", '\u00A0');
|
ENTITIES.put("gt", '>');
|
||||||
ENTITIES.put("iexcl", '\u00A1');
|
ENTITIES.put("nbsp", '\u00A0');
|
||||||
ENTITIES.put("cent", '\u00A2');
|
ENTITIES.put("iexcl", '\u00A1');
|
||||||
ENTITIES.put("pound", '\u00A3');
|
ENTITIES.put("cent", '\u00A2');
|
||||||
ENTITIES.put("curren", '\u00A4');
|
ENTITIES.put("pound", '\u00A3');
|
||||||
ENTITIES.put("yen", '\u00A5');
|
ENTITIES.put("curren", '\u00A4');
|
||||||
ENTITIES.put("brvbar", '\u00A6');
|
ENTITIES.put("yen", '\u00A5');
|
||||||
ENTITIES.put("sect", '\u00A7');
|
ENTITIES.put("brvbar", '\u00A6');
|
||||||
ENTITIES.put("uml", '\u00A8');
|
ENTITIES.put("sect", '\u00A7');
|
||||||
ENTITIES.put("copy", '\u00A9');
|
ENTITIES.put("uml", '\u00A8');
|
||||||
ENTITIES.put("ordf", '\u00AA');
|
ENTITIES.put("copy", '\u00A9');
|
||||||
ENTITIES.put("laquo", '\u00AB');
|
ENTITIES.put("ordf", '\u00AA');
|
||||||
ENTITIES.put("not", '\u00AC');
|
ENTITIES.put("laquo", '\u00AB');
|
||||||
ENTITIES.put("shy", '\u00AD');
|
ENTITIES.put("not", '\u00AC');
|
||||||
ENTITIES.put("reg", '\u00AE');
|
ENTITIES.put("shy", '\u00AD');
|
||||||
ENTITIES.put("macr", '\u00AF');
|
ENTITIES.put("reg", '\u00AE');
|
||||||
ENTITIES.put("deg", '\u00B0');
|
ENTITIES.put("macr", '\u00AF');
|
||||||
ENTITIES.put("plusmn", '\u00B1');
|
ENTITIES.put("deg", '\u00B0');
|
||||||
ENTITIES.put("sup2", '\u00B2');
|
ENTITIES.put("plusmn", '\u00B1');
|
||||||
ENTITIES.put("sup3", '\u00B3');
|
ENTITIES.put("sup2", '\u00B2');
|
||||||
ENTITIES.put("acute", '\u00B4');
|
ENTITIES.put("sup3", '\u00B3');
|
||||||
ENTITIES.put("micro", '\u00B5');
|
ENTITIES.put("acute", '\u00B4');
|
||||||
ENTITIES.put("para", '\u00B6');
|
ENTITIES.put("micro", '\u00B5');
|
||||||
ENTITIES.put("middot", '\u00B7');
|
ENTITIES.put("para", '\u00B6');
|
||||||
ENTITIES.put("cedil", '\u00B8');
|
ENTITIES.put("middot", '\u00B7');
|
||||||
ENTITIES.put("sup1", '\u00B9');
|
ENTITIES.put("cedil", '\u00B8');
|
||||||
ENTITIES.put("ordm", '\u00BA');
|
ENTITIES.put("sup1", '\u00B9');
|
||||||
ENTITIES.put("raquo", '\u00BB');
|
ENTITIES.put("ordm", '\u00BA');
|
||||||
ENTITIES.put("frac14", '\u00BC');
|
ENTITIES.put("raquo", '\u00BB');
|
||||||
ENTITIES.put("frac12", '\u00BD');
|
ENTITIES.put("frac14", '\u00BC');
|
||||||
ENTITIES.put("frac34", '\u00BE');
|
ENTITIES.put("frac12", '\u00BD');
|
||||||
ENTITIES.put("iquest", '\u00BF');
|
ENTITIES.put("frac34", '\u00BE');
|
||||||
ENTITIES.put("Agrave", '\u00C0');
|
ENTITIES.put("iquest", '\u00BF');
|
||||||
ENTITIES.put("Aacute", '\u00C1');
|
ENTITIES.put("Agrave", '\u00C0');
|
||||||
ENTITIES.put("Acirc", '\u00C2');
|
ENTITIES.put("Aacute", '\u00C1');
|
||||||
ENTITIES.put("Atilde", '\u00C3');
|
ENTITIES.put("Acirc", '\u00C2');
|
||||||
ENTITIES.put("Auml", '\u00C4');
|
ENTITIES.put("Atilde", '\u00C3');
|
||||||
ENTITIES.put("Aring", '\u00C5');
|
ENTITIES.put("Auml", '\u00C4');
|
||||||
ENTITIES.put("AElig", '\u00C6');
|
ENTITIES.put("Aring", '\u00C5');
|
||||||
ENTITIES.put("Ccedil", '\u00C7');
|
ENTITIES.put("AElig", '\u00C6');
|
||||||
ENTITIES.put("Egrave", '\u00C8');
|
ENTITIES.put("Ccedil", '\u00C7');
|
||||||
ENTITIES.put("Eacute", '\u00C9');
|
ENTITIES.put("Egrave", '\u00C8');
|
||||||
ENTITIES.put("Ecirc", '\u00CA');
|
ENTITIES.put("Eacute", '\u00C9');
|
||||||
ENTITIES.put("Euml", '\u00CB');
|
ENTITIES.put("Ecirc", '\u00CA');
|
||||||
ENTITIES.put("Igrave", '\u00CC');
|
ENTITIES.put("Euml", '\u00CB');
|
||||||
ENTITIES.put("Iacute", '\u00CD');
|
ENTITIES.put("Igrave", '\u00CC');
|
||||||
ENTITIES.put("Icirc", '\u00CE');
|
ENTITIES.put("Iacute", '\u00CD');
|
||||||
ENTITIES.put("Iuml", '\u00CF');
|
ENTITIES.put("Icirc", '\u00CE');
|
||||||
ENTITIES.put("ETH", '\u00D0');
|
ENTITIES.put("Iuml", '\u00CF');
|
||||||
ENTITIES.put("Ntilde", '\u00D1');
|
ENTITIES.put("ETH", '\u00D0');
|
||||||
ENTITIES.put("Ograve", '\u00D2');
|
ENTITIES.put("Ntilde", '\u00D1');
|
||||||
ENTITIES.put("Oacute", '\u00D3');
|
ENTITIES.put("Ograve", '\u00D2');
|
||||||
ENTITIES.put("Ocirc", '\u00D4');
|
ENTITIES.put("Oacute", '\u00D3');
|
||||||
ENTITIES.put("Otilde", '\u00D5');
|
ENTITIES.put("Ocirc", '\u00D4');
|
||||||
ENTITIES.put("Ouml", '\u00D6');
|
ENTITIES.put("Otilde", '\u00D5');
|
||||||
ENTITIES.put("times", '\u00D7');
|
ENTITIES.put("Ouml", '\u00D6');
|
||||||
ENTITIES.put("Oslash", '\u00D8');
|
ENTITIES.put("times", '\u00D7');
|
||||||
ENTITIES.put("Ugrave", '\u00D9');
|
ENTITIES.put("Oslash", '\u00D8');
|
||||||
ENTITIES.put("Uacute", '\u00DA');
|
ENTITIES.put("Ugrave", '\u00D9');
|
||||||
ENTITIES.put("Ucirc", '\u00DB');
|
ENTITIES.put("Uacute", '\u00DA');
|
||||||
ENTITIES.put("Uuml", '\u00DC');
|
ENTITIES.put("Ucirc", '\u00DB');
|
||||||
ENTITIES.put("Yacute", '\u00DD');
|
ENTITIES.put("Uuml", '\u00DC');
|
||||||
ENTITIES.put("THORN", '\u00DE');
|
ENTITIES.put("Yacute", '\u00DD');
|
||||||
ENTITIES.put("szlig", '\u00DF');
|
ENTITIES.put("THORN", '\u00DE');
|
||||||
ENTITIES.put("agrave", '\u00E0');
|
ENTITIES.put("szlig", '\u00DF');
|
||||||
ENTITIES.put("aacute", '\u00E1');
|
ENTITIES.put("agrave", '\u00E0');
|
||||||
ENTITIES.put("acirc", '\u00E2');
|
ENTITIES.put("aacute", '\u00E1');
|
||||||
ENTITIES.put("atilde", '\u00E3');
|
ENTITIES.put("acirc", '\u00E2');
|
||||||
ENTITIES.put("auml", '\u00E4');
|
ENTITIES.put("atilde", '\u00E3');
|
||||||
ENTITIES.put("aring", '\u00E5');
|
ENTITIES.put("auml", '\u00E4');
|
||||||
ENTITIES.put("aelig", '\u00E6');
|
ENTITIES.put("aring", '\u00E5');
|
||||||
ENTITIES.put("ccedil", '\u00E7');
|
ENTITIES.put("aelig", '\u00E6');
|
||||||
ENTITIES.put("egrave", '\u00E8');
|
ENTITIES.put("ccedil", '\u00E7');
|
||||||
ENTITIES.put("eacute", '\u00E9');
|
ENTITIES.put("egrave", '\u00E8');
|
||||||
ENTITIES.put("ecirc", '\u00EA');
|
ENTITIES.put("eacute", '\u00E9');
|
||||||
ENTITIES.put("euml", '\u00EB');
|
ENTITIES.put("ecirc", '\u00EA');
|
||||||
ENTITIES.put("igrave", '\u00EC');
|
ENTITIES.put("euml", '\u00EB');
|
||||||
ENTITIES.put("iacute", '\u00ED');
|
ENTITIES.put("igrave", '\u00EC');
|
||||||
ENTITIES.put("icirc", '\u00EE');
|
ENTITIES.put("iacute", '\u00ED');
|
||||||
ENTITIES.put("iuml", '\u00EF');
|
ENTITIES.put("icirc", '\u00EE');
|
||||||
ENTITIES.put("eth", '\u00F0');
|
ENTITIES.put("iuml", '\u00EF');
|
||||||
ENTITIES.put("ntilde", '\u00F1');
|
ENTITIES.put("eth", '\u00F0');
|
||||||
ENTITIES.put("ograve", '\u00F2');
|
ENTITIES.put("ntilde", '\u00F1');
|
||||||
ENTITIES.put("oacute", '\u00F3');
|
ENTITIES.put("ograve", '\u00F2');
|
||||||
ENTITIES.put("ocirc", '\u00F4');
|
ENTITIES.put("oacute", '\u00F3');
|
||||||
ENTITIES.put("otilde", '\u00F5');
|
ENTITIES.put("ocirc", '\u00F4');
|
||||||
ENTITIES.put("ouml", '\u00F6');
|
ENTITIES.put("otilde", '\u00F5');
|
||||||
ENTITIES.put("divide", '\u00F7');
|
ENTITIES.put("ouml", '\u00F6');
|
||||||
ENTITIES.put("oslash", '\u00F8');
|
ENTITIES.put("divide", '\u00F7');
|
||||||
ENTITIES.put("ugrave", '\u00F9');
|
ENTITIES.put("oslash", '\u00F8');
|
||||||
ENTITIES.put("uacute", '\u00FA');
|
ENTITIES.put("ugrave", '\u00F9');
|
||||||
ENTITIES.put("ucirc", '\u00FB');
|
ENTITIES.put("uacute", '\u00FA');
|
||||||
ENTITIES.put("uuml", '\u00FC');
|
ENTITIES.put("ucirc", '\u00FB');
|
||||||
ENTITIES.put("yacute", '\u00FD');
|
ENTITIES.put("uuml", '\u00FC');
|
||||||
ENTITIES.put("thorn", '\u00FE');
|
ENTITIES.put("yacute", '\u00FD');
|
||||||
ENTITIES.put("yuml", '\u00FF');
|
ENTITIES.put("thorn", '\u00FE');
|
||||||
ENTITIES.put("OElig", '\u0152');
|
ENTITIES.put("yuml", '\u00FF');
|
||||||
ENTITIES.put("oelig", '\u0153');
|
ENTITIES.put("OElig", '\u0152');
|
||||||
ENTITIES.put("Scaron", '\u0160');
|
ENTITIES.put("oelig", '\u0153');
|
||||||
ENTITIES.put("scaron", '\u0161');
|
ENTITIES.put("Scaron", '\u0160');
|
||||||
ENTITIES.put("Yuml", '\u0178');
|
ENTITIES.put("scaron", '\u0161');
|
||||||
ENTITIES.put("fnof", '\u0192');
|
ENTITIES.put("Yuml", '\u0178');
|
||||||
ENTITIES.put("circ", '\u02C6');
|
ENTITIES.put("fnof", '\u0192');
|
||||||
ENTITIES.put("tilde", '\u02DC');
|
ENTITIES.put("circ", '\u02C6');
|
||||||
ENTITIES.put("Alpha", '\u0391');
|
ENTITIES.put("tilde", '\u02DC');
|
||||||
ENTITIES.put("Beta", '\u0392');
|
ENTITIES.put("Alpha", '\u0391');
|
||||||
ENTITIES.put("Gamma", '\u0393');
|
ENTITIES.put("Beta", '\u0392');
|
||||||
ENTITIES.put("Delta", '\u0394');
|
ENTITIES.put("Gamma", '\u0393');
|
||||||
ENTITIES.put("Epsilon", '\u0395');
|
ENTITIES.put("Delta", '\u0394');
|
||||||
ENTITIES.put("Zeta", '\u0396');
|
ENTITIES.put("Epsilon", '\u0395');
|
||||||
ENTITIES.put("Eta", '\u0397');
|
ENTITIES.put("Zeta", '\u0396');
|
||||||
ENTITIES.put("Theta", '\u0398');
|
ENTITIES.put("Eta", '\u0397');
|
||||||
ENTITIES.put("Iota", '\u0399');
|
ENTITIES.put("Theta", '\u0398');
|
||||||
ENTITIES.put("Kappa", '\u039A');
|
ENTITIES.put("Iota", '\u0399');
|
||||||
ENTITIES.put("Lambda", '\u039B');
|
ENTITIES.put("Kappa", '\u039A');
|
||||||
ENTITIES.put("Mu", '\u039C');
|
ENTITIES.put("Lambda", '\u039B');
|
||||||
ENTITIES.put("Nu", '\u039D');
|
ENTITIES.put("Mu", '\u039C');
|
||||||
ENTITIES.put("Xi", '\u039E');
|
ENTITIES.put("Nu", '\u039D');
|
||||||
ENTITIES.put("Omicron", '\u039F');
|
ENTITIES.put("Xi", '\u039E');
|
||||||
ENTITIES.put("Pi", '\u03A0');
|
ENTITIES.put("Omicron", '\u039F');
|
||||||
ENTITIES.put("Rho", '\u03A1');
|
ENTITIES.put("Pi", '\u03A0');
|
||||||
ENTITIES.put("Sigma", '\u03A3');
|
ENTITIES.put("Rho", '\u03A1');
|
||||||
ENTITIES.put("Tau", '\u03A4');
|
ENTITIES.put("Sigma", '\u03A3');
|
||||||
ENTITIES.put("Upsilon", '\u03A5');
|
ENTITIES.put("Tau", '\u03A4');
|
||||||
ENTITIES.put("Phi", '\u03A6');
|
ENTITIES.put("Upsilon", '\u03A5');
|
||||||
ENTITIES.put("Chi", '\u03A7');
|
ENTITIES.put("Phi", '\u03A6');
|
||||||
ENTITIES.put("Psi", '\u03A8');
|
ENTITIES.put("Chi", '\u03A7');
|
||||||
ENTITIES.put("Omega", '\u03A9');
|
ENTITIES.put("Psi", '\u03A8');
|
||||||
ENTITIES.put("alpha", '\u03B1');
|
ENTITIES.put("Omega", '\u03A9');
|
||||||
ENTITIES.put("beta", '\u03B2');
|
ENTITIES.put("alpha", '\u03B1');
|
||||||
ENTITIES.put("gamma", '\u03B3');
|
ENTITIES.put("beta", '\u03B2');
|
||||||
ENTITIES.put("delta", '\u03B4');
|
ENTITIES.put("gamma", '\u03B3');
|
||||||
ENTITIES.put("epsilon", '\u03B5');
|
ENTITIES.put("delta", '\u03B4');
|
||||||
ENTITIES.put("zeta", '\u03B6');
|
ENTITIES.put("epsilon", '\u03B5');
|
||||||
ENTITIES.put("eta", '\u03B7');
|
ENTITIES.put("zeta", '\u03B6');
|
||||||
ENTITIES.put("theta", '\u03B8');
|
ENTITIES.put("eta", '\u03B7');
|
||||||
ENTITIES.put("iota", '\u03B9');
|
ENTITIES.put("theta", '\u03B8');
|
||||||
ENTITIES.put("kappa", '\u03BA');
|
ENTITIES.put("iota", '\u03B9');
|
||||||
ENTITIES.put("lambda", '\u03BB');
|
ENTITIES.put("kappa", '\u03BA');
|
||||||
ENTITIES.put("mu", '\u03BC');
|
ENTITIES.put("lambda", '\u03BB');
|
||||||
ENTITIES.put("nu", '\u03BD');
|
ENTITIES.put("mu", '\u03BC');
|
||||||
ENTITIES.put("xi", '\u03BE');
|
ENTITIES.put("nu", '\u03BD');
|
||||||
ENTITIES.put("omicron", '\u03BF');
|
ENTITIES.put("xi", '\u03BE');
|
||||||
ENTITIES.put("pi", '\u03C0');
|
ENTITIES.put("omicron", '\u03BF');
|
||||||
ENTITIES.put("rho", '\u03C1');
|
ENTITIES.put("pi", '\u03C0');
|
||||||
ENTITIES.put("sigmaf", '\u03C2');
|
ENTITIES.put("rho", '\u03C1');
|
||||||
ENTITIES.put("sigma", '\u03C3');
|
ENTITIES.put("sigmaf", '\u03C2');
|
||||||
ENTITIES.put("tau", '\u03C4');
|
ENTITIES.put("sigma", '\u03C3');
|
||||||
ENTITIES.put("upsilon", '\u03C5');
|
ENTITIES.put("tau", '\u03C4');
|
||||||
ENTITIES.put("phi", '\u03C6');
|
ENTITIES.put("upsilon", '\u03C5');
|
||||||
ENTITIES.put("chi", '\u03C7');
|
ENTITIES.put("phi", '\u03C6');
|
||||||
ENTITIES.put("psi", '\u03C8');
|
ENTITIES.put("chi", '\u03C7');
|
||||||
ENTITIES.put("omega", '\u03C9');
|
ENTITIES.put("psi", '\u03C8');
|
||||||
ENTITIES.put("thetasym", '\u03D1');
|
ENTITIES.put("omega", '\u03C9');
|
||||||
ENTITIES.put("upsih", '\u03D2');
|
ENTITIES.put("thetasym", '\u03D1');
|
||||||
ENTITIES.put("piv", '\u03D6');
|
ENTITIES.put("upsih", '\u03D2');
|
||||||
ENTITIES.put("ensp", '\u2002');
|
ENTITIES.put("piv", '\u03D6');
|
||||||
ENTITIES.put("emsp", '\u2003');
|
ENTITIES.put("ensp", '\u2002');
|
||||||
ENTITIES.put("thinsp", '\u2009');
|
ENTITIES.put("emsp", '\u2003');
|
||||||
ENTITIES.put("zwnj", '\u200C');
|
ENTITIES.put("thinsp", '\u2009');
|
||||||
ENTITIES.put("zwj", '\u200D');
|
ENTITIES.put("zwnj", '\u200C');
|
||||||
ENTITIES.put("lrm", '\u200E');
|
ENTITIES.put("zwj", '\u200D');
|
||||||
ENTITIES.put("rlm", '\u200F');
|
ENTITIES.put("lrm", '\u200E');
|
||||||
ENTITIES.put("ndash", '\u2013');
|
ENTITIES.put("rlm", '\u200F');
|
||||||
ENTITIES.put("mdash", '\u2014');
|
ENTITIES.put("ndash", '\u2013');
|
||||||
ENTITIES.put("lsquo", '\u2018');
|
ENTITIES.put("mdash", '\u2014');
|
||||||
ENTITIES.put("rsquo", '\u2019');
|
ENTITIES.put("lsquo", '\u2018');
|
||||||
ENTITIES.put("sbquo", '\u201A');
|
ENTITIES.put("rsquo", '\u2019');
|
||||||
ENTITIES.put("ldquo", '\u201C');
|
ENTITIES.put("sbquo", '\u201A');
|
||||||
ENTITIES.put("rdquo", '\u201D');
|
ENTITIES.put("ldquo", '\u201C');
|
||||||
ENTITIES.put("bdquo", '\u201E');
|
ENTITIES.put("rdquo", '\u201D');
|
||||||
ENTITIES.put("dagger", '\u2020');
|
ENTITIES.put("bdquo", '\u201E');
|
||||||
ENTITIES.put("Dagger", '\u2021');
|
ENTITIES.put("dagger", '\u2020');
|
||||||
ENTITIES.put("bull", '\u2022');
|
ENTITIES.put("Dagger", '\u2021');
|
||||||
ENTITIES.put("hellip", '\u2026');
|
ENTITIES.put("bull", '\u2022');
|
||||||
ENTITIES.put("permil", '\u2030');
|
ENTITIES.put("hellip", '\u2026');
|
||||||
ENTITIES.put("prime", '\u2032');
|
ENTITIES.put("permil", '\u2030');
|
||||||
ENTITIES.put("Prime", '\u2033');
|
ENTITIES.put("prime", '\u2032');
|
||||||
ENTITIES.put("lsaquo", '\u2039');
|
ENTITIES.put("Prime", '\u2033');
|
||||||
ENTITIES.put("rsaquo", '\u203A');
|
ENTITIES.put("lsaquo", '\u2039');
|
||||||
ENTITIES.put("oline", '\u203E');
|
ENTITIES.put("rsaquo", '\u203A');
|
||||||
ENTITIES.put("frasl", '\u2044');
|
ENTITIES.put("oline", '\u203E');
|
||||||
ENTITIES.put("euro", '\u20AC');
|
ENTITIES.put("frasl", '\u2044');
|
||||||
ENTITIES.put("image", '\u2111');
|
ENTITIES.put("euro", '\u20AC');
|
||||||
ENTITIES.put("weierp", '\u2118');
|
ENTITIES.put("image", '\u2111');
|
||||||
ENTITIES.put("real", '\u211C');
|
ENTITIES.put("weierp", '\u2118');
|
||||||
ENTITIES.put("trade", '\u2122');
|
ENTITIES.put("real", '\u211C');
|
||||||
ENTITIES.put("alefsym", '\u2135');
|
ENTITIES.put("trade", '\u2122');
|
||||||
ENTITIES.put("larr", '\u2190');
|
ENTITIES.put("alefsym", '\u2135');
|
||||||
ENTITIES.put("uarr", '\u2191');
|
ENTITIES.put("larr", '\u2190');
|
||||||
ENTITIES.put("rarr", '\u2192');
|
ENTITIES.put("uarr", '\u2191');
|
||||||
ENTITIES.put("darr", '\u2193');
|
ENTITIES.put("rarr", '\u2192');
|
||||||
ENTITIES.put("harr", '\u2194');
|
ENTITIES.put("darr", '\u2193');
|
||||||
ENTITIES.put("crarr", '\u21B5');
|
ENTITIES.put("harr", '\u2194');
|
||||||
ENTITIES.put("lArr", '\u21D0');
|
ENTITIES.put("crarr", '\u21B5');
|
||||||
ENTITIES.put("uArr", '\u21D1');
|
ENTITIES.put("lArr", '\u21D0');
|
||||||
ENTITIES.put("rArr", '\u21D2');
|
ENTITIES.put("uArr", '\u21D1');
|
||||||
ENTITIES.put("dArr", '\u21D3');
|
ENTITIES.put("rArr", '\u21D2');
|
||||||
ENTITIES.put("hArr", '\u21D4');
|
ENTITIES.put("dArr", '\u21D3');
|
||||||
ENTITIES.put("forall", '\u2200');
|
ENTITIES.put("hArr", '\u21D4');
|
||||||
ENTITIES.put("part", '\u2202');
|
ENTITIES.put("forall", '\u2200');
|
||||||
ENTITIES.put("exist", '\u2203');
|
ENTITIES.put("part", '\u2202');
|
||||||
ENTITIES.put("empty", '\u2205');
|
ENTITIES.put("exist", '\u2203');
|
||||||
ENTITIES.put("nabla", '\u2207');
|
ENTITIES.put("empty", '\u2205');
|
||||||
ENTITIES.put("isin", '\u2208');
|
ENTITIES.put("nabla", '\u2207');
|
||||||
ENTITIES.put("notin", '\u2209');
|
ENTITIES.put("isin", '\u2208');
|
||||||
ENTITIES.put("ni", '\u220B');
|
ENTITIES.put("notin", '\u2209');
|
||||||
ENTITIES.put("prod", '\u220F');
|
ENTITIES.put("ni", '\u220B');
|
||||||
ENTITIES.put("sum", '\u2211');
|
ENTITIES.put("prod", '\u220F');
|
||||||
ENTITIES.put("minus", '\u2212');
|
ENTITIES.put("sum", '\u2211');
|
||||||
ENTITIES.put("lowast", '\u2217');
|
ENTITIES.put("minus", '\u2212');
|
||||||
ENTITIES.put("radic", '\u221A');
|
ENTITIES.put("lowast", '\u2217');
|
||||||
ENTITIES.put("prop", '\u221D');
|
ENTITIES.put("radic", '\u221A');
|
||||||
ENTITIES.put("infin", '\u221E');
|
ENTITIES.put("prop", '\u221D');
|
||||||
ENTITIES.put("ang", '\u2220');
|
ENTITIES.put("infin", '\u221E');
|
||||||
ENTITIES.put("and", '\u2227');
|
ENTITIES.put("ang", '\u2220');
|
||||||
ENTITIES.put("or", '\u2228');
|
ENTITIES.put("and", '\u2227');
|
||||||
ENTITIES.put("cap", '\u2229');
|
ENTITIES.put("or", '\u2228');
|
||||||
ENTITIES.put("cup", '\u222A');
|
ENTITIES.put("cap", '\u2229');
|
||||||
ENTITIES.put("'int'", '\u222B');
|
ENTITIES.put("cup", '\u222A');
|
||||||
ENTITIES.put("there4", '\u2234');
|
ENTITIES.put("'int'", '\u222B');
|
||||||
ENTITIES.put("sim", '\u223C');
|
ENTITIES.put("there4", '\u2234');
|
||||||
ENTITIES.put("cong", '\u2245');
|
ENTITIES.put("sim", '\u223C');
|
||||||
ENTITIES.put("asymp", '\u2248');
|
ENTITIES.put("cong", '\u2245');
|
||||||
ENTITIES.put("ne", '\u2260');
|
ENTITIES.put("asymp", '\u2248');
|
||||||
ENTITIES.put("equiv", '\u2261');
|
ENTITIES.put("ne", '\u2260');
|
||||||
ENTITIES.put("le", '\u2264');
|
ENTITIES.put("equiv", '\u2261');
|
||||||
ENTITIES.put("ge", '\u2265');
|
ENTITIES.put("le", '\u2264');
|
||||||
ENTITIES.put("sub", '\u2282');
|
ENTITIES.put("ge", '\u2265');
|
||||||
ENTITIES.put("sup", '\u2283');
|
ENTITIES.put("sub", '\u2282');
|
||||||
ENTITIES.put("nsub", '\u2284');
|
ENTITIES.put("sup", '\u2283');
|
||||||
ENTITIES.put("sube", '\u2286');
|
ENTITIES.put("nsub", '\u2284');
|
||||||
ENTITIES.put("supe", '\u2287');
|
ENTITIES.put("sube", '\u2286');
|
||||||
ENTITIES.put("oplus", '\u2295');
|
ENTITIES.put("supe", '\u2287');
|
||||||
ENTITIES.put("otimes", '\u2297');
|
ENTITIES.put("oplus", '\u2295');
|
||||||
ENTITIES.put("perp", '\u22A5');
|
ENTITIES.put("otimes", '\u2297');
|
||||||
ENTITIES.put("sdot", '\u22C5');
|
ENTITIES.put("perp", '\u22A5');
|
||||||
ENTITIES.put("lceil", '\u2308');
|
ENTITIES.put("sdot", '\u22C5');
|
||||||
ENTITIES.put("rceil", '\u2309');
|
ENTITIES.put("lceil", '\u2308');
|
||||||
ENTITIES.put("lfloor", '\u230A');
|
ENTITIES.put("rceil", '\u2309');
|
||||||
ENTITIES.put("rfloor", '\u230B');
|
ENTITIES.put("lfloor", '\u230A');
|
||||||
ENTITIES.put("lang", '\u2329');
|
ENTITIES.put("rfloor", '\u230B');
|
||||||
ENTITIES.put("rang", '\u232A');
|
ENTITIES.put("lang", '\u2329');
|
||||||
ENTITIES.put("loz", '\u25CA');
|
ENTITIES.put("rang", '\u232A');
|
||||||
ENTITIES.put("spades", '\u2660');
|
ENTITIES.put("loz", '\u25CA');
|
||||||
ENTITIES.put("clubs", '\u2663');
|
ENTITIES.put("spades", '\u2660');
|
||||||
ENTITIES.put("hearts", '\u2665');
|
ENTITIES.put("clubs", '\u2663');
|
||||||
ENTITIES.put("diams", '\u2666');
|
ENTITIES.put("hearts", '\u2665');
|
||||||
}
|
ENTITIES.put("diams", '\u2666');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,29 +1,30 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An expression involving an operator and two operands; may be an
|
* An expression involving an operator and two operands; may be an {@link AssignmentExpression}, a
|
||||||
* {@link AssignmentExpression}, a {@link BinaryExpression} or a {@link LogicalExpression}.
|
* {@link BinaryExpression} or a {@link LogicalExpression}.
|
||||||
*/
|
*/
|
||||||
public abstract class ABinaryExpression extends Expression {
|
public abstract class ABinaryExpression extends Expression {
|
||||||
private final String operator;
|
private final String operator;
|
||||||
private final Expression left, right;
|
private final Expression left, right;
|
||||||
|
|
||||||
public ABinaryExpression(SourceLocation loc, String type, String operator, Expression left, Expression right) {
|
public ABinaryExpression(
|
||||||
super(type, loc);
|
SourceLocation loc, String type, String operator, Expression left, Expression right) {
|
||||||
this.operator = operator;
|
super(type, loc);
|
||||||
this.left = left;
|
this.operator = operator;
|
||||||
this.right = right;
|
this.left = left;
|
||||||
}
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
public String getOperator() {
|
public String getOperator() {
|
||||||
return operator;
|
return operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getLeft() {
|
public Expression getLeft() {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getRight() {
|
public Expression getRight() {
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,82 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.INodeWithSymbol;
|
import com.semmle.ts.ast.INodeWithSymbol;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** Common backing class for {@linkplain ClassDeclaration} and {@linkplain ClassExpression}. */
|
||||||
* Common backing class for {@linkplain ClassDeclaration} and {@linkplain ClassExpression}.
|
|
||||||
*/
|
|
||||||
public class AClass implements INodeWithSymbol {
|
public class AClass implements INodeWithSymbol {
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private final List<TypeParameter> typeParameters;
|
private final List<TypeParameter> typeParameters;
|
||||||
private final Expression superClass;
|
private final Expression superClass;
|
||||||
private final List<ITypeExpression> superInterfaces;
|
private final List<ITypeExpression> superInterfaces;
|
||||||
private final ClassBody body;
|
private final ClassBody body;
|
||||||
private final List<Decorator> decorators;
|
private final List<Decorator> decorators;
|
||||||
private int typeSymbol = -1;
|
private int typeSymbol = -1;
|
||||||
|
|
||||||
public AClass(Identifier id, List<TypeParameter> typeParameters, Expression superClass, List<ITypeExpression> superInterfaces,
|
public AClass(
|
||||||
ClassBody body) {
|
Identifier id,
|
||||||
this.id = id;
|
List<TypeParameter> typeParameters,
|
||||||
this.typeParameters = typeParameters;
|
Expression superClass,
|
||||||
this.superClass = superClass;
|
List<ITypeExpression> superInterfaces,
|
||||||
this.superInterfaces = superInterfaces;
|
ClassBody body) {
|
||||||
this.body = body;
|
this.id = id;
|
||||||
this.decorators = new ArrayList<Decorator>();
|
this.typeParameters = typeParameters;
|
||||||
}
|
this.superClass = superClass;
|
||||||
|
this.superInterfaces = superInterfaces;
|
||||||
|
this.body = body;
|
||||||
|
this.decorators = new ArrayList<Decorator>();
|
||||||
|
}
|
||||||
|
|
||||||
public Identifier getId() {
|
public Identifier getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasId() {
|
public boolean hasId() {
|
||||||
return id != null;
|
return id != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TypeParameter> getTypeParameters() {
|
public List<TypeParameter> getTypeParameters() {
|
||||||
return typeParameters;
|
return typeParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasTypeParameters() {
|
public boolean hasTypeParameters() {
|
||||||
return !typeParameters.isEmpty();
|
return !typeParameters.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getSuperClass() {
|
public Expression getSuperClass() {
|
||||||
return superClass;
|
return superClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSuperClass() {
|
public boolean hasSuperClass() {
|
||||||
return superClass != null;
|
return superClass != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ITypeExpression> getSuperInterfaces() {
|
public List<ITypeExpression> getSuperInterfaces() {
|
||||||
return superInterfaces;
|
return superInterfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassBody getBody() {
|
public ClassBody getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDecorators(List<Decorator> decorators) {
|
public void addDecorators(List<Decorator> decorators) {
|
||||||
this.decorators.addAll(decorators);
|
this.decorators.addAll(decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Decorator> getDecorators() {
|
public List<Decorator> getDecorators() {
|
||||||
return decorators;
|
return decorators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public int getSymbol() {
|
||||||
return typeSymbol;
|
return typeSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public void setSymbol(int symbol) {
|
||||||
this.typeSymbol = symbol;
|
this.typeSymbol = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,144 +1,146 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.DecoratorList;
|
import com.semmle.ts.ast.DecoratorList;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AFunction<B> {
|
public class AFunction<B> {
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private final List<IPattern> params, allParams;
|
private final List<IPattern> params, allParams;
|
||||||
private final List<Expression> rawParams, defaults;
|
private final List<Expression> rawParams, defaults;
|
||||||
private final IPattern rest;
|
private final IPattern rest;
|
||||||
private final B body;
|
private final B body;
|
||||||
private final boolean generator, async;
|
private final boolean generator, async;
|
||||||
private final List<TypeParameter> typeParameters;
|
private final List<TypeParameter> typeParameters;
|
||||||
private final ITypeExpression returnType;
|
private final ITypeExpression returnType;
|
||||||
private final List<ITypeExpression> parameterTypes;
|
private final List<ITypeExpression> parameterTypes;
|
||||||
private final ITypeExpression thisParameterType;
|
private final ITypeExpression thisParameterType;
|
||||||
private final List<DecoratorList> parameterDecorators;
|
private final List<DecoratorList> parameterDecorators;
|
||||||
|
|
||||||
public AFunction(Identifier id, List<Expression> params, B body, boolean generator, boolean async,
|
public AFunction(
|
||||||
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, List<DecoratorList> parameterDecorators,
|
Identifier id,
|
||||||
ITypeExpression returnType, ITypeExpression thisParameterType) {
|
List<Expression> params,
|
||||||
this.id = id;
|
B body,
|
||||||
this.params = new ArrayList<IPattern>(params.size());
|
boolean generator,
|
||||||
this.defaults = new ArrayList<Expression>(params.size());
|
boolean async,
|
||||||
this.parameterTypes = parameterTypes;
|
List<TypeParameter> typeParameters,
|
||||||
this.body = body;
|
List<ITypeExpression> parameterTypes,
|
||||||
this.generator = generator;
|
List<DecoratorList> parameterDecorators,
|
||||||
this.async = async;
|
ITypeExpression returnType,
|
||||||
this.rawParams = params;
|
ITypeExpression thisParameterType) {
|
||||||
this.typeParameters = typeParameters;
|
this.id = id;
|
||||||
this.returnType = returnType;
|
this.params = new ArrayList<IPattern>(params.size());
|
||||||
this.thisParameterType = thisParameterType;
|
this.defaults = new ArrayList<Expression>(params.size());
|
||||||
this.parameterDecorators = parameterDecorators;
|
this.parameterTypes = parameterTypes;
|
||||||
|
this.body = body;
|
||||||
|
this.generator = generator;
|
||||||
|
this.async = async;
|
||||||
|
this.rawParams = params;
|
||||||
|
this.typeParameters = typeParameters;
|
||||||
|
this.returnType = returnType;
|
||||||
|
this.thisParameterType = thisParameterType;
|
||||||
|
this.parameterDecorators = parameterDecorators;
|
||||||
|
|
||||||
IPattern rest = null;
|
IPattern rest = null;
|
||||||
for (Expression param : params) {
|
for (Expression param : params) {
|
||||||
if (param instanceof RestElement) {
|
if (param instanceof RestElement) {
|
||||||
rest = (IPattern)((RestElement) param).getArgument();
|
rest = (IPattern) ((RestElement) param).getArgument();
|
||||||
} else if (param instanceof AssignmentPattern) {
|
} else if (param instanceof AssignmentPattern) {
|
||||||
AssignmentPattern ap = (AssignmentPattern) param;
|
AssignmentPattern ap = (AssignmentPattern) param;
|
||||||
this.params.add((IPattern)ap.getLeft());
|
this.params.add((IPattern) ap.getLeft());
|
||||||
this.defaults.add(ap.getRight());
|
this.defaults.add(ap.getRight());
|
||||||
} else {
|
} else {
|
||||||
// workaround for parser bug, which currently (erroneously) accepts
|
// workaround for parser bug, which currently (erroneously) accepts
|
||||||
// async arrow functions with parens around their parameters
|
// async arrow functions with parens around their parameters
|
||||||
param = param.stripParens();
|
param = param.stripParens();
|
||||||
this.params.add((IPattern) param);
|
this.params.add((IPattern) param);
|
||||||
this.defaults.add(null);
|
this.defaults.add(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.rest = rest;
|
this.rest = rest;
|
||||||
|
|
||||||
this.allParams = new ArrayList<IPattern>(this.params);
|
this.allParams = new ArrayList<IPattern>(this.params);
|
||||||
if (rest != null)
|
if (rest != null) this.allParams.add(rest);
|
||||||
this.allParams.add(rest);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this function have a name? */
|
||||||
* Does this function have a name?
|
public boolean hasId() {
|
||||||
*/
|
return id != null;
|
||||||
public boolean hasId() {
|
}
|
||||||
return id != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Identifier getId() {
|
public Identifier getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IPattern> getParams() {
|
public List<IPattern> getParams() {
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDefault(int i) {
|
public boolean hasDefault(int i) {
|
||||||
return i < defaults.size();
|
return i < defaults.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getDefault(int i) {
|
public Expression getDefault(int i) {
|
||||||
if (i >= defaults.size())
|
if (i >= defaults.size()) return null;
|
||||||
return null;
|
return defaults.get(i);
|
||||||
return defaults.get(i);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasRest() {
|
public boolean hasRest() {
|
||||||
return rest != null;
|
return rest != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPattern getRest() {
|
public IPattern getRest() {
|
||||||
return rest;
|
return rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public B getBody() {
|
public B getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGenerator() {
|
public boolean isGenerator() {
|
||||||
return generator;
|
return generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAsync() {
|
public boolean isAsync() {
|
||||||
return async;
|
return async;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IPattern> getAllParams() {
|
public List<IPattern> getAllParams() {
|
||||||
return allParams;
|
return allParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Expression> getRawParams() {
|
public List<Expression> getRawParams() {
|
||||||
return rawParams;
|
return rawParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITypeExpression getReturnType() {
|
public ITypeExpression getReturnType() {
|
||||||
return returnType;
|
return returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasParameterType(int i) {
|
public boolean hasParameterType(int i) {
|
||||||
return getParameterType(i) != null;
|
return getParameterType(i) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITypeExpression getParameterType(int i) {
|
public ITypeExpression getParameterType(int i) {
|
||||||
if (i >= parameterTypes.size())
|
if (i >= parameterTypes.size()) return null;
|
||||||
return null;
|
return parameterTypes.get(i);
|
||||||
return parameterTypes.get(i);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public List<ITypeExpression> getParameterTypes() {
|
public List<ITypeExpression> getParameterTypes() {
|
||||||
return parameterTypes;
|
return parameterTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TypeParameter> getTypeParameters() {
|
public List<TypeParameter> getTypeParameters() {
|
||||||
return typeParameters;
|
return typeParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITypeExpression getThisParameterType() {
|
public ITypeExpression getThisParameterType() {
|
||||||
return thisParameterType;
|
return thisParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DecoratorList> getParameterDecorators() {
|
public List<DecoratorList> getParameterDecorators() {
|
||||||
return parameterDecorators;
|
return parameterDecorators;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,147 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.DecoratorList;
|
import com.semmle.ts.ast.DecoratorList;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function expression, which may be either an {@link ArrowFunctionExpression} or
|
* A function expression, which may be either an {@link ArrowFunctionExpression} or a normal {@link
|
||||||
* a normal {@link FunctionExpression}.
|
* FunctionExpression}.
|
||||||
*/
|
*/
|
||||||
public abstract class AFunctionExpression extends Expression implements IFunction {
|
public abstract class AFunctionExpression extends Expression implements IFunction {
|
||||||
private final AFunction<? extends Node> fn;
|
private final AFunction<? extends Node> fn;
|
||||||
private int symbol = -1;
|
private int symbol = -1;
|
||||||
|
|
||||||
public AFunctionExpression(String type, SourceLocation loc, Identifier id,
|
public AFunctionExpression(
|
||||||
List<Expression> params, Node body, Boolean generator, Boolean async,
|
String type,
|
||||||
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, List<DecoratorList> parameterDecorators,
|
SourceLocation loc,
|
||||||
ITypeExpression returnType, ITypeExpression thisParameterType) {
|
Identifier id,
|
||||||
super(type, loc);
|
List<Expression> params,
|
||||||
this.fn = new AFunction<Node>(id, params, body, generator == Boolean.TRUE, async == Boolean.TRUE, typeParameters, parameterTypes,
|
Node body,
|
||||||
parameterDecorators, returnType, thisParameterType);
|
Boolean generator,
|
||||||
}
|
Boolean async,
|
||||||
|
List<TypeParameter> typeParameters,
|
||||||
|
List<ITypeExpression> parameterTypes,
|
||||||
|
List<DecoratorList> parameterDecorators,
|
||||||
|
ITypeExpression returnType,
|
||||||
|
ITypeExpression thisParameterType) {
|
||||||
|
super(type, loc);
|
||||||
|
this.fn =
|
||||||
|
new AFunction<Node>(
|
||||||
|
id,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator == Boolean.TRUE,
|
||||||
|
async == Boolean.TRUE,
|
||||||
|
typeParameters,
|
||||||
|
parameterTypes,
|
||||||
|
parameterDecorators,
|
||||||
|
returnType,
|
||||||
|
thisParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
public AFunctionExpression(String type, SourceLocation loc, AFunction<? extends Node> fn) {
|
public AFunctionExpression(String type, SourceLocation loc, AFunction<? extends Node> fn) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Identifier getId() { return fn.getId(); }
|
@Override
|
||||||
@Override public List<IPattern> getParams() { return fn.getParams(); }
|
public Identifier getId() {
|
||||||
@Override public boolean hasDefault(int i) { return fn.hasDefault(i); }
|
return fn.getId();
|
||||||
@Override public Expression getDefault(int i) { return fn.getDefault(i); }
|
}
|
||||||
@Override public IPattern getRest() { return fn.getRest(); }
|
|
||||||
@Override public Node getBody() { return fn.getBody(); }
|
|
||||||
@Override public boolean hasRest() { return fn.hasRest(); }
|
|
||||||
public boolean hasId() { return fn.hasId(); }
|
|
||||||
public boolean isGenerator() { return fn.isGenerator(); }
|
|
||||||
public boolean isAsync() { return fn.isAsync(); }
|
|
||||||
public List<IPattern> getAllParams() { return fn.getAllParams(); }
|
|
||||||
@Override public List<Expression> getRawParameters() { return fn.getRawParams(); }
|
|
||||||
public ITypeExpression getReturnType() { return fn.getReturnType(); }
|
|
||||||
public boolean hasParameterType(int i) { return fn.hasParameterType(i); }
|
|
||||||
public ITypeExpression getParameterType(int i) { return fn.getParameterType(i); }
|
|
||||||
public List<ITypeExpression> getParameterTypes() { return fn.getParameterTypes(); }
|
|
||||||
public List<TypeParameter> getTypeParameters() { return fn.getTypeParameters(); }
|
|
||||||
public ITypeExpression getThisParameterType() { return fn.getThisParameterType(); }
|
|
||||||
public List<DecoratorList> getParameterDecorators() { return fn.getParameterDecorators(); }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasDeclareKeyword() {
|
public List<IPattern> getParams() {
|
||||||
return false;
|
return fn.getParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public boolean hasDefault(int i) {
|
||||||
return symbol;
|
return fn.hasDefault(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public Expression getDefault(int i) {
|
||||||
this.symbol = symbol;
|
return fn.getDefault(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPattern getRest() {
|
||||||
|
return fn.getRest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getBody() {
|
||||||
|
return fn.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRest() {
|
||||||
|
return fn.hasRest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasId() {
|
||||||
|
return fn.hasId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGenerator() {
|
||||||
|
return fn.isGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAsync() {
|
||||||
|
return fn.isAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IPattern> getAllParams() {
|
||||||
|
return fn.getAllParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Expression> getRawParameters() {
|
||||||
|
return fn.getRawParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeExpression getReturnType() {
|
||||||
|
return fn.getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasParameterType(int i) {
|
||||||
|
return fn.hasParameterType(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeExpression getParameterType(int i) {
|
||||||
|
return fn.getParameterType(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ITypeExpression> getParameterTypes() {
|
||||||
|
return fn.getParameterTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TypeParameter> getTypeParameters() {
|
||||||
|
return fn.getTypeParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeExpression getThisParameterType() {
|
||||||
|
return fn.getThisParameterType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DecoratorList> getParameterDecorators() {
|
||||||
|
return fn.getParameterDecorators();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDeclareKeyword() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSymbol(int symbol) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,26 +2,22 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An array expression such as <code>[x, , "hello"]</code>. */
|
||||||
* An array expression such as <code>[x, , "hello"]</code>.
|
|
||||||
*/
|
|
||||||
public class ArrayExpression extends Expression {
|
public class ArrayExpression extends Expression {
|
||||||
private final List<Expression> elements;
|
private final List<Expression> elements;
|
||||||
|
|
||||||
public ArrayExpression(SourceLocation loc, List<Expression> elements) {
|
public ArrayExpression(SourceLocation loc, List<Expression> elements) {
|
||||||
super("ArrayExpression", loc);
|
super("ArrayExpression", loc);
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The elements of the array; omitted elements are represented by {@literal null}. */
|
||||||
* The elements of the array; omitted elements are represented by {@literal null}.
|
public List<Expression> getElements() {
|
||||||
*/
|
return elements;
|
||||||
public List<Expression> getElements() {
|
}
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,76 +3,68 @@ package com.semmle.js.ast;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An array pattern as in <code>var [x, y] = z;</code>. */
|
||||||
* An array pattern as in <code>var [x, y] = z;</code>.
|
|
||||||
*/
|
|
||||||
public class ArrayPattern extends Expression implements DestructuringPattern {
|
public class ArrayPattern extends Expression implements DestructuringPattern {
|
||||||
private final List<Expression> elements, rawElements;
|
private final List<Expression> elements, rawElements;
|
||||||
private final List<Expression> defaults;
|
private final List<Expression> defaults;
|
||||||
private final Expression restPattern;
|
private final Expression restPattern;
|
||||||
|
|
||||||
public ArrayPattern(SourceLocation loc, List<Expression> elements) {
|
public ArrayPattern(SourceLocation loc, List<Expression> elements) {
|
||||||
super("ArrayPattern", loc);
|
super("ArrayPattern", loc);
|
||||||
this.rawElements = elements;
|
this.rawElements = elements;
|
||||||
this.elements = new ArrayList<Expression>(elements.size());
|
this.elements = new ArrayList<Expression>(elements.size());
|
||||||
this.defaults = new ArrayList<Expression>(elements.size());
|
this.defaults = new ArrayList<Expression>(elements.size());
|
||||||
Expression rest = null;
|
Expression rest = null;
|
||||||
for (Expression element : elements) {
|
for (Expression element : elements) {
|
||||||
if (element instanceof RestElement) {
|
if (element instanceof RestElement) {
|
||||||
rest = ((RestElement)element).getArgument();
|
rest = ((RestElement) element).getArgument();
|
||||||
} else {
|
} else {
|
||||||
if (element instanceof AssignmentPattern) {
|
if (element instanceof AssignmentPattern) {
|
||||||
AssignmentPattern assgn = (AssignmentPattern) element;
|
AssignmentPattern assgn = (AssignmentPattern) element;
|
||||||
this.defaults.add(assgn.getRight());
|
this.defaults.add(assgn.getRight());
|
||||||
this.elements.add(assgn.getLeft());
|
this.elements.add(assgn.getLeft());
|
||||||
} else {
|
} else {
|
||||||
this.defaults.add(null);
|
this.defaults.add(null);
|
||||||
this.elements.add(element);
|
this.elements.add(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.restPattern = rest;
|
this.restPattern = rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The element patterns of the array pattern; omitted element patterns are
|
* The element patterns of the array pattern; omitted element patterns are represented by
|
||||||
* represented by {@literal null}.
|
* {@literal null}.
|
||||||
*/
|
*/
|
||||||
public List<Expression> getElements() {
|
public List<Expression> getElements() {
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The default expressions for the element patterns of the array pattern. */
|
||||||
* The default expressions for the element patterns of the array pattern.
|
public List<Expression> getDefaults() {
|
||||||
*/
|
return defaults;
|
||||||
public List<Expression> getDefaults() {
|
}
|
||||||
return defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Return the rest pattern of this array pattern, if any. */
|
||||||
* Return the rest pattern of this array pattern, if any.
|
public Expression getRest() {
|
||||||
*/
|
return restPattern;
|
||||||
public Expression getRest() {
|
}
|
||||||
return restPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this array pattern have a rest pattern? */
|
||||||
* Does this array pattern have a rest pattern?
|
public boolean hasRest() {
|
||||||
*/
|
return restPattern != null;
|
||||||
public boolean hasRest() {
|
}
|
||||||
return restPattern != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The raw element patterns of the array pattern; patterns with defaults
|
* The raw element patterns of the array pattern; patterns with defaults are represented as {@link
|
||||||
* are represented as {@link AssignmentPattern}s.
|
* AssignmentPattern}s.
|
||||||
*/
|
*/
|
||||||
public List<Expression> getRawElements() {
|
public List<Expression> getRawElements() {
|
||||||
return rawElements;
|
return rawElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,55 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An arrow function expression such as <code>(x) => x*x</code>. */
|
||||||
* An arrow function expression such as <code>(x) => x*x</code>.
|
|
||||||
*/
|
|
||||||
public class ArrowFunctionExpression extends AFunctionExpression {
|
public class ArrowFunctionExpression extends AFunctionExpression {
|
||||||
public ArrowFunctionExpression(SourceLocation loc,
|
public ArrowFunctionExpression(
|
||||||
List<Expression> params, Node body, Boolean generator, Boolean async) {
|
SourceLocation loc, List<Expression> params, Node body, Boolean generator, Boolean async) {
|
||||||
super("ArrowFunctionExpression", loc, null, params, body, generator, async, Collections.emptyList(), Collections.emptyList(),
|
super(
|
||||||
Collections.emptyList(), null, null);
|
"ArrowFunctionExpression",
|
||||||
}
|
loc,
|
||||||
|
null,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
public ArrowFunctionExpression(SourceLocation loc,
|
public ArrowFunctionExpression(
|
||||||
List<Expression> params, Node body, Boolean generator, Boolean async,
|
SourceLocation loc,
|
||||||
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, ITypeExpression returnType) {
|
List<Expression> params,
|
||||||
super("ArrowFunctionExpression", loc, null, params, body, generator, async, typeParameters, parameterTypes, Collections.emptyList(),
|
Node body,
|
||||||
returnType, null);
|
Boolean generator,
|
||||||
}
|
Boolean async,
|
||||||
|
List<TypeParameter> typeParameters,
|
||||||
|
List<ITypeExpression> parameterTypes,
|
||||||
|
ITypeExpression returnType) {
|
||||||
|
super(
|
||||||
|
"ArrowFunctionExpression",
|
||||||
|
loc,
|
||||||
|
null,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
typeParameters,
|
||||||
|
parameterTypes,
|
||||||
|
Collections.emptyList(),
|
||||||
|
returnType,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** An assignment expression such as <code>x = 23</code> or <code>y += 19</code>. */
|
||||||
* An assignment expression such as <code>x = 23</code> or <code>y += 19</code>.
|
|
||||||
*/
|
|
||||||
public class AssignmentExpression extends ABinaryExpression {
|
public class AssignmentExpression extends ABinaryExpression {
|
||||||
public AssignmentExpression(SourceLocation loc, String operator, Expression left, Expression right) {
|
public AssignmentExpression(
|
||||||
super(loc, "AssignmentExpression", operator, left, right);
|
SourceLocation loc, String operator, Expression left, Expression right) {
|
||||||
}
|
super(loc, "AssignmentExpression", operator, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An assignment pattern occurring in an lvalue position.
|
* An assignment pattern occurring in an lvalue position.
|
||||||
*
|
*
|
||||||
* Assignment patterns specify default values for function parameters, for-in/for-of loop variables and
|
* <p>Assignment patterns specify default values for function parameters, for-in/for-of loop
|
||||||
* in destructuring assignments. We normalise them away during AST construction, attaching information
|
* variables and in destructuring assignments. We normalise them away during AST construction,
|
||||||
* about the default value directly to the parameter or variable in question. Hence, assignment patterns
|
* attaching information about the default value directly to the parameter or variable in question.
|
||||||
* are not expected to appear in the AST the extractor works on.
|
* Hence, assignment patterns are not expected to appear in the AST the extractor works on.
|
||||||
*/
|
*/
|
||||||
public class AssignmentPattern extends ABinaryExpression implements IPattern {
|
public class AssignmentPattern extends ABinaryExpression implements IPattern {
|
||||||
public AssignmentPattern(SourceLocation loc, String operator, Expression left, Expression right) {
|
public AssignmentPattern(SourceLocation loc, String operator, Expression left, Expression right) {
|
||||||
super(loc, "AssignmentPattern", operator, left, right);
|
super(loc, "AssignmentPattern", operator, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
public class AwaitExpression extends Expression {
|
public class AwaitExpression extends Expression {
|
||||||
private Expression argument;
|
private Expression argument;
|
||||||
|
|
||||||
public AwaitExpression(SourceLocation loc, Expression argument) {
|
public AwaitExpression(SourceLocation loc, Expression argument) {
|
||||||
super("AwaitExpression", loc);
|
super("AwaitExpression", loc);
|
||||||
this.argument = argument;
|
this.argument = argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getArgument() {
|
public Expression getArgument() {
|
||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
|
||||||
return v.visit(this, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
|
return v.visit(this, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A binary expression such as <code>x + y</code>. */
|
||||||
* A binary expression such as <code>x + y</code>.
|
|
||||||
*/
|
|
||||||
public class BinaryExpression extends ABinaryExpression {
|
public class BinaryExpression extends ABinaryExpression {
|
||||||
public BinaryExpression(SourceLocation loc, String operator, Expression left, Expression right) {
|
public BinaryExpression(SourceLocation loc, String operator, Expression left, Expression right) {
|
||||||
super(loc, "BinaryExpression", operator, left, right);
|
super(loc, "BinaryExpression", operator, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
public class BindExpression extends Expression {
|
public class BindExpression extends Expression {
|
||||||
private final Expression object, callee;
|
private final Expression object, callee;
|
||||||
|
|
||||||
public BindExpression(SourceLocation loc, Expression object, Expression callee) {
|
public BindExpression(SourceLocation loc, Expression object, Expression callee) {
|
||||||
super("BindExpression", loc);
|
super("BindExpression", loc);
|
||||||
this.object = object;
|
this.object = object;
|
||||||
this.callee = callee;
|
this.callee = callee;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasObject() {
|
public boolean hasObject() {
|
||||||
return object != null;
|
return object != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getObject() {
|
public Expression getObject() {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getCallee() {
|
public Expression getCallee() {
|
||||||
return callee;
|
return callee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,22 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A block statement such as <code>{ console.log("Hi"); }</code>. */
|
||||||
* A block statement such as <code>{ console.log("Hi"); }</code>.
|
|
||||||
*/
|
|
||||||
public class BlockStatement extends Statement {
|
public class BlockStatement extends Statement {
|
||||||
private final List<Statement> body;
|
private final List<Statement> body;
|
||||||
|
|
||||||
public BlockStatement(SourceLocation loc, List<Statement> body) {
|
public BlockStatement(SourceLocation loc, List<Statement> body) {
|
||||||
super("BlockStatement", loc);
|
super("BlockStatement", loc);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The statements in the block. */
|
||||||
* The statements in the block.
|
public List<Statement> getBody() {
|
||||||
*/
|
return body;
|
||||||
public List<Statement> getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A break statement either with a label (<code>break outer;</code>) or without (<code>break;</code>).
|
* A break statement either with a label (<code>break outer;</code>) or without (<code>break;</code>
|
||||||
|
* ).
|
||||||
*/
|
*/
|
||||||
public class BreakStatement extends JumpStatement {
|
public class BreakStatement extends JumpStatement {
|
||||||
public BreakStatement(SourceLocation loc, Identifier label) {
|
public BreakStatement(SourceLocation loc, Identifier label) {
|
||||||
super("BreakStatement", loc, label);
|
super("BreakStatement", loc, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
/** A function call expression such as <code>f(1, 1)</code>. */
|
||||||
|
|
||||||
/**
|
|
||||||
* A function call expression such as <code>f(1, 1)</code>.
|
|
||||||
*/
|
|
||||||
public class CallExpression extends InvokeExpression {
|
public class CallExpression extends InvokeExpression {
|
||||||
public CallExpression(SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments, List<Expression> arguments, Boolean optional, Boolean onOptionalChain) {
|
public CallExpression(
|
||||||
super("CallExpression", loc, callee, typeArguments, arguments, optional, onOptionalChain);
|
SourceLocation loc,
|
||||||
}
|
Expression callee,
|
||||||
|
List<ITypeExpression> typeArguments,
|
||||||
|
List<Expression> arguments,
|
||||||
|
Boolean optional,
|
||||||
|
Boolean onOptionalChain) {
|
||||||
|
super("CallExpression", loc, callee, typeArguments, arguments, optional, onOptionalChain);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,40 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A catch clause with or without a guarding expression. */
|
||||||
* A catch clause with or without a guarding expression.
|
|
||||||
*/
|
|
||||||
public class CatchClause extends Statement {
|
public class CatchClause extends Statement {
|
||||||
private final IPattern param;
|
private final IPattern param;
|
||||||
private final Expression guard;
|
private final Expression guard;
|
||||||
private final BlockStatement body;
|
private final BlockStatement body;
|
||||||
|
|
||||||
public CatchClause(SourceLocation loc, IPattern param, Expression guard, BlockStatement body) {
|
public CatchClause(SourceLocation loc, IPattern param, Expression guard, BlockStatement body) {
|
||||||
super("CatchClause", loc);
|
super("CatchClause", loc);
|
||||||
this.param = param;
|
this.param = param;
|
||||||
this.guard = guard;
|
this.guard = guard;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The parameter of the catch clause. */
|
||||||
* The parameter of the catch clause.
|
public IPattern getParam() {
|
||||||
*/
|
return param;
|
||||||
public IPattern getParam() {
|
}
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this catch clause have a guarding expression? */
|
||||||
* Does this catch clause have a guarding expression?
|
public boolean hasGuard() {
|
||||||
*/
|
return guard != null;
|
||||||
public boolean hasGuard() {
|
}
|
||||||
return guard != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The guarding expression of the catch clause; may be null. */
|
||||||
* The guarding expression of the catch clause; may be null.
|
public Expression getGuard() {
|
||||||
*/
|
return guard;
|
||||||
public Expression getGuard() {
|
}
|
||||||
return guard;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The body of the catch clause. */
|
||||||
* The body of the catch clause.
|
public BlockStatement getBody() {
|
||||||
*/
|
return body;
|
||||||
public BlockStatement getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A chainable expression, such as a member access or function call. */
|
||||||
* A chainable expression, such as a member access or function call.
|
|
||||||
*/
|
|
||||||
public interface Chainable {
|
public interface Chainable {
|
||||||
/**
|
/** Is this step of the chain optional? */
|
||||||
* Is this step of the chain optional?
|
abstract boolean isOptional();
|
||||||
*/
|
|
||||||
abstract boolean isOptional();
|
|
||||||
|
|
||||||
/**
|
/** Is this on an optional chain? */
|
||||||
* Is this on an optional chain?
|
abstract boolean isOnOptionalChain();
|
||||||
*/
|
|
||||||
abstract boolean isOnOptionalChain();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,30 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** The body of a {@linkplain ClassDeclaration} or {@linkplain ClassExpression}. */
|
||||||
* The body of a {@linkplain ClassDeclaration} or {@linkplain ClassExpression}.
|
|
||||||
*/
|
|
||||||
public class ClassBody extends Node {
|
public class ClassBody extends Node {
|
||||||
private final List<MemberDefinition<?>> body;
|
private final List<MemberDefinition<?>> body;
|
||||||
|
|
||||||
public ClassBody(SourceLocation loc, List<MemberDefinition<?>> body) {
|
public ClassBody(SourceLocation loc, List<MemberDefinition<?>> body) {
|
||||||
super("ClassBody", loc);
|
super("ClassBody", loc);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MemberDefinition<?>> getBody() {
|
public List<MemberDefinition<?>> getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMember(MemberDefinition<?> md) {
|
public void addMember(MemberDefinition<?> md) {
|
||||||
body.add(md);
|
body.add(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDefinition getConstructor() {
|
public MethodDefinition getConstructor() {
|
||||||
for (MemberDefinition<?> md : body)
|
for (MemberDefinition<?> md : body) if (md.isConstructor()) return (MethodDefinition) md;
|
||||||
if (md.isConstructor())
|
return null;
|
||||||
return (MethodDefinition) md;
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
|
||||||
return v.visit(this, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
|
return v.visit(this, c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class declaration such as
|
* A class declaration such as
|
||||||
@@ -19,48 +18,61 @@ import com.semmle.ts.ast.TypeParameter;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ClassDeclaration extends Statement {
|
public class ClassDeclaration extends Statement {
|
||||||
private final AClass klass;
|
private final AClass klass;
|
||||||
private final boolean hasDeclareKeyword;
|
private final boolean hasDeclareKeyword;
|
||||||
private final boolean hasAbstractKeyword;
|
private final boolean hasAbstractKeyword;
|
||||||
|
|
||||||
public ClassDeclaration(SourceLocation loc, Identifier id, Expression superClass, ClassBody body) {
|
public ClassDeclaration(
|
||||||
this(loc, id, Collections.emptyList(), superClass, Collections.emptyList(), body, false, false);
|
SourceLocation loc, Identifier id, Expression superClass, ClassBody body) {
|
||||||
}
|
this(loc, id, Collections.emptyList(), superClass, Collections.emptyList(), body, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
public ClassDeclaration(SourceLocation loc, Identifier id, List<TypeParameter> typeParameters, Expression superClass,
|
public ClassDeclaration(
|
||||||
List<ITypeExpression> superInterfaces, ClassBody body, boolean hasDeclareKeyword, boolean hasAbstractKeyword) {
|
SourceLocation loc,
|
||||||
this(loc, new AClass(id, typeParameters, superClass, superInterfaces, body), hasDeclareKeyword, hasAbstractKeyword);
|
Identifier id,
|
||||||
}
|
List<TypeParameter> typeParameters,
|
||||||
|
Expression superClass,
|
||||||
|
List<ITypeExpression> superInterfaces,
|
||||||
|
ClassBody body,
|
||||||
|
boolean hasDeclareKeyword,
|
||||||
|
boolean hasAbstractKeyword) {
|
||||||
|
this(
|
||||||
|
loc,
|
||||||
|
new AClass(id, typeParameters, superClass, superInterfaces, body),
|
||||||
|
hasDeclareKeyword,
|
||||||
|
hasAbstractKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
public ClassDeclaration(SourceLocation loc, AClass klass, boolean hasDeclareKeyword, boolean hasAbstractKeyword) {
|
public ClassDeclaration(
|
||||||
super("ClassDeclaration", loc);
|
SourceLocation loc, AClass klass, boolean hasDeclareKeyword, boolean hasAbstractKeyword) {
|
||||||
this.klass = klass;
|
super("ClassDeclaration", loc);
|
||||||
this.hasDeclareKeyword = hasDeclareKeyword;
|
this.klass = klass;
|
||||||
this.hasAbstractKeyword = hasAbstractKeyword;
|
this.hasDeclareKeyword = hasDeclareKeyword;
|
||||||
}
|
this.hasAbstractKeyword = hasAbstractKeyword;
|
||||||
|
}
|
||||||
|
|
||||||
public AClass getClassDef() {
|
public AClass getClassDef() {
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDecorators(List<Decorator> decorators) {
|
public void addDecorators(List<Decorator> decorators) {
|
||||||
klass.addDecorators(decorators);
|
klass.addDecorators(decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Decorator> getDecorators() {
|
public List<Decorator> getDecorators() {
|
||||||
return klass.getDecorators();
|
return klass.getDecorators();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDeclareKeyword() {
|
public boolean hasDeclareKeyword() {
|
||||||
return hasDeclareKeyword;
|
return hasDeclareKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAbstractKeyword() {
|
public boolean hasAbstractKeyword() {
|
||||||
return hasAbstractKeyword;
|
return hasAbstractKeyword;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class expression as in
|
* A class expression as in
|
||||||
@@ -19,36 +18,41 @@ import com.semmle.ts.ast.TypeParameter;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ClassExpression extends Expression {
|
public class ClassExpression extends Expression {
|
||||||
private final AClass klass;
|
private final AClass klass;
|
||||||
|
|
||||||
public ClassExpression(SourceLocation loc, Identifier id, Expression superClass, ClassBody body) {
|
public ClassExpression(SourceLocation loc, Identifier id, Expression superClass, ClassBody body) {
|
||||||
this(loc, id, Collections.emptyList(), superClass, Collections.emptyList(), body);
|
this(loc, id, Collections.emptyList(), superClass, Collections.emptyList(), body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassExpression(SourceLocation loc, Identifier id, List<TypeParameter> typeParameters, Expression superClass,
|
public ClassExpression(
|
||||||
List<ITypeExpression> superInterfaces, ClassBody body) {
|
SourceLocation loc,
|
||||||
this(loc, new AClass(id, typeParameters, superClass, superInterfaces, body));
|
Identifier id,
|
||||||
}
|
List<TypeParameter> typeParameters,
|
||||||
|
Expression superClass,
|
||||||
|
List<ITypeExpression> superInterfaces,
|
||||||
|
ClassBody body) {
|
||||||
|
this(loc, new AClass(id, typeParameters, superClass, superInterfaces, body));
|
||||||
|
}
|
||||||
|
|
||||||
public ClassExpression(SourceLocation loc, AClass klass) {
|
public ClassExpression(SourceLocation loc, AClass klass) {
|
||||||
super("ClassExpression", loc);
|
super("ClassExpression", loc);
|
||||||
this.klass = klass;
|
this.klass = klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AClass getClassDef() {
|
public AClass getClassDef() {
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDecorators(List<Decorator> decorators) {
|
public void addDecorators(List<Decorator> decorators) {
|
||||||
klass.addDecorators(decorators);
|
klass.addDecorators(decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<Decorator> getDecorators() {
|
public Iterable<Decorator> getDecorators() {
|
||||||
return klass.getDecorators();
|
return klass.getDecorators();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,71 +8,53 @@ import static com.semmle.js.ast.Comment.Kind.LINE;
|
|||||||
/**
|
/**
|
||||||
* A source code comment.
|
* A source code comment.
|
||||||
*
|
*
|
||||||
* This is not part of the SpiderMonkey AST format.
|
* <p>This is not part of the SpiderMonkey AST format.
|
||||||
*/
|
*/
|
||||||
public class Comment extends SourceElement {
|
public class Comment extends SourceElement {
|
||||||
/**
|
/** The kinds of comments recognized by the parser. */
|
||||||
* The kinds of comments recognized by the parser.
|
public static enum Kind {
|
||||||
*/
|
/** A C++-style line comment starting with two slashes. */
|
||||||
public static enum Kind {
|
LINE,
|
||||||
/**
|
|
||||||
* A C++-style line comment starting with two slashes.
|
|
||||||
*/
|
|
||||||
LINE,
|
|
||||||
|
|
||||||
/**
|
/** A C-style block comment starting with slash-star and ending with star-slash. */
|
||||||
* A C-style block comment starting with slash-star and ending with star-slash.
|
BLOCK,
|
||||||
*/
|
|
||||||
BLOCK,
|
|
||||||
|
|
||||||
/**
|
/** The start of an HTML comment (<code><!--</code>). */
|
||||||
* The start of an HTML comment (<code><!--</code>).
|
HTML_START,
|
||||||
*/
|
|
||||||
HTML_START,
|
|
||||||
|
|
||||||
/**
|
/** The end of an HTML comment (<code>--></code>). */
|
||||||
* The end of an HTML comment (<code>--></code>).
|
HTML_END
|
||||||
*/
|
};
|
||||||
HTML_END
|
|
||||||
};
|
|
||||||
|
|
||||||
private final String text;
|
private final String text;
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
|
|
||||||
public Comment(SourceLocation loc, String text) {
|
public Comment(SourceLocation loc, String text) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.text = text;
|
this.text = text;
|
||||||
String raw = getLoc().getSource();
|
String raw = getLoc().getSource();
|
||||||
if (raw.startsWith("//"))
|
if (raw.startsWith("//")) this.kind = LINE;
|
||||||
this.kind = LINE;
|
else if (raw.startsWith("/*")) this.kind = BLOCK;
|
||||||
else if (raw.startsWith("/*"))
|
else if (raw.startsWith("<!--")) this.kind = HTML_START;
|
||||||
this.kind = BLOCK;
|
else this.kind = HTML_END;
|
||||||
else if (raw.startsWith("<!--"))
|
}
|
||||||
this.kind = HTML_START;
|
|
||||||
else
|
|
||||||
this.kind = HTML_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** What kind of comment is this? */
|
||||||
* What kind of comment is this?
|
public Kind getKind() {
|
||||||
*/
|
return kind;
|
||||||
public Kind getKind() {
|
}
|
||||||
return kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this a JSDoc documentation comment? */
|
||||||
* Is this a JSDoc documentation comment?
|
public boolean isDocComment() {
|
||||||
*/
|
return kind == BLOCK && text.startsWith("*");
|
||||||
public boolean isDocComment() {
|
}
|
||||||
return kind == BLOCK && text.startsWith("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text of the comment, not including its delimiters.
|
* The text of the comment, not including its delimiters.
|
||||||
*
|
*
|
||||||
* For documentation comments, the leading asterisk is included.
|
* <p>For documentation comments, the leading asterisk is included.
|
||||||
*/
|
*/
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,35 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A block in a comprehension expression. */
|
||||||
* A block in a comprehension expression.
|
|
||||||
*/
|
|
||||||
public class ComprehensionBlock extends Expression {
|
public class ComprehensionBlock extends Expression {
|
||||||
private final IPattern left;
|
private final IPattern left;
|
||||||
private final Expression right;
|
private final Expression right;
|
||||||
private final boolean of;
|
private final boolean of;
|
||||||
|
|
||||||
public ComprehensionBlock(SourceLocation loc, IPattern left, Expression right, Boolean of) {
|
public ComprehensionBlock(SourceLocation loc, IPattern left, Expression right, Boolean of) {
|
||||||
super("ComprehensionBlock", loc);
|
super("ComprehensionBlock", loc);
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
this.of = of != Boolean.FALSE;
|
this.of = of != Boolean.FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The iterator variable of this comprehension block. */
|
||||||
* The iterator variable of this comprehension block.
|
public IPattern getLeft() {
|
||||||
*/
|
return left;
|
||||||
public IPattern getLeft() {
|
}
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The expression this comprehension block iterates over. */
|
||||||
* The expression this comprehension block iterates over.
|
public Expression getRight() {
|
||||||
*/
|
return right;
|
||||||
public Expression getRight() {
|
}
|
||||||
return right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this a <code>for-of</code> comprehension block? */
|
||||||
* Is this a <code>for-of</code> comprehension block?
|
public boolean isOf() {
|
||||||
*/
|
return of;
|
||||||
public boolean isOf() {
|
}
|
||||||
return of;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,60 +2,53 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A comprehension expression. */
|
||||||
* A comprehension expression.
|
|
||||||
*/
|
|
||||||
public class ComprehensionExpression extends Expression {
|
public class ComprehensionExpression extends Expression {
|
||||||
private final Expression body;
|
private final Expression body;
|
||||||
private final List<ComprehensionBlock> blocks;
|
private final List<ComprehensionBlock> blocks;
|
||||||
private final Expression filter;
|
private final Expression filter;
|
||||||
private final boolean generator;
|
private final boolean generator;
|
||||||
|
|
||||||
public ComprehensionExpression(SourceLocation loc, Expression body, List<ComprehensionBlock> blocks, Expression filter, Boolean generator) {
|
public ComprehensionExpression(
|
||||||
super("ComprehensionExpression", loc);
|
SourceLocation loc,
|
||||||
this.body = body;
|
Expression body,
|
||||||
this.blocks = blocks;
|
List<ComprehensionBlock> blocks,
|
||||||
this.filter = filter;
|
Expression filter,
|
||||||
this.generator = generator == Boolean.TRUE;
|
Boolean generator) {
|
||||||
}
|
super("ComprehensionExpression", loc);
|
||||||
|
this.body = body;
|
||||||
|
this.blocks = blocks;
|
||||||
|
this.filter = filter;
|
||||||
|
this.generator = generator == Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The body expression of this comprehension. */
|
||||||
* The body expression of this comprehension.
|
public Expression getBody() {
|
||||||
*/
|
return body;
|
||||||
public Expression getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The comprehension blocks of this comprehension. */
|
||||||
* The comprehension blocks of this comprehension.
|
public List<ComprehensionBlock> getBlocks() {
|
||||||
*/
|
return blocks;
|
||||||
public List<ComprehensionBlock> getBlocks() {
|
}
|
||||||
return blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this comprehension expression have a filter expression? */
|
||||||
* Does this comprehension expression have a filter expression?
|
public boolean hasFilter() {
|
||||||
*/
|
return filter != null;
|
||||||
public boolean hasFilter() {
|
}
|
||||||
return filter != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The filter expression of this comprehension; may be null. */
|
||||||
* The filter expression of this comprehension; may be null.
|
public Expression getFilter() {
|
||||||
*/
|
return filter;
|
||||||
public Expression getFilter() {
|
}
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this a generator expression? */
|
||||||
* Is this a generator expression?
|
public boolean isGenerator() {
|
||||||
*/
|
return generator;
|
||||||
public boolean isGenerator() {
|
}
|
||||||
return generator;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,35 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A conditional expression such as <code>i >= 0 ? a[i] : null</code>. */
|
||||||
* A conditional expression such as <code>i >= 0 ? a[i] : null</code>.
|
|
||||||
*/
|
|
||||||
public class ConditionalExpression extends Expression {
|
public class ConditionalExpression extends Expression {
|
||||||
private final Expression test;
|
private final Expression test;
|
||||||
private final Expression consequent, alternate;
|
private final Expression consequent, alternate;
|
||||||
|
|
||||||
public ConditionalExpression(SourceLocation loc, Expression test, Expression consequent, Expression alternate) {
|
public ConditionalExpression(
|
||||||
super("ConditionalExpression", loc);
|
SourceLocation loc, Expression test, Expression consequent, Expression alternate) {
|
||||||
this.test = test;
|
super("ConditionalExpression", loc);
|
||||||
this.consequent = consequent;
|
this.test = test;
|
||||||
this.alternate = alternate;
|
this.consequent = consequent;
|
||||||
}
|
this.alternate = alternate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The test expression of this conditional expression. */
|
||||||
* The test expression of this conditional expression.
|
public Expression getTest() {
|
||||||
*/
|
return test;
|
||||||
public Expression getTest() {
|
}
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The then-branch of this conditional expression. */
|
||||||
* The then-branch of this conditional expression.
|
public Expression getConsequent() {
|
||||||
*/
|
return consequent;
|
||||||
public Expression getConsequent() {
|
}
|
||||||
return consequent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The else-branch of this conditional expression. */
|
||||||
* The else-branch of this conditional expression.
|
public Expression getAlternate() {
|
||||||
*/
|
return alternate;
|
||||||
public Expression getAlternate() {
|
}
|
||||||
return alternate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A continue statement either with a label (<code>continue outer;</code>) or without (<code>continue;</code>).
|
* A continue statement either with a label (<code>continue outer;</code>) or without (<code>
|
||||||
|
* continue;</code>).
|
||||||
*/
|
*/
|
||||||
public class ContinueStatement extends JumpStatement {
|
public class ContinueStatement extends JumpStatement {
|
||||||
public ContinueStatement(SourceLocation loc, Identifier label) {
|
public ContinueStatement(SourceLocation loc, Identifier label) {
|
||||||
super("ContinueStatement", loc, label);
|
super("ContinueStatement", loc, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A debugger statement <code>debugger;</code>. */
|
||||||
* A debugger statement <code>debugger;</code>.
|
|
||||||
*/
|
|
||||||
public class DebuggerStatement extends Statement {
|
public class DebuggerStatement extends Statement {
|
||||||
public DebuggerStatement(SourceLocation loc) {
|
public DebuggerStatement(SourceLocation loc) {
|
||||||
super("DebuggerStatement", loc);
|
super("DebuggerStatement", loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,125 +4,145 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines bitmasks where each bit corresponds to a flag on
|
* Defines bitmasks where each bit corresponds to a flag on {@linkplain MemberDefinition} or
|
||||||
* {@linkplain MemberDefinition} or {@linkplain VariableDeclarator}.
|
* {@linkplain VariableDeclarator}.
|
||||||
*/
|
*/
|
||||||
public class DeclarationFlags {
|
public class DeclarationFlags {
|
||||||
public static final int computed = 1 << 0;
|
public static final int computed = 1 << 0;
|
||||||
public static final int abstract_ = 1 << 1;
|
public static final int abstract_ = 1 << 1;
|
||||||
public static final int static_ = 1 << 2;
|
public static final int static_ = 1 << 2;
|
||||||
public static final int readonly = 1 << 3;
|
public static final int readonly = 1 << 3;
|
||||||
public static final int public_ = 1 << 4;
|
public static final int public_ = 1 << 4;
|
||||||
public static final int private_ = 1 << 5;
|
public static final int private_ = 1 << 5;
|
||||||
public static final int protected_ = 1 << 6;
|
public static final int protected_ = 1 << 6;
|
||||||
public static final int optional = 1 << 7;
|
public static final int optional = 1 << 7;
|
||||||
public static final int definiteAssignmentAssertion = 1 << 8;
|
public static final int definiteAssignmentAssertion = 1 << 8;
|
||||||
|
|
||||||
public static final int none = 0;
|
public static final int none = 0;
|
||||||
public static final int numberOfFlags = 9;
|
public static final int numberOfFlags = 9;
|
||||||
|
|
||||||
public static final List<String> names = Arrays.asList("computed", "abstract", "static", "readonly", "public", "private", "protected",
|
public static final List<String> names =
|
||||||
"optional", "definiteAssignmentAssertion");
|
Arrays.asList(
|
||||||
|
"computed",
|
||||||
|
"abstract",
|
||||||
|
"static",
|
||||||
|
"readonly",
|
||||||
|
"public",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"optional",
|
||||||
|
"definiteAssignmentAssertion");
|
||||||
|
|
||||||
public static final List<String> relationNames = Arrays.asList("isComputed", "isAbstractMember", "isStatic", "hasReadonlyKeyword",
|
public static final List<String> relationNames =
|
||||||
"hasPublicKeyword", "hasPrivateKeyword", "hasProtectedKeyword", "isOptionalMember", "hasDefiniteAssignmentAssertion");
|
Arrays.asList(
|
||||||
|
"isComputed",
|
||||||
|
"isAbstractMember",
|
||||||
|
"isStatic",
|
||||||
|
"hasReadonlyKeyword",
|
||||||
|
"hasPublicKeyword",
|
||||||
|
"hasPrivateKeyword",
|
||||||
|
"hasProtectedKeyword",
|
||||||
|
"isOptionalMember",
|
||||||
|
"hasDefiniteAssignmentAssertion");
|
||||||
|
|
||||||
public static boolean isComputed(int flags) {
|
public static boolean isComputed(int flags) {
|
||||||
return (flags & computed) != 0;
|
return (flags & computed) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAbstract(int flags) {
|
public static boolean isAbstract(int flags) {
|
||||||
return (flags & abstract_) != 0;
|
return (flags & abstract_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStatic(int flags) {
|
public static boolean isStatic(int flags) {
|
||||||
return (flags & static_) != 0;
|
return (flags & static_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isReadonly(int flags) {
|
public static boolean isReadonly(int flags) {
|
||||||
return (flags & readonly) != 0;
|
return (flags & readonly) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPublic(int flags) {
|
public static boolean isPublic(int flags) {
|
||||||
return (flags & public_) != 0;
|
return (flags & public_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPrivate(int flags) {
|
public static boolean isPrivate(int flags) {
|
||||||
return (flags & private_) != 0;
|
return (flags & private_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isProtected(int flags) {
|
public static boolean isProtected(int flags) {
|
||||||
return (flags & protected_) != 0;
|
return (flags & protected_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOptional(int flags) {
|
public static boolean isOptional(int flags) {
|
||||||
return (flags & optional) != 0;
|
return (flags & optional) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasDefiniteAssignmentAssertion(int flags) {
|
public static boolean hasDefiniteAssignmentAssertion(int flags) {
|
||||||
return (flags & definiteAssignmentAssertion) != 0;
|
return (flags & definiteAssignmentAssertion) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the computed bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the computed bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getComputed(boolean enable) {
|
public static int getComputed(boolean enable) {
|
||||||
return enable ? computed : 0;
|
return enable ? computed : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the abstract bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the abstract bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getAbstract(boolean enable) {
|
public static int getAbstract(boolean enable) {
|
||||||
return enable ? abstract_ : 0;
|
return enable ? abstract_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the static bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the static bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getStatic(boolean enable) {
|
public static int getStatic(boolean enable) {
|
||||||
return enable ? static_ : 0;
|
return enable ? static_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the public bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the public bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getPublic(boolean enable) {
|
public static int getPublic(boolean enable) {
|
||||||
return enable ? public_ : 0;
|
return enable ? public_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the readonly bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the readonly bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getReadonly(boolean enable) {
|
public static int getReadonly(boolean enable) {
|
||||||
return enable ? readonly : 0;
|
return enable ? readonly : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the private bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the private bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getPrivate(boolean enable) {
|
public static int getPrivate(boolean enable) {
|
||||||
return enable ? private_ : 0;
|
return enable ? private_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the protected bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the protected bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getProtected(boolean enable) {
|
public static int getProtected(boolean enable) {
|
||||||
return enable ? protected_ : 0;
|
return enable ? protected_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the optional bit set to the value of <tt>enable</tt>. */
|
/** Returns a mask with the optional bit set to the value of <tt>enable</tt>. */
|
||||||
public static int getOptional(boolean enable) {
|
public static int getOptional(boolean enable) {
|
||||||
return enable ? optional : 0;
|
return enable ? optional : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mask with the definite assignment assertion bit set to the value of <tt>enable</tt>. */
|
/**
|
||||||
public static int getDefiniteAssignmentAssertion(boolean enable) {
|
* Returns a mask with the definite assignment assertion bit set to the value of <tt>enable</tt>.
|
||||||
return enable ? definiteAssignmentAssertion : 0;
|
*/
|
||||||
}
|
public static int getDefiniteAssignmentAssertion(boolean enable) {
|
||||||
|
return enable ? definiteAssignmentAssertion : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns true if the <tt>n</tt>th bit is set in <tt>flags</tt>. */
|
/** Returns true if the <tt>n</tt>th bit is set in <tt>flags</tt>. */
|
||||||
public static boolean hasNthFlag(int flags, int n) {
|
public static boolean hasNthFlag(int flags, int n) {
|
||||||
return (flags & (1 << n)) != 0;
|
return (flags & (1 << n)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFlagNames(int flags) {
|
public static String getFlagNames(int flags) {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
for (int i = 0; i < numberOfFlags; ++i) {
|
for (int i = 0; i < numberOfFlags; ++i) {
|
||||||
if (hasNthFlag(flags, i)) {
|
if (hasNthFlag(flags, i)) {
|
||||||
if (b.length() > 0) {
|
if (b.length() > 0) {
|
||||||
b.append(", ");
|
b.append(", ");
|
||||||
}
|
}
|
||||||
b.append(names.get(i));
|
b.append(names.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
public class Decorator extends Expression {
|
public class Decorator extends Expression {
|
||||||
private final Expression expression;
|
private final Expression expression;
|
||||||
|
|
||||||
public Decorator(SourceLocation loc, Expression expression) {
|
public Decorator(SourceLocation loc, Expression expression) {
|
||||||
super("Decorator", loc);
|
super("Decorator", loc);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getExpression() {
|
public Expression getExpression() {
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,4 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** An array or object pattern. */
|
||||||
* An array or object pattern.
|
public interface DestructuringPattern extends IPattern {}
|
||||||
*/
|
|
||||||
public interface DestructuringPattern extends IPattern {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A do-while statement of the form <code>do { ... } while(...);</code>. */
|
||||||
* A do-while statement of the form <code>do { ... } while(...);</code>.
|
|
||||||
*/
|
|
||||||
public class DoWhileStatement extends Loop {
|
public class DoWhileStatement extends Loop {
|
||||||
private final Expression test;
|
private final Expression test;
|
||||||
|
|
||||||
public DoWhileStatement(SourceLocation loc, Expression test, Statement body) {
|
public DoWhileStatement(SourceLocation loc, Expression test, Statement body) {
|
||||||
super("DoWhileStatement", loc, body);
|
super("DoWhileStatement", loc, body);
|
||||||
this.test = test;
|
this.test = test;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The test expression of this loop. */
|
||||||
* The test expression of this loop.
|
public Expression getTest() {
|
||||||
*/
|
return test;
|
||||||
public Expression getTest() {
|
}
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node getContinueTarget() {
|
public Node getContinueTarget() {
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
public class DynamicImport extends Expression {
|
public class DynamicImport extends Expression {
|
||||||
private final Expression source;
|
private final Expression source;
|
||||||
|
|
||||||
public DynamicImport(SourceLocation loc, Expression source) {
|
public DynamicImport(SourceLocation loc, Expression source) {
|
||||||
super("DynamicImport", loc);
|
super("DynamicImport", loc);
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getSource() {
|
public Expression getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** An empty statement <code>;</code>. */
|
||||||
* An empty statement <code>;</code>.
|
|
||||||
*/
|
|
||||||
public class EmptyStatement extends Statement {
|
public class EmptyStatement extends Statement {
|
||||||
public EmptyStatement(SourceLocation loc) {
|
public EmptyStatement(SourceLocation loc) {
|
||||||
super("EmptyStatement", loc);
|
super("EmptyStatement", loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,55 +4,49 @@ package com.semmle.js.ast;
|
|||||||
* An enhanced for statement, that is, either a {@link ForInStatement} or a {@link ForOfStatement}.
|
* An enhanced for statement, that is, either a {@link ForInStatement} or a {@link ForOfStatement}.
|
||||||
*/
|
*/
|
||||||
public abstract class EnhancedForStatement extends Loop {
|
public abstract class EnhancedForStatement extends Loop {
|
||||||
private final Node left;
|
private final Node left;
|
||||||
private final Expression defaultValue;
|
private final Expression defaultValue;
|
||||||
private final Expression right;
|
private final Expression right;
|
||||||
|
|
||||||
public EnhancedForStatement(String type, SourceLocation loc, Node left,
|
public EnhancedForStatement(
|
||||||
Expression right, Statement body) {
|
String type, SourceLocation loc, Node left, Expression right, Statement body) {
|
||||||
super(type, loc, body);
|
super(type, loc, body);
|
||||||
if (left instanceof AssignmentPattern) {
|
if (left instanceof AssignmentPattern) {
|
||||||
AssignmentPattern ap = (AssignmentPattern) left;
|
AssignmentPattern ap = (AssignmentPattern) left;
|
||||||
this.left = ap.getLeft();
|
this.left = ap.getLeft();
|
||||||
this.defaultValue = ap.getRight();
|
this.defaultValue = ap.getRight();
|
||||||
} else {
|
} else {
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.defaultValue = null;
|
this.defaultValue = null;
|
||||||
}
|
}
|
||||||
this.right = right;
|
this.right = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The iterator variable of this statement; may be either a {@link VariableDeclaration} statement,
|
* The iterator variable of this statement; may be either a {@link VariableDeclaration} statement,
|
||||||
* or an lvalue {@link Expression}.
|
* or an lvalue {@link Expression}.
|
||||||
*/
|
*/
|
||||||
public Node getLeft() {
|
public Node getLeft() {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Does the iterator variable of this statement have a default value? */
|
||||||
* Does the iterator variable of this statement have a default value?
|
public boolean hasDefaultValue() {
|
||||||
*/
|
return defaultValue != null;
|
||||||
public boolean hasDefaultValue() {
|
}
|
||||||
return defaultValue != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Get the default value of the iterator variable of this statement. */
|
||||||
* Get the default value of the iterator variable of this statement.
|
public Expression getDefaultValue() {
|
||||||
*/
|
return defaultValue;
|
||||||
public Expression getDefaultValue() {
|
}
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The expression this loop iterates over. */
|
||||||
* The expression this loop iterates over.
|
public Expression getRight() {
|
||||||
*/
|
return right;
|
||||||
public Expression getRight() {
|
}
|
||||||
return right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node getContinueTarget() {
|
public Node getContinueTarget() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ package com.semmle.js.ast;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ExportAllDeclaration extends ExportDeclaration {
|
public class ExportAllDeclaration extends ExportDeclaration {
|
||||||
private final Literal source;
|
private final Literal source;
|
||||||
|
|
||||||
public ExportAllDeclaration(SourceLocation loc, Literal source) {
|
public ExportAllDeclaration(SourceLocation loc, Literal source) {
|
||||||
super("ExportAllDeclaration", loc);
|
super("ExportAllDeclaration", loc);
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Literal getSource() {
|
public Literal getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
public abstract class ExportDeclaration extends Statement {
|
public abstract class ExportDeclaration extends Statement {
|
||||||
|
|
||||||
public ExportDeclaration(String type, SourceLocation loc) {
|
public ExportDeclaration(String type, SourceLocation loc) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,23 +14,23 @@ package com.semmle.js.ast;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ExportDefaultDeclaration extends ExportDeclaration {
|
public class ExportDefaultDeclaration extends ExportDeclaration {
|
||||||
/**
|
/**
|
||||||
* Either an {@linkplain Expression} or a {@linkplain FunctionDeclaration} or
|
* Either an {@linkplain Expression} or a {@linkplain FunctionDeclaration} or a {@linkplain
|
||||||
* a {@linkplain ClassDeclaration}.
|
* ClassDeclaration}.
|
||||||
*/
|
*/
|
||||||
private final Node declaration;
|
private final Node declaration;
|
||||||
|
|
||||||
public ExportDefaultDeclaration(SourceLocation loc, Node declaration) {
|
public ExportDefaultDeclaration(SourceLocation loc, Node declaration) {
|
||||||
super("ExportDefaultDeclaration", loc);
|
super("ExportDefaultDeclaration", loc);
|
||||||
this.declaration = declaration;
|
this.declaration = declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node getDeclaration() {
|
public Node getDeclaration() {
|
||||||
return declaration;
|
return declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A default export specifier, such as <code>f</code> in <code>export f from 'foo';</code>. */
|
||||||
* A default export specifier, such as <code>f</code> in
|
|
||||||
* <code>export f from 'foo';</code>.
|
|
||||||
*/
|
|
||||||
public class ExportDefaultSpecifier extends ExportSpecifier {
|
public class ExportDefaultSpecifier extends ExportSpecifier {
|
||||||
public ExportDefaultSpecifier(SourceLocation loc, Identifier exported) {
|
public ExportDefaultSpecifier(SourceLocation loc, Identifier exported) {
|
||||||
super("ExportDefaultSpecifier", loc, null, exported);
|
super("ExportDefaultSpecifier", loc, null, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,45 +6,46 @@ import java.util.List;
|
|||||||
* A named export declaration, which can be of one of the following forms:
|
* A named export declaration, which can be of one of the following forms:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>export var x = 23;</code></li>
|
* <li><code>export var x = 23;</code>
|
||||||
* <li><code>export { x, y } from 'foo';</code></li>
|
* <li><code>export { x, y } from 'foo';</code>
|
||||||
* <li><code>export { x, y };</code></li>
|
* <li><code>export { x, y };</code>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class ExportNamedDeclaration extends ExportDeclaration {
|
public class ExportNamedDeclaration extends ExportDeclaration {
|
||||||
private final Statement declaration;
|
private final Statement declaration;
|
||||||
private final List<ExportSpecifier> specifiers;
|
private final List<ExportSpecifier> specifiers;
|
||||||
private final Literal source;
|
private final Literal source;
|
||||||
|
|
||||||
public ExportNamedDeclaration(SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source) {
|
public ExportNamedDeclaration(
|
||||||
super("ExportNamedDeclaration", loc);
|
SourceLocation loc, Statement declaration, List<ExportSpecifier> specifiers, Literal source) {
|
||||||
this.declaration = declaration;
|
super("ExportNamedDeclaration", loc);
|
||||||
this.specifiers = specifiers;
|
this.declaration = declaration;
|
||||||
this.source = source;
|
this.specifiers = specifiers;
|
||||||
}
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
public Statement getDeclaration() {
|
public Statement getDeclaration() {
|
||||||
return declaration;
|
return declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasDeclaration() {
|
public boolean hasDeclaration() {
|
||||||
return declaration != null;
|
return declaration != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ExportSpecifier> getSpecifiers() {
|
public List<ExportSpecifier> getSpecifiers() {
|
||||||
return specifiers;
|
return specifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Literal getSource() {
|
public Literal getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSource() {
|
public boolean hasSource() {
|
||||||
return source != null;
|
return source != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A namespace export specifier such as <code>* as foo</code> in
|
* A namespace export specifier such as <code>* as foo</code> in <code>export * as foo from 'foo';
|
||||||
* <code>export * as foo from 'foo';</code>.
|
* </code>.
|
||||||
*/
|
*/
|
||||||
public class ExportNamespaceSpecifier extends ExportSpecifier {
|
public class ExportNamespaceSpecifier extends ExportSpecifier {
|
||||||
public ExportNamespaceSpecifier(SourceLocation loc, Identifier exported) {
|
public ExportNamespaceSpecifier(SourceLocation loc, Identifier exported) {
|
||||||
super("ExportNamespaceSpecifier", loc, null, exported);
|
super("ExportNamespaceSpecifier", loc, null, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An export specifier in an {@linkplain ExportNamedDeclaration}; may either be a plain
|
* An export specifier in an {@linkplain ExportNamedDeclaration}; may either be a plain identifier
|
||||||
* identifier <code>x</code>, or a rename export <code>x as y</code>.
|
* <code>x</code>, or a rename export <code>x as y</code>.
|
||||||
*/
|
*/
|
||||||
public class ExportSpecifier extends Expression {
|
public class ExportSpecifier extends Expression {
|
||||||
private final Identifier local, exported;
|
private final Identifier local, exported;
|
||||||
|
|
||||||
public ExportSpecifier(SourceLocation loc, Identifier local, Identifier exported) {
|
public ExportSpecifier(SourceLocation loc, Identifier local, Identifier exported) {
|
||||||
this("ExportSpecifier", loc, local, exported);
|
this("ExportSpecifier", loc, local, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExportSpecifier(String type, SourceLocation loc, Identifier local, Identifier exported) {
|
public ExportSpecifier(String type, SourceLocation loc, Identifier local, Identifier exported) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.local = local;
|
this.local = local;
|
||||||
this.exported = exported == local ? new NodeCopier().copy(exported) : exported;
|
this.exported = exported == local ? new NodeCopier().copy(exported) : exported;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getLocal() {
|
public Identifier getLocal() {
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getExported() {
|
public Identifier getExported() {
|
||||||
return exported;
|
return exported;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,26 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import com.semmle.ts.ast.ITypedAstNode;
|
import com.semmle.ts.ast.ITypedAstNode;
|
||||||
|
|
||||||
/**
|
/** Common superclass of all expressions. */
|
||||||
* Common superclass of all expressions.
|
|
||||||
*/
|
|
||||||
public abstract class Expression extends Node implements ITypedAstNode {
|
public abstract class Expression extends Node implements ITypedAstNode {
|
||||||
private int staticTypeId = -1;
|
private int staticTypeId = -1;
|
||||||
|
|
||||||
public Expression(String type, SourceLocation loc) {
|
public Expression(String type, SourceLocation loc) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** This expression, but with any surrounding parentheses stripped off. */
|
||||||
* This expression, but with any surrounding parentheses stripped off.
|
public Expression stripParens() {
|
||||||
*/
|
return this;
|
||||||
public Expression stripParens() {
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getStaticTypeId() {
|
public int getStaticTypeId() {
|
||||||
return staticTypeId;
|
return staticTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStaticTypeId(int staticTypeId) {
|
public void setStaticTypeId(int staticTypeId) {
|
||||||
this.staticTypeId = staticTypeId;
|
this.staticTypeId = staticTypeId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,21 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** An expression statement such as <code>alert("Hi!");</code>. */
|
||||||
* An expression statement such as <code>alert("Hi!");</code>.
|
|
||||||
*/
|
|
||||||
public class ExpressionStatement extends Statement {
|
public class ExpressionStatement extends Statement {
|
||||||
private final Expression expression;
|
private final Expression expression;
|
||||||
|
|
||||||
public ExpressionStatement(SourceLocation loc, Expression expression) {
|
public ExpressionStatement(SourceLocation loc, Expression expression) {
|
||||||
super("ExpressionStatement", loc);
|
super("ExpressionStatement", loc);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The expression wrapped by this expression statement. */
|
||||||
* The expression wrapped by this expression statement.
|
public Expression getExpression() {
|
||||||
*/
|
return expression;
|
||||||
public Expression getExpression() {
|
}
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,51 +3,60 @@ package com.semmle.js.ast;
|
|||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
|
|
||||||
public class FieldDefinition extends MemberDefinition<Expression> {
|
public class FieldDefinition extends MemberDefinition<Expression> {
|
||||||
private final ITypeExpression typeAnnotation;
|
private final ITypeExpression typeAnnotation;
|
||||||
private final int fieldParameterIndex;
|
private final int fieldParameterIndex;
|
||||||
|
|
||||||
private static final int notFieldParameter = -1;
|
private static final int notFieldParameter = -1;
|
||||||
|
|
||||||
public FieldDefinition(SourceLocation loc, int flags, Expression key, Expression value) {
|
public FieldDefinition(SourceLocation loc, int flags, Expression key, Expression value) {
|
||||||
this(loc, flags, key, value, null);
|
this(loc, flags, key, value, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldDefinition(SourceLocation loc, int flags,
|
public FieldDefinition(
|
||||||
Expression key, Expression value, ITypeExpression typeAnnotation) {
|
SourceLocation loc,
|
||||||
this(loc, flags, key, value, typeAnnotation, notFieldParameter);
|
int flags,
|
||||||
}
|
Expression key,
|
||||||
|
Expression value,
|
||||||
|
ITypeExpression typeAnnotation) {
|
||||||
|
this(loc, flags, key, value, typeAnnotation, notFieldParameter);
|
||||||
|
}
|
||||||
|
|
||||||
public FieldDefinition(SourceLocation loc, int flags, Expression key, Expression value, ITypeExpression typeAnnotation,
|
public FieldDefinition(
|
||||||
int fieldParameterIndex) {
|
SourceLocation loc,
|
||||||
super("FieldDefinition", loc, flags, key, value);
|
int flags,
|
||||||
this.typeAnnotation = typeAnnotation;
|
Expression key,
|
||||||
this.fieldParameterIndex = fieldParameterIndex;
|
Expression value,
|
||||||
}
|
ITypeExpression typeAnnotation,
|
||||||
|
int fieldParameterIndex) {
|
||||||
|
super("FieldDefinition", loc, flags, key, value);
|
||||||
|
this.typeAnnotation = typeAnnotation;
|
||||||
|
this.fieldParameterIndex = fieldParameterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
public ITypeExpression getTypeAnnotation() {
|
public ITypeExpression getTypeAnnotation() {
|
||||||
return typeAnnotation;
|
return typeAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConcrete() {
|
public boolean isConcrete() {
|
||||||
return !isAbstract();
|
return !isAbstract();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isParameterField() {
|
public boolean isParameterField() {
|
||||||
return fieldParameterIndex != notFieldParameter;
|
return fieldParameterIndex != notFieldParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is a field parameter, returns the index of the parameter that
|
* If this is a field parameter, returns the index of the parameter that generated it, or -1 if
|
||||||
* generated it, or -1 if this is not a field parameter.
|
* this is not a field parameter.
|
||||||
*/
|
*/
|
||||||
public int getFieldParameterIndex() {
|
public int getFieldParameterIndex() {
|
||||||
return fieldParameterIndex;
|
return fieldParameterIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,20 @@ package com.semmle.js.ast;
|
|||||||
* This also includes legacy for-each statements.
|
* This also includes legacy for-each statements.
|
||||||
*/
|
*/
|
||||||
public class ForInStatement extends EnhancedForStatement {
|
public class ForInStatement extends EnhancedForStatement {
|
||||||
private final boolean each;
|
private final boolean each;
|
||||||
|
|
||||||
public ForInStatement(SourceLocation loc, Node left, Expression right, Statement body, Boolean each) {
|
public ForInStatement(
|
||||||
super("ForInStatement", loc, left, right, body);
|
SourceLocation loc, Node left, Expression right, Statement body, Boolean each) {
|
||||||
this.each = each == Boolean.TRUE;
|
super("ForInStatement", loc, left, right, body);
|
||||||
}
|
this.each = each == Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEach() {
|
public boolean isEach() {
|
||||||
return each;
|
return each;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,22 +9,22 @@ package com.semmle.js.ast;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ForOfStatement extends EnhancedForStatement {
|
public class ForOfStatement extends EnhancedForStatement {
|
||||||
private boolean isAwait;
|
private boolean isAwait;
|
||||||
|
|
||||||
public ForOfStatement(SourceLocation loc, Node left, Expression right, Statement body) {
|
public ForOfStatement(SourceLocation loc, Node left, Expression right, Statement body) {
|
||||||
super("ForOfStatement", loc, left, right, body);
|
super("ForOfStatement", loc, left, right, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAwait(boolean isAwait) {
|
public void setAwait(boolean isAwait) {
|
||||||
this.isAwait = isAwait;
|
this.isAwait = isAwait;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAwait() {
|
public boolean isAwait() {
|
||||||
return isAwait;
|
return isAwait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,70 +10,59 @@ package com.semmle.js.ast;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ForStatement extends Loop {
|
public class ForStatement extends Loop {
|
||||||
private final Node init;
|
private final Node init;
|
||||||
private final Expression test, update;
|
private final Expression test, update;
|
||||||
|
|
||||||
public ForStatement(SourceLocation loc, Node init, Expression test, Expression update, Statement body) {
|
public ForStatement(
|
||||||
super("ForStatement", loc, body);
|
SourceLocation loc, Node init, Expression test, Expression update, Statement body) {
|
||||||
this.init = init;
|
super("ForStatement", loc, body);
|
||||||
this.test = test;
|
this.init = init;
|
||||||
this.update = update;
|
this.test = test;
|
||||||
}
|
this.update = update;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Does this for statement have an initialization part? */
|
||||||
* Does this for statement have an initialization part?
|
public boolean hasInit() {
|
||||||
*/
|
return init != null;
|
||||||
public boolean hasInit() {
|
}
|
||||||
return init != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The initialization part of this for statement; may be a {@link VariableDeclaration}
|
* The initialization part of this for statement; may be a {@link VariableDeclaration} statement,
|
||||||
* statement, an {@link Expression}, or {@literal null}.
|
* an {@link Expression}, or {@literal null}.
|
||||||
*/
|
*/
|
||||||
public Node getInit() {
|
public Node getInit() {
|
||||||
return init;
|
return init;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Does this for statement have a test? */
|
||||||
* Does this for statement have a test?
|
public boolean hasTest() {
|
||||||
*/
|
return test != null;
|
||||||
public boolean hasTest() {
|
}
|
||||||
return test != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The test expression of this for statement; may be null. */
|
||||||
* The test expression of this for statement; may be null.
|
public Expression getTest() {
|
||||||
*/
|
return test;
|
||||||
public Expression getTest() {
|
}
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this for statement have an update expression? */
|
||||||
* Does this for statement have an update expression?
|
public boolean hasUpdate() {
|
||||||
*/
|
return update != null;
|
||||||
public boolean hasUpdate() {
|
}
|
||||||
return update != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The update expression of this for statement; may be null. */
|
||||||
* The update expression of this for statement; may be null.
|
public Expression getUpdate() {
|
||||||
*/
|
return update;
|
||||||
public Expression getUpdate() {
|
}
|
||||||
return update;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node getContinueTarget() {
|
public Node getContinueTarget() {
|
||||||
if (update != null)
|
if (update != null) return update;
|
||||||
return update;
|
if (test != null) return test;
|
||||||
if (test != null)
|
return body;
|
||||||
return test;
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.DecoratorList;
|
import com.semmle.ts.ast.DecoratorList;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function declaration such as
|
* A function declaration such as
|
||||||
@@ -17,71 +16,173 @@ import com.semmle.ts.ast.TypeParameter;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class FunctionDeclaration extends Statement implements IFunction {
|
public class FunctionDeclaration extends Statement implements IFunction {
|
||||||
private final AFunction<? extends Node> fn;
|
private final AFunction<? extends Node> fn;
|
||||||
private final boolean hasDeclareKeyword;
|
private final boolean hasDeclareKeyword;
|
||||||
private int symbol = -1;
|
private int symbol = -1;
|
||||||
|
|
||||||
public FunctionDeclaration(SourceLocation loc, Identifier id, List<Expression> params, Node body, boolean generator,
|
public FunctionDeclaration(
|
||||||
boolean async) {
|
SourceLocation loc,
|
||||||
this(loc, new AFunction<>(id, params, body, generator, async, Collections.emptyList(), Collections.emptyList(),
|
Identifier id,
|
||||||
Collections.emptyList(), null, null),
|
List<Expression> params,
|
||||||
false);
|
Node body,
|
||||||
}
|
boolean generator,
|
||||||
|
boolean async) {
|
||||||
|
this(
|
||||||
|
loc,
|
||||||
|
new AFunction<>(
|
||||||
|
id,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
null),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
public FunctionDeclaration(SourceLocation loc, Identifier id,
|
public FunctionDeclaration(
|
||||||
List<Expression> params, Node body, boolean generator, boolean async, boolean hasDeclareKeyword,
|
SourceLocation loc,
|
||||||
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, ITypeExpression returnType,
|
Identifier id,
|
||||||
ITypeExpression thisParameterType) {
|
List<Expression> params,
|
||||||
this(loc, new AFunction<>(id, params, body, generator, async, typeParameters, parameterTypes, Collections.emptyList(),
|
Node body,
|
||||||
returnType, thisParameterType), hasDeclareKeyword);
|
boolean generator,
|
||||||
}
|
boolean async,
|
||||||
|
boolean hasDeclareKeyword,
|
||||||
|
List<TypeParameter> typeParameters,
|
||||||
|
List<ITypeExpression> parameterTypes,
|
||||||
|
ITypeExpression returnType,
|
||||||
|
ITypeExpression thisParameterType) {
|
||||||
|
this(
|
||||||
|
loc,
|
||||||
|
new AFunction<>(
|
||||||
|
id,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
typeParameters,
|
||||||
|
parameterTypes,
|
||||||
|
Collections.emptyList(),
|
||||||
|
returnType,
|
||||||
|
thisParameterType),
|
||||||
|
hasDeclareKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
private FunctionDeclaration(SourceLocation loc, AFunction<Node> fn, boolean hasDeclareKeyword) {
|
private FunctionDeclaration(SourceLocation loc, AFunction<Node> fn, boolean hasDeclareKeyword) {
|
||||||
super("FunctionDeclaration", loc);
|
super("FunctionDeclaration", loc);
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.hasDeclareKeyword = hasDeclareKeyword;
|
this.hasDeclareKeyword = hasDeclareKeyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionExpression asFunctionExpression() {
|
public FunctionExpression asFunctionExpression() {
|
||||||
return new FunctionExpression(getLoc(), fn);
|
return new FunctionExpression(getLoc(), fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Identifier getId() { return fn.getId(); }
|
@Override
|
||||||
@Override public List<IPattern> getParams() { return fn.getParams(); }
|
public Identifier getId() {
|
||||||
@Override public boolean hasDefault(int i) { return fn.hasDefault(i); }
|
return fn.getId();
|
||||||
@Override public Expression getDefault(int i) { return fn.getDefault(i); }
|
}
|
||||||
@Override public IPattern getRest() { return fn.getRest(); }
|
|
||||||
@Override public Node getBody() { return fn.getBody(); }
|
|
||||||
@Override public boolean hasRest() { return fn.hasRest(); }
|
|
||||||
public boolean hasId() { return fn.hasId(); }
|
|
||||||
public boolean isGenerator() { return fn.isGenerator(); }
|
|
||||||
public boolean isAsync() { return fn.isAsync(); }
|
|
||||||
public List<IPattern> getAllParams() { return fn.getAllParams(); }
|
|
||||||
@Override public List<Expression> getRawParameters() { return fn.getRawParams(); }
|
|
||||||
public ITypeExpression getReturnType() { return fn.getReturnType(); }
|
|
||||||
@Override public boolean hasParameterType(int i) { return fn.hasParameterType(i); }
|
|
||||||
@Override public ITypeExpression getParameterType(int i) { return fn.getParameterType(i); }
|
|
||||||
public List<ITypeExpression> getParameterTypes() { return fn.getParameterTypes(); }
|
|
||||||
public List<TypeParameter> getTypeParameters() { return fn.getTypeParameters(); }
|
|
||||||
public ITypeExpression getThisParameterType() { return fn.getThisParameterType(); }
|
|
||||||
public List<DecoratorList> getParameterDecorators() { return fn.getParameterDecorators(); }
|
|
||||||
|
|
||||||
public boolean hasDeclareKeyword() {
|
@Override
|
||||||
return hasDeclareKeyword;
|
public List<IPattern> getParams() {
|
||||||
}
|
return fn.getParams();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public boolean hasDefault(int i) {
|
||||||
return this.symbol;
|
return fn.hasDefault(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public Expression getDefault(int i) {
|
||||||
this.symbol = symbol;
|
return fn.getDefault(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPattern getRest() {
|
||||||
|
return fn.getRest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getBody() {
|
||||||
|
return fn.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRest() {
|
||||||
|
return fn.hasRest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasId() {
|
||||||
|
return fn.hasId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGenerator() {
|
||||||
|
return fn.isGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAsync() {
|
||||||
|
return fn.isAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IPattern> getAllParams() {
|
||||||
|
return fn.getAllParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Expression> getRawParameters() {
|
||||||
|
return fn.getRawParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeExpression getReturnType() {
|
||||||
|
return fn.getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasParameterType(int i) {
|
||||||
|
return fn.hasParameterType(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITypeExpression getParameterType(int i) {
|
||||||
|
return fn.getParameterType(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ITypeExpression> getParameterTypes() {
|
||||||
|
return fn.getParameterTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TypeParameter> getTypeParameters() {
|
||||||
|
return fn.getTypeParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeExpression getThisParameterType() {
|
||||||
|
return fn.getThisParameterType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DecoratorList> getParameterDecorators() {
|
||||||
|
return fn.getParameterDecorators();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasDeclareKeyword() {
|
||||||
|
return hasDeclareKeyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSymbol() {
|
||||||
|
return this.symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSymbol(int symbol) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,68 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.DecoratorList;
|
import com.semmle.ts.ast.DecoratorList;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A plain function expression. */
|
||||||
* A plain function expression.
|
|
||||||
*/
|
|
||||||
public class FunctionExpression extends AFunctionExpression {
|
public class FunctionExpression extends AFunctionExpression {
|
||||||
public FunctionExpression(SourceLocation loc, Identifier id,
|
public FunctionExpression(
|
||||||
List<Expression> params, Node body, Boolean generator, Boolean async) {
|
SourceLocation loc,
|
||||||
super("FunctionExpression", loc, id, params, body, generator, async, Collections.emptyList(), Collections.emptyList(),
|
Identifier id,
|
||||||
Collections.emptyList(), null, null);
|
List<Expression> params,
|
||||||
}
|
Node body,
|
||||||
|
Boolean generator,
|
||||||
|
Boolean async) {
|
||||||
|
super(
|
||||||
|
"FunctionExpression",
|
||||||
|
loc,
|
||||||
|
id,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
public FunctionExpression(SourceLocation loc, Identifier id,
|
public FunctionExpression(
|
||||||
List<Expression> params, Node body, Boolean generator, Boolean async,
|
SourceLocation loc,
|
||||||
List<TypeParameter> typeParameters, List<ITypeExpression> parameterTypes, List<DecoratorList> parameterDecorators,
|
Identifier id,
|
||||||
ITypeExpression returnType, ITypeExpression thisParameterType) {
|
List<Expression> params,
|
||||||
super("FunctionExpression", loc, id, params, body, generator, async, typeParameters, parameterTypes, parameterDecorators,
|
Node body,
|
||||||
returnType, thisParameterType);
|
Boolean generator,
|
||||||
}
|
Boolean async,
|
||||||
|
List<TypeParameter> typeParameters,
|
||||||
|
List<ITypeExpression> parameterTypes,
|
||||||
|
List<DecoratorList> parameterDecorators,
|
||||||
|
ITypeExpression returnType,
|
||||||
|
ITypeExpression thisParameterType) {
|
||||||
|
super(
|
||||||
|
"FunctionExpression",
|
||||||
|
loc,
|
||||||
|
id,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
generator,
|
||||||
|
async,
|
||||||
|
typeParameters,
|
||||||
|
parameterTypes,
|
||||||
|
parameterDecorators,
|
||||||
|
returnType,
|
||||||
|
thisParameterType);
|
||||||
|
}
|
||||||
|
|
||||||
public FunctionExpression(SourceLocation loc, AFunction<? extends Node> fn) {
|
public FunctionExpression(SourceLocation loc, AFunction<? extends Node> fn) {
|
||||||
super("FunctionExpression", loc, fn);
|
super("FunctionExpression", loc, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +1,66 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.DecoratorList;
|
import com.semmle.ts.ast.DecoratorList;
|
||||||
import com.semmle.ts.ast.INodeWithSymbol;
|
import com.semmle.ts.ast.INodeWithSymbol;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import com.semmle.ts.ast.TypeParameter;
|
import com.semmle.ts.ast.TypeParameter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A function declaration or expression. */
|
||||||
* A function declaration or expression.
|
|
||||||
*/
|
|
||||||
public interface IFunction extends IStatementContainer, INodeWithSymbol {
|
public interface IFunction extends IStatementContainer, INodeWithSymbol {
|
||||||
/**
|
/** The function name; may be null for function expressions. */
|
||||||
* The function name; may be null for function expressions.
|
public Identifier getId();
|
||||||
*/
|
|
||||||
public Identifier getId();
|
|
||||||
|
|
||||||
/**
|
/** The parameters of the function, not including the rest parameter. */
|
||||||
* The parameters of the function, not including the rest parameter.
|
public List<IPattern> getParams();
|
||||||
*/
|
|
||||||
public List<IPattern> getParams();
|
|
||||||
|
|
||||||
/**
|
/** The parameters of the function, including the rest parameter. */
|
||||||
* The parameters of the function, including the rest parameter.
|
public List<IPattern> getAllParams();
|
||||||
*/
|
|
||||||
public List<IPattern> getAllParams();
|
|
||||||
|
|
||||||
/**
|
/** Does the i'th parameter have a default expression? */
|
||||||
* Does the i'th parameter have a default expression?
|
public boolean hasDefault(int i);
|
||||||
*/
|
|
||||||
public boolean hasDefault(int i);
|
|
||||||
|
|
||||||
/**
|
/** The default expression for the i'th parameter; may be null. */
|
||||||
* The default expression for the i'th parameter; may be null.
|
public Expression getDefault(int i);
|
||||||
*/
|
|
||||||
public Expression getDefault(int i);
|
|
||||||
|
|
||||||
/**
|
/** The rest parameter of this function; may be null. */
|
||||||
* The rest parameter of this function; may be null.
|
public IPattern getRest();
|
||||||
*/
|
|
||||||
public IPattern getRest();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The body of the function; usually a {@link BlockStatement}, but may
|
* The body of the function; usually a {@link BlockStatement}, but may be an {@link Expression}
|
||||||
* be an {@link Expression} for function expressions.
|
* for function expressions.
|
||||||
*/
|
*/
|
||||||
public Node getBody();
|
public Node getBody();
|
||||||
|
|
||||||
/**
|
/** Does this function have a rest parameter? */
|
||||||
* Does this function have a rest parameter?
|
public boolean hasRest();
|
||||||
*/
|
|
||||||
public boolean hasRest();
|
|
||||||
|
|
||||||
/**
|
/** Is this function a generator function? */
|
||||||
* Is this function a generator function?
|
public boolean isGenerator();
|
||||||
*/
|
|
||||||
public boolean isGenerator();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The raw parameters of this function; parameters with defaults are
|
* The raw parameters of this function; parameters with defaults are represented as {@link
|
||||||
* represented as {@link AssignmentPattern}s and the rest parameter
|
* AssignmentPattern}s and the rest parameter (if any) as a {@link RestElement}.
|
||||||
* (if any) as a {@link RestElement}.
|
*/
|
||||||
*/
|
public List<Expression> getRawParameters();
|
||||||
public List<Expression> getRawParameters();
|
|
||||||
|
|
||||||
/**
|
/** Is this function an asynchronous function? */
|
||||||
* Is this function an asynchronous function?
|
public boolean isAsync();
|
||||||
*/
|
|
||||||
public boolean isAsync();
|
|
||||||
|
|
||||||
/**
|
/** The return type of the function, if any. */
|
||||||
* The return type of the function, if any.
|
public ITypeExpression getReturnType();
|
||||||
*/
|
|
||||||
public ITypeExpression getReturnType();
|
|
||||||
|
|
||||||
/**
|
/** Does the i'th parameter have a type annotation? */
|
||||||
* Does the i'th parameter have a type annotation?
|
public boolean hasParameterType(int i);
|
||||||
*/
|
|
||||||
public boolean hasParameterType(int i);
|
|
||||||
|
|
||||||
/**
|
/** The type annotation for the i'th parameter; may be null. */
|
||||||
* The type annotation for the i'th parameter; may be null.
|
public ITypeExpression getParameterType(int i);
|
||||||
*/
|
|
||||||
public ITypeExpression getParameterType(int i);
|
|
||||||
|
|
||||||
public List<TypeParameter> getTypeParameters();
|
public List<TypeParameter> getTypeParameters();
|
||||||
|
|
||||||
public ITypeExpression getThisParameterType();
|
public ITypeExpression getThisParameterType();
|
||||||
|
|
||||||
public List<DecoratorList> getParameterDecorators();
|
public List<DecoratorList> getParameterDecorators();
|
||||||
|
|
||||||
public boolean hasDeclareKeyword();
|
public boolean hasDeclareKeyword();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** The common interface implemented by all AST node types. */
|
||||||
* The common interface implemented by all AST node types.
|
|
||||||
*/
|
|
||||||
public interface INode extends ISourceElement {
|
public interface INode extends ISourceElement {
|
||||||
/**
|
/** Accept a visitor object. */
|
||||||
* Accept a visitor object.
|
public <C, R> R accept(Visitor<C, R> v, C c);
|
||||||
*/
|
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c);
|
|
||||||
|
|
||||||
/**
|
/** Return the node's type tag. */
|
||||||
* Return the node's type tag.
|
public String getType();
|
||||||
*/
|
|
||||||
public String getType();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface encompassing variables ({@link Identifier}) and complex patterns
|
* A marker interface encompassing variables ({@link Identifier}) and complex patterns used in
|
||||||
* used in destructuring assignments ({@link ArrayPattern}, {@link ObjectPattern}).
|
* destructuring assignments ({@link ArrayPattern}, {@link ObjectPattern}).
|
||||||
*/
|
*/
|
||||||
public interface IPattern extends INode {
|
public interface IPattern extends INode {}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A source code element potentially associated with a location. */
|
||||||
* A source code element potentially associated with a location.
|
|
||||||
*/
|
|
||||||
public interface ISourceElement {
|
public interface ISourceElement {
|
||||||
/**
|
/** Get the source location of this element; may be null. */
|
||||||
* Get the source location of this element; may be null.
|
public SourceLocation getLoc();
|
||||||
*/
|
|
||||||
public SourceLocation getLoc();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A statement container, that is, either a {@link Program} or a {@link IFunction}. */
|
||||||
* A statement container, that is, either a {@link Program} or a {@link IFunction}.
|
public interface IStatementContainer extends INode {}
|
||||||
*/
|
|
||||||
public interface IStatementContainer extends INode {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,40 +6,37 @@ import com.semmle.ts.ast.ITypeExpression;
|
|||||||
/**
|
/**
|
||||||
* An identifier.
|
* An identifier.
|
||||||
*
|
*
|
||||||
* Identifiers can either be variable declarations (like <code>x</code> in <code>var x;</code>),
|
* <p>Identifiers can either be variable declarations (like <code>x</code> in <code>var x;</code>),
|
||||||
* variable references (like <code>x</code> in <code>x = 42</code>), property names
|
* variable references (like <code>x</code> in <code>x = 42</code>), property names (like <code>f
|
||||||
* (like <code>f</code> in <code>e.f</code>), statement labels (like <code>l</code> in
|
* </code> in <code>e.f</code>), statement labels (like <code>l</code> in <code>l: while(true);
|
||||||
* <code>l: while(true);</code>), or statement label references (like <code>l</code> in
|
* </code>), or statement label references (like <code>l</code> in <code>break l;</code>).
|
||||||
* <code>break l;</code>).
|
|
||||||
*/
|
*/
|
||||||
public class Identifier extends Expression implements IPattern, ITypeExpression, INodeWithSymbol {
|
public class Identifier extends Expression implements IPattern, ITypeExpression, INodeWithSymbol {
|
||||||
private final String name;
|
private final String name;
|
||||||
private int symbol = -1;
|
private int symbol = -1;
|
||||||
|
|
||||||
public Identifier(SourceLocation loc, String name) {
|
public Identifier(SourceLocation loc, String name) {
|
||||||
super("Identifier", loc);
|
super("Identifier", loc);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The name of this identifier. */
|
||||||
* The name of this identifier.
|
public String getName() {
|
||||||
*/
|
return name;
|
||||||
public String getName() {
|
}
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public int getSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public void setSymbol(int symbol) {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,40 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** An if statement. */
|
||||||
* An if statement.
|
|
||||||
*/
|
|
||||||
public class IfStatement extends Statement {
|
public class IfStatement extends Statement {
|
||||||
private final Expression test;
|
private final Expression test;
|
||||||
private final Statement consequent, alternate;
|
private final Statement consequent, alternate;
|
||||||
|
|
||||||
public IfStatement(SourceLocation loc, Expression test, Statement consequent, Statement alternate) {
|
public IfStatement(
|
||||||
super("IfStatement", loc);
|
SourceLocation loc, Expression test, Statement consequent, Statement alternate) {
|
||||||
this.test = test;
|
super("IfStatement", loc);
|
||||||
this.consequent = consequent;
|
this.test = test;
|
||||||
this.alternate = alternate;
|
this.consequent = consequent;
|
||||||
}
|
this.alternate = alternate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The test expression of this if statement. */
|
||||||
* The test expression of this if statement.
|
public Expression getTest() {
|
||||||
*/
|
return test;
|
||||||
public Expression getTest() {
|
}
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The then-branch of this if statement. */
|
||||||
* The then-branch of this if statement.
|
public Statement getConsequent() {
|
||||||
*/
|
return consequent;
|
||||||
public Statement getConsequent() {
|
}
|
||||||
return consequent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The else-branch of this if statement; may be null. */
|
||||||
* The else-branch of this if statement; may be null.
|
public Statement getAlternate() {
|
||||||
*/
|
return alternate;
|
||||||
public Statement getAlternate() {
|
}
|
||||||
return alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this if statement have an else branch? */
|
||||||
* Does this if statement have an else branch?
|
public boolean hasAlternate() {
|
||||||
*/
|
return alternate != null;
|
||||||
public boolean hasAlternate() {
|
}
|
||||||
return alternate != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,28 +15,28 @@ import java.util.List;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ImportDeclaration extends Statement {
|
public class ImportDeclaration extends Statement {
|
||||||
/** List of import specifiers detailing how declarations are imported; may be empty. */
|
/** List of import specifiers detailing how declarations are imported; may be empty. */
|
||||||
private final List<ImportSpecifier> specifiers;
|
private final List<ImportSpecifier> specifiers;
|
||||||
|
|
||||||
/** The module from which declarations are imported. */
|
/** The module from which declarations are imported. */
|
||||||
private final Literal source;
|
private final Literal source;
|
||||||
|
|
||||||
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source) {
|
public ImportDeclaration(SourceLocation loc, List<ImportSpecifier> specifiers, Literal source) {
|
||||||
super("ImportDeclaration", loc);
|
super("ImportDeclaration", loc);
|
||||||
this.specifiers = specifiers;
|
this.specifiers = specifiers;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Literal getSource() {
|
public Literal getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportSpecifier> getSpecifiers() {
|
public List<ImportSpecifier> getSpecifiers() {
|
||||||
return specifiers;
|
return specifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A default import specifier, such as <code>f</code> in
|
* A default import specifier, such as <code>f</code> in <code>import f, { x, y } from 'foo';</code>
|
||||||
* <code>import f, { x, y } from 'foo';</code>.
|
* .
|
||||||
*
|
*
|
||||||
* Default import specifiers do not have an explicit imported name
|
* <p>Default import specifiers do not have an explicit imported name (the imported name is,
|
||||||
* (the imported name is, implicitly, <code>default</code>).
|
* implicitly, <code>default</code>).
|
||||||
*/
|
*/
|
||||||
public class ImportDefaultSpecifier extends ImportSpecifier {
|
public class ImportDefaultSpecifier extends ImportSpecifier {
|
||||||
public ImportDefaultSpecifier(SourceLocation loc, Identifier local) {
|
public ImportDefaultSpecifier(SourceLocation loc, Identifier local) {
|
||||||
super("ImportDefaultSpecifier", loc, null, local);
|
super("ImportDefaultSpecifier", loc, null, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A namespace import specifier such as <code>* as foo</code> in
|
* A namespace import specifier such as <code>* as foo</code> in <code>import * as foo from 'foo';
|
||||||
* <code>import * as foo from 'foo';</code>.
|
* </code>.
|
||||||
*
|
*
|
||||||
* Namespace import specifiers do not have an imported name.
|
* <p>Namespace import specifiers do not have an imported name.
|
||||||
*/
|
*/
|
||||||
public class ImportNamespaceSpecifier extends ImportSpecifier {
|
public class ImportNamespaceSpecifier extends ImportSpecifier {
|
||||||
public ImportNamespaceSpecifier(SourceLocation loc, Identifier local) {
|
public ImportNamespaceSpecifier(SourceLocation loc, Identifier local) {
|
||||||
super("ImportNamespaceSpecifier", loc, null, local);
|
super("ImportNamespaceSpecifier", loc, null, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An import specifier such as <code>x</code> and <code>y as z</code> in
|
* An import specifier such as <code>x</code> and <code>y as z</code> in <code>
|
||||||
* <code>import { x, y as z } from 'foo';</code>.
|
* import { x, y as z } from 'foo';</code>.
|
||||||
*
|
*
|
||||||
* An import specifier has a local name and an imported name; for instance,
|
* <p>An import specifier has a local name and an imported name; for instance, <code>y as z</code>
|
||||||
* <code>y as z</code> has local name <code>z</code> and imported name <code>y</code>,
|
* has local name <code>z</code> and imported name <code>y</code>, while <code>x</code> has both
|
||||||
* while <code>x</code> has both local and imported name <code>x</code>.
|
* local and imported name <code>x</code>.
|
||||||
*/
|
*/
|
||||||
public class ImportSpecifier extends Expression {
|
public class ImportSpecifier extends Expression {
|
||||||
private final Identifier imported, local;
|
private final Identifier imported, local;
|
||||||
|
|
||||||
public ImportSpecifier(SourceLocation loc, Identifier imported, Identifier local) {
|
public ImportSpecifier(SourceLocation loc, Identifier imported, Identifier local) {
|
||||||
this("ImportSpecifier", loc, imported, local);
|
this("ImportSpecifier", loc, imported, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImportSpecifier(String type, SourceLocation loc, Identifier imported, Identifier local) {
|
public ImportSpecifier(String type, SourceLocation loc, Identifier imported, Identifier local) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.imported = imported;
|
this.imported = imported;
|
||||||
this.local = local == imported ? new NodeCopier().copy(local) : local;
|
this.local = local == imported ? new NodeCopier().copy(local) : local;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getImported() {
|
public Identifier getImported() {
|
||||||
return imported;
|
return imported;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getLocal() {
|
public Identifier getLocal() {
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,84 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.semmle.ts.ast.INodeWithSymbol;
|
import com.semmle.ts.ast.INodeWithSymbol;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An invocation, that is, either a {@link CallExpression} or a {@link NewExpression}. */
|
||||||
* An invocation, that is, either a {@link CallExpression} or a {@link NewExpression}.
|
|
||||||
*/
|
|
||||||
public abstract class InvokeExpression extends Expression implements INodeWithSymbol, Chainable {
|
public abstract class InvokeExpression extends Expression implements INodeWithSymbol, Chainable {
|
||||||
private final Expression callee;
|
private final Expression callee;
|
||||||
private final List<ITypeExpression> typeArguments;
|
private final List<ITypeExpression> typeArguments;
|
||||||
private final List<Expression> arguments;
|
private final List<Expression> arguments;
|
||||||
private final boolean optional;
|
private final boolean optional;
|
||||||
private final boolean onOptionalChain;
|
private final boolean onOptionalChain;
|
||||||
private int resolvedSignatureId = -1;
|
private int resolvedSignatureId = -1;
|
||||||
private int overloadIndex = -1;
|
private int overloadIndex = -1;
|
||||||
private int symbol = -1;
|
private int symbol = -1;
|
||||||
|
|
||||||
public InvokeExpression(String type, SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments,
|
public InvokeExpression(
|
||||||
List<Expression> arguments, Boolean optional, Boolean onOptionalChain) {
|
String type,
|
||||||
super(type, loc);
|
SourceLocation loc,
|
||||||
this.callee = callee;
|
Expression callee,
|
||||||
this.typeArguments = typeArguments;
|
List<ITypeExpression> typeArguments,
|
||||||
this.arguments = arguments;
|
List<Expression> arguments,
|
||||||
this.optional = optional == Boolean.TRUE;
|
Boolean optional,
|
||||||
this.onOptionalChain = onOptionalChain == Boolean.TRUE;
|
Boolean onOptionalChain) {
|
||||||
}
|
super(type, loc);
|
||||||
|
this.callee = callee;
|
||||||
|
this.typeArguments = typeArguments;
|
||||||
|
this.arguments = arguments;
|
||||||
|
this.optional = optional == Boolean.TRUE;
|
||||||
|
this.onOptionalChain = onOptionalChain == Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/** The callee expression of this invocation. */
|
||||||
* The callee expression of this invocation.
|
public Expression getCallee() {
|
||||||
*/
|
return callee;
|
||||||
public Expression getCallee() {
|
}
|
||||||
return callee;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The type arguments of this invocation. */
|
||||||
* The type arguments of this invocation.
|
public List<ITypeExpression> getTypeArguments() {
|
||||||
*/
|
return typeArguments;
|
||||||
public List<ITypeExpression> getTypeArguments() {
|
}
|
||||||
return typeArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The argument expressions of this invocation. */
|
||||||
* The argument expressions of this invocation.
|
public List<Expression> getArguments() {
|
||||||
*/
|
return arguments;
|
||||||
public List<Expression> getArguments() {
|
}
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOptional() {
|
public boolean isOptional() {
|
||||||
return optional;
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOnOptionalChain() {
|
public boolean isOnOptionalChain() {
|
||||||
return onOptionalChain;
|
return onOptionalChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getResolvedSignatureId() {
|
public int getResolvedSignatureId() {
|
||||||
return resolvedSignatureId;
|
return resolvedSignatureId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResolvedSignatureId(int resolvedSignatureId) {
|
public void setResolvedSignatureId(int resolvedSignatureId) {
|
||||||
this.resolvedSignatureId = resolvedSignatureId;
|
this.resolvedSignatureId = resolvedSignatureId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOverloadIndex() {
|
public int getOverloadIndex() {
|
||||||
return overloadIndex;
|
return overloadIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOverloadIndex(int overloadIndex) {
|
public void setOverloadIndex(int overloadIndex) {
|
||||||
this.overloadIndex = overloadIndex;
|
this.overloadIndex = overloadIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public int getSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public void setSymbol(int symbol) {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A jump statement, that is, either a {@link BreakStatement} or a {@link ContinueStatement}. */
|
||||||
* A jump statement, that is, either a {@link BreakStatement} or a {@link ContinueStatement}.
|
|
||||||
*/
|
|
||||||
public abstract class JumpStatement extends Statement {
|
public abstract class JumpStatement extends Statement {
|
||||||
private final Identifier label;
|
private final Identifier label;
|
||||||
|
|
||||||
public JumpStatement(String type, SourceLocation loc, Identifier label) {
|
public JumpStatement(String type, SourceLocation loc, Identifier label) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Does this jump have an explicit target label? */
|
||||||
* Does this jump have an explicit target label?
|
public boolean hasLabel() {
|
||||||
*/
|
return label != null;
|
||||||
public boolean hasLabel() {
|
}
|
||||||
return label != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Get the target label of this jump; may be null. */
|
||||||
* Get the target label of this jump; may be null.
|
public Identifier getLabel() {
|
||||||
*/
|
return label;
|
||||||
public Identifier getLabel() {
|
}
|
||||||
return label;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,28 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A labeled statement. */
|
||||||
* A labeled statement.
|
|
||||||
*/
|
|
||||||
public class LabeledStatement extends Statement {
|
public class LabeledStatement extends Statement {
|
||||||
private final Identifier label;
|
private final Identifier label;
|
||||||
private final Statement body;
|
private final Statement body;
|
||||||
|
|
||||||
public LabeledStatement(SourceLocation loc, Identifier label, Statement body) {
|
public LabeledStatement(SourceLocation loc, Identifier label, Statement body) {
|
||||||
super("LabeledStatement", loc);
|
super("LabeledStatement", loc);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The label of the labeled statement. */
|
||||||
* The label of the labeled statement.
|
public Identifier getLabel() {
|
||||||
*/
|
return label;
|
||||||
public Identifier getLabel() {
|
}
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The statement wrapped by this labeled statement. */
|
||||||
* The statement wrapped by this labeled statement.
|
public Statement getBody() {
|
||||||
*/
|
return body;
|
||||||
public Statement getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,29 +2,27 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An old-style let expression of the form <code>let (vardecls) expr</code>. */
|
||||||
* An old-style let expression of the form <code>let (vardecls) expr</code>.
|
|
||||||
*/
|
|
||||||
public class LetExpression extends Expression {
|
public class LetExpression extends Expression {
|
||||||
private final List<VariableDeclarator> head;
|
private final List<VariableDeclarator> head;
|
||||||
private final Expression body;
|
private final Expression body;
|
||||||
|
|
||||||
public LetExpression(SourceLocation loc, List<VariableDeclarator> head, Expression body) {
|
public LetExpression(SourceLocation loc, List<VariableDeclarator> head, Expression body) {
|
||||||
super("LetExpression", loc);
|
super("LetExpression", loc);
|
||||||
this.head = head;
|
this.head = head;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<VariableDeclarator> getHead() {
|
public List<VariableDeclarator> getHead() {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression getBody() {
|
public Expression getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,29 +2,27 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An old-style let statement of the form <code>let(vardecls) stmt</code>. */
|
||||||
* An old-style let statement of the form <code>let(vardecls) stmt</code>.
|
|
||||||
*/
|
|
||||||
public class LetStatement extends Statement {
|
public class LetStatement extends Statement {
|
||||||
private final List<VariableDeclarator> head;
|
private final List<VariableDeclarator> head;
|
||||||
private final Statement body;
|
private final Statement body;
|
||||||
|
|
||||||
public LetStatement(SourceLocation loc, List<VariableDeclarator> head, Statement body) {
|
public LetStatement(SourceLocation loc, List<VariableDeclarator> head, Statement body) {
|
||||||
super("LetStatement", loc);
|
super("LetStatement", loc);
|
||||||
this.head = head;
|
this.head = head;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return v.visit(this, c);
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<VariableDeclarator> getHead() {
|
public List<VariableDeclarator> getHead() {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement getBody() {
|
public Statement getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,92 +5,78 @@ import com.semmle.ts.ast.ITypeExpression;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A literal constant.
|
* A literal constant.
|
||||||
* <p>
|
*
|
||||||
* A <tt>null</tt> literal may occur as a TypeScript type annotation - other
|
* <p>A <tt>null</tt> literal may occur as a TypeScript type annotation - other literals are always
|
||||||
* literals are always expressions.
|
* expressions.
|
||||||
*/
|
*/
|
||||||
public class Literal extends Expression implements ITypeExpression {
|
public class Literal extends Expression implements ITypeExpression {
|
||||||
private final TokenType tokenType;
|
private final TokenType tokenType;
|
||||||
private final Object value;
|
private final Object value;
|
||||||
private final String raw;
|
private final String raw;
|
||||||
|
|
||||||
public Literal(SourceLocation loc, TokenType tokenType, Object value) {
|
public Literal(SourceLocation loc, TokenType tokenType, Object value) {
|
||||||
super("Literal", loc);
|
super("Literal", loc);
|
||||||
|
|
||||||
// for numbers, check whether they can be represented as integers
|
// for numbers, check whether they can be represented as integers
|
||||||
if (value instanceof Double) {
|
if (value instanceof Double) {
|
||||||
Double dvalue = (Double)value;
|
Double dvalue = (Double) value;
|
||||||
if (dvalue >= Long.MIN_VALUE && dvalue <= Long.MAX_VALUE && (dvalue%1) == 0)
|
if (dvalue >= Long.MIN_VALUE && dvalue <= Long.MAX_VALUE && (dvalue % 1) == 0)
|
||||||
value = dvalue.longValue();
|
value = dvalue.longValue();
|
||||||
} else if (value instanceof CharSequence) {
|
} else if (value instanceof CharSequence) {
|
||||||
value = value.toString();
|
value = value.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tokenType = tokenType;
|
this.tokenType = tokenType;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.raw = getLoc().getSource();
|
this.raw = getLoc().getSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The type of the token corresponding to this literal. */
|
||||||
* The type of the token corresponding to this literal.
|
public TokenType getTokenType() {
|
||||||
*/
|
return tokenType;
|
||||||
public TokenType getTokenType() {
|
}
|
||||||
return tokenType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of this literal; may be null if this is a null literal or a literal whose value
|
* The value of this literal; may be null if this is a null literal or a literal whose value
|
||||||
* cannot be represented by the parser.
|
* cannot be represented by the parser.
|
||||||
*/
|
*/
|
||||||
public Object getValue() {
|
public Object getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The source text of this literal. */
|
||||||
* The source text of this literal.
|
public String getRaw() {
|
||||||
*/
|
return raw;
|
||||||
public String getRaw() {
|
}
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this a regular expression literal? */
|
||||||
* Is this a regular expression literal?
|
public boolean isRegExp() {
|
||||||
*/
|
return tokenType == TokenType.regexp;
|
||||||
public boolean isRegExp() {
|
}
|
||||||
return tokenType == TokenType.regexp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The value of this literal expressed as a string. */
|
||||||
* The value of this literal expressed as a string.
|
public String getStringValue() {
|
||||||
*/
|
// regular expressions may have a null value; use the raw value instead
|
||||||
public String getStringValue() {
|
if (isRegExp()) return raw;
|
||||||
// regular expressions may have a null value; use the raw value instead
|
return String.valueOf(value);
|
||||||
if (isRegExp())
|
}
|
||||||
return raw;
|
|
||||||
return String.valueOf(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is the value of this literal falsy? */
|
||||||
* Is the value of this literal falsy?
|
public boolean isFalsy() {
|
||||||
*/
|
if (isRegExp()) return false;
|
||||||
public boolean isFalsy() {
|
return value == null
|
||||||
if (isRegExp())
|
|| value instanceof Number && ((Number) value).intValue() == 0
|
||||||
return false;
|
|| value == Boolean.FALSE
|
||||||
return value == null ||
|
|| value instanceof String && ((String) value).isEmpty();
|
||||||
value instanceof Number && ((Number)value).intValue() == 0 ||
|
}
|
||||||
value == Boolean.FALSE ||
|
|
||||||
value instanceof String && ((String)value).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is the value of this literal truthy? */
|
||||||
* Is the value of this literal truthy?
|
public boolean isTruthy() {
|
||||||
*/
|
return !isFalsy();
|
||||||
public boolean isTruthy() {
|
}
|
||||||
return !isFalsy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ package com.semmle.js.ast;
|
|||||||
* A short-circuiting binary expression, i.e., either <code>&&</code> or <code>||</code>.
|
* A short-circuiting binary expression, i.e., either <code>&&</code> or <code>||</code>.
|
||||||
*/
|
*/
|
||||||
public class LogicalExpression extends ABinaryExpression {
|
public class LogicalExpression extends ABinaryExpression {
|
||||||
public LogicalExpression(SourceLocation loc, String operator, Expression left, Expression right) {
|
public LogicalExpression(SourceLocation loc, String operator, Expression left, Expression right) {
|
||||||
super(loc, "LogicalExpression", operator, left, right);
|
super(loc, "LogicalExpression", operator, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,24 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A loop statement, that is, a {@link WhileStatement}, a {@link DoWhileStatement}, a {@link ForStatement},
|
* A loop statement, that is, a {@link WhileStatement}, a {@link DoWhileStatement}, a {@link
|
||||||
* or a {@link EnhancedForStatement}.
|
* ForStatement}, or a {@link EnhancedForStatement}.
|
||||||
*/
|
*/
|
||||||
public abstract class Loop extends Statement {
|
public abstract class Loop extends Statement {
|
||||||
protected final Statement body;
|
protected final Statement body;
|
||||||
|
|
||||||
public Loop(String type, SourceLocation loc, Statement body) {
|
public Loop(String type, SourceLocation loc, Statement body) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The loop body. */
|
||||||
* The loop body.
|
public final Statement getBody() {
|
||||||
*/
|
return body;
|
||||||
public final Statement getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The child node of this loop where execution resumes after a <code>continue</code> statement.
|
* The child node of this loop where execution resumes after a <code>continue</code> statement.
|
||||||
*/
|
*/
|
||||||
public abstract Node getContinueTarget();
|
public abstract Node getContinueTarget();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,126 +6,119 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* A member definition in a {@linkplain ClassBody}.
|
* A member definition in a {@linkplain ClassBody}.
|
||||||
*
|
*
|
||||||
* A member definition has a name and an optional initial value, whose type is
|
* <p>A member definition has a name and an optional initial value, whose type is given by the type
|
||||||
* given by the type parameter {@code V}.
|
* parameter {@code V}.
|
||||||
*/
|
*/
|
||||||
public abstract class MemberDefinition<V extends Expression> extends Node {
|
public abstract class MemberDefinition<V extends Expression> extends Node {
|
||||||
/**
|
/** A bitmask of flags defined in {@linkplain DeclarationFlags}. */
|
||||||
* A bitmask of flags defined in {@linkplain DeclarationFlags}.
|
private final int flags;
|
||||||
*/
|
|
||||||
private final int flags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the member.
|
* The name of the member.
|
||||||
*
|
*
|
||||||
* If {@link #isComputed()} is false, this must be an {@link Identifier}, otherwise
|
* <p>If {@link #isComputed()} is false, this must be an {@link Identifier}, otherwise it can be
|
||||||
* it can be an arbitrary expression.
|
* an arbitrary expression.
|
||||||
*/
|
*/
|
||||||
private final Expression key;
|
private final Expression key;
|
||||||
|
|
||||||
/** The initial value of the member. */
|
/** The initial value of the member. */
|
||||||
private final V value;
|
private final V value;
|
||||||
|
|
||||||
/** The decorators applied to this member, if any. */
|
/** The decorators applied to this member, if any. */
|
||||||
private final List<Decorator> decorators;
|
private final List<Decorator> decorators;
|
||||||
|
|
||||||
public MemberDefinition(String type, SourceLocation loc, int flags, Expression key, V value) {
|
public MemberDefinition(String type, SourceLocation loc, int flags, Expression key, V value) {
|
||||||
super(type, loc);
|
super(type, loc);
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.decorators = new ArrayList<Decorator>();
|
this.decorators = new ArrayList<Decorator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the flags, as defined by {@linkplain DeclarationFlags}. */
|
/** Returns the flags, as defined by {@linkplain DeclarationFlags}. */
|
||||||
public int getFlags() {
|
public int getFlags() {
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this has the <tt>static</tt> modifier. */
|
/** Returns true if this has the <tt>static</tt> modifier. */
|
||||||
public boolean isStatic() {
|
public boolean isStatic() {
|
||||||
return DeclarationFlags.isStatic(flags);
|
return DeclarationFlags.isStatic(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the member name is computed. */
|
/** Returns true if the member name is computed. */
|
||||||
public boolean isComputed() {
|
public boolean isComputed() {
|
||||||
return DeclarationFlags.isComputed(flags);
|
return DeclarationFlags.isComputed(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this is an abstract member. */
|
/** Returns true if this is an abstract member. */
|
||||||
public boolean isAbstract() {
|
public boolean isAbstract() {
|
||||||
return DeclarationFlags.isAbstract(flags);
|
return DeclarationFlags.isAbstract(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Returns true if has the <tt>public</tt> modifier (not true for implicitly public members). */
|
||||||
* Returns true if has the <tt>public</tt> modifier (not true for implicitly
|
public boolean hasPublicKeyword() {
|
||||||
* public members).
|
return DeclarationFlags.isPublic(flags);
|
||||||
*/
|
}
|
||||||
public boolean hasPublicKeyword() {
|
|
||||||
return DeclarationFlags.isPublic(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if this is a private member. */
|
/** Returns true if this is a private member. */
|
||||||
public boolean hasPrivateKeyword() {
|
public boolean hasPrivateKeyword() {
|
||||||
return DeclarationFlags.isPrivate(flags);
|
return DeclarationFlags.isPrivate(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this is a protected member. */
|
/** Returns true if this is a protected member. */
|
||||||
public boolean hasProtectedKeyword() {
|
public boolean hasProtectedKeyword() {
|
||||||
return DeclarationFlags.isProtected(flags);
|
return DeclarationFlags.isProtected(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this is a readonly member. */
|
/** Returns true if this is a readonly member. */
|
||||||
public boolean hasReadonlyKeyword() {
|
public boolean hasReadonlyKeyword() {
|
||||||
return DeclarationFlags.isReadonly(flags);
|
return DeclarationFlags.isReadonly(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the expression denoting the name of the member, or {@code null} if
|
* Returns the expression denoting the name of the member, or {@code null} if this is a
|
||||||
* this is a call/construct signature.
|
* call/construct signature.
|
||||||
*/
|
*/
|
||||||
public Expression getKey() {
|
public Expression getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V getValue() {
|
public V getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The name of the method, if it can be determined. */
|
/** The name of the method, if it can be determined. */
|
||||||
public String getName() {
|
public String getName() {
|
||||||
if (!isComputed() && key instanceof Identifier)
|
if (!isComputed() && key instanceof Identifier) return ((Identifier) key).getName();
|
||||||
return ((Identifier)key).getName();
|
if (key instanceof Literal) return ((Literal) key).getStringValue();
|
||||||
if (key instanceof Literal)
|
return null;
|
||||||
return ((Literal)key).getStringValue();
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** True if this is a constructor; does not hold for construct signatures. */
|
/** True if this is a constructor; does not hold for construct signatures. */
|
||||||
public boolean isConstructor() {
|
public boolean isConstructor() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True if this is a non-abstract field or a method with a body. */
|
/** True if this is a non-abstract field or a method with a body. */
|
||||||
public abstract boolean isConcrete();
|
public abstract boolean isConcrete();
|
||||||
|
|
||||||
public boolean isCallSignature() {
|
public boolean isCallSignature() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIndexSignature() {
|
public boolean isIndexSignature() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDecorators(List<Decorator> decorators) {
|
public void addDecorators(List<Decorator> decorators) {
|
||||||
this.decorators.addAll(decorators);
|
this.decorators.addAll(decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Decorator> getDecorators() {
|
public List<Decorator> getDecorators() {
|
||||||
return this.decorators;
|
return this.decorators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isParameterField() {
|
public boolean isParameterField() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,69 +3,70 @@ package com.semmle.js.ast;
|
|||||||
import com.semmle.ts.ast.INodeWithSymbol;
|
import com.semmle.ts.ast.INodeWithSymbol;
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
|
|
||||||
/**
|
/** A member expression, either computed (<code>e[f]</code>) or static (<code>e.f</code>). */
|
||||||
* A member expression, either computed (<code>e[f]</code>) or static (<code>e.f</code>).
|
public class MemberExpression extends Expression
|
||||||
*/
|
implements ITypeExpression, INodeWithSymbol, Chainable {
|
||||||
public class MemberExpression extends Expression implements ITypeExpression, INodeWithSymbol, Chainable {
|
private final Expression object, property;
|
||||||
private final Expression object, property;
|
private final boolean computed;
|
||||||
private final boolean computed;
|
private final boolean optional;
|
||||||
private final boolean optional;
|
private final boolean onOptionalChain;
|
||||||
private final boolean onOptionalChain;
|
private int symbol = -1;
|
||||||
private int symbol = -1;
|
|
||||||
|
|
||||||
public MemberExpression(SourceLocation loc, Expression object, Expression property, Boolean computed, Boolean optional, Boolean onOptionalChain) {
|
public MemberExpression(
|
||||||
super("MemberExpression", loc);
|
SourceLocation loc,
|
||||||
this.object = object;
|
Expression object,
|
||||||
this.property = property;
|
Expression property,
|
||||||
this.computed = computed == Boolean.TRUE;
|
Boolean computed,
|
||||||
this.optional = optional == Boolean.TRUE;
|
Boolean optional,
|
||||||
this.onOptionalChain = onOptionalChain == Boolean.TRUE;
|
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
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The base expression of this member expression. */
|
||||||
* The base expression of this member expression.
|
public Expression getObject() {
|
||||||
*/
|
return object;
|
||||||
public Expression getObject() {
|
}
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The property expression of this member expression; for static member expressions this is always
|
* The property expression of this member expression; for static member expressions this is always
|
||||||
* an {@link Identifier}.
|
* an {@link Identifier}.
|
||||||
*/
|
*/
|
||||||
public Expression getProperty() {
|
public Expression getProperty() {
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Is this a computed member expression? */
|
||||||
* Is this a computed member expression?
|
public boolean isComputed() {
|
||||||
*/
|
return computed;
|
||||||
public boolean isComputed() {
|
}
|
||||||
return computed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOptional() {
|
public boolean isOptional() {
|
||||||
return optional;
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOnOptionalChain() {
|
public boolean isOnOptionalChain() {
|
||||||
return onOptionalChain;
|
return onOptionalChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSymbol() {
|
public int getSymbol() {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSymbol(int symbol) {
|
public void setSymbol(int symbol) {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,28 @@ package com.semmle.js.ast;
|
|||||||
/**
|
/**
|
||||||
* A meta property access (cf. ECMAScript 2015 Language Specification, Chapter 12.3.8).
|
* A meta property access (cf. ECMAScript 2015 Language Specification, Chapter 12.3.8).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>Currently the only recognised meta properties are <code>new.target</code> and <code>
|
||||||
* Currently the only recognised meta properties are <code>new.target</code> and
|
* function.sent</code>.
|
||||||
* <code>function.sent</code>.
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
public class MetaProperty extends Expression {
|
public class MetaProperty extends Expression {
|
||||||
private final Identifier meta, property;
|
private final Identifier meta, property;
|
||||||
|
|
||||||
public MetaProperty(SourceLocation loc, Identifier meta, Identifier property) {
|
public MetaProperty(SourceLocation loc, Identifier meta, Identifier property) {
|
||||||
super("MetaProperty", loc);
|
super("MetaProperty", loc);
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
this.property = property;
|
this.property = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getMeta() {
|
public Identifier getMeta() {
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier getProperty() {
|
public Identifier getProperty() {
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,62 +4,73 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MethodDefinition extends MemberDefinition<FunctionExpression> {
|
public class MethodDefinition extends MemberDefinition<FunctionExpression> {
|
||||||
public enum Kind {
|
public enum Kind {
|
||||||
CONSTRUCTOR, METHOD, GET, SET, FUNCTION_CALL_SIGNATURE, CONSTRUCTOR_CALL_SIGNATURE, INDEX_SIGNATURE
|
CONSTRUCTOR,
|
||||||
};
|
METHOD,
|
||||||
|
GET,
|
||||||
|
SET,
|
||||||
|
FUNCTION_CALL_SIGNATURE,
|
||||||
|
CONSTRUCTOR_CALL_SIGNATURE,
|
||||||
|
INDEX_SIGNATURE
|
||||||
|
};
|
||||||
|
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
private final List<FieldDefinition> parameterFields;
|
private final List<FieldDefinition> parameterFields;
|
||||||
|
|
||||||
public MethodDefinition(SourceLocation loc, int flags, Kind kind, Expression key, FunctionExpression value) {
|
public MethodDefinition(
|
||||||
this(loc, flags, kind, key, value, new ArrayList<>());
|
SourceLocation loc, int flags, Kind kind, Expression key, FunctionExpression value) {
|
||||||
}
|
this(loc, flags, kind, key, value, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
public MethodDefinition(SourceLocation loc, int flags, Kind kind, Expression key, FunctionExpression value,
|
public MethodDefinition(
|
||||||
List<FieldDefinition> parameterFields) {
|
SourceLocation loc,
|
||||||
super("MethodDefinition", loc, flags, key, value);
|
int flags,
|
||||||
this.kind = kind;
|
Kind kind,
|
||||||
this.parameterFields = parameterFields;
|
Expression key,
|
||||||
}
|
FunctionExpression value,
|
||||||
|
List<FieldDefinition> parameterFields) {
|
||||||
|
super("MethodDefinition", loc, flags, key, value);
|
||||||
|
this.kind = kind;
|
||||||
|
this.parameterFields = parameterFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Kind getKind() {
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
|
||||||
public Kind getKind() {
|
@Override
|
||||||
return kind;
|
public boolean isCallSignature() {
|
||||||
}
|
return kind == Kind.FUNCTION_CALL_SIGNATURE || kind == Kind.CONSTRUCTOR_CALL_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCallSignature() {
|
public boolean isIndexSignature() {
|
||||||
return kind == Kind.FUNCTION_CALL_SIGNATURE || kind == Kind.CONSTRUCTOR_CALL_SIGNATURE;
|
return kind == Kind.INDEX_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isIndexSignature() {
|
public boolean isConstructor() {
|
||||||
return kind == Kind.INDEX_SIGNATURE;
|
return !isStatic() && !isComputed() && "constructor".equals(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConstructor() {
|
public boolean isConcrete() {
|
||||||
return !isStatic() && !isComputed() && "constructor".equals(getName());
|
return getValue().getBody() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConcrete() {
|
public <C, R> R accept(Visitor<C, R> v, C c) {
|
||||||
return getValue().getBody() != null;
|
return v.visit(this, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public <C, R> R accept(Visitor<C, R> v, C c) {
|
* Returns the parameter fields synthesized for initializing constructor parameters, if this is a
|
||||||
return v.visit(this, c);
|
* constructor, or an empty list otherwise.
|
||||||
}
|
*
|
||||||
|
* <p>The index in this list does not correspond to the parameter index, as there can be ordinary
|
||||||
/**
|
* parameters interleaved with parameter fields.
|
||||||
* Returns the parameter fields synthesized for initializing constructor
|
*/
|
||||||
* parameters, if this is a constructor, or an empty list otherwise.
|
public List<FieldDefinition> getParameterFields() {
|
||||||
* <p>
|
return parameterFields;
|
||||||
* The index in this list does not correspond to the parameter index, as there
|
}
|
||||||
* can be ordinary parameters interleaved with parameter fields.
|
|
||||||
*/
|
|
||||||
public List<FieldDefinition> getParameterFields() {
|
|
||||||
return parameterFields;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
|
import com.semmle.ts.ast.ITypeExpression;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.semmle.ts.ast.ITypeExpression;
|
/** A <code>new</code> expression. */
|
||||||
|
|
||||||
/**
|
|
||||||
* A <code>new</code> expression.
|
|
||||||
*/
|
|
||||||
public class NewExpression extends InvokeExpression {
|
public class NewExpression extends InvokeExpression {
|
||||||
public NewExpression(SourceLocation loc, Expression callee, List<ITypeExpression> typeArguments, List<Expression> arguments) {
|
public NewExpression(
|
||||||
super("NewExpression", loc, callee, typeArguments, arguments, false, false);
|
SourceLocation loc,
|
||||||
}
|
Expression callee,
|
||||||
|
List<ITypeExpression> typeArguments,
|
||||||
|
List<Expression> arguments) {
|
||||||
|
super("NewExpression", loc, callee, typeArguments, arguments, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** Common superclass of all AST node types. */
|
||||||
* Common superclass of all AST node types.
|
|
||||||
*/
|
|
||||||
public abstract class Node extends SourceElement implements INode {
|
public abstract class Node extends SourceElement implements INode {
|
||||||
private final String type;
|
private final String type;
|
||||||
|
|
||||||
public Node(String type, SourceLocation loc) {
|
public Node(String type, SourceLocation loc) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getType() {
|
public final String getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,26 +2,22 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An object literal. */
|
||||||
* An object literal.
|
|
||||||
*/
|
|
||||||
public class ObjectExpression extends Expression {
|
public class ObjectExpression extends Expression {
|
||||||
private final List<Property> properties;
|
private final List<Property> properties;
|
||||||
|
|
||||||
public ObjectExpression(SourceLocation loc, List<Property> properties) {
|
public ObjectExpression(SourceLocation loc, List<Property> properties) {
|
||||||
super("ObjectExpression", loc);
|
super("ObjectExpression", loc);
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The properties in this literal. */
|
||||||
* The properties in this literal.
|
public List<Property> getProperties() {
|
||||||
*/
|
return properties;
|
||||||
public List<Property> getProperties() {
|
}
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,60 +3,52 @@ package com.semmle.js.ast;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** An object pattern. */
|
||||||
* An object pattern.
|
|
||||||
*/
|
|
||||||
public class ObjectPattern extends Expression implements DestructuringPattern {
|
public class ObjectPattern extends Expression implements DestructuringPattern {
|
||||||
private final List<Property> rawProperties, properties;
|
private final List<Property> rawProperties, properties;
|
||||||
private final Expression restPattern;
|
private final Expression restPattern;
|
||||||
|
|
||||||
public ObjectPattern(SourceLocation loc, List<Property> properties) {
|
public ObjectPattern(SourceLocation loc, List<Property> properties) {
|
||||||
super("ObjectPattern", loc);
|
super("ObjectPattern", loc);
|
||||||
this.rawProperties = properties;
|
this.rawProperties = properties;
|
||||||
this.properties = new ArrayList<Property>(properties.size());
|
this.properties = new ArrayList<Property>(properties.size());
|
||||||
Expression rest = null;
|
Expression rest = null;
|
||||||
for (Property prop : properties) {
|
for (Property prop : properties) {
|
||||||
Expression val = prop.getValue();
|
Expression val = prop.getValue();
|
||||||
if (val instanceof RestElement) {
|
if (val instanceof RestElement) {
|
||||||
rest = ((RestElement)val).getArgument();
|
rest = ((RestElement) val).getArgument();
|
||||||
} else {
|
} else {
|
||||||
this.properties.add(prop);
|
this.properties.add(prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.restPattern = rest;
|
this.restPattern = rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The property patterns in this literal. */
|
||||||
* The property patterns in this literal.
|
public List<Property> getProperties() {
|
||||||
*/
|
return properties;
|
||||||
public List<Property> getProperties() {
|
}
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Does this object pattern have a rest pattern? */
|
||||||
* Does this object pattern have a rest pattern?
|
public boolean hasRest() {
|
||||||
*/
|
return restPattern != null;
|
||||||
public boolean hasRest() {
|
}
|
||||||
return restPattern != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The rest pattern of this literal, if any. */
|
||||||
* The rest pattern of this literal, if any.
|
public Expression getRest() {
|
||||||
*/
|
return restPattern;
|
||||||
public Expression getRest() {
|
}
|
||||||
return restPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The raw property patterns in this literal; the rest
|
* The raw property patterns in this literal; the rest pattern (if any) is represented as a {@link
|
||||||
* pattern (if any) is represented as a {@link RestElement}.
|
* RestElement}.
|
||||||
*/
|
*/
|
||||||
public List<Property> getRawProperties() {
|
public List<Property> getRawProperties() {
|
||||||
return rawProperties;
|
return rawProperties;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A parenthesized expression. */
|
||||||
* A parenthesized expression.
|
|
||||||
*/
|
|
||||||
public class ParenthesizedExpression extends Expression {
|
public class ParenthesizedExpression extends Expression {
|
||||||
private final Expression expression;
|
private final Expression expression;
|
||||||
|
|
||||||
public ParenthesizedExpression(SourceLocation loc, Expression expression) {
|
public ParenthesizedExpression(SourceLocation loc, Expression expression) {
|
||||||
super("ParenthesizedExpression", loc);
|
super("ParenthesizedExpression", loc);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The expression between parentheses. */
|
||||||
* The expression between parentheses.
|
public Expression getExpression() {
|
||||||
*/
|
return expression;
|
||||||
public Expression getExpression() {
|
}
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Expression stripParens() {
|
public Expression stripParens() {
|
||||||
return expression.stripParens();
|
return expression.stripParens();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,65 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A source position identifying a single character. */
|
||||||
* A source position identifying a single character.
|
|
||||||
*/
|
|
||||||
public class Position implements Comparable<Position> {
|
public class Position implements Comparable<Position> {
|
||||||
private final int line, column, offset;
|
private final int line, column, offset;
|
||||||
|
|
||||||
public Position(int line, int column, int offset) {
|
public Position(int line, int column, int offset) {
|
||||||
this.line = line;
|
this.line = line;
|
||||||
this.column = column;
|
this.column = column;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The line number (1-based) of this position. */
|
||||||
* The line number (1-based) of this position.
|
public int getLine() {
|
||||||
*/
|
return line;
|
||||||
public int getLine() {
|
}
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The column number (1-based) of this position. */
|
||||||
* The column number (1-based) of this position.
|
public int getColumn() {
|
||||||
*/
|
return column;
|
||||||
public int getColumn() {
|
}
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset (0-based) of this position from the start
|
* The offset (0-based) of this position from the start of the file, that is, the number of
|
||||||
* of the file, that is, the number of characters that
|
* characters that precede it.
|
||||||
* precede it.
|
*/
|
||||||
*/
|
public int getOffset() {
|
||||||
public int getOffset() {
|
return offset;
|
||||||
return offset;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Position that) {
|
public int compareTo(Position that) {
|
||||||
if (this.line < that.line)
|
if (this.line < that.line) return -1;
|
||||||
return -1;
|
if (this.line == that.line)
|
||||||
if (this.line == that.line)
|
if (this.column < that.column) return -1;
|
||||||
if (this.column < that.column)
|
else if (this.column == that.column) return 0;
|
||||||
return -1;
|
else return 1;
|
||||||
else if (this.column == that.column)
|
return 1;
|
||||||
return 0;
|
}
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + column;
|
result = prime * result + column;
|
||||||
result = prime * result + line;
|
result = prime * result + line;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj) return true;
|
||||||
return true;
|
if (obj == null) return false;
|
||||||
if (obj == null)
|
if (getClass() != obj.getClass()) return false;
|
||||||
return false;
|
Position other = (Position) obj;
|
||||||
if (getClass() != obj.getClass())
|
if (column != other.column) return false;
|
||||||
return false;
|
if (line != other.line) return false;
|
||||||
Position other = (Position) obj;
|
return true;
|
||||||
if (column != other.column)
|
}
|
||||||
return false;
|
|
||||||
if (line != other.line)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return line + ":" + column;
|
return line + ":" + column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,39 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
|
import com.semmle.ts.ast.INodeWithSymbol;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.semmle.ts.ast.INodeWithSymbol;
|
/** A top-level program entity forming the root of an AST. */
|
||||||
|
|
||||||
/**
|
|
||||||
* A top-level program entity forming the root of an AST.
|
|
||||||
*/
|
|
||||||
public class Program extends Node implements IStatementContainer, INodeWithSymbol {
|
public class Program extends Node implements IStatementContainer, INodeWithSymbol {
|
||||||
private final List<Statement> body;
|
private final List<Statement> body;
|
||||||
private final String sourceType;
|
private final String sourceType;
|
||||||
private int symbolId = -1;
|
private int symbolId = -1;
|
||||||
|
|
||||||
public Program(SourceLocation loc, List<Statement> body, String sourceType) {
|
public Program(SourceLocation loc, List<Statement> body, String sourceType) {
|
||||||
super("Program", loc);
|
super("Program", loc);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The statements in this program. */
|
||||||
* The statements in this program.
|
public List<Statement> getBody() {
|
||||||
*/
|
return body;
|
||||||
public List<Statement> getBody() {
|
}
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSourceType() {
|
public String getSourceType() {
|
||||||
return sourceType;
|
return sourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSymbol() {
|
public int getSymbol() {
|
||||||
return this.symbolId;
|
return this.symbolId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSymbol(int symbolId) {
|
public void setSymbol(int symbolId) {
|
||||||
this.symbolId = symbolId;
|
this.symbolId = symbolId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,137 +1,131 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
|
import com.semmle.util.data.StringUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.semmle.util.data.StringUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A property in an object literal or an object pattern.
|
* A property in an object literal or an object pattern.
|
||||||
*
|
*
|
||||||
* This includes both regular properties as well as accessor properties, method properties,
|
* <p>This includes both regular properties as well as accessor properties, method properties,
|
||||||
* properties with computed names, and spread/rest properties.
|
* properties with computed names, and spread/rest properties.
|
||||||
*/
|
*/
|
||||||
public class Property extends Node {
|
public class Property extends Node {
|
||||||
public static enum Kind {
|
public static enum Kind {
|
||||||
/** Either a normal property or a spread/rest property. */
|
/** Either a normal property or a spread/rest property. */
|
||||||
INIT(false),
|
INIT(false),
|
||||||
|
|
||||||
/** Getter property. */
|
/** Getter property. */
|
||||||
GET(true),
|
GET(true),
|
||||||
|
|
||||||
/** Setter property. */
|
/** Setter property. */
|
||||||
SET(true);
|
SET(true);
|
||||||
|
|
||||||
public final boolean isAccessor;
|
public final boolean isAccessor;
|
||||||
|
|
||||||
private Kind(boolean isAccessor) {
|
private Kind(boolean isAccessor) {
|
||||||
this.isAccessor = isAccessor;
|
this.isAccessor = isAccessor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Expression key;
|
private final Expression key;
|
||||||
private final Expression value, rawValue;
|
private final Expression value, rawValue;
|
||||||
private final Expression defaultValue; // only applies to property patterns
|
private final Expression defaultValue; // only applies to property patterns
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
private final boolean computed, method;
|
private final boolean computed, method;
|
||||||
private final List<Decorator> decorators;
|
private final List<Decorator> decorators;
|
||||||
|
|
||||||
public Property(SourceLocation loc, Expression key, Expression rawValue, String kind, Boolean computed, Boolean method) {
|
public Property(
|
||||||
super("Property", loc);
|
SourceLocation loc,
|
||||||
this.key = key;
|
Expression key,
|
||||||
if (rawValue instanceof AssignmentPattern) {
|
Expression rawValue,
|
||||||
AssignmentPattern ap = (AssignmentPattern) rawValue;
|
String kind,
|
||||||
if (ap.getLeft() == key)
|
Boolean computed,
|
||||||
rawValue = ap = new AssignmentPattern(ap.getLoc(), ap.getOperator(), new NodeCopier().copy(key), ap.getRight());
|
Boolean method) {
|
||||||
this.value = ap.getLeft();
|
super("Property", loc);
|
||||||
this.defaultValue = ap.getRight();
|
this.key = key;
|
||||||
} else {
|
if (rawValue instanceof AssignmentPattern) {
|
||||||
this.value = rawValue == key ? new NodeCopier().copy(rawValue) : rawValue;
|
AssignmentPattern ap = (AssignmentPattern) rawValue;
|
||||||
this.defaultValue = null;
|
if (ap.getLeft() == key)
|
||||||
}
|
rawValue =
|
||||||
this.rawValue = rawValue;
|
ap =
|
||||||
this.kind = Kind.valueOf(StringUtil.uc(kind));
|
new AssignmentPattern(
|
||||||
this.computed = computed == Boolean.TRUE;
|
ap.getLoc(), ap.getOperator(), new NodeCopier().copy(key), ap.getRight());
|
||||||
this.method = method == Boolean.TRUE;
|
this.value = ap.getLeft();
|
||||||
this.decorators = new ArrayList<Decorator>();
|
this.defaultValue = ap.getRight();
|
||||||
}
|
} else {
|
||||||
|
this.value = rawValue == key ? new NodeCopier().copy(rawValue) : rawValue;
|
||||||
|
this.defaultValue = null;
|
||||||
|
}
|
||||||
|
this.rawValue = rawValue;
|
||||||
|
this.kind = Kind.valueOf(StringUtil.uc(kind));
|
||||||
|
this.computed = computed == Boolean.TRUE;
|
||||||
|
this.method = method == Boolean.TRUE;
|
||||||
|
this.decorators = new ArrayList<Decorator>();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key of this property; usually a {@link Literal} or an {@link Identifier}, but may
|
* The key of this property; usually a {@link Literal} or an {@link Identifier}, but may be an
|
||||||
* be an arbitrary expression for properties with computed names. For spread/rest properties
|
* arbitrary expression for properties with computed names. For spread/rest properties this method
|
||||||
* this method returns {@code null}.
|
* returns {@code null}.
|
||||||
*/
|
*/
|
||||||
public Expression getKey() {
|
public Expression getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The value expression of this property. */
|
||||||
* The value expression of this property.
|
public Expression getValue() {
|
||||||
*/
|
return value;
|
||||||
public Expression getValue() {
|
}
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The default value of this property pattern. */
|
||||||
* The default value of this property pattern.
|
public Expression getDefaultValue() {
|
||||||
*/
|
return defaultValue;
|
||||||
public Expression getDefaultValue() {
|
}
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this a property pattern with a default value? */
|
||||||
* Is this a property pattern with a default value?
|
public boolean hasDefaultValue() {
|
||||||
*/
|
return defaultValue != null;
|
||||||
public boolean hasDefaultValue() {
|
}
|
||||||
return defaultValue != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The kind of this property. */
|
||||||
* The kind of this property.
|
public Kind getKind() {
|
||||||
*/
|
return kind;
|
||||||
public Kind getKind() {
|
}
|
||||||
return kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is the name of this property computed? */
|
||||||
* Is the name of this property computed?
|
public boolean isComputed() {
|
||||||
*/
|
return computed;
|
||||||
public boolean isComputed() {
|
}
|
||||||
return computed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this property declared using method syntax? */
|
||||||
* Is this property declared using method syntax?
|
public boolean isMethod() {
|
||||||
*/
|
return method;
|
||||||
public boolean isMethod() {
|
}
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Is this property declared using shorthand syntax? */
|
||||||
* Is this property declared using shorthand syntax?
|
public boolean isShorthand() {
|
||||||
*/
|
return key != null && key.getLoc().equals(value.getLoc());
|
||||||
public boolean isShorthand() {
|
}
|
||||||
return key != null && key.getLoc().equals(value.getLoc());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The raw value expression of this property; if this property is a property
|
* The raw value expression of this property; if this property is a property pattern with a
|
||||||
* pattern with a default value, this method returns an {@link AssignmentPattern}.
|
* default value, this method returns an {@link AssignmentPattern}.
|
||||||
*/
|
*/
|
||||||
public Expression getRawValue() {
|
public Expression getRawValue() {
|
||||||
return rawValue;
|
return rawValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDecorators(List<Decorator> decorators) {
|
public void addDecorators(List<Decorator> decorators) {
|
||||||
this.decorators.addAll(decorators);
|
this.decorators.addAll(decorators);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Decorator> getDecorators() {
|
public List<Decorator> getDecorators() {
|
||||||
return this.decorators;
|
return this.decorators;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,27 +3,25 @@ package com.semmle.js.ast;
|
|||||||
/**
|
/**
|
||||||
* A rest element <code>...xs</code> in lvalue position.
|
* A rest element <code>...xs</code> in lvalue position.
|
||||||
*
|
*
|
||||||
* Rest elements can only appear as part of a function's parameter list or in an array
|
* <p>Rest elements can only appear as part of a function's parameter list or in an array pattern;
|
||||||
* pattern; they are rewritten away by the constructors of {@linkplain AFunction} and
|
* they are rewritten away by the constructors of {@linkplain AFunction} and {@link ArrayPattern},
|
||||||
* {@link ArrayPattern}, and don't appear in the AST the extractor works on.
|
* and don't appear in the AST the extractor works on.
|
||||||
*/
|
*/
|
||||||
public class RestElement extends Expression implements IPattern {
|
public class RestElement extends Expression implements IPattern {
|
||||||
private final Expression argument;
|
private final Expression argument;
|
||||||
|
|
||||||
public RestElement(SourceLocation loc, Expression argument) {
|
public RestElement(SourceLocation loc, Expression argument) {
|
||||||
super("RestElement", loc);
|
super("RestElement", loc);
|
||||||
this.argument = argument;
|
this.argument = argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The argument expression of this spread element. */
|
||||||
* The argument expression of this spread element.
|
public Expression getArgument() {
|
||||||
*/
|
return argument;
|
||||||
public Expression getArgument() {
|
}
|
||||||
return argument;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,26 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A return statement. */
|
||||||
* A return statement.
|
|
||||||
*/
|
|
||||||
public class ReturnStatement extends Statement {
|
public class ReturnStatement extends Statement {
|
||||||
private final Expression argument;
|
private final Expression argument;
|
||||||
|
|
||||||
public ReturnStatement(SourceLocation loc, Expression argument) {
|
public ReturnStatement(SourceLocation loc, Expression argument) {
|
||||||
super("ReturnStatement", loc);
|
super("ReturnStatement", loc);
|
||||||
this.argument = argument;
|
this.argument = argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Does this return statement have an argument expression? */
|
||||||
* Does this return statement have an argument expression?
|
public boolean hasArgument() {
|
||||||
*/
|
return argument != null;
|
||||||
public boolean hasArgument() {
|
}
|
||||||
return argument != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The argument expression of this return statement; may be null. */
|
||||||
* The argument expression of this return statement; may be null.
|
public Expression getArgument() {
|
||||||
*/
|
return argument;
|
||||||
public Expression getArgument() {
|
}
|
||||||
return argument;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,22 @@ package com.semmle.js.ast;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/** A comma expression containing two or more expressions evaluated in sequence. */
|
||||||
* A comma expression containing two or more expressions evaluated in sequence.
|
|
||||||
*/
|
|
||||||
public class SequenceExpression extends Expression {
|
public class SequenceExpression extends Expression {
|
||||||
private final List<Expression> expressions;
|
private final List<Expression> expressions;
|
||||||
|
|
||||||
public SequenceExpression(SourceLocation loc, List<Expression> expressions) {
|
public SequenceExpression(SourceLocation loc, List<Expression> expressions) {
|
||||||
super("SequenceExpression", loc);
|
super("SequenceExpression", loc);
|
||||||
this.expressions = expressions;
|
this.expressions = expressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
public <Q, A> A accept(Visitor<Q, A> v, Q q) {
|
||||||
return v.visit(this, q);
|
return v.visit(this, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The expressions in this sequence. */
|
||||||
* The expressions in this sequence.
|
public List<Expression> getExpressions() {
|
||||||
*/
|
return expressions;
|
||||||
public List<Expression> getExpressions() {
|
}
|
||||||
return expressions;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** Common superclass of all source elements. */
|
||||||
* Common superclass of all source elements.
|
|
||||||
*/
|
|
||||||
public class SourceElement implements ISourceElement {
|
public class SourceElement implements ISourceElement {
|
||||||
private final SourceLocation loc;
|
private final SourceLocation loc;
|
||||||
|
|
||||||
public SourceElement(SourceLocation loc) {
|
public SourceElement(SourceLocation loc) {
|
||||||
this.loc = loc;
|
this.loc = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasLoc() {
|
public boolean hasLoc() {
|
||||||
return loc != null;
|
return loc != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final SourceLocation getLoc() {
|
public final SourceLocation getLoc() {
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +1,79 @@
|
|||||||
package com.semmle.js.ast;
|
package com.semmle.js.ast;
|
||||||
|
|
||||||
/**
|
/** A source location representing a range of characters. */
|
||||||
* A source location representing a range of characters.
|
|
||||||
*/
|
|
||||||
public class SourceLocation {
|
public class SourceLocation {
|
||||||
private String source;
|
private String source;
|
||||||
private Position start, end;
|
private Position start, end;
|
||||||
|
|
||||||
public SourceLocation(String source, Position start, Position end) {
|
public SourceLocation(String source, Position start, Position end) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation(Position start) {
|
public SourceLocation(Position start) {
|
||||||
this(null, start, null);
|
this(null, start, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation(String source, Position start) {
|
public SourceLocation(String source, Position start) {
|
||||||
this(source, start, null);
|
this(source, start, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation(SourceLocation that) {
|
public SourceLocation(SourceLocation that) {
|
||||||
this(that.source, that.start, that.end);
|
this(that.source, that.start, that.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** The source code contained in this location. */
|
||||||
* The source code contained in this location.
|
public String getSource() {
|
||||||
*/
|
return source;
|
||||||
public String getSource() {
|
}
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Set the source code contain in this location. */
|
||||||
* Set the source code contain in this location.
|
public void setSource(String source) {
|
||||||
*/
|
this.source = source;
|
||||||
public void setSource(String source) {
|
}
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The start position of the location. */
|
||||||
* The start position of the location.
|
public Position getStart() {
|
||||||
*/
|
return start;
|
||||||
public Position getStart() {
|
}
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Set the start position of this location. */
|
||||||
* Set the start position of this location.
|
public void setStart(Position start) {
|
||||||
*/
|
this.start = start;
|
||||||
public void setStart(Position start) {
|
}
|
||||||
this.start = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** The end position of the location. */
|
||||||
* The end position of the location.
|
public Position getEnd() {
|
||||||
*/
|
return end;
|
||||||
public Position getEnd() {
|
}
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/** Set the end position of this location. */
|
||||||
* Set the end position of this location.
|
public void setEnd(Position end) {
|
||||||
*/
|
this.end = end;
|
||||||
public void setEnd(Position end) {
|
}
|
||||||
this.end = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((end == null) ? 0 : end.hashCode());
|
result = prime * result + ((end == null) ? 0 : end.hashCode());
|
||||||
result = prime * result + ((start == null) ? 0 : start.hashCode());
|
result = prime * result + ((start == null) ? 0 : start.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj) return true;
|
||||||
return true;
|
if (obj == null) return false;
|
||||||
if (obj == null)
|
if (getClass() != obj.getClass()) return false;
|
||||||
return false;
|
SourceLocation other = (SourceLocation) obj;
|
||||||
if (getClass() != obj.getClass())
|
if (end == null) {
|
||||||
return false;
|
if (other.end != null) return false;
|
||||||
SourceLocation other = (SourceLocation) obj;
|
} else if (!end.equals(other.end)) return false;
|
||||||
if (end == null) {
|
if (start == null) {
|
||||||
if (other.end != null)
|
if (other.start != null) return false;
|
||||||
return false;
|
} else if (!start.equals(other.start)) return false;
|
||||||
} else if (!end.equals(other.end))
|
return true;
|
||||||
return false;
|
}
|
||||||
if (start == null) {
|
|
||||||
if (other.start != null)
|
|
||||||
return false;
|
|
||||||
} else if (!start.equals(other.start))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user