mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 10:41:56 -05:00
Refactor tryGetGlobalSymbols into list of things to try (#22704)
* Refactor `tryGetGlobalSymbols` into list of things to try * Refactor to `||` expression
This commit is contained in:
@@ -24,6 +24,8 @@ namespace ts.Completions {
|
||||
TypeKeywords,
|
||||
}
|
||||
|
||||
const enum GlobalsSearch { Continue, Success, Fail }
|
||||
|
||||
export function getCompletionsAtPosition(
|
||||
host: LanguageServiceHost,
|
||||
typeChecker: TypeChecker,
|
||||
@@ -1046,52 +1048,38 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function tryGetGlobalSymbols(): boolean {
|
||||
let objectLikeContainer: ObjectLiteralExpression | BindingPattern;
|
||||
let namedImportsOrExports: NamedImportsOrExports;
|
||||
let classLikeContainer: ClassLikeDeclaration;
|
||||
let jsxContainer: JsxOpeningLikeElement;
|
||||
const result: GlobalsSearch = tryGetObjectLikeCompletionSymbols()
|
||||
|| tryGetImportOrExportClauseCompletionSymbols()
|
||||
|| tryGetConstructorCompletion()
|
||||
|| tryGetClassLikeCompletionSymbols()
|
||||
|| tryGetJsxCompletionSymbols()
|
||||
|| (getGlobalCompletions(), GlobalsSearch.Success);
|
||||
return result === GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) {
|
||||
return tryGetObjectLikeCompletionSymbols(objectLikeContainer);
|
||||
}
|
||||
function tryGetConstructorCompletion(): GlobalsSearch {
|
||||
if (!tryGetConstructorLikeCompletionContainer(contextToken)) return GlobalsSearch.Continue;
|
||||
// no members, only keywords
|
||||
completionKind = CompletionKind.None;
|
||||
// Declaring new property/method/accessor
|
||||
isNewIdentifierLocation = true;
|
||||
// Has keywords for constructor parameter
|
||||
keywordFilters = KeywordCompletionFilters.ConstructorParameterKeywords;
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) {
|
||||
// cursor is in an import clause
|
||||
// try to show exported member for imported module
|
||||
return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports);
|
||||
}
|
||||
|
||||
if (tryGetConstructorLikeCompletionContainer(contextToken)) {
|
||||
// no members, only keywords
|
||||
completionKind = CompletionKind.None;
|
||||
// Declaring new property/method/accessor
|
||||
isNewIdentifierLocation = true;
|
||||
// Has keywords for constructor parameter
|
||||
keywordFilters = KeywordCompletionFilters.ConstructorParameterKeywords;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (classLikeContainer = tryGetClassLikeCompletionContainer(contextToken)) {
|
||||
// cursor inside class declaration
|
||||
getGetClassLikeCompletionSymbols(classLikeContainer);
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
|
||||
|
||||
if (attrsType) {
|
||||
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties);
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
function tryGetJsxCompletionSymbols(): GlobalsSearch {
|
||||
const jsxContainer = tryGetContainingJsxElement(contextToken);
|
||||
// Cursor is inside a JSX self-closing element or opening element
|
||||
const attrsType = jsxContainer && typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
|
||||
if (!attrsType) return GlobalsSearch.Continue;
|
||||
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties);
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
function getGlobalCompletions(): void {
|
||||
if (tryGetFunctionLikeBodyCompletionContainer(contextToken)) {
|
||||
keywordFilters = KeywordCompletionFilters.FunctionLikeBodyKeywords;
|
||||
}
|
||||
@@ -1155,8 +1143,6 @@ namespace ts.Completions {
|
||||
getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", target);
|
||||
}
|
||||
filterGlobalCompletion(symbols);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isSnippetScope(scopeNode: Node): boolean {
|
||||
@@ -1434,7 +1420,10 @@ namespace ts.Completions {
|
||||
*
|
||||
* @returns true if 'symbols' was successfully populated; false otherwise.
|
||||
*/
|
||||
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | ObjectBindingPattern): boolean {
|
||||
function tryGetObjectLikeCompletionSymbols(): GlobalsSearch | undefined {
|
||||
const objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
|
||||
if (!objectLikeContainer) return GlobalsSearch.Continue;
|
||||
|
||||
// We're looking up possible property names from contextual/inferred/declared type.
|
||||
completionKind = CompletionKind.ObjectPropertyDeclaration;
|
||||
|
||||
@@ -1446,7 +1435,7 @@ namespace ts.Completions {
|
||||
// other than those within the declared type.
|
||||
isNewIdentifierLocation = true;
|
||||
const typeForObject = typeChecker.getContextualType(objectLikeContainer);
|
||||
if (!typeForObject) return false;
|
||||
if (!typeForObject) return GlobalsSearch.Fail;
|
||||
typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false);
|
||||
existingMembers = objectLikeContainer.properties;
|
||||
}
|
||||
@@ -1474,7 +1463,7 @@ namespace ts.Completions {
|
||||
}
|
||||
if (canGetType) {
|
||||
const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
if (!typeForObject) return false;
|
||||
if (!typeForObject) return GlobalsSearch.Fail;
|
||||
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
|
||||
typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter((symbol) => !(getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.NonPublicAccessibilityModifier));
|
||||
existingMembers = objectLikeContainer.elements;
|
||||
@@ -1485,7 +1474,7 @@ namespace ts.Completions {
|
||||
// Add filtered items to the completion list
|
||||
symbols = filterObjectMembersList(typeMembers, Debug.assertDefined(existingMembers));
|
||||
}
|
||||
return true;
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1503,7 +1492,12 @@ namespace ts.Completions {
|
||||
*
|
||||
* @returns true if 'symbols' was successfully populated; false otherwise.
|
||||
*/
|
||||
function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean {
|
||||
function tryGetImportOrExportClauseCompletionSymbols(): GlobalsSearch {
|
||||
const namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken);
|
||||
if (!namedImportsOrExports) return undefined;
|
||||
|
||||
// cursor is in an import clause
|
||||
// try to show exported member for imported module
|
||||
const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ?
|
||||
SyntaxKind.ImportDeclaration :
|
||||
SyntaxKind.ExportDeclaration;
|
||||
@@ -1511,7 +1505,7 @@ namespace ts.Completions {
|
||||
const moduleSpecifier = importOrExportDeclaration.moduleSpecifier;
|
||||
|
||||
if (!moduleSpecifier) {
|
||||
return false;
|
||||
return GlobalsSearch.Fail;
|
||||
}
|
||||
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
@@ -1520,19 +1514,22 @@ namespace ts.Completions {
|
||||
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
|
||||
if (!moduleSpecifierSymbol) {
|
||||
symbols = emptyArray;
|
||||
return true;
|
||||
return GlobalsSearch.Fail;
|
||||
}
|
||||
|
||||
const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
|
||||
symbols = filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements);
|
||||
return true;
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregates relevant symbols for completion in class declaration
|
||||
* Relevant symbols are stored in the captured 'symbols' variable.
|
||||
*/
|
||||
function getGetClassLikeCompletionSymbols(classLikeDeclaration: ClassLikeDeclaration) {
|
||||
function tryGetClassLikeCompletionSymbols(): GlobalsSearch {
|
||||
const classLikeDeclaration = tryGetClassLikeCompletionContainer(contextToken);
|
||||
if (!classLikeDeclaration) return GlobalsSearch.Continue;
|
||||
|
||||
// We're looking up possible property names from parent type.
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
// Declaring new property/method/accessor
|
||||
@@ -1582,6 +1579,7 @@ namespace ts.Completions {
|
||||
classElementModifierFlags);
|
||||
}
|
||||
}
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user