Add assert keyword in completions (#47644)

* add contextual keyword assert in completions

* clean up
This commit is contained in:
Gabriela Araujo Britto 2022-01-27 21:17:43 -03:00 committed by GitHub
parent f2c51c10f5
commit 90280518ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 2 deletions

View File

@ -288,7 +288,7 @@ namespace ts.Completions {
switch (completionData.kind) {
case CompletionDataKind.Data:
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext);
const response = completionInfoFromData(sourceFile, host, program, compilerOptions, log, completionData, preferences, formatContext, position);
if (response?.isIncomplete) {
incompleteCompletionsCache?.set(response);
}
@ -452,6 +452,7 @@ namespace ts.Completions {
completionData: CompletionData,
preferences: UserPreferences,
formatContext: formatting.FormatContext | undefined,
position: number
): CompletionInfo | undefined {
const {
symbols,
@ -512,7 +513,7 @@ namespace ts.Completions {
isJsxIdentifierExpected,
isRightOfOpenTag,
);
getJSCompletionEntries(sourceFile, location.pos, uniqueNames, getEmitScriptTarget(compilerOptions), entries); // TODO: GH#18217
getJSCompletionEntries(sourceFile, location.pos, uniqueNames, getEmitScriptTarget(compilerOptions), entries);
}
else {
if (!isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) {
@ -556,6 +557,13 @@ namespace ts.Completions {
}
}
const entryNames = new Set(entries.map(e => e.name));
for (const keywordEntry of getContextualKeywords(contextToken, position)) {
if (!entryNames.has(keywordEntry.name)) {
insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true);
}
}
for (const literal of literals) {
insertSorted(entries, createCompletionEntryForLiteral(sourceFile, preferences, literal), compareCompletionEntries, /*allowDuplicates*/ true);
}
@ -3630,6 +3638,38 @@ namespace ts.Completions {
return isIdentifier(node) ? node.originalKeywordKind || SyntaxKind.Unknown : node.kind;
}
function getContextualKeywords(
contextToken: Node | undefined,
position: number,
): readonly CompletionEntry[] {
const entries = [];
/**
* An `AssertClause` can come after an import declaration:
* import * from "foo" |
* import "foo" |
* or after a re-export declaration that has a module specifier:
* export { foo } from "foo" |
* Source: https://tc39.es/proposal-import-assertions/
*/
if (contextToken) {
const file = contextToken.getSourceFile();
const parent = contextToken.parent;
const tokenLine = file.getLineAndCharacterOfPosition(contextToken.end).line;
const currentLine = file.getLineAndCharacterOfPosition(position).line;
if ((isImportDeclaration(parent) || isExportDeclaration(parent) && parent.moduleSpecifier)
&& contextToken === parent.moduleSpecifier
&& tokenLine === currentLine) {
entries.push({
name: tokenToString(SyntaxKind.AssertKeyword)!,
kind: ScriptElementKind.keyword,
kindModifiers: ScriptElementKindModifier.none,
sortText: SortText.GlobalsOrKeywords,
});
}
}
return entries;
}
/** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined {
return findAncestor(node, n =>

View File

@ -0,0 +1,54 @@
/// <reference path="fourslash.ts" />
// @allowJs: true
// @Filename: a.ts
//// const f = {
//// a: 1
////};
//// import * as thing from "thing" /*0*/
//// export { foo } from "foo" /*1*/
//// import "foo" as /*2*/
//// import "foo" a/*3*/
//// import * as that from "that"
//// /*4*/
//// import * /*5*/ as those from "those"
// @Filename: b.js
//// import * as thing from "thing" /*js*/;
const assertEntry = {
name: "assert",
kind: "keyword",
sortText: completion.SortText.GlobalsOrKeywords,
};
verify.completions(
{
marker: "0",
includes: [assertEntry],
},
{
marker: "1",
includes: [assertEntry],
},
{
marker: "2",
excludes: ["assert"],
},
{
marker: "3",
includes: [assertEntry],
},
{
marker: "4",
excludes: ["assert"],
},
{
marker: "5",
excludes: ["assert"],
},
{
marker: "js",
includes: [assertEntry],
},
);