Skip to content

Commit

Permalink
fix: handle faulty imports
Browse files Browse the repository at this point in the history
Do not throw silently for incompatible
import paths. Fix comment removal
for JS files to accept ' as string.

fixes #12765
  • Loading branch information
caalador committed Jan 21, 2022
1 parent eaad21e commit 4e4d79a
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public final class StringUtil {
* Comment parser state enumeration.
*/
private enum State {
NORMAL, IN_LINE_COMMENT, IN_BLOCK_COMMENT, IN_STRING
NORMAL, IN_LINE_COMMENT, IN_BLOCK_COMMENT, IN_STRING, IN_STRING_APOSTROPHE
}

/**
Expand Down Expand Up @@ -99,6 +99,78 @@ public final static String removeComments(String code) {
return handled;
}

/**
* Removes comments (block comments and line comments) from the JS code.
*
* @return the code with removed comments
*/
public static String removeJsComments(String code) {
State state = State.NORMAL;
StringBuilder result = new StringBuilder();
Map<String, Character> replacements = new HashMap<>();
Scanner scanner = new Scanner(normalize(code, replacements));
scanner.useDelimiter("");
while (scanner.hasNext()) {
String character = scanner.next();
switch (state) {
case NORMAL:
if (character.equals("/") && scanner.hasNext()) {
String nextCharacter = scanner.next();
if (nextCharacter.equals("/")) {
state = State.IN_LINE_COMMENT;
} else if (nextCharacter.equals("*")) {
state = State.IN_BLOCK_COMMENT;
} else {
result.append(character).append(nextCharacter);
}
} else {
result.append(character);
if (character.equals("\"")) {
state = State.IN_STRING;
} else if (character.equals("\'")) {
state = State.IN_STRING_APOSTROPHE;
}
}
break;
case IN_STRING:
result.append(character);
if (character.equals("\"")) {
state = State.NORMAL;
} else if (character.equals("\\") && scanner.hasNext()) {
result.append(scanner.next());
}
break;
case IN_STRING_APOSTROPHE:
result.append(character);
if (character.equals("\'")) {
state = State.NORMAL;
} else if (character.equals("\\") && scanner.hasNext()) {
result.append(scanner.next());
}
break;
case IN_LINE_COMMENT:
if (character.equals("\n")) {
result.append(character);
state = State.NORMAL;
}
break;
case IN_BLOCK_COMMENT:
if (character.equals("*") && scanner.hasNext("/")) {
scanner.next();
state = State.NORMAL;
break;
}
}
}
scanner.close();
String handled = result.toString();
for (Entry<String, Character> entry : replacements.entrySet()) {
handled = handled.replace(entry.getKey(),
String.valueOf(entry.getValue()));
}
return handled;
}

private static String normalize(String str,
Map<String, Character> replacements) {
StringBuilder builder = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -574,7 +575,10 @@ private void visitImportsRecursively(Path filePath, String path,
if (file == null && !importedPath.startsWith("./")) {
// In case such file doesn't exist it may be external: inside
// node_modules folder
file = getFile(getNodeModulesDir(), resolvedPath);
file = getFile(getNodeModulesDir(), importedPath);
if (!file.exists()) {
file = null;
}
resolvedPath = importedPath;
}
if (file == null) {
Expand Down Expand Up @@ -632,12 +636,19 @@ private String resolve(String importedPath, Path moduleFile, String path) {
String pathPrefix = moduleFile.toString();
pathPrefix = pathPrefix.substring(0,
pathPrefix.length() - path.length());
String resolvedPath = moduleFile.getParent().resolve(importedPath)
.toString();
if (resolvedPath.startsWith(pathPrefix)) {
resolvedPath = resolvedPath.substring(pathPrefix.length());
try {
String resolvedPath = moduleFile.getParent().resolve(importedPath)
.toString();
if (resolvedPath.startsWith(pathPrefix)) {
resolvedPath = resolvedPath.substring(pathPrefix.length());
}
return resolvedPath;
} catch (InvalidPathException ipe) {
getLogger().error("Invalid import '{}' in file '{}'", importedPath,
moduleFile);
getLogger().debug("Failed to resolve path.", ipe);
}
return resolvedPath;
return importedPath;
}

private String normalizePath(String path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ List<String> getImportedPaths() {
* @return the code with removed comments
*/
String removeComments() {
return StringUtil.removeComments(content);
return StringUtil.removeJsComments(content);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,44 @@ public void commentRemoval_emojiInString_removalDoesnotThrowResultIsTheSame() {
@Test
public void removeComments_commentsWithAsterisksInside_commentIsRemoved() {
String result = StringUtil.removeComments("/* comment **/ ;");
Assert.assertEquals(result, " ;");
Assert.assertEquals(" ;", result);
}

@Test
public void removeJsComments_handlesApostropheAsInString() {
String httpImport = "import 'http://localhost:56445/files/transformed/@vaadin/vaadin-text-field/vaadin-text-field.js';";

Assert.assertEquals("Nothing shoiuld be removed for import", httpImport,
StringUtil.removeJsComments(httpImport));

String result = StringUtil.removeJsComments("/* comment **/ ;");
Assert.assertEquals(" ;", result);

String singleLineBlock = StringUtil.removeJsComments(
"return html`/* single line block comment*/`;");

Assert.assertEquals("return html``;", singleLineBlock);

String blockComment = StringUtil
.removeJsComments("return html`/* block with new lines\n"
+ "* still in my/their block */`;");
Assert.assertEquals("return html``;", blockComment);

String newLineSingleBlock = StringUtil
.removeJsComments("return html`/* not here \n*/`;");
Assert.assertEquals("return html``;", newLineSingleBlock);

String noComments = "<vaadin-text-field label=\"Nats Url(s)\" placeholder=\"nats://server:port\" id=\"natsUrlTxt\" style=\"width:100%\"></vaadin-text-field>`";
Assert.assertEquals(noComments,
StringUtil.removeJsComments(noComments));

String lineComment = StringUtil
.removeJsComments("return html`// this line comment\n`;");
Assert.assertEquals("return html`\n`;", lineComment);

String mixedComments = StringUtil.removeJsComments(
"return html`/* not here \n*/\nCode;// neither this\n"
+ "/* this should // be fine\n* to remove / */`;");
Assert.assertEquals("return html`\nCode;\n`;", mixedComments);
}
}

0 comments on commit 4e4d79a

Please sign in to comment.