diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts
index 54447417a2a49..954cd1da9e1bf 100644
--- a/src/services/signatureHelp.ts
+++ b/src/services/signatureHelp.ts
@@ -120,14 +120,22 @@ namespace ts.SignatureHelp {
if (argumentInfo.invocation.kind === InvocationKind.Contextual) return undefined;
// See if we can find some symbol with the call expression name that has call signatures.
const expression = getExpressionFromInvocation(argumentInfo.invocation);
- const name = isIdentifier(expression) ? expression.text : isPropertyAccessExpression(expression) ? expression.name.text : undefined;
+ const name = isPropertyAccessExpression(expression) ? expression.name.text : undefined;
const typeChecker = program.getTypeChecker();
return name === undefined ? undefined : firstDefined(program.getSourceFiles(), sourceFile =>
firstDefined(sourceFile.getNamedDeclarations().get(name), declaration => {
const type = declaration.symbol && typeChecker.getTypeOfSymbolAtLocation(declaration.symbol, declaration);
const callSignatures = type && type.getCallSignatures();
if (callSignatures && callSignatures.length) {
- return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, sourceFile, typeChecker));
+ return typeChecker.runWithCancellationToken(
+ cancellationToken,
+ typeChecker => createSignatureHelpItems(
+ callSignatures,
+ callSignatures[0],
+ argumentInfo,
+ sourceFile,
+ typeChecker,
+ /*useFullPrefix*/ true));
}
}));
}
@@ -496,10 +504,11 @@ namespace ts.SignatureHelp {
{ isTypeParameterList, argumentCount, argumentsSpan: applicableSpan, invocation, argumentIndex }: ArgumentListInfo,
sourceFile: SourceFile,
typeChecker: TypeChecker,
+ useFullPrefix?: boolean,
): SignatureHelpItems {
const enclosingDeclaration = getEnclosingDeclarationFromInvocation(invocation);
- const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol : typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation));
- const callTargetDisplayParts = callTargetSymbol ? symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : emptyArray;
+ const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol : (typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)) || useFullPrefix && resolvedSignature.declaration?.symbol);
+ const callTargetDisplayParts = callTargetSymbol ? symbolToDisplayParts(typeChecker, callTargetSymbol, useFullPrefix ? sourceFile : undefined, /*meaning*/ undefined) : emptyArray;
const items = map(candidates, candidateSignature => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile));
if (argumentIndex !== 0) {
diff --git a/tests/cases/fourslash/signatureHelpJSMissingIdentifier.ts b/tests/cases/fourslash/signatureHelpJSMissingIdentifier.ts
new file mode 100644
index 0000000000000..73b22459d6303
--- /dev/null
+++ b/tests/cases/fourslash/signatureHelpJSMissingIdentifier.ts
@@ -0,0 +1,9 @@
+///
+
+// @allowJs: true
+// @checkJs: true
+
+// @Filename: test.js
+////log(/**/)
+
+verify.noSignatureHelp("");
diff --git a/tests/cases/fourslash/signatureHelpJSMissingPropertyAccess.ts b/tests/cases/fourslash/signatureHelpJSMissingPropertyAccess.ts
new file mode 100644
index 0000000000000..1c1cf427528b0
--- /dev/null
+++ b/tests/cases/fourslash/signatureHelpJSMissingPropertyAccess.ts
@@ -0,0 +1,19 @@
+///
+
+// @allowJs: true
+// @checkJs: true
+
+// @Filename: test.js
+////foo.filter(/**/)
+
+goTo.marker("");
+verify.signatureHelp({
+ text: "ReadonlyArray.filter(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[]",
+ overloadsCount: 2,
+ docComment: "Returns the elements of an array that meet the condition specified in a callback function.",
+ parameterDocComment: "A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.",
+ tags: [
+ { name: "param", text: "predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array." },
+ { name: "param", text: "thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value." }
+ ]
+});