From bea7221174de736d7f01ea9de3624d971a76f2c6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Mar 2015 16:59:34 -0700 Subject: [PATCH 1/3] Ensure we find export default declaration targets if we search for them by name --- src/compiler/checker.ts | 7 ++++ .../es5ExportDefaultClassDeclaration3.js | 35 +++++++++++++++++++ .../es5ExportDefaultClassDeclaration3.types | 33 +++++++++++++++++ .../es5ExportDefaultFunctionDeclaration3.js | 21 +++++++++++ ...es5ExportDefaultFunctionDeclaration3.types | 22 ++++++++++++ .../es5ExportDefaultClassDeclaration3.ts | 16 +++++++++ .../es5ExportDefaultFunctionDeclaration3.ts | 11 ++++++ 7 files changed, 145 insertions(+) create mode 100644 tests/baselines/reference/es5ExportDefaultClassDeclaration3.js create mode 100644 tests/baselines/reference/es5ExportDefaultClassDeclaration3.types create mode 100644 tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.js create mode 100644 tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.types create mode 100644 tests/cases/compiler/es5ExportDefaultClassDeclaration3.ts create mode 100644 tests/cases/compiler/es5ExportDefaultFunctionDeclaration3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3c0bf39f1fa81..cf4049294bb49 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -349,6 +349,13 @@ module ts { } result = undefined; } + else if (location.kind === SyntaxKind.SourceFile) { + result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & SymbolFlags.ModuleMember); + if (result && (result.flags & meaning) && result.valueDeclaration && (result.valueDeclaration.flags & NodeFlags.Default) && result.valueDeclaration.localSymbol.name === name) { + break loop; + } + result = undefined; + } break; case SyntaxKind.EnumDeclaration: if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.EnumMember)) { diff --git a/tests/baselines/reference/es5ExportDefaultClassDeclaration3.js b/tests/baselines/reference/es5ExportDefaultClassDeclaration3.js new file mode 100644 index 0000000000000..bff80940a02cb --- /dev/null +++ b/tests/baselines/reference/es5ExportDefaultClassDeclaration3.js @@ -0,0 +1,35 @@ +//// [es5ExportDefaultClassDeclaration3.ts] + +var before: C = new C(); + +export default class C { + method(): C { + return new C(); + } +} + +var after: C = new C(); + +var t: typeof C = C; + + + +//// [es5ExportDefaultClassDeclaration3.js] +var before = new C(); +var C = (function () { + function C() { + } + C.prototype.method = function () { + return new C(); + }; + return C; +})(); +exports.default = C; +var after = new C(); +var t = C; + + +//// [es5ExportDefaultClassDeclaration3.d.ts] +export default class C { + method(): C; +} diff --git a/tests/baselines/reference/es5ExportDefaultClassDeclaration3.types b/tests/baselines/reference/es5ExportDefaultClassDeclaration3.types new file mode 100644 index 0000000000000..1ed302ac45eb0 --- /dev/null +++ b/tests/baselines/reference/es5ExportDefaultClassDeclaration3.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/es5ExportDefaultClassDeclaration3.ts === + +var before: C = new C(); +>before : C +>C : C +>new C() : C +>C : typeof C + +export default class C { +>C : C + + method(): C { +>method : () => C +>C : C + + return new C(); +>new C() : C +>C : typeof C + } +} + +var after: C = new C(); +>after : C +>C : C +>new C() : C +>C : typeof C + +var t: typeof C = C; +>t : typeof C +>C : typeof C +>C : typeof C + + diff --git a/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.js b/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.js new file mode 100644 index 0000000000000..1fc5797643948 --- /dev/null +++ b/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.js @@ -0,0 +1,21 @@ +//// [es5ExportDefaultFunctionDeclaration3.ts] + +var before: typeof func = func(); + +export default function func(): typeof func { + return func; +} + +var after: typeof func = func(); + +//// [es5ExportDefaultFunctionDeclaration3.js] +var before = func(); +function func() { + return func; +} +exports.default = func; +var after = func(); + + +//// [es5ExportDefaultFunctionDeclaration3.d.ts] +export default function func(): typeof func; diff --git a/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.types b/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.types new file mode 100644 index 0000000000000..d3a8ff92b2f91 --- /dev/null +++ b/tests/baselines/reference/es5ExportDefaultFunctionDeclaration3.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/es5ExportDefaultFunctionDeclaration3.ts === + +var before: typeof func = func(); +>before : () => typeof func +>func : () => typeof func +>func() : () => typeof func +>func : () => typeof func + +export default function func(): typeof func { +>func : () => typeof func +>func : () => typeof func + + return func; +>func : () => typeof func +} + +var after: typeof func = func(); +>after : () => typeof func +>func : () => typeof func +>func() : () => typeof func +>func : () => typeof func + diff --git a/tests/cases/compiler/es5ExportDefaultClassDeclaration3.ts b/tests/cases/compiler/es5ExportDefaultClassDeclaration3.ts new file mode 100644 index 0000000000000..b464e329b8463 --- /dev/null +++ b/tests/cases/compiler/es5ExportDefaultClassDeclaration3.ts @@ -0,0 +1,16 @@ +// @target: es5 +// @module: commonjs +// @declaration: true + +var before: C = new C(); + +export default class C { + method(): C { + return new C(); + } +} + +var after: C = new C(); + +var t: typeof C = C; + diff --git a/tests/cases/compiler/es5ExportDefaultFunctionDeclaration3.ts b/tests/cases/compiler/es5ExportDefaultFunctionDeclaration3.ts new file mode 100644 index 0000000000000..7db21de339ecc --- /dev/null +++ b/tests/cases/compiler/es5ExportDefaultFunctionDeclaration3.ts @@ -0,0 +1,11 @@ +// @target: es5 +// @module: commonjs +// @declaration: true + +var before: typeof func = func(); + +export default function func(): typeof func { + return func; +} + +var after: typeof func = func(); \ No newline at end of file From 383f01dbf6c4f1f8f6d9dfcb9cc119bb8ffd39c6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 30 Mar 2015 20:28:24 -0700 Subject: [PATCH 2/3] Handel export default declaration completions --- src/services/services.ts | 7 ++++++- tests/cases/fourslash/exportDefaultClass.ts | 12 ++++++++++++ tests/cases/fourslash/exportDefaultFunction.ts | 12 ++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/exportDefaultClass.ts create mode 100644 tests/cases/fourslash/exportDefaultFunction.ts diff --git a/src/services/services.ts b/src/services/services.ts index 41ffc04e5aefd..4609c7227869e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2404,6 +2404,11 @@ module ts { return undefined; } + // If this is the default export, get the name of the declaration if it exists + if (displayName === "default" && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) && symbol.valueDeclaration.localSymbol && symbol.valueDeclaration.localSymbol.name) { + displayName = symbol.valueDeclaration.localSymbol.name; + } + let firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { @@ -2620,7 +2625,7 @@ module ts { previousToken.getStart() : position; - let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile); + let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; diff --git a/tests/cases/fourslash/exportDefaultClass.ts b/tests/cases/fourslash/exportDefaultClass.ts new file mode 100644 index 0000000000000..04ab351ab3609 --- /dev/null +++ b/tests/cases/fourslash/exportDefaultClass.ts @@ -0,0 +1,12 @@ +/// + +////export default class C { +//// method() { /*1*/ } +////} +//// /*2*/ + +goTo.marker('1'); +verify.completionListContains("C", "class C", /*documentation*/ undefined, "class"); + +goTo.marker('2'); +verify.completionListContains("C", "class C", /*documentation*/ undefined, "class"); \ No newline at end of file diff --git a/tests/cases/fourslash/exportDefaultFunction.ts b/tests/cases/fourslash/exportDefaultFunction.ts new file mode 100644 index 0000000000000..859d9641acd58 --- /dev/null +++ b/tests/cases/fourslash/exportDefaultFunction.ts @@ -0,0 +1,12 @@ +/// + +////export default function func() { +//// /*1*/ +////} +//// /*2*/ + +goTo.marker('1'); +verify.completionListContains("func", "function func(): void", /*documentation*/ undefined, "function"); + +goTo.marker('2'); +verify.completionListContains("func", "function func(): void", /*documentation*/ undefined, "function"); \ No newline at end of file From 0c5d736251da81caf6e81481b0db9b9eba207662 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 31 Mar 2015 21:17:24 -0700 Subject: [PATCH 3/3] Respond to code review remarks --- src/compiler/checker.ts | 3 ++- src/compiler/utilities.ts | 17 ++++++++++------- src/services/services.ts | 7 +++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cf4049294bb49..73dc52a9b08ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -351,7 +351,8 @@ module ts { } else if (location.kind === SyntaxKind.SourceFile) { result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & SymbolFlags.ModuleMember); - if (result && (result.flags & meaning) && result.valueDeclaration && (result.valueDeclaration.flags & NodeFlags.Default) && result.valueDeclaration.localSymbol.name === name) { + let localSymbol = getLocalSymbolForExportDefault(result); + if (result && (result.flags & meaning) && localSymbol && localSymbol.name === name) { break loop; } result = undefined; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9fa0674c25c07..e9a18254f8e57 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -145,7 +145,7 @@ module ts { return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken; } - + export function nodeIsPresent(node: Node) { return !nodeIsMissing(node); } @@ -288,7 +288,7 @@ module ts { errorNode = (node).name; break; } - + if (errorNode === undefined) { // If we don't have a better node, then just set the error on the first token of // construct. @@ -634,7 +634,7 @@ module ts { return false; } - + export function childIsDecorated(node: Node): boolean { switch (node.kind) { case SyntaxKind.ClassDeclaration: @@ -745,7 +745,7 @@ module ts { export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { let moduleState = getModuleInstanceState(node) return moduleState === ModuleInstanceState.Instantiated || - (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); + (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); } export function isExternalModuleImportEqualsDeclaration(node: Node) { @@ -1161,7 +1161,7 @@ module ts { export function createTextSpanFromBounds(start: number, end: number) { return createTextSpan(start, end - start); } - + export function textChangeRangeNewSpan(range: TextChangeRange) { return createTextSpan(range.span.start, range.newLength); } @@ -1435,13 +1435,13 @@ module ts { return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } } - + function get16BitUnicodeEscapeSequence(charCode: number): string { let hexCharCode = charCode.toString(16).toUpperCase(); let paddedHexCode = ("0000" + hexCharCode).slice(-4); return "\\u" + paddedHexCode; } - + let nonAsciiCharacters = /[^\u0000-\u007F]/g; export function escapeNonAsciiCharacters(s: string): string { // Replace non-ASCII characters with '\uNNNN' escapes if any exist. @@ -1768,4 +1768,7 @@ module ts { } } + export function getLocalSymbolForExportDefault(symbol: Symbol) { + return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined; + } } diff --git a/src/services/services.ts b/src/services/services.ts index 4609c7227869e..0a05191cf6aab 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2405,8 +2405,11 @@ module ts { } // If this is the default export, get the name of the declaration if it exists - if (displayName === "default" && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) && symbol.valueDeclaration.localSymbol && symbol.valueDeclaration.localSymbol.name) { - displayName = symbol.valueDeclaration.localSymbol.name; + if (displayName === "default") { + let localSymbol = getLocalSymbolForExportDefault(symbol); + if (localSymbol && localSymbol.name) { + displayName = symbol.valueDeclaration.localSymbol.name; + } } let firstCharCode = displayName.charCodeAt(0);