Skip to content

Commit 44434a3

Browse files
committed
Revert "Ugghhghgh"
This reverts commit cad98b9.
1 parent cad98b9 commit 44434a3

File tree

6 files changed

+66
-68
lines changed

6 files changed

+66
-68
lines changed

src/compiler/checker.ts

+45-41
Original file line numberDiff line numberDiff line change
@@ -532,13 +532,26 @@ namespace ts {
532532
if (!node) {
533533
return undefined;
534534
}
535-
if (contextFlags! & ContextFlags.Completions) {
536-
return runWithInferenceBlockedFromSourceNode(node, /*stop*/ undefined, () => getContextualType(node, contextFlags));
535+
const containingCall = findAncestor(node, isCallLikeExpression);
536+
const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
537+
if (contextFlags! & ContextFlags.Completions && containingCall) {
538+
let toMarkSkip = node as Node;
539+
do {
540+
getNodeLinks(toMarkSkip).skipDirectInference = true;
541+
toMarkSkip = toMarkSkip.parent;
542+
} while (toMarkSkip && toMarkSkip !== containingCall);
543+
getNodeLinks(containingCall).resolvedSignature = undefined;
544+
}
545+
const result = getContextualType(node, contextFlags);
546+
if (contextFlags! & ContextFlags.Completions && containingCall) {
547+
let toMarkSkip = node as Node;
548+
do {
549+
getNodeLinks(toMarkSkip).skipDirectInference = undefined;
550+
toMarkSkip = toMarkSkip.parent;
551+
} while (toMarkSkip && toMarkSkip !== containingCall);
552+
getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
537553
}
538-
return getContextualType(node, contextFlags);
539-
},
540-
getContextualTypeForCompletions: (nodeIn: Expression, editingNodeIn: Node) => {
541-
return runWithInferenceBlockedFromSourceNode(editingNodeIn, editingNodeIn, () => getContextualType(nodeIn, ContextFlags.Completions));
554+
return result;
542555
},
543556
getContextualTypeForObjectLiteralElement: nodeIn => {
544557
const node = getParseTreeNode(nodeIn, isObjectLiteralElementLike);
@@ -728,42 +741,33 @@ namespace ts {
728741
getMemberOverrideModifierStatus,
729742
};
730743

731-
function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, stop: Node | undefined, fn: () => T): T {
732-
const containingCall = findAncestor(stop || node, isCallLikeExpression);
733-
const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
734-
if (containingCall) {
735-
let toMarkSkip = node!;
736-
do {
737-
getNodeLinks(toMarkSkip).skipDirectInference = true;
738-
toMarkSkip = toMarkSkip.parent;
739-
} while (toMarkSkip && toMarkSkip !== (stop || containingCall));
740-
getNodeLinks(containingCall).resolvedSignature = undefined;
741-
}
742-
const result = fn();
743-
if (containingCall) {
744-
let toMarkSkip = node!;
745-
do {
746-
getNodeLinks(toMarkSkip).skipDirectInference = undefined;
747-
toMarkSkip = toMarkSkip.parent;
748-
} while (toMarkSkip && toMarkSkip !== (stop || containingCall));
749-
getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
750-
}
751-
return result;
752-
}
753-
754744
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, argumentIndex?: number): Signature | undefined {
755-
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
756-
let res;
757-
apparentArgumentCount = argumentCount;
745+
let node = getParseTreeNode(nodeIn, isCallLikeExpression);
758746
if (node && argumentIndex !== undefined) {
759-
const editingArgument =
760-
tryCast(node, isCallOrNewExpression)?.arguments?.[argumentIndex] ||
761-
tryCast(node, isJsxOpeningLikeElement)?.attributes?.properties[argumentIndex];
762-
res = runWithInferenceBlockedFromSourceNode(editingArgument, /*stop*/ undefined, () => getResolvedSignature(node, candidatesOutArray, checkMode));
763-
}
764-
else {
765-
res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined;
747+
const replacementArg = setParentRecursive(factory.createAsExpression(factory.createStringLiteral(""), factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword)), /*incremental*/ false);
748+
switch (node.kind) {
749+
case SyntaxKind.CallExpression:
750+
node = factory.updateCallExpression(node, node.expression, node.typeArguments, [
751+
...node.arguments.slice(0, argumentIndex),
752+
replacementArg,
753+
...node.arguments.slice(argumentIndex + 1),
754+
]);
755+
break;
756+
case SyntaxKind.NewExpression:
757+
node = factory.updateNewExpression(node, node.expression, node.typeArguments, [
758+
...node.arguments?.slice(0, argumentIndex) || emptyArray,
759+
replacementArg,
760+
...node.arguments?.slice(argumentIndex + 1) || emptyArray,
761+
]);
762+
break;
763+
default:
764+
Debug.failBadSyntaxKind(node);
765+
}
766+
setParent(replacementArg, node);
767+
setParent(node, nodeIn.parent);
766768
}
769+
apparentArgumentCount = argumentCount;
770+
const res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined;
767771
apparentArgumentCount = undefined;
768772
return res;
769773
}
@@ -22683,7 +22687,7 @@ namespace ts {
2268322687
const properties = getPropertiesOfObjectType(target);
2268422688
for (const targetProp of properties) {
2268522689
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
22686-
if (sourceProp && !some(sourceProp.declarations, d => !!getNodeLinks(d).skipDirectInference)) {
22690+
if (sourceProp) {
2268722691
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
2268822692
}
2268922693
}
@@ -29781,7 +29785,7 @@ namespace ts {
2978129785

2978229786
for (let i = 0; i < argCount; i++) {
2978329787
const arg = args[i];
29784-
if (arg.kind !== SyntaxKind.OmittedExpression && !getNodeLinks(arg).skipDirectInference) {
29788+
if (arg.kind !== SyntaxKind.OmittedExpression) {
2978529789
const paramType = getTypeAtPosition(signature, i);
2978629790
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
2978729791
inferTypes(context.inferences, argType, paramType);

src/compiler/types.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -4269,7 +4269,6 @@ namespace ts {
42694269
/* @internal */ getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined;
42704270
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined;
42714271
/* @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined;
4272-
/* @internal */ getContextualTypeForCompletions(node: Expression, editingNode: Node): Type | undefined;
42734272
/* @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean;
42744273
/* @internal */ getTypeOfPropertyOfContextualType(type: Type, name: __String): Type | undefined;
42754274

@@ -4279,7 +4278,7 @@ namespace ts {
42794278
* @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`.
42804279
*/
42814280
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
4282-
/* @internal */ getResolvedSignatureForStringLiteralCompletions(node: CallLikeExpression, candidatesOutArray: Signature[], argumentCount: number, argumentIndex: number): Signature | undefined;
4281+
/* @internal */ getResolvedSignatureForStringLiteralCompletions(node: CallExpression | NewExpression, candidatesOutArray: Signature[], argumentCount: number, argumentIndex: number): Signature | undefined;
42834282
/* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
42844283
/* @internal */ getExpandedParameters(sig: Signature): readonly (readonly Symbol[])[];
42854284
/* @internal */ hasEffectiveRestParameter(sig: Signature): boolean;

src/harness/fourslashImpl.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ namespace FourSlash {
168168
// The position of the end of the current selection, or -1 if nothing is selected
169169
public selectionEnd = -1;
170170

171-
public lastKnownMarker: string | undefined;
171+
public lastKnownMarker = "";
172172

173173
// The file that's currently 'opened'
174174
public activeFile!: FourSlashFile;
@@ -400,7 +400,7 @@ namespace FourSlash {
400400
continue;
401401
}
402402
const memo = Utils.memoize(
403-
(_version: number, _active: string, _caret: number, _selectEnd: number, _marker: string | undefined, ...args: any[]) => (ls[key] as Function)(...args),
403+
(_version: number, _active: string, _caret: number, _selectEnd: number, _marker: string, ...args: any[]) => (ls[key] as Function)(...args),
404404
(...args) => args.map(a => a && typeof a === "object" ? JSON.stringify(a) : a).join("|,|")
405405
);
406406
proxy[key] = (...args: any[]) => memo(
@@ -540,8 +540,8 @@ namespace FourSlash {
540540
}
541541

542542
private messageAtLastKnownMarker(message: string) {
543-
const locationDescription = this.lastKnownMarker !== undefined ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition);
544-
return `At marker '${locationDescription}': ${message}`;
543+
const locationDescription = this.lastKnownMarker ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition);
544+
return `At ${locationDescription}: ${message}`;
545545
}
546546

547547
private assertionMessageAtLastKnownMarker(msg: string) {
@@ -864,7 +864,7 @@ namespace FourSlash {
864864
else {
865865
for (const marker of toArray(options.marker)) {
866866
this.goToMarker(marker);
867-
this.verifyCompletionsWorker({ ...options, marker });
867+
this.verifyCompletionsWorker(options);
868868
}
869869
}
870870
}

src/services/stringCompletions.ts

+7-14
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,12 @@ namespace ts.Completions.StringCompletions {
210210

211211
case SyntaxKind.CallExpression:
212212
case SyntaxKind.NewExpression:
213-
case SyntaxKind.JsxAttribute:
214213
if (!isRequireCallArgument(node) && !isImportCall(parent)) {
215-
const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile);
214+
const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile);
216215
// Get string literal completions from specialized signatures of the target
217216
// i.e. declare function f(a: 'A');
218217
// f("/*completion position*/")
219-
return argumentInfo ? getStringLiteralCompletionsFromSignature(argumentInfo.invocation, node, argumentInfo, typeChecker) : fromContextualType();
218+
return argumentInfo ? getStringLiteralCompletionsFromSignature(parent as CallExpression | NewExpression, argumentInfo, typeChecker) : fromContextualType();
220219
}
221220
// falls through (is `require("")` or `require(""` or `import("")`)
222221

@@ -238,7 +237,7 @@ namespace ts.Completions.StringCompletions {
238237
function fromContextualType(): StringLiteralCompletion {
239238
// Get completion for string literal from string literal type
240239
// i.e. var x: "hi" | "hello" = "/*completion position*/"
241-
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker, ContextFlags.Completions)), isNewIdentifier: false };
240+
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false };
242241
}
243242
}
244243

@@ -258,21 +257,15 @@ namespace ts.Completions.StringCompletions {
258257
type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text : undefined);
259258
}
260259

261-
function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: StringLiteralLike, argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes {
260+
function getStringLiteralCompletionsFromSignature(node: CallExpression | NewExpression, argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes {
262261
let isNewIdentifier = false;
263262

264263
const uniques = new Map<string, true>();
265264
const candidates: Signature[] = [];
266-
let argumentCount = argumentInfo.argumentCount;
267-
let argumentIndex = argumentInfo.argumentIndex;
268-
if (isJsxOpeningLikeElement(call)) {
269-
argumentCount = call.attributes.properties.length;
270-
argumentIndex = findIndex(call.attributes.properties, p => tryCast(p, isJsxAttribute)?.initializer === arg);
271-
}
272-
checker.getResolvedSignatureForStringLiteralCompletions(call, candidates, argumentCount, argumentIndex);
265+
checker.getResolvedSignatureForStringLiteralCompletions(node, candidates, argumentInfo.argumentCount, argumentInfo.argumentIndex);
273266
const types = flatMap(candidates, candidate => {
274-
if (!signatureHasRestParameter(candidate) && argumentCount > candidate.parameters.length) return;
275-
const type = candidate.getTypeParameterAtPosition(argumentIndex);
267+
if (!signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length) return;
268+
const type = candidate.getTypeParameterAtPosition(argumentInfo.argumentIndex);
276269
isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String);
277270
return getStringLiteralTypes(type, uniques);
278271
});

src/services/utilities.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -2657,21 +2657,21 @@ namespace ts {
26572657
|| isAsExpression(expression) && isObjectLiteralExpression(expression.expression);
26582658
}
26592659

2660-
export function getContextualTypeFromParent(node: Expression, checker: TypeChecker, contextFlags?: ContextFlags): Type | undefined {
2660+
export function getContextualTypeFromParent(node: Expression, checker: TypeChecker): Type | undefined {
26612661
const { parent } = node;
26622662
switch (parent.kind) {
26632663
case SyntaxKind.NewExpression:
2664-
return checker.getContextualType(parent as NewExpression, contextFlags);
2664+
return checker.getContextualType(parent as NewExpression);
26652665
case SyntaxKind.BinaryExpression: {
26662666
const { left, operatorToken, right } = parent as BinaryExpression;
26672667
return isEqualityOperatorKind(operatorToken.kind)
26682668
? checker.getTypeAtLocation(node === right ? left : right)
2669-
: checker.getContextualType(node, contextFlags);
2669+
: checker.getContextualType(node);
26702670
}
26712671
case SyntaxKind.CaseClause:
26722672
return (parent as CaseClause).expression === node ? getSwitchedType(parent as CaseClause, checker) : undefined;
26732673
default:
2674-
return checker.getContextualType(node, contextFlags);
2674+
return checker.getContextualType(node);
26752675
}
26762676
}
26772677

tests/cases/fourslash/completionsLiteralOverload.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//// dragenter: any;
1010
//// }
1111
//// declare function addListener<K extends keyof Events>(type: K, listener: (ev: Events[K]) => any): void;
12+
//// declare function addListener(type: string, listener: (ev: any) => any): void;
1213
////
1314
//// declare function ListenerComponent<K extends keyof Events>(props: { type: K, onWhatever: (ev: Events[K]) => void }): JSX.Element;
1415
////
@@ -18,6 +19,7 @@
1819
// @Filename: /b.js
1920
//// addListener("/*js*/");
2021

21-
verify.completions({ marker: ["ts", "tsx", "js"], exact: ["", "drag", "dragenter"] });
22+
verify.completions({ marker: ["ts", "js"], isNewIdentifierLocation: true, exact: ["", "drag", "dragenter"] });
23+
verify.completions({ marker: "tsx", exact: ["", "drag", "dragenter"] });
2224
edit.insert("drag");
23-
verify.completions({ marker: ["ts", "tsx", "js"], exact: ["", "drag", "dragenter"] });
25+
verify.completions({ isNewIdentifierLocation: true, exact: ["", "drag", "dragenter"] });

0 commit comments

Comments
 (0)