mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
JS(extractor): improve parser support for flowtype syntax
This commit is contained in:
@@ -3040,6 +3040,10 @@ public class Parser {
|
||||
return parseClassPropertyBody(pi, hadConstructor, isStatic);
|
||||
}
|
||||
|
||||
protected boolean atGetterSetterName(PropertyInfo pi) {
|
||||
return !pi.isGenerator && !pi.isAsync && pi.key instanceof Identifier && this.type != TokenType.parenL && (((Identifier) pi.key).getName().equals("get") || ((Identifier) pi.key).getName().equals("set"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a method declaration in a class, assuming that its name has already been consumed.
|
||||
*/
|
||||
@@ -3047,7 +3051,7 @@ public class Parser {
|
||||
pi.kind = "method";
|
||||
boolean isGetSet = false;
|
||||
if (!pi.computed) {
|
||||
if (!pi.isGenerator && !pi.isAsync && pi.key instanceof Identifier && this.type != TokenType.parenL && (((Identifier) pi.key).getName().equals("get") || ((Identifier) pi.key).getName().equals("set"))) {
|
||||
if (atGetterSetterName(pi)) {
|
||||
isGetSet = true;
|
||||
pi.kind = ((Identifier) pi.key).getName();
|
||||
this.parsePropertyName(pi);
|
||||
|
||||
@@ -146,6 +146,10 @@ public class FlowParser extends ESNextParser {
|
||||
boolean oldInType = inType;
|
||||
inType = true;
|
||||
this.expect(tok == null ? TokenType.colon : tok);
|
||||
if (this.type == TokenType.modulo) {// an annotation like '%checks' without a preceeding type
|
||||
inType = oldInType;
|
||||
return;
|
||||
}
|
||||
if (allowLeadingPipeOrAnd) {
|
||||
if (this.type == TokenType.bitwiseAND || this.type == TokenType.bitwiseOR) {
|
||||
this.next();
|
||||
@@ -223,14 +227,29 @@ public class FlowParser extends ESNextParser {
|
||||
while (this.type != TokenType.braceR) {
|
||||
Position stmtStart = startLoc;
|
||||
|
||||
// todo: declare check
|
||||
this.next();
|
||||
if (this.eat(TokenType._import)) {
|
||||
this.flowParseDeclareImport(stmtStart);
|
||||
} else {
|
||||
// todo: declare check
|
||||
this.next();
|
||||
|
||||
this.flowParseDeclare(stmtStart);
|
||||
this.flowParseDeclare(stmtStart);
|
||||
}
|
||||
}
|
||||
this.expect(TokenType.braceR);
|
||||
}
|
||||
|
||||
private void flowParseDeclareImport(Position stmtStart) {
|
||||
String kind = flowParseImportSpecifiers();
|
||||
if (kind == null) {
|
||||
this.raise(stmtStart, "Imports within a `declare module` body must always be `import type` or `import typeof`.");
|
||||
}
|
||||
this.expect(TokenType.name);
|
||||
this.expectContextual("from");
|
||||
this.expect(TokenType.string);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
private void flowParseDeclareModuleExports() {
|
||||
this.expectContextual("module");
|
||||
this.expect(TokenType.dot);
|
||||
@@ -737,7 +756,7 @@ public class FlowParser extends ESNextParser {
|
||||
|
||||
private void flowParsePostfixType() {
|
||||
this.flowParsePrimaryType();
|
||||
if (this.type == TokenType.bracketL) {
|
||||
while (this.type == TokenType.bracketL) {
|
||||
this.expect(TokenType.bracketL);
|
||||
this.expect(TokenType.bracketR);
|
||||
}
|
||||
@@ -807,11 +826,20 @@ public class FlowParser extends ESNextParser {
|
||||
// if allowExpression is true then we're parsing an arrow function and if
|
||||
// there's a return type then it's been handled elsewhere
|
||||
this.flowParseTypeAnnotation();
|
||||
this.flowParseChecksAnnotation();
|
||||
}
|
||||
|
||||
return super.parseFunctionBody(id, params, isArrowFunction);
|
||||
}
|
||||
|
||||
private void flowParseChecksAnnotation() {
|
||||
// predicate functions with the special '%checks' annotation
|
||||
if (this.type == TokenType.modulo && lookaheadIsIdent("checks", true)) {
|
||||
this.next();
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
|
||||
// interfaces
|
||||
@Override
|
||||
protected Statement parseStatement(boolean declaration, boolean topLevel, Set<String> exports) {
|
||||
@@ -975,24 +1003,30 @@ public class FlowParser extends ESNextParser {
|
||||
return param;
|
||||
}
|
||||
|
||||
private String flowParseImportSpecifiers() {
|
||||
String kind = null;
|
||||
if (this.type == TokenType._typeof) {
|
||||
kind = "typeof";
|
||||
} else if (this.isContextual("type")) {
|
||||
kind = "type";
|
||||
}
|
||||
if (kind != null) {
|
||||
String lh = lookahead(4);
|
||||
if (!lh.isEmpty()) {
|
||||
int c = lh.codePointAt(0);
|
||||
if ((Identifiers.isIdentifierStart(c, true) && !"from".equals(lh)) || c == '{' || c == '*') {
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ImportSpecifier> parseImportSpecifiers() {
|
||||
String kind = null;
|
||||
if (flow()) {
|
||||
if (this.type == TokenType._typeof) {
|
||||
kind = "typeof";
|
||||
} else if (this.isContextual("type")) {
|
||||
kind = "type";
|
||||
}
|
||||
if (kind != null) {
|
||||
String lh = lookahead(4);
|
||||
if (!lh.isEmpty()) {
|
||||
int c = lh.codePointAt(0);
|
||||
if ((Identifiers.isIdentifierStart(c, true) && !"from".equals(lh)) || c == '{' || c == '*') {
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
kind = flowParseImportSpecifiers();
|
||||
}
|
||||
|
||||
List<ImportSpecifier> specs = super.parseImportSpecifiers();
|
||||
@@ -1102,6 +1136,7 @@ public class FlowParser extends ESNextParser {
|
||||
boolean oldNoAnonFunctionType = noAnonFunctionType;
|
||||
noAnonFunctionType = true;
|
||||
flowParseTypeAnnotation();
|
||||
flowParseChecksAnnotation();
|
||||
noAnonFunctionType = oldNoAnonFunctionType;
|
||||
if (this.type != TokenType.arrow)
|
||||
unexpected();
|
||||
@@ -1158,4 +1193,12 @@ public class FlowParser extends ESNextParser {
|
||||
this.eat(TokenType.plusMin);
|
||||
super.parsePropertyName(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean atGetterSetterName(PropertyInfo pi) {
|
||||
if (flow() && this.isRelational("<"))
|
||||
return false;
|
||||
return super.atGetterSetterName(pi);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class Main {
|
||||
* such a way that it may produce different tuples for the same file under the same
|
||||
* {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2018-11-20";
|
||||
public static final String EXTRACTOR_VERSION = "2018-11-22_a";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user