From 9cb87a554967d9772bf984ab107cb2805723717b Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Thu, 23 Mar 2017 21:39:26 +0100 Subject: [PATCH 1/2] Refactor linebreak-style [new-fixer] `linebreak-style` The rule checks the line ending directly in the source text instead of using a scanner. That way we also find failures inside multiline comments and template strings. --- src/rules/linebreakStyleRule.ts | 56 +++++++------------ .../linebreak-style/failure/CRLF/test.js.fix | 4 ++ .../linebreak-style/failure/CRLF/test.ts.fix | 4 ++ .../linebreak-style/failure/LF/test.js.fix | 4 ++ .../linebreak-style/failure/LF/test.ts.fix | 4 ++ 5 files changed, 37 insertions(+), 35 deletions(-) create mode 100644 test/rules/linebreak-style/failure/CRLF/test.js.fix create mode 100644 test/rules/linebreak-style/failure/CRLF/test.ts.fix create mode 100644 test/rules/linebreak-style/failure/LF/test.js.fix create mode 100644 test/rules/linebreak-style/failure/LF/test.ts.fix diff --git a/src/rules/linebreakStyleRule.ts b/src/rules/linebreakStyleRule.ts index 07fc208c40a..c73c9556103 100644 --- a/src/rules/linebreakStyleRule.ts +++ b/src/rules/linebreakStyleRule.ts @@ -39,48 +39,34 @@ export class Rule extends Lint.Rules.AbstractRule { optionExamples: [`[true, "${OPTION_LINEBREAK_STYLE_LF}"]`, `[true, "${OPTION_LINEBREAK_STYLE_CRLF}"]`], type: "maintainability", typescriptOnly: false, + hasFix: true, }; /* tslint:enable:object-literal-sort-keys */ - public static FAILURE_STRINGS = { - CRLF: `Expected linebreak to be '${OPTION_LINEBREAK_STYLE_CRLF}'`, - LF: `Expected linebreak to be '${OPTION_LINEBREAK_STYLE_LF}'`, - }; + public static FAILURE_CRLF = `Expected linebreak to be '${OPTION_LINEBREAK_STYLE_CRLF}'`; + public static FAILURE_LF = `Expected linebreak to be '${OPTION_LINEBREAK_STYLE_LF}'`; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const failures: Lint.RuleFailure[] = []; - const scanner = ts.createScanner( - sourceFile.languageVersion, - false, - sourceFile.languageVariant, - sourceFile.getFullText(), - ); - - const ruleArguments = this.getOptions().ruleArguments; - const linebreakStyle = ruleArguments.length > 0 ? ruleArguments[0] : OPTION_LINEBREAK_STYLE_LF; - const expectLF = linebreakStyle === OPTION_LINEBREAK_STYLE_CRLF; - const expectedEOL = expectLF ? "\r\n" : "\n"; - const failureString = expectLF ? Rule.FAILURE_STRINGS.CRLF : Rule.FAILURE_STRINGS.LF; + return this.applyWithFunction(sourceFile, walk, this.ruleArguments.indexOf(OPTION_LINEBREAK_STYLE_CRLF) !== -1); + } +} - for (let token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) { - if (token === ts.SyntaxKind.NewLineTrivia) { - const text = scanner.getTokenText(); - if (text !== expectedEOL) { - failures.push(this.createFailure(sourceFile, scanner, failureString)); - } +function walk(ctx: Lint.WalkContext) { + const expectedCr = ctx.options; + const sourceText = ctx.sourceFile.text; + const lineStarts = ctx.sourceFile.getLineStarts(); + for (let i = 1; i < lineStarts.length; ++i) { + const lineEnd = lineStarts[i] - 1; + if (sourceText[lineEnd - 1] === "\r") { + if (!expectedCr) { + ctx.addFailure(lineStarts[i - 1], lineEnd - 1, Rule.FAILURE_LF, ctx.createFix( + Lint.Replacement.deleteText(lineEnd - 1, 1), + )); } + } else if (expectedCr) { + ctx.addFailure(lineStarts[i - 1], lineEnd, Rule.FAILURE_CRLF, ctx.createFix( + Lint.Replacement.appendText(lineEnd, "\r"), + )); } - - return failures; - } - - public createFailure(sourceFile: ts.SourceFile, scanner: ts.Scanner, failure: string): Lint.RuleFailure { - // get the start of the current line - const start = sourceFile.getPositionOfLineAndCharacter(sourceFile.getLineAndCharacterOfPosition(scanner.getStartPos()).line, 0); - // since line endings are not visible, we simply end at the beginning of - // the line ending, which happens to be the start of the token. - const end = scanner.getStartPos(); - - return new Lint.RuleFailure(sourceFile, start, end, failure, this.getOptions().ruleName); } } diff --git a/test/rules/linebreak-style/failure/CRLF/test.js.fix b/test/rules/linebreak-style/failure/CRLF/test.js.fix new file mode 100644 index 00000000000..4a60171c332 --- /dev/null +++ b/test/rules/linebreak-style/failure/CRLF/test.js.fix @@ -0,0 +1,4 @@ +// this line uses CRLF +// this line uses CRLF +// this line uses CRLF +// this line uses CRLF diff --git a/test/rules/linebreak-style/failure/CRLF/test.ts.fix b/test/rules/linebreak-style/failure/CRLF/test.ts.fix new file mode 100644 index 00000000000..4a60171c332 --- /dev/null +++ b/test/rules/linebreak-style/failure/CRLF/test.ts.fix @@ -0,0 +1,4 @@ +// this line uses CRLF +// this line uses CRLF +// this line uses CRLF +// this line uses CRLF diff --git a/test/rules/linebreak-style/failure/LF/test.js.fix b/test/rules/linebreak-style/failure/LF/test.js.fix new file mode 100644 index 00000000000..1f88a5a75a2 --- /dev/null +++ b/test/rules/linebreak-style/failure/LF/test.js.fix @@ -0,0 +1,4 @@ +// this line uses LF +// this line uses LF +// this line uses LF +// this line uses LF diff --git a/test/rules/linebreak-style/failure/LF/test.ts.fix b/test/rules/linebreak-style/failure/LF/test.ts.fix new file mode 100644 index 00000000000..1f88a5a75a2 --- /dev/null +++ b/test/rules/linebreak-style/failure/LF/test.ts.fix @@ -0,0 +1,4 @@ +// this line uses LF +// this line uses LF +// this line uses LF +// this line uses LF From f81bda6d13f2a4ad171dfd87a490d82cb5089692 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Fri, 24 Mar 2017 09:09:28 +0100 Subject: [PATCH 2/2] Fix line endings in tests --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 97de27519a4..f141c2ac31b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,4 @@ *.lint text eol=lf *.fix text eol=lf /test/rules/linebreak-style/**/CRLF/*.lint text eol=crlf +/test/rules/linebreak-style/**/LF/*.fix text eol=crlf