From 7b7d2b6006ec510fc391fc1a197647ad3382c622 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Feb 2015 11:54:10 -0800 Subject: [PATCH 1/3] Support navigation bar for new import/export syntax --- src/services/navigationBar.ts | 45 ++++++++++++++++++- .../scriptLexicalStructureExports.ts | 18 ++++++++ .../scriptLexicalStructureImports.ts | 25 +++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/scriptLexicalStructureExports.ts create mode 100644 tests/cases/fourslash/scriptLexicalStructureImports.ts diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index b254397f8b..8bc02d7698 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -50,6 +50,38 @@ module ts.NavigationBar { case SyntaxKind.ArrayBindingPattern: forEach((node).elements, visit); break; + + case SyntaxKind.ExportDeclaration: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; + if ((node).exportClause) { + forEach((node).exportClause.elements, visit); + } + break; + + case SyntaxKind.ImportDeclaration: + var importClause = (node).importClause; + if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + childNodes.push(importClause); + } + + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + if (importClause.namedBindings) { + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { + childNodes.push(importClause.namedBindings); + } + else { + forEach((importClause.namedBindings).elements, visit); + } + } + } + break; + case SyntaxKind.BindingElement: case SyntaxKind.VariableDeclaration: if (isBindingPattern((node).name)) { @@ -62,7 +94,11 @@ module ts.NavigationBar { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ModuleDeclaration: case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: childNodes.push(node); + break; } } @@ -291,9 +327,16 @@ module ts.NavigationBar { else { return createItem(node, getTextOfNode(name), ts.ScriptElementKind.variableElement); } - + case SyntaxKind.Constructor: return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement); + + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.alias); } return undefined; diff --git a/tests/cases/fourslash/scriptLexicalStructureExports.ts b/tests/cases/fourslash/scriptLexicalStructureExports.ts new file mode 100644 index 0000000000..f2a4adfa0d --- /dev/null +++ b/tests/cases/fourslash/scriptLexicalStructureExports.ts @@ -0,0 +1,18 @@ +/// + + +////export { {| "itemName": "a", "kind": "alias", "parentName": "" |}a } from "a"; +//// +////export { {| "itemName": "B", "kind": "alias", "parentName": "" |}b as B } from "a" +//// +////{| "itemName": "e", "kind": "alias", "parentName": "" |} export import e = require("a"); +//// +////export * from "a"; // no bindings here + +test.markers().forEach((marker) => { + if (marker.data) { + verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + } +}); + +verify.getScriptLexicalStructureListCount(4); diff --git a/tests/cases/fourslash/scriptLexicalStructureImports.ts b/tests/cases/fourslash/scriptLexicalStructureImports.ts new file mode 100644 index 0000000000..9d9e3e8b46 --- /dev/null +++ b/tests/cases/fourslash/scriptLexicalStructureImports.ts @@ -0,0 +1,25 @@ +/// + + +////import {| "itemName": "d1", "kind": "alias", "parentName": "" |}d1 from "a"; +//// +////import { {| "itemName": "a", "kind": "alias", "parentName": "" |}a } from "a"; +//// +////import { {| "itemName": "B", "kind": "alias", "parentName": "" |}b as B } from "a" +//// +////import {| "itemName": "d2", "kind": "alias", "parentName": "" |}d2, +//// { {| "itemName": "c", "kind": "alias", "parentName": "" |}c, +//// {| "itemName": "D", "kind": "alias", "parentName": "" |} d as D } from "a" +//// +////{| "itemName": "e", "kind": "alias", "parentName": "" |}import e = require("a"); +//// +////import {| "itemName": "ns", "kind": "alias", "parentName": "" |}* as ns from "a"; + + +test.markers().forEach((marker) => { + if (marker.data) { + verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); + } +}); + +verify.getScriptLexicalStructureListCount(9); From 951f7cf31f977a23d7f893a8e549dd5ecc95498a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Feb 2015 12:24:41 -0800 Subject: [PATCH 2/3] Support navigateTo for new import/export syntax --- src/services/services.ts | 42 +++++++++++++++++++ tests/cases/fourslash/navigateItemsExports.ts | 20 +++++++++ tests/cases/fourslash/navigateItemsImports.ts | 25 +++++++++++ 3 files changed, 87 insertions(+) create mode 100644 tests/cases/fourslash/navigateItemsExports.ts create mode 100644 tests/cases/fourslash/navigateItemsImports.ts diff --git a/src/services/services.ts b/src/services/services.ts index 708869fddf..be515abeb5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -802,6 +802,11 @@ module ts { case SyntaxKind.EnumDeclaration: case SyntaxKind.ModuleDeclaration: case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeLiteral: @@ -841,6 +846,37 @@ module ts { case SyntaxKind.PropertySignature: namedDeclarations.push(node); break; + + case SyntaxKind.ExportDeclaration: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; + if ((node).exportClause) { + forEach((node).exportClause.elements, visit); + } + break; + + case SyntaxKind.ImportDeclaration: + var importClause = (node).importClause; + if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + namedDeclarations.push(importClause); + } + + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + if (importClause.namedBindings) { + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { + namedDeclarations.push(importClause.namedBindings); + } + else { + forEach((importClause.namedBindings).elements, visit); + } + } + } + break; } }); @@ -2010,6 +2046,12 @@ module ts { case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement; case SyntaxKind.EnumMember: return ScriptElementKind.variableElement; case SyntaxKind.Parameter: return (node.flags & NodeFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement; + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportClause: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.NamespaceImport: + return ScriptElementKind.alias; } return ScriptElementKind.unknown; } diff --git a/tests/cases/fourslash/navigateItemsExports.ts b/tests/cases/fourslash/navigateItemsExports.ts new file mode 100644 index 0000000000..646d557aac --- /dev/null +++ b/tests/cases/fourslash/navigateItemsExports.ts @@ -0,0 +1,20 @@ +/// + +////export { {| "itemName": "a", "kind": "alias", "parentName": "" |}a } from "a"; +//// +////export { {| "itemName": "B", "kind": "alias", "parentName": "" |}b as B } from "a"; +//// +////export { {| "itemName": "c", "kind": "alias", "parentName": "" |}c, +//// {| "itemName": "D", "kind": "alias", "parentName": "" |}d as D } from "a"; +//// +////{| "itemName": "f", "kind": "alias", "parentName": "" |}export import f = require("a"); + +test.markers().forEach(marker => { + verify.navigationItemsListContains( + marker.data.itemName, + marker.data.kind, + marker.data.itemName, + "exact", + marker.fileName, + marker.data.parentName); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/navigateItemsImports.ts b/tests/cases/fourslash/navigateItemsImports.ts new file mode 100644 index 0000000000..8ac3e00063 --- /dev/null +++ b/tests/cases/fourslash/navigateItemsImports.ts @@ -0,0 +1,25 @@ +/// + +////import {| "itemName": "ns", "kind": "alias", "parentName": "" |}* as ns from "a"; +//// +////import { {| "itemName": "a", "kind": "alias", "parentName": "" |}a } from "a"; +//// +////import { {| "itemName": "B", "kind": "alias", "parentName": "" |}b as B } from "a"; +//// +////import { {| "itemName": "c", "kind": "alias", "parentName": "" |}c, +//// {| "itemName": "D", "kind": "alias", "parentName": "" |}d as D } from "a"; +//// +////import {| "itemName": "d1", "kind": "alias", "parentName": "" |}d1, { +//// {| "itemName": "e", "kind": "alias", "parentName": "" |}e } from "a"; +//// +////{| "itemName": "f", "kind": "alias", "parentName": "" |}import f = require("a"); + +test.markers().forEach(marker => { + verify.navigationItemsListContains( + marker.data.itemName, + marker.data.kind, + marker.data.itemName, + "exact", + marker.fileName, + marker.data.parentName); +}); \ No newline at end of file From bc4057af858e0a50c4dffab9286eb24cc7114230 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 24 Feb 2015 13:03:14 -0800 Subject: [PATCH 3/3] breakpoint support for new import/export syntax --- src/services/breakpoints.ts | 10 +++++- .../reference/bpSpan_exports.baseline | 17 +++++++++ .../reference/bpSpan_imports.baseline | 35 +++++++++++++++++++ .../fourslash/breakpointValidationExports.ts | 9 +++++ .../fourslash/breakpointValidationImports.ts | 12 +++++++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/bpSpan_exports.baseline create mode 100644 tests/baselines/reference/bpSpan_imports.baseline create mode 100644 tests/cases/fourslash/breakpointValidationExports.ts create mode 100644 tests/cases/fourslash/breakpointValidationImports.ts diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index a4943705e7..59c4e71689 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -178,7 +178,15 @@ module ts.BreakpointResolver { case SyntaxKind.ImportEqualsDeclaration: // import statement without including semicolon - return textSpan(node,(node).moduleReference); + return textSpan(node, (node).moduleReference); + + case SyntaxKind.ImportDeclaration: + // import statement without including semicolon + return textSpan(node, (node).moduleSpecifier); + + case SyntaxKind.ExportDeclaration: + // import statement without including semicolon + return textSpan(node, (node).moduleSpecifier); case SyntaxKind.ModuleDeclaration: // span on complete module if it is instantiated diff --git a/tests/baselines/reference/bpSpan_exports.baseline b/tests/baselines/reference/bpSpan_exports.baseline new file mode 100644 index 0000000000..1b09fb75a2 --- /dev/null +++ b/tests/baselines/reference/bpSpan_exports.baseline @@ -0,0 +1,17 @@ + +1 >export * from "a"; + + ~~~~~~~~~~~~~~~~~~~ => Pos: (0 to 18) SpanInfo: {"start":0,"length":17} + >export * from "a" + >:=> (line 1, col 0) to (line 1, col 17) +-------------------------------- +2 >export {a as A} from "a"; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (19 to 44) SpanInfo: {"start":19,"length":24} + >export {a as A} from "a" + >:=> (line 2, col 0) to (line 2, col 24) +-------------------------------- +3 >export import e = require("a"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (45 to 75) SpanInfo: {"start":45,"length":30} + >export import e = require("a") + >:=> (line 3, col 0) to (line 3, col 30) \ No newline at end of file diff --git a/tests/baselines/reference/bpSpan_imports.baseline b/tests/baselines/reference/bpSpan_imports.baseline new file mode 100644 index 0000000000..c59f9faf90 --- /dev/null +++ b/tests/baselines/reference/bpSpan_imports.baseline @@ -0,0 +1,35 @@ + +1 >import * as NS from "a"; + + ~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (0 to 24) SpanInfo: {"start":0,"length":23} + >import * as NS from "a" + >:=> (line 1, col 0) to (line 1, col 23) +-------------------------------- +2 >import {a as A} from "a"; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (25 to 50) SpanInfo: {"start":25,"length":24} + >import {a as A} from "a" + >:=> (line 2, col 0) to (line 2, col 24) +-------------------------------- +3 > import d from "a"; + + ~~~~~~~~~~~~~~~~~~~~ => Pos: (51 to 70) SpanInfo: {"start":52,"length":17} + >import d from "a" + >:=> (line 3, col 1) to (line 3, col 18) +-------------------------------- +4 >import d2, {c, d as D} from "a"; + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (71 to 103) SpanInfo: {"start":71,"length":31} + >import d2, {c, d as D} from "a" + >:=> (line 4, col 0) to (line 4, col 31) +-------------------------------- +5 >import "a"; + + ~~~~~~~~~~~~ => Pos: (104 to 115) SpanInfo: {"start":104,"length":10} + >import "a" + >:=> (line 5, col 0) to (line 5, col 10) +-------------------------------- +6 >import e = require("a"); + ~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (116 to 139) SpanInfo: {"start":116,"length":23} + >import e = require("a") + >:=> (line 6, col 0) to (line 6, col 23) \ No newline at end of file diff --git a/tests/cases/fourslash/breakpointValidationExports.ts b/tests/cases/fourslash/breakpointValidationExports.ts new file mode 100644 index 0000000000..092d4fdc14 --- /dev/null +++ b/tests/cases/fourslash/breakpointValidationExports.ts @@ -0,0 +1,9 @@ +/// + +// @BaselineFile: bpSpan_exports.baseline +// @Filename: bpSpan_exports.ts +////export * from "a"; +////export {a as A} from "a"; +////export import e = require("a"); + +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file diff --git a/tests/cases/fourslash/breakpointValidationImports.ts b/tests/cases/fourslash/breakpointValidationImports.ts new file mode 100644 index 0000000000..c2ec25a109 --- /dev/null +++ b/tests/cases/fourslash/breakpointValidationImports.ts @@ -0,0 +1,12 @@ +/// + +// @BaselineFile: bpSpan_imports.baseline +// @Filename: bpSpan_imports.ts +////import * as NS from "a"; +////import {a as A} from "a"; +//// import d from "a"; +////import d2, {c, d as D} from "a"; +////import "a"; +////import e = require("a"); + +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file