-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow skipping diagnostics in .js file using comments and quick fixes to add them #14568
Changes from 4 commits
91571f0
fe7719f
706acdf
13e80b9
936a91d
cc6affa
6e86596
fd9fb8f
509b2dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* @internal */ | ||
namespace ts.codefix { | ||
registerCodeFix({ | ||
errorCodes: getApplicableDiagnosticCodes(), | ||
getCodeActions: getDisableJsDiagnosticsCodeActions | ||
}); | ||
|
||
function getApplicableDiagnosticCodes(): number[] { | ||
const allDiagnostcs = <MapLike<DiagnosticMessage>>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); | ||
|
||
// First try to see if we can put the '// @ts-suppress' on the previous line. | ||
// We need to make sure that we are not in the middle of a string literal or a comment. | ||
// We also want to check if the previous line holds a comment for a node on the next line | ||
// if so, we do not want to separate the node from its comment if we can. | ||
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}` | ||
}; | ||
} | ||
} | ||
|
||
// If all fails, add an extra new line immediatlly before the error span. | ||
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}` | ||
}] | ||
}] | ||
}]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
=== tests/cases/compiler/a.js === | ||
|
||
var x = 0; | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
||
|
||
/// @ts-suppress | ||
x(); | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
||
/// @ts-suppress | ||
x(); | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
||
/// @ts-suppress | ||
x( | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
||
2, | ||
3); | ||
|
||
|
||
|
||
// @ts-suppress | ||
// come comment | ||
// some other comment | ||
|
||
// @anohter | ||
|
||
x(); | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
||
|
||
|
||
// @ts-suppress: no call signature | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just an arbitrary message rather than something indicating a specific diagnostic to suppress, right? Could be useful to have a way to give a specific one to hide (say, something matching There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is what i had in mind with test. but the error code seemed fairly useless. like you need to go somewhere to know what I think this is something we can target for in the future. |
||
x(); | ||
>x : Symbol(x, Decl(a.js, 1, 3)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
=== tests/cases/compiler/a.js === | ||
|
||
var x = 0; | ||
>x : number | ||
>0 : 0 | ||
|
||
|
||
/// @ts-suppress | ||
x(); | ||
>x() : any | ||
>x : number | ||
|
||
/// @ts-suppress | ||
x(); | ||
>x() : any | ||
>x : number | ||
|
||
/// @ts-suppress | ||
x( | ||
>x( 2, 3) : any | ||
>x : number | ||
|
||
2, | ||
>2 : 2 | ||
|
||
3); | ||
>3 : 3 | ||
|
||
|
||
|
||
// @ts-suppress | ||
// come comment | ||
// some other comment | ||
|
||
// @anohter | ||
|
||
x(); | ||
>x() : any | ||
>x : number | ||
|
||
|
||
|
||
// @ts-suppress: no call signature | ||
x(); | ||
>x() : any | ||
>x : number | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// @allowJs: true | ||
// @checkJs: true | ||
// @noEmit: true | ||
|
||
// @fileName: a.js | ||
var x = 0; | ||
|
||
|
||
/// @ts-suppress | ||
x(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it supposed to work in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nope. js only and only for semantic errors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually wanted this functionality in .ts a few days ago -- embedding a chunk of stable JS code in TS code. Sometimes you need to embed code rather than have it as an external module, for encapsulation. Such as, I was writing a plugin that needed to use compression, and I've embedded LZW algo in my ts plugin. Of course LZW algo in JS needed a bunch of |
||
|
||
/// @ts-suppress | ||
x(); | ||
|
||
/// @ts-suppress | ||
x( | ||
2, | ||
3); | ||
|
||
|
||
|
||
// @ts-suppress | ||
// come comment | ||
// some other comment | ||
|
||
// @anohter | ||
|
||
x(); | ||
|
||
|
||
|
||
// @ts-suppress: no call signature | ||
x(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/// <reference path='fourslash.ts' /> | ||
|
||
// @allowjs: true | ||
// @noEmit: true | ||
|
||
// @Filename: a.js | ||
////[|// @ts-check|] | ||
////var x = ""; | ||
////x = 1; | ||
|
||
verify.rangeAfterCodeFix("// @ts-nocheck", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/// <reference path='fourslash.ts' /> | ||
|
||
// @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); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/// <reference path='fourslash.ts' /> | ||
|
||
// @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); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/// <reference path='fourslash.ts' /> | ||
|
||
// @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); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to add an entry in
src/harness/tsconfig.json
as well?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added.