Reviewers: arv-chromium, slightlylate, peterhal,
Message:
Note: I'm just cleaning out old issues. New patches will go through
github once I get up to speed on it.
----
Some open questions:
- Should '//:lint' force on checking?
- Should lint and nolint nest? Meaning, should the following be entirely
nolint?
//:nolint
var a
//:nolint
var b
//:lint
var c // ?
//:lint
- Should nolint disable checks inside an imported module?
#--cut--
dl_check() {
local f=$(basename $1)
test -e $f || curl -sO $1
openssl sha1 < $f | grep -q "= $2" && return 0
echo sha1 mismatch!
return 1
}
git checkout -b issue7801048-nolint
dl_check
https://codereview.appspot.com/download/issue7801048_1.diff \
d33432ff858dbe5a && git apply issue7801048_1.diff && make test
#--cut--
----
I have two follow-up patches for this, but I'll try submitting them
through
github. I still need to get comfortable with the new workflow.
Description:
Handle '//:lint' and '//:nolint' comments.
Currently this only disables 'strictSemicolons' inside 'nolint' zones.
The transition from 'nolint' to 'lint' is a little tricky since comments
are not tokens, meaning that for proper transition back to 'lint' mode,
you need to make sure there is a semicolon (i.e. you have to manually
add a token) either before or after the 'lint' to make sure any errors
from the 'nolint' side don't leak through.
BUG=None
TEST=test/feature/Syntax/Error_StrictSemiColonsNoLint.js
test/feature/Syntax/StrictSemiColonsNoLint.js
Please review this at
https://codereview.appspot.com/7801048/
Affected files:
M src/syntax/Parser.js
M src/syntax/Scanner.js
A test/feature/Syntax/Error_StrictSemiColonsNoLint.js
A test/feature/Syntax/StrictSemiColonsNoLint.js
Index: src/syntax/Parser.js
diff --git a/src/syntax/Parser.js b/src/syntax/Parser.js
index
323065f9ae8ca7fe5767d788ada70239b0aaa26a..d74233ca0b38b386cb36ce6f4eafe346229c9ac2
100644
--- a/src/syntax/Parser.js
+++ b/src/syntax/Parser.js
@@ -134,7 +134,7 @@ export class Parser {
*/
constructor(errorReporter, file) {
this.errorReporter_ = errorReporter;
- this.scanner_ = new Scanner(errorReporter, file);
+ this.scanner_ = new Scanner(errorReporter, file, this);
/**
* Keeps track of whether we currently allow yield expressions.
@@ -142,6 +142,7 @@ export class Parser {
* @private
*/
this.allowYield_ = options.unstarredGenerators;
+ this.noLint = false;
}
// 14 Program
@@ -3410,7 +3411,7 @@ export class Parser {
eatPossibleImplicitSemiColon_() {
var token = this.peekTokenNoLineTerminator_();
if (!token) {
- if (!options.strictSemicolons)
+ if (!options.strictSemicolons || this.noLint)
return;
} else {
switch (token.type) {
@@ -3419,7 +3420,7 @@ export class Parser {
return;
case END_OF_FILE:
case CLOSE_CURLY:
- if (!options.strictSemicolons)
+ if (!options.strictSemicolons || this.noLint)
return;
}
}
Index: src/syntax/Scanner.js
diff --git a/src/syntax/Scanner.js b/src/syntax/Scanner.js
index
efb5126c1d455476418cda98b8ba7225c5f76c65..5f387230fa02dd38dac75968765c0df04ae07353
100644
--- a/src/syntax/Scanner.js
+++ b/src/syntax/Scanner.js
@@ -247,7 +247,7 @@ function isRegularExpressionFirstChar(code) {
}
var index, input, length, token, lastToken, lookaheadToken,
currentCharCode,
- lineNumberTable, errorReporter;
+ lineNumberTable, errorReporter, currentParser;
/**
* Scans javascript source code into tokens. All entrypoints assume the
@@ -263,7 +263,7 @@ export class Scanner {
* @param {ErrorReport} reporter
* @param {SourceFile} file
*/
- constructor(reporter, file) {
+ constructor(reporter, file, parser) {
// These are not instance fields and this class should probably be
refactor
// to not give a false impression that multiple instances can be
created.
errorReporter = reporter;
@@ -275,6 +275,7 @@ export class Scanner {
token = null;
lookaheadToken = null;
updateCurrentCharCode();
+ currentParser = parser;
}
get lastToken() {
@@ -608,9 +609,20 @@ function skipComment() {
}
function skipSingleLineComment() {
- while (!isAtEnd() && !isLineTerminator(currentCharCode)) {
- next();
+ var c, text;
+ index += 2;
+ if (!isAtEnd() && !isLineTerminator(c = input.charCodeAt(index++))) {
+ // Check for '//:' first so that we can immediately skip the expensive
slice
+ // and regexp for normal comments.
+ if (c === 58) { // :
+ text = input.slice(index, index + 6);
+ if (text.search(/^(?:no)?lint\b/) === 0)
+ currentParser.noLint = text[0] === 'n';
+ }
+ while (!isAtEnd() && !isLineTerminator(input.charCodeAt(index++))) {}
}
+
+ updateCurrentCharCode();
}
function skipMultiLineComment() {
Index: test/feature/Syntax/Error_StrictSemiColonsNoLint.js
diff --git a/test/feature/Syntax/Error_StrictSemiColonsNoLint.js
b/test/feature/Syntax/Error_StrictSemiColonsNoLint.js
new file mode 100644
index
0000000000000000000000000000000000000000..1833213a591d69a8d4676f1e62856d4db1385661
--- /dev/null
+++ b/test/feature/Syntax/Error_StrictSemiColonsNoLint.js
@@ -0,0 +1,34 @@
+// Should not compile.
+// Options: --strict-semicolons
+// Error: 34:1: Semi-colon expected
+
+//:this is a nolint error test.
+// It is identical to StrictSemiColonsNoLint.js except for one missing
+// semicolon.
+
+// Note: The leading letter in the var names changes for each expected
+// transition between lint and nolint.
+var a0;
+var a1;
+//:nolint
+var b2
+//:nolint These don't nest (should they?).
+var b3
+// hello lint
+var b4
+var b5
+var b6;
+var b7
+var b8
+//:lint
+//:nolint
+var c1
+var c2
+//:hello lint
+var c3
+var c4
+; // Necessary for nolint-to-lint transitions.
+//:lint
+var d1 // <<< missing semicolon here. The error location is at the next
token.
+//:lint
+var d2;
Index: test/feature/Syntax/StrictSemiColonsNoLint.js
diff --git a/test/feature/Syntax/StrictSemiColonsNoLint.js
b/test/feature/Syntax/StrictSemiColonsNoLint.js
new file mode 100644
index
0000000000000000000000000000000000000000..936fa9597ccdcf5aca565b769db86a09d8247a66
--- /dev/null
+++ b/test/feature/Syntax/StrictSemiColonsNoLint.js
@@ -0,0 +1,30 @@
+// Options: --strict-semicolons
+
+//:this is a nolint test.
+
+// Note: The leading letter in the var names changes for each expected
+// transition between lint and nolint.
+var a0;
+var a1;
+//:nolint
+var b2
+//:nolint These don't nest (should they?).
+var b3
+// hello lint
+var b4
+var b5
+var b6;
+var b7
+var b8
+//:lint
+//:nolint
+var c1
+var c2
+//:hello lint
+var c3
+var c4
+; // Necessary for nolint-to-lint transitions.
+//:lint
+var d1;
+//:lint
+var d2;