diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9e56c58411930..67599bccd2aba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -672,9 +672,9 @@ namespace ts { return moduleSpecifier && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true); }, resolveExternalModuleSymbol, - tryGetThisTypeAt: (nodeIn, includeGlobalThis) => { + tryGetThisTypeAt: (nodeIn, includeGlobalThis, container) => { const node = getParseTreeNode(nodeIn); - return node && tryGetThisTypeAt(node, includeGlobalThis); + return node && tryGetThisTypeAt(node, includeGlobalThis, container); }, getTypeArgumentConstraint: nodeIn => { const node = getParseTreeNode(nodeIn, isTypeNode); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a6121cddb6096..8e12a47c9f03c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4597,7 +4597,7 @@ namespace ts { */ /* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol; /** @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression. */ - /* @internal */ tryGetThisTypeAt(node: Node, includeGlobalThis?: boolean): Type | undefined; + /* @internal */ tryGetThisTypeAt(node: Node, includeGlobalThis?: boolean, container?: Node): Type | undefined; /* @internal */ getTypeArgumentConstraint(node: TypeNode): Type | undefined; /** diff --git a/src/services/completions.ts b/src/services/completions.ts index 2f6b940f7cf7d..9e5ae92726972 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2616,7 +2616,7 @@ namespace ts.Completions { // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== SyntaxKind.SourceFile) { - const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false); + const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, isClassLike(scopeNode.parent) ? scopeNode : undefined); if (thisType && !isProbablyGlobalType(thisType, sourceFile, typeChecker)) { for (const symbol of getPropertiesForCompletion(thisType, typeChecker)) { symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.ThisType }; diff --git a/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration1.ts b/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration1.ts new file mode 100644 index 0000000000000..5de5f9abbae5a --- /dev/null +++ b/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration1.ts @@ -0,0 +1,28 @@ +/// + +////class Foo { +//// private _prop = 1; +//// public a = [|_/*1*/|] +//// +//// foo() { +//// [|_/*2*/|] +//// } +////} + +verify.completions({ + marker: ["1", "2"], + includes: [ + { + name: "_prop", + insertText: "this._prop", + kind: "property", + sortText: completion.SortText.SuggestedClassMembers, + source: completion.CompletionSource.ThisProperty, + text: "(property) Foo._prop: number", + kindModifiers: "private" + }, + ], + preferences: { + includeInsertTextCompletions: true + } +}); diff --git a/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration2.ts b/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration2.ts new file mode 100644 index 0000000000000..824b5f2855a62 --- /dev/null +++ b/tests/cases/fourslash/completionsThisPropertiesInPropertyDeclaration2.ts @@ -0,0 +1,28 @@ +/// + +////class Foo { +//// private static _prop = 1; +//// public static a = [|_/*1*/|] +//// +//// static foo() { +//// [|_/*2*/|] +//// } +////} + +verify.completions({ + marker: ["2"], + includes: [ + { + name: "_prop", + insertText: "this._prop", + kind: "property", + sortText: completion.SortText.SuggestedClassMembers, + source: completion.CompletionSource.ThisProperty, + text: "(property) Foo._prop: number", + kindModifiers: "private,static" + }, + ], + preferences: { + includeInsertTextCompletions: true + } +});