mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-07 05:41:22 -06:00
parent
3214ab380c
commit
ddab2dd308
@ -20,7 +20,8 @@ namespace ts.Completions {
|
||||
None,
|
||||
ClassElementKeywords, // Keywords at class keyword
|
||||
ConstructorParameterKeywords, // Keywords at constructor parameter
|
||||
FunctionLikeBodyKeywords // Keywords at function like body
|
||||
FunctionLikeBodyKeywords, // Keywords at function like body
|
||||
TypeKeywords,
|
||||
}
|
||||
|
||||
export function getCompletionsAtPosition(
|
||||
@ -565,7 +566,7 @@ namespace ts.Completions {
|
||||
}
|
||||
case "none": {
|
||||
// Didn't find a symbol with this name. See if we can find a keyword instead.
|
||||
if (some(getKeywordCompletions(KeywordCompletionFilters.None), c => c.name === name)) {
|
||||
if (allKeywordsCompletions().some(c => c.name === name)) {
|
||||
return {
|
||||
name,
|
||||
kind: ScriptElementKind.keyword,
|
||||
@ -1163,6 +1164,9 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function filterGlobalCompletion(symbols: Symbol[]): void {
|
||||
const isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
|
||||
if (isTypeCompletion) keywordFilters = KeywordCompletionFilters.TypeKeywords;
|
||||
|
||||
filterMutate(symbols, symbol => {
|
||||
if (!isSourceFile(location)) {
|
||||
// export = /**/ here we want to get all meanings, so any symbol is ok
|
||||
@ -1170,19 +1174,14 @@ namespace ts.Completions {
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is an alias, follow what it aliases
|
||||
if (symbol && symbol.flags & SymbolFlags.Alias) {
|
||||
symbol = typeChecker.getAliasedSymbol(symbol);
|
||||
}
|
||||
symbol = skipAlias(symbol, typeChecker);
|
||||
|
||||
// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
|
||||
if (isInRightSideOfInternalImportEqualsDeclaration(location)) {
|
||||
return !!(symbol.flags & SymbolFlags.Namespace);
|
||||
}
|
||||
|
||||
if (insideJsDocTagTypeExpression ||
|
||||
(!isContextTokenValueLocation(contextToken) &&
|
||||
(isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) {
|
||||
if (isTypeCompletion) {
|
||||
// Its a type, but you can reach it by namespace.type as well
|
||||
return symbolCanBeReferencedAtTypeLocation(symbol);
|
||||
}
|
||||
@ -1199,7 +1198,7 @@ namespace ts.Completions {
|
||||
contextToken.parent.kind === SyntaxKind.TypeQuery;
|
||||
}
|
||||
|
||||
function isContextTokenTypeLocation(contextToken: Node) {
|
||||
function isContextTokenTypeLocation(contextToken: Node): boolean {
|
||||
if (contextToken) {
|
||||
const parentKind = contextToken.parent.kind;
|
||||
switch (contextToken.kind) {
|
||||
@ -1217,6 +1216,7 @@ namespace ts.Completions {
|
||||
return parentKind === SyntaxKind.AsExpression;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function symbolCanBeReferencedAtTypeLocation(symbol: Symbol): boolean {
|
||||
@ -2130,51 +2130,38 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
// A cache of completion entries for keywords, these do not change between sessions
|
||||
const _keywordCompletions: CompletionEntry[][] = [];
|
||||
function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): CompletionEntry[] {
|
||||
const completions = _keywordCompletions[keywordFilter];
|
||||
if (completions) {
|
||||
return completions;
|
||||
const _keywordCompletions: ReadonlyArray<CompletionEntry>[] = [];
|
||||
const allKeywordsCompletions: () => ReadonlyArray<CompletionEntry> = ts.memoize(() => {
|
||||
const res: CompletionEntry[] = [];
|
||||
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
|
||||
res.push({
|
||||
name: tokenToString(i),
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
sortText: "0"
|
||||
});
|
||||
}
|
||||
return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter);
|
||||
|
||||
type FilterKeywordCompletions = (entryName: string) => boolean;
|
||||
function generateKeywordCompletions(keywordFilter: KeywordCompletionFilters): CompletionEntry[] {
|
||||
return res;
|
||||
});
|
||||
function getKeywordCompletions(keywordFilter: KeywordCompletionFilters): ReadonlyArray<CompletionEntry> {
|
||||
return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => {
|
||||
const kind = stringToToken(entry.name);
|
||||
switch (keywordFilter) {
|
||||
case KeywordCompletionFilters.None:
|
||||
return getAllKeywordCompletions();
|
||||
// "undefined" is a global variable, so don't need a keyword completion for it.
|
||||
return kind !== SyntaxKind.UndefinedKeyword;
|
||||
case KeywordCompletionFilters.ClassElementKeywords:
|
||||
return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText);
|
||||
return isClassMemberCompletionKeyword(kind);
|
||||
case KeywordCompletionFilters.ConstructorParameterKeywords:
|
||||
return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText);
|
||||
return isConstructorParameterCompletionKeyword(kind);
|
||||
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
|
||||
return getFilteredKeywordCompletions(isFunctionLikeBodyCompletionKeywordText);
|
||||
return isFunctionLikeBodyCompletionKeyword(kind);
|
||||
case KeywordCompletionFilters.TypeKeywords:
|
||||
return isTypeKeyword(kind);
|
||||
default:
|
||||
Debug.assertNever(keywordFilter);
|
||||
return Debug.assertNever(keywordFilter);
|
||||
}
|
||||
}
|
||||
|
||||
function getAllKeywordCompletions() {
|
||||
const allKeywordsCompletions: CompletionEntry[] = [];
|
||||
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
|
||||
// "undefined" is a global variable, so don't need a keyword completion for it.
|
||||
if (i === SyntaxKind.UndefinedKeyword) continue;
|
||||
allKeywordsCompletions.push({
|
||||
name: tokenToString(i),
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
sortText: "0"
|
||||
});
|
||||
}
|
||||
return allKeywordsCompletions;
|
||||
}
|
||||
|
||||
function getFilteredKeywordCompletions(filterFn: FilterKeywordCompletions) {
|
||||
return filter(
|
||||
getKeywordCompletions(KeywordCompletionFilters.None),
|
||||
entry => filterFn(entry.name)
|
||||
);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function isClassMemberCompletionKeyword(kind: SyntaxKind) {
|
||||
@ -2222,15 +2209,12 @@ namespace ts.Completions {
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
case SyntaxKind.GetKeyword:
|
||||
case SyntaxKind.SetKeyword:
|
||||
case SyntaxKind.UndefinedKeyword:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isFunctionLikeBodyCompletionKeywordText(text: string) {
|
||||
return isFunctionLikeBodyCompletionKeyword(stringToToken(text));
|
||||
}
|
||||
|
||||
function isEqualityOperatorKind(kind: ts.SyntaxKind): kind is EqualityOperator {
|
||||
switch (kind) {
|
||||
case ts.SyntaxKind.EqualsEqualsEqualsToken:
|
||||
|
||||
@ -1070,12 +1070,16 @@ namespace ts {
|
||||
export const typeKeywords: ReadonlyArray<SyntaxKind> = [
|
||||
SyntaxKind.AnyKeyword,
|
||||
SyntaxKind.BooleanKeyword,
|
||||
SyntaxKind.KeyOfKeyword,
|
||||
SyntaxKind.NeverKeyword,
|
||||
SyntaxKind.NullKeyword,
|
||||
SyntaxKind.NumberKeyword,
|
||||
SyntaxKind.ObjectKeyword,
|
||||
SyntaxKind.StringKeyword,
|
||||
SyntaxKind.SymbolKeyword,
|
||||
SyntaxKind.VoidKeyword,
|
||||
SyntaxKind.UndefinedKeyword,
|
||||
SyntaxKind.UniqueKeyword,
|
||||
];
|
||||
|
||||
export function isTypeKeyword(kind: SyntaxKind): boolean {
|
||||
|
||||
7
tests/cases/fourslash/completionsTypeKeywords.ts
Normal file
7
tests/cases/fourslash/completionsTypeKeywords.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////type T = /**/
|
||||
|
||||
goTo.marker();
|
||||
verify.completionListContains("undefined", "undefined", undefined, "keyword");
|
||||
verify.not.completionListContains("await");
|
||||
Loading…
x
Reference in New Issue
Block a user