From 5e59eece34bd7c5197e7ca9bbd41eaeb1b66172f Mon Sep 17 00:00:00 2001 From: Orta Date: Wed, 22 Jan 2020 08:13:04 -0500 Subject: [PATCH] Adds support for showing default exports in the navtree (#35477) * Adds support for showing default exports in the navtree - Fixes #34601 * Handle the feedback in #35477 * Navigation items using default export or export = will get noted if they are a const vs function --- src/harness/fourslashImpl.ts | 6 +-- src/services/navigationBar.ts | 6 ++- src/services/utilities.ts | 5 +++ .../completionsImport_default_anonymous.ts | 1 + ...sImport_default_exportDefaultIdentifier.ts | 16 ++++---- ...ompletionsImport_exportEquals_anonymous.ts | 1 + .../navigationItemsExportDefaultExpression.ts | 39 ++++++++++++++++++ .../navigationItemsExportEqualsExpression.ts | 40 +++++++++++++++++++ 8 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 tests/cases/fourslash/navigationItemsExportDefaultExpression.ts create mode 100644 tests/cases/fourslash/navigationItemsExportEqualsExpression.ts diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index b3437e811b..ea6ccd68fb 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -860,10 +860,10 @@ namespace FourSlash { if (kind !== undefined || kindModifiers !== undefined) { if (actual.kind !== kind) { - this.raiseError(`Unexpected kind for ${actual.name}: Expected ${kind}, actual ${actual.kind}`); + this.raiseError(`Unexpected kind for ${actual.name}: Expected '${kind}', actual '${actual.kind}'`); } if (actual.kindModifiers !== (kindModifiers || "")) { - this.raiseError(`Bad kind modifiers for ${actual.name}: Expected ${kindModifiers || ""}, actual ${actual.kindModifiers}`); + this.raiseError(`Bad kindModifiers for ${actual.name}: Expected ${kindModifiers || ""}, actual ${actual.kindModifiers}`); } } @@ -2873,7 +2873,7 @@ namespace FourSlash { private verifyNavigationTreeOrBar(json: any, tree: any, name: "Tree" | "Bar", options: { checkSpans?: boolean } | undefined) { if (JSON.stringify(tree, replacer) !== JSON.stringify(json)) { - this.raiseError(`verifyNavigation${name} failed - expected: ${stringify(json)}, got: ${stringify(tree, replacer)}`); + this.raiseError(`verifyNavigation${name} failed - \n${showTextDiff(stringify(json), stringify(tree, replacer))}`); } function replacer(key: string, value: any) { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 650496bfbc..38faf25da7 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -17,7 +17,7 @@ namespace ts.NavigationBar { /** * Maximum amount of characters to return - * The amount was choosen arbitrarily. + * The amount was chosen arbitrarily. */ const maxLength = 150; @@ -307,6 +307,7 @@ namespace ts.NavigationBar { addNodeWithRecursiveChild(node, getInteriorModule(node).body); break; + case SyntaxKind.ExportAssignment: case SyntaxKind.ExportSpecifier: case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.IndexSignature: @@ -681,6 +682,9 @@ namespace ts.NavigationBar { return isExternalModule(sourceFile) ? `"${escapeString(getBaseFileName(removeFileExtension(normalizePath(sourceFile.fileName))))}"` : ""; + case SyntaxKind.ExportAssignment: + return isExportAssignment(node) && node.isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; + case SyntaxKind.ArrowFunction: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9d52fcf88b..9c4b58bf0b 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -438,6 +438,10 @@ namespace ts { } case SyntaxKind.Identifier: return isImportClause(node.parent) ? ScriptElementKind.alias : ScriptElementKind.unknown; + case SyntaxKind.ExportAssignment: + const scriptKind = getNodeKind((node as ExportAssignment).expression); + // If the expression didn't come back with something (like it does for an identifiers) + return scriptKind === ScriptElementKind.unknown ? ScriptElementKind.constElement : scriptKind; default: return ScriptElementKind.unknown; } @@ -1154,6 +1158,7 @@ namespace ts { if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier); if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); if (node.flags & NodeFlags.Ambient) result.push(ScriptElementKindModifier.ambientModifier); + if (node.kind === SyntaxKind.ExportAssignment) result.push(ScriptElementKindModifier.exportedModifier); return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none; } diff --git a/tests/cases/fourslash/completionsImport_default_anonymous.ts b/tests/cases/fourslash/completionsImport_default_anonymous.ts index 80ad6494dc..e3506d1e94 100644 --- a/tests/cases/fourslash/completionsImport_default_anonymous.ts +++ b/tests/cases/fourslash/completionsImport_default_anonymous.ts @@ -31,6 +31,7 @@ verify.completions( sourceDisplay: "./foo-bar", text: "(property) default: 0", kind: "property", + kindModifiers: "export", hasAction: true, sortText: completion.SortText.AutoImportSuggestions }, diff --git a/tests/cases/fourslash/completionsImport_default_exportDefaultIdentifier.ts b/tests/cases/fourslash/completionsImport_default_exportDefaultIdentifier.ts index ea332cd7ff..c9f58870a7 100644 --- a/tests/cases/fourslash/completionsImport_default_exportDefaultIdentifier.ts +++ b/tests/cases/fourslash/completionsImport_default_exportDefaultIdentifier.ts @@ -15,16 +15,18 @@ goTo.marker(""); verify.completions({ marker: "", includes: { - name: "foo", - source: "/a", - sourceDisplay: "./a", - text: "(alias) const foo: 0\nexport default foo", - kind: "alias", - hasAction: true, - sortText: completion.SortText.AutoImportSuggestions + name: "foo", + source: "/a", + sourceDisplay: "./a", + text: "(alias) const foo: 0\nexport default foo", + kind: "alias", + kindModifiers: "export", + hasAction: true, + sortText: completion.SortText.AutoImportSuggestions }, preferences: { includeCompletionsForModuleExports: true }, }); + verify.applyCodeActionFromCompletion("", { name: "foo", source: "/a", diff --git a/tests/cases/fourslash/completionsImport_exportEquals_anonymous.ts b/tests/cases/fourslash/completionsImport_exportEquals_anonymous.ts index e8d675cba8..6c80b652a9 100644 --- a/tests/cases/fourslash/completionsImport_exportEquals_anonymous.ts +++ b/tests/cases/fourslash/completionsImport_exportEquals_anonymous.ts @@ -18,6 +18,7 @@ const exportEntry: FourSlashInterface.ExpectedCompletionEntryObject = { sourceDisplay: "./foo-bar", text: "(property) export=: 0", kind: "property", + kindModifiers: "export", hasAction: true, sortText: completion.SortText.AutoImportSuggestions }; diff --git a/tests/cases/fourslash/navigationItemsExportDefaultExpression.ts b/tests/cases/fourslash/navigationItemsExportDefaultExpression.ts new file mode 100644 index 0000000000..6425fd4bf7 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsExportDefaultExpression.ts @@ -0,0 +1,39 @@ +/// + +//// const abc = 12; +//// export default function () {} +//// export default () => "" +//// export default abc; +//// export default class AB {} + +verify.navigationTree({ + "text": '"navigationItemsExportDefaultExpression"', + "kind": "module", + "childItems": [ + { + "text": "default", + "kind": "function", + "kindModifiers": "export" + }, + { + "text": "default", + "kind": "function", + "kindModifiers": "export" + }, + { + "text": "AB", + "kind": "class", + "kindModifiers": "export" + }, + { + "text": "abc", + "kind": "const" + }, + { + "text": "default", + "kind": "const", + "kindModifiers": "export" + } + ] +}); + diff --git a/tests/cases/fourslash/navigationItemsExportEqualsExpression.ts b/tests/cases/fourslash/navigationItemsExportEqualsExpression.ts new file mode 100644 index 0000000000..053a1fa002 --- /dev/null +++ b/tests/cases/fourslash/navigationItemsExportEqualsExpression.ts @@ -0,0 +1,40 @@ +// 35477 +/// + +//// const abc = 12; +//// export = abc; +//// export = function () {} +//// export = () => "" +//// export = class AB {} + +verify.navigationTree({ + "text": '"navigationItemsExportEqualsExpression"', + "kind": "module", + "childItems": [ + { + "text": "export=", + "kind": "function", + "kindModifiers": "export" + }, + { + "text": "export=", + "kind": "function", + "kindModifiers": "export" + }, + { + "text": "export=", + "kind": "class", + "kindModifiers": "export" + }, + { + "text": "abc", + "kind": "const" + }, + { + "text": "export=", + "kind": "const", + "kindModifiers": "export" + } + ] +}); +