Merge pull request #3757 from Microsoft/noImportClauseBuilders

Don't show builders in import clauses
This commit is contained in:
Daniel Rosenwasser 2015-07-07 14:45:39 -07:00
commit f2731e4033
4 changed files with 144 additions and 91 deletions

View file

@ -3010,68 +3010,21 @@ namespace ts {
}
function tryGetGlobalSymbols(): boolean {
let objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
let jsxContainer = tryGetContainingJsxElement(contextToken);
if (objectLikeContainer) {
// We're looking up possible property names from contextual/inferred/declared type.
isMemberCompletion = true;
let objectLikeContainer: ObjectLiteralExpression | BindingPattern;
let importClause: ImportClause;
let jsxContainer: JsxOpeningLikeElement;
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;
if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) {
return tryGetObjectLikeCompletionSymbols(objectLikeContainer);
}
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
isMemberCompletion = true;
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;
return tryGetImportClauseCompletionSymbols(importClause);
}
else if (jsxContainer) {
if (jsxContainer = tryGetContainingJsxElement(contextToken)) {
let attrsType: Type;
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
// Cursor is inside a JSX self-closing element or opening element
@ -3153,7 +3106,7 @@ namespace ts {
return result;
}
function showCompletionsInImportsClause(node: Node): boolean {
function shouldShowCompletionsInImportsClause(node: Node): boolean {
if (node) {
// import {|
// import {a,|
@ -3251,6 +3204,86 @@ namespace ts {
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,
* on the condition that one exists and that the context implies completion should be given.

View file

@ -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");

View 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);

View 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();