Skip to content

Commit 46827f4

Browse files
author
Andy
authored
Handle completions at name of namespace declaration (microsoft#25661)
* Handle completions at name of namespace declaration * Handle namespace merging
1 parent 37277e8 commit 46827f4

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

src/services/completions.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,9 @@ namespace ts.Completions {
921921
case SyntaxKind.QualifiedName:
922922
node = (parent as QualifiedName).left;
923923
break;
924+
case SyntaxKind.ModuleDeclaration:
925+
node = (parent as ModuleDeclaration).name;
926+
break;
924927
case SyntaxKind.ImportType:
925928
case SyntaxKind.MetaProperty:
926929
node = parent;
@@ -1062,6 +1065,8 @@ namespace ts.Completions {
10621065
const isRhsOfImportDeclaration = isInRightSideOfInternalImportEqualsDeclaration(node);
10631066
const allowTypeOrValue = isRhsOfImportDeclaration || (!isTypeLocation && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker));
10641067
if (isEntityName(node) || isImportType) {
1068+
const isNamespaceName = isModuleDeclaration(node.parent);
1069+
if (isNamespaceName) isNewIdentifierLocation = true;
10651070
let symbol = typeChecker.getSymbolAtLocation(node);
10661071
if (symbol) {
10671072
symbol = skipAlias(symbol, typeChecker);
@@ -1071,13 +1076,17 @@ namespace ts.Completions {
10711076
const exportedSymbols = Debug.assertEachDefined(typeChecker.getExportsOfModule(symbol), "getExportsOfModule() should all be defined");
10721077
const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess(isImportType ? <ImportTypeNode>node : <PropertyAccessExpression>(node.parent), symbol.name);
10731078
const isValidTypeAccess = (symbol: Symbol) => symbolCanBeReferencedAtTypeLocation(symbol);
1074-
const isValidAccess = allowTypeOrValue ?
1075-
// Any kind is allowed when dotting off namespace in internal import equals declaration
1076-
(symbol: Symbol) => isValidTypeAccess(symbol) || isValidValueAccess(symbol) :
1077-
isTypeLocation ? isValidTypeAccess : isValidValueAccess;
1078-
for (const symbol of exportedSymbols) {
1079-
if (isValidAccess(symbol)) {
1080-
symbols.push(symbol);
1079+
const isValidAccess: (symbol: Symbol) => boolean =
1080+
isNamespaceName
1081+
// At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion.
1082+
? symbol => !!(symbol.flags & SymbolFlags.Namespace) && !symbol.declarations.every(d => d.parent === node.parent)
1083+
: allowTypeOrValue ?
1084+
// Any kind is allowed when dotting off namespace in internal import equals declaration
1085+
symbol => isValidTypeAccess(symbol) || isValidValueAccess(symbol) :
1086+
isTypeLocation ? isValidTypeAccess : isValidValueAccess;
1087+
for (const exportedSymbol of exportedSymbols) {
1088+
if (isValidAccess(exportedSymbol)) {
1089+
symbols.push(exportedSymbol);
10811090
}
10821091
}
10831092

@@ -1461,7 +1470,8 @@ namespace ts.Completions {
14611470
function isNewIdentifierDefinitionLocation(previousToken: Node | undefined): boolean {
14621471
if (previousToken) {
14631472
const containingNodeKind = previousToken.parent.kind;
1464-
switch (previousToken.kind) {
1473+
// Previous token may have been a keyword that was converted to an identifier.
1474+
switch (keywordForNode(previousToken)) {
14651475
case SyntaxKind.CommaToken:
14661476
return containingNodeKind === SyntaxKind.CallExpression // func( a, |
14671477
|| containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */
@@ -1507,14 +1517,6 @@ namespace ts.Completions {
15071517
case SyntaxKind.ProtectedKeyword:
15081518
return containingNodeKind === SyntaxKind.PropertyDeclaration; // class A{ public |
15091519
}
1510-
1511-
// Previous token may have been a keyword that was converted to an identifier.
1512-
switch (keywordForNode(previousToken)) {
1513-
case SyntaxKind.PublicKeyword:
1514-
case SyntaxKind.ProtectedKeyword:
1515-
case SyntaxKind.PrivateKeyword:
1516-
return true;
1517-
}
15181520
}
15191521

15201522
return false;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////{ namespace /*0*/ }
4+
////namespace N/*1*/ {}
5+
////namespace N.M {}
6+
////namespace N./*2*/
7+
////
8+
////namespace N1.M/*3*/ {}
9+
////namespace N2.M {}
10+
////namespace N2.M/*4*/
11+
12+
verify.completions(
13+
{ marker: ["0", "1"], isNewIdentifierLocation: true },
14+
{ marker: "2", exact: ["M"], isNewIdentifierLocation: true },
15+
{ marker: "3", exact: undefined, isNewIdentifierLocation: true },
16+
{ marker: "4", exact: "M", isNewIdentifierLocation: true },
17+
);

0 commit comments

Comments
 (0)