From 67f0ffe7fb1f579102269de7781e2d08f899ebfb Mon Sep 17 00:00:00 2001 From: zhengbli Date: Tue, 28 Jun 2016 13:06:26 -0700 Subject: [PATCH 01/34] Port 9396 to release 2.0 --- src/compiler/program.ts | 28 +++++++++++++++---- .../fourslash/server/typeReferenceOnServer.ts | 9 ++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/server/typeReferenceOnServer.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7593f4f5434..fb74f1dcaab 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -187,8 +187,22 @@ namespace ts { const typeReferenceExtensions = [".d.ts"]; function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) { - return options.typeRoots || - map(defaultTypeRoots, d => combinePaths(options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(), d)); + if (options.typeRoots) { + return options.typeRoots; + } + + let currentDirectory: string; + if (options.configFilePath) { + currentDirectory = getDirectoryPath(options.configFilePath); + } + else if (host.getCurrentDirectory) { + currentDirectory = host.getCurrentDirectory(); + } + + if (!currentDirectory) { + return undefined; + } + return map(defaultTypeRoots, d => combinePaths(currentDirectory, d)); } /** @@ -228,7 +242,7 @@ namespace ts { const failedLookupLocations: string[] = []; // Check primary library paths - if (typeRoots.length) { + if (typeRoots && typeRoots.length) { if (traceEnabled) { trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); } @@ -1046,9 +1060,11 @@ namespace ts { let result: string[] = []; if (host.directoryExists && host.getDirectories) { const typeRoots = getEffectiveTypeRoots(options, host); - for (const root of typeRoots) { - if (host.directoryExists(root)) { - result = result.concat(host.getDirectories(root)); + if (typeRoots) { + for (const root of typeRoots) { + if (host.directoryExists(root)) { + result = result.concat(host.getDirectories(root)); + } } } } diff --git a/tests/cases/fourslash/server/typeReferenceOnServer.ts b/tests/cases/fourslash/server/typeReferenceOnServer.ts new file mode 100644 index 00000000000..574ea6f60c4 --- /dev/null +++ b/tests/cases/fourslash/server/typeReferenceOnServer.ts @@ -0,0 +1,9 @@ +/// + +/////// +////var x: number; +////x./*1*/ + +goTo.marker("1"); +verify.not.completionListIsEmpty(); + From 8ff873e7a614afbb27cff26775a3b218cf26bd5f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 28 Jun 2016 13:34:01 -0700 Subject: [PATCH 02/34] Fix crash in async functions when targetting ES5. When targetting ES5 and with --noImplicitReturns, an async function whose return type could not be determined would cause a compiler crash. --- src/compiler/checker.ts | 2 +- .../asyncFunctionNoReturnType.errors.txt | 25 +++++++++++++++++++ .../reference/asyncFunctionNoReturnType.js | 20 +++++++++++++++ .../compiler/asyncFunctionNoReturnType.ts | 5 ++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/asyncFunctionNoReturnType.errors.txt create mode 100644 tests/baselines/reference/asyncFunctionNoReturnType.js create mode 100644 tests/cases/compiler/asyncFunctionNoReturnType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06591a7ab3d..ce001e1e088 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15388,7 +15388,7 @@ namespace ts { function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean { const unwrappedReturnType = isAsyncFunctionLike(func) ? getPromisedType(returnType) : returnType; - return maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.Any); + return unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.Any); } function checkReturnStatement(node: ReturnStatement) { diff --git a/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt b/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt new file mode 100644 index 00000000000..a7dbb6ecb64 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionNoReturnType.errors.txt @@ -0,0 +1,25 @@ +error TS2318: Cannot find global type 'Promise'. +tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher. +tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS1057: An async function or method must have a valid awaitable return type. +tests/cases/compiler/asyncFunctionNoReturnType.ts(1,1): error TS7030: Not all code paths return a value. +tests/cases/compiler/asyncFunctionNoReturnType.ts(2,9): error TS2304: Cannot find name 'window'. +tests/cases/compiler/asyncFunctionNoReturnType.ts(3,9): error TS7030: Not all code paths return a value. + + +!!! error TS2318: Cannot find global type 'Promise'. +==== tests/cases/compiler/asyncFunctionNoReturnType.ts (5 errors) ==== + async () => { + ~~~~~ +!!! error TS1311: Async functions are only available when targeting ECMAScript 2015 or higher. + ~~~~~~~~~~~~~ +!!! error TS1057: An async function or method must have a valid awaitable return type. + ~~~~~~~~~~~~~ +!!! error TS7030: Not all code paths return a value. + if (window) + ~~~~~~ +!!! error TS2304: Cannot find name 'window'. + return; + ~~~~~~~ +!!! error TS7030: Not all code paths return a value. + } + \ No newline at end of file diff --git a/tests/baselines/reference/asyncFunctionNoReturnType.js b/tests/baselines/reference/asyncFunctionNoReturnType.js new file mode 100644 index 00000000000..dd84e17c88b --- /dev/null +++ b/tests/baselines/reference/asyncFunctionNoReturnType.js @@ -0,0 +1,20 @@ +//// [asyncFunctionNoReturnType.ts] +async () => { + if (window) + return; +} + + +//// [asyncFunctionNoReturnType.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +(function () __awaiter(this, void 0, void 0, function* () { + if (window) + return; +})); diff --git a/tests/cases/compiler/asyncFunctionNoReturnType.ts b/tests/cases/compiler/asyncFunctionNoReturnType.ts new file mode 100644 index 00000000000..4a4b5316d72 --- /dev/null +++ b/tests/cases/compiler/asyncFunctionNoReturnType.ts @@ -0,0 +1,5 @@ +// @noImplicitReturns: true +async () => { + if (window) + return; +} From 690c682b6e852372f9ba312ef41fc9a547725ec6 Mon Sep 17 00:00:00 2001 From: Yui Date: Tue, 28 Jun 2016 15:55:46 -0700 Subject: [PATCH 03/34] Merge master into release-2.0 (#9400) * do not format comma/closeparen in jsxelement * format jsx expression * make rules optional * Remove upper boilerplate from issue template Our issue stats did not improve appreciably when we added the issue template. Reduce upper boilerplate text and try to make it more action-oriented * Update issue_template.md * new options should be optional for compatibility * Add getCurrentDirectory to ServerHost * Add nullchecks for typeRoots, remove getCurrentDirectory from ServerHost as it is always the installation location * VarDate interface and relevant Date.prototype members * Fix 9363: Object destructuring broken-variables are bound to the wrong object (#9383) * Fix emit incorrect destructuring mapping in var declaration * Add tests and baselines * Add additional tests and baselines --- issue_template.md | 21 +++--------- src/compiler/emitter.ts | 4 ++- src/harness/fourslash.ts | 1 + src/lib/scripthost.d.ts | 10 ++++++ src/server/editorServices.ts | 1 + src/services/formatting/rules.ts | 26 +++++++++++++-- src/services/formatting/rulesProvider.ts | 9 +++++ src/services/services.ts | 1 + .../destructuringParameterDeclaration7ES5.js | 27 +++++++++++++++ ...tructuringParameterDeclaration7ES5.symbols | 33 +++++++++++++++++++ ...estructuringParameterDeclaration7ES5.types | 33 +++++++++++++++++++ .../destructuringParameterDeclaration7ES5.ts | 14 ++++++++ .../cases/fourslash/formattingJsxElements.ts | 32 ++++++++++++++---- .../fourslash/formattingOptionsChangeJsx.ts | 32 ++++++++++++++++++ 14 files changed, 218 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/destructuringParameterDeclaration7ES5.js create mode 100644 tests/baselines/reference/destructuringParameterDeclaration7ES5.symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration7ES5.types create mode 100644 tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts create mode 100644 tests/cases/fourslash/formattingOptionsChangeJsx.ts diff --git a/issue_template.md b/issue_template.md index dcd2280570c..7799960ec78 100644 --- a/issue_template.md +++ b/issue_template.md @@ -1,24 +1,13 @@ - + + -For bug reports, please include the information below. -__________________________________________________________ --> - -**TypeScript Version:** - -1.7.5 / 1.8.0-beta / nightly (1.9.0-dev.20160217) +**TypeScript Version:** 1.8.0 / nightly (2.0.0-dev.201xxxxx) **Code** ```ts -// A self-contained demonstration of the problem follows... +// A *self-contained* demonstration of the problem follows... ``` diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0879a3a9ee4..30f0e74adb4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4545,8 +4545,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } write(";"); - tempIndex++; } + // Regardless of whether we will emit a var declaration for the binding pattern, we generate the temporary + // variable for the parameter (see: emitParameter) + tempIndex++; } else if (initializer) { writeLine(); diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index bae2977c44a..a42abbbc609 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -324,6 +324,7 @@ namespace FourSlash { InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, + InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }; diff --git a/src/lib/scripthost.d.ts b/src/lib/scripthost.d.ts index 7faae06714c..baf93f55d55 100644 --- a/src/lib/scripthost.d.ts +++ b/src/lib/scripthost.d.ts @@ -276,3 +276,13 @@ interface VBArrayConstructor { } declare var VBArray: VBArrayConstructor; + +/** + * Automation date (VT_DATE) + */ +interface VarDate { } + +interface DateConstructor { + new (vd: VarDate): Date; + getVarDate: () => VarDate; +} \ No newline at end of file diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e48d6192017..092450e526c 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1580,6 +1580,7 @@ namespace ts.server { InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, + InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }); diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index b95b23cfca8..110ac9bf4ea 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -225,6 +225,12 @@ namespace ts.formatting { public NoSpaceBeforeTemplateMiddleAndTail: Rule; public SpaceBeforeTemplateMiddleAndTail: Rule; + // No space after { and before } in JSX expression + public NoSpaceAfterOpenBraceInJsxExpression: Rule; + public SpaceAfterOpenBraceInJsxExpression: Rule; + public NoSpaceBeforeCloseBraceInJsxExpression: Rule; + public SpaceBeforeCloseBraceInJsxExpression: Rule; + constructor() { /// /// Common Rules @@ -316,7 +322,7 @@ namespace ts.formatting { // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] - this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotForContext), RuleAction.Space)); + this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext, Rules.IsNotForContext), RuleAction.Space)); // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. this.SpaceAfterTryFinally = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword]), SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); @@ -444,8 +450,8 @@ namespace ts.formatting { /// // Insert space after comma delimiter - this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNextTokenNotCloseBracket), RuleAction.Space)); - this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), RuleAction.Space)); + this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isNonJsxElementContext), RuleAction.Delete)); // Insert space before and after binary operators this.SpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); @@ -491,6 +497,12 @@ namespace ts.formatting { this.NoSpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); this.SpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + // No space after { and before } in JSX expression + this.NoSpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Delete)); + this.SpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Space)); + this.NoSpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Delete)); + this.SpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.isJsxExpressionContext), RuleAction.Space)); + // Insert space after function keyword for anonymous functions this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Delete)); @@ -729,6 +741,14 @@ namespace ts.formatting { return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; } + static isNonJsxElementContext(context: FormattingContext): boolean { + return context.contextNode.kind !== SyntaxKind.JsxElement; + } + + static isJsxExpressionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxExpression; + } + static IsNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean { return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); } diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index d672a401d89..1be0f9e912d 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -90,6 +90,15 @@ namespace ts.formatting { rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail); } + if (options.InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { + rules.push(this.globalRules.SpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.SpaceBeforeCloseBraceInJsxExpression); + } + else { + rules.push(this.globalRules.NoSpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.NoSpaceBeforeCloseBraceInJsxExpression); + } + if (options.InsertSpaceAfterSemicolonInForStatements) { rules.push(this.globalRules.SpaceAfterSemicolonInFor); } diff --git a/src/services/services.ts b/src/services/services.ts index a17d9feed24..529ce8a7bf7 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1267,6 +1267,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; + InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number | string | undefined; diff --git a/tests/baselines/reference/destructuringParameterDeclaration7ES5.js b/tests/baselines/reference/destructuringParameterDeclaration7ES5.js new file mode 100644 index 00000000000..f9dac1ae2fa --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration7ES5.js @@ -0,0 +1,27 @@ +//// [destructuringParameterDeclaration7ES5.ts] + +interface ISomething { + foo: string, + bar: string +} + +function foo({}, {foo, bar}: ISomething) {} + +function baz([], {foo, bar}: ISomething) {} + +function one([], {}) {} + +function two([], [a, b, c]: number[]) {} + + +//// [destructuringParameterDeclaration7ES5.js] +function foo(_a, _b) { + var foo = _b.foo, bar = _b.bar; +} +function baz(_a, _b) { + var foo = _b.foo, bar = _b.bar; +} +function one(_a, _b) { } +function two(_a, _b) { + var a = _b[0], b = _b[1], c = _b[2]; +} diff --git a/tests/baselines/reference/destructuringParameterDeclaration7ES5.symbols b/tests/baselines/reference/destructuringParameterDeclaration7ES5.symbols new file mode 100644 index 00000000000..44709f18e1b --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration7ES5.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts === + +interface ISomething { +>ISomething : Symbol(ISomething, Decl(destructuringParameterDeclaration7ES5.ts, 0, 0)) + + foo: string, +>foo : Symbol(ISomething.foo, Decl(destructuringParameterDeclaration7ES5.ts, 1, 22)) + + bar: string +>bar : Symbol(ISomething.bar, Decl(destructuringParameterDeclaration7ES5.ts, 2, 16)) +} + +function foo({}, {foo, bar}: ISomething) {} +>foo : Symbol(foo, Decl(destructuringParameterDeclaration7ES5.ts, 4, 1)) +>foo : Symbol(foo, Decl(destructuringParameterDeclaration7ES5.ts, 6, 18)) +>bar : Symbol(bar, Decl(destructuringParameterDeclaration7ES5.ts, 6, 22)) +>ISomething : Symbol(ISomething, Decl(destructuringParameterDeclaration7ES5.ts, 0, 0)) + +function baz([], {foo, bar}: ISomething) {} +>baz : Symbol(baz, Decl(destructuringParameterDeclaration7ES5.ts, 6, 43)) +>foo : Symbol(foo, Decl(destructuringParameterDeclaration7ES5.ts, 8, 18)) +>bar : Symbol(bar, Decl(destructuringParameterDeclaration7ES5.ts, 8, 22)) +>ISomething : Symbol(ISomething, Decl(destructuringParameterDeclaration7ES5.ts, 0, 0)) + +function one([], {}) {} +>one : Symbol(one, Decl(destructuringParameterDeclaration7ES5.ts, 8, 43)) + +function two([], [a, b, c]: number[]) {} +>two : Symbol(two, Decl(destructuringParameterDeclaration7ES5.ts, 10, 23)) +>a : Symbol(a, Decl(destructuringParameterDeclaration7ES5.ts, 12, 18)) +>b : Symbol(b, Decl(destructuringParameterDeclaration7ES5.ts, 12, 20)) +>c : Symbol(c, Decl(destructuringParameterDeclaration7ES5.ts, 12, 23)) + diff --git a/tests/baselines/reference/destructuringParameterDeclaration7ES5.types b/tests/baselines/reference/destructuringParameterDeclaration7ES5.types new file mode 100644 index 00000000000..7d64383b0b6 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration7ES5.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts === + +interface ISomething { +>ISomething : ISomething + + foo: string, +>foo : string + + bar: string +>bar : string +} + +function foo({}, {foo, bar}: ISomething) {} +>foo : ({}: {}, {foo, bar}: ISomething) => void +>foo : string +>bar : string +>ISomething : ISomething + +function baz([], {foo, bar}: ISomething) {} +>baz : ([]: any[], {foo, bar}: ISomething) => void +>foo : string +>bar : string +>ISomething : ISomething + +function one([], {}) {} +>one : ([]: any[], {}: {}) => void + +function two([], [a, b, c]: number[]) {} +>two : ([]: any[], [a, b, c]: number[]) => void +>a : number +>b : number +>c : number + diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts new file mode 100644 index 00000000000..97822e92e2d --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration7ES5.ts @@ -0,0 +1,14 @@ +// @target: es5 + +interface ISomething { + foo: string, + bar: string +} + +function foo({}, {foo, bar}: ISomething) {} + +function baz([], {foo, bar}: ISomething) {} + +function one([], {}) {} + +function two([], [a, b, c]: number[]) {} diff --git a/tests/cases/fourslash/formattingJsxElements.ts b/tests/cases/fourslash/formattingJsxElements.ts index fbe4bb5d29e..e07149960db 100644 --- a/tests/cases/fourslash/formattingJsxElements.ts +++ b/tests/cases/fourslash/formattingJsxElements.ts @@ -9,7 +9,7 @@ //// //// ) ////} -//// +//// ////function foo1() { //// return ( ////
@@ -45,8 +45,8 @@ //// class3= {/*5*/ //// }/>/*6*/ //// ) -////} -//// +////} +//// ////(function () { //// return
/*grandchildJsxElementAutoformat*/ /////*containedClosingTagAutoformat*/ -//// +////; +//// +////
,{integer}
;/*commaInJsxElement*/ +////
, {integer}
;/*commaInJsxElement2*/ +////);/*closingParenInJsxElement*/ +////) ;/*closingParenInJsxElement2*/ +////;/*jsxExpressionSpaces*/ +////;/*jsxExpressionSpaces2*/ format.document(); goTo.marker("autoformat"); @@ -114,7 +121,7 @@ verify.indentationIs(12); goTo.marker("danglingBracketAutoformat") // TODO: verify.currentLineContentIs(" >"); -verify.currentLineContentIs(" >"); +verify.currentLineContentIs(" >"); goTo.marker("closingTagAutoformat"); verify.currentLineContentIs("
"); @@ -125,4 +132,17 @@ verify.indentationIs(8); goTo.marker("grandchildJsxElementAutoformat"); verify.currentLineContentIs(" "); goTo.marker("containedClosingTagAutoformat"); -verify.currentLineContentIs(" "); \ No newline at end of file +verify.currentLineContentIs(" "); + +goTo.marker("commaInJsxElement"); +verify.currentLineContentIs("
,{integer}
;"); +goTo.marker("commaInJsxElement2"); +verify.currentLineContentIs("
, {integer}
;"); +goTo.marker("closingParenInJsxElement"); +verify.currentLineContentIs(");"); +goTo.marker("closingParenInJsxElement2"); +verify.currentLineContentIs(") ;"); +goTo.marker("jsxExpressionSpaces"); +verify.currentLineContentIs(";"); +goTo.marker("jsxExpressionSpaces2"); +verify.currentLineContentIs(";"); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingOptionsChangeJsx.ts b/tests/cases/fourslash/formattingOptionsChangeJsx.ts new file mode 100644 index 00000000000..a3c7e28a1ef --- /dev/null +++ b/tests/cases/fourslash/formattingOptionsChangeJsx.ts @@ -0,0 +1,32 @@ +/// + +//@Filename: file.tsx +/////*InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces*/; + +runTest("InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces", ";", ";"); + + +function runTest(propertyName: string, expectedStringWhenTrue: string, expectedStringWhenFalse: string) { + // Go to the correct file + goTo.marker(propertyName); + + // Set the option to false first + format.setOption(propertyName, false); + + // Format + format.document(); + + // Verify + goTo.marker(propertyName); + verify.currentLineContentIs(expectedStringWhenFalse); + + // Set the option to true + format.setOption(propertyName, true); + + // Format + format.document(); + + // Verify + goTo.marker(propertyName); + verify.currentLineContentIs(expectedStringWhenTrue); +} \ No newline at end of file From 17a428c21f6820b05519a381c0448b5c0cb14ce4 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 28 Jun 2016 16:04:52 -0700 Subject: [PATCH 04/34] Fix #9402: Do not report unused identifier errors for catch variables --- src/compiler/checker.ts | 1 - .../reference/unusedParameterInCatchClause.errors.txt | 10 ---------- .../reference/unusedParameterInCatchClause.symbols | 8 ++++++++ .../reference/unusedParameterInCatchClause.types | 8 ++++++++ 4 files changed, 16 insertions(+), 11 deletions(-) delete mode 100644 tests/baselines/reference/unusedParameterInCatchClause.errors.txt create mode 100644 tests/baselines/reference/unusedParameterInCatchClause.symbols create mode 100644 tests/baselines/reference/unusedParameterInCatchClause.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06591a7ab3d..a7b69c96e1c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15563,7 +15563,6 @@ namespace ts { } checkBlock(catchClause.block); - checkUnusedIdentifiers(catchClause); } if (node.finallyBlock) { diff --git a/tests/baselines/reference/unusedParameterInCatchClause.errors.txt b/tests/baselines/reference/unusedParameterInCatchClause.errors.txt deleted file mode 100644 index e996763e2c6..00000000000 --- a/tests/baselines/reference/unusedParameterInCatchClause.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/compiler/unusedParameterInCatchClause.ts(3,18): error TS6133: 'ex' is declared but never used. - - -==== tests/cases/compiler/unusedParameterInCatchClause.ts (1 errors) ==== - - function f1() { - try {} catch(ex){} - ~~ -!!! error TS6133: 'ex' is declared but never used. - } \ No newline at end of file diff --git a/tests/baselines/reference/unusedParameterInCatchClause.symbols b/tests/baselines/reference/unusedParameterInCatchClause.symbols new file mode 100644 index 00000000000..9406d3ea53e --- /dev/null +++ b/tests/baselines/reference/unusedParameterInCatchClause.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/unusedParameterInCatchClause.ts === + +function f1() { +>f1 : Symbol(f1, Decl(unusedParameterInCatchClause.ts, 0, 0)) + + try {} catch(ex){} +>ex : Symbol(ex, Decl(unusedParameterInCatchClause.ts, 2, 17)) +} diff --git a/tests/baselines/reference/unusedParameterInCatchClause.types b/tests/baselines/reference/unusedParameterInCatchClause.types new file mode 100644 index 00000000000..ad23b5d753b --- /dev/null +++ b/tests/baselines/reference/unusedParameterInCatchClause.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/unusedParameterInCatchClause.ts === + +function f1() { +>f1 : () => void + + try {} catch(ex){} +>ex : any +} From 27e66b0bc85bc59d51dfb360b5581451a89c1e06 Mon Sep 17 00:00:00 2001 From: Zev Spitz Date: Wed, 29 Jun 2016 02:16:18 +0300 Subject: [PATCH 05/34] getVarDate should be on the Date interface --- src/lib/scripthost.d.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/scripthost.d.ts b/src/lib/scripthost.d.ts index baf93f55d55..b163a7e5154 100644 --- a/src/lib/scripthost.d.ts +++ b/src/lib/scripthost.d.ts @@ -284,5 +284,8 @@ interface VarDate { } interface DateConstructor { new (vd: VarDate): Date; +} + +interface Date { getVarDate: () => VarDate; -} \ No newline at end of file +} From aeadbe4376acae542b4c8344b50e0d98fafbc879 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 28 Jun 2016 23:37:26 -0700 Subject: [PATCH 06/34] Defere checking unsed identifier checks --- src/compiler/checker.ts | 152 +++++++++++++++++++++++++++------------- 1 file changed, 103 insertions(+), 49 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a7b69c96e1c..05cb7df24fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -51,6 +51,7 @@ namespace ts { const compilerOptions = host.getCompilerOptions(); const languageVersion = compilerOptions.target || ScriptTarget.ES3; const modulekind = getEmitModuleKind(compilerOptions); + const noUnusedIdentifiers = compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; const strictNullChecks = compilerOptions.strictNullChecks; @@ -8323,7 +8324,7 @@ namespace ts { const extendedTypeNode = getClassExtendsHeritageClauseElement(node); if (extendedTypeNode) { const t = getTypeFromTypeNode(extendedTypeNode); - if (t !== unknownType && t.symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (t !== unknownType && t.symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { t.symbol.hasReference = true; } } @@ -8331,7 +8332,7 @@ namespace ts { function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); - if (symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { symbol.hasReference = true; } @@ -10248,7 +10249,7 @@ namespace ts { return unknownType; } - if ((compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (noUnusedIdentifiers && !isInAmbientContext(node)) { prop.hasReference = true; } @@ -12155,47 +12156,54 @@ namespace ts { } function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { - Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); + if (node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)) { - const isAsync = isAsyncFunctionLike(node); - const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type)); - if (!node.asteriskToken) { - // return is not necessary in the body of generators - checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); - } - - if (node.body) { - if (!node.type) { - // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors - // we need. An example is the noImplicitAny errors resulting from widening the return expression - // of a function. Because checking of function expression bodies is deferred, there was never an - // appropriate time to do this during the main walk of the file (see the comment at the top of - // checkFunctionExpressionBodies). So it must be done now. - getReturnTypeOfSignature(getSignatureFromDeclaration(node)); + const isAsync = isAsyncFunctionLike(node); + const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type)); + if (!node.asteriskToken) { + // return is not necessary in the body of generators + checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } - if (node.body.kind === SyntaxKind.Block) { - checkSourceElement(node.body); - } - else { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so we - // should not be checking assignability of a promise to the return type. Instead, we need to - // check assignability of the awaited type of the expression body against the promised type of - // its return type annotation. - const exprType = checkExpression(node.body); - if (returnOrPromisedType) { - if (isAsync) { - const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member); - checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); + if (node.body) { + if (!node.type) { + // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors + // we need. An example is the noImplicitAny errors resulting from widening the return expression + // of a function. Because checking of function expression bodies is deferred, there was never an + // appropriate time to do this during the main walk of the file (see the comment at the top of + // checkFunctionExpressionBodies). So it must be done now. + getReturnTypeOfSignature(getSignatureFromDeclaration(node)); + } + + if (node.body.kind === SyntaxKind.Block) { + checkSourceElement(node.body); + } + else { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so we + // should not be checking assignability of a promise to the return type. Instead, we need to + // check assignability of the awaited type of the expression body against the promised type of + // its return type annotation. + const exprType = checkExpression(node.body); + if (returnOrPromisedType) { + if (isAsync) { + const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member); + checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); + } + else { + checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); + } } - else { - checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); } } } - checkUnusedIdentifiers(node); - checkUnusedTypeParameters(node); + } + else { + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } } } @@ -13423,8 +13431,10 @@ namespace ts { checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); - checkUnusedIdentifiers(node); - checkUnusedTypeParameters(node); + + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } const symbol = getSymbolOfNode(node); const firstDeclaration = getDeclarationOfKind(symbol, node.kind); @@ -13586,6 +13596,8 @@ namespace ts { function checkAccessorDeferred(node: AccessorDeclaration) { checkSourceElement(node.body); + checkUnusedIdentifiers(node); + checkUnusedTypeParameters(node); } function checkMissingDeclaration(node: Node) { @@ -13618,7 +13630,7 @@ namespace ts { checkGrammarTypeArguments(node, node.typeArguments); const type = getTypeFromTypeReference(node); if (type !== unknownType) { - if (type.symbol && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (type.symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { type.symbol.hasReference = true; } if (node.typeArguments) { @@ -14471,8 +14483,7 @@ namespace ts { } checkSourceElement(node.body); - checkUnusedIdentifiers(node); - checkUnusedTypeParameters(node); + if (!node.asteriskToken) { const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type)); checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); @@ -14492,10 +14503,19 @@ namespace ts { getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } } + + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } + } + + function checkFunctionOrConstructorDeclarationDeferred(node: FunctionDeclaration | ConstructorDeclaration) { + checkUnusedIdentifiers(node); + checkUnusedTypeParameters(node); } function checkUnusedIdentifiers(node: FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction | ForInStatement | Block | CatchClause): void { - if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !isInAmbientContext(node)) { for (const key in node.locals) { if (hasProperty(node.locals, key)) { const local = node.locals[key]; @@ -14514,7 +14534,7 @@ namespace ts { } } - function checkUnusedClassLocals(node: ClassDeclaration): void { + function checkUnusedClassLocals(node: ClassDeclaration | ClassExpression): void { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { if (node.members) { for (const member of node.members) { @@ -14535,7 +14555,7 @@ namespace ts { } } - function checkUnusedTypeParameters(node: ClassDeclaration | FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | ConstructorDeclaration | SignatureDeclaration | InterfaceDeclaration) { + function checkUnusedTypeParameters(node: ClassDeclaration | ClassExpression | FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction | ConstructorDeclaration | SignatureDeclaration | InterfaceDeclaration) { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { if (node.typeParameters) { for (const typeParameter of node.typeParameters) { @@ -14570,6 +14590,12 @@ namespace ts { checkGrammarStatementInAmbientContext(node); } forEach(node.statements, checkSourceElement); + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } + } + + function checkBlockDeferred(node: Block | ForInStatement | ForOfStatement) { checkUnusedIdentifiers(node); } @@ -15075,7 +15101,9 @@ namespace ts { } checkSourceElement(node.statement); - checkUnusedIdentifiers(node); + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } } function checkForInStatement(node: ForInStatement) { @@ -15123,7 +15151,9 @@ namespace ts { } checkSourceElement(node.statement); - checkUnusedIdentifiers(node); + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } } function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void { @@ -15716,6 +15746,8 @@ namespace ts { function checkClassExpressionDeferred(node: ClassExpression) { forEach(node.members, checkSourceElement); + checkUnusedClassLocals(node); + checkUnusedTypeParameters(node); } function checkClassDeclaration(node: ClassDeclaration) { @@ -15724,6 +15756,13 @@ namespace ts { } checkClassLikeDeclaration(node); forEach(node.members, checkSourceElement); + + if (produceDiagnostics && noUnusedIdentifiers) { + checkNodeDeferred(node); + } + } + + function checkClassDeclarationDefered(node: ClassDeclaration) { checkUnusedClassLocals(node); checkUnusedTypeParameters(node); } @@ -16614,7 +16653,7 @@ namespace ts { if (target.flags & SymbolFlags.Type) { checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); } - if ((compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters) && !isInAmbientContext(node)) { + if (noUnusedIdentifiers && !isInAmbientContext(node)) { target.hasReference = true; } } @@ -16929,6 +16968,18 @@ namespace ts { case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node); break; + case SyntaxKind.Constructor: + case SyntaxKind.FunctionDeclaration: + checkFunctionOrConstructorDeclarationDeferred(node); + break; + case SyntaxKind.Block: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + checkBlockDeferred(node); + break; + case SyntaxKind.ClassDeclaration: + checkClassDeclarationDefered(node); + break; } } } @@ -16959,10 +17010,13 @@ namespace ts { deferredNodes = []; forEach(node.statements, checkSourceElement); + + checkDeferredNodes(); + if (isExternalModule(node)) { checkUnusedModuleLocals(node); } - checkDeferredNodes(); + deferredNodes = undefined; if (isExternalOrCommonJsModule(node)) { From 5f8cf1af3e4be61037cbafd698535d32d292941f Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Wed, 29 Jun 2016 08:44:06 -0700 Subject: [PATCH 07/34] Don't emit source files found under node_modules --- src/compiler/program.ts | 18 ++++++++++-------- src/compiler/utilities.ts | 8 +++----- .../moduleAugmentationInDependency2.js | 2 -- .../pathMappingBasedModuleResolution5_node.js | 3 --- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index fb74f1dcaab..5cb3b8dad7e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1097,7 +1097,7 @@ namespace ts { const modulesWithElidedImports: Map = {}; // Track source files that are JavaScript files found by searching under node_modules, as these shouldn't be compiled. - const jsFilesFoundSearchingNodeModules: Map = {}; + const sourceFilesFoundSearchingNodeModules: Map = {}; const start = new Date().getTime(); @@ -1378,7 +1378,7 @@ namespace ts { getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, getSourceFiles: program.getSourceFiles, - getFilesFromNodeModules: () => jsFilesFoundSearchingNodeModules, + isSourceFileFromNodeModules: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path), writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, @@ -2066,15 +2066,17 @@ namespace ts { // - noResolve is falsy // - module name comes from the list of imports // - it's not a top level JavaScript module that exceeded the search max - const isJsFileUnderNodeModules = resolution && resolution.isExternalLibraryImport && - hasJavaScriptFileExtension(resolution.resolvedFileName); + const isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport; + const isJsFileFromNodeModules = isFromNodeModulesSearch && hasJavaScriptFileExtension(resolution.resolvedFileName); - if (isJsFileUnderNodeModules) { - jsFilesFoundSearchingNodeModules[resolvedPath] = true; + if (isFromNodeModulesSearch) { + sourceFilesFoundSearchingNodeModules[resolvedPath] = true; + } + if (isJsFileFromNodeModules) { currentNodeModulesJsDepth++; } - const elideImport = isJsFileUnderNodeModules && currentNodeModulesJsDepth > maxNodeModulesJsDepth; + const elideImport = isJsFileFromNodeModules && currentNodeModulesJsDepth > maxNodeModulesJsDepth; const shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport; if (elideImport) { @@ -2089,7 +2091,7 @@ namespace ts { file.imports[i].end); } - if (isJsFileUnderNodeModules) { + if (isJsFileFromNodeModules) { currentNodeModulesJsDepth--; } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e8f2832cd59..e4111e3f925 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -36,7 +36,7 @@ namespace ts { getSourceFiles(): SourceFile[]; /* @internal */ - getFilesFromNodeModules(): Map; + isSourceFileFromNodeModules(file: SourceFile): boolean; getCommonSourceDirectory(): string; getCanonicalFileName(fileName: string): string; @@ -2277,10 +2277,9 @@ namespace ts { } else { const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; - const nodeModulesFiles = host.getFilesFromNodeModules(); for (const sourceFile of sourceFiles) { // Don't emit if source file is a declaration file, or was located under node_modules - if (!isDeclarationFile(sourceFile) && !lookUp(nodeModulesFiles, sourceFile.path)) { + if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromNodeModules(sourceFile)) { onSingleFileEmit(host, sourceFile); } } @@ -2314,10 +2313,9 @@ namespace ts { function onBundledEmit(host: EmitHost) { // Can emit only sources that are not declaration file and are either non module code or module with // --module or --target es6 specified. Files included by searching under node_modules are also not emitted. - const nodeModulesFiles = host.getFilesFromNodeModules(); const bundledSources = filter(host.getSourceFiles(), sourceFile => !isDeclarationFile(sourceFile) && - !lookUp(nodeModulesFiles, sourceFile.path) && + !host.isSourceFileFromNodeModules(sourceFile) && (!isExternalModule(sourceFile) || !!getEmitModuleKind(options))); if (bundledSources.length) { diff --git a/tests/baselines/reference/moduleAugmentationInDependency2.js b/tests/baselines/reference/moduleAugmentationInDependency2.js index 381f1e72d8f..0a5d83695a3 100644 --- a/tests/baselines/reference/moduleAugmentationInDependency2.js +++ b/tests/baselines/reference/moduleAugmentationInDependency2.js @@ -8,8 +8,6 @@ export {}; //// [app.ts] import "A" -//// [index.js] -"use strict"; //// [app.js] "use strict"; require("A"); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js index 1958800f918..e4440299cc7 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js @@ -31,9 +31,6 @@ exports.x = 1; //// [file2.js] "use strict"; exports.y = 1; -//// [file4.js] -"use strict"; -exports.z1 = 1; //// [file1.js] "use strict"; var file1_1 = require("folder2/file1"); From c5e680c8be31b0b7651e3ccb078d421e34a76e57 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Jun 2016 09:12:50 -0700 Subject: [PATCH 08/34] Destructuring assignment removes undefined from type when default value is given --- src/compiler/checker.ts | 6 ++++++ .../destructuringAssignmentWithDefault.js | 11 +++++++++++ .../destructuringAssignmentWithDefault.symbols | 12 ++++++++++++ .../destructuringAssignmentWithDefault.types | 17 +++++++++++++++++ .../destructuringAssignmentWithDefault.ts | 4 ++++ 5 files changed, 50 insertions(+) create mode 100644 tests/baselines/reference/destructuringAssignmentWithDefault.js create mode 100644 tests/baselines/reference/destructuringAssignmentWithDefault.symbols create mode 100644 tests/baselines/reference/destructuringAssignmentWithDefault.types create mode 100644 tests/cases/compiler/destructuringAssignmentWithDefault.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06591a7ab3d..9ec2ec3309b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12544,6 +12544,12 @@ namespace ts { if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { const prop = exprOrAssignment; if (prop.objectAssignmentInitializer) { + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. + if (strictNullChecks && + !(getCombinedTypeFlags(checkExpressionCached(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { + sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); + } checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, contextualMapper); } target = (exprOrAssignment).name; diff --git a/tests/baselines/reference/destructuringAssignmentWithDefault.js b/tests/baselines/reference/destructuringAssignmentWithDefault.js new file mode 100644 index 00000000000..ce3837e1162 --- /dev/null +++ b/tests/baselines/reference/destructuringAssignmentWithDefault.js @@ -0,0 +1,11 @@ +//// [destructuringAssignmentWithDefault.ts] +const a: { x?: number } = { }; +let x = 0; +({x = 1} = a); + + +//// [destructuringAssignmentWithDefault.js] +var a = {}; +var x = 0; +(_a = a.x, x = _a === void 0 ? 1 : _a, a); +var _a; diff --git a/tests/baselines/reference/destructuringAssignmentWithDefault.symbols b/tests/baselines/reference/destructuringAssignmentWithDefault.symbols new file mode 100644 index 00000000000..b011834c4f0 --- /dev/null +++ b/tests/baselines/reference/destructuringAssignmentWithDefault.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/destructuringAssignmentWithDefault.ts === +const a: { x?: number } = { }; +>a : Symbol(a, Decl(destructuringAssignmentWithDefault.ts, 0, 5)) +>x : Symbol(x, Decl(destructuringAssignmentWithDefault.ts, 0, 10)) + +let x = 0; +>x : Symbol(x, Decl(destructuringAssignmentWithDefault.ts, 1, 3)) + +({x = 1} = a); +>x : Symbol(x, Decl(destructuringAssignmentWithDefault.ts, 2, 2)) +>a : Symbol(a, Decl(destructuringAssignmentWithDefault.ts, 0, 5)) + diff --git a/tests/baselines/reference/destructuringAssignmentWithDefault.types b/tests/baselines/reference/destructuringAssignmentWithDefault.types new file mode 100644 index 00000000000..1dc1fe23533 --- /dev/null +++ b/tests/baselines/reference/destructuringAssignmentWithDefault.types @@ -0,0 +1,17 @@ +=== tests/cases/compiler/destructuringAssignmentWithDefault.ts === +const a: { x?: number } = { }; +>a : { x?: number | undefined; } +>x : number | undefined +>{ } : {} + +let x = 0; +>x : number +>0 : number + +({x = 1} = a); +>({x = 1} = a) : { x?: number | undefined; } +>{x = 1} = a : { x?: number | undefined; } +>{x = 1} : { x?: number; } +>x : number +>a : { x?: number | undefined; } + diff --git a/tests/cases/compiler/destructuringAssignmentWithDefault.ts b/tests/cases/compiler/destructuringAssignmentWithDefault.ts new file mode 100644 index 00000000000..45ade402eb8 --- /dev/null +++ b/tests/cases/compiler/destructuringAssignmentWithDefault.ts @@ -0,0 +1,4 @@ +// @strictNullChecks: true +const a: { x?: number } = { }; +let x = 0; +({x = 1} = a); From 72325131940a10cf073bc5f01499ab29e384e57e Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 29 Jun 2016 12:01:33 -0700 Subject: [PATCH 09/34] Add nullcheck when calculating indentations for implort clause --- src/services/formatting/smartIndenter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 120a5be6e4e..4eebf4b9431 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -497,7 +497,7 @@ namespace ts.formatting { return childKind !== SyntaxKind.NamedExports; case SyntaxKind.ImportDeclaration: return childKind !== SyntaxKind.ImportClause || - (child).namedBindings.kind !== SyntaxKind.NamedImports; + ((child).namedBindings && (child).namedBindings.kind !== SyntaxKind.NamedImports); case SyntaxKind.JsxElement: return childKind !== SyntaxKind.JsxClosingElement; } From e7fcb661c3b2667522078c58d9b258226888b17a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 12:06:47 -0700 Subject: [PATCH 10/34] Use a deferred list to check for unused identifiers --- src/compiler/checker.ts | 267 ++++++++++++++++++++++------------------ 1 file changed, 147 insertions(+), 120 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 05cb7df24fb..938776c35e8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -188,6 +188,7 @@ namespace ts { let jsxElementClassType: Type; let deferredNodes: Node[]; + let deferredUnusedIdentifierNodes: Node[]; let flowLoopStart = 0; let flowLoopCount = 0; @@ -395,7 +396,7 @@ namespace ts { target.flags |= source.flags; if (source.valueDeclaration && (!target.valueDeclaration || - (target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && source.valueDeclaration.kind !== SyntaxKind.ModuleDeclaration))) { + (target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && source.valueDeclaration.kind !== SyntaxKind.ModuleDeclaration))) { // other kinds of value declarations take precedence over modules target.valueDeclaration = source.valueDeclaration; } @@ -665,8 +666,8 @@ namespace ts { useResult = result.flags & SymbolFlags.TypeParameter // type parameters are visible in parameter list, return type and type parameter list ? lastLocation === (location).type || - lastLocation.kind === SyntaxKind.Parameter || - lastLocation.kind === SyntaxKind.TypeParameter + lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.TypeParameter // local types not visible outside the function body : false; } @@ -855,7 +856,7 @@ namespace ts { if (!result) { if (nameNotFoundMessage) { if (!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && - !checkAndReportErrorForExtendingInterface(errorLocation)) { + !checkAndReportErrorForExtendingInterface(errorLocation)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); } } @@ -962,7 +963,7 @@ namespace ts { return true; } return false; - } + } function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); @@ -1023,8 +1024,8 @@ namespace ts { const exportDefaultSymbol = isShorthandAmbientModule(moduleSymbol.valueDeclaration) ? moduleSymbol : moduleSymbol.exports["export="] ? - getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : - resolveSymbol(moduleSymbol.exports["default"]); + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); @@ -4537,7 +4538,7 @@ namespace ts { : undefined; const typeParameters = classType ? classType.localTypeParameters : declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : - getTypeParametersFromJSDocTemplate(declaration); + getTypeParametersFromJSDocTemplate(declaration); const returnType = getSignatureReturnTypeFromDeclaration(declaration, minArgumentCount, isJSConstructSignature, classType); const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ? createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) : @@ -5166,7 +5167,7 @@ namespace ts { if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : - neverType; + neverType; } else if (typeSet.length === 1) { return typeSet[0]; @@ -5402,8 +5403,8 @@ namespace ts { const count = sources.length; const mapper: TypeMapper = count == 1 ? createUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : - count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) : - createArrayTypeMapper(sources, targets); + count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) : + createArrayTypeMapper(sources, targets); mapper.mappedTypes = sources; return mapper; } @@ -5726,8 +5727,8 @@ namespace ts { } function isSignatureAssignableTo(source: Signature, - target: Signature, - ignoreReturnTypes: boolean): boolean { + target: Signature, + ignoreReturnTypes: boolean): boolean { return compareSignaturesRelated(source, target, ignoreReturnTypes, /*reportErrors*/ false, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False; } @@ -5735,11 +5736,11 @@ namespace ts { * See signatureRelatedTo, compareSignaturesIdentical */ function compareSignaturesRelated(source: Signature, - target: Signature, - ignoreReturnTypes: boolean, - reportErrors: boolean, - errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void, - compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { + target: Signature, + ignoreReturnTypes: boolean, + reportErrors: boolean, + errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void, + compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -5821,10 +5822,10 @@ namespace ts { } function compareTypePredicateRelatedTo(source: TypePredicate, - target: TypePredicate, - reportErrors: boolean, - errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void, - compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { + target: TypePredicate, + reportErrors: boolean, + errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void, + compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { if (source.kind !== target.kind) { if (reportErrors) { errorReporter(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); @@ -6905,7 +6906,7 @@ namespace ts { function isStringLiteralUnionType(type: Type): boolean { return type.flags & TypeFlags.StringLiteral ? true : type.flags & TypeFlags.Union ? forEach((type).types, isStringLiteralUnionType) : - false; + false; } /** @@ -6987,11 +6988,11 @@ namespace ts { const resolved = type; const members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); const regularNew = createAnonymousType(resolved.symbol, - members, - resolved.callSignatures, - resolved.constructSignatures, - resolved.stringIndexInfo, - resolved.numberIndexInfo); + members, + resolved.callSignatures, + resolved.constructSignatures, + resolved.stringIndexInfo, + resolved.numberIndexInfo); regularNew.flags = resolved.flags & ~TypeFlags.FreshObjectLiteral; (type).regularType = regularNew; return regularNew; @@ -7819,7 +7820,7 @@ namespace ts { // We cache results of flow type resolution for shared nodes that were previously visited in // the same getFlowTypeOfReference invocation. A node is considered shared when it is the // antecedent of more than one node. - for (let i = visitedFlowStart; i < visitedFlowCount; i++) { + for (let i = visitedFlowStart; i < visitedFlowCount; i++) { if (visitedFlowNodes[i] === flow) { return visitedFlowTypes[i]; } @@ -8206,7 +8207,7 @@ namespace ts { const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type; return isTypeAssignableTo(candidate, targetType) ? candidate : isTypeAssignableTo(type, candidate) ? type : - getIntersectionType([type, candidate]); + getIntersectionType([type, candidate]); } function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { @@ -8625,9 +8626,9 @@ namespace ts { getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) { // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') const className = (((container.parent as BinaryExpression) // x.prototype.y = f - .left as PropertyAccessExpression) // x.prototype.y - .expression as PropertyAccessExpression) // x.prototype - .expression; // x + .left as PropertyAccessExpression) // x.prototype.y + .expression as PropertyAccessExpression) // x.prototype + .expression; // x const classSymbol = checkExpression(className).symbol; if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) { return getInferredClassType(classSymbol); @@ -9872,7 +9873,7 @@ namespace ts { elemType = checkExpression(node.tagName); } if (elemType.flags & TypeFlags.Union) { - const types = ( elemType).types; + const types = (elemType).types; return getUnionType(types.map(type => { return getResolvedJsxType(node, type, elemClassType); })); @@ -11804,7 +11805,7 @@ namespace ts { // if inference didn't come up with anything but {}, fall back to the binding pattern if present. if (links.type === emptyObjectType && (parameter.valueDeclaration.name.kind === SyntaxKind.ObjectBindingPattern || - parameter.valueDeclaration.name.kind === SyntaxKind.ArrayBindingPattern)) { + parameter.valueDeclaration.name.kind === SyntaxKind.ArrayBindingPattern)) { links.type = getTypeFromBindingPattern(parameter.valueDeclaration.name); } assignBindingElementTypes(parameter.valueDeclaration); @@ -12156,53 +12157,47 @@ namespace ts { } function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { - if (node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)) { + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); - const isAsync = isAsyncFunctionLike(node); - const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type)); - if (!node.asteriskToken) { - // return is not necessary in the body of generators - checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); - } - - if (node.body) { - if (!node.type) { - // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors - // we need. An example is the noImplicitAny errors resulting from widening the return expression - // of a function. Because checking of function expression bodies is deferred, there was never an - // appropriate time to do this during the main walk of the file (see the comment at the top of - // checkFunctionExpressionBodies). So it must be done now. - getReturnTypeOfSignature(getSignatureFromDeclaration(node)); - } - - if (node.body.kind === SyntaxKind.Block) { - checkSourceElement(node.body); - } - else { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so we - // should not be checking assignability of a promise to the return type. Instead, we need to - // check assignability of the awaited type of the expression body against the promised type of - // its return type annotation. - const exprType = checkExpression(node.body); - if (returnOrPromisedType) { - if (isAsync) { - const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member); - checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); - } - else { - checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); - } - } - if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); - } - } - } + const isAsync = isAsyncFunctionLike(node); + const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type)); + if (!node.asteriskToken) { + // return is not necessary in the body of generators + checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } - else { + + if (node.body) { + if (!node.type) { + // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors + // we need. An example is the noImplicitAny errors resulting from widening the return expression + // of a function. Because checking of function expression bodies is deferred, there was never an + // appropriate time to do this during the main walk of the file (see the comment at the top of + // checkFunctionExpressionBodies). So it must be done now. + getReturnTypeOfSignature(getSignatureFromDeclaration(node)); + } + + if (node.body.kind === SyntaxKind.Block) { + checkSourceElement(node.body); + } + else { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so we + // should not be checking assignability of a promise to the return type. Instead, we need to + // check assignability of the awaited type of the expression body against the promised type of + // its return type annotation. + const exprType = checkExpression(node.body); + if (returnOrPromisedType) { + if (isAsync) { + const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member); + checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); + } + else { + checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); + } + } + } if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + checkUnusedIdentifiersDeferred(node) } } } @@ -13433,7 +13428,7 @@ namespace ts { checkSourceElement(node.body); if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + checkUnusedIdentifiersDeferred(node); } const symbol = getSymbolOfNode(node); @@ -13580,6 +13575,9 @@ namespace ts { } if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) { checkSourceElement(node.body); + if (noUnusedIdentifiers) { + checkUnusedIdentifiersDeferred(node); + } } else { checkNodeDeferred(node); @@ -13596,8 +13594,9 @@ namespace ts { function checkAccessorDeferred(node: AccessorDeclaration) { checkSourceElement(node.body); - checkUnusedIdentifiers(node); - checkUnusedTypeParameters(node); + if (produceDiagnostics && noUnusedIdentifiers) { + checkUnusedIdentifiersDeferred(node); + } } function checkMissingDeclaration(node: Node) { @@ -14505,16 +14504,57 @@ namespace ts { } if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + checkUnusedIdentifiersDeferred(node) } } - function checkFunctionOrConstructorDeclarationDeferred(node: FunctionDeclaration | ConstructorDeclaration) { - checkUnusedIdentifiers(node); - checkUnusedTypeParameters(node); + function checkUnusedIdentifiersDeferred(node: Node) { + deferredUnusedIdentifierNodes.push(node); } - function checkUnusedIdentifiers(node: FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction | ForInStatement | Block | CatchClause): void { + function checkUnusedIdentifiersDeferredNodes() { + for (const node of deferredUnusedIdentifierNodes) { + switch (node.kind) { + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: + checkUnusedModuleLocals(node); + break; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + checkUnusedClassLocals(node); + checkUnusedTypeParameters(node); + break; + case SyntaxKind.InterfaceDeclaration: + checkUnusedTypeParameters(node); + break; + case SyntaxKind.Block: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + checkUnusedIdentifiers(node); + break; + case SyntaxKind.Constructor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + checkUnusedIdentifiers(node); + + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + checkUnusedTypeParameters(node); + break; + }; + } + } + + function checkUnusedIdentifiers(node: FunctionLikeDeclaration | ForStatement | Block): void { if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !isInAmbientContext(node)) { for (const key in node.locals) { if (hasProperty(node.locals, key)) { @@ -14590,15 +14630,11 @@ namespace ts { checkGrammarStatementInAmbientContext(node); } forEach(node.statements, checkSourceElement); - if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + if (produceDiagnostics && noUnusedIdentifiers && node.locals) { + checkUnusedIdentifiersDeferred(node); } } - function checkBlockDeferred(node: Block | ForInStatement | ForOfStatement) { - checkUnusedIdentifiers(node); - } - function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact if (!hasDeclaredRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { @@ -15101,8 +15137,8 @@ namespace ts { } checkSourceElement(node.statement); - if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + if (produceDiagnostics && noUnusedIdentifiers && node.locals) { + checkUnusedIdentifiersDeferred(node); } } @@ -15151,8 +15187,8 @@ namespace ts { } checkSourceElement(node.statement); - if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + if (produceDiagnostics && noUnusedIdentifiers && node.locals) { + checkUnusedIdentifiersDeferred(node) } } @@ -15746,8 +15782,9 @@ namespace ts { function checkClassExpressionDeferred(node: ClassExpression) { forEach(node.members, checkSourceElement); - checkUnusedClassLocals(node); - checkUnusedTypeParameters(node); + if (produceDiagnostics && noUnusedIdentifiers) { + checkUnusedIdentifiersDeferred(node) + } } function checkClassDeclaration(node: ClassDeclaration) { @@ -15758,15 +15795,10 @@ namespace ts { forEach(node.members, checkSourceElement); if (produceDiagnostics && noUnusedIdentifiers) { - checkNodeDeferred(node); + checkUnusedIdentifiersDeferred(node); } } - function checkClassDeclarationDefered(node: ClassDeclaration) { - checkUnusedClassLocals(node); - checkUnusedTypeParameters(node); - } - function checkClassLikeDeclaration(node: ClassLikeDeclaration) { checkGrammarClassDeclarationHeritageClauses(node); checkDecorators(node); @@ -16472,7 +16504,9 @@ namespace ts { if (node.body) { checkSourceElement(node.body); - checkUnusedModuleLocals(node); + if (produceDiagnostics && noUnusedIdentifiers) { + checkUnusedIdentifiersDeferred(node); + } } } @@ -16968,18 +17002,6 @@ namespace ts { case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node); break; - case SyntaxKind.Constructor: - case SyntaxKind.FunctionDeclaration: - checkFunctionOrConstructorDeclarationDeferred(node); - break; - case SyntaxKind.Block: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - checkBlockDeferred(node); - break; - case SyntaxKind.ClassDeclaration: - checkClassDeclarationDefered(node); - break; } } } @@ -17009,15 +17031,20 @@ namespace ts { potentialThisCollisions.length = 0; deferredNodes = []; + deferredUnusedIdentifierNodes = []; + forEach(node.statements, checkSourceElement); checkDeferredNodes(); - if (isExternalModule(node)) { - checkUnusedModuleLocals(node); + if (isExternalModule(node) && produceDiagnostics && noUnusedIdentifiers) { + checkUnusedIdentifiersDeferred(node); } + checkUnusedIdentifiersDeferredNodes(); + deferredNodes = undefined; + deferredUnusedIdentifierNodes = undefined; if (isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); From 7836ba093e1f1dab8d79a58eae96918e5bb0cfe7 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 12:07:08 -0700 Subject: [PATCH 11/34] push checks to checkUnusedIdentifiersDeferred --- src/compiler/checker.ts | 125 ++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 69 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 938776c35e8..6a7cbce6083 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12196,9 +12196,7 @@ namespace ts { } } } - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node) - } + checkUnusedIdentifiersDeferred(node); } } @@ -13426,10 +13424,7 @@ namespace ts { checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); - - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node); - } + checkUnusedIdentifiersDeferred(node); const symbol = getSymbolOfNode(node); const firstDeclaration = getDeclarationOfKind(symbol, node.kind); @@ -13575,9 +13570,7 @@ namespace ts { } if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) { checkSourceElement(node.body); - if (noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node); - } + checkUnusedIdentifiersDeferred(node); } else { checkNodeDeferred(node); @@ -13594,9 +13587,7 @@ namespace ts { function checkAccessorDeferred(node: AccessorDeclaration) { checkSourceElement(node.body); - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node); - } + checkUnusedIdentifiersDeferred(node); } function checkMissingDeclaration(node: Node) { @@ -14503,54 +14494,56 @@ namespace ts { } } - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node) - } + checkUnusedIdentifiersDeferred(node); } function checkUnusedIdentifiersDeferred(node: Node) { - deferredUnusedIdentifierNodes.push(node); + if (deferredUnusedIdentifierNodes) { + deferredUnusedIdentifierNodes.push(node); + } } function checkUnusedIdentifiersDeferredNodes() { - for (const node of deferredUnusedIdentifierNodes) { - switch (node.kind) { - case SyntaxKind.SourceFile: - case SyntaxKind.ModuleDeclaration: - checkUnusedModuleLocals(node); - break; - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - checkUnusedClassLocals(node); - checkUnusedTypeParameters(node); - break; - case SyntaxKind.InterfaceDeclaration: - checkUnusedTypeParameters(node); - break; - case SyntaxKind.Block: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - checkUnusedIdentifiers(node); - break; - case SyntaxKind.Constructor: - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ArrowFunction: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - checkUnusedIdentifiers(node); + if (deferredUnusedIdentifierNodes) { + for (const node of deferredUnusedIdentifierNodes) { + switch (node.kind) { + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: + checkUnusedModuleLocals(node); + break; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + checkUnusedClassLocals(node); + checkUnusedTypeParameters(node); + break; + case SyntaxKind.InterfaceDeclaration: + checkUnusedTypeParameters(node); + break; + case SyntaxKind.Block: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + checkUnusedIdentifiers(node); + break; + case SyntaxKind.Constructor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + checkUnusedIdentifiers(node); - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - checkUnusedTypeParameters(node); - break; - }; + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + checkUnusedTypeParameters(node); + break; + }; + } } } @@ -14630,7 +14623,7 @@ namespace ts { checkGrammarStatementInAmbientContext(node); } forEach(node.statements, checkSourceElement); - if (produceDiagnostics && noUnusedIdentifiers && node.locals) { + if (node.locals) { checkUnusedIdentifiersDeferred(node); } } @@ -15137,7 +15130,7 @@ namespace ts { } checkSourceElement(node.statement); - if (produceDiagnostics && noUnusedIdentifiers && node.locals) { + if (node.locals) { checkUnusedIdentifiersDeferred(node); } } @@ -15187,8 +15180,8 @@ namespace ts { } checkSourceElement(node.statement); - if (produceDiagnostics && noUnusedIdentifiers && node.locals) { - checkUnusedIdentifiersDeferred(node) + if (node.locals) { + checkUnusedIdentifiersDeferred(node); } } @@ -15782,9 +15775,7 @@ namespace ts { function checkClassExpressionDeferred(node: ClassExpression) { forEach(node.members, checkSourceElement); - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node) - } + checkUnusedIdentifiersDeferred(node); } function checkClassDeclaration(node: ClassDeclaration) { @@ -15794,9 +15785,7 @@ namespace ts { checkClassLikeDeclaration(node); forEach(node.members, checkSourceElement); - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node); - } + checkUnusedIdentifiersDeferred(node); } function checkClassLikeDeclaration(node: ClassLikeDeclaration) { @@ -16504,9 +16493,7 @@ namespace ts { if (node.body) { checkSourceElement(node.body); - if (produceDiagnostics && noUnusedIdentifiers) { - checkUnusedIdentifiersDeferred(node); - } + checkUnusedIdentifiersDeferred(node); } } @@ -17031,13 +17018,13 @@ namespace ts { potentialThisCollisions.length = 0; deferredNodes = []; - deferredUnusedIdentifierNodes = []; + deferredUnusedIdentifierNodes = produceDiagnostics && noUnusedIdentifiers ? [] : undefined; forEach(node.statements, checkSourceElement); checkDeferredNodes(); - if (isExternalModule(node) && produceDiagnostics && noUnusedIdentifiers) { + if (isExternalModule(node)) { checkUnusedIdentifiersDeferred(node); } From b1b3ae07e0aaab8e7a897e47277d66994cd3ea2b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 12:09:49 -0700 Subject: [PATCH 12/34] use isParameterPropertyDeclaration to test for paramter propoerties --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a7cbce6083..65f0a8dd888 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14557,7 +14557,7 @@ namespace ts { error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name); } else if (local.valueDeclaration.kind === SyntaxKind.Parameter && compilerOptions.noUnusedParameters) { - if (local.valueDeclaration.flags === 0) { + if (!isParameterPropertyDeclaration(local.valueDeclaration)) { error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name); } } From c28487db92a5079767300df89ece6e28d52e7bf3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 13:18:06 -0700 Subject: [PATCH 13/34] Report unused identifiers in for statements --- src/compiler/checker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 65f0a8dd888..06813b82557 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15090,6 +15090,7 @@ namespace ts { if (node.condition) checkExpression(node.condition); if (node.incrementor) checkExpression(node.incrementor); checkSourceElement(node.statement); + checkUnusedIdentifiersDeferred(node); } function checkForOfStatement(node: ForOfStatement): void { From 4789ff0316f7a19e53fda55f07a54ff3aedaa26d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 13:34:41 -0700 Subject: [PATCH 14/34] Do not check ambients, and overloads --- src/compiler/checker.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06813b82557..d1c3a88c85e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14532,8 +14532,11 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - checkUnusedIdentifiers(node); - + if ((node).body) { + checkUnusedIdentifiers(node); + } + checkUnusedTypeParameters(node); + break; case SyntaxKind.MethodSignature: case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: @@ -17029,7 +17032,9 @@ namespace ts { checkUnusedIdentifiersDeferred(node); } - checkUnusedIdentifiersDeferredNodes(); + if (!node.isDeclarationFile) { + checkUnusedIdentifiersDeferredNodes(); + } deferredNodes = undefined; deferredUnusedIdentifierNodes = undefined; From 62f47fe995acec622aa88afa19e933b94ee94e3d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 13:35:10 -0700 Subject: [PATCH 15/34] Add tests --- .../unusedLocalsAndParameters.errors.txt | 159 +++++++++ .../reference/unusedLocalsAndParameters.js | 168 +++++++++ ...usedLocalsAndParametersDeferred.errors.txt | 172 +++++++++ .../unusedLocalsAndParametersDeferred.js | 325 ++++++++++++++++++ ...edLocalsAndParametersOverloadSignatures.js | 45 +++ ...alsAndParametersOverloadSignatures.symbols | 70 ++++ ...ocalsAndParametersOverloadSignatures.types | 74 ++++ .../compiler/unusedLocalsAndParameters.ts | 86 +++++ .../unusedLocalsAndParametersDeferred.ts | 162 +++++++++ ...edLocalsAndParametersOverloadSignatures.ts | 25 ++ 10 files changed, 1286 insertions(+) create mode 100644 tests/baselines/reference/unusedLocalsAndParameters.errors.txt create mode 100644 tests/baselines/reference/unusedLocalsAndParameters.js create mode 100644 tests/baselines/reference/unusedLocalsAndParametersDeferred.errors.txt create mode 100644 tests/baselines/reference/unusedLocalsAndParametersDeferred.js create mode 100644 tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.js create mode 100644 tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.symbols create mode 100644 tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.types create mode 100644 tests/cases/compiler/unusedLocalsAndParameters.ts create mode 100644 tests/cases/compiler/unusedLocalsAndParametersDeferred.ts create mode 100644 tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts diff --git a/tests/baselines/reference/unusedLocalsAndParameters.errors.txt b/tests/baselines/reference/unusedLocalsAndParameters.errors.txt new file mode 100644 index 00000000000..a7b1d1b37f4 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParameters.errors.txt @@ -0,0 +1,159 @@ +tests/cases/compiler/unusedLocalsAndParameters.ts(5,12): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(10,22): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(16,5): error TS6133: 'farrow' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(16,15): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(19,7): error TS6133: 'C' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(21,12): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(24,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/unusedLocalsAndParameters.ts(24,11): error TS6133: 'v' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(28,5): error TS6133: 'E' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(30,12): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(33,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/unusedLocalsAndParameters.ts(33,11): error TS6133: 'v' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(39,12): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(42,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/unusedLocalsAndParameters.ts(42,11): error TS6133: 'v' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(49,10): error TS6133: 'i' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(53,10): error TS6133: 'i' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(57,17): error TS6133: 'n' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(64,11): error TS6133: 'c' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(69,11): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(72,11): error TS6133: 'c' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(75,11): error TS6133: 'c' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(80,11): error TS6133: 'N' is declared but never used. +tests/cases/compiler/unusedLocalsAndParameters.ts(81,9): error TS6133: 'x' is declared but never used. + + +==== tests/cases/compiler/unusedLocalsAndParameters.ts (24 errors) ==== + + export { }; + + // function declaration paramter + function f(a) { + ~ +!!! error TS6133: 'a' is declared but never used. + } + f(0); + + // function expression paramter + var fexp = function (a) { + ~ +!!! error TS6133: 'a' is declared but never used. + }; + + fexp(0); + + // arrow function paramter + var farrow = (a) => { + ~~~~~~ +!!! error TS6133: 'farrow' is declared but never used. + ~ +!!! error TS6133: 'a' is declared but never used. + }; + + class C { + ~ +!!! error TS6133: 'C' is declared but never used. + // Method declaration paramter + method(a) { + ~ +!!! error TS6133: 'a' is declared but never used. + } + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + ~ +!!! error TS6133: 'v' is declared but never used. + } + } + + var E = class { + ~ +!!! error TS6133: 'E' is declared but never used. + // Method declaration paramter + method(a) { + ~ +!!! error TS6133: 'a' is declared but never used. + } + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + ~ +!!! error TS6133: 'v' is declared but never used. + } + } + + var o = { + // Object literal method declaration paramter + method(a) { + ~ +!!! error TS6133: 'a' is declared but never used. + }, + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + ~ +!!! error TS6133: 'v' is declared but never used. + } + }; + + o; + + // in a for..in statment + for (let i in o) { + ~ +!!! error TS6133: 'i' is declared but never used. + } + + // in a for..of statment + for (let i of [1, 2, 3]) { + ~ +!!! error TS6133: 'i' is declared but never used. + } + + // in a for. statment + for (let i = 0, n; i < 10; i++) { + ~ +!!! error TS6133: 'n' is declared but never used. + } + + // in a block + + const condition = false; + if (condition) { + const c = 0; + ~ +!!! error TS6133: 'c' is declared but never used. + } + + // in try/catch/finally + try { + const a = 0; + ~ +!!! error TS6133: 'a' is declared but never used. + } + catch (e) { + const c = 1; + ~ +!!! error TS6133: 'c' is declared but never used. + } + finally { + const c = 0; + ~ +!!! error TS6133: 'c' is declared but never used. + } + + + // in a namespace + namespace N { + ~ +!!! error TS6133: 'N' is declared but never used. + var x; + ~ +!!! error TS6133: 'x' is declared but never used. + } + + \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsAndParameters.js b/tests/baselines/reference/unusedLocalsAndParameters.js new file mode 100644 index 00000000000..64ff373db4a --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParameters.js @@ -0,0 +1,168 @@ +//// [unusedLocalsAndParameters.ts] + +export { }; + +// function declaration paramter +function f(a) { +} +f(0); + +// function expression paramter +var fexp = function (a) { +}; + +fexp(0); + +// arrow function paramter +var farrow = (a) => { +}; + +class C { + // Method declaration paramter + method(a) { + } + // Accessor declaration paramter + set x(v: number) { + } +} + +var E = class { + // Method declaration paramter + method(a) { + } + // Accessor declaration paramter + set x(v: number) { + } +} + +var o = { + // Object literal method declaration paramter + method(a) { + }, + // Accessor declaration paramter + set x(v: number) { + } +}; + +o; + +// in a for..in statment +for (let i in o) { +} + +// in a for..of statment +for (let i of [1, 2, 3]) { +} + +// in a for. statment +for (let i = 0, n; i < 10; i++) { +} + +// in a block + +const condition = false; +if (condition) { + const c = 0; +} + +// in try/catch/finally +try { + const a = 0; +} +catch (e) { + const c = 1; +} +finally { + const c = 0; +} + + +// in a namespace +namespace N { + var x; +} + + + +//// [unusedLocalsAndParameters.js] +"use strict"; +// function declaration paramter +function f(a) { +} +f(0); +// function expression paramter +var fexp = function (a) { +}; +fexp(0); +// arrow function paramter +var farrow = function (a) { +}; +var C = (function () { + function C() { + } + // Method declaration paramter + C.prototype.method = function (a) { + }; + Object.defineProperty(C.prototype, "x", { + // Accessor declaration paramter + set: function (v) { + }, + enumerable: true, + configurable: true + }); + return C; +}()); +var E = (function () { + function class_1() { + } + // Method declaration paramter + class_1.prototype.method = function (a) { + }; + Object.defineProperty(class_1.prototype, "x", { + // Accessor declaration paramter + set: function (v) { + }, + enumerable: true, + configurable: true + }); + return class_1; +}()); +var o = { + // Object literal method declaration paramter + method: function (a) { + }, + // Accessor declaration paramter + set x(v) { + } +}; +o; +// in a for..in statment +for (var i in o) { +} +// in a for..of statment +for (var _i = 0, _a = [1, 2, 3]; _i < _a.length; _i++) { + var i = _a[_i]; +} +// in a for. statment +for (var i = 0, n = void 0; i < 10; i++) { +} +// in a block +var condition = false; +if (condition) { + var c = 0; +} +// in try/catch/finally +try { + var a = 0; +} +catch (e) { + var c = 1; +} +finally { + var c = 0; +} +// in a namespace +var N; +(function (N) { + var x; +})(N || (N = {})); diff --git a/tests/baselines/reference/unusedLocalsAndParametersDeferred.errors.txt b/tests/baselines/reference/unusedLocalsAndParametersDeferred.errors.txt new file mode 100644 index 00000000000..63afd213f1c --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersDeferred.errors.txt @@ -0,0 +1,172 @@ +tests/cases/compiler/unusedLocalsAndParametersDeferred.ts(42,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/unusedLocalsAndParametersDeferred.ts(65,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. +tests/cases/compiler/unusedLocalsAndParametersDeferred.ts(87,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + + +==== tests/cases/compiler/unusedLocalsAndParametersDeferred.ts (3 errors) ==== + + export { }; + + function defered(a: () => T): T { + return a(); + } + + // function declaration paramter + function f(a) { + defered(() => { + a; + }); + } + f(0); + + // function expression paramter + var fexp = function (a) { + defered(() => { + a; + }); + }; + fexp(1); + + // arrow function paramter + var farrow = (a) => { + defered(() => { + a; + }); + }; + farrow(2); + + let prop1; + + class C { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop1; + }); + } + + new C(); + + let prop2; + + var E = class { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop2; + }); + } + + new E(); + + + var o = { + // Object literal method declaration paramter + method(a) { + defered(() => { + a; + }); + }, + // Accessor declaration paramter + set x(v: number) { + ~ +!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. + defered(() => { + v; + }); + }, + // in a property initalizer + p: defered(() => { + prop1; + }) + }; + + o; + + // in a for..in statment + for (let i in o) { + defered(() => { + i; + }); + } + + // in a for..of statment + for (let i of [1,2,3]) { + defered(() => { + i; + }); + } + + // in a for. statment + for (let i = 0; i < 10; i++) { + defered(() => { + i; + }); + } + + // in a block + + const condition = false; + if (condition) { + const c = 0; + defered(() => { + c; + }); + } + + // in try/catch/finally + try { + const a = 0; + defered(() => { + a; + }); + } + catch (e) { + const c = 1; + defered(() => { + c; + }); + } + finally { + const c = 0; + defered(() => { + c; + }); + } + + + // in a namespace + namespace N { + var x; + defered(() => { + x; + }); + } + N; + \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsAndParametersDeferred.js b/tests/baselines/reference/unusedLocalsAndParametersDeferred.js new file mode 100644 index 00000000000..7fbfd15c526 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersDeferred.js @@ -0,0 +1,325 @@ +//// [unusedLocalsAndParametersDeferred.ts] + +export { }; + +function defered(a: () => T): T { + return a(); +} + +// function declaration paramter +function f(a) { + defered(() => { + a; + }); +} +f(0); + +// function expression paramter +var fexp = function (a) { + defered(() => { + a; + }); +}; +fexp(1); + +// arrow function paramter +var farrow = (a) => { + defered(() => { + a; + }); +}; +farrow(2); + +let prop1; + +class C { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop1; + }); +} + +new C(); + +let prop2; + +var E = class { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop2; + }); +} + +new E(); + + +var o = { + // Object literal method declaration paramter + method(a) { + defered(() => { + a; + }); + }, + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + }, + // in a property initalizer + p: defered(() => { + prop1; + }) +}; + +o; + +// in a for..in statment +for (let i in o) { + defered(() => { + i; + }); +} + +// in a for..of statment +for (let i of [1,2,3]) { + defered(() => { + i; + }); +} + +// in a for. statment +for (let i = 0; i < 10; i++) { + defered(() => { + i; + }); +} + +// in a block + +const condition = false; +if (condition) { + const c = 0; + defered(() => { + c; + }); +} + +// in try/catch/finally +try { + const a = 0; + defered(() => { + a; + }); +} +catch (e) { + const c = 1; + defered(() => { + c; + }); +} +finally { + const c = 0; + defered(() => { + c; + }); +} + + +// in a namespace +namespace N { + var x; + defered(() => { + x; + }); +} +N; + + +//// [unusedLocalsAndParametersDeferred.js] +"use strict"; +function defered(a) { + return a(); +} +// function declaration paramter +function f(a) { + defered(function () { + a; + }); +} +f(0); +// function expression paramter +var fexp = function (a) { + defered(function () { + a; + }); +}; +fexp(1); +// arrow function paramter +var farrow = function (a) { + defered(function () { + a; + }); +}; +farrow(2); +var prop1; +var C = (function () { + function C() { + // in a property initalizer + this.p = defered(function () { + prop1; + }); + } + // Method declaration paramter + C.prototype.method = function (a) { + defered(function () { + a; + }); + }; + Object.defineProperty(C.prototype, "x", { + // Accessor declaration paramter + set: function (v) { + defered(function () { + v; + }); + }, + enumerable: true, + configurable: true + }); + return C; +}()); +new C(); +var prop2; +var E = (function () { + function class_1() { + // in a property initalizer + this.p = defered(function () { + prop2; + }); + } + // Method declaration paramter + class_1.prototype.method = function (a) { + defered(function () { + a; + }); + }; + Object.defineProperty(class_1.prototype, "x", { + // Accessor declaration paramter + set: function (v) { + defered(function () { + v; + }); + }, + enumerable: true, + configurable: true + }); + return class_1; +}()); +new E(); +var o = { + // Object literal method declaration paramter + method: function (a) { + defered(function () { + a; + }); + }, + // Accessor declaration paramter + set x(v) { + defered(function () { + v; + }); + }, + // in a property initalizer + p: defered(function () { + prop1; + }) +}; +o; +// in a for..in statment +var _loop_1 = function(i) { + defered(function () { + i; + }); +}; +for (var i in o) { + _loop_1(i); +} +// in a for..of statment +var _loop_2 = function(i) { + defered(function () { + i; + }); +}; +for (var _i = 0, _a = [1, 2, 3]; _i < _a.length; _i++) { + var i = _a[_i]; + _loop_2(i); +} +// in a for. statment +var _loop_3 = function(i) { + defered(function () { + i; + }); +}; +for (var i = 0; i < 10; i++) { + _loop_3(i); +} +// in a block +var condition = false; +if (condition) { + var c_1 = 0; + defered(function () { + c_1; + }); +} +// in try/catch/finally +try { + var a_1 = 0; + defered(function () { + a_1; + }); +} +catch (e) { + var c_2 = 1; + defered(function () { + c_2; + }); +} +finally { + var c_3 = 0; + defered(function () { + c_3; + }); +} +// in a namespace +var N; +(function (N) { + var x; + defered(function () { + x; + }); +})(N || (N = {})); +N; diff --git a/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.js b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.js new file mode 100644 index 00000000000..221d49a0fdf --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.js @@ -0,0 +1,45 @@ +//// [unusedLocalsAndParametersOverloadSignatures.ts] + +export function func(details: number, message: string, ...args: any[]): void; +export function func(details: number, message: string): any { + return details + message; +} + +export class C { + constructor(details: number, message: string, ...args: any[]); + constructor(details: number, message: string) { + details + message; + } + + method(details: number, message: string, ...args: any[]): void; + method(details: number, message: string): any { + return details + message; + } +} + + +export function genericFunc(details: number, message: T, ...args: any[]): void; +export function genericFunc(details: number, message: any): any { + return details + message; +} + +//// [unusedLocalsAndParametersOverloadSignatures.js] +"use strict"; +function func(details, message) { + return details + message; +} +exports.func = func; +var C = (function () { + function C(details, message) { + details + message; + } + C.prototype.method = function (details, message) { + return details + message; + }; + return C; +}()); +exports.C = C; +function genericFunc(details, message) { + return details + message; +} +exports.genericFunc = genericFunc; diff --git a/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.symbols b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.symbols new file mode 100644 index 00000000000..da3c47f2e42 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.symbols @@ -0,0 +1,70 @@ +=== tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts === + +export function func(details: number, message: string, ...args: any[]): void; +>func : Symbol(func, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 0, 0), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 1, 77)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 1, 21)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 1, 37)) +>args : Symbol(args, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 1, 54)) + +export function func(details: number, message: string): any { +>func : Symbol(func, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 0, 0), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 1, 77)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 2, 21)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 2, 37)) + + return details + message; +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 2, 21)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 2, 37)) +} + +export class C { +>C : Symbol(C, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 4, 1)) + + constructor(details: number, message: string, ...args: any[]); +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 7, 16)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 7, 32)) +>args : Symbol(args, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 7, 49)) + + constructor(details: number, message: string) { +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 8, 16)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 8, 32)) + + details + message; +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 8, 16)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 8, 32)) + } + + method(details: number, message: string, ...args: any[]): void; +>method : Symbol(C.method, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 10, 5), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 12, 67)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 12, 11)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 12, 27)) +>args : Symbol(args, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 12, 44)) + + method(details: number, message: string): any { +>method : Symbol(C.method, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 10, 5), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 12, 67)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 13, 11)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 13, 27)) + + return details + message; +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 13, 11)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 13, 27)) + } +} + + +export function genericFunc(details: number, message: T, ...args: any[]): void; +>genericFunc : Symbol(genericFunc, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 16, 1), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 82)) +>T : Symbol(T, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 28)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 31)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 47)) +>T : Symbol(T, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 28)) +>args : Symbol(args, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 59)) + +export function genericFunc(details: number, message: any): any { +>genericFunc : Symbol(genericFunc, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 16, 1), Decl(unusedLocalsAndParametersOverloadSignatures.ts, 19, 82)) +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 20, 28)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 20, 44)) + + return details + message; +>details : Symbol(details, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 20, 28)) +>message : Symbol(message, Decl(unusedLocalsAndParametersOverloadSignatures.ts, 20, 44)) +} diff --git a/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.types b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.types new file mode 100644 index 00000000000..2a216c8acd2 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersOverloadSignatures.types @@ -0,0 +1,74 @@ +=== tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts === + +export function func(details: number, message: string, ...args: any[]): void; +>func : (details: number, message: string, ...args: any[]) => void +>details : number +>message : string +>args : any[] + +export function func(details: number, message: string): any { +>func : (details: number, message: string, ...args: any[]) => void +>details : number +>message : string + + return details + message; +>details + message : string +>details : number +>message : string +} + +export class C { +>C : C + + constructor(details: number, message: string, ...args: any[]); +>details : number +>message : string +>args : any[] + + constructor(details: number, message: string) { +>details : number +>message : string + + details + message; +>details + message : string +>details : number +>message : string + } + + method(details: number, message: string, ...args: any[]): void; +>method : (details: number, message: string, ...args: any[]) => void +>details : number +>message : string +>args : any[] + + method(details: number, message: string): any { +>method : (details: number, message: string, ...args: any[]) => void +>details : number +>message : string + + return details + message; +>details + message : string +>details : number +>message : string + } +} + + +export function genericFunc(details: number, message: T, ...args: any[]): void; +>genericFunc : (details: number, message: T, ...args: any[]) => void +>T : T +>details : number +>message : T +>T : T +>args : any[] + +export function genericFunc(details: number, message: any): any { +>genericFunc : (details: number, message: T, ...args: any[]) => void +>details : number +>message : any + + return details + message; +>details + message : any +>details : number +>message : any +} diff --git a/tests/cases/compiler/unusedLocalsAndParameters.ts b/tests/cases/compiler/unusedLocalsAndParameters.ts new file mode 100644 index 00000000000..1f4fc944ff4 --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndParameters.ts @@ -0,0 +1,86 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +export { }; + +// function declaration paramter +function f(a) { +} +f(0); + +// function expression paramter +var fexp = function (a) { +}; + +fexp(0); + +// arrow function paramter +var farrow = (a) => { +}; + +class C { + // Method declaration paramter + method(a) { + } + // Accessor declaration paramter + set x(v: number) { + } +} + +var E = class { + // Method declaration paramter + method(a) { + } + // Accessor declaration paramter + set x(v: number) { + } +} + +var o = { + // Object literal method declaration paramter + method(a) { + }, + // Accessor declaration paramter + set x(v: number) { + } +}; + +o; + +// in a for..in statment +for (let i in o) { +} + +// in a for..of statment +for (let i of [1, 2, 3]) { +} + +// in a for. statment +for (let i = 0, n; i < 10; i++) { +} + +// in a block + +const condition = false; +if (condition) { + const c = 0; +} + +// in try/catch/finally +try { + const a = 0; +} +catch (e) { + const c = 1; +} +finally { + const c = 0; +} + + +// in a namespace +namespace N { + var x; +} + + \ No newline at end of file diff --git a/tests/cases/compiler/unusedLocalsAndParametersDeferred.ts b/tests/cases/compiler/unusedLocalsAndParametersDeferred.ts new file mode 100644 index 00000000000..75b98308199 --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndParametersDeferred.ts @@ -0,0 +1,162 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +export { }; + +function defered(a: () => T): T { + return a(); +} + +// function declaration paramter +function f(a) { + defered(() => { + a; + }); +} +f(0); + +// function expression paramter +var fexp = function (a) { + defered(() => { + a; + }); +}; +fexp(1); + +// arrow function paramter +var farrow = (a) => { + defered(() => { + a; + }); +}; +farrow(2); + +let prop1; + +class C { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop1; + }); +} + +new C(); + +let prop2; + +var E = class { + // Method declaration paramter + method(a) { + defered(() => { + a; + }); + } + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + } + // in a property initalizer + p = defered(() => { + prop2; + }); +} + +new E(); + + +var o = { + // Object literal method declaration paramter + method(a) { + defered(() => { + a; + }); + }, + // Accessor declaration paramter + set x(v: number) { + defered(() => { + v; + }); + }, + // in a property initalizer + p: defered(() => { + prop1; + }) +}; + +o; + +// in a for..in statment +for (let i in o) { + defered(() => { + i; + }); +} + +// in a for..of statment +for (let i of [1,2,3]) { + defered(() => { + i; + }); +} + +// in a for. statment +for (let i = 0; i < 10; i++) { + defered(() => { + i; + }); +} + +// in a block + +const condition = false; +if (condition) { + const c = 0; + defered(() => { + c; + }); +} + +// in try/catch/finally +try { + const a = 0; + defered(() => { + a; + }); +} +catch (e) { + const c = 1; + defered(() => { + c; + }); +} +finally { + const c = 0; + defered(() => { + c; + }); +} + + +// in a namespace +namespace N { + var x; + defered(() => { + x; + }); +} +N; + \ No newline at end of file diff --git a/tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts b/tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts new file mode 100644 index 00000000000..32affb28be3 --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndParametersOverloadSignatures.ts @@ -0,0 +1,25 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +export function func(details: number, message: string, ...args: any[]): void; +export function func(details: number, message: string): any { + return details + message; +} + +export class C { + constructor(details: number, message: string, ...args: any[]); + constructor(details: number, message: string) { + details + message; + } + + method(details: number, message: string, ...args: any[]): void; + method(details: number, message: string): any { + return details + message; + } +} + + +export function genericFunc(details: number, message: T, ...args: any[]): void; +export function genericFunc(details: number, message: any): any { + return details + message; +} \ No newline at end of file From d4513c8affcd1e127b72e6f03d03a9ef073da031 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 14:07:42 -0700 Subject: [PATCH 16/34] Consolidate type reference marking in getTypeFromTypeReference --- src/compiler/checker.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1c3a88c85e..26b94358f36 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4961,6 +4961,10 @@ namespace ts { // type reference in checkTypeReferenceOrExpressionWithTypeArguments. links.resolvedSymbol = symbol; links.resolvedType = type; + + if (noUnusedIdentifiers && symbol !== unknownSymbol && !isInAmbientContext(node)) { + symbol.hasReference = true; + } } return links.resolvedType; } @@ -8321,16 +8325,6 @@ namespace ts { return container === declarationContainer; } - function updateReferencesForInterfaceHeritiageClauseTargets(node: InterfaceDeclaration): void { - const extendedTypeNode = getClassExtendsHeritageClauseElement(node); - if (extendedTypeNode) { - const t = getTypeFromTypeNode(extendedTypeNode); - if (t !== unknownType && t.symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { - t.symbol.hasReference = true; - } - } - } - function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); if (symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { @@ -13620,9 +13614,6 @@ namespace ts { checkGrammarTypeArguments(node, node.typeArguments); const type = getTypeFromTypeReference(node); if (type !== unknownType) { - if (type.symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { - type.symbol.hasReference = true; - } if (node.typeArguments) { // Do type argument local checks only if referenced type is successfully resolved forEach(node.typeArguments, checkSourceElement); @@ -16099,7 +16090,6 @@ namespace ts { if (produceDiagnostics) { checkTypeForDuplicateIndexSignatures(node); - updateReferencesForInterfaceHeritiageClauseTargets(node); checkUnusedTypeParameters(node); } } From 97aa9879784c4b4720099fd12a902341ab0838aa Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 14:07:55 -0700 Subject: [PATCH 17/34] Handel type aliases --- src/compiler/checker.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26b94358f36..b715310ad02 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14546,15 +14546,15 @@ namespace ts { for (const key in node.locals) { if (hasProperty(node.locals, key)) { const local = node.locals[key]; - if (!local.hasReference && local.valueDeclaration) { - if (local.valueDeclaration.kind !== SyntaxKind.Parameter && compilerOptions.noUnusedLocals) { - error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name); - } - else if (local.valueDeclaration.kind === SyntaxKind.Parameter && compilerOptions.noUnusedParameters) { - if (!isParameterPropertyDeclaration(local.valueDeclaration)) { + if (!local.hasReference) { + if (local.valueDeclaration && local.valueDeclaration.kind === SyntaxKind.Parameter) { + if (compilerOptions.noUnusedParameters && !isParameterPropertyDeclaration(local.valueDeclaration)) { error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name); } } + else if (compilerOptions.noUnusedLocals) { + forEach(local.declarations, d => error(d.name || d, Diagnostics._0_is_declared_but_never_used, local.name)); + } } } } From f81a8e7382820ec94815ee2dbbb94818b052c1b0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 14:08:20 -0700 Subject: [PATCH 18/34] Add tests --- .../unusedLocalsAndParametersTypeAliases.js | 35 +++++++++++ ...usedLocalsAndParametersTypeAliases.symbols | 59 +++++++++++++++++ ...unusedLocalsAndParametersTypeAliases.types | 63 +++++++++++++++++++ ...LocalsAndParametersTypeAliases2.errors.txt | 20 ++++++ .../unusedLocalsAndParametersTypeAliases2.js | 18 ++++++ .../unusedLocalsAndParametersTypeAliases.ts | 29 +++++++++ .../unusedLocalsAndParametersTypeAliases2.ts | 13 ++++ 7 files changed, 237 insertions(+) create mode 100644 tests/baselines/reference/unusedLocalsAndParametersTypeAliases.js create mode 100644 tests/baselines/reference/unusedLocalsAndParametersTypeAliases.symbols create mode 100644 tests/baselines/reference/unusedLocalsAndParametersTypeAliases.types create mode 100644 tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt create mode 100644 tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.js create mode 100644 tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts create mode 100644 tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.js b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.js new file mode 100644 index 00000000000..b854278a3e3 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.js @@ -0,0 +1,35 @@ +//// [unusedLocalsAndParametersTypeAliases.ts] + +// used in a declaration +type handler1 = () => void; +export interface I1 { + getHandler: handler1; +} + +// exported +export type handler2 = () => void; + +// used in extends clause +type handler3 = () => void; +export interface I3 { + getHandler: T; +} + +// used in another type alias declaration +type handler4 = () => void; +type handler5 = handler4 | (()=>number); +var x: handler5; +x(); + +// used as type argument +type handler6 = () => void; +var y: Array; +y[0](); + + +//// [unusedLocalsAndParametersTypeAliases.js] +"use strict"; +var x; +x(); +var y; +y[0](); diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.symbols b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.symbols new file mode 100644 index 00000000000..9f9004d7a28 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.symbols @@ -0,0 +1,59 @@ +=== tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts === + +// used in a declaration +type handler1 = () => void; +>handler1 : Symbol(handler1, Decl(unusedLocalsAndParametersTypeAliases.ts, 0, 0)) + +export interface I1 { +>I1 : Symbol(I1, Decl(unusedLocalsAndParametersTypeAliases.ts, 2, 27)) + + getHandler: handler1; +>getHandler : Symbol(I1.getHandler, Decl(unusedLocalsAndParametersTypeAliases.ts, 3, 21)) +>handler1 : Symbol(handler1, Decl(unusedLocalsAndParametersTypeAliases.ts, 0, 0)) +} + +// exported +export type handler2 = () => void; +>handler2 : Symbol(handler2, Decl(unusedLocalsAndParametersTypeAliases.ts, 5, 1)) + +// used in extends clause +type handler3 = () => void; +>handler3 : Symbol(handler3, Decl(unusedLocalsAndParametersTypeAliases.ts, 8, 34)) + +export interface I3 { +>I3 : Symbol(I3, Decl(unusedLocalsAndParametersTypeAliases.ts, 11, 27)) +>T : Symbol(T, Decl(unusedLocalsAndParametersTypeAliases.ts, 12, 20)) +>handler3 : Symbol(handler3, Decl(unusedLocalsAndParametersTypeAliases.ts, 8, 34)) + + getHandler: T; +>getHandler : Symbol(I3.getHandler, Decl(unusedLocalsAndParametersTypeAliases.ts, 12, 41)) +>T : Symbol(T, Decl(unusedLocalsAndParametersTypeAliases.ts, 12, 20)) +} + +// used in another type alias declaration +type handler4 = () => void; +>handler4 : Symbol(handler4, Decl(unusedLocalsAndParametersTypeAliases.ts, 14, 1)) + +type handler5 = handler4 | (()=>number); +>handler5 : Symbol(handler5, Decl(unusedLocalsAndParametersTypeAliases.ts, 17, 27)) +>handler4 : Symbol(handler4, Decl(unusedLocalsAndParametersTypeAliases.ts, 14, 1)) + +var x: handler5; +>x : Symbol(x, Decl(unusedLocalsAndParametersTypeAliases.ts, 19, 3)) +>handler5 : Symbol(handler5, Decl(unusedLocalsAndParametersTypeAliases.ts, 17, 27)) + +x(); +>x : Symbol(x, Decl(unusedLocalsAndParametersTypeAliases.ts, 19, 3)) + +// used as type argument +type handler6 = () => void; +>handler6 : Symbol(handler6, Decl(unusedLocalsAndParametersTypeAliases.ts, 20, 4)) + +var y: Array; +>y : Symbol(y, Decl(unusedLocalsAndParametersTypeAliases.ts, 24, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>handler6 : Symbol(handler6, Decl(unusedLocalsAndParametersTypeAliases.ts, 20, 4)) + +y[0](); +>y : Symbol(y, Decl(unusedLocalsAndParametersTypeAliases.ts, 24, 3)) + diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.types b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.types new file mode 100644 index 00000000000..82c87deb7d0 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases.types @@ -0,0 +1,63 @@ +=== tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts === + +// used in a declaration +type handler1 = () => void; +>handler1 : () => void + +export interface I1 { +>I1 : I1 + + getHandler: handler1; +>getHandler : () => void +>handler1 : () => void +} + +// exported +export type handler2 = () => void; +>handler2 : () => void + +// used in extends clause +type handler3 = () => void; +>handler3 : () => void + +export interface I3 { +>I3 : I3 +>T : T +>handler3 : () => void + + getHandler: T; +>getHandler : T +>T : T +} + +// used in another type alias declaration +type handler4 = () => void; +>handler4 : () => void + +type handler5 = handler4 | (()=>number); +>handler5 : (() => void) | (() => number) +>handler4 : () => void + +var x: handler5; +>x : (() => void) | (() => number) +>handler5 : (() => void) | (() => number) + +x(); +>x() : void | number +>x : (() => void) | (() => number) + +// used as type argument +type handler6 = () => void; +>handler6 : () => void + +var y: Array; +>y : (() => void)[] +>Array : T[] +>handler6 : () => void + +y[0](); +>y[0]() : void +>y[0] : () => void +>y : (() => void)[] +>0 : number + diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt new file mode 100644 index 00000000000..d6abf6f2f3f --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(3,6): error TS6133: 'handler1' is declared but never used. +tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts(7,10): error TS6133: 'handler2' is declared but never used. + + +==== tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts (2 errors) ==== + + // unused + type handler1 = () => void; + ~~~~~~~~ +!!! error TS6133: 'handler1' is declared but never used. + + + function foo() { + type handler2 = () => void; + ~~~~~~~~ +!!! error TS6133: 'handler2' is declared but never used. + foo(); + } + + export {} \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.js b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.js new file mode 100644 index 00000000000..7da916370ca --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndParametersTypeAliases2.js @@ -0,0 +1,18 @@ +//// [unusedLocalsAndParametersTypeAliases2.ts] + +// unused +type handler1 = () => void; + + +function foo() { + type handler2 = () => void; + foo(); +} + +export {} + +//// [unusedLocalsAndParametersTypeAliases2.js] +"use strict"; +function foo() { + foo(); +} diff --git a/tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts b/tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts new file mode 100644 index 00000000000..b94f88845bc --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndParametersTypeAliases.ts @@ -0,0 +1,29 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +// used in a declaration +type handler1 = () => void; +export interface I1 { + getHandler: handler1; +} + +// exported +export type handler2 = () => void; + +// used in extends clause +type handler3 = () => void; +export interface I3 { + getHandler: T; +} + +// used in another type alias declaration +type handler4 = () => void; +type handler5 = handler4 | (()=>number); +var x: handler5; +x(); + +// used as type argument +type handler6 = () => void; +var y: Array; +y[0](); + \ No newline at end of file diff --git a/tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts b/tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts new file mode 100644 index 00000000000..23d23a5bc18 --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndParametersTypeAliases2.ts @@ -0,0 +1,13 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +// unused +type handler1 = () => void; + + +function foo() { + type handler2 = () => void; + foo(); +} + +export {} \ No newline at end of file From adca77003e2229b9d0ad7170676fd2b121efefc3 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 29 Jun 2016 16:00:11 -0700 Subject: [PATCH 19/34] Add test --- .../formattingIllegalImportClause.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/cases/fourslash/formattingIllegalImportClause.ts diff --git a/tests/cases/fourslash/formattingIllegalImportClause.ts b/tests/cases/fourslash/formattingIllegalImportClause.ts new file mode 100644 index 00000000000..9e97087c000 --- /dev/null +++ b/tests/cases/fourslash/formattingIllegalImportClause.ts @@ -0,0 +1,26 @@ +/// + +//// var expect = require('expect.js'); +//// import React from 'react'/*1*/; +//// import { mount } from 'enzyme'; +//// require('../setup'); +//// var Amount = require('../../src/js/components/amount'); + +//// describe('', () => { +//// var history +//// beforeEach(() => { +//// history = createMemoryHistory(); +//// sinon.spy(history, 'pushState'); +//// }); + +//// afterEach(() => { +//// }) + +//// it('redirects to order summary', () => { + +//// }); +//// }); + +format.document(); +goTo.marker("1"); +verify.currentLineContentIs("import React from 'react';") \ No newline at end of file From 5a45c44eb789f52ceb1aa0e23a230ecb599bfb08 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Wed, 29 Jun 2016 17:04:42 -0700 Subject: [PATCH 20/34] Dont load JavaScript if types packages are present --- src/compiler/program.ts | 19 ++++++++++++------- .../amd/maxDepthIncreased/root.js | 6 ++++-- .../nodeModulesMaxDepthIncreased.errors.txt | 18 +++++++++++++++--- .../amd/nodeModulesMaxDepthIncreased.json | 1 + .../node/maxDepthIncreased/root.js | 5 ++++- .../nodeModulesMaxDepthIncreased.errors.txt | 18 +++++++++++++++--- .../node/nodeModulesMaxDepthIncreased.json | 1 + .../node_modules/@types/m4/entry.d.ts | 1 + .../node_modules/@types/m4/package.json | 5 +++++ .../node_modules/m4/entry.js | 1 + .../node_modules/m4/package.json | 5 +++++ .../maxDepthIncreased/root.ts | 8 +++++++- 12 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/entry.d.ts create mode 100644 tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/package.json create mode 100644 tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/entry.js create mode 100644 tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/package.json diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 5cb3b8dad7e..c56debdf251 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -779,13 +779,18 @@ namespace ts { while (true) { const baseName = getBaseFileName(directory); if (baseName !== "node_modules") { - const result = - // first: try to load module as-is - loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) || - // second: try to load module from the scope '@types' - loadModuleFromNodeModulesFolder(combinePaths("@types", moduleName), directory, failedLookupLocations, state); - if (result) { - return result; + // Try to load source from the package + const packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state); + if (packageResult && hasTypeScriptFileExtension(packageResult)) { + // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package + return packageResult; + } + else { + // Else prefer a types package over non-TypeScript results (e.g. JavaScript files) + const typesResult = loadModuleFromNodeModulesFolder(combinePaths("@types", moduleName), directory, failedLookupLocations, state); + if (typesResult || packageResult) { + return typesResult || packageResult; + } } } diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js index 77951a4889d..0024891fbe3 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js @@ -1,6 +1,8 @@ -define(["require", "exports", "m1"], function (require, exports, m1) { +define(["require", "exports", "m1", "m4"], function (require, exports, m1, m4) { "use strict"; m1.f1("test"); m1.f2.a = 10; - m1.f2.person.age = "10"; // Error: Should be number + m1.f2.person.age = "10"; // Should error if loaded the .js files correctly + var r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info + var r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file }); diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt index f63c2a789e8..473d69bc526 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt @@ -1,4 +1,5 @@ -maxDepthIncreased/root.ts(4,1): error TS2322: Type 'string' is not assignable to type 'number'. +maxDepthIncreased/root.ts(7,1): error TS2322: Type 'string' is not assignable to type 'number'. +maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. ==== index.js (0 errors) ==== @@ -28,11 +29,22 @@ maxDepthIncreased/root.ts(4,1): error TS2322: Type 'string' is not assignable to exports.f2 = m2; -==== maxDepthIncreased/root.ts (1 errors) ==== +==== entry.d.ts (0 errors) ==== + export declare var foo: number; + +==== maxDepthIncreased/root.ts (2 errors) ==== import * as m1 from "m1"; + import * as m4 from "m4"; + m1.f1("test"); m1.f2.a = 10; - m1.f2.person.age = "10"; // Error: Should be number + + m1.f2.person.age = "10"; // Should error if loaded the .js files correctly ~~~~~~~~~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type 'number'. + let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info + ~~~~ +!!! error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. + + let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file \ No newline at end of file diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.json b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.json index 1350bf6441e..bb3234f1db2 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.json +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.json @@ -10,6 +10,7 @@ "maxDepthIncreased/node_modules/m2/node_modules/m3/index.js", "maxDepthIncreased/node_modules/m2/entry.js", "maxDepthIncreased/node_modules/m1/index.js", + "maxDepthIncreased/node_modules/@types/m4/entry.d.ts", "maxDepthIncreased/root.ts" ], "emittedFiles": [ diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js index 3a0a96991b0..ba6d7e96241 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js @@ -1,5 +1,8 @@ "use strict"; var m1 = require("m1"); +var m4 = require("m4"); m1.f1("test"); m1.f2.a = 10; -m1.f2.person.age = "10"; // Error: Should be number +m1.f2.person.age = "10"; // Should error if loaded the .js files correctly +var r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info +var r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt index f63c2a789e8..473d69bc526 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt @@ -1,4 +1,5 @@ -maxDepthIncreased/root.ts(4,1): error TS2322: Type 'string' is not assignable to type 'number'. +maxDepthIncreased/root.ts(7,1): error TS2322: Type 'string' is not assignable to type 'number'. +maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. ==== index.js (0 errors) ==== @@ -28,11 +29,22 @@ maxDepthIncreased/root.ts(4,1): error TS2322: Type 'string' is not assignable to exports.f2 = m2; -==== maxDepthIncreased/root.ts (1 errors) ==== +==== entry.d.ts (0 errors) ==== + export declare var foo: number; + +==== maxDepthIncreased/root.ts (2 errors) ==== import * as m1 from "m1"; + import * as m4 from "m4"; + m1.f1("test"); m1.f2.a = 10; - m1.f2.person.age = "10"; // Error: Should be number + + m1.f2.person.age = "10"; // Should error if loaded the .js files correctly ~~~~~~~~~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type 'number'. + let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info + ~~~~ +!!! error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. + + let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file \ No newline at end of file diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.json b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.json index 1350bf6441e..bb3234f1db2 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.json +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.json @@ -10,6 +10,7 @@ "maxDepthIncreased/node_modules/m2/node_modules/m3/index.js", "maxDepthIncreased/node_modules/m2/entry.js", "maxDepthIncreased/node_modules/m1/index.js", + "maxDepthIncreased/node_modules/@types/m4/entry.d.ts", "maxDepthIncreased/root.ts" ], "emittedFiles": [ diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/entry.d.ts b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/entry.d.ts new file mode 100644 index 00000000000..f0fc245910a --- /dev/null +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/entry.d.ts @@ -0,0 +1 @@ +export declare var foo: number; diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/package.json b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/package.json new file mode 100644 index 00000000000..53ac1558a23 --- /dev/null +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@types/m4/package.json @@ -0,0 +1,5 @@ +{ + "types": "entry.d.ts", + "name": "m4", + "version": "1.0.0" +} \ No newline at end of file diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/entry.js b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/entry.js new file mode 100644 index 00000000000..a1cb557b18d --- /dev/null +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/entry.js @@ -0,0 +1 @@ +exports.test = "hello, world"; diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/package.json b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/package.json new file mode 100644 index 00000000000..4ae99f312fc --- /dev/null +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/m4/package.json @@ -0,0 +1,5 @@ +{ + "name": "m4", + "version": "1.0.0", + "main": "entry.js" +} \ No newline at end of file diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts index 9ed943bebba..5d9f331b249 100644 --- a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts @@ -1,4 +1,10 @@ import * as m1 from "m1"; +import * as m4 from "m4"; + m1.f1("test"); m1.f2.a = 10; -m1.f2.person.age = "10"; // Error: Should be number + +m1.f2.person.age = "10"; // Should error if loaded the .js files correctly +let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info + +let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file From d8047b607f11cdf319284bb344282582c7c0aea0 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Wed, 29 Jun 2016 17:05:55 -0700 Subject: [PATCH 21/34] Renamed API --- src/compiler/program.ts | 2 +- src/compiler/utilities.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c56debdf251..2e4492efa7b 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1383,7 +1383,7 @@ namespace ts { getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, getSourceFiles: program.getSourceFiles, - isSourceFileFromNodeModules: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path), + isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path), writeFile: writeFileCallback || ( (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e4111e3f925..7892af6624f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -36,7 +36,7 @@ namespace ts { getSourceFiles(): SourceFile[]; /* @internal */ - isSourceFileFromNodeModules(file: SourceFile): boolean; + isSourceFileFromExternalLibrary(file: SourceFile): boolean; getCommonSourceDirectory(): string; getCanonicalFileName(fileName: string): string; @@ -2279,7 +2279,7 @@ namespace ts { const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; for (const sourceFile of sourceFiles) { // Don't emit if source file is a declaration file, or was located under node_modules - if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromNodeModules(sourceFile)) { + if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) { onSingleFileEmit(host, sourceFile); } } @@ -2315,7 +2315,7 @@ namespace ts { // --module or --target es6 specified. Files included by searching under node_modules are also not emitted. const bundledSources = filter(host.getSourceFiles(), sourceFile => !isDeclarationFile(sourceFile) && - !host.isSourceFileFromNodeModules(sourceFile) && + !host.isSourceFileFromExternalLibrary(sourceFile) && (!isExternalModule(sourceFile) || !!getEmitModuleKind(options))); if (bundledSources.length) { From 5f6e25c8d2994694cefc907e50d7ba19f1e07722 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Jun 2016 18:47:10 -0700 Subject: [PATCH 22/34] Use checkExpression, not checkExpressionCached --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ec2ec3309b..0aad4f61960 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12547,7 +12547,7 @@ namespace ts { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. if (strictNullChecks && - !(getCombinedTypeFlags(checkExpressionCached(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { + !(getCombinedTypeFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, contextualMapper); From dc5cf3386182233e135d31b222b1683a963f9718 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 22:54:18 -0700 Subject: [PATCH 23/34] Do not report unused errors for module augmentations --- src/compiler/checker.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b715310ad02..d593683a2a9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14604,7 +14604,11 @@ namespace ts { if (hasProperty(node.locals, key)) { const local = node.locals[key]; if (!local.hasReference && !local.exportSymbol) { - forEach(local.declarations, d => error(d.name, Diagnostics._0_is_declared_but_never_used, local.name)); + for (const declaration of local.declarations) { + if (!isAmbientModule(declaration)) { + error(declaration.name, Diagnostics._0_is_declared_but_never_used, local.name); + } + } } } } @@ -16487,7 +16491,9 @@ namespace ts { if (node.body) { checkSourceElement(node.body); - checkUnusedIdentifiersDeferred(node); + if (!isGlobalScopeAugmentation(node)) { + checkUnusedIdentifiersDeferred(node); + } } } From f751901eee100fea85bf17917700e4d465e50ede Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 23:46:41 -0700 Subject: [PATCH 24/34] Consolidate refernce marking in resolveName to allow marking aliases correctelly --- src/compiler/checker.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d593683a2a9..40ff595b0ad 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -899,6 +899,10 @@ namespace ts { error(errorLocation, Diagnostics.Identifier_0_must_be_imported_from_a_module, name); } } + + if (result && noUnusedIdentifiers && !isInAmbientContext(location)) { + result.hasReference = true; + } } return result; } @@ -4961,10 +4965,6 @@ namespace ts { // type reference in checkTypeReferenceOrExpressionWithTypeArguments. links.resolvedSymbol = symbol; links.resolvedType = type; - - if (noUnusedIdentifiers && symbol !== unknownSymbol && !isInAmbientContext(node)) { - symbol.hasReference = true; - } } return links.resolvedType; } @@ -8327,9 +8327,6 @@ namespace ts { function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); - if (symbol && noUnusedIdentifiers && !isInAmbientContext(node)) { - symbol.hasReference = true; - } // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects. // Although in down-level emit of arrow function, we emit it using function expression which means that @@ -16674,9 +16671,6 @@ namespace ts { if (target.flags & SymbolFlags.Type) { checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); } - if (noUnusedIdentifiers && !isInAmbientContext(node)) { - target.hasReference = true; - } } } else { From 8fb3b25c1e3874334c668a9b82165316a3ad223b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 29 Jun 2016 23:46:50 -0700 Subject: [PATCH 25/34] add tests --- tests/baselines/reference/unusedImports11.js | 41 ++++++++++++++++ .../reference/unusedImports11.symbols | 43 +++++++++++++++++ .../baselines/reference/unusedImports11.types | 48 +++++++++++++++++++ .../reference/unusedImports12.errors.txt | 29 +++++++++++ tests/baselines/reference/unusedImports12.js | 27 +++++++++++ tests/cases/compiler/unusedImports11.ts | 19 ++++++++ tests/cases/compiler/unusedImports12.ts | 13 +++++ 7 files changed, 220 insertions(+) create mode 100644 tests/baselines/reference/unusedImports11.js create mode 100644 tests/baselines/reference/unusedImports11.symbols create mode 100644 tests/baselines/reference/unusedImports11.types create mode 100644 tests/baselines/reference/unusedImports12.errors.txt create mode 100644 tests/baselines/reference/unusedImports12.js create mode 100644 tests/cases/compiler/unusedImports11.ts create mode 100644 tests/cases/compiler/unusedImports12.ts diff --git a/tests/baselines/reference/unusedImports11.js b/tests/baselines/reference/unusedImports11.js new file mode 100644 index 00000000000..86561e1021e --- /dev/null +++ b/tests/baselines/reference/unusedImports11.js @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/unusedImports11.ts] //// + +//// [b.ts] + +export class Member {} +export default Member; + + +//// [a.ts] +import { Member } from './b'; +import d, { Member as M } from './b'; +import * as ns from './b'; +import r = require("./b"); + +new Member(); +new d(); +new M(); +new ns.Member(); +new r.Member(); + +//// [b.js] +"use strict"; +var Member = (function () { + function Member() { + } + return Member; +}()); +exports.Member = Member; +exports.__esModule = true; +exports["default"] = Member; +//// [a.js] +"use strict"; +var b_1 = require('./b'); +var b_2 = require('./b'); +var ns = require('./b'); +var r = require("./b"); +new b_1.Member(); +new b_2["default"](); +new b_2.Member(); +new ns.Member(); +new r.Member(); diff --git a/tests/baselines/reference/unusedImports11.symbols b/tests/baselines/reference/unusedImports11.symbols new file mode 100644 index 00000000000..995b4a40c2a --- /dev/null +++ b/tests/baselines/reference/unusedImports11.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/a.ts === +import { Member } from './b'; +>Member : Symbol(Member, Decl(a.ts, 0, 8)) + +import d, { Member as M } from './b'; +>d : Symbol(d, Decl(a.ts, 1, 6)) +>Member : Symbol(M, Decl(a.ts, 1, 11)) +>M : Symbol(M, Decl(a.ts, 1, 11)) + +import * as ns from './b'; +>ns : Symbol(ns, Decl(a.ts, 2, 6)) + +import r = require("./b"); +>r : Symbol(r, Decl(a.ts, 2, 26)) + +new Member(); +>Member : Symbol(Member, Decl(a.ts, 0, 8)) + +new d(); +>d : Symbol(d, Decl(a.ts, 1, 6)) + +new M(); +>M : Symbol(M, Decl(a.ts, 1, 11)) + +new ns.Member(); +>ns.Member : Symbol(Member, Decl(b.ts, 0, 0)) +>ns : Symbol(ns, Decl(a.ts, 2, 6)) +>Member : Symbol(Member, Decl(b.ts, 0, 0)) + +new r.Member(); +>r.Member : Symbol(Member, Decl(b.ts, 0, 0)) +>r : Symbol(r, Decl(a.ts, 2, 26)) +>Member : Symbol(Member, Decl(b.ts, 0, 0)) + +=== tests/cases/compiler/b.ts === + +export class Member {} +>Member : Symbol(Member, Decl(b.ts, 0, 0)) + +export default Member; +>Member : Symbol(Member, Decl(b.ts, 0, 0)) + + diff --git a/tests/baselines/reference/unusedImports11.types b/tests/baselines/reference/unusedImports11.types new file mode 100644 index 00000000000..1d71a0226b6 --- /dev/null +++ b/tests/baselines/reference/unusedImports11.types @@ -0,0 +1,48 @@ +=== tests/cases/compiler/a.ts === +import { Member } from './b'; +>Member : typeof Member + +import d, { Member as M } from './b'; +>d : typeof Member +>Member : typeof Member +>M : typeof Member + +import * as ns from './b'; +>ns : typeof ns + +import r = require("./b"); +>r : typeof ns + +new Member(); +>new Member() : Member +>Member : typeof Member + +new d(); +>new d() : Member +>d : typeof Member + +new M(); +>new M() : Member +>M : typeof Member + +new ns.Member(); +>new ns.Member() : Member +>ns.Member : typeof Member +>ns : typeof ns +>Member : typeof Member + +new r.Member(); +>new r.Member() : Member +>r.Member : typeof Member +>r : typeof ns +>Member : typeof Member + +=== tests/cases/compiler/b.ts === + +export class Member {} +>Member : Member + +export default Member; +>Member : Member + + diff --git a/tests/baselines/reference/unusedImports12.errors.txt b/tests/baselines/reference/unusedImports12.errors.txt new file mode 100644 index 00000000000..89b0687317b --- /dev/null +++ b/tests/baselines/reference/unusedImports12.errors.txt @@ -0,0 +1,29 @@ +tests/cases/compiler/a.ts(1,10): error TS6133: 'Member' is declared but never used. +tests/cases/compiler/a.ts(2,8): error TS6133: 'd' is declared but never used. +tests/cases/compiler/a.ts(2,23): error TS6133: 'M' is declared but never used. +tests/cases/compiler/a.ts(3,13): error TS6133: 'ns' is declared but never used. +tests/cases/compiler/a.ts(4,8): error TS6133: 'r' is declared but never used. + + +==== tests/cases/compiler/a.ts (5 errors) ==== + import { Member } from './b'; + ~~~~~~ +!!! error TS6133: 'Member' is declared but never used. + import d, { Member as M } from './b'; + ~ +!!! error TS6133: 'd' is declared but never used. + ~ +!!! error TS6133: 'M' is declared but never used. + import * as ns from './b'; + ~~ +!!! error TS6133: 'ns' is declared but never used. + import r = require("./b"); + ~ +!!! error TS6133: 'r' is declared but never used. + +==== tests/cases/compiler/b.ts (0 errors) ==== + + export class Member {} + export default Member; + + \ No newline at end of file diff --git a/tests/baselines/reference/unusedImports12.js b/tests/baselines/reference/unusedImports12.js new file mode 100644 index 00000000000..ece9b105bc9 --- /dev/null +++ b/tests/baselines/reference/unusedImports12.js @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/unusedImports12.ts] //// + +//// [b.ts] + +export class Member {} +export default Member; + + +//// [a.ts] +import { Member } from './b'; +import d, { Member as M } from './b'; +import * as ns from './b'; +import r = require("./b"); + + +//// [b.js] +"use strict"; +var Member = (function () { + function Member() { + } + return Member; +}()); +exports.Member = Member; +exports.__esModule = true; +exports["default"] = Member; +//// [a.js] +"use strict"; diff --git a/tests/cases/compiler/unusedImports11.ts b/tests/cases/compiler/unusedImports11.ts new file mode 100644 index 00000000000..4f2fed649d1 --- /dev/null +++ b/tests/cases/compiler/unusedImports11.ts @@ -0,0 +1,19 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +// @filename: b.ts +export class Member {} +export default Member; + + +// @filename: a.ts +import { Member } from './b'; +import d, { Member as M } from './b'; +import * as ns from './b'; +import r = require("./b"); + +new Member(); +new d(); +new M(); +new ns.Member(); +new r.Member(); \ No newline at end of file diff --git a/tests/cases/compiler/unusedImports12.ts b/tests/cases/compiler/unusedImports12.ts new file mode 100644 index 00000000000..14206284b64 --- /dev/null +++ b/tests/cases/compiler/unusedImports12.ts @@ -0,0 +1,13 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +// @filename: b.ts +export class Member {} +export default Member; + + +// @filename: a.ts +import { Member } from './b'; +import d, { Member as M } from './b'; +import * as ns from './b'; +import r = require("./b"); From 3d9c9206e437542ffce326b7d9820ec98613fead Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 30 Jun 2016 00:03:54 -0700 Subject: [PATCH 26/34] Code review comments --- src/compiler/checker.ts | 60 ++++++++++++++++++++--------------------- src/compiler/types.ts | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 40ff595b0ad..f42ca9ffe34 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -901,7 +901,7 @@ namespace ts { } if (result && noUnusedIdentifiers && !isInAmbientContext(location)) { - result.hasReference = true; + result.isReferenced = true; } } return result; @@ -10242,7 +10242,7 @@ namespace ts { } if (noUnusedIdentifiers && !isInAmbientContext(node)) { - prop.hasReference = true; + prop.isReferenced = true; } getNodeLinks(node).resolvedSymbol = prop; @@ -12187,7 +12187,7 @@ namespace ts { } } } - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } } @@ -13415,7 +13415,7 @@ namespace ts { checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); const symbol = getSymbolOfNode(node); const firstDeclaration = getDeclarationOfKind(symbol, node.kind); @@ -13561,7 +13561,7 @@ namespace ts { } if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) { checkSourceElement(node.body); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } else { checkNodeDeferred(node); @@ -13578,7 +13578,7 @@ namespace ts { function checkAccessorDeferred(node: AccessorDeclaration) { checkSourceElement(node.body); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } function checkMissingDeclaration(node: Node) { @@ -14482,26 +14482,26 @@ namespace ts { } } - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } - function checkUnusedIdentifiersDeferred(node: Node) { + function registerForUnusedIdentifiersCheck(node: Node) { if (deferredUnusedIdentifierNodes) { deferredUnusedIdentifierNodes.push(node); } } - function checkUnusedIdentifiersDeferredNodes() { + function checkUnusedIdentifiers() { if (deferredUnusedIdentifierNodes) { for (const node of deferredUnusedIdentifierNodes) { switch (node.kind) { case SyntaxKind.SourceFile: case SyntaxKind.ModuleDeclaration: - checkUnusedModuleLocals(node); + checkUnusedModuleMembers(node); break; case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - checkUnusedClassLocals(node); + checkUnusedClassMembers(node); checkUnusedTypeParameters(node); break; case SyntaxKind.InterfaceDeclaration: @@ -14511,7 +14511,7 @@ namespace ts { case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - checkUnusedIdentifiers(node); + checkUnusedLocalsAndParameters(node); break; case SyntaxKind.Constructor: case SyntaxKind.FunctionExpression: @@ -14521,7 +14521,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: if ((node).body) { - checkUnusedIdentifiers(node); + checkUnusedLocalsAndParameters(node); } checkUnusedTypeParameters(node); break; @@ -14538,12 +14538,12 @@ namespace ts { } } - function checkUnusedIdentifiers(node: FunctionLikeDeclaration | ForStatement | Block): void { + function checkUnusedLocalsAndParameters(node: FunctionLikeDeclaration | ForStatement | Block): void { if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !isInAmbientContext(node)) { for (const key in node.locals) { if (hasProperty(node.locals, key)) { const local = node.locals[key]; - if (!local.hasReference) { + if (!local.isReferenced) { if (local.valueDeclaration && local.valueDeclaration.kind === SyntaxKind.Parameter) { if (compilerOptions.noUnusedParameters && !isParameterPropertyDeclaration(local.valueDeclaration)) { error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name); @@ -14558,18 +14558,18 @@ namespace ts { } } - function checkUnusedClassLocals(node: ClassDeclaration | ClassExpression): void { + function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { if (node.members) { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { - if (isPrivateNode(member) && !member.symbol.hasReference) { + if (isPrivateNode(member) && !member.symbol.isReferenced) { error(member.name, Diagnostics._0_is_declared_but_never_used, member.symbol.name); } } else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { - if (isPrivateNode(parameter) && !parameter.symbol.hasReference) { + if (isPrivateNode(parameter) && !parameter.symbol.isReferenced) { error(parameter.name, Diagnostics._0_is_declared_but_never_used, parameter.symbol.name); } } @@ -14583,7 +14583,7 @@ namespace ts { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { if (node.typeParameters) { for (const typeParameter of node.typeParameters) { - if (!typeParameter.symbol.hasReference) { + if (!typeParameter.symbol.isReferenced) { error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, typeParameter.symbol.name); } } @@ -14595,12 +14595,12 @@ namespace ts { return (node.flags & NodeFlags.Private) !== 0; } - function checkUnusedModuleLocals(node: ModuleDeclaration | SourceFile): void { + function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile): void { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { for (const key in node.locals) { if (hasProperty(node.locals, key)) { const local = node.locals[key]; - if (!local.hasReference && !local.exportSymbol) { + if (!local.isReferenced && !local.exportSymbol) { for (const declaration of local.declarations) { if (!isAmbientModule(declaration)) { error(declaration.name, Diagnostics._0_is_declared_but_never_used, local.name); @@ -14619,7 +14619,7 @@ namespace ts { } forEach(node.statements, checkSourceElement); if (node.locals) { - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } } @@ -15085,7 +15085,7 @@ namespace ts { if (node.condition) checkExpression(node.condition); if (node.incrementor) checkExpression(node.incrementor); checkSourceElement(node.statement); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } function checkForOfStatement(node: ForOfStatement): void { @@ -15127,7 +15127,7 @@ namespace ts { checkSourceElement(node.statement); if (node.locals) { - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } } @@ -15177,7 +15177,7 @@ namespace ts { checkSourceElement(node.statement); if (node.locals) { - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } } @@ -15771,7 +15771,7 @@ namespace ts { function checkClassExpressionDeferred(node: ClassExpression) { forEach(node.members, checkSourceElement); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } function checkClassDeclaration(node: ClassDeclaration) { @@ -15781,7 +15781,7 @@ namespace ts { checkClassLikeDeclaration(node); forEach(node.members, checkSourceElement); - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } function checkClassLikeDeclaration(node: ClassLikeDeclaration) { @@ -16489,7 +16489,7 @@ namespace ts { if (node.body) { checkSourceElement(node.body); if (!isGlobalScopeAugmentation(node)) { - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } } } @@ -17019,11 +17019,11 @@ namespace ts { checkDeferredNodes(); if (isExternalModule(node)) { - checkUnusedIdentifiersDeferred(node); + registerForUnusedIdentifiersCheck(node); } if (!node.isDeclarationFile) { - checkUnusedIdentifiersDeferredNodes(); + checkUnusedIdentifiers(); } deferredNodes = undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 56029fd316c..a3d7fd4823d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2128,7 +2128,7 @@ namespace ts { /* @internal */ parent?: Symbol; // Parent symbol /* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol /* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums - /* @internal */ hasReference?: boolean; // True if the symbol is referenced elsewhere + /* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere } /* @internal */ From b40512d8a21f5dd66df4b4c5a4940b68509effb9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 30 Jun 2016 01:00:53 -0700 Subject: [PATCH 27/34] Only mark symbols found in a local symbol table --- src/compiler/checker.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f42ca9ffe34..0bedc9f404a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -51,7 +51,7 @@ namespace ts { const compilerOptions = host.getCompilerOptions(); const languageVersion = compilerOptions.target || ScriptTarget.ES3; const modulekind = getEmitModuleKind(compilerOptions); - const noUnusedIdentifiers = compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters; + const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; const strictNullChecks = compilerOptions.strictNullChecks; @@ -849,6 +849,10 @@ namespace ts { location = location.parent; } + if (result && nameNotFoundMessage && noUnusedIdentifiers) { + result.isReferenced = true; + } + if (!result) { result = getSymbol(globals, name, meaning); } @@ -899,10 +903,6 @@ namespace ts { error(errorLocation, Diagnostics.Identifier_0_must_be_imported_from_a_module, name); } } - - if (result && noUnusedIdentifiers && !isInAmbientContext(location)) { - result.isReferenced = true; - } } return result; } From 0535d55a9775c83e5c70a30fae5192561546bb90 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 30 Jun 2016 06:38:18 -0700 Subject: [PATCH 28/34] Show "" if the name of a declaration is unavailable --- src/services/navigationBar.ts | 3 +-- .../navigationBarNamespaceImportWithNoName.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/navigationBarNamespaceImportWithNoName.ts diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index bfbaf5a6287..022c538e762 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -412,8 +412,7 @@ namespace ts.NavigationBar { case SyntaxKind.JSDocTypedefTag: return getJSDocTypedefTagName(node); default: - Debug.fail(); - return ""; + return ""; } } diff --git a/tests/cases/fourslash/navigationBarNamespaceImportWithNoName.ts b/tests/cases/fourslash/navigationBarNamespaceImportWithNoName.ts new file mode 100644 index 00000000000..732e2deb1dd --- /dev/null +++ b/tests/cases/fourslash/navigationBarNamespaceImportWithNoName.ts @@ -0,0 +1,13 @@ +////import *{} from 'foo'; +verify.navigationBar([ + { + "text": "\"navigationBarNamespaceImportWithNoName\"", + "kind": "module", + "childItems": [ + { + "text": "", + "kind": "alias" + } + ] + } +]); From 4195eb3670cfe784995828e97758d93a600838cd Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 29 Jun 2016 13:29:54 -0700 Subject: [PATCH 29/34] Parse `export default async function` as a declaration --- src/compiler/parser.ts | 10 +++++----- src/compiler/types.ts | 2 +- .../reference/exportDefaultAsyncFunction.js | 18 ++++++++++++++++++ .../exportDefaultAsyncFunction.symbols | 8 ++++++++ .../reference/exportDefaultAsyncFunction.types | 9 +++++++++ .../compiler/exportDefaultAsyncFunction.ts | 3 +++ 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/exportDefaultAsyncFunction.js create mode 100644 tests/baselines/reference/exportDefaultAsyncFunction.symbols create mode 100644 tests/baselines/reference/exportDefaultAsyncFunction.types create mode 100644 tests/cases/compiler/exportDefaultAsyncFunction.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9f02e8c2926..d720cd0648f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1155,12 +1155,12 @@ namespace ts { if (token === SyntaxKind.ExportKeyword) { nextToken(); if (token === SyntaxKind.DefaultKeyword) { - return lookAhead(nextTokenIsClassOrFunction); + return lookAhead(nextTokenIsClassOrFunctionOrAsync); } return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.AsKeyword && token !== SyntaxKind.OpenBraceToken && canFollowModifier(); } if (token === SyntaxKind.DefaultKeyword) { - return nextTokenIsClassOrFunction(); + return nextTokenIsClassOrFunctionOrAsync(); } if (token === SyntaxKind.StaticKeyword) { nextToken(); @@ -1182,9 +1182,9 @@ namespace ts { || isLiteralPropertyName(); } - function nextTokenIsClassOrFunction(): boolean { + function nextTokenIsClassOrFunctionOrAsync(): boolean { nextToken(); - return token === SyntaxKind.ClassKeyword || token === SyntaxKind.FunctionKeyword; + return token === SyntaxKind.ClassKeyword || token === SyntaxKind.FunctionKeyword || token === SyntaxKind.AsyncKeyword; } // True if positioned at the start of a list element @@ -5070,7 +5070,7 @@ namespace ts { * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ function parseModifiers(permitInvalidConstAsModifier?: boolean): ModifiersArray { - let flags = 0; + let flags: NodeFlags = 0; let modifiers: ModifiersArray; while (true) { const modifierStart = scanner.getStartPos(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 56029fd316c..0110fda4e41 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -469,7 +469,7 @@ namespace ts { } export interface ModifiersArray extends NodeArray { - flags: number; + flags: NodeFlags; } // @kind(SyntaxKind.AbstractKeyword) diff --git a/tests/baselines/reference/exportDefaultAsyncFunction.js b/tests/baselines/reference/exportDefaultAsyncFunction.js new file mode 100644 index 00000000000..a06b41b5e73 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAsyncFunction.js @@ -0,0 +1,18 @@ +//// [exportDefaultAsyncFunction.ts] +export default async function foo(): Promise {} +foo(); + + +//// [exportDefaultAsyncFunction.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +export default function foo() { + return __awaiter(this, void 0, void 0, function* () { }); +} +foo(); diff --git a/tests/baselines/reference/exportDefaultAsyncFunction.symbols b/tests/baselines/reference/exportDefaultAsyncFunction.symbols new file mode 100644 index 00000000000..47178519558 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAsyncFunction.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/exportDefaultAsyncFunction.ts === +export default async function foo(): Promise {} +>foo : Symbol(foo, Decl(exportDefaultAsyncFunction.ts, 0, 0)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) + +foo(); +>foo : Symbol(foo, Decl(exportDefaultAsyncFunction.ts, 0, 0)) + diff --git a/tests/baselines/reference/exportDefaultAsyncFunction.types b/tests/baselines/reference/exportDefaultAsyncFunction.types new file mode 100644 index 00000000000..7258c6fcf0c --- /dev/null +++ b/tests/baselines/reference/exportDefaultAsyncFunction.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/exportDefaultAsyncFunction.ts === +export default async function foo(): Promise {} +>foo : () => Promise +>Promise : Promise + +foo(); +>foo() : Promise +>foo : () => Promise + diff --git a/tests/cases/compiler/exportDefaultAsyncFunction.ts b/tests/cases/compiler/exportDefaultAsyncFunction.ts new file mode 100644 index 00000000000..c05296711ec --- /dev/null +++ b/tests/cases/compiler/exportDefaultAsyncFunction.ts @@ -0,0 +1,3 @@ +// @target: es6 +export default async function foo(): Promise {} +foo(); From 1fa69caf13ddb9474bb4231d02268701ddbbf67f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 30 Jun 2016 10:38:59 -0700 Subject: [PATCH 30/34] handel private properties correctelly --- src/compiler/checker.ts | 9 +- src/compiler/types.ts | 2 + .../reference/unusedPrivateMembers.js | 114 +++++++++++++++++ .../reference/unusedPrivateMembers.symbols | 113 ++++++++++++++++ .../reference/unusedPrivateMembers.types | 121 ++++++++++++++++++ tests/cases/compiler/unusedPrivateMembers.ts | 51 ++++++++ 6 files changed, 408 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/unusedPrivateMembers.js create mode 100644 tests/baselines/reference/unusedPrivateMembers.symbols create mode 100644 tests/baselines/reference/unusedPrivateMembers.types create mode 100644 tests/cases/compiler/unusedPrivateMembers.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0bedc9f404a..33ff04697f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10241,8 +10241,13 @@ namespace ts { return unknownType; } - if (noUnusedIdentifiers && !isInAmbientContext(node)) { - prop.isReferenced = true; + if (noUnusedIdentifiers && (prop.flags & SymbolFlags.ClassMember)) { + if (prop.flags & SymbolFlags.Instantiated) { + getSymbolLinks(prop).target.isReferenced = true; + } + else { + prop.isReferenced = true; + } } getNodeLinks(node).resolvedSymbol = prop; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a3d7fd4823d..7d7e92f27c3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2107,6 +2107,8 @@ namespace ts { PropertyOrAccessor = Property | Accessor, Export = ExportNamespace | ExportType | ExportValue, + ClassMember = Method | Accessor | Property, + /* @internal */ // The set of things we consider semantically classifiable. Used to speed up the LS during // classification. diff --git a/tests/baselines/reference/unusedPrivateMembers.js b/tests/baselines/reference/unusedPrivateMembers.js new file mode 100644 index 00000000000..cdb540349c3 --- /dev/null +++ b/tests/baselines/reference/unusedPrivateMembers.js @@ -0,0 +1,114 @@ +//// [unusedPrivateMembers.ts] + +class Test1 { + private initializeInternal() { + } + + public test() { + var x = new Test1(); + x.initializeInternal(); + } +} + +class Test2 { + private p = 0; + public test() { + var x = new Test2(); + x.p; + } +} + +class Test3 { + private get x () { + return 0; + } + + public test() { + var x = new Test3(); + x.x; + } +} + +class Test4 { + private set x(v) { + v; + } + + public test() { + var x = new Test4(); + x.x; + } +} + +class Test5 { + private p: T; + public test() { + var x = new Test5(); + x.p; + } +} + + +//// [unusedPrivateMembers.js] +var Test1 = (function () { + function Test1() { + } + Test1.prototype.initializeInternal = function () { + }; + Test1.prototype.test = function () { + var x = new Test1(); + x.initializeInternal(); + }; + return Test1; +}()); +var Test2 = (function () { + function Test2() { + this.p = 0; + } + Test2.prototype.test = function () { + var x = new Test2(); + x.p; + }; + return Test2; +}()); +var Test3 = (function () { + function Test3() { + } + Object.defineProperty(Test3.prototype, "x", { + get: function () { + return 0; + }, + enumerable: true, + configurable: true + }); + Test3.prototype.test = function () { + var x = new Test3(); + x.x; + }; + return Test3; +}()); +var Test4 = (function () { + function Test4() { + } + Object.defineProperty(Test4.prototype, "x", { + set: function (v) { + v; + }, + enumerable: true, + configurable: true + }); + Test4.prototype.test = function () { + var x = new Test4(); + x.x; + }; + return Test4; +}()); +var Test5 = (function () { + function Test5() { + } + Test5.prototype.test = function () { + var x = new Test5(); + x.p; + }; + return Test5; +}()); diff --git a/tests/baselines/reference/unusedPrivateMembers.symbols b/tests/baselines/reference/unusedPrivateMembers.symbols new file mode 100644 index 00000000000..0d4426a594a --- /dev/null +++ b/tests/baselines/reference/unusedPrivateMembers.symbols @@ -0,0 +1,113 @@ +=== tests/cases/compiler/unusedPrivateMembers.ts === + +class Test1 { +>Test1 : Symbol(Test1, Decl(unusedPrivateMembers.ts, 0, 0)) + + private initializeInternal() { +>initializeInternal : Symbol(Test1.initializeInternal, Decl(unusedPrivateMembers.ts, 1, 13)) + } + + public test() { +>test : Symbol(Test1.test, Decl(unusedPrivateMembers.ts, 3, 5)) + + var x = new Test1(); +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 6, 11)) +>Test1 : Symbol(Test1, Decl(unusedPrivateMembers.ts, 0, 0)) + + x.initializeInternal(); +>x.initializeInternal : Symbol(Test1.initializeInternal, Decl(unusedPrivateMembers.ts, 1, 13)) +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 6, 11)) +>initializeInternal : Symbol(Test1.initializeInternal, Decl(unusedPrivateMembers.ts, 1, 13)) + } +} + +class Test2 { +>Test2 : Symbol(Test2, Decl(unusedPrivateMembers.ts, 9, 1)) + + private p = 0; +>p : Symbol(Test2.p, Decl(unusedPrivateMembers.ts, 11, 13)) + + public test() { +>test : Symbol(Test2.test, Decl(unusedPrivateMembers.ts, 12, 18)) + + var x = new Test2(); +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 14, 11)) +>Test2 : Symbol(Test2, Decl(unusedPrivateMembers.ts, 9, 1)) + + x.p; +>x.p : Symbol(Test2.p, Decl(unusedPrivateMembers.ts, 11, 13)) +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 14, 11)) +>p : Symbol(Test2.p, Decl(unusedPrivateMembers.ts, 11, 13)) + } +} + +class Test3 { +>Test3 : Symbol(Test3, Decl(unusedPrivateMembers.ts, 17, 1)) + + private get x () { +>x : Symbol(Test3.x, Decl(unusedPrivateMembers.ts, 19, 13)) + + return 0; + } + + public test() { +>test : Symbol(Test3.test, Decl(unusedPrivateMembers.ts, 22, 5)) + + var x = new Test3(); +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 25, 11)) +>Test3 : Symbol(Test3, Decl(unusedPrivateMembers.ts, 17, 1)) + + x.x; +>x.x : Symbol(Test3.x, Decl(unusedPrivateMembers.ts, 19, 13)) +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 25, 11)) +>x : Symbol(Test3.x, Decl(unusedPrivateMembers.ts, 19, 13)) + } +} + +class Test4 { +>Test4 : Symbol(Test4, Decl(unusedPrivateMembers.ts, 28, 1)) + + private set x(v) { +>x : Symbol(Test4.x, Decl(unusedPrivateMembers.ts, 30, 13)) +>v : Symbol(v, Decl(unusedPrivateMembers.ts, 31, 18)) + + v; +>v : Symbol(v, Decl(unusedPrivateMembers.ts, 31, 18)) + } + + public test() { +>test : Symbol(Test4.test, Decl(unusedPrivateMembers.ts, 33, 5)) + + var x = new Test4(); +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 36, 11)) +>Test4 : Symbol(Test4, Decl(unusedPrivateMembers.ts, 28, 1)) + + x.x; +>x.x : Symbol(Test4.x, Decl(unusedPrivateMembers.ts, 30, 13)) +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 36, 11)) +>x : Symbol(Test4.x, Decl(unusedPrivateMembers.ts, 30, 13)) + } +} + +class Test5 { +>Test5 : Symbol(Test5, Decl(unusedPrivateMembers.ts, 39, 1)) +>T : Symbol(T, Decl(unusedPrivateMembers.ts, 41, 12)) + + private p: T; +>p : Symbol(Test5.p, Decl(unusedPrivateMembers.ts, 41, 16)) +>T : Symbol(T, Decl(unusedPrivateMembers.ts, 41, 12)) + + public test() { +>test : Symbol(Test5.test, Decl(unusedPrivateMembers.ts, 42, 17)) + + var x = new Test5(); +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 44, 11)) +>Test5 : Symbol(Test5, Decl(unusedPrivateMembers.ts, 39, 1)) + + x.p; +>x.p : Symbol(Test5.p, Decl(unusedPrivateMembers.ts, 41, 16)) +>x : Symbol(x, Decl(unusedPrivateMembers.ts, 44, 11)) +>p : Symbol(Test5.p, Decl(unusedPrivateMembers.ts, 41, 16)) + } +} + diff --git a/tests/baselines/reference/unusedPrivateMembers.types b/tests/baselines/reference/unusedPrivateMembers.types new file mode 100644 index 00000000000..1d303068f24 --- /dev/null +++ b/tests/baselines/reference/unusedPrivateMembers.types @@ -0,0 +1,121 @@ +=== tests/cases/compiler/unusedPrivateMembers.ts === + +class Test1 { +>Test1 : Test1 + + private initializeInternal() { +>initializeInternal : () => void + } + + public test() { +>test : () => void + + var x = new Test1(); +>x : Test1 +>new Test1() : Test1 +>Test1 : typeof Test1 + + x.initializeInternal(); +>x.initializeInternal() : void +>x.initializeInternal : () => void +>x : Test1 +>initializeInternal : () => void + } +} + +class Test2 { +>Test2 : Test2 + + private p = 0; +>p : number +>0 : number + + public test() { +>test : () => void + + var x = new Test2(); +>x : Test2 +>new Test2() : Test2 +>Test2 : typeof Test2 + + x.p; +>x.p : number +>x : Test2 +>p : number + } +} + +class Test3 { +>Test3 : Test3 + + private get x () { +>x : number + + return 0; +>0 : number + } + + public test() { +>test : () => void + + var x = new Test3(); +>x : Test3 +>new Test3() : Test3 +>Test3 : typeof Test3 + + x.x; +>x.x : number +>x : Test3 +>x : number + } +} + +class Test4 { +>Test4 : Test4 + + private set x(v) { +>x : any +>v : any + + v; +>v : any + } + + public test() { +>test : () => void + + var x = new Test4(); +>x : Test4 +>new Test4() : Test4 +>Test4 : typeof Test4 + + x.x; +>x.x : any +>x : Test4 +>x : any + } +} + +class Test5 { +>Test5 : Test5 +>T : T + + private p: T; +>p : T +>T : T + + public test() { +>test : () => void + + var x = new Test5(); +>x : Test5 +>new Test5() : Test5 +>Test5 : typeof Test5 + + x.p; +>x.p : number +>x : Test5 +>p : number + } +} + diff --git a/tests/cases/compiler/unusedPrivateMembers.ts b/tests/cases/compiler/unusedPrivateMembers.ts new file mode 100644 index 00000000000..ab4e5ba9bca --- /dev/null +++ b/tests/cases/compiler/unusedPrivateMembers.ts @@ -0,0 +1,51 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true +//@target:ES5 + +class Test1 { + private initializeInternal() { + } + + public test() { + var x = new Test1(); + x.initializeInternal(); + } +} + +class Test2 { + private p = 0; + public test() { + var x = new Test2(); + x.p; + } +} + +class Test3 { + private get x () { + return 0; + } + + public test() { + var x = new Test3(); + x.x; + } +} + +class Test4 { + private set x(v) { + v; + } + + public test() { + var x = new Test4(); + x.x; + } +} + +class Test5 { + private p: T; + public test() { + var x = new Test5(); + x.p; + } +} From b8486906264bb7228c363a3b2e8be36ab9dbdef4 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 30 Jun 2016 14:26:07 -0700 Subject: [PATCH 31/34] Port 9426 to release 2.0 --- src/services/formatting/smartIndenter.ts | 2 +- .../formattingIllegalImportClause.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/formattingIllegalImportClause.ts diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 120a5be6e4e..4eebf4b9431 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -497,7 +497,7 @@ namespace ts.formatting { return childKind !== SyntaxKind.NamedExports; case SyntaxKind.ImportDeclaration: return childKind !== SyntaxKind.ImportClause || - (child).namedBindings.kind !== SyntaxKind.NamedImports; + ((child).namedBindings && (child).namedBindings.kind !== SyntaxKind.NamedImports); case SyntaxKind.JsxElement: return childKind !== SyntaxKind.JsxClosingElement; } diff --git a/tests/cases/fourslash/formattingIllegalImportClause.ts b/tests/cases/fourslash/formattingIllegalImportClause.ts new file mode 100644 index 00000000000..9e97087c000 --- /dev/null +++ b/tests/cases/fourslash/formattingIllegalImportClause.ts @@ -0,0 +1,26 @@ +/// + +//// var expect = require('expect.js'); +//// import React from 'react'/*1*/; +//// import { mount } from 'enzyme'; +//// require('../setup'); +//// var Amount = require('../../src/js/components/amount'); + +//// describe('', () => { +//// var history +//// beforeEach(() => { +//// history = createMemoryHistory(); +//// sinon.spy(history, 'pushState'); +//// }); + +//// afterEach(() => { +//// }) + +//// it('redirects to order summary', () => { + +//// }); +//// }); + +format.document(); +goTo.marker("1"); +verify.currentLineContentIs("import React from 'react';") \ No newline at end of file From 54b4bef8c8eea59c56c0d2a1b5ffa19cd03a3316 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 30 Jun 2016 15:18:17 -0700 Subject: [PATCH 32/34] Handel Swtich statements check for locals on for statments only mark private properties --- src/compiler/checker.ts | 25 +++++++----- .../reference/unusedSwitchStatment.errors.txt | 31 +++++++++++++++ .../reference/unusedSwitchStatment.js | 38 +++++++++++++++++++ tests/cases/compiler/unusedSwitchStatment.ts | 21 ++++++++++ 4 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/unusedSwitchStatment.errors.txt create mode 100644 tests/baselines/reference/unusedSwitchStatment.js create mode 100644 tests/cases/compiler/unusedSwitchStatment.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 33ff04697f9..be94a7ce4e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10241,9 +10241,12 @@ namespace ts { return unknownType; } - if (noUnusedIdentifiers && (prop.flags & SymbolFlags.ClassMember)) { + if (noUnusedIdentifiers && + (prop.flags & SymbolFlags.ClassMember) && + prop.valueDeclaration && (prop.valueDeclaration.flags & NodeFlags.Private)) { if (prop.flags & SymbolFlags.Instantiated) { getSymbolLinks(prop).target.isReferenced = true; + } else { prop.isReferenced = true; @@ -14513,10 +14516,11 @@ namespace ts { checkUnusedTypeParameters(node); break; case SyntaxKind.Block: + case SyntaxKind.CaseBlock: case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: case SyntaxKind.ForOfStatement: - checkUnusedLocalsAndParameters(node); + checkUnusedLocalsAndParameters(node); break; case SyntaxKind.Constructor: case SyntaxKind.FunctionExpression: @@ -14543,7 +14547,7 @@ namespace ts { } } - function checkUnusedLocalsAndParameters(node: FunctionLikeDeclaration | ForStatement | Block): void { + function checkUnusedLocalsAndParameters(node: Node): void { if (node.parent.kind !== SyntaxKind.InterfaceDeclaration && noUnusedIdentifiers && !isInAmbientContext(node)) { for (const key in node.locals) { if (hasProperty(node.locals, key)) { @@ -14568,13 +14572,13 @@ namespace ts { if (node.members) { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { - if (isPrivateNode(member) && !member.symbol.isReferenced) { + if (!member.symbol.isReferenced && member.flags & NodeFlags.Private) { error(member.name, Diagnostics._0_is_declared_but_never_used, member.symbol.name); } } else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { - if (isPrivateNode(parameter) && !parameter.symbol.isReferenced) { + if (!parameter.symbol.isReferenced && parameter.flags & NodeFlags.Private) { error(parameter.name, Diagnostics._0_is_declared_but_never_used, parameter.symbol.name); } } @@ -14596,10 +14600,6 @@ namespace ts { } } - function isPrivateNode(node: Node): boolean { - return (node.flags & NodeFlags.Private) !== 0; - } - function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile): void { if (compilerOptions.noUnusedLocals && !isInAmbientContext(node)) { for (const key in node.locals) { @@ -15090,7 +15090,9 @@ namespace ts { if (node.condition) checkExpression(node.condition); if (node.incrementor) checkExpression(node.incrementor); checkSourceElement(node.statement); - registerForUnusedIdentifiersCheck(node); + if (node.locals) { + registerForUnusedIdentifiersCheck(node); + } } function checkForOfStatement(node: ForOfStatement): void { @@ -15556,6 +15558,9 @@ namespace ts { } forEach(clause.statements, checkSourceElement); }); + if (node.caseBlock.locals) { + registerForUnusedIdentifiersCheck(node.caseBlock); + } } function checkLabeledStatement(node: LabeledStatement) { diff --git a/tests/baselines/reference/unusedSwitchStatment.errors.txt b/tests/baselines/reference/unusedSwitchStatment.errors.txt new file mode 100644 index 00000000000..58359eed90d --- /dev/null +++ b/tests/baselines/reference/unusedSwitchStatment.errors.txt @@ -0,0 +1,31 @@ +tests/cases/compiler/unusedSwitchStatment.ts(4,13): error TS6133: 'x' is declared but never used. +tests/cases/compiler/unusedSwitchStatment.ts(7,15): error TS6133: 'c' is declared but never used. +tests/cases/compiler/unusedSwitchStatment.ts(10,13): error TS6133: 'z' is declared but never used. + + +==== tests/cases/compiler/unusedSwitchStatment.ts (3 errors) ==== + + switch (1) { + case 0: + let x; + ~ +!!! error TS6133: 'x' is declared but never used. + break; + case 1: + const c = 1; + ~ +!!! error TS6133: 'c' is declared but never used. + break; + default: + let z = 2; + ~ +!!! error TS6133: 'z' is declared but never used. + } + + + switch (2) { + case 0: + let x; + case 1: + x++; + } \ No newline at end of file diff --git a/tests/baselines/reference/unusedSwitchStatment.js b/tests/baselines/reference/unusedSwitchStatment.js new file mode 100644 index 00000000000..2fd0d1fc49e --- /dev/null +++ b/tests/baselines/reference/unusedSwitchStatment.js @@ -0,0 +1,38 @@ +//// [unusedSwitchStatment.ts] + +switch (1) { + case 0: + let x; + break; + case 1: + const c = 1; + break; + default: + let z = 2; +} + + +switch (2) { + case 0: + let x; + case 1: + x++; +} + +//// [unusedSwitchStatment.js] +switch (1) { + case 0: + var x = void 0; + break; + case 1: + var c = 1; + break; + default: + var z = 2; +} +switch (2) { + case 0: + var x = void 0; + case 1: + x++; +} diff --git a/tests/cases/compiler/unusedSwitchStatment.ts b/tests/cases/compiler/unusedSwitchStatment.ts new file mode 100644 index 00000000000..53f93b913aa --- /dev/null +++ b/tests/cases/compiler/unusedSwitchStatment.ts @@ -0,0 +1,21 @@ +//@noUnusedLocals:true +//@noUnusedParameters:true + +switch (1) { + case 0: + let x; + break; + case 1: + const c = 1; + break; + default: + let z = 2; +} + + +switch (2) { + case 0: + let x; + case 1: + x++; +} \ No newline at end of file From 5e4f13f342a75ec8f7cf65cb669bec9d6e6c5581 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Thu, 30 Jun 2016 16:36:39 -0700 Subject: [PATCH 33/34] Removed one error to avoid full path issues --- .../amd/maxDepthIncreased/root.js | 1 - .../amd/nodeModulesMaxDepthIncreased.errors.txt | 6 +----- .../node/maxDepthIncreased/root.js | 1 - .../node/nodeModulesMaxDepthIncreased.errors.txt | 6 +----- .../projects/NodeModulesSearch/maxDepthIncreased/root.ts | 1 - 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js index 0024891fbe3..9ef3915c851 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/maxDepthIncreased/root.js @@ -3,6 +3,5 @@ define(["require", "exports", "m1", "m4"], function (require, exports, m1, m4) { m1.f1("test"); m1.f2.a = 10; m1.f2.person.age = "10"; // Should error if loaded the .js files correctly - var r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info var r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file }); diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt index 473d69bc526..f511000d5ac 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/amd/nodeModulesMaxDepthIncreased.errors.txt @@ -1,5 +1,4 @@ maxDepthIncreased/root.ts(7,1): error TS2322: Type 'string' is not assignable to type 'number'. -maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. ==== index.js (0 errors) ==== @@ -32,7 +31,7 @@ maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on ==== entry.d.ts (0 errors) ==== export declare var foo: number; -==== maxDepthIncreased/root.ts (2 errors) ==== +==== maxDepthIncreased/root.ts (1 errors) ==== import * as m1 from "m1"; import * as m4 from "m4"; @@ -42,9 +41,6 @@ maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on m1.f2.person.age = "10"; // Should error if loaded the .js files correctly ~~~~~~~~~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type 'number'. - let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info - ~~~~ -!!! error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file \ No newline at end of file diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js index ba6d7e96241..f6783cda79b 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/maxDepthIncreased/root.js @@ -4,5 +4,4 @@ var m4 = require("m4"); m1.f1("test"); m1.f2.a = 10; m1.f2.person.age = "10"; // Should error if loaded the .js files correctly -var r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info var r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file diff --git a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt index 473d69bc526..f511000d5ac 100644 --- a/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt +++ b/tests/baselines/reference/project/nodeModulesMaxDepthIncreased/node/nodeModulesMaxDepthIncreased.errors.txt @@ -1,5 +1,4 @@ maxDepthIncreased/root.ts(7,1): error TS2322: Type 'string' is not assignable to type 'number'. -maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. ==== index.js (0 errors) ==== @@ -32,7 +31,7 @@ maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on ==== entry.d.ts (0 errors) ==== export declare var foo: number; -==== maxDepthIncreased/root.ts (2 errors) ==== +==== maxDepthIncreased/root.ts (1 errors) ==== import * as m1 from "m1"; import * as m4 from "m4"; @@ -42,9 +41,6 @@ maxDepthIncreased/root.ts(8,13): error TS2339: Property 'test' does not exist on m1.f2.person.age = "10"; // Should error if loaded the .js files correctly ~~~~~~~~~~~~~~~~ !!! error TS2322: Type 'string' is not assignable to type 'number'. - let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info - ~~~~ -!!! error TS2339: Property 'test' does not exist on type 'typeof "C:/src/TypeScript/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/node_modules/@...'. let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file \ No newline at end of file diff --git a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts index 5d9f331b249..2b80564ae26 100644 --- a/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts +++ b/tests/cases/projects/NodeModulesSearch/maxDepthIncreased/root.ts @@ -5,6 +5,5 @@ m1.f1("test"); m1.f2.a = 10; m1.f2.person.age = "10"; // Should error if loaded the .js files correctly -let r1 = m4.test.charAt(2); // Should error if correctly not using the .js file but using @types info let r2 = 3 + m4.foo; // Should be OK if correctly using the @types .d.ts file From d64ab2f9ad798c55e6121fb75ae7b1fa76d71a79 Mon Sep 17 00:00:00 2001 From: Doug Ilijev Date: Thu, 30 Jun 2016 18:33:32 -0700 Subject: [PATCH 34/34] Fix incorrectly-saved quote symbols in ThirdPartyNoticeText.txt --- ThirdPartyNoticeText.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThirdPartyNoticeText.txt b/ThirdPartyNoticeText.txt index 6fbb7e4a0ce..a9ffbddbd89 100644 --- a/ThirdPartyNoticeText.txt +++ b/ThirdPartyNoticeText.txt @@ -21,7 +21,7 @@ Third Party Code Components -------------------------------------------- ------------------- DefinitelyTyped -------------------- -This file is based on or incorporates material from the projects listed below (collectively ?Third Party Code?). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft, not the third party, licenses the Third Party Code to you under the terms set forth in the EULA for the Microsoft Product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. +This file is based on or incorporates material from the projects listed below (collectively "Third Party Code"). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft, not the third party, licenses the Third Party Code to you under the terms set forth in the EULA for the Microsoft Product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. DefinitelyTyped This project is licensed under the MIT license. Copyrights are respective of each contributor listed at the beginning of each definition file.