From 0f83fc130e2e4376cc64c7af48e8401c7eb2c68b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 22 Aug 2016 23:10:05 -0700 Subject: [PATCH 01/17] Added tests. --- .../es6/templates/taggedTemplateWithConstructableTag01.ts | 3 +++ .../es6/templates/taggedTemplateWithConstructableTag02.ts | 6 ++++++ 2 files changed, 9 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts b/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts new file mode 100644 index 00000000000..996f5b80298 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts @@ -0,0 +1,3 @@ +class CtorTag { } + +CtorTag `Hello world!`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts b/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts new file mode 100644 index 00000000000..7c6f009bf23 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts @@ -0,0 +1,6 @@ +interface I { + new (...args: any[]): string; + new (): number; +} +var tag: I; +tag `Hello world!`; \ No newline at end of file From e7798c002ef4bb86d29bf7262aadb03b398aadba Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 22 Aug 2016 23:10:16 -0700 Subject: [PATCH 02/17] Accepted baselines. --- .../taggedTemplateWithConstructableTag01.js | 13 +++++++++++++ ...aggedTemplateWithConstructableTag01.symbols | 7 +++++++ .../taggedTemplateWithConstructableTag01.types | 9 +++++++++ .../taggedTemplateWithConstructableTag02.js | 12 ++++++++++++ ...aggedTemplateWithConstructableTag02.symbols | 16 ++++++++++++++++ .../taggedTemplateWithConstructableTag02.types | 18 ++++++++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag01.js create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag01.symbols create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag01.types create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag02.js create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag02.symbols create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag02.types diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag01.js b/tests/baselines/reference/taggedTemplateWithConstructableTag01.js new file mode 100644 index 00000000000..dbcb70edf00 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag01.js @@ -0,0 +1,13 @@ +//// [taggedTemplateWithConstructableTag01.ts] +class CtorTag { } + +CtorTag `Hello world!`; + +//// [taggedTemplateWithConstructableTag01.js] +var CtorTag = (function () { + function CtorTag() { + } + return CtorTag; +}()); +(_a = ["Hello world!"], _a.raw = ["Hello world!"], CtorTag(_a)); +var _a; diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag01.symbols b/tests/baselines/reference/taggedTemplateWithConstructableTag01.symbols new file mode 100644 index 00000000000..340d5887808 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag01.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts === +class CtorTag { } +>CtorTag : Symbol(CtorTag, Decl(taggedTemplateWithConstructableTag01.ts, 0, 0)) + +CtorTag `Hello world!`; +>CtorTag : Symbol(CtorTag, Decl(taggedTemplateWithConstructableTag01.ts, 0, 0)) + diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag01.types b/tests/baselines/reference/taggedTemplateWithConstructableTag01.types new file mode 100644 index 00000000000..05e5aba7cde --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag01.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts === +class CtorTag { } +>CtorTag : CtorTag + +CtorTag `Hello world!`; +>CtorTag `Hello world!` : any +>CtorTag : typeof CtorTag +>`Hello world!` : string + diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag02.js b/tests/baselines/reference/taggedTemplateWithConstructableTag02.js new file mode 100644 index 00000000000..6c38d508bd2 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag02.js @@ -0,0 +1,12 @@ +//// [taggedTemplateWithConstructableTag02.ts] +interface I { + new (...args: any[]): string; + new (): number; +} +var tag: I; +tag `Hello world!`; + +//// [taggedTemplateWithConstructableTag02.js] +var tag; +(_a = ["Hello world!"], _a.raw = ["Hello world!"], tag(_a)); +var _a; diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag02.symbols b/tests/baselines/reference/taggedTemplateWithConstructableTag02.symbols new file mode 100644 index 00000000000..2b2ccdbcbcf --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag02.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts === +interface I { +>I : Symbol(I, Decl(taggedTemplateWithConstructableTag02.ts, 0, 0)) + + new (...args: any[]): string; +>args : Symbol(args, Decl(taggedTemplateWithConstructableTag02.ts, 1, 9)) + + new (): number; +} +var tag: I; +>tag : Symbol(tag, Decl(taggedTemplateWithConstructableTag02.ts, 4, 3)) +>I : Symbol(I, Decl(taggedTemplateWithConstructableTag02.ts, 0, 0)) + +tag `Hello world!`; +>tag : Symbol(tag, Decl(taggedTemplateWithConstructableTag02.ts, 4, 3)) + diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag02.types b/tests/baselines/reference/taggedTemplateWithConstructableTag02.types new file mode 100644 index 00000000000..1b96c3324dd --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag02.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts === +interface I { +>I : I + + new (...args: any[]): string; +>args : any[] + + new (): number; +} +var tag: I; +>tag : I +>I : I + +tag `Hello world!`; +>tag `Hello world!` : any +>tag : I +>`Hello world!` : string + From 3292631b421fd85a870e65aaf82fab8aabf27dfe Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 22 Aug 2016 23:24:13 -0700 Subject: [PATCH 03/17] Added test for untyped tag. --- .../conformance/es6/templates/taggedTemplateUntypedTagCall01.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts diff --git a/tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts b/tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts new file mode 100644 index 00000000000..b77e04b3095 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts @@ -0,0 +1,2 @@ +var tag: Function; +tag `Hello world!`; \ No newline at end of file From 310e9c3a5110fb07bd987f7fcce1b87d7d591180 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 22 Aug 2016 23:25:37 -0700 Subject: [PATCH 04/17] Accepted baselines. --- .../reference/taggedTemplateUntypedTagCall01.js | 8 ++++++++ .../reference/taggedTemplateUntypedTagCall01.symbols | 8 ++++++++ .../reference/taggedTemplateUntypedTagCall01.types | 10 ++++++++++ 3 files changed, 26 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplateUntypedTagCall01.js create mode 100644 tests/baselines/reference/taggedTemplateUntypedTagCall01.symbols create mode 100644 tests/baselines/reference/taggedTemplateUntypedTagCall01.types diff --git a/tests/baselines/reference/taggedTemplateUntypedTagCall01.js b/tests/baselines/reference/taggedTemplateUntypedTagCall01.js new file mode 100644 index 00000000000..e0d16eec39d --- /dev/null +++ b/tests/baselines/reference/taggedTemplateUntypedTagCall01.js @@ -0,0 +1,8 @@ +//// [taggedTemplateUntypedTagCall01.ts] +var tag: Function; +tag `Hello world!`; + +//// [taggedTemplateUntypedTagCall01.js] +var tag; +(_a = ["Hello world!"], _a.raw = ["Hello world!"], tag(_a)); +var _a; diff --git a/tests/baselines/reference/taggedTemplateUntypedTagCall01.symbols b/tests/baselines/reference/taggedTemplateUntypedTagCall01.symbols new file mode 100644 index 00000000000..07af0a996e5 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateUntypedTagCall01.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts === +var tag: Function; +>tag : Symbol(tag, Decl(taggedTemplateUntypedTagCall01.ts, 0, 3)) +>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +tag `Hello world!`; +>tag : Symbol(tag, Decl(taggedTemplateUntypedTagCall01.ts, 0, 3)) + diff --git a/tests/baselines/reference/taggedTemplateUntypedTagCall01.types b/tests/baselines/reference/taggedTemplateUntypedTagCall01.types new file mode 100644 index 00000000000..3949869550c --- /dev/null +++ b/tests/baselines/reference/taggedTemplateUntypedTagCall01.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateUntypedTagCall01.ts === +var tag: Function; +>tag : Function +>Function : Function + +tag `Hello world!`; +>tag `Hello world!` : any +>tag : Function +>`Hello world!` : string + From c21d16a3bbb58b9beac271b1735fa782243d447a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 23 Aug 2016 11:14:05 -0700 Subject: [PATCH 05/17] Added test for decorators. --- .../decorators/class/constructableDecoratorOnClass01.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts diff --git a/tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts b/tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts new file mode 100644 index 00000000000..a9f9fa1699d --- /dev/null +++ b/tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts @@ -0,0 +1,8 @@ +// @experimentalDecorators: true + +class CtorDtor {} + +@CtorDtor +class C { + +} From d6ec5f29796ff094267df0e11b3b17bc6b95a28a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 23 Aug 2016 11:14:33 -0700 Subject: [PATCH 06/17] Accepted baselines. --- .../constructableDecoratorOnClass01.js | 30 +++++++++++++++++++ .../constructableDecoratorOnClass01.symbols | 13 ++++++++ .../constructableDecoratorOnClass01.types | 13 ++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/baselines/reference/constructableDecoratorOnClass01.js create mode 100644 tests/baselines/reference/constructableDecoratorOnClass01.symbols create mode 100644 tests/baselines/reference/constructableDecoratorOnClass01.types diff --git a/tests/baselines/reference/constructableDecoratorOnClass01.js b/tests/baselines/reference/constructableDecoratorOnClass01.js new file mode 100644 index 00000000000..26c5bf4a1c4 --- /dev/null +++ b/tests/baselines/reference/constructableDecoratorOnClass01.js @@ -0,0 +1,30 @@ +//// [constructableDecoratorOnClass01.ts] + +class CtorDtor {} + +@CtorDtor +class C { + +} + + +//// [constructableDecoratorOnClass01.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var CtorDtor = (function () { + function CtorDtor() { + } + return CtorDtor; +}()); +var C = (function () { + function C() { + } + C = __decorate([ + CtorDtor + ], C); + return C; +}()); diff --git a/tests/baselines/reference/constructableDecoratorOnClass01.symbols b/tests/baselines/reference/constructableDecoratorOnClass01.symbols new file mode 100644 index 00000000000..46de420b826 --- /dev/null +++ b/tests/baselines/reference/constructableDecoratorOnClass01.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts === + +class CtorDtor {} +>CtorDtor : Symbol(CtorDtor, Decl(constructableDecoratorOnClass01.ts, 0, 0)) + +@CtorDtor +>CtorDtor : Symbol(CtorDtor, Decl(constructableDecoratorOnClass01.ts, 0, 0)) + +class C { +>C : Symbol(C, Decl(constructableDecoratorOnClass01.ts, 1, 17)) + +} + diff --git a/tests/baselines/reference/constructableDecoratorOnClass01.types b/tests/baselines/reference/constructableDecoratorOnClass01.types new file mode 100644 index 00000000000..d66778a27e6 --- /dev/null +++ b/tests/baselines/reference/constructableDecoratorOnClass01.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts === + +class CtorDtor {} +>CtorDtor : CtorDtor + +@CtorDtor +>CtorDtor : typeof CtorDtor + +class C { +>C : C + +} + From 7ecbfb21481fd81464404802bd7a5d713cdf8a09 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 23 Aug 2016 11:30:44 -0700 Subject: [PATCH 07/17] Unify untyped call checking between decorators and template tags. --- src/compiler/checker.ts | 43 +++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 370802478bc..bde11422b95 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11943,18 +11943,12 @@ namespace ts { // Function interface, since they have none by default. This is a bit of a leap of faith // that the user will not add any. const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); - const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct); - // TS 1.0 spec: 4.12 - // If FuncExpr is of type Any, or of an object type that has no call or construct signatures - // but is a subtype of the Function interface, the call is an untyped function call. In an - // untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual + + // TS 1.0 Spec: 4.12 + // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual // types are provided for the argument expressions, and the result is always of type Any. - // We exclude union types because we may have a union of function types that happen to have - // no common signatures. - if (isTypeAny(funcType) || - (isTypeAny(apparentType) && funcType.flags & TypeFlags.TypeParameter) || - (!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) { + if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { // The unknownType indicates that an error already occurred (and was reported). No // need to report another error in this case. if (funcType !== unknownType && node.typeArguments) { @@ -11977,6 +11971,29 @@ namespace ts { return resolveCall(node, callSignatures, candidatesOutArray); } + /** + * TS 1.0 spec: 4.12 + * If FuncExpr is of type Any, or of an object type that has no call or construct signatures + * but is a subtype of the Function interface, the call is an untyped function call. + */ + function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) { + if (isTypeAny(funcType)) { + return true; + } + if (isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter) { + return true; + } + if (!numCallSignatures && !numConstructSignatures) { + // We exclude union types because we may have a union of function types that happen to have + // no common signatures. + if (funcType.flags & TypeFlags.Union) { + return false; + } + return isTypeAssignableTo(funcType, globalFunctionType); + } + return false; + } + function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature { if (node.arguments && languageVersion < ScriptTarget.ES5) { const spreadIndex = getSpreadArgumentIndex(node.arguments); @@ -12102,8 +12119,9 @@ namespace ts { } const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); + const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct); - if (isTypeAny(tagType) || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) { + if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } @@ -12148,7 +12166,8 @@ namespace ts { } const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); - if (funcType === anyType || (!callSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) { + const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct); + if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } From 5ce285c367c8baf70576ce6b1562015328aa118a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 23 Aug 2016 11:30:57 -0700 Subject: [PATCH 08/17] Accepted baselines. --- .../constructableDecoratorOnClass01.errors.txt | 16 ++++++++++++++++ ...ggedTemplateWithConstructableTag01.errors.txt | 9 +++++++++ ...ggedTemplateWithConstructableTag02.errors.txt | 12 ++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 tests/baselines/reference/constructableDecoratorOnClass01.errors.txt create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag01.errors.txt create mode 100644 tests/baselines/reference/taggedTemplateWithConstructableTag02.errors.txt diff --git a/tests/baselines/reference/constructableDecoratorOnClass01.errors.txt b/tests/baselines/reference/constructableDecoratorOnClass01.errors.txt new file mode 100644 index 00000000000..f390aaf8550 --- /dev/null +++ b/tests/baselines/reference/constructableDecoratorOnClass01.errors.txt @@ -0,0 +1,16 @@ +tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts(4,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Cannot invoke an expression whose type lacks a call signature. + + +==== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts (1 errors) ==== + + class CtorDtor {} + + @CtorDtor + ~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Cannot invoke an expression whose type lacks a call signature. + class C { + + } + \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag01.errors.txt b/tests/baselines/reference/taggedTemplateWithConstructableTag01.errors.txt new file mode 100644 index 00000000000..b114acc5277 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag01.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts(3,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. + + +==== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag01.ts (1 errors) ==== + class CtorTag { } + + CtorTag `Hello world!`; + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplateWithConstructableTag02.errors.txt b/tests/baselines/reference/taggedTemplateWithConstructableTag02.errors.txt new file mode 100644 index 00000000000..9bc4414b24f --- /dev/null +++ b/tests/baselines/reference/taggedTemplateWithConstructableTag02.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts(6,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. + + +==== tests/cases/conformance/es6/templates/taggedTemplateWithConstructableTag02.ts (1 errors) ==== + interface I { + new (...args: any[]): string; + new (): number; + } + var tag: I; + tag `Hello world!`; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. \ No newline at end of file From 73c3961355322515567875286141c4da723fb8ae Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Wed, 24 Aug 2016 18:50:04 -0700 Subject: [PATCH 09/17] Adding display parts to definition items to support FindAllReferences --- src/services/services.ts | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index babb5cf4574..7718be5a3d4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -300,8 +300,8 @@ namespace ts { } } // For syntactic classifications, all trivia are classcified together, including jsdoc comments. - // For that to work, the jsdoc comments should still be the leading trivia of the first child. - // Restoring the scanner position ensures that. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. pos = this.pos; forEachChild(this, processNode, processNodes); if (pos < this.end) { @@ -1374,8 +1374,13 @@ namespace ts { containerName: string; } + export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { + // For more complex definitions where kind and name are insufficient to properly colorize the text + displayParts?: SymbolDisplayPart[]; + } + export interface ReferencedSymbol { - definition: DefinitionInfo; + definition: ReferencedSymbolDefinitionInfo; references: ReferenceEntry[]; } @@ -6108,7 +6113,7 @@ namespace ts { return result; - function getDefinition(symbol: Symbol): DefinitionInfo { + function getDefinition(symbol: Symbol): ReferencedSymbolDefinitionInfo { const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); const name = map(info.displayParts, p => p.text).join(""); const declarations = symbol.declarations; @@ -6122,7 +6127,8 @@ namespace ts { name, kind: info.symbolKind, fileName: declarations[0].getSourceFile().fileName, - textSpan: createTextSpan(declarations[0].getStart(), 0) + textSpan: createTextSpan(declarations[0].getStart(), 0), + displayParts: info.displayParts }; } @@ -6317,7 +6323,7 @@ namespace ts { } }); - const definition: DefinitionInfo = { + const definition: ReferencedSymbolDefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, @@ -6634,6 +6640,11 @@ namespace ts { getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); } + const symbol = typeChecker.getSymbolAtLocation(node); + + const displayParts = symbol ? getSymbolDisplayPartsDocumentationAndSymbolKind( + symbol, node.getSourceFile(), getContainerNode(node), node).displayParts : undefined; + return [{ definition: { containerKind: "", @@ -6641,7 +6652,8 @@ namespace ts { fileName: node.getSourceFile().fileName, kind: ScriptElementKind.variableElement, name: type.text, - textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()) + textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts }, references: references }]; From e0a36840c058210d7d29cea9e9bd039e4cf4210a Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Thu, 25 Aug 2016 11:53:44 -0700 Subject: [PATCH 10/17] PR feedback --- src/services/services.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 7718be5a3d4..6da12696937 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1375,8 +1375,7 @@ namespace ts { } export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { - // For more complex definitions where kind and name are insufficient to properly colorize the text - displayParts?: SymbolDisplayPart[]; + displayParts: SymbolDisplayPart[]; } export interface ReferencedSymbol { @@ -6640,11 +6639,6 @@ namespace ts { getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); } - const symbol = typeChecker.getSymbolAtLocation(node); - - const displayParts = symbol ? getSymbolDisplayPartsDocumentationAndSymbolKind( - symbol, node.getSourceFile(), getContainerNode(node), node).displayParts : undefined; - return [{ definition: { containerKind: "", @@ -6653,7 +6647,7 @@ namespace ts { kind: ScriptElementKind.variableElement, name: type.text, textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), - displayParts + displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)] }, references: references }]; From 0a985ee28771c1aee386c7a2cb74c36ce8721e81 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 26 Aug 2016 13:25:19 -0700 Subject: [PATCH 11/17] Parse untyped object type members separated by ',' Previously if the first member was untyped and the separator was ',', then parsing would fail. --- src/compiler/parser.ts | 1 + .../reference/parseObjectLiteralsWithoutTypes.js | 10 ++++++++++ .../parseObjectLiteralsWithoutTypes.symbols | 16 ++++++++++++++++ .../parseObjectLiteralsWithoutTypes.types | 16 ++++++++++++++++ .../compiler/parseObjectLiteralsWithoutTypes.ts | 3 +++ 5 files changed, 46 insertions(+) create mode 100644 tests/baselines/reference/parseObjectLiteralsWithoutTypes.js create mode 100644 tests/baselines/reference/parseObjectLiteralsWithoutTypes.symbols create mode 100644 tests/baselines/reference/parseObjectLiteralsWithoutTypes.types create mode 100644 tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b5ba89887a2..b28f13e438f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2339,6 +2339,7 @@ namespace ts { token() === SyntaxKind.LessThanToken || token() === SyntaxKind.QuestionToken || token() === SyntaxKind.ColonToken || + token() === SyntaxKind.CommaToken || canParseSemicolon(); } return false; diff --git a/tests/baselines/reference/parseObjectLiteralsWithoutTypes.js b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.js new file mode 100644 index 00000000000..4872cb8773b --- /dev/null +++ b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.js @@ -0,0 +1,10 @@ +//// [parseObjectLiteralsWithoutTypes.ts] +let x: { foo, bar } +let y: { foo: number, bar } +let z: { foo, bar: number } + + +//// [parseObjectLiteralsWithoutTypes.js] +var x; +var y; +var z; diff --git a/tests/baselines/reference/parseObjectLiteralsWithoutTypes.symbols b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.symbols new file mode 100644 index 00000000000..1e0bd775d10 --- /dev/null +++ b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts === +let x: { foo, bar } +>x : Symbol(x, Decl(parseObjectLiteralsWithoutTypes.ts, 0, 3)) +>foo : Symbol(foo, Decl(parseObjectLiteralsWithoutTypes.ts, 0, 8)) +>bar : Symbol(bar, Decl(parseObjectLiteralsWithoutTypes.ts, 0, 13)) + +let y: { foo: number, bar } +>y : Symbol(y, Decl(parseObjectLiteralsWithoutTypes.ts, 1, 3)) +>foo : Symbol(foo, Decl(parseObjectLiteralsWithoutTypes.ts, 1, 8)) +>bar : Symbol(bar, Decl(parseObjectLiteralsWithoutTypes.ts, 1, 21)) + +let z: { foo, bar: number } +>z : Symbol(z, Decl(parseObjectLiteralsWithoutTypes.ts, 2, 3)) +>foo : Symbol(foo, Decl(parseObjectLiteralsWithoutTypes.ts, 2, 8)) +>bar : Symbol(bar, Decl(parseObjectLiteralsWithoutTypes.ts, 2, 13)) + diff --git a/tests/baselines/reference/parseObjectLiteralsWithoutTypes.types b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.types new file mode 100644 index 00000000000..dcd9cb79d19 --- /dev/null +++ b/tests/baselines/reference/parseObjectLiteralsWithoutTypes.types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts === +let x: { foo, bar } +>x : { foo: any; bar: any; } +>foo : any +>bar : any + +let y: { foo: number, bar } +>y : { foo: number; bar: any; } +>foo : number +>bar : any + +let z: { foo, bar: number } +>z : { foo: any; bar: number; } +>foo : any +>bar : number + diff --git a/tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts b/tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts new file mode 100644 index 00000000000..7f00e4b15e7 --- /dev/null +++ b/tests/cases/compiler/parseObjectLiteralsWithoutTypes.ts @@ -0,0 +1,3 @@ +let x: { foo, bar } +let y: { foo: number, bar } +let z: { foo, bar: number } From 3f8cd8230163b9b33f5b511bc639398a101b8bc0 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 26 Aug 2016 13:30:59 -0700 Subject: [PATCH 12/17] Update other tests and baselines --- ...ShorthandPropertiesAssignmentError.errors.txt | 13 ++----------- ...tLiteralShorthandPropertiesAssignmentError.js | 5 ++--- ...signmentErrorFromMissingIdentifier.errors.txt | 16 ++++------------ ...ertiesAssignmentErrorFromMissingIdentifier.js | 8 ++++---- ...tLiteralShorthandPropertiesAssignmentError.ts | 2 +- ...ertiesAssignmentErrorFromMissingIdentifier.ts | 4 ++-- 6 files changed, 15 insertions(+), 33 deletions(-) diff --git a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.errors.txt b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.errors.txt index 50839d5e56b..6f405facceb 100644 --- a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.errors.txt +++ b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.errors.txt @@ -1,8 +1,5 @@ tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts(4,43): error TS2322: Type '{ name: string; id: number; }' is not assignable to type '{ b: string; id: number; }'. Object literal may only specify known properties, and 'name' does not exist in type '{ b: string; id: number; }'. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts(5,16): error TS1131: Property or signature expected. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts(5,22): error TS2403: Subsequent variable declarations must have the same type. Variable 'id' must be of type 'number', but here has type 'any'. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts(5,25): error TS1128: Declaration or statement expected. tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts(6,79): error TS2322: Type '{ name: string; id: number; }' is not assignable to type '{ id: string; name: number; }'. Types of property 'id' are incompatible. Type 'number' is not assignable to type 'string'. @@ -11,7 +8,7 @@ tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPr Type 'number' is not assignable to type 'boolean'. -==== tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts (6 errors) ==== +==== tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts (3 errors) ==== var id: number = 10000; var name: string = "my name"; @@ -19,13 +16,7 @@ tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPr ~~~~ !!! error TS2322: Type '{ name: string; id: number; }' is not assignable to type '{ b: string; id: number; }'. !!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ b: string; id: number; }'. - var person1: { name, id }; // error: can't use short-hand property assignment in type position - ~~~~ -!!! error TS1131: Property or signature expected. - ~~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'id' must be of type 'number', but here has type 'any'. - ~ -!!! error TS1128: Declaration or statement expected. + var person1: { name, id }; // ok function foo(name: string, id: number): { id: string, name: number } { return { name, id }; } // error ~~~~~~~~~~~~ !!! error TS2322: Type '{ name: string; id: number; }' is not assignable to type '{ id: string; name: number; }'. diff --git a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.js b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.js index 8e2d7f80356..4d01f799348 100644 --- a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.js +++ b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentError.js @@ -3,7 +3,7 @@ var id: number = 10000; var name: string = "my name"; var person: { b: string; id: number } = { name, id }; // error -var person1: { name, id }; // error: can't use short-hand property assignment in type position +var person1: { name, id }; // ok function foo(name: string, id: number): { id: string, name: number } { return { name, id }; } // error function bar(obj: { name: string; id: boolean }) { } bar({ name, id }); // error @@ -14,8 +14,7 @@ bar({ name, id }); // error var id = 10000; var name = "my name"; var person = { name: name, id: id }; // error -var person1 = name, id; -; // error: can't use short-hand property assignment in type position +var person1; // ok function foo(name, id) { return { name: name, id: id }; } // error function bar(obj) { } bar({ name: name, id: id }); // error diff --git a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.errors.txt b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.errors.txt index b4f695c835d..92750fd29a0 100644 --- a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.errors.txt +++ b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.errors.txt @@ -3,15 +3,12 @@ tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPr tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts(5,79): error TS2322: Type '{ name: string; id: number; }' is not assignable to type '{ name: number; id: string; }'. Types of property 'name' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts(7,16): error TS1131: Property or signature expected. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts(7,22): error TS2403: Subsequent variable declarations must have the same type. Variable 'id' must be of type 'number', but here has type 'any'. -tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts(7,25): error TS1128: Declaration or statement expected. tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts(8,5): error TS2322: Type '{ name: number; id: string; }' is not assignable to type '{ name: string; id: number; }'. Types of property 'name' are incompatible. Type 'number' is not assignable to type 'string'. -==== tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts (6 errors) ==== +==== tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts (3 errors) ==== var id: number = 10000; var name: string = "my name"; @@ -25,15 +22,10 @@ tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPr !!! error TS2322: Types of property 'name' are incompatible. !!! error TS2322: Type 'string' is not assignable to type 'number'. function foo(name: string, id: number): { name: string, id: number } { return { name, id }; } // error - var person1: { name, id }; // error : Can't use shorthand in the type position - ~~~~ -!!! error TS1131: Property or signature expected. - ~~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'id' must be of type 'number', but here has type 'any'. - ~ -!!! error TS1128: Declaration or statement expected. + var person1: { name, id }; // ok var person2: { name: string, id: number } = bar("hello", 5); ~~~~~~~ !!! error TS2322: Type '{ name: number; id: string; }' is not assignable to type '{ name: string; id: number; }'. !!! error TS2322: Types of property 'name' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type 'string'. \ No newline at end of file +!!! error TS2322: Type 'number' is not assignable to type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.js b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.js index 71449746add..7800cbff53e 100644 --- a/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.js +++ b/tests/baselines/reference/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.js @@ -5,8 +5,9 @@ var name: string = "my name"; var person: { b: string; id: number } = { name, id }; // error function bar(name: string, id: number): { name: number, id: string } { return { name, id }; } // error function foo(name: string, id: number): { name: string, id: number } { return { name, id }; } // error -var person1: { name, id }; // error : Can't use shorthand in the type position -var person2: { name: string, id: number } = bar("hello", 5); +var person1: { name, id }; // ok +var person2: { name: string, id: number } = bar("hello", 5); + //// [objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.js] var id = 10000; @@ -14,6 +15,5 @@ var name = "my name"; var person = { name: name, id: id }; // error function bar(name, id) { return { name: name, id: id }; } // error function foo(name, id) { return { name: name, id: id }; } // error -var person1 = name, id; -; // error : Can't use shorthand in the type position +var person1; // ok var person2 = bar("hello", 5); diff --git a/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts b/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts index b745b93b3ca..55f10aec932 100644 --- a/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts +++ b/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentError.ts @@ -2,7 +2,7 @@ var name: string = "my name"; var person: { b: string; id: number } = { name, id }; // error -var person1: { name, id }; // error: can't use short-hand property assignment in type position +var person1: { name, id }; // ok function foo(name: string, id: number): { id: string, name: number } { return { name, id }; } // error function bar(obj: { name: string; id: boolean }) { } bar({ name, id }); // error diff --git a/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts b/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts index 6b0943a8d77..104be41a839 100644 --- a/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts +++ b/tests/cases/conformance/es6/shorthandPropertyAssignment/objectLiteralShorthandPropertiesAssignmentErrorFromMissingIdentifier.ts @@ -4,5 +4,5 @@ var name: string = "my name"; var person: { b: string; id: number } = { name, id }; // error function bar(name: string, id: number): { name: number, id: string } { return { name, id }; } // error function foo(name: string, id: number): { name: string, id: number } { return { name, id }; } // error -var person1: { name, id }; // error : Can't use shorthand in the type position -var person2: { name: string, id: number } = bar("hello", 5); \ No newline at end of file +var person1: { name, id }; // ok +var person2: { name: string, id: number } = bar("hello", 5); From 4c847eb257434ac129a8a7b62bdb9a17a272028e Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Fri, 26 Aug 2016 15:04:08 -0700 Subject: [PATCH 13/17] Fixing errors and adding a fourslash test --- src/harness/fourslash.ts | 62 +++++++++++++------ src/services/services.ts | 11 +++- .../findReferencesDefinitionDisplayParts.ts | 23 +++++++ tests/cases/fourslash/fourslash.ts | 1 + 4 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 tests/cases/fourslash/findReferencesDefinitionDisplayParts.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 63731417f48..694dcf6394e 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -206,6 +206,24 @@ namespace FourSlash { private inputFiles = ts.createMap(); // Map between inputFile's fileName and its content for easily looking up when resolving references + private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { + let result = ""; + ts.forEach(displayParts, part => { + if (result) { + result += ",\n "; + } + else { + result = "[\n "; + } + result += JSON.stringify(part); + }); + if (result) { + result += "\n]"; + } + + return result; + } + // Add input file which has matched file name with the given reference-file path. // This is necessary when resolveReference flag is specified private addMatchedInputFile(referenceFilePath: string, extensions: string[]) { @@ -777,6 +795,20 @@ namespace FourSlash { ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges)); } + public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) { + const referencedSymbols = this.findReferencesAtCaret(); + + if (referencedSymbols.length === 0) { + this.raiseError("No referenced symbols found at current caret position"); + } + else if (referencedSymbols.length > 1) { + this.raiseError("More than one referenced symbol found"); + } + + assert.equal(TestState.getDisplayPartsJson(referencedSymbols[0].definition.displayParts), + TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts")); + } + private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) { for (let i = 0; i < references.length; i++) { const reference = references[i]; @@ -811,6 +843,10 @@ namespace FourSlash { return this.languageService.getReferencesAtPosition(this.activeFile.fileName, this.currentCaretPosition); } + private findReferencesAtCaret() { + return this.languageService.findReferences(this.activeFile.fileName, this.currentCaretPosition); + } + public getSyntacticDiagnostics(expected: string) { const diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); this.testDiagnostics(expected, diagnostics); @@ -856,30 +892,12 @@ namespace FourSlash { displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { - function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { - let result = ""; - ts.forEach(displayParts, part => { - if (result) { - result += ",\n "; - } - else { - result = "[\n "; - } - result += JSON.stringify(part); - }); - if (result) { - result += "\n]"; - } - - return result; - } - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind")); assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers")); assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); - assert.equal(getDisplayPartsJson(actualQuickInfo.displayParts), getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); - assert.equal(getDisplayPartsJson(actualQuickInfo.documentation), getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); + assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); + assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); } public verifyRenameLocations(findInStrings: boolean, findInComments: boolean, ranges?: Range[]) { @@ -2947,6 +2965,10 @@ namespace FourSlashInterface { this.state.verifyRangesReferenceEachOther(ranges); } + public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) { + this.state.verifyDisplayPartsOfReferencedSymbol(expected); + } + public rangesWithSameTextReferenceEachOther() { this.state.verifyRangesWithSameTextReferenceEachOther(); } diff --git a/src/services/services.ts b/src/services/services.ts index 6da12696937..8794446e83e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6328,7 +6328,8 @@ namespace ts { fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, - textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) + textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()), + displayParts: [displayPart(labelName, SymbolDisplayPartKind.text)] }; return [{ definition, references }]; @@ -6568,6 +6569,11 @@ namespace ts { getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } + const thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); + + const { displayParts } = getSymbolDisplayPartsDocumentationAndSymbolKind( + thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword); + return [{ definition: { containerKind: "", @@ -6575,7 +6581,8 @@ namespace ts { fileName: node.getSourceFile().fileName, kind: ScriptElementKind.variableElement, name: "this", - textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()) + textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts }, references: references }]; diff --git a/tests/cases/fourslash/findReferencesDefinitionDisplayParts.ts b/tests/cases/fourslash/findReferencesDefinitionDisplayParts.ts new file mode 100644 index 00000000000..d424bd0c500 --- /dev/null +++ b/tests/cases/fourslash/findReferencesDefinitionDisplayParts.ts @@ -0,0 +1,23 @@ +/// + +//// class Gre/*1*/eter { +//// someFunction() { th/*2*/is; } +//// } +//// +//// type Options = "opt/*3*/ion 1" | "option 2"; +//// let myOption: Options = "option 1"; +//// +//// some/*4*/Label: +//// break someLabel; + +goTo.marker("1"); +verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "Greeter", kind: "className" }]); + +goTo.marker("2"); +verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "this", kind: "keyword" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "this", kind: "keyword" }]); + +goTo.marker("3"); +verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "\"option 1\"", kind: "stringLiteral" }]); + +goTo.marker("4"); +verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "someLabel", kind: "text" }]); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 9ce3197a46f..59037e0de67 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -171,6 +171,7 @@ declare namespace FourSlashInterface { * If `ranges` is omitted, this is `test.ranges()`. */ rangesReferenceEachOther(ranges?: Range[]): void; + findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]): void; rangesWithSameTextReferenceEachOther(): void; currentParameterHelpArgumentNameIs(name: string): void; currentParameterSpanIs(parameter: string): void; From e62f1181b6a94161f8bfa88a84c2cf4c0f66bc3a Mon Sep 17 00:00:00 2001 From: Yui Date: Fri, 26 Aug 2016 16:46:10 -0700 Subject: [PATCH 14/17] fix typo of missing node.kind (#10569) --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d0f7918dc89..f02cf266744 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6587,7 +6587,7 @@ const _super = (function (geti, seti) { // import { x, y } from "foo" // import d, * as x from "foo" // import d, { x, y } from "foo" - const isNakedImport = SyntaxKind.ImportDeclaration && !(node).importClause; + const isNakedImport = node.kind === SyntaxKind.ImportDeclaration && !(node).importClause; if (!isNakedImport) { write(varOrConst); write(getGeneratedNameForNode(node)); From d72ed3c0b0fcf1f3c5f2b06d430c5e9c2ea6ca6f Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Fri, 26 Aug 2016 16:52:25 -0700 Subject: [PATCH 15/17] Check for this symbol before getting display parts --- src/services/services.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index dd99c0dba52..c19eb487d75 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6570,8 +6570,8 @@ namespace ts { const thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); - const { displayParts } = getSymbolDisplayPartsDocumentationAndSymbolKind( - thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword); + const displayParts = thisOrSuperSymbol && getSymbolDisplayPartsDocumentationAndSymbolKind( + thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts; return [{ definition: { From 0b9573118454ab2420abc168405be1a78b482b57 Mon Sep 17 00:00:00 2001 From: Yui Date: Tue, 30 Aug 2016 16:07:36 -0700 Subject: [PATCH 16/17] Fix 10408 : Better error message for set/get with noImplicitAny error (#10597) * Giving more explicit error message when there is no-implicit-any on get/set accessor * Update error message number * Add new test and baselines * Address PR: assert that getter must existed * Address PR: undo renumbering of error messages --- src/compiler/checker.ts | 8 +++- src/compiler/diagnosticMessages.json | 14 +++--- ...AndSetAccessorWithAnyReturnType.errors.txt | 4 +- ...noImplicitAnyMissingGetAccessor.errors.txt | 27 ++++++++++++ .../noImplicitAnyMissingGetAccessor.js | 44 +++++++++++++++++++ ...noImplicitAnyMissingSetAccessor.errors.txt | 17 +++++++ .../noImplicitAnyMissingSetAccessor.js | 43 ++++++++++++++++++ .../noImplicitAnyMissingGetAccessor.ts | 14 ++++++ .../noImplicitAnyMissingSetAccessor.ts | 13 ++++++ 9 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/noImplicitAnyMissingGetAccessor.errors.txt create mode 100644 tests/baselines/reference/noImplicitAnyMissingGetAccessor.js create mode 100644 tests/baselines/reference/noImplicitAnyMissingSetAccessor.errors.txt create mode 100644 tests/baselines/reference/noImplicitAnyMissingSetAccessor.js create mode 100644 tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts create mode 100644 tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a98c72c9e10..863c9e7c37a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3346,7 +3346,13 @@ namespace ts { // Otherwise, fall back to 'any'. else { if (compilerOptions.noImplicitAny) { - error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol)); + if (setter) { + error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); + } + else { + Debug.assert(!!getter, "there must existed getter as we are current checking either setter or getter in this function"); + error(getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); + } } type = anyType; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b8978b32571..e6bf1d5a170 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2871,11 +2871,7 @@ "Element implicitly has an 'any' type because index expression is not of type 'number'.": { "category": "Error", "code": 7015 - }, - "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation.": { - "category": "Error", - "code": 7016 - }, + }, "Index signature of object type implicitly has an 'any' type.": { "category": "Error", "code": 7017 @@ -2932,6 +2928,14 @@ "category": "Error", "code": 7031 }, + "Property '{0}' implicitly has type 'any', because its set accessor lacks a parameter type annotation.": { + "category": "Error", + "code": 7032 + }, + "Property '{0}' implicitly has type 'any', because its get accessor lacks a return type annotation.": { + "category": "Error", + "code": 7033 + }, "You cannot rename this element.": { "category": "Error", "code": 8000 diff --git a/tests/baselines/reference/implicitAnyGetAndSetAccessorWithAnyReturnType.errors.txt b/tests/baselines/reference/implicitAnyGetAndSetAccessorWithAnyReturnType.errors.txt index 460ff97b10e..1e2de97aae0 100644 --- a/tests/baselines/reference/implicitAnyGetAndSetAccessorWithAnyReturnType.errors.txt +++ b/tests/baselines/reference/implicitAnyGetAndSetAccessorWithAnyReturnType.errors.txt @@ -2,7 +2,7 @@ tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(3,5): erro tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(4,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(9,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(15,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(15,16): error TS7016: Property 'haveOnlySet' implicitly has type 'any', because its 'set' accessor lacks a type annotation. +tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(15,16): error TS7032: Property 'haveOnlySet' implicitly has type 'any', because its set accessor lacks a parameter type annotation. tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(15,28): error TS7006: Parameter 'newXValue' implicitly has an 'any' type. tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(20,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(20,16): error TS7010: 'haveOnlyGet', which lacks return-type annotation, implicitly has an 'any' return type. @@ -33,7 +33,7 @@ tests/cases/compiler/implicitAnyGetAndSetAccessorWithAnyReturnType.ts(20,16): er ~~~~~~~~~~~ !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. ~~~~~~~~~~~ -!!! error TS7016: Property 'haveOnlySet' implicitly has type 'any', because its 'set' accessor lacks a type annotation. +!!! error TS7032: Property 'haveOnlySet' implicitly has type 'any', because its set accessor lacks a parameter type annotation. ~~~~~~~~~ !!! error TS7006: Parameter 'newXValue' implicitly has an 'any' type. } diff --git a/tests/baselines/reference/noImplicitAnyMissingGetAccessor.errors.txt b/tests/baselines/reference/noImplicitAnyMissingGetAccessor.errors.txt new file mode 100644 index 00000000000..ef2a273711f --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyMissingGetAccessor.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts(4,25): error TS7032: Property 'message' implicitly has type 'any', because its set accessor lacks a parameter type annotation. +tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts(4,33): error TS7006: Parameter 'str' implicitly has an 'any' type. +tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts(9,16): error TS7032: Property 'message' implicitly has type 'any', because its set accessor lacks a parameter type annotation. +tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts(9,24): error TS7006: Parameter 'str' implicitly has an 'any' type. + + +==== tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts (4 errors) ==== + + abstract class Parent + { + public abstract set message(str); + ~~~~~~~ +!!! error TS7032: Property 'message' implicitly has type 'any', because its set accessor lacks a parameter type annotation. + ~~~ +!!! error TS7006: Parameter 'str' implicitly has an 'any' type. + } + + class Child extends Parent { + _x: any; + public set message(str) { + ~~~~~~~ +!!! error TS7032: Property 'message' implicitly has type 'any', because its set accessor lacks a parameter type annotation. + ~~~ +!!! error TS7006: Parameter 'str' implicitly has an 'any' type. + this._x = str; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitAnyMissingGetAccessor.js b/tests/baselines/reference/noImplicitAnyMissingGetAccessor.js new file mode 100644 index 00000000000..38a2a731af4 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyMissingGetAccessor.js @@ -0,0 +1,44 @@ +//// [noImplicitAnyMissingGetAccessor.ts] + +abstract class Parent +{ + public abstract set message(str); +} + +class Child extends Parent { + _x: any; + public set message(str) { + this._x = str; + } +} + +//// [noImplicitAnyMissingGetAccessor.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Parent = (function () { + function Parent() { + } + Object.defineProperty(Parent.prototype, "message", { + set: function (str) { }, + enumerable: true, + configurable: true + }); + return Parent; +}()); +var Child = (function (_super) { + __extends(Child, _super); + function Child() { + _super.apply(this, arguments); + } + Object.defineProperty(Child.prototype, "message", { + set: function (str) { + this._x = str; + }, + enumerable: true, + configurable: true + }); + return Child; +}(Parent)); diff --git a/tests/baselines/reference/noImplicitAnyMissingSetAccessor.errors.txt b/tests/baselines/reference/noImplicitAnyMissingSetAccessor.errors.txt new file mode 100644 index 00000000000..ba104209189 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyMissingSetAccessor.errors.txt @@ -0,0 +1,17 @@ +tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts(4,25): error TS7033: Property 'message' implicitly has type 'any', because its get accessor lacks a return type annotation. + + +==== tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts (1 errors) ==== + + abstract class Parent + { + public abstract get message(); + ~~~~~~~ +!!! error TS7033: Property 'message' implicitly has type 'any', because its get accessor lacks a return type annotation. + } + + class Child extends Parent { + public get message() { + return ""; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitAnyMissingSetAccessor.js b/tests/baselines/reference/noImplicitAnyMissingSetAccessor.js new file mode 100644 index 00000000000..d4e0d17186d --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyMissingSetAccessor.js @@ -0,0 +1,43 @@ +//// [noImplicitAnyMissingSetAccessor.ts] + +abstract class Parent +{ + public abstract get message(); +} + +class Child extends Parent { + public get message() { + return ""; + } +} + +//// [noImplicitAnyMissingSetAccessor.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Parent = (function () { + function Parent() { + } + Object.defineProperty(Parent.prototype, "message", { + get: function () { }, + enumerable: true, + configurable: true + }); + return Parent; +}()); +var Child = (function (_super) { + __extends(Child, _super); + function Child() { + _super.apply(this, arguments); + } + Object.defineProperty(Child.prototype, "message", { + get: function () { + return ""; + }, + enumerable: true, + configurable: true + }); + return Child; +}(Parent)); diff --git a/tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts b/tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts new file mode 100644 index 00000000000..d6c7b012cf9 --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyMissingGetAccessor.ts @@ -0,0 +1,14 @@ +// @noImplicitAny : true +// @target: es5 + +abstract class Parent +{ + public abstract set message(str); +} + +class Child extends Parent { + _x: any; + public set message(str) { + this._x = str; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts b/tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts new file mode 100644 index 00000000000..ae18faf1f6f --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyMissingSetAccessor.ts @@ -0,0 +1,13 @@ +// @noImplicitAny: true +// @target: es5 + +abstract class Parent +{ + public abstract get message(); +} + +class Child extends Parent { + public get message() { + return ""; + } +} \ No newline at end of file From 707d61d7fe953b04b3ad117294a33135573ced3a Mon Sep 17 00:00:00 2001 From: Yui Date: Wed, 31 Aug 2016 13:53:14 -0700 Subject: [PATCH 17/17] Fix RWC Runner to report both .types and .symbols errors (#10513) * Correctly append .types or .symbols when calling from rwc runner * Report both errors from generating .types or .symbols * Address PR --- src/harness/harness.ts | 25 +++++++++++++++++++------ src/harness/rwcRunner.ts | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 9e27f500b80..ac0de944213 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1370,23 +1370,31 @@ namespace Harness { // Produce baselines. The first gives the types for all expressions. // The second gives symbols for all identifiers. - let e1: Error, e2: Error; + let typesError: Error, symbolsError: Error; try { checkBaseLines(/*isSymbolBaseLine*/ false); } catch (e) { - e1 = e; + typesError = e; } try { checkBaseLines(/*isSymbolBaseLine*/ true); } catch (e) { - e2 = e; + symbolsError = e; } - if (e1 || e2) { - throw e1 || e2; + if (typesError && symbolsError) { + throw new Error(typesError.message + ts.sys.newLine + symbolsError.message); + } + + if (typesError) { + throw typesError; + } + + if (symbolsError) { + throw symbolsError; } return; @@ -1396,7 +1404,12 @@ namespace Harness { const fullExtension = isSymbolBaseLine ? ".symbols" : ".types"; - Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, fullExtension), () => fullBaseLine, opts); + // When calling this function from rwc-runner, the baselinePath will have no extension. + // As rwc test- file is stored in json which ".json" will get stripped off. + // When calling this function from compiler-runner, the baselinePath will then has either ".ts" or ".tsx" extension + const outputFileName = ts.endsWith(baselinePath, ".ts") || ts.endsWith(baselinePath, ".tsx") ? + baselinePath.replace(/\.tsx?/, fullExtension) : baselinePath.concat(fullExtension); + Harness.Baseline.runBaseline(outputFileName, () => fullBaseLine, opts); } function generateBaseLine(typeWriterResults: ts.Map, isSymbolBaseline: boolean): string { diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index ba1ab71ec19..fff0d6bfb49 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -223,7 +223,8 @@ namespace RWC { }); it("has the expected types", () => { - Harness.Compiler.doTypeAndSymbolBaseline(`${baseName}.types`, compilerResult, inputFiles + // We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols" + Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles .concat(otherFiles) .filter(file => !!compilerResult.program.getSourceFile(file.unitName)) .filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);