From 91571f05d31b968d30ef358f505ae2c837c30faf Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 23 Feb 2017 15:58:49 -0800 Subject: [PATCH 01/21] Add support for handeling .js file correctelly in fixAddMissingMember code fix --- src/compiler/diagnosticMessages.json | 5 ++ src/services/codefixes/fixAddMissingMember.ts | 82 ++++++++++++------- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b9572b2b0f4b5..d1c7f82eadcc0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3351,6 +3351,11 @@ "category": "Message", "code": 90017 }, + "Initialize property '{0}' in the constructor.": { + "category": "Message", + "code": 90018 + }, + "Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": { "category": "Error", "code": 8017 diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 6ae2ba3f51c99..fe4176a766a07 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -23,45 +23,67 @@ namespace ts.codefix { return undefined; } - if (!(token.parent && token.parent.kind === SyntaxKind.PropertyAccessExpression)) { + if (!isPropertyAccessExpression(token.parent) || token.parent.expression.kind !== SyntaxKind.ThisKeyword) { return undefined; } - if ((token.parent as PropertyAccessExpression).expression.kind !== SyntaxKind.ThisKeyword) { - return undefined; - } + return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile(); - let typeString = "any"; - if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { - const binaryExpression = token.parent.parent as BinaryExpression; + function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined { + let typeString = "any"; - const checker = context.program.getTypeChecker(); - const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right))); - typeString = checker.typeToString(widenedType); - } + if (token.parent.parent.kind === SyntaxKind.BinaryExpression) { + const binaryExpression = token.parent.parent as BinaryExpression; - const startPos = classDeclaration.members.pos; + const checker = context.program.getTypeChecker(); + const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right))); + typeString = checker.typeToString(widenedType); + } - return [{ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: startPos, length: 0 }, - newText: `${token.getFullText(sourceFile)}: ${typeString};` + const startPos = classDeclaration.members.pos; + + return [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: `${token.getFullText(sourceFile)}: ${typeString};` + }] + }] + }, + { + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: `[name: string]: ${typeString};` + }] }] - }] - }, - { - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: startPos, length: 0 }, - newText: `[name: string]: ${typeString};` + }]; + } + + function getActionsForAddMissingMemberInJavaScriptFile(): CodeAction[] | undefined { + const classConstructor = getFirstConstructorWithBody(classDeclaration); + if (!classConstructor) { + return undefined; + } + + const memberName = token.getText(); + const startPos = classConstructor.body.getEnd() - 1; + + return [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [memberName]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: `this.${memberName} = undefined;` + }] }] - }] - }]; + }]; + } } } \ No newline at end of file From 0b1fff7e66a93b6e887895725f8c10b4b1b9b28e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 6 Jan 2017 17:15:39 -0800 Subject: [PATCH 02/21] Add `--checkJsFiles` --- src/compiler/commandLineParser.ts | 6 ++++++ src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/program.ts | 2 +- src/compiler/types.ts | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index dc69297289116..85a099c6dcaad 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -481,6 +481,12 @@ namespace ts { name: "plugin", type: "object" } + }, + { + name: "checkJsFiles", + type: "boolean", + experimental: true, + description: Diagnostics.Report_errors_in_js_files } ]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 318f06ceeaa3f..83b4cb961a45a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3362,5 +3362,9 @@ "Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": { "category": "Error", "code": 8018 + }, + "Report errors in .js files.": { + "category": "Message", + "code": 8019 } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d9ddf486e0d1d..ecef2377baed3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -907,7 +907,7 @@ namespace ts { // For JavaScript files, we don't want to report semantic errors. // Instead, we'll report errors for using TypeScript-only constructs from within a // JavaScript file when we get syntactic diagnostics for the file. - const checkDiagnostics = isSourceFileJavaScript(sourceFile) ? [] : typeChecker.getDiagnostics(sourceFile, cancellationToken); + const checkDiagnostics = !options.checkJsFiles && isSourceFileJavaScript(sourceFile) ? [] : typeChecker.getDiagnostics(sourceFile, cancellationToken); const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f96f8623885ca..02d0a784b3dbc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3312,6 +3312,7 @@ alwaysStrict?: boolean; // Always combine with strict property baseUrl?: string; charset?: string; + checkJsFiles?: boolean; /* @internal */ configFilePath?: string; declaration?: boolean; declarationDir?: string; From 9f0c5ce1418df7ffb14eb7fefca4910a436dd3d2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 6 Jan 2017 19:03:17 -0800 Subject: [PATCH 03/21] Add support for `//@check` directives --- src/compiler/parser.ts | 5 +++++ src/compiler/program.ts | 3 ++- src/compiler/types.ts | 1 + src/services/services.ts | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 308d3a317f94e..48fe3ce542607 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5817,6 +5817,7 @@ namespace ts { const typeReferenceDirectives: FileReference[] = []; const amdDependencies: { path: string; name: string }[] = []; let amdModuleName: string; + let hasCheckDirective = false; // Keep scanning all the leading trivia in the file until we get to something that // isn't trivia. Any single line comment will be analyzed to see if it is a @@ -5878,6 +5879,9 @@ namespace ts { amdDependencies.push(amdDependency); } } + + const checkDirectiveRegEx = /^\/\/\s*@check\s*/gim; + hasCheckDirective = hasCheckDirective || !!checkDirectiveRegEx.exec(comment); } } @@ -5885,6 +5889,7 @@ namespace ts { sourceFile.typeReferenceDirectives = typeReferenceDirectives; sourceFile.amdDependencies = amdDependencies; sourceFile.moduleName = amdModuleName; + sourceFile.hasCheckDirective = hasCheckDirective; } function setExternalModuleIndicator(sourceFile: SourceFile) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ecef2377baed3..64da4f6de7126 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -907,7 +907,8 @@ namespace ts { // For JavaScript files, we don't want to report semantic errors. // Instead, we'll report errors for using TypeScript-only constructs from within a // JavaScript file when we get syntactic diagnostics for the file. - const checkDiagnostics = !options.checkJsFiles && isSourceFileJavaScript(sourceFile) ? [] : typeChecker.getDiagnostics(sourceFile, cancellationToken); + const includeCheckDiagnostics = options.checkJsFiles || sourceFile.hasCheckDirective || !isSourceFileJavaScript(sourceFile); + const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 02d0a784b3dbc..3028b295d276a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2272,6 +2272,7 @@ /* @internal */ moduleAugmentations: LiteralExpression[]; /* @internal */ patternAmbientModules?: PatternAmbientModule[]; /* @internal */ ambientModuleNames: string[]; + /* @internal */ hasCheckDirective: boolean; } export interface Bundle extends Node { diff --git a/src/services/services.ts b/src/services/services.ts index f122e39bcc617..037894661ff6f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -473,6 +473,7 @@ namespace ts { public moduleAugmentations: LiteralExpression[]; private namedDeclarations: Map; public ambientModuleNames: string[]; + public hasCheckDirective: boolean; constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end); From 0b247b12a35b004f90489fcd9bc05bdc210a6394 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 6 Mar 2017 14:49:50 -0800 Subject: [PATCH 04/21] Add tests --- tests/baselines/reference/checkJsFiles.errors.txt | 13 +++++++++++++ tests/baselines/reference/checkJsFiles2.errors.txt | 14 ++++++++++++++ tests/baselines/reference/checkJsFiles3.errors.txt | 14 ++++++++++++++ tests/cases/compiler/checkJsFiles.ts | 6 ++++++ tests/cases/compiler/checkJsFiles2.ts | 7 +++++++ tests/cases/compiler/checkJsFiles3.ts | 6 ++++++ 6 files changed, 60 insertions(+) create mode 100644 tests/baselines/reference/checkJsFiles.errors.txt create mode 100644 tests/baselines/reference/checkJsFiles2.errors.txt create mode 100644 tests/baselines/reference/checkJsFiles3.errors.txt create mode 100644 tests/cases/compiler/checkJsFiles.ts create mode 100644 tests/cases/compiler/checkJsFiles2.ts create mode 100644 tests/cases/compiler/checkJsFiles3.ts diff --git a/tests/baselines/reference/checkJsFiles.errors.txt b/tests/baselines/reference/checkJsFiles.errors.txt new file mode 100644 index 0000000000000..8371e101dd1da --- /dev/null +++ b/tests/baselines/reference/checkJsFiles.errors.txt @@ -0,0 +1,13 @@ +error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +tests/cases/compiler/a.js(3,1): error TS2322: Type '0' is not assignable to type 'string'. + + +!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +==== tests/cases/compiler/a.js (1 errors) ==== + + var x = "string"; + x = 0; + ~ +!!! error TS2322: Type '0' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/checkJsFiles2.errors.txt b/tests/baselines/reference/checkJsFiles2.errors.txt new file mode 100644 index 0000000000000..566ba3786b857 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles2.errors.txt @@ -0,0 +1,14 @@ +error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type 'string'. + + +!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +==== tests/cases/compiler/a.js (1 errors) ==== + + // @check + var x = "string"; + x = 0; + ~ +!!! error TS2322: Type '0' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/checkJsFiles3.errors.txt b/tests/baselines/reference/checkJsFiles3.errors.txt new file mode 100644 index 0000000000000..566ba3786b857 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles3.errors.txt @@ -0,0 +1,14 @@ +error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. + Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type 'string'. + + +!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. +!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. +==== tests/cases/compiler/a.js (1 errors) ==== + + // @check + var x = "string"; + x = 0; + ~ +!!! error TS2322: Type '0' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles.ts b/tests/cases/compiler/checkJsFiles.ts new file mode 100644 index 0000000000000..c36673b0239f3 --- /dev/null +++ b/tests/cases/compiler/checkJsFiles.ts @@ -0,0 +1,6 @@ +// @allowJs: true +// @checkJsFiles: true + +// @fileName: a.js +var x = "string"; +x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles2.ts b/tests/cases/compiler/checkJsFiles2.ts new file mode 100644 index 0000000000000..fe8978666b061 --- /dev/null +++ b/tests/cases/compiler/checkJsFiles2.ts @@ -0,0 +1,7 @@ +// @allowJs: true +// @checkJsFiles: false + +// @fileName: a.js +// @check +var x = "string"; +x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles3.ts b/tests/cases/compiler/checkJsFiles3.ts new file mode 100644 index 0000000000000..964f909bc6f69 --- /dev/null +++ b/tests/cases/compiler/checkJsFiles3.ts @@ -0,0 +1,6 @@ +// @allowJs: true + +// @fileName: a.js +// @check +var x = "string"; +x = 0; \ No newline at end of file From 1f9bb693ec389ae740da78106f46794a4653645a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 6 Mar 2017 21:01:47 -0800 Subject: [PATCH 05/21] Add --noEmit to tests --- tests/baselines/reference/checkJsFiles.errors.txt | 4 ---- tests/baselines/reference/checkJsFiles2.errors.txt | 4 ---- tests/baselines/reference/checkJsFiles3.errors.txt | 4 ---- tests/cases/compiler/checkJsFiles.ts | 1 + tests/cases/compiler/checkJsFiles2.ts | 1 + tests/cases/compiler/checkJsFiles3.ts | 1 + 6 files changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/checkJsFiles.errors.txt b/tests/baselines/reference/checkJsFiles.errors.txt index 8371e101dd1da..41344dc384aee 100644 --- a/tests/baselines/reference/checkJsFiles.errors.txt +++ b/tests/baselines/reference/checkJsFiles.errors.txt @@ -1,10 +1,6 @@ -error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. - Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. tests/cases/compiler/a.js(3,1): error TS2322: Type '0' is not assignable to type 'string'. -!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. -!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. ==== tests/cases/compiler/a.js (1 errors) ==== var x = "string"; diff --git a/tests/baselines/reference/checkJsFiles2.errors.txt b/tests/baselines/reference/checkJsFiles2.errors.txt index 566ba3786b857..5c1a211a646fb 100644 --- a/tests/baselines/reference/checkJsFiles2.errors.txt +++ b/tests/baselines/reference/checkJsFiles2.errors.txt @@ -1,10 +1,6 @@ -error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. - Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type 'string'. -!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. -!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. ==== tests/cases/compiler/a.js (1 errors) ==== // @check diff --git a/tests/baselines/reference/checkJsFiles3.errors.txt b/tests/baselines/reference/checkJsFiles3.errors.txt index 566ba3786b857..5c1a211a646fb 100644 --- a/tests/baselines/reference/checkJsFiles3.errors.txt +++ b/tests/baselines/reference/checkJsFiles3.errors.txt @@ -1,10 +1,6 @@ -error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. - Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type 'string'. -!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file. -!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. ==== tests/cases/compiler/a.js (1 errors) ==== // @check diff --git a/tests/cases/compiler/checkJsFiles.ts b/tests/cases/compiler/checkJsFiles.ts index c36673b0239f3..0f19653973796 100644 --- a/tests/cases/compiler/checkJsFiles.ts +++ b/tests/cases/compiler/checkJsFiles.ts @@ -1,5 +1,6 @@ // @allowJs: true // @checkJsFiles: true +// @noEmit: true // @fileName: a.js var x = "string"; diff --git a/tests/cases/compiler/checkJsFiles2.ts b/tests/cases/compiler/checkJsFiles2.ts index fe8978666b061..e18eecb039315 100644 --- a/tests/cases/compiler/checkJsFiles2.ts +++ b/tests/cases/compiler/checkJsFiles2.ts @@ -1,5 +1,6 @@ // @allowJs: true // @checkJsFiles: false +// @noEmit: true // @fileName: a.js // @check diff --git a/tests/cases/compiler/checkJsFiles3.ts b/tests/cases/compiler/checkJsFiles3.ts index 964f909bc6f69..a0a9a152fee6e 100644 --- a/tests/cases/compiler/checkJsFiles3.ts +++ b/tests/cases/compiler/checkJsFiles3.ts @@ -1,4 +1,5 @@ // @allowJs: true +// @noEmit: true // @fileName: a.js // @check From b015c1d9b0181bcb499af1e801d9acb70d5a6d4f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 6 Mar 2017 21:39:32 -0800 Subject: [PATCH 06/21] Allow @check directives to switch on/off checking in a file --- src/compiler/parser.ts | 15 +++++++++++---- src/compiler/program.ts | 7 +++---- src/compiler/types.ts | 6 +++++- src/harness/harness.ts | 2 +- src/services/services.ts | 2 +- .../baselines/reference/checkJsFiles4.errors.txt | 10 ++++++++++ tests/baselines/reference/checkJsFiles5.symbols | 9 +++++++++ tests/baselines/reference/checkJsFiles5.types | 12 ++++++++++++ tests/cases/compiler/checkJsFiles4.ts | 8 ++++++++ tests/cases/compiler/checkJsFiles5.ts | 8 ++++++++ 10 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 tests/baselines/reference/checkJsFiles4.errors.txt create mode 100644 tests/baselines/reference/checkJsFiles5.symbols create mode 100644 tests/baselines/reference/checkJsFiles5.types create mode 100644 tests/cases/compiler/checkJsFiles4.ts create mode 100644 tests/cases/compiler/checkJsFiles5.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 48fe3ce542607..ef23ee175fd86 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5817,7 +5817,7 @@ namespace ts { const typeReferenceDirectives: FileReference[] = []; const amdDependencies: { path: string; name: string }[] = []; let amdModuleName: string; - let hasCheckDirective = false; + let checkJsDirective: CheckJsDirective = undefined; // Keep scanning all the leading trivia in the file until we get to something that // isn't trivia. Any single line comment will be analyzed to see if it is a @@ -5880,8 +5880,15 @@ namespace ts { } } - const checkDirectiveRegEx = /^\/\/\s*@check\s*/gim; - hasCheckDirective = hasCheckDirective || !!checkDirectiveRegEx.exec(comment); + const checkJsDirectiveRegEx = /^\/\/\/?\s*@check(\s+(true|false))?/gim; + const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment); + if (checkJsDirectiveMatchResult) { + checkJsDirective = { + enabled: compareStrings(checkJsDirectiveMatchResult[2], "false", /*ignoreCase*/ true) !== Comparison.EqualTo, + end: range.end, + pos: range.pos + }; + } } } @@ -5889,7 +5896,7 @@ namespace ts { sourceFile.typeReferenceDirectives = typeReferenceDirectives; sourceFile.amdDependencies = amdDependencies; sourceFile.moduleName = amdModuleName; - sourceFile.hasCheckDirective = hasCheckDirective; + sourceFile.checkJsDirective = checkJsDirective; } function setExternalModuleIndicator(sourceFile: SourceFile) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 64da4f6de7126..29559c12191a8 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -904,10 +904,9 @@ namespace ts { Debug.assert(!!sourceFile.bindDiagnostics); const bindDiagnostics = sourceFile.bindDiagnostics; - // For JavaScript files, we don't want to report semantic errors. - // Instead, we'll report errors for using TypeScript-only constructs from within a - // JavaScript file when we get syntactic diagnostics for the file. - const includeCheckDiagnostics = options.checkJsFiles || sourceFile.hasCheckDirective || !isSourceFileJavaScript(sourceFile); + // For JavaScript files, we don't want to report semantic errors unless ecplicitlly requested. + const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || + (sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : options.checkJsFiles); const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3028b295d276a..beb68a015b036 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1940,6 +1940,10 @@ fileName: string; } + export interface CheckJsDirective extends TextRange { + enabled: boolean; + } + export type CommentKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia; export interface CommentRange extends TextRange { @@ -2272,7 +2276,7 @@ /* @internal */ moduleAugmentations: LiteralExpression[]; /* @internal */ patternAmbientModules?: PatternAmbientModule[]; /* @internal */ ambientModuleNames: string[]; - /* @internal */ hasCheckDirective: boolean; + /* @internal */ checkJsDirective: CheckJsDirective | undefined; } export interface Bundle extends Node { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 23e8106864a92..9304940ce1f90 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -202,7 +202,7 @@ namespace Utils { for (const childName in node) { if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator" || // for now ignore jsdoc comments - childName === "jsDocComment") { + childName === "jsDocComment" || childName === "checkJsDirective") { continue; } const child = (node)[childName]; diff --git a/src/services/services.ts b/src/services/services.ts index 037894661ff6f..a77bacb9a86a8 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -473,7 +473,7 @@ namespace ts { public moduleAugmentations: LiteralExpression[]; private namedDeclarations: Map; public ambientModuleNames: string[]; - public hasCheckDirective: boolean; + public checkJsDirective: CheckJsDirective | undefined; constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end); diff --git a/tests/baselines/reference/checkJsFiles4.errors.txt b/tests/baselines/reference/checkJsFiles4.errors.txt new file mode 100644 index 0000000000000..87eb0f3b7d4e8 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles4.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type 'string'. + + +==== tests/cases/compiler/a.js (1 errors) ==== + + // @check true + var x = "string"; + x = 0; + ~ +!!! error TS2322: Type '0' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/checkJsFiles5.symbols b/tests/baselines/reference/checkJsFiles5.symbols new file mode 100644 index 0000000000000..cdb53964aa5e2 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles5.symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/a.js === + +// @check false +var x = "string"; +>x : Symbol(x, Decl(a.js, 2, 3)) + +x = 0; +>x : Symbol(x, Decl(a.js, 2, 3)) + diff --git a/tests/baselines/reference/checkJsFiles5.types b/tests/baselines/reference/checkJsFiles5.types new file mode 100644 index 0000000000000..bd1ab8d942cd9 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles5.types @@ -0,0 +1,12 @@ +=== tests/cases/compiler/a.js === + +// @check false +var x = "string"; +>x : string +>"string" : "string" + +x = 0; +>x = 0 : 0 +>x : string +>0 : 0 + diff --git a/tests/cases/compiler/checkJsFiles4.ts b/tests/cases/compiler/checkJsFiles4.ts new file mode 100644 index 0000000000000..364397a3e8a2b --- /dev/null +++ b/tests/cases/compiler/checkJsFiles4.ts @@ -0,0 +1,8 @@ +// @allowJs: true +// @checkJsFiles: false +// @noEmit: true + +// @fileName: a.js +// @check true +var x = "string"; +x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles5.ts b/tests/cases/compiler/checkJsFiles5.ts new file mode 100644 index 0000000000000..572f6b3b5f81a --- /dev/null +++ b/tests/cases/compiler/checkJsFiles5.ts @@ -0,0 +1,8 @@ +// @allowJs: true +// @checkJsFiles: true +// @noEmit: true + +// @fileName: a.js +// @check false +var x = "string"; +x = 0; \ No newline at end of file From 9305d4d99e9799afb998bd34aede02ec0f4f1401 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 13:48:37 -0800 Subject: [PATCH 07/21] Change flag name to `checkJs` --- src/compiler/commandLineParser.ts | 2 +- src/compiler/program.ts | 2 +- src/compiler/types.ts | 2 +- tests/cases/compiler/checkJsFiles.ts | 2 +- tests/cases/compiler/checkJsFiles2.ts | 2 +- tests/cases/compiler/checkJsFiles4.ts | 2 +- tests/cases/compiler/checkJsFiles5.ts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 85a099c6dcaad..70966c48e7ce4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -483,7 +483,7 @@ namespace ts { } }, { - name: "checkJsFiles", + name: "checkJs", type: "boolean", experimental: true, description: Diagnostics.Report_errors_in_js_files diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 29559c12191a8..5fd178a891fc3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -906,7 +906,7 @@ namespace ts { const bindDiagnostics = sourceFile.bindDiagnostics; // For JavaScript files, we don't want to report semantic errors unless ecplicitlly requested. const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || - (sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : options.checkJsFiles); + (sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : options.checkJs); const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index beb68a015b036..7e7fe7c28e4ea 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3317,7 +3317,7 @@ alwaysStrict?: boolean; // Always combine with strict property baseUrl?: string; charset?: string; - checkJsFiles?: boolean; + checkJs?: boolean; /* @internal */ configFilePath?: string; declaration?: boolean; declarationDir?: string; diff --git a/tests/cases/compiler/checkJsFiles.ts b/tests/cases/compiler/checkJsFiles.ts index 0f19653973796..62e2eb3301d32 100644 --- a/tests/cases/compiler/checkJsFiles.ts +++ b/tests/cases/compiler/checkJsFiles.ts @@ -1,5 +1,5 @@ // @allowJs: true -// @checkJsFiles: true +// @checkJs: true // @noEmit: true // @fileName: a.js diff --git a/tests/cases/compiler/checkJsFiles2.ts b/tests/cases/compiler/checkJsFiles2.ts index e18eecb039315..36bc2cbd255c4 100644 --- a/tests/cases/compiler/checkJsFiles2.ts +++ b/tests/cases/compiler/checkJsFiles2.ts @@ -1,5 +1,5 @@ // @allowJs: true -// @checkJsFiles: false +// @checkJs: false // @noEmit: true // @fileName: a.js diff --git a/tests/cases/compiler/checkJsFiles4.ts b/tests/cases/compiler/checkJsFiles4.ts index 364397a3e8a2b..8bebedf55e782 100644 --- a/tests/cases/compiler/checkJsFiles4.ts +++ b/tests/cases/compiler/checkJsFiles4.ts @@ -1,5 +1,5 @@ // @allowJs: true -// @checkJsFiles: false +// @checkJs: false // @noEmit: true // @fileName: a.js diff --git a/tests/cases/compiler/checkJsFiles5.ts b/tests/cases/compiler/checkJsFiles5.ts index 572f6b3b5f81a..c28114f570b13 100644 --- a/tests/cases/compiler/checkJsFiles5.ts +++ b/tests/cases/compiler/checkJsFiles5.ts @@ -1,5 +1,5 @@ // @allowJs: true -// @checkJsFiles: true +// @checkJs: true // @noEmit: true // @fileName: a.js From fb218b789746f2c8e12ea8919e4951a7403e9525 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 13:49:52 -0800 Subject: [PATCH 08/21] Error if `--checkJs` is used without `--allowJs` --- src/compiler/program.ts | 4 ++++ tests/baselines/reference/checkJsFiles6.errors.txt | 9 +++++++++ tests/cases/compiler/checkJsFiles6.ts | 6 ++++++ 3 files changed, 19 insertions(+) create mode 100644 tests/baselines/reference/checkJsFiles6.errors.txt create mode 100644 tests/cases/compiler/checkJsFiles6.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 5fd178a891fc3..f524a54985943 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1685,6 +1685,10 @@ namespace ts { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); } + if (options.checkJs && !options.allowJs) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs")); + } + if (options.emitDecoratorMetadata && !options.experimentalDecorators) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); diff --git a/tests/baselines/reference/checkJsFiles6.errors.txt b/tests/baselines/reference/checkJsFiles6.errors.txt new file mode 100644 index 0000000000000..89063e5069845 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles6.errors.txt @@ -0,0 +1,9 @@ +error TS5052: Option 'checkJs' cannot be specified without specifying option 'allowJs'. +error TS6054: File 'tests/cases/compiler/a.js' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'. + + +!!! error TS5052: Option 'checkJs' cannot be specified without specifying option 'allowJs'. +!!! error TS6054: File 'tests/cases/compiler/a.js' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'. +==== tests/cases/compiler/a.js (0 errors) ==== + + var x; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles6.ts b/tests/cases/compiler/checkJsFiles6.ts new file mode 100644 index 0000000000000..358704ae22e64 --- /dev/null +++ b/tests/cases/compiler/checkJsFiles6.ts @@ -0,0 +1,6 @@ +// @allowJs: false +// @checkJs: true +// @noEmit: true + +// @fileName: a.js +var x; \ No newline at end of file From e9f82145b781f68aa243fb078b8c898552759798 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 23:03:47 -0800 Subject: [PATCH 09/21] Code review comments --- src/compiler/parser.ts | 4 ++-- src/compiler/program.ts | 2 +- tests/baselines/reference/checkJsFiles2.errors.txt | 2 +- tests/baselines/reference/checkJsFiles3.errors.txt | 2 +- tests/baselines/reference/checkJsFiles4.errors.txt | 2 +- tests/baselines/reference/checkJsFiles5.symbols | 2 +- tests/baselines/reference/checkJsFiles5.types | 2 +- tests/cases/compiler/checkJsFiles2.ts | 2 +- tests/cases/compiler/checkJsFiles3.ts | 2 +- tests/cases/compiler/checkJsFiles4.ts | 2 +- tests/cases/compiler/checkJsFiles5.ts | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ef23ee175fd86..faff106959467 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5880,11 +5880,11 @@ namespace ts { } } - const checkJsDirectiveRegEx = /^\/\/\/?\s*@check(\s+(true|false))?/gim; + const checkJsDirectiveRegEx = /^\/\/\/?\s*(@ts-check|@ts-nocheck)\s*$/gim; const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment); if (checkJsDirectiveMatchResult) { checkJsDirective = { - enabled: compareStrings(checkJsDirectiveMatchResult[2], "false", /*ignoreCase*/ true) !== Comparison.EqualTo, + enabled: compareStrings(checkJsDirectiveMatchResult[1], "@ts-check", /*ignoreCase*/ true) === Comparison.EqualTo, end: range.end, pos: range.pos }; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f524a54985943..d46c3b2479fff 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -904,7 +904,7 @@ namespace ts { Debug.assert(!!sourceFile.bindDiagnostics); const bindDiagnostics = sourceFile.bindDiagnostics; - // For JavaScript files, we don't want to report semantic errors unless ecplicitlly requested. + // For JavaScript files, we don't want to report semantic errors unless explicitly requested. const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || (sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : options.checkJs); const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; diff --git a/tests/baselines/reference/checkJsFiles2.errors.txt b/tests/baselines/reference/checkJsFiles2.errors.txt index 5c1a211a646fb..7fc852fba1406 100644 --- a/tests/baselines/reference/checkJsFiles2.errors.txt +++ b/tests/baselines/reference/checkJsFiles2.errors.txt @@ -3,7 +3,7 @@ tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type ==== tests/cases/compiler/a.js (1 errors) ==== - // @check + // @ts-check var x = "string"; x = 0; ~ diff --git a/tests/baselines/reference/checkJsFiles3.errors.txt b/tests/baselines/reference/checkJsFiles3.errors.txt index 5c1a211a646fb..7fc852fba1406 100644 --- a/tests/baselines/reference/checkJsFiles3.errors.txt +++ b/tests/baselines/reference/checkJsFiles3.errors.txt @@ -3,7 +3,7 @@ tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type ==== tests/cases/compiler/a.js (1 errors) ==== - // @check + // @ts-check var x = "string"; x = 0; ~ diff --git a/tests/baselines/reference/checkJsFiles4.errors.txt b/tests/baselines/reference/checkJsFiles4.errors.txt index 87eb0f3b7d4e8..7fc852fba1406 100644 --- a/tests/baselines/reference/checkJsFiles4.errors.txt +++ b/tests/baselines/reference/checkJsFiles4.errors.txt @@ -3,7 +3,7 @@ tests/cases/compiler/a.js(4,1): error TS2322: Type '0' is not assignable to type ==== tests/cases/compiler/a.js (1 errors) ==== - // @check true + // @ts-check var x = "string"; x = 0; ~ diff --git a/tests/baselines/reference/checkJsFiles5.symbols b/tests/baselines/reference/checkJsFiles5.symbols index cdb53964aa5e2..76cc21c46a677 100644 --- a/tests/baselines/reference/checkJsFiles5.symbols +++ b/tests/baselines/reference/checkJsFiles5.symbols @@ -1,6 +1,6 @@ === tests/cases/compiler/a.js === -// @check false +// @ts-nocheck var x = "string"; >x : Symbol(x, Decl(a.js, 2, 3)) diff --git a/tests/baselines/reference/checkJsFiles5.types b/tests/baselines/reference/checkJsFiles5.types index bd1ab8d942cd9..15704315bbec9 100644 --- a/tests/baselines/reference/checkJsFiles5.types +++ b/tests/baselines/reference/checkJsFiles5.types @@ -1,6 +1,6 @@ === tests/cases/compiler/a.js === -// @check false +// @ts-nocheck var x = "string"; >x : string >"string" : "string" diff --git a/tests/cases/compiler/checkJsFiles2.ts b/tests/cases/compiler/checkJsFiles2.ts index 36bc2cbd255c4..2e4d4396e46f9 100644 --- a/tests/cases/compiler/checkJsFiles2.ts +++ b/tests/cases/compiler/checkJsFiles2.ts @@ -3,6 +3,6 @@ // @noEmit: true // @fileName: a.js -// @check +// @ts-check var x = "string"; x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles3.ts b/tests/cases/compiler/checkJsFiles3.ts index a0a9a152fee6e..885bf1979f55c 100644 --- a/tests/cases/compiler/checkJsFiles3.ts +++ b/tests/cases/compiler/checkJsFiles3.ts @@ -2,6 +2,6 @@ // @noEmit: true // @fileName: a.js -// @check +// @ts-check var x = "string"; x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles4.ts b/tests/cases/compiler/checkJsFiles4.ts index 8bebedf55e782..2e4d4396e46f9 100644 --- a/tests/cases/compiler/checkJsFiles4.ts +++ b/tests/cases/compiler/checkJsFiles4.ts @@ -3,6 +3,6 @@ // @noEmit: true // @fileName: a.js -// @check true +// @ts-check var x = "string"; x = 0; \ No newline at end of file diff --git a/tests/cases/compiler/checkJsFiles5.ts b/tests/cases/compiler/checkJsFiles5.ts index c28114f570b13..10f59aed17278 100644 --- a/tests/cases/compiler/checkJsFiles5.ts +++ b/tests/cases/compiler/checkJsFiles5.ts @@ -3,6 +3,6 @@ // @noEmit: true // @fileName: a.js -// @check false +// @ts-nocheck var x = "string"; x = 0; \ No newline at end of file From a202fa4c888b55368d3ecd506ba0594cf84577b0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 8 Mar 2017 23:08:55 -0800 Subject: [PATCH 10/21] add es6 to buildProtocol --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 4512aa23794f4..4a31c8da17903 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -422,7 +422,7 @@ compileFile(buildProtocolJs, [buildProtocolTs], [], /*useBuiltCompiler*/ false, - {noOutFile: true}); + { noOutFile: true, lib: "es6" }); file(buildProtocolDts, [buildProtocolTs, buildProtocolJs, typescriptServicesDts], function() { From fe7719f0a9747214046eb1dc8bbf5047b2fc90d3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 23:03:47 -0800 Subject: [PATCH 11/21] Disable check diagnostics per line --- src/compiler/program.ts | 29 +++++++++++- .../checkJsFiles_skipDiagnostics.symbols | 38 +++++++++++++++ .../checkJsFiles_skipDiagnostics.types | 47 +++++++++++++++++++ .../compiler/checkJsFiles_skipDiagnostics.ts | 33 +++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols create mode 100644 tests/baselines/reference/checkJsFiles_skipDiagnostics.types create mode 100644 tests/cases/compiler/checkJsFiles_skipDiagnostics.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 67e9f62fe2db0..bdc8f76cf6049 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -4,6 +4,7 @@ namespace ts { const emptyArray: any[] = []; + const suppressDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-suppress)?)/; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string { while (true) { @@ -923,10 +924,36 @@ namespace ts { const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); - return bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile); + const diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile); + return isSourceFileJavaScript(sourceFile) + ? filter(diagnostics, shouldReportDiagnostic) + : diagnostics; }); } + /** + * Skip errors if previous line start with '// @ts-suppress' comment, not counting non-empty non-comment lines + */ + function shouldReportDiagnostic(diagnostic: Diagnostic) { + const { file, start } = diagnostic; + const lineStarts = getLineStarts(file); + let { line } = computeLineAndCharacterOfPosition(lineStarts, start); + while (line > 0) { + const previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]); + const result = suppressDiagnosticCommentRegEx.exec(previousLineText); + if (!result) { + // non-empty line + return true; + } + if (result[3]) { + // @ts-suppress + return false; + } + line--; + } + return true; + } + function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] { return runWithCancellationToken(() => { const diagnostics: Diagnostic[] = []; diff --git a/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols b/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols new file mode 100644 index 0000000000000..a0f2200048f25 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols @@ -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 +x(); +>x : Symbol(x, Decl(a.js, 1, 3)) + diff --git a/tests/baselines/reference/checkJsFiles_skipDiagnostics.types b/tests/baselines/reference/checkJsFiles_skipDiagnostics.types new file mode 100644 index 0000000000000..69105a3112aa9 --- /dev/null +++ b/tests/baselines/reference/checkJsFiles_skipDiagnostics.types @@ -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 + diff --git a/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts b/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts new file mode 100644 index 0000000000000..bcbcc815e7c21 --- /dev/null +++ b/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts @@ -0,0 +1,33 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @fileName: a.js +var x = 0; + + +/// @ts-suppress +x(); + +/// @ts-suppress +x(); + +/// @ts-suppress +x( + 2, + 3); + + + +// @ts-suppress +// come comment +// some other comment + +// @anohter + +x(); + + + +// @ts-suppress: no call signature +x(); \ No newline at end of file From 706acdf13834bfd479b63aced65e157033353c42 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 13:40:15 -0800 Subject: [PATCH 12/21] 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 83b4cb961a45a..6495f6d9ac464 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 0000000000000..6e4a5f38586c6 --- /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 76be34c67cda5..ae1643dfa3baa 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 61d48bdc3bc85..6c8bd0a9dbe7e 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 93f861e80aa58..b97b3c509f8e7 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 7c5bf862fc8a0..c894df121f862 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 0000000000000..070712c2523ea --- /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 0000000000000..4a55f2ba44f92 --- /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 0000000000000..f486a7e171bf5 --- /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 0000000000000..cadbda2c27395 --- /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 0000000000000..56b9fbf20d988 --- /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 0000000000000..a0497b4deb9e5 --- /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 0000000000000..ad8377e129de5 --- /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 0000000000000..8ec350479af1e --- /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); + From 13e80b955875248a0a55b5f1926cf1defaaa53e5 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 13:40:15 -0800 Subject: [PATCH 13/21] Fix building webTestServer --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 595875dfc3248..5779d75022f50 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -945,7 +945,7 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () { // Browser tests var nodeServerOutFile = "tests/webTestServer.js"; var nodeServerInFile = "tests/webTestServer.ts"; -compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true }); +compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true, lib: "es6" }); desc("Runs browserify on run.js to produce a file suitable for running tests in the browser"); task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() { From 936a91d27118c4b836f7549668976bbfe7050be8 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 9 Mar 2017 16:12:58 -0800 Subject: [PATCH 14/21] Add comment --- src/services/codefixes/disableJsDiagnostics.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index 6e4a5f38586c6..c18c0153a0368 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -20,9 +20,14 @@ namespace ts.codefix { 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) + const tokenLeadingCommnets = getLeadingCommentRangesOfNode(token, sourceFile); if (!tokenLeadingCommnets || !tokenLeadingCommnets.length || tokenLeadingCommnets[0].pos >= startPosition) { return { span: { start: startPosition, length: 0 }, @@ -30,6 +35,8 @@ namespace ts.codefix { }; } } + + // 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}` From 6e86596a732c868cc709dcc5c1db21566030a373 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 13 Mar 2017 22:43:37 -0700 Subject: [PATCH 15/21] Add debugging utilities --- src/harness/fourslash.ts | 11 ++++++++++- tests/cases/fourslash/fourslash.ts | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0df9f4f4dd2bd..11103bf6e2d59 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1,4 +1,4 @@ -// +// // Copyright (c) Microsoft Corporation. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -2550,6 +2550,11 @@ namespace FourSlash { } } + public printAvailableCodeFixes() { + const codeFixes = this.getCodeFixActions(this.activeFile.fileName); + Harness.IO.log(stringify(codeFixes)); + } + // Get the text of the entire line the caret is currently at private getCurrentLineContent() { const text = this.getFileContent(this.activeFile.fileName); @@ -3738,6 +3743,10 @@ namespace FourSlashInterface { this.state.printCompletionListMembers(); } + public printAvailableCodeFixes() { + this.state.printAvailableCodeFixes(); + } + public printBreakpointLocation(pos: number) { this.state.printBreakpointLocation(pos); } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index ab83752d93bd0..418066fb6f93e 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -296,6 +296,7 @@ declare namespace FourSlashInterface { printCurrentQuickInfo(): void; printCurrentSignatureHelp(): void; printCompletionListMembers(): void; + printAvailableCodeFixes(): void; printBreakpointLocation(pos: number): void; printBreakpointAtCurrentLocation(): void; printNameOrDottedNameSpans(pos: number): void; From fd9fb8f9bce4828fc657cfb36a3a47c3283a583c Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 13 Mar 2017 22:49:54 -0700 Subject: [PATCH 16/21] Support static properties --- src/services/codefixes/fixAddMissingMember.ts | 95 ++++++++++++------- .../fourslash/codeFixAddMissingMember.ts | 14 +++ .../fourslash/codeFixAddMissingMember2.ts | 14 +++ .../fourslash/codeFixAddMissingMember3.ts | 14 +++ .../fourslash/codeFixAddMissingMember4.ts | 22 +++++ .../fourslash/codeFixAddMissingMember5.ts | 19 ++++ .../fourslash/codeFixAddMissingMember6.ts | 18 ++++ .../fourslash/codeFixAddMissingMember7.ts | 15 +++ ...xUndeclaredIndexSignatureNumericLiteral.ts | 2 +- 9 files changed, 179 insertions(+), 34 deletions(-) create mode 100644 tests/cases/fourslash/codeFixAddMissingMember.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember2.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember3.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember4.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember5.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember6.ts create mode 100644 tests/cases/fourslash/codeFixAddMissingMember7.ts diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index fe4176a766a07..bc2ee6fe0f885 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { registerCodeFix({ errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code], @@ -13,22 +13,27 @@ namespace ts.codefix { // this.missing = 1; // ^^^^^^^ const token = getTokenAtPosition(sourceFile, start); - if (token.kind != SyntaxKind.Identifier) { return undefined; } - const classDeclaration = getContainingClass(token); - if (!classDeclaration) { + if (!isPropertyAccessExpression(token.parent) || token.parent.expression.kind !== SyntaxKind.ThisKeyword) { return undefined; } - if (!isPropertyAccessExpression(token.parent) || token.parent.expression.kind !== SyntaxKind.ThisKeyword) { + const classMemberDeclaration = getThisContainer(token, /*includeArrowFunctions*/ false); + if (!isClassElement(classMemberDeclaration)) { return undefined; } - return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile(); + const classDeclaration = classMemberDeclaration.parent; + if (!classDeclaration || !isClassLike(classDeclaration)) { + return undefined; + } + const isStatic = hasModifier(getThisContainer(token, /*includeArrowFunctions*/ false), ModifierFlags.Static); + + return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile(); function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined { let typeString = "any"; @@ -43,47 +48,71 @@ namespace ts.codefix { const startPos = classDeclaration.members.pos; - return [{ + const actions = [{ description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]), changes: [{ fileName: sourceFile.fileName, textChanges: [{ span: { start: startPos, length: 0 }, - newText: `${token.getFullText(sourceFile)}: ${typeString};` - }] - }] - }, - { - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: startPos, length: 0 }, - newText: `[name: string]: ${typeString};` + newText: `${isStatic ? "static " : ""}${token.getFullText(sourceFile)}: ${typeString};` }] }] }]; - } - function getActionsForAddMissingMemberInJavaScriptFile(): CodeAction[] | undefined { - const classConstructor = getFirstConstructorWithBody(classDeclaration); - if (!classConstructor) { - return undefined; + if (!isStatic) { + actions.push({ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: `[x: string]: ${typeString};` + }] + }] + }); } + return actions; + } + + function getActionsForAddMissingMemberInJavaScriptFile(): CodeAction[] | undefined { const memberName = token.getText(); - const startPos = classConstructor.body.getEnd() - 1; - return [{ - description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [memberName]), - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: startPos, length: 0 }, - newText: `this.${memberName} = undefined;` + if (isStatic) { + if (classDeclaration.kind === SyntaxKind.ClassExpression) { + return undefined; + } + + const className = classDeclaration.name.getText(); + + return [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [memberName]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: classDeclaration.getEnd(), length: 0 }, + newText: `${context.newLineCharacter}${className}.${memberName} = undefined;${context.newLineCharacter}` + }] }] - }] - }]; + }]; + } + else { + const classConstructor = getFirstConstructorWithBody(classDeclaration); + if (!classConstructor) { + return undefined; + } + + return [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [memberName]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: classConstructor.body.getEnd() - 1, length: 0 }, + newText: `this.${memberName} = undefined;${context.newLineCharacter}` + }] + }] + }]; + } } } } \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember.ts b/tests/cases/fourslash/codeFixAddMissingMember.ts new file mode 100644 index 0000000000000..43c0bc3b765ec --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember.ts @@ -0,0 +1,14 @@ +/// + +////[|class C { +//// method() { +//// this.foo = 10; +//// } +////}|] + +verify.rangeAfterCodeFix(`class C { + foo: number; + method() { + this.foo = 10; + } +}`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember2.ts b/tests/cases/fourslash/codeFixAddMissingMember2.ts new file mode 100644 index 0000000000000..7b64fde8c0109 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember2.ts @@ -0,0 +1,14 @@ +/// + +////[|class C { +//// method() { +//// this.foo = 10; +//// } +////}|] + +verify.rangeAfterCodeFix(`class C { + [x:string]: number; + method() { + this.foo = 10; + } +}`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 1); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember3.ts b/tests/cases/fourslash/codeFixAddMissingMember3.ts new file mode 100644 index 0000000000000..5864c9c10297f --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember3.ts @@ -0,0 +1,14 @@ +/// + +////[|class C { +//// static method() { +//// this.foo = 10; +//// } +////}|] + +verify.rangeAfterCodeFix(`class C { + static foo: number; + static method() { + this.foo = 10; + } +}`); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember4.ts b/tests/cases/fourslash/codeFixAddMissingMember4.ts new file mode 100644 index 0000000000000..08df9ccabc2ee --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember4.ts @@ -0,0 +1,22 @@ +/// + +// @checkJs: true +// @allowJs: true + +// @Filename: a.js +////[|class C { +//// constructor() { +//// } +//// method() { +//// this.foo === 10; +//// } +////}|] + +verify.rangeAfterCodeFix(`class C { + constructor() { + this.foo = undefined; +} + method() { + this.foo === 10; + } +}`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember5.ts b/tests/cases/fourslash/codeFixAddMissingMember5.ts new file mode 100644 index 0000000000000..cbabc0ba6c58f --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember5.ts @@ -0,0 +1,19 @@ +/// + +// @checkJs: true +// @allowJs: true + +// @Filename: a.js +////[|class C { +//// static method() { +//// ()=>{ this.foo === 10 }; +//// } +////} +////|] + +verify.rangeAfterCodeFix(`class C { + static method() { + ()=>{ this.foo === 10 }; + } +} +C.foo = undefined;`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember6.ts b/tests/cases/fourslash/codeFixAddMissingMember6.ts new file mode 100644 index 0000000000000..2f3911d779e05 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember6.ts @@ -0,0 +1,18 @@ +/// + +// @checkJs: true +// @allowJs: true + +// @Filename: a.js +////[|class C { +//// constructor() { +//// } +//// prop = ()=>{ this.foo === 10 }; +////}|] + +verify.rangeAfterCodeFix(`class C { + constructor() { + this.foo = undefined; + } + prop = ()=>{ this.foo === 10 }; +}`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixAddMissingMember7.ts b/tests/cases/fourslash/codeFixAddMissingMember7.ts new file mode 100644 index 0000000000000..0e937a3ab6e95 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddMissingMember7.ts @@ -0,0 +1,15 @@ +/// + +// @checkJs: true +// @allowJs: true + +// @Filename: a.js +////[|class C { +//// static p = ()=>{ this.foo === 10 }; +////} +////|] + +verify.rangeAfterCodeFix(`class C { + static p = ()=>{ this.foo === 10 }; +} +C.foo = undefined;`, /*includeWhiteSpace*/false, /*errorCode*/ undefined, /*index*/ 2); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixUndeclaredIndexSignatureNumericLiteral.ts b/tests/cases/fourslash/codeFixUndeclaredIndexSignatureNumericLiteral.ts index 2e49a8184eb73..0a2b0ee799df3 100644 --- a/tests/cases/fourslash/codeFixUndeclaredIndexSignatureNumericLiteral.ts +++ b/tests/cases/fourslash/codeFixUndeclaredIndexSignatureNumericLiteral.ts @@ -8,7 +8,7 @@ verify.rangeAfterCodeFix(` class A { - [name: string]: number; + [x: string]: number; constructor() { this.x = 10; From 509b2dc18e32ec0ac399b131a2381e12ef77e6de Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 13 Mar 2017 23:03:06 -0700 Subject: [PATCH 17/21] Add disableJsDiagnostics codefixes to harnes --- src/harness/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index 21622325368cc..9f0e30baa1c85 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -1,4 +1,4 @@ -{ +{ "extends": "../tsconfig-base", "compilerOptions": { "removeComments": false, @@ -81,6 +81,7 @@ "../services/codefixes/helpers.ts", "../services/codefixes/importFixes.ts", "../services/codefixes/unusedIdentifierFixes.ts", + "../services/codefixes/disableJsDiagnostics.ts", "harness.ts", "sourceMapRecorder.ts", From 798062944ba3add53e264b3b77c5c9cf55e18523 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 15 Mar 2017 12:27:47 -0700 Subject: [PATCH 18/21] Code review comments --- src/services/codefixes/fixAddMissingMember.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index bc2ee6fe0f885..765ffa818b671 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -31,7 +31,7 @@ namespace ts.codefix { return undefined; } - const isStatic = hasModifier(getThisContainer(token, /*includeArrowFunctions*/ false), ModifierFlags.Static); + const isStatic = hasModifier(classMemberDeclaration, ModifierFlags.Static); return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile(); @@ -54,7 +54,7 @@ namespace ts.codefix { fileName: sourceFile.fileName, textChanges: [{ span: { start: startPos, length: 0 }, - newText: `${isStatic ? "static " : ""}${token.getFullText(sourceFile)}: ${typeString};` + newText: `${isStatic ? "static " : ""}${token.getText(sourceFile)}: ${typeString};` }] }] }]; From 3b57b5d4d570beccd2d87df9812dc90941897c21 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 15 Mar 2017 15:17:33 -0700 Subject: [PATCH 19/21] Refactor checking for checkJs value in a common helper --- src/compiler/core.ts | 6 +++++- src/compiler/program.ts | 5 ++--- src/services/codefixes/disableJsDiagnostics.ts | 8 ++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c380a39611dd0..14aeb35dc89f1 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { @@ -2360,4 +2360,8 @@ namespace ts { return Extension.Jsx; } } + + export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) { + return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; + } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bdc8f76cf6049..8f1bd4ba36e87 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,4 +1,4 @@ -/// +/// /// /// @@ -918,8 +918,7 @@ namespace ts { Debug.assert(!!sourceFile.bindDiagnostics); const bindDiagnostics = sourceFile.bindDiagnostics; // For JavaScript files, we don't want to report semantic errors unless explicitly requested. - const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || - (sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : options.checkJs); + const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options); const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : []; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index c18c0153a0368..621555cf84ba7 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { registerCodeFix({ errorCodes: getApplicableDiagnosticCodes(), @@ -12,10 +12,6 @@ namespace ts.codefix { .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); @@ -46,7 +42,7 @@ namespace ts.codefix { function getDisableJsDiagnosticsCodeActions(context: CodeFixContext): CodeAction[] | undefined { const { sourceFile, program, newLineCharacter, span } = context; - if (!isInJavaScriptFile(sourceFile) || !shouldCheckJsFile(sourceFile, program.getCompilerOptions())) { + if (!isInJavaScriptFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) { return undefined; } From db6c96967cb856c6eeadae5b87ca34178664aca2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 22 Mar 2017 16:23:21 -0700 Subject: [PATCH 20/21] Change ingore diagonstic comment to `// @ts-ignore` --- src/compiler/core.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/program.ts | 10 +++++----- src/harness/fourslash.ts | 2 +- src/services/codefixes/disableJsDiagnostics.ts | 16 ++++++++-------- src/services/codefixes/fixAddMissingMember.ts | 2 +- .../checkJsFiles_skipDiagnostics.symbols | 10 +++++----- .../reference/checkJsFiles_skipDiagnostics.types | 10 +++++----- .../Default initialized TSConfig/tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../compiler/checkJsFiles_skipDiagnostics.ts | 10 +++++----- .../codeFixDisableJsDiagnosticsInFile3.ts | 2 +- .../codeFixDisableJsDiagnosticsInFile4.ts | 2 +- .../codeFixDisableJsDiagnosticsInFile5.ts | 2 +- .../codeFixDisableJsDiagnosticsInFile6.ts | 2 +- .../codeFixDisableJsDiagnosticsInFile7.ts | 2 +- .../codeFixDisableJsDiagnosticsInFile8.ts | 2 +- 23 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 14aeb35dc89f1..a56f1004d28cf 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0aed8bf2be183..983e128ec7f77 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3484,7 +3484,7 @@ "category": "Message", "code": 90018 }, - "Suppress this error message.": { + "Ignore this error message.": { "category": "Message", "code": 90019 }, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b4b93c0d21b63..31fc665649a73 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,10 +1,10 @@ -/// +/// /// /// namespace ts { const emptyArray: any[] = []; - const suppressDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-suppress)?)/; + const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string { while (true) { @@ -926,7 +926,7 @@ namespace ts { } /** - * Skip errors if previous line start with '// @ts-suppress' comment, not counting non-empty non-comment lines + * Skip errors if previous line start with '// @ts-ignore' comment, not counting non-empty non-comment lines */ function shouldReportDiagnostic(diagnostic: Diagnostic) { const { file, start } = diagnostic; @@ -934,13 +934,13 @@ namespace ts { let { line } = computeLineAndCharacterOfPosition(lineStarts, start); while (line > 0) { const previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]); - const result = suppressDiagnosticCommentRegEx.exec(previousLineText); + const result = ignoreDiagnosticCommentRegEx.exec(previousLineText); if (!result) { // non-empty line return true; } if (result[3]) { - // @ts-suppress + // @ts-ignore return false; } line--; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0285cdc51fecc..aa07407b0f214 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1,4 +1,4 @@ -// +// // Copyright (c) Microsoft Corporation. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index 621555cf84ba7..7fa5c5bf23ff8 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { registerCodeFix({ errorCodes: getApplicableDiagnosticCodes(), @@ -12,12 +12,12 @@ namespace ts.codefix { .map(d => allDiagnostcs[d].code); } - function getSuppressCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string) { - let { line } = getLineAndCharacterOfPosition(sourceFile, position); + function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string) { + const { 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. + // First try to see if we can put the '// @ts-ignore' 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. @@ -27,7 +27,7 @@ namespace ts.codefix { if (!tokenLeadingCommnets || !tokenLeadingCommnets.length || tokenLeadingCommnets[0].pos >= startPosition) { return { span: { start: startPosition, length: 0 }, - newText: `// @ts-suppress${newLineCharacter}` + newText: `// @ts-ignore${newLineCharacter}` }; } } @@ -35,7 +35,7 @@ namespace ts.codefix { // 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}` + newText: `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}` }; } @@ -47,10 +47,10 @@ namespace ts.codefix { } return [{ - description: getLocaleSpecificMessage(Diagnostics.Suppress_this_error_message), + description: getLocaleSpecificMessage(Diagnostics.Ignore_this_error_message), changes: [{ fileName: sourceFile.fileName, - textChanges: [getSuppressCommentLocationForLocation(sourceFile, span.start, newLineCharacter)] + textChanges: [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter)] }] }, { diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 765ffa818b671..1934de11f3542 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { registerCodeFix({ errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code], diff --git a/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols b/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols index a0f2200048f25..eb2afaf4361e0 100644 --- a/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols +++ b/tests/baselines/reference/checkJsFiles_skipDiagnostics.symbols @@ -4,15 +4,15 @@ var x = 0; >x : Symbol(x, Decl(a.js, 1, 3)) -/// @ts-suppress +/// @ts-ignore x(); >x : Symbol(x, Decl(a.js, 1, 3)) -/// @ts-suppress +/// @ts-ignore x(); >x : Symbol(x, Decl(a.js, 1, 3)) -/// @ts-suppress +/// @ts-ignore x( >x : Symbol(x, Decl(a.js, 1, 3)) @@ -21,7 +21,7 @@ x( -// @ts-suppress +// @ts-ignore // come comment // some other comment @@ -32,7 +32,7 @@ x(); -// @ts-suppress: no call signature +// @ts-ignore: no call signature x(); >x : Symbol(x, Decl(a.js, 1, 3)) diff --git a/tests/baselines/reference/checkJsFiles_skipDiagnostics.types b/tests/baselines/reference/checkJsFiles_skipDiagnostics.types index 69105a3112aa9..aa24f1f0541b1 100644 --- a/tests/baselines/reference/checkJsFiles_skipDiagnostics.types +++ b/tests/baselines/reference/checkJsFiles_skipDiagnostics.types @@ -5,17 +5,17 @@ var x = 0; >0 : 0 -/// @ts-suppress +/// @ts-ignore x(); >x() : any >x : number -/// @ts-suppress +/// @ts-ignore x(); >x() : any >x : number -/// @ts-suppress +/// @ts-ignore x( >x( 2, 3) : any >x : number @@ -28,7 +28,7 @@ x( -// @ts-suppress +// @ts-ignore // come comment // some other comment @@ -40,7 +40,7 @@ x(); -// @ts-suppress: no call signature +// @ts-ignore: no call signature x(); >x() : any >x : number diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 5918c273ce5bf..97f59dea8eae6 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 38c4542b40739..b90e3fc6c580e 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index d948b648153e7..482cfa6a9d550 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 70870f296e100..c6a26629dab29 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index 3eabb0894f163..72289dd1787e0 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ "lib": ["es5","es2015.promise"], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 5918c273ce5bf..97f59dea8eae6 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index b88ac604c14e8..1ac7c8c54da43 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ "lib": ["es5","es2015.core"], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index db838e21d2fee..33a9ecc5cd408 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -5,6 +5,7 @@ "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ // "lib": [], /* Specify library files to be included in the compilation: */ // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ diff --git a/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts b/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts index bcbcc815e7c21..48364c6a592ec 100644 --- a/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts +++ b/tests/cases/compiler/checkJsFiles_skipDiagnostics.ts @@ -6,20 +6,20 @@ var x = 0; -/// @ts-suppress +/// @ts-ignore x(); -/// @ts-suppress +/// @ts-ignore x(); -/// @ts-suppress +/// @ts-ignore x( 2, 3); -// @ts-suppress +// @ts-ignore // come comment // some other comment @@ -29,5 +29,5 @@ x(); -// @ts-suppress: no call signature +// @ts-ignore: no call signature x(); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts index f486a7e171bf5..5cace444859f2 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile3.ts @@ -10,5 +10,5 @@ // Disable checking for next line verify.rangeAfterCodeFix(`var x = ""; -// @ts-suppress +// @ts-ignore x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts index cadbda2c27395..1319325a3d2ef 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile4.ts @@ -13,6 +13,6 @@ // Disable checking for next line verify.rangeAfterCodeFix(`"test \\ "; -// @ts-suppress +// @ts-ignore x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts index 56b9fbf20d988..3a4b619a7fa8e 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile5.ts @@ -12,6 +12,6 @@ // Disable checking for next line verify.rangeAfterCodeFix(`/** comment */ -// @ts-suppress +// @ts-ignore x = 1;`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts index a0497b4deb9e5..5b93f4953d1fc 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile6.ts @@ -12,6 +12,6 @@ ////} // Disable checking for next line -verify.rangeAfterCodeFix(`// @ts-suppress +verify.rangeAfterCodeFix(`// @ts-ignore f(x());`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts index ad8377e129de5..767fa98430465 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile7.ts @@ -12,6 +12,6 @@ ////} // Disable checking for next line -verify.rangeAfterCodeFix(`// @ts-suppress +verify.rangeAfterCodeFix(`// @ts-ignore x();`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); diff --git a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts index 8ec350479af1e..3df5864f198b9 100644 --- a/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts +++ b/tests/cases/fourslash/codeFixDisableJsDiagnosticsInFile8.ts @@ -14,6 +14,6 @@ // Disable checking for next line verify.rangeAfterCodeFix(`f( - // @ts-suppress + // @ts-ignore x());`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); From e630ab1a3181b6b5d6a25069d15cbcb77bc3eb1b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 27 Mar 2017 14:20:00 -0700 Subject: [PATCH 21/21] Report semantic errors for JS files if checkJs is enabled --- src/server/session.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/session.ts b/src/server/session.ts index 11c99dfe46c9e..337aab1c3fb9f 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -31,7 +31,8 @@ namespace ts.server { } else { // For configured projects, require that skipLibCheck be set also - return project.getCompilerOptions().skipLibCheck && project.isJsOnlyProject(); + const options = project.getCompilerOptions(); + return options.skipLibCheck && !options.checkJs && project.isJsOnlyProject(); } }