diff --git a/src/enableDisableRules.ts b/src/enableDisableRules.ts index e9636eaa815..8f32cb7e0d4 100644 --- a/src/enableDisableRules.ts +++ b/src/enableDisableRules.ts @@ -40,21 +40,30 @@ export class EnableDisableRulesWalker extends SkippableTokenAwareRuleWalker { scanner.getToken() === ts.SyntaxKind.SingleLineCommentTrivia) { const commentText = scanner.getTokenText(); const startPosition = scanner.getTokenPos(); - this.handlePossibleTslintSwitch(commentText, startPosition); + this.handlePossibleTslintSwitch(commentText, startPosition, node, scanner); } }); } - private handlePossibleTslintSwitch(commentText: string, startingPosition: number) { + private getStartOfLinePosition(node: ts.SourceFile, position: number, lineOffset = 0) { + return node.getPositionOfLineAndCharacter( + node.getLineAndCharacterOfPosition(position).line + lineOffset, 0 + ); + } + + private handlePossibleTslintSwitch(commentText: string, startingPosition: number, node: ts.SourceFile, scanner: ts.Scanner) { // regex is: start of string followed by "/*" or "//" followed by any amount of whitespace followed by "tslint:" if (commentText.match(/^(\/\*|\/\/)\s*tslint:/)) { const commentTextParts = commentText.split(":"); // regex is: start of string followed by either "enable" or "disable" + // followed optionally by -line or -next-line // followed by either whitespace or end of string - const enableOrDisableMatch = commentTextParts[1].match(/^(enable|disable)(\s|$)/); + const enableOrDisableMatch = commentTextParts[1].match(/^(enable|disable)(-(line|next-line))?(\s|$)/); if (enableOrDisableMatch != null) { const isEnabled = enableOrDisableMatch[1] === "enable"; + const isCurrentLine = enableOrDisableMatch[3] === "line"; + const isNextLine = enableOrDisableMatch[3] === "next-line"; let rulesList = ["all"]; if (commentTextParts.length > 2) { rulesList = commentTextParts[2].split(/\s+/); @@ -63,10 +72,31 @@ export class EnableDisableRulesWalker extends SkippableTokenAwareRuleWalker { if (!(ruleToAdd in this.enableDisableRuleMap)) { this.enableDisableRuleMap[ruleToAdd] = []; } - this.enableDisableRuleMap[ruleToAdd].push({ - isEnabled: isEnabled, - position: startingPosition, - }); + if (isCurrentLine) { + // start at the beginning of the current line + this.enableDisableRuleMap[ruleToAdd].push({ + isEnabled: isEnabled, + position: this.getStartOfLinePosition(node, startingPosition), + }); + // end at the beginning of the next line + this.enableDisableRuleMap[ruleToAdd].push({ + isEnabled: !isEnabled, + position: scanner.getTextPos() + 1, + }); + } else { + // start at the current position + this.enableDisableRuleMap[ruleToAdd].push({ + isEnabled: isEnabled, + position: startingPosition, + }); + // end at the beginning of the line following the next line + if (isNextLine) { + this.enableDisableRuleMap[ruleToAdd].push({ + isEnabled: !isEnabled, + position: this.getStartOfLinePosition(node, startingPosition, 2), + }); + } + } } } } diff --git a/test/files/enabledisable.test.ts b/test/files/enabledisable.test.ts index 79ce7112a5c..ef82e12240e 100644 --- a/test/files/enabledisable.test.ts +++ b/test/files/enabledisable.test.ts @@ -27,5 +27,19 @@ re = /`/; var AAAaA = 'test' // tslint:enable +var AAAaA = 'test' // tslint:disable-line +var AAAaA = 'test' /* tslint:disable-line */ + +// tslint:disable-next-line:quotemark variable-name +var AAAaA = 'test' +/* tslint:disable-next-line:quotemark variable-name */ +var AAAaA = 'test' + +// tslint:disable +var AAAaA = 'test' // tslint:enable-line:quotemark +// tslint:enable-next-line:variable-name +var AAAaA = 'test' +// tslint:enable + /* tslint:disable:quotemark */ var s = 'xxx'; diff --git a/test/ruleDisableEnableTests.ts b/test/ruleDisableEnableTests.ts index 9b1fcfc4bb2..8c78fc447a0 100644 --- a/test/ruleDisableEnableTests.ts +++ b/test/ruleDisableEnableTests.ts @@ -50,6 +50,9 @@ describe("Enable and Disable Rules", () => { const expectedFailure5 = quotemarkFailure([10, 13], [10, 19]); const expectedFailure6 = quotemarkFailure([16, 13], [16, 19]); + const expectedFailure7 = quotemarkFailure([39, 13], [39, 19]); + const expectedFailure8 = variableNameFailure([41, 5], [41, 10]); + const ll = new Linter(relativePath, source, options); const result = ll.lint(); const parsedResult = JSON.parse(result.output); @@ -66,6 +69,8 @@ describe("Enable and Disable Rules", () => { TestUtils.assertContainsFailure(actualFailures, expectedFailure4); TestUtils.assertContainsFailure(actualFailures, expectedFailure5); TestUtils.assertContainsFailure(actualFailures, expectedFailure6); - assert.lengthOf(actualFailures, 6); + TestUtils.assertContainsFailure(actualFailures, expectedFailure7); + TestUtils.assertContainsFailure(actualFailures, expectedFailure8); + assert.lengthOf(actualFailures, 8); }); });