diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c807406d53..052b39d511 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10292,11 +10292,12 @@ module ts { case SyntaxKind.StringLiteral: // External module name in an import declaration - if (isExternalModuleImportEqualsDeclaration(node.parent.parent) && - getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) { - var importSymbol = getSymbolOfNode(node.parent.parent); - var moduleType = getTypeOfSymbol(importSymbol); - return moduleType ? moduleType.symbol : undefined; + var moduleName: Expression; + if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && + getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || + ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && + (node.parent).moduleSpecifier === node)) { + return resolveExternalModuleName(node, node); } // Intentional fall-through diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c5bb46aa96..b53c000724 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -745,6 +745,12 @@ module ts { } var parent = name.parent; + if (parent.kind === SyntaxKind.ImportSpecifier || parent.kind === SyntaxKind.ExportSpecifier) { + if ((parent).propertyName) { + return true; + } + } + if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) { return (parent).name === name; } 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/navigationBar.ts b/src/services/navigationBar.ts index e32ac03cae..90c639287c 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 0b23b134bc..58c1d08110 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; } @@ -3292,6 +3334,17 @@ module ts { return undefined; } + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directelly. + if (symbol.flags & SymbolFlags.Import) { + var declaration = symbol.declarations[0]; + if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { + symbol = typeInfoResolver.getAliasedSymbol(symbol); + } + } + var result: DefinitionInfo[] = []; // Because name in short-hand property assignment has two different meanings: property name and property value, @@ -4022,7 +4075,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). @@ -4039,7 +4092,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(); @@ -4059,13 +4112,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); @@ -4094,16 +4185,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; } @@ -4458,6 +4555,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 @@ -4534,6 +4636,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 @@ -4744,12 +4853,18 @@ module ts { case SyntaxKind.NamedImports: case SyntaxKind.ImportSpecifier: case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace; // An external module can be a Value case SyntaxKind.SourceFile: return SemanticMeaning.Namespace | SemanticMeaning.Value; } + + return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace; + Debug.fail("Unknown declaration type"); } 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/baselines/reference/es6ImportNamedImport.types b/tests/baselines/reference/es6ImportNamedImport.types index e86955b3c9..cb06c9918e 100644 --- a/tests/baselines/reference/es6ImportNamedImport.types +++ b/tests/baselines/reference/es6ImportNamedImport.types @@ -23,16 +23,16 @@ import { a } from "es6ImportNamedImport_0"; >a : number import { a as b } from "es6ImportNamedImport_0"; ->a : unknown +>a : number >b : number import { x, a as y } from "es6ImportNamedImport_0"; >x : number ->a : unknown +>a : number >y : number import { x as z, } from "es6ImportNamedImport_0"; ->x : unknown +>x : number >z : number import { m, } from "es6ImportNamedImport_0"; @@ -43,8 +43,8 @@ import { a1, x1 } from "es6ImportNamedImport_0"; >x1 : number import { a1 as a11, x1 as x11 } from "es6ImportNamedImport_0"; ->a1 : unknown +>a1 : number >a11 : number ->x1 : unknown +>x1 : number >x11 : number diff --git a/tests/baselines/reference/es6ImportNamedImportInEs5.types b/tests/baselines/reference/es6ImportNamedImportInEs5.types index 4f96b8a4df..334ae905e9 100644 --- a/tests/baselines/reference/es6ImportNamedImportInEs5.types +++ b/tests/baselines/reference/es6ImportNamedImportInEs5.types @@ -23,16 +23,16 @@ import { a } from "es6ImportNamedImportInEs5_0"; >a : number import { a as b } from "es6ImportNamedImportInEs5_0"; ->a : unknown +>a : number >b : number import { x, a as y } from "es6ImportNamedImportInEs5_0"; >x : number ->a : unknown +>a : number >y : number import { x as z, } from "es6ImportNamedImportInEs5_0"; ->x : unknown +>x : number >z : number import { m, } from "es6ImportNamedImportInEs5_0"; @@ -43,8 +43,8 @@ import { a1, x1 } from "es6ImportNamedImportInEs5_0"; >x1 : number import { a1 as a11, x1 as x11 } from "es6ImportNamedImportInEs5_0"; ->a1 : unknown +>a1 : number >a11 : number ->x1 : unknown +>x1 : number >x11 : number 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/goToDefinitionExternamModuleName6.ts b/tests/cases/fourslash/goToDefinitionExternamModuleName6.ts new file mode 100644 index 0000000000..46cafbb806 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionExternamModuleName6.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: b.ts +////import * from 'e/*1*/'; + +// @Filename: a.ts +/////*2*/declare module "e" { +//// class Foo { } +////} + +goTo.marker('1'); +goTo.definition(); +verify.caretAtMarker('2'); \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionExternamModuleName7.ts b/tests/cases/fourslash/goToDefinitionExternamModuleName7.ts new file mode 100644 index 0000000000..dcaf4b1f02 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionExternamModuleName7.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: b.ts +////import {Foo, Bar} from 'e/*1*/'; + +// @Filename: a.ts +/////*2*/declare module "e" { +//// class Foo { } +////} + +goTo.marker('1'); +goTo.definition(); +verify.caretAtMarker('2'); \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionExternamModuleName8.ts b/tests/cases/fourslash/goToDefinitionExternamModuleName8.ts new file mode 100644 index 0000000000..03c36567dc --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionExternamModuleName8.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: b.ts +////export {Foo, Bar} from 'e/*1*/'; + +// @Filename: a.ts +/////*2*/declare module "e" { +//// class Foo { } +////} + +goTo.marker('1'); +goTo.definition(); +verify.caretAtMarker('2'); \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionExternamModuleName9.ts b/tests/cases/fourslash/goToDefinitionExternamModuleName9.ts new file mode 100644 index 0000000000..43111c6763 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionExternamModuleName9.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: b.ts +////export * from 'e/*1*/'; + +// @Filename: a.ts +/////*2*/declare module "e" { +//// class Foo { } +////} + +goTo.marker('1'); +goTo.definition(); +verify.caretAtMarker('2'); \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionImportedNames.ts b/tests/cases/fourslash/goToDefinitionImportedNames.ts new file mode 100644 index 0000000000..64eb2df96b --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: b.ts +////export {/*classAliasDefinition*/Class} from "a"; + + +// @Filename: a.ts +////export module Module { +////} +/////*classDefinition*/export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("b.ts"); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames2.ts b/tests/cases/fourslash/goToDefinitionImportedNames2.ts new file mode 100644 index 0000000000..8533dad62a --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames2.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: b.ts +////import {/*classAliasDefinition*/Class} from "a"; + + +// @Filename: a.ts +////export module Module { +////} +/////*classDefinition*/export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("b.ts"); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames3.ts b/tests/cases/fourslash/goToDefinitionImportedNames3.ts new file mode 100644 index 0000000000..d55137575e --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames3.ts @@ -0,0 +1,38 @@ +/// + +// @Filename: e.ts +//// import {M, /*classAliasDefinition*/C, I} from "d"; +//// var c = new /*classReference*/C(); + + +// @Filename: d.ts +////export * from "c"; + + +// @Filename: c.ts +////export {Module as M, Class as C, Interface as I} from "b"; + + +// @Filename: b.ts +////export * from "a"; + + +// @Filename: a.ts +////export module Module { +////} +/////*classDefinition*/export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("e.ts"); + +goTo.marker('classReference'); +goTo.definition(); +verify.caretAtMarker('classAliasDefinition'); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames4.ts b/tests/cases/fourslash/goToDefinitionImportedNames4.ts new file mode 100644 index 0000000000..cce49af874 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames4.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: b.ts +////import {Class as /*classAliasDefinition*/ClassAlias} from "a"; + + +// @Filename: a.ts +////export module Module { +////} +/////*classDefinition*/export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("b.ts"); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames5.ts b/tests/cases/fourslash/goToDefinitionImportedNames5.ts new file mode 100644 index 0000000000..46a8c45e27 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames5.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: b.ts +////export {Class as /*classAliasDefinition*/ClassAlias} from "a"; + + +// @Filename: a.ts +////export module Module { +////} +/////*classDefinition*/export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("b.ts"); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames6.ts b/tests/cases/fourslash/goToDefinitionImportedNames6.ts new file mode 100644 index 0000000000..27b6c55d10 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames6.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: b.ts +////import /*moduleAliasDefinition*/alias = require("a"); + + +// @Filename: a.ts +/////*moduleDefinition*/export module Module { +////} +////export class Class { +//// private f; +////} +////export interface Interface { +//// x; +////} + +goTo.file("b.ts"); + +goTo.marker('moduleAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('moduleDefinition'); diff --git a/tests/cases/fourslash/goToDefinitionImportedNames7.ts b/tests/cases/fourslash/goToDefinitionImportedNames7.ts new file mode 100644 index 0000000000..46d09012d4 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionImportedNames7.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: b.ts +////import /*classAliasDefinition*/defaultExport from "a"; + + +// @Filename: a.ts +/////*classDefinition*/class Class { +//// private f; +////} +////export = Class; + +goTo.file("b.ts"); + +goTo.marker('classAliasDefinition'); +goTo.definition(); +verify.caretAtMarker('classDefinition'); 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);