diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 33d4008885d..68011b586f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4508,8 +4508,21 @@ module ts { } else { error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target); - return resolveErrorCall(node); } + + // No signature was applicable. We have already reported the errors for the invalid signature. + // If this is a type resolution session, e.g. Language Service, try to get better information that anySignature. + // Pick the first candidate that matches the arity. This way we can get a contextual type for cases like: + // declare function f(a: { xa: number; xb: number; }); + // f({ | + if (!fullTypeCheck) { + for (var i = 0, n = candidates.length; i < n; i++) { + if (signatureHasCorrectArity(node, candidates[i])) { + return candidates[i]; + } + } + } + return resolveErrorCall(node); // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order diff --git a/src/compiler/types.ts b/src/compiler/types.ts index da2cb9099c2..ee6ad334b3d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1204,7 +1204,8 @@ module ts { } public static toString(parts: SymbolDisplayPart[]) { - return parts.map(p => p.text).join(""); + var result = map(parts, p => p.text); + return result ? result.join("") : ""; } } diff --git a/src/services/services.ts b/src/services/services.ts index 703a05c62cb..e2663d5455e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2162,9 +2162,16 @@ module ts { } // TODO: this is a hack for now, we need a proper walking mechanism to verify that we have the correct node - var mappedNode = getTouchingToken(sourceFile, TypeScript.end(node) - 1); - if (isPunctuation(mappedNode.kind)) { - mappedNode = mappedNode.parent; + var precedingToken = findTokenOnLeftOfPosition(sourceFile, TypeScript.end(node)); + var mappedNode: Node; + if (!precedingToken) { + mappedNode = sourceFile; + } + else if (isPunctuation(precedingToken.kind)) { + mappedNode = precedingToken.parent; + } + else { + mappedNode = precedingToken; } Debug.assert(mappedNode, "Could not map a Fidelity node to an AST node"); diff --git a/tests/cases/fourslash/completionListInObjectLiteralThatIsParameterOfFunctionCall.ts b/tests/cases/fourslash/completionListInObjectLiteralThatIsParameterOfFunctionCall.ts new file mode 100644 index 00000000000..9dcf7456226 --- /dev/null +++ b/tests/cases/fourslash/completionListInObjectLiteralThatIsParameterOfFunctionCall.ts @@ -0,0 +1,11 @@ +/// + +////function f(a: { xa: number; xb: number; }) { } +////var xc; +////f({ +//// /**/ + +goTo.marker() +verify.memberListContains('xa'); +verify.memberListContains('xb'); +verify.memberListCount(2); \ No newline at end of file