Skip to content

Commit da3116c

Browse files
committed
moved fourslash test for PR microsoft#37546 to fourslash native category
review of regex
1 parent f5a8cef commit da3116c

File tree

2 files changed

+108
-7
lines changed

2 files changed

+108
-7
lines changed

src/services/completions.ts

+37-7
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,8 @@ namespace ts.Completions {
831831
// * |c|
832832
// */
833833
const lineStart = getLineStartPositionForPosition(position, sourceFile);
834-
const m = /^(?:[*\s]+|\s*\/\*\*\s+)(@)?$/.exec(
834+
// jsdoc tag will be listed if there is more than one whitespace after "*"
835+
const m = /^(?:\s*(?:[*\s]+(?=\s))?\s+|\s*\/\*\*\s+)(@)?$/.exec(
835836
sourceFile.text.substring(lineStart, position)
836837
);
837838
if (m) {
@@ -1271,6 +1272,7 @@ namespace ts.Completions {
12711272
function tryGetGlobalSymbols(): boolean {
12721273
const result: GlobalsSearch = tryGetObjectLikeCompletionSymbols()
12731274
|| tryGetImportOrExportClauseCompletionSymbols()
1275+
|| tryGetLocalNamedExportCompletionSymbols()
12741276
|| tryGetConstructorCompletion()
12751277
|| tryGetClassLikeCompletionSymbols()
12761278
|| tryGetJsxCompletionSymbols()
@@ -1881,19 +1883,17 @@ namespace ts.Completions {
18811883
* export { | };
18821884
*
18831885
* Relevant symbols are stored in the captured 'symbols' variable.
1884-
*
1885-
* @returns true if 'symbols' was successfully populated; false otherwise.
18861886
*/
18871887
function tryGetImportOrExportClauseCompletionSymbols(): GlobalsSearch {
18881888
// `import { |` or `import { a as 0, | }`
18891889
const namedImportsOrExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
18901890
? tryCast(contextToken.parent, isNamedImportsOrExports) : undefined;
18911891
if (!namedImportsOrExports) return GlobalsSearch.Continue;
18921892

1893-
// cursor is in an import clause
1894-
// try to show exported member for imported module
1893+
// try to show exported member for imported/re-exported module
18951894
const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent;
1896-
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier!); // TODO: GH#18217
1895+
if (!moduleSpecifier) return namedImportsOrExports.kind === SyntaxKind.NamedImports ? GlobalsSearch.Fail : GlobalsSearch.Continue;
1896+
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217
18971897
if (!moduleSpecifierSymbol) return GlobalsSearch.Fail;
18981898

18991899
completionKind = CompletionKind.MemberLike;
@@ -1904,6 +1904,36 @@ namespace ts.Completions {
19041904
return GlobalsSearch.Success;
19051905
}
19061906

1907+
/**
1908+
* Adds local declarations for completions in named exports:
1909+
*
1910+
* export { | };
1911+
*
1912+
* Does not check for the absence of a module specifier (`export {} from "./other"`)
1913+
* because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
1914+
* preventing this function from running.
1915+
*/
1916+
function tryGetLocalNamedExportCompletionSymbols(): GlobalsSearch {
1917+
const namedExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
1918+
? tryCast(contextToken.parent, isNamedExports)
1919+
: undefined;
1920+
1921+
if (!namedExports) {
1922+
return GlobalsSearch.Continue;
1923+
}
1924+
1925+
const localsContainer = findAncestor(namedExports, or(isSourceFile, isModuleDeclaration))!;
1926+
completionKind = CompletionKind.None;
1927+
isNewIdentifierLocation = false;
1928+
localsContainer.locals?.forEach((symbol, name) => {
1929+
symbols.push(symbol);
1930+
if (localsContainer.symbol?.exports?.has(name)) {
1931+
symbolToSortTextMap[getSymbolId(symbol)] = SortText.OptionalMember;
1932+
}
1933+
});
1934+
return GlobalsSearch.Success;
1935+
}
1936+
19071937
/**
19081938
* Aggregates relevant symbols for completion in class declaration
19091939
* Relevant symbols are stored in the captured 'symbols' variable.
@@ -2299,7 +2329,7 @@ namespace ts.Completions {
22992329
}
23002330
}
23012331

2302-
// Set SortText to OptionalMember if it is an optinoal member
2332+
// Set SortText to OptionalMember if it is an optional member
23032333
function setSortTextToOptionalMember() {
23042334
symbols.forEach(m => {
23052335
if (m.flags & SymbolFlags.Optional) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/// <reference path="./fourslash.ts"/>
2+
3+
//
4+
// fourslash test: src/services/completions.ts#getCompletionData (#37546)
5+
//
6+
7+
/////**
8+
//// +/*1*/
9+
//// */
10+
////function a0(s: string) {}
11+
////
12+
13+
/**
14+
*
15+
*/
16+
const jsDocTagNames = [
17+
"abstract", "access", "alias", "argument", "async", "augments", "author", "borrows", "callback", "class",
18+
"classdesc", "constant", "constructor", "constructs", "copyright", "default", "deprecated", "description", "emits", "enum",
19+
"event", "example", "exports", "extends", "external", "field", "file", "fileoverview", "fires", "function",
20+
"generator", "global", "hideconstructor", "host", "ignore", "implements", "inheritdoc", "inner", "instance", "interface",
21+
"kind", "lends", "license", "listens", "member", "memberof", "method", "mixes", "module", "name",
22+
"namespace", "override", "package", "param", "private", "property", "protected", "public", "readonly", "requires",
23+
"returns", "see", "since", "static", "summary", "template", "this", "throws", "todo", "tutorial",
24+
"type", "typedef", "var", "variation", "version", "virtual", "yields"
25+
];
26+
const jsDocTags = jsDocTagNames.map(name => "@" + name);
27+
28+
29+
// ℹ️ line 2: [ +|c|]
30+
verify.completions({
31+
marker: "1",
32+
exact: [] // or undefined
33+
});
34+
35+
// ℹ️ line 2: [ +|c|] -> [ +@|c|]
36+
// before the fix, jsdoc tag names was listed but no longer appears
37+
edit.insert("@");
38+
verify.completions({
39+
marker: "1",
40+
exact: undefined
41+
});
42+
43+
// ℹ️ line 2: [ +@|c|] -> [ *|c|]
44+
// before the fix, jsdoc tags was listed but no longer appears
45+
edit.replaceLine(1, " *");
46+
// goTo.position({ line: 1, character: 2 });
47+
verify.completions({
48+
// marker: "1", // marker is not available
49+
exact: undefined
50+
});
51+
52+
// ℹ️ line 2: [ *|c|] -> [ *@|c|]
53+
// this behavior does not by "hasDocComment" section
54+
edit.insert("@");
55+
verify.completions({
56+
includes: jsDocTagNames
57+
});
58+
59+
// ℹ️ line 2: [ *@|c|] -> [ * |c|]
60+
// jsdoc tags are listed when there is more than one whitespace after "*"
61+
edit.replaceLine(1, " * ");
62+
verify.completions({
63+
includes: jsDocTags
64+
});
65+
66+
// ℹ️ line 2: [ * |c|] -> [ * @|c|]
67+
// jsdoc tag names will be listed
68+
edit.insert("@");
69+
verify.completions({
70+
includes: jsDocTagNames
71+
});

0 commit comments

Comments
 (0)