From e2c5a90cc3bcbc0ea78e13bf0f5b889a2aed8248 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Tue, 30 Jun 2020 14:25:27 -0700 Subject: [PATCH] Disable signature help on unresolved bare identifiers; add more declaration info on other unresolved calls (#39352) * Disable signature help on unresolved bare identifiers; add more declaration info on unresolvedproperty access * Remove stray ts-ignore --- src/services/signatureHelp.ts | 17 +++++++++++++---- .../signatureHelpJSMissingIdentifier.ts | 9 +++++++++ .../signatureHelpJSMissingPropertyAccess.ts | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpJSMissingIdentifier.ts create mode 100644 tests/cases/fourslash/signatureHelpJSMissingPropertyAccess.ts diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 54447417a2..954cd1da9e 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 0000000000..73b22459d6 --- /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 0000000000..1c1cf42752 --- /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." } + ] +});