JS: Extractor: More robust ES2015 checking

Created shared AbstractDetector to not duplicate all the tedious logic
;)

I took inspiration from the tests in  `javascript/extractor/tests/esnext/input/dynamic-import.js`
This commit is contained in:
Rasmus Wriedt Larsen
2024-03-25 13:17:15 +01:00
parent cd84500c56
commit 04a0740ccb
5 changed files with 114 additions and 1 deletions

View File

@@ -0,0 +1,34 @@
package com.semmle.js.extractor;
import com.semmle.js.ast.DynamicImport;
import com.semmle.js.ast.ExportDeclaration;
import com.semmle.js.ast.Expression;
import com.semmle.js.ast.ImportDeclaration;
import com.semmle.js.ast.Node;
import com.semmle.js.ast.Statement;
/** A utility class for detecting Node.js code. */
public class ES2015Detector extends AbstractDetector {
/**
* Is {@code ast} a program that uses ES2015 import/export code?
*/
public static boolean looksLikeES2015(Node ast) {
return new ES2015Detector().programDetection(ast);
}
@Override
protected boolean visitStatement(Statement stmt) {
if (stmt instanceof ImportDeclaration || stmt instanceof ExportDeclaration) {
return true;
}
return super.visitStatement(stmt);
}
@Override
protected boolean visitExpression(Expression e) {
if (e instanceof DynamicImport) {
return true;
}
return super.visitExpression(e);
}
}

View File

@@ -58,6 +58,26 @@ public class JSExtractor {
JSParser.Result parserRes =
JSParser.parse(config, sourceType, source, textualExtractor.getMetrics());
// Check if we guessed wrong with the regex in `establishSourceType`, (which could
// happen due to a block-comment line starting with ' import').
if (config.getSourceType() == SourceType.AUTO && sourceType != SourceType.SCRIPT) {
boolean wrongGuess = false;
if (sourceType == SourceType.MODULE) {
// check that we did see an import/export declaration
wrongGuess = ES2015Detector.looksLikeES2015(parserRes.getAST()) == false;
} else if (sourceType == SourceType.CLOSURE_MODULE ) {
// TODO
}
if (wrongGuess) {
sourceType = SourceType.SCRIPT;
parserRes =
JSParser.parse(config, sourceType, source, textualExtractor.getMetrics());
}
}
return extract(textualExtractor, source, toplevelKind, scopeManager, sourceType, parserRes);
}