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/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index e64e29d280..c9c1833522 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -35,9 +35,13 @@ module ts.formatting { // Space after keyword but not before ; or : or ? public NoSpaceBeforeSemicolon: Rule; public NoSpaceBeforeColon: Rule; - public NoSpaceBeforeQMark: Rule; + public NoSpaceBeforeQuestionMark: Rule; public SpaceAfterColon: Rule; - public SpaceAfterQMark: Rule; + // insert space after '?' only when it is used in conditional operator + public SpaceAfterQuestionMarkInConditionalOperator: Rule; + // in other cases there should be no space between '?' and next token + public NoSpaceAfterQuestionMark: Rule; + public SpaceAfterSemicolon: Rule; // Space/new line after }. @@ -215,9 +219,10 @@ module ts.formatting { // Space after keyword but not before ; or : or ? this.NoSpaceBeforeSemicolon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeColon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.ColonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - this.NoSpaceBeforeQMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); + this.NoSpaceBeforeQuestionMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); this.SpaceAfterColon = new Rule(RuleDescriptor.create3(SyntaxKind.ColonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space)); - this.SpaceAfterQMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space)); + this.SpaceAfterQuestionMarkInConditionalOperator = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), RuleAction.Space)); + this.NoSpaceAfterQuestionMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.SpaceAfterSemicolon = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); // Space after }. @@ -341,7 +346,8 @@ module ts.formatting { this.HighPriorityCommonRules = [ this.IgnoreBeforeComment, this.IgnoreAfterLineComment, - this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQMark, this.SpaceAfterQMark, + this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, + this.NoSpaceAfterQuestionMark, this.NoSpaceBeforeDot, this.NoSpaceAfterDot, this.NoSpaceAfterUnaryPrefixOperator, this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, @@ -475,6 +481,10 @@ module ts.formatting { return !Rules.IsBinaryOpContext(context); } + static IsConditionalOperatorContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConditionalExpression; + } + static IsSameLineTokenOrBeforeMultilineBlockContext(context: FormattingContext): boolean { //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. //// 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/src/services/services.ts b/src/services/services.ts index db6a09c1a7..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; } @@ -3986,7 +4028,7 @@ module ts { var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for, we need to normalize it as external module names will have quote - var declaredName = getDeclaredName(symbol); + var declaredName = getDeclaredName(symbol, node); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). @@ -4003,7 +4045,7 @@ module ts { getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); } else { - var internedName = getInternedName(symbol, declarations) + var internedName = getInternedName(symbol, node, declarations) forEach(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); @@ -4023,13 +4065,51 @@ module ts { return result; - function getDeclaredName(symbol: Symbol) { + function isImportOrExportSpecifierName(location: Node): boolean { + return location.parent && + (location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) && + (location.parent).propertyName === location; + } + + function isImportOrExportSpecifierImportSymbol(symbol: Symbol) { + return (symbol.flags & SymbolFlags.Import) && forEach(symbol.declarations, declaration => { + return declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ExportSpecifier; + }); + } + + function getDeclaredName(symbol: Symbol, location: Node) { + // Special case for function expressions, whose names are solely local to their bodies. + var functionExpression = forEach(symbol.declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined); + + // When a name gets interned into a SourceFile's 'identifiers' Map, + // its name is escaped and stored in the same way its symbol name/identifier + // name should be stored. Function expressions, however, are a special case, + // because despite sometimes having a name, the binder unconditionally binds them + // to a symbol with the name "__function". + if (functionExpression && functionExpression.name) { + var name = functionExpression.name.text; + } + + // If this is an export or import specifier it could have been renamed using the as syntax. + // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name) + // so check for the propertyName. + if (isImportOrExportSpecifierName(location)) { + return location.getText(); + } + var name = typeInfoResolver.symbolToString(symbol); return stripQuotes(name); } - function getInternedName(symbol: Symbol, declarations: Declaration[]): string { + function getInternedName(symbol: Symbol, location: Node, declarations: Declaration[]): string { + // If this is an export or import specifier it could have been renamed using the as syntax. + // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name) + // so check for the propertyName. + if (isImportOrExportSpecifierName(location)) { + return location.getText(); + } + // Special case for function expressions, whose names are solely local to their bodies. var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined); @@ -4058,16 +4138,22 @@ module ts { function getSymbolScope(symbol: Symbol): Node { // If this is private property or method, the scope is the containing class - if (symbol.getFlags() && (SymbolFlags.Property | SymbolFlags.Method)) { + if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { var privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } } + // If the symbol is an import we would like to find it if we are looking for what it imports. + // So consider it visibile outside its declaration scope. + if (symbol.flags & SymbolFlags.Import) { + return undefined; + } + // if this symbol is visible from its parent container, e.g. exported, then bail out // if symbol correspond to the union property - bail out - if (symbol.parent || (symbol.getFlags() & SymbolFlags.UnionProperty)) { + if (symbol.parent || (symbol.flags & SymbolFlags.UnionProperty)) { return undefined; } @@ -4422,6 +4508,11 @@ module ts { // The search set contains at least the current symbol var result = [symbol]; + // If the symbol is an alias, add what it alaises to the list + if (isImportOrExportSpecifierImportSymbol(symbol)) { + result.push(typeInfoResolver.getAliasedSymbol(symbol)); + } + // If the location is in a context sensitive location (i.e. in an object literal) try // to get a contextual type for it, and add the property symbol from the contextual // type to the search set @@ -4498,6 +4589,13 @@ module ts { return true; } + // If the reference symbol is an alias, check if what it is aliasing is one of the search + // symbols. + if (isImportOrExportSpecifierImportSymbol(referenceSymbol) && + searchSymbols.indexOf(typeInfoResolver.getAliasedSymbol(referenceSymbol)) >= 0) { + return true; + } + // If the reference location is in an object literal, try to get the contextual type for the // object literal, lookup the property symbol in the contextual type, and use this symbol to // compare to our searchSymbol 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 diff --git a/tests/cases/fourslash/findAllRefsOnImportAliases.ts b/tests/cases/fourslash/findAllRefsOnImportAliases.ts new file mode 100644 index 0000000000..dbfab33aa8 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsOnImportAliases.ts @@ -0,0 +1,29 @@ +/// + +//@Filename: a.ts +////export class /*1*/Class{ +////} + +//@Filename: b.ts +////import { /*2*/Class } from "a"; +//// +////var c = new /*3*/Class(); + +//@Filename: c.ts +////export { /*4*/Class } from "a"; + +goTo.file("a.ts"); +goTo.marker("1"); +verify.referencesCountIs(4); + +goTo.file("b.ts"); +goTo.marker("2"); +verify.referencesCountIs(4); + +goTo.marker("3"); +verify.referencesCountIs(4); + +goTo.file("c.ts"); +goTo.marker("4"); +verify.referencesCountIs(4); + diff --git a/tests/cases/fourslash/findAllRefsOnImportAliases2.ts b/tests/cases/fourslash/findAllRefsOnImportAliases2.ts new file mode 100644 index 0000000000..dca6b13bbd --- /dev/null +++ b/tests/cases/fourslash/findAllRefsOnImportAliases2.ts @@ -0,0 +1,31 @@ +/// + +//@Filename: a.ts +////export class /*1*/Class{ +////} + +//@Filename: b.ts +////import { /*2*/Class as /*3*/C2} from "a"; +//// +////var c = new C2(); + +//@Filename: c.ts +////export { /*4*/Class as /*5*/C3 } from "a"; + +goTo.file("a.ts"); +goTo.marker("1"); +verify.referencesCountIs(3); + +goTo.file("b.ts"); +goTo.marker("2"); +verify.referencesCountIs(3); + +goTo.marker("3"); +verify.referencesCountIs(2); + +goTo.file("c.ts"); +goTo.marker("4"); +verify.referencesCountIs(3); + +goTo.marker("5"); +verify.referencesCountIs(1); diff --git a/tests/cases/fourslash/formattingConditionalOperator.ts b/tests/cases/fourslash/formattingConditionalOperator.ts new file mode 100644 index 0000000000..545adb572b --- /dev/null +++ b/tests/cases/fourslash/formattingConditionalOperator.ts @@ -0,0 +1,6 @@ +/// + +////var x=true?1:2 +format.document(); +goTo.bof(); +verify.currentLineContentIs("var x = true ? 1 : 2");; \ No newline at end of file diff --git a/tests/cases/fourslash/formattingQMark.ts b/tests/cases/fourslash/formattingQMark.ts new file mode 100644 index 0000000000..83ca56a49f --- /dev/null +++ b/tests/cases/fourslash/formattingQMark.ts @@ -0,0 +1,12 @@ +/// + +////interface A { +/////*1*/ foo? (); +/////*2*/ foo? (); +////} + +format.document(); +goTo.marker("1"); +verify.currentLineContentIs(" foo?();"); +goTo.marker("2"); +verify.currentLineContentIs(" foo?();"); \ No newline at end of file diff --git a/tests/cases/fourslash/genericsFormatting.ts b/tests/cases/fourslash/genericsFormatting.ts index f6f1426316..36833cadd1 100644 --- a/tests/cases/fourslash/genericsFormatting.ts +++ b/tests/cases/fourslash/genericsFormatting.ts @@ -30,4 +30,4 @@ goTo.marker("inNewSignature"); verify.currentLineContentIs(" new (a: T);"); goTo.marker("inOptionalMethodSignature"); -verify.currentLineContentIs(" op? (a: T, b: M);"); \ No newline at end of file +verify.currentLineContentIs(" op?(a: T, b: M);"); \ No newline at end of file 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 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);