From 7ff4238f93d760a953b525c1a6ee1daca21475a8 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 24 Nov 2015 17:44:10 -0800 Subject: [PATCH 1/5] Fix crushing of getting signatureDeclaration when we are not in function declaration --- src/services/services.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 8d66b5c7b8a1b..54c76a063b2d3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4247,24 +4247,22 @@ namespace ts { } else { // Method/function type parameter - let container = getContainingFunction(location); - if (container) { - let signatureDeclaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent; - let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration); - if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) { + let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent; + if (declaration && isFunctionLikeKind(declaration.kind)) { + let signature = typeChecker.getSignatureFromDeclaration(declaration); + if (declaration.kind === SyntaxKind.ConstructSignature) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); } - else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) { - addFullSymbolName(signatureDeclaration.symbol); + else if (declaration.kind !== SyntaxKind.CallSignature && (declaration).name) { + addFullSymbolName(declaration.symbol); } addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } else { - // Type aliash type parameter + // Type alias type parameter // For example // type list = T[]; // Both T will go through same code path - let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent; displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); displayParts.push(spacePart()); addFullSymbolName(declaration.symbol); From 81fdc4384f5a9582d010414884066a4d5172c974 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 24 Nov 2015 17:50:00 -0800 Subject: [PATCH 2/5] Add fourslash tests --- ...mpletionListInTypeParameterOfTypeAlias3.ts | 13 ++++++ ...sTypeParameterInFunctionLikeInTypeAlias.ts | 22 ++++++++++ ...nfoDisplayPartsTypeParameterInTypeAlias.ts | 3 -- ...sTypeParameterOfFunctionLikeInTypeAlias.ts | 41 +++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts create mode 100644 tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.ts create mode 100644 tests/cases/fourslash/quickInfoDisplayPartsTypeParameterOfFunctionLikeInTypeAlias.ts diff --git a/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts new file mode 100644 index 0000000000000..59cceda2aad48 --- /dev/null +++ b/tests/cases/fourslash/completionListInTypeParameterOfTypeAlias3.ts @@ -0,0 +1,13 @@ +/// + +//// type constructorType = new + +//// type MixinCtor = new () => /*0*/A & { constructor: MixinCtor }; +//// type MixinCtor = new () => A & { constructor: { constructor: MixinCtor } }; + +let typeAliashDisplayParts = [{ text: "type", kind: "keyword" }, { text: " ", kind: "space" }, { text: "MixinCtor", kind: "aliasName" }, + { text: "<", kind: "punctuation" }, { text: "A", kind: "typeParameterName" }, { text: ">", kind: "punctuation" }]; + +let typeParameterDisplayParts = [{ text: "(", kind: "punctuation" }, { text: "type parameter", kind: "text" }, { text: ")", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "A", kind: "typeParameterName" }, { text: " ", kind: "space" }, { text: "in", kind: "keyword" }, { text: " ", kind: "space" }]; + +goTo.marker('0'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("0").position, length: "A".length }, + typeParameterDisplayParts.concat(typeAliashDisplayParts), []); + +goTo.marker('1'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("1").position, length: "A".length }, + typeParameterDisplayParts.concat(typeAliashDisplayParts), []);; + +goTo.marker('2'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("2").position, length: "A".length }, + typeParameterDisplayParts.concat(typeAliashDisplayParts), []); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInTypeAlias.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInTypeAlias.ts index b6a10e086c25b..5dbcfa93d783e 100644 --- a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInTypeAlias.ts +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInTypeAlias.ts @@ -3,9 +3,6 @@ ////type /*0*/List = /*2*/T[] ////type /*3*/List2 = /*5*/T[]; -type List2 = T[]; - -type L = T[] let typeAliashDisplayParts = [{ text: "type", kind: "keyword" }, { text: " ", kind: "space" }, { text: "List", kind: "aliasName" }, { text: "<", kind: "punctuation" }, { text: "T", kind: "typeParameterName" }, { text: ">", kind: "punctuation" }]; diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterOfFunctionLikeInTypeAlias.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterOfFunctionLikeInTypeAlias.ts new file mode 100644 index 0000000000000..917358fde570b --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterOfFunctionLikeInTypeAlias.ts @@ -0,0 +1,41 @@ +/// + +//// type jamming = new () => jamming; +//// type jamming = (new () => jamming) & { constructor: /*2*/A }; +//// type jamming = new () => jamming & { constructor: /*3*/A }; + +let typeAliashDisplayParts = [{ text: "type", kind: "keyword" }, { text: " ", kind: "space" }, { text: "jamming", kind: "aliasName" }, + { text: "<", kind: "punctuation" }, { text: "A", kind: "typeParameterName" }, { text: ">", kind: "punctuation" }]; + +let typeParameterDisplayParts = [{ text: "(", kind: "punctuation" }, { text: "type parameter", kind: "text" }, { text: ")", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "A", kind: "typeParameterName" }, { text: " ", kind: "space" }, { text: "in", kind: "keyword" }, { text: " ", kind: "space" }]; + +let constructorTypeDisplayParts = [{ text: "<", kind: "punctuation" }, { text: "A", kind: "typeParameterName" }, { text: ">", kind: "punctuation" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "new", kind: "keyword" }, { "text": " ", kind: "space" }, { text: "<", kind: "punctuation" }, { text: "A", kind: "typeParameterName" }, + { text: ">", kind: "punctuation" }, { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, {"text": " ", kind: "space" }, + { text: "=>", kind: "punctuation" }, { "text": " ", kind: "space" }, { text: "jamming", kind: "aliasName" }]; + +let constructorTypeWithLongReturnTypeDisplayParts = [{ "text": "<", kind: "punctuation" }, { "text": "A", kind: "typeParameterName" }, { "text": ">", kind: "punctuation" }, + { "text": "(", kind: "punctuation" }, { "text": ")", kind: "punctuation" }, { "text": ":", kind: "punctuation" }, { "text": " ", kind: "space" }, { "text": "(", kind: "punctuation" }, + { "text": "new", kind: "keyword" }, { "text": " ", kind: "space" }, { "text": "<", kind: "punctuation" }, { "text": "A", kind: "typeParameterName" }, { "text": ">", kind: "punctuation" }, + { "text": "(", kind: "punctuation" }, { "text": ")", kind: "punctuation" }, { "text": " ", kind: "space" }, { "text": "=>", kind: "punctuation" }, { "text": " ", kind: "space" }, + { "text": "jamming", kind: "aliasName" }, { "text": ")", kind: "punctuation" }, { "text": " ", kind: "space" }, { "text": "&", kind: "punctuation" }, { "text": " ", kind: "space" }, + { "text": "{", kind: "punctuation" }, { "text": "\n", kind: "lineBreak" }, { "text": " ", kind: "space" }, { "text": "constructor", kind: "propertyName" }, { "text": ":", kind: "punctuation" }, + { "text": " ", kind: "space" }, { "text": "A", kind: "typeParameterName" }, {"text":";", kind: "punctuation" }, {"text":"\n", kind: "lineBreak" }, {"text":"}", kind: "punctuation" }]; + +goTo.marker('0'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("0").position, length: "A".length }, + typeParameterDisplayParts.concat(constructorTypeDisplayParts), []); + +goTo.marker('1'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("1").position, length: "A".length }, + typeParameterDisplayParts.concat(constructorTypeDisplayParts), []); + +goTo.marker('2'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("2").position, length: "A".length }, + typeParameterDisplayParts.concat(typeAliashDisplayParts), []); + +goTo.marker('3'); +verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName("3").position, length: "A".length }, + typeParameterDisplayParts.concat(constructorTypeWithLongReturnTypeDisplayParts), []); \ No newline at end of file From c5a2969255e7b1c1d45c3b6bb276455e6992ed8d Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 25 Nov 2015 11:41:51 -0800 Subject: [PATCH 3/5] check for null --- src/services/services.ts | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 54c76a063b2d3..b53ff02e195da 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4247,26 +4247,30 @@ namespace ts { } else { // Method/function type parameter - let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent; - if (declaration && isFunctionLikeKind(declaration.kind)) { - let signature = typeChecker.getSignatureFromDeclaration(declaration); - if (declaration.kind === SyntaxKind.ConstructSignature) { - displayParts.push(keywordPart(SyntaxKind.NewKeyword)); - displayParts.push(spacePart()); + let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); + declaration = declaration ? declaration.parent : undefined; + + if (declaration) { + if (isFunctionLikeKind(declaration.kind)) { + let signature = typeChecker.getSignatureFromDeclaration(declaration); + if (declaration.kind === SyntaxKind.ConstructSignature) { + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); + } + else if (declaration.kind !== SyntaxKind.CallSignature && (declaration).name) { + addFullSymbolName(declaration.symbol); + } + addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } - else if (declaration.kind !== SyntaxKind.CallSignature && (declaration).name) { + else { + // Type alias type parameter + // For example + // type list = T[]; // Both T will go through same code path + displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); + displayParts.push(spacePart()); addFullSymbolName(declaration.symbol); + writeTypeParametersOfSymbol(declaration.symbol, sourceFile); } - addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); - } - else { - // Type alias type parameter - // For example - // type list = T[]; // Both T will go through same code path - displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); - displayParts.push(spacePart()); - addFullSymbolName(declaration.symbol); - writeTypeParametersOfSymbol(declaration.symbol, sourceFile); } } } From 62fb5e85e4d432faa241778b06015a636738f8d1 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 25 Nov 2015 17:33:11 -0800 Subject: [PATCH 4/5] Include debug assert --- src/services/services.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index b53ff02e195da..ea5a4a027ccfa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1901,7 +1901,7 @@ namespace ts { sourceMapText = text; } else { - Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name); + Debug.assert(outputText === undefined, `Unexpected multiple outputs for the file: '${name}'`); outputText = text; } }, @@ -4248,7 +4248,8 @@ namespace ts { else { // Method/function type parameter let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); - declaration = declaration ? declaration.parent : undefined; + Debug.assert(declaration !== undefined); + declaration = declaration.parent; if (declaration) { if (isFunctionLikeKind(declaration.kind)) { From 2cc7a7904ac932f3d2fce7afc1d2b16b1723527a Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 30 Nov 2015 09:10:14 -0800 Subject: [PATCH 5/5] use const --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index 18fa58a74f70e..4e0a0265b9193 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4254,7 +4254,7 @@ namespace ts { if (declaration) { if (isFunctionLikeKind(declaration.kind)) { - let signature = typeChecker.getSignatureFromDeclaration(declaration); + const signature = typeChecker.getSignatureFromDeclaration(declaration); if (declaration.kind === SyntaxKind.ConstructSignature) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart());