diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2659263215829..c9564927f5e3d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -349,6 +349,14 @@ module ts { } result = undefined; } + else if (location.kind === SyntaxKind.SourceFile) { + result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & SymbolFlags.ModuleMember); + let localSymbol = getLocalSymbolForExportDefault(result); + if (result && (result.flags & meaning) && localSymbol && localSymbol.name === name) { + break loop; + } + result = undefined; + } break; case SyntaxKind.EnumDeclaration: if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.EnumMember)) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a30462594b6df..1deb9ce97e258 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); } @@ -296,7 +296,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. @@ -642,7 +642,7 @@ module ts { return false; } - + export function childIsDecorated(node: Node): boolean { switch (node.kind) { case SyntaxKind.ClassDeclaration: @@ -754,7 +754,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) { @@ -1170,7 +1170,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); } @@ -1444,13 +1444,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. @@ -1799,4 +1799,8 @@ module ts { return (node.parent.kind === SyntaxKind.QualifiedName && (node.parent).right === node) || (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node); } + + 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 55ebc30bfe59f..7492c0cf98b26 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2459,6 +2459,14 @@ module ts { return undefined; } + // If this is the default export, get the name of the declaration if it exists + if (displayName === "default") { + let localSymbol = getLocalSymbolForExportDefault(symbol); + if (localSymbol && 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)) { @@ -2675,7 +2683,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/baselines/reference/APISample_linter.types.pull b/tests/baselines/reference/APISample_linter.types.pull index 759a8390d608c..e2a29716fcc9f 100644 --- a/tests/baselines/reference/APISample_linter.types.pull +++ b/tests/baselines/reference/APISample_linter.types.pull @@ -4984,6 +4984,27 @@ declare module "typescript" { >CompilerHost : CompilerHost >Program : Program } +declare module "typescript" { + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ + function readConfigFile(fileName: string): any; +>readConfigFile : (fileName: string) => any +>fileName : string + + /** + * Parse the contents of a config file (tsconfig.json). + * @param json The contents of the config file to parse + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ + function parseConfigFile(json: any, basePath?: string): ParsedCommandLine; +>parseConfigFile : (json: any, basePath?: string) => ParsedCommandLine +>json : any +>basePath : string +>ParsedCommandLine : ParsedCommandLine +} declare module "typescript" { /** The version of the language service API */ let servicesVersion: string; 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 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