From 706acdf13834bfd479b63aced65e157033353c42 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 13:40:15 -0800 Subject: [PATCH] Add quick fix to disable error checking in a .js file --- src/compiler/diagnosticMessages.json | 10 +++ .../codefixes/disableJsDiagnostics.ts | 67 +++++++++++++++++++ src/services/codefixes/fixes.ts | 1 + .../codefixes/unusedIdentifierFixes.ts | 12 +--- src/services/tsconfig.json | 3 +- src/services/utilities.ts | 7 ++ .../codeFixDisableJsDiagnosticsInFile.ts | 11 +++ .../codeFixDisableJsDiagnosticsInFile2.ts | 15 +++++ .../codeFixDisableJsDiagnosticsInFile3.ts | 14 ++++ .../codeFixDisableJsDiagnosticsInFile4.ts | 18 +++++ .../codeFixDisableJsDiagnosticsInFile5.ts | 17 +++++ .../codeFixDisableJsDiagnosticsInFile6.ts | 17 +++++ .../codeFixDisableJsDiagnosticsInFile7.ts | 17 +++++ .../codeFixDisableJsDiagnosticsInFile8.ts | 19 ++++++ 14 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 src/services/codefixes/disableJsDiagnostics.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile2.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts create mode 100644 tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 83b4cb961a4..6495f6d9ac4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3355,6 +3355,16 @@ "category": "Message", "code": 90017 }, + "Disable checking for this file.": { + "category": "Message", + "code": 90018 + }, + "Suppress this error message.": { + "category": "Message", + "code": 90019 + }, + + "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { "category": "Error", "code": 8017 diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts new file mode 100644 index 00000000000..6e4a5f38586 --- /dev/null +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -0,0 +1,67 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: getApplicableDiagnosticCodes(), + getCodeActions: getDisableJsDiagnosticsCodeActions + }); + + function getApplicableDiagnosticCodes(): number[] { + const allDiagnostcs = >Diagnostics; + return Object.keys(allDiagnostcs) + .filter(d => allDiagnostcs[d] && allDiagnostcs[d].category === DiagnosticCategory.Error) + .map(d => allDiagnostcs[d].code); + } + + function shouldCheckJsFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) { + return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; + } + + function getSuppressCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string) { + let { line } = getLineAndCharacterOfPosition(sourceFile, position); + const lineStartPosition = getStartPositionOfLine(line, sourceFile); + const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); + if (!isInComment(sourceFile, startPosition) && !isInString(sourceFile, startPosition) && !isInTemplateString(sourceFile, startPosition)) { + const token = getTouchingToken(sourceFile, startPosition); + const tokenLeadingCommnets = getLeadingCommentRangesOfNode(token, sourceFile) + if (!tokenLeadingCommnets || !tokenLeadingCommnets.length || tokenLeadingCommnets[0].pos >= startPosition) { + return { + span: { start: startPosition, length: 0 }, + newText: `// @ts-suppress${newLineCharacter}` + }; + } + } + return { + span: { start: position, length: 0 }, + newText: `${position === startPosition ? "" : newLineCharacter}// @ts-suppress${newLineCharacter}` + }; + } + + function getDisableJsDiagnosticsCodeActions(context: CodeFixContext): CodeAction[] | undefined { + const { sourceFile, program, newLineCharacter, span } = context; + + if (!isInJavaScriptFile(sourceFile) || !shouldCheckJsFile(sourceFile, program.getCompilerOptions())) { + return undefined; + } + + return [{ + description: getLocaleSpecificMessage(Diagnostics.Suppress_this_error_message), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [getSuppressCommentLocationForLocation(sourceFile, span.start, newLineCharacter)] + }] + }, + { + description: getLocaleSpecificMessage(Diagnostics.Disable_checking_for_this_file), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { + start: sourceFile.checkJsDirective ? sourceFile.checkJsDirective.pos : 0, + length: sourceFile.checkJsDirective ? sourceFile.checkJsDirective.end - sourceFile.checkJsDirective.pos : 0 + }, + newText: `// @ts-nocheck${newLineCharacter}` + }] + }] + }]; + } +} \ No newline at end of file diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index 76be34c67cd..ae1643dfa3b 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -7,4 +7,5 @@ /// /// /// +/// /// diff --git a/src/services/codefixes/unusedIdentifierFixes.ts b/src/services/codefixes/unusedIdentifierFixes.ts index 61d48bdc3bc..6c8bd0a9dbe 100644 --- a/src/services/codefixes/unusedIdentifierFixes.ts +++ b/src/services/codefixes/unusedIdentifierFixes.ts @@ -105,9 +105,10 @@ namespace ts.codefix { else { // import |d,| * as ns from './file' const start = importClause.name.getStart(); - let end = findFirstNonSpaceCharPosStarting(importClause.name.end); + const text = sourceFile.text; + let end = getFirstNonSpaceCharacterPosition(text, importClause.name.end); if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) { - end = findFirstNonSpaceCharPosStarting(end + 1); + end = getFirstNonSpaceCharacterPosition(text, end + 1); } return createCodeFix("", start, end - start); @@ -166,13 +167,6 @@ namespace ts.codefix { return createCodeFix("", start, end - start); } - function findFirstNonSpaceCharPosStarting(start: number) { - while (isWhiteSpace(sourceFile.text.charCodeAt(start))) { - start += 1; - } - return start; - } - function createCodeFix(newText: string, start: number, length: number): CodeAction[] { return [{ description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }), diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 93f861e80aa..b97b3c509f8 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -90,6 +90,7 @@ "codefixes/fixes.ts", "codefixes/helpers.ts", "codefixes/importFixes.ts", - "codefixes/unusedIdentifierFixes.ts" + "codefixes/unusedIdentifierFixes.ts", + "codefixes/disableJsDiagnostics.ts" ] } \ No newline at end of file diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 7c5bf862fc8..c894df121f8 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1388,4 +1388,11 @@ namespace ts { // First token is the open curly, this is where we want to put the 'super' call. return constructor.body.getFirstToken(sourceFile).getEnd(); } + + export function getFirstNonSpaceCharacterPosition(text: string, position: number) { + while (isWhiteSpace(text.charCodeAt(position))) { + position += 1; + } + return position; + } } diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile.ts new file mode 100644 index 00000000000..070712c2523 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile.ts @@ -0,0 +1,11 @@ +/// + +// @allowjs: true +// @noEmit: true + +// @Filename: a.js +////[|// @ts-check|] +////var x = ""; +////x = 1; + +verify.rangeAfterCodeFix("// @ts-nocheck", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile2.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile2.ts new file mode 100644 index 00000000000..4a55f2ba44f --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile2.ts @@ -0,0 +1,15 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////[|var x = ""; +////x = 1;|] + +// Disable checking for the whole file +verify.rangeAfterCodeFix(`// @ts-nocheck +var x = ""; +x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); + diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts new file mode 100644 index 00000000000..f486a7e171b --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts @@ -0,0 +1,14 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////[|var x = ""; +////x = 1;|] + +// Disable checking for next line +verify.rangeAfterCodeFix(`var x = ""; +// @ts-suppress +x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts new file mode 100644 index 00000000000..cadbda2c273 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts @@ -0,0 +1,18 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////var x = ""; +//// +////[|"test \ +////"; x = 1;|] + +// Disable checking for next line +verify.rangeAfterCodeFix(`"test \\ +"; +// @ts-suppress +x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); + diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts new file mode 100644 index 00000000000..56b9fbf20d9 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts @@ -0,0 +1,17 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////var x = ""; +//// +////[|/** comment */ +////x = 1;|] + +// Disable checking for next line +verify.rangeAfterCodeFix(`/** comment */ +// @ts-suppress +x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); + diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts new file mode 100644 index 00000000000..a0497b4deb9 --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts @@ -0,0 +1,17 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////var x = 0; +//// +////function f(_a) { +//// [|f(x());|] +////} + +// Disable checking for next line +verify.rangeAfterCodeFix(`// @ts-suppress + f(x());`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); + diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts new file mode 100644 index 00000000000..ad8377e129d --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts @@ -0,0 +1,17 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////var x = 0; +//// +////function f(_a) { +//// [|x();|] +////} + +// Disable checking for next line +verify.rangeAfterCodeFix(`// @ts-suppress + x();`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); + diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts new file mode 100644 index 00000000000..8ec350479af --- /dev/null +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts @@ -0,0 +1,19 @@ +/// + +// @allowjs: true +// @noEmit: true +// @checkJs: true + +// @Filename: a.js +////var x = 0; +//// +////function f(_a) { +//// /** comment for f */ +//// [|f(x());|] +////} + +// Disable checking for next line +verify.rangeAfterCodeFix(`f( + // @ts-suppress + x());`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); +