diff --git a/src/com/google/javascript/jscomp/RhinoErrorReporter.java b/src/com/google/javascript/jscomp/RhinoErrorReporter.java index 1d4ecc3d4e2..951cb960e28 100644 --- a/src/com/google/javascript/jscomp/RhinoErrorReporter.java +++ b/src/com/google/javascript/jscomp/RhinoErrorReporter.java @@ -168,7 +168,7 @@ private RhinoErrorReporter(AbstractCompiler compiler) { // Parse tree too deep. .put(Pattern.compile("Too deep recursion while parsing"), PARSE_TREE_TOO_DEEP) - // Octal literals + // Old-style octal literals .put(Pattern.compile("^Octal .*literal.*"), INVALID_OCTAL_LITERAL) .put( diff --git a/src/com/google/javascript/jscomp/parsing/IRFactory.java b/src/com/google/javascript/jscomp/parsing/IRFactory.java index 054b31f21a2..fbb5bd9b12b 100644 --- a/src/com/google/javascript/jscomp/parsing/IRFactory.java +++ b/src/com/google/javascript/jscomp/parsing/IRFactory.java @@ -195,19 +195,10 @@ class IRFactory { static final String INVALID_OCTAL_DIGIT = "Invalid octal digit in octal literal."; - static final String STRING_CONTINUATION_ERROR = - "String continuations are not supported in this language mode."; - static final String STRING_CONTINUATION_WARNING = "String continuations are not recommended. See" + " https://google.github.io/styleguide/javascriptguide.xml?showone=Multiline_string_literals#Multiline_string_literals"; - static final String BINARY_NUMBER_LITERAL_WARNING = - "Binary integer literals are not supported in this language mode."; - - static final String OCTAL_NUMBER_LITERAL_WARNING = - "Octal integer literals are not supported in this language mode."; - static final String OCTAL_STRING_LITERAL_WARNING = "Octal literals in strings are not supported in this language mode."; @@ -844,7 +835,6 @@ Node transformNumberAsString(LiteralToken token) { } static int lineno(ParseTree node) { - // location lines start at zero, our AST starts at 1. return lineno(node.location.start); } @@ -852,6 +842,14 @@ static int charno(ParseTree node) { return charno(node.location.start); } + static int lineno(com.google.javascript.jscomp.parsing.parser.Token token) { + return lineno(token.location.start); + } + + static int charno(com.google.javascript.jscomp.parsing.parser.Token token) { + return charno(token.location.start); + } + static int lineno(SourcePosition location) { // location lines start at zero, our AST starts at 1. return location.line + 1; @@ -861,6 +859,33 @@ static int charno(SourcePosition location) { return location.column; } + void maybeWarnForFeature(ParseTree node, Feature feature) { + features = features.with(feature); + if (!isSupportedForInputLanguageMode(feature)) { + errorReporter.warning( + "this language feature is only supported for " + + LanguageMode.minimumRequiredFor(feature) + + " mode or better: " + + feature, + sourceName, + lineno(node), charno(node)); + } + } + + void maybeWarnForFeature( + com.google.javascript.jscomp.parsing.parser.Token token, Feature feature) { + features = features.with(feature); + if (!isSupportedForInputLanguageMode(feature)) { + errorReporter.warning( + "this language feature is only supported for " + + LanguageMode.minimumRequiredFor(feature) + + " mode or better: " + + feature, + sourceName, + lineno(token), charno(token)); + } + } + void setSourceInfo(Node node, Node ref) { node.setLineno(ref.getLineno()); node.setCharno(ref.getCharno()); @@ -2588,20 +2613,6 @@ private Node transformListOrEmpty( } } - void maybeWarnForFeature(ParseTree node, Feature feature) { - features = features.with(feature); - if (!isSupportedForInputLanguageMode(feature)) { - - errorReporter.warning( - "this language feature is only supported for " - + LanguageMode.minimumRequiredFor(feature) - + " mode or better: " - + feature, - sourceName, - lineno(node), charno(node)); - } - } - void maybeProcessAccessibilityModifier(ParseTree parseTree, Node n, @Nullable TokenType type) { if (type != null) { Visibility access; @@ -2975,17 +2986,13 @@ String normalizeString(LiteralToken token, boolean templateLiteral) { result.append('\u000B'); break; case '\n': - features = features.with(Feature.STRING_CONTINUATION); - if (isEs5OrBetterMode()) { - errorReporter.warning(STRING_CONTINUATION_WARNING, - sourceName, - lineno(token.location.start), charno(token.location.start)); - } else { - errorReporter.error(STRING_CONTINUATION_ERROR, - sourceName, - lineno(token.location.start), charno(token.location.start)); - } // line continuation, skip the line break + maybeWarnForFeature(token, Feature.STRING_CONTINUATION); + errorReporter.warning( + STRING_CONTINUATION_WARNING, + sourceName, + lineno(token.location.start), + charno(token.location.start)); break; case '0': if (cur + 1 >= value.length()) { @@ -3092,12 +3099,7 @@ private boolean inStrictContext() { return Double.valueOf(value); case 'b': case 'B': { - features = features.with(Feature.BINARY_LITERALS); - if (!isSupportedForInputLanguageMode(Feature.BINARY_LITERALS)) { - errorReporter.warning(BINARY_NUMBER_LITERAL_WARNING, - sourceName, - lineno(token.location.start), charno(token.location.start)); - } + maybeWarnForFeature(token, Feature.BINARY_LITERALS); double v = 0; int c = 1; while (++c < length) { @@ -3107,12 +3109,7 @@ private boolean inStrictContext() { } case 'o': case 'O': { - features = features.with(Feature.OCTAL_LITERALS); - if (!isSupportedForInputLanguageMode(Feature.OCTAL_LITERALS)) { - errorReporter.warning(OCTAL_NUMBER_LITERAL_WARNING, - sourceName, - lineno(token.location.start), charno(token.location.start)); - } + maybeWarnForFeature(token, Feature.OCTAL_LITERALS); double v = 0; int c = 1; while (++c < length) { @@ -3138,13 +3135,8 @@ private boolean inStrictContext() { if (isOctalDigit(digit)) { v = (v * 8) + octaldigit(digit); } else { - if (inStrictContext()) { - errorReporter.error(INVALID_ES5_STRICT_OCTAL, sourceName, - lineno(location.start), charno(location.start)); - } else { - errorReporter.error(INVALID_OCTAL_DIGIT, sourceName, - lineno(location.start), charno(location.start)); - } + errorReporter.error(INVALID_OCTAL_DIGIT, sourceName, + lineno(location.start), charno(location.start)); return 0; } } diff --git a/test/com/google/javascript/jscomp/NodeUtilTest.java b/test/com/google/javascript/jscomp/NodeUtilTest.java index b16dffdb6e2..129e799dd94 100644 --- a/test/com/google/javascript/jscomp/NodeUtilTest.java +++ b/test/com/google/javascript/jscomp/NodeUtilTest.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static com.google.common.truth.Truth.assertThat; +import static com.google.javascript.jscomp.DiagnosticGroups.ES5_STRICT; import static com.google.javascript.jscomp.testing.NodeSubject.assertNode; import com.google.common.base.Joiner; @@ -49,10 +50,16 @@ public final class NodeUtilTest extends TestCase { private static Node parse(String js) { + CompilerOptions options = new CompilerOptions(); + options.setLanguageIn(LanguageMode.ECMASCRIPT_2015); + + // To allow octal literals such as 0123 to be parsed. + options.setStrictModeInput(false); + options.setWarningLevel(ES5_STRICT, CheckLevel.OFF); + Compiler compiler = new Compiler(); - compiler.initCompilerOptionsIfTesting(); - compiler.getOptions().setLanguageIn(LanguageMode.ECMASCRIPT_2015); - compiler.getOptions().setStrictModeInput(true); + compiler.initOptions(options); + Node n = compiler.parseTestCode(js); assertThat(compiler.getErrors()).isEmpty(); return n; diff --git a/test/com/google/javascript/jscomp/parsing/ParserTest.java b/test/com/google/javascript/jscomp/parsing/ParserTest.java index fff0c7279bd..680dfc2075a 100644 --- a/test/com/google/javascript/jscomp/parsing/ParserTest.java +++ b/test/com/google/javascript/jscomp/parsing/ParserTest.java @@ -2072,8 +2072,11 @@ public void testStringLineContinuation() { expectFeatures(Feature.STRING_CONTINUATION); mode = LanguageMode.ECMASCRIPT3; strictMode = SLOPPY; - Node n = parseError("'one\\\ntwo';", - "String continuations are not supported in this language mode."); + Node n = parseWarning( + "'one\\\ntwo';", + requiresLanguageModeMessage(LanguageMode.ECMASCRIPT5, Feature.STRING_CONTINUATION), + "String continuations are not recommended. See" + + " https://google.github.io/styleguide/javascriptguide.xml?showone=Multiline_string_literals#Multiline_string_literals"); assertThat(n.getFirstFirstChild().getString()).isEqualTo("onetwo"); mode = LanguageMode.ECMASCRIPT5; @@ -2226,11 +2229,9 @@ public void testBinaryLiterals() { expectFeatures(Feature.BINARY_LITERALS); mode = LanguageMode.ECMASCRIPT3; strictMode = SLOPPY; - parseWarning("0b0001;", - "Binary integer literals are not supported in this language mode."); + parseWarning("0b0001;", getRequiresEs6Message(Feature.BINARY_LITERALS)); mode = LanguageMode.ECMASCRIPT5; - parseWarning("0b0001;", - "Binary integer literals are not supported in this language mode."); + parseWarning("0b0001;", getRequiresEs6Message(Feature.BINARY_LITERALS)); mode = LanguageMode.ECMASCRIPT6; parse("0b0001;"); } @@ -2239,11 +2240,9 @@ public void testOctalLiterals() { expectFeatures(Feature.OCTAL_LITERALS); mode = LanguageMode.ECMASCRIPT3; strictMode = SLOPPY; - parseWarning("0o0001;", - "Octal integer literals are not supported in this language mode."); + parseWarning("0o0001;", getRequiresEs6Message(Feature.OCTAL_LITERALS)); mode = LanguageMode.ECMASCRIPT5; - parseWarning("0o0001;", - "Octal integer literals are not supported in this language mode."); + parseWarning("0o0001;", getRequiresEs6Message(Feature.OCTAL_LITERALS)); mode = LanguageMode.ECMASCRIPT6; parse("0o0001;"); }