JS: Set SourceType correctly

This commit is contained in:
Asger Feldthaus
2020-06-29 13:42:22 +01:00
parent fcb365188b
commit 1a16d7339a
3 changed files with 23 additions and 9 deletions

View File

@@ -2,6 +2,8 @@ package com.semmle.js.extractor;
import java.nio.file.Path;
import com.semmle.js.extractor.ExtractorConfig.SourceType;
/**
* Denotes where a code snippet originated from within a file.
*/
@@ -10,12 +12,14 @@ public class FileSnippet {
private int line;
private int column;
private int topLevelKind;
private SourceType sourceType;
public FileSnippet(Path originalFile, int line, int column, int topLevelKind) {
public FileSnippet(Path originalFile, int line, int column, int topLevelKind, SourceType sourceType) {
this.originalFile = originalFile;
this.line = line;
this.column = column;
this.topLevelKind = topLevelKind;
this.sourceType = sourceType;
}
public Path getOriginalFile() {
@@ -33,4 +37,8 @@ public class FileSnippet {
public int getTopLevelKind() {
return topLevelKind;
}
public SourceType getSourceType() {
return sourceType;
}
}

View File

@@ -1,5 +1,6 @@
package com.semmle.js.extractor;
import java.io.File;
import java.nio.file.Path;
import java.util.regex.Pattern;
@@ -55,7 +56,7 @@ public class HTMLExtractor implements IExtractor {
for (Element elt : src.getAllElements()) {
LoCInfo snippetLoC = null;
if (elt.getName().equals(HTMLElementName.SCRIPT)) {
SourceType sourceType = getScriptSourceType(elt);
SourceType sourceType = getScriptSourceType(elt, textualExtractor.getExtractedFile());
if (sourceType != null) {
// Jericho sometimes misparses empty elements, which will show up as start tags
// ending in "/"; we manually exclude these cases to avoid spurious syntax errors
@@ -149,18 +150,23 @@ public class HTMLExtractor implements IExtractor {
* Deduce the {@link SourceType} with which the given <code>script</code> element should be
* extracted, returning <code>null</code> if it cannot be determined.
*/
private SourceType getScriptSourceType(Element script) {
private SourceType getScriptSourceType(Element script, File file) {
String scriptType = getAttributeValueLC(script, "type");
String scriptLanguage = getScriptLanguage(script);
SourceType fallbackSourceType = config.getSourceType();
if (file.getName().endsWith(".vue")) {
fallbackSourceType = SourceType.MODULE;
}
if (isTypeScriptTag(script)) return config.getSourceType();
if (isTypeScriptTag(script)) return fallbackSourceType;
// if `type` and `language` are both either missing, contain the
// string "javascript", or if `type` is the string "text/jsx", this is a plain script
if ((scriptType == null || scriptType.contains("javascript") || "text/jsx".equals(scriptType))
&& (scriptLanguage == null || scriptLanguage.contains("javascript")))
// use default source type
return config.getSourceType();
return fallbackSourceType;
// if `type` is "text/babel", the source type depends on the `data-plugins` attribute
if ("text/babel".equals(scriptType)) {
@@ -168,7 +174,7 @@ public class HTMLExtractor implements IExtractor {
if (plugins != null && plugins.contains("transform-es2015-modules-umd")) {
return SourceType.MODULE;
}
return config.getSourceType();
return fallbackSourceType;
}
// if `type` is "module", extract as module
@@ -214,7 +220,7 @@ public class HTMLExtractor implements IExtractor {
boolean isTypeScript) {
if (isTypeScript) {
Path file = textualExtractor.getExtractedFile().toPath();
FileSnippet snippet = new FileSnippet(file, line, column, toplevelKind);
FileSnippet snippet = new FileSnippet(file, line, column, toplevelKind, config.getSourceType());
VirtualSourceRoot vroot = config.getVirtualSourceRoot();
// Vue files are special in that they can be imported as modules, and may only contain one <script> tag.
// For .vue files we omit the usual snippet decoration to ensure the TypeScript compiler can find it.

View File

@@ -25,9 +25,9 @@ public class TypeScriptExtractor implements IExtractor {
ScopeManager scopeManager =
new ScopeManager(textualExtractor.getTrapwriter(), ECMAVersion.ECMA2017);
try {
SourceType sourceType = jsExtractor.establishSourceType(source, false);
FileSnippet snippet = state.getSnippets().get(sourceFile.toPath());
int toplevelKind = snippet == null ? 0 : snippet.getTopLevelKind();
SourceType sourceType = snippet != null ? snippet.getSourceType() : jsExtractor.establishSourceType(source, false);
int toplevelKind = snippet != null ? snippet.getTopLevelKind() : 0;
return jsExtractor.extract(textualExtractor, source, toplevelKind, scopeManager, sourceType, res).snd();
} catch (ParseError e) {
e.setPosition(locationManager.translatePosition(e.getPosition()));