Merge pull request #3757 from Microsoft/noImportClauseBuilders
Don't show builders in import clauses
This commit is contained in:
commit
f2731e4033
|
@ -3010,68 +3010,21 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryGetGlobalSymbols(): boolean {
|
function tryGetGlobalSymbols(): boolean {
|
||||||
let objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
|
let objectLikeContainer: ObjectLiteralExpression | BindingPattern;
|
||||||
let jsxContainer = tryGetContainingJsxElement(contextToken);
|
let importClause: ImportClause;
|
||||||
if (objectLikeContainer) {
|
let jsxContainer: JsxOpeningLikeElement;
|
||||||
// We're looking up possible property names from contextual/inferred/declared type.
|
|
||||||
isMemberCompletion = true;
|
|
||||||
|
|
||||||
let typeForObject: Type;
|
if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) {
|
||||||
let existingMembers: Declaration[];
|
return tryGetObjectLikeCompletionSymbols(objectLikeContainer);
|
||||||
|
|
||||||
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
|
||||||
// We are completing on contextual types, but may also include properties
|
|
||||||
// other than those within the declared type.
|
|
||||||
isNewIdentifierLocation = true;
|
|
||||||
|
|
||||||
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
|
|
||||||
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
|
||||||
}
|
|
||||||
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
|
||||||
// We are *only* completing on properties from the type being destructured.
|
|
||||||
isNewIdentifierLocation = false;
|
|
||||||
|
|
||||||
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
|
||||||
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!typeForObject) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeMembers = typeChecker.getPropertiesOfType(typeForObject);
|
|
||||||
if (typeMembers && typeMembers.length > 0) {
|
|
||||||
// Add filtered items to the completion list
|
|
||||||
symbols = filterObjectMembersList(typeMembers, existingMembers);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (getAncestor(contextToken, SyntaxKind.ImportClause)) {
|
|
||||||
// cursor is in import clause
|
if (importClause = <ImportClause>getAncestor(contextToken, SyntaxKind.ImportClause)) {
|
||||||
|
// cursor is in an import clause
|
||||||
// try to show exported member for imported module
|
// try to show exported member for imported module
|
||||||
isMemberCompletion = true;
|
return tryGetImportClauseCompletionSymbols(importClause);
|
||||||
isNewIdentifierLocation = true;
|
|
||||||
if (showCompletionsInImportsClause(contextToken)) {
|
|
||||||
let importDeclaration = <ImportDeclaration>getAncestor(contextToken, SyntaxKind.ImportDeclaration);
|
|
||||||
Debug.assert(importDeclaration !== undefined);
|
|
||||||
|
|
||||||
let exports: Symbol[];
|
|
||||||
if (importDeclaration.moduleSpecifier) {
|
|
||||||
let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier);
|
|
||||||
if (moduleSpecifierSymbol) {
|
|
||||||
exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration);
|
|
||||||
symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (jsxContainer) {
|
|
||||||
|
if (jsxContainer = tryGetContainingJsxElement(contextToken)) {
|
||||||
let attrsType: Type;
|
let attrsType: Type;
|
||||||
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
|
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
|
||||||
// Cursor is inside a JSX self-closing element or opening element
|
// Cursor is inside a JSX self-closing element or opening element
|
||||||
|
@ -3153,7 +3106,7 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCompletionsInImportsClause(node: Node): boolean {
|
function shouldShowCompletionsInImportsClause(node: Node): boolean {
|
||||||
if (node) {
|
if (node) {
|
||||||
// import {|
|
// import {|
|
||||||
// import {a,|
|
// import {a,|
|
||||||
|
@ -3251,6 +3204,86 @@ namespace ts {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregates relevant symbols for completion in object literals and object binding patterns.
|
||||||
|
* Relevant symbols are stored in the captured 'symbols' variable.
|
||||||
|
*
|
||||||
|
* @returns true if 'symbols' was successfully populated; false otherwise.
|
||||||
|
*/
|
||||||
|
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | BindingPattern): boolean {
|
||||||
|
// We're looking up possible property names from contextual/inferred/declared type.
|
||||||
|
isMemberCompletion = true;
|
||||||
|
|
||||||
|
let typeForObject: Type;
|
||||||
|
let existingMembers: Declaration[];
|
||||||
|
|
||||||
|
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||||
|
// We are completing on contextual types, but may also include properties
|
||||||
|
// other than those within the declared type.
|
||||||
|
isNewIdentifierLocation = true;
|
||||||
|
|
||||||
|
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
|
||||||
|
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
||||||
|
}
|
||||||
|
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
||||||
|
// We are *only* completing on properties from the type being destructured.
|
||||||
|
isNewIdentifierLocation = false;
|
||||||
|
|
||||||
|
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||||
|
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!typeForObject) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeMembers = typeChecker.getPropertiesOfType(typeForObject);
|
||||||
|
if (typeMembers && typeMembers.length > 0) {
|
||||||
|
// Add filtered items to the completion list
|
||||||
|
symbols = filterObjectMembersList(typeMembers, existingMembers);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregates relevant symbols for completion in import clauses; for instance,
|
||||||
|
*
|
||||||
|
* import { $ } from "moduleName";
|
||||||
|
*
|
||||||
|
* Relevant symbols are stored in the captured 'symbols' variable.
|
||||||
|
*
|
||||||
|
* @returns true if 'symbols' was successfully populated; false otherwise.
|
||||||
|
*/
|
||||||
|
function tryGetImportClauseCompletionSymbols(importClause: ImportClause): boolean {
|
||||||
|
// cursor is in import clause
|
||||||
|
// try to show exported member for imported module
|
||||||
|
if (shouldShowCompletionsInImportsClause(contextToken)) {
|
||||||
|
isMemberCompletion = true;
|
||||||
|
isNewIdentifierLocation = false;
|
||||||
|
|
||||||
|
let importDeclaration = <ImportDeclaration>importClause.parent;
|
||||||
|
Debug.assert(importDeclaration !== undefined && importDeclaration.kind === SyntaxKind.ImportDeclaration);
|
||||||
|
|
||||||
|
let exports: Symbol[];
|
||||||
|
let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier);
|
||||||
|
if (moduleSpecifierSymbol) {
|
||||||
|
exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
//let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration);
|
||||||
|
symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isMemberCompletion = false;
|
||||||
|
isNewIdentifierLocation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the immediate owning object literal or binding pattern of a context token,
|
* Returns the immediate owning object literal or binding pattern of a context token,
|
||||||
* on the condition that one exists and that the context implies completion should be given.
|
* on the condition that one exists and that the context implies completion should be given.
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
/// <reference path='fourslash.ts'/>
|
|
||||||
|
|
||||||
// @Filename: m1.ts
|
|
||||||
////export var foo: number = 1;
|
|
||||||
////export function bar() { return 10; }
|
|
||||||
////export function baz() { return 10; }
|
|
||||||
|
|
||||||
// @Filename: m2.ts
|
|
||||||
////import {/*1*/, /*2*/ from "m1"
|
|
||||||
////import {/*3*/} from "m1"
|
|
||||||
////import {foo,/*4*/ from "m1"
|
|
||||||
////import {bar as /*5*/, /*6*/ from "m1"
|
|
||||||
////import {foo, bar, baz as b,/*7*/} from "m1"
|
|
||||||
function verifyCompletionAtMarker(marker: string, ...completions: string[]) {
|
|
||||||
goTo.marker(marker);
|
|
||||||
if (completions.length) {
|
|
||||||
for (var i = 0; i < completions.length; ++i) {
|
|
||||||
verify.completionListContains(completions[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
verify.completionListIsEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCompletionAtMarker("1", "foo", "bar", "baz");
|
|
||||||
verifyCompletionAtMarker("2", "foo", "bar", "baz");
|
|
||||||
verifyCompletionAtMarker("3", "foo", "bar", "baz");
|
|
||||||
verifyCompletionAtMarker("4", "bar", "baz");
|
|
||||||
verifyCompletionAtMarker("5");
|
|
||||||
verifyCompletionAtMarker("6", "foo", "baz");
|
|
||||||
verifyCompletionAtMarker("7");
|
|
39
tests/cases/fourslash/completionListInImportClause01.ts
Normal file
39
tests/cases/fourslash/completionListInImportClause01.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/// <reference path='fourslash.ts'/>
|
||||||
|
|
||||||
|
// @Filename: m1.ts
|
||||||
|
////export var foo: number = 1;
|
||||||
|
////export function bar() { return 10; }
|
||||||
|
////export function baz() { return 10; }
|
||||||
|
|
||||||
|
// @Filename: m2.ts
|
||||||
|
////import {/*1*/, /*2*/ from "m1"
|
||||||
|
////import {/*3*/} from "m1"
|
||||||
|
////import {foo,/*4*/ from "m1"
|
||||||
|
////import {bar as /*5*/, /*6*/ from "m1"
|
||||||
|
////import {foo, bar, baz as b,/*7*/} from "m1"
|
||||||
|
function verifyCompletionAtMarker(marker: string, showBuilder: boolean, ...completions: string[]) {
|
||||||
|
goTo.marker(marker);
|
||||||
|
if (completions.length) {
|
||||||
|
for (let completion of completions) {
|
||||||
|
verify.completionListContains(completion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
verify.completionListIsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showBuilder) {
|
||||||
|
verify.completionListAllowsNewIdentifier();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
verify.not.completionListAllowsNewIdentifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyCompletionAtMarker("1", /*showBuilder*/ false, "foo", "bar", "baz");
|
||||||
|
verifyCompletionAtMarker("2", /*showBuilder*/ false, "foo", "bar", "baz");
|
||||||
|
verifyCompletionAtMarker("3", /*showBuilder*/ false, "foo", "bar", "baz");
|
||||||
|
verifyCompletionAtMarker("4", /*showBuilder*/ false, "bar", "baz");
|
||||||
|
verifyCompletionAtMarker("5", /*showBuilder*/ true);
|
||||||
|
verifyCompletionAtMarker("6", /*showBuilder*/ false, "foo", "baz");
|
||||||
|
verifyCompletionAtMarker("7", /*showBuilder*/ false);
|
13
tests/cases/fourslash/completionListInImportClause02.ts
Normal file
13
tests/cases/fourslash/completionListInImportClause02.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/// <reference path='fourslash.ts'/>
|
||||||
|
|
||||||
|
////declare module "M1" {
|
||||||
|
//// export var V;
|
||||||
|
////}
|
||||||
|
////
|
||||||
|
////declare module "M2" {
|
||||||
|
//// import { /**/ } from "M1"
|
||||||
|
////}
|
||||||
|
|
||||||
|
goTo.marker();
|
||||||
|
verify.completionListContains("V");
|
||||||
|
verify.not.completionListAllowsNewIdentifier();
|
Loading…
Reference in a new issue