Skip to content

Commit 39ddd44

Browse files
committed
move logic back to services
1 parent 9422555 commit 39ddd44

18 files changed

+103
-109
lines changed

src/compiler/checker.ts

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
addRange,
77
addRelatedInfo,
88
addSyntheticLeadingComment,
9-
addToSeen,
109
AliasDeclarationNode,
1110
AllAccessorDeclarations,
1211
AmbientModuleDeclaration,
@@ -265,7 +264,6 @@ import {
265264
getContainingClassStaticBlock,
266265
getContainingFunction,
267266
getContainingFunctionOrClassStaticBlock,
268-
getContextualTypeFromParent,
269267
getDeclarationModifierFlagsFromSymbol,
270268
getDeclarationOfKind,
271269
getDeclarationsOfKind,
@@ -1755,7 +1753,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
17551753
getTypeOfPropertyOfContextualType,
17561754
getFullyQualifiedName,
17571755
getResolvedSignature: (node, candidatesOutArray, argumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
1758-
getContextualStringLiteralCompletionTypes,
17591756
getCandidateSignaturesForStringLiteralCompletions,
17601757
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)),
17611758
getExpandedParameters,
@@ -1931,23 +1928,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19311928
getSymbolFlags,
19321929
};
19331930

1934-
function getContextualStringLiteralCompletionTypes(expression: Expression) {
1935-
const seen = new Map<string, true>();
1936-
1937-
return [
1938-
...getStringLiteralTypes(getContextualTypeFromParent(expression, checker, ContextFlags.None), seen),
1939-
...getStringLiteralTypes(getContextualTypeFromParent(expression, checker, ContextFlags.Completions), seen),
1940-
];
1941-
}
1942-
1943-
function getStringLiteralTypes(type: Type | undefined, uniques = new Map<string, true>()): readonly StringLiteralType[] {
1944-
if (!type) return emptyArray;
1945-
// skip constraint
1946-
type = type.flags & TypeFlags.TypeParameter ? getBaseConstraintOfType(type) || type : type;
1947-
return type.flags & TypeFlags.Union ? flatMap((type as UnionType).types, t => getStringLiteralTypes(t, uniques)) :
1948-
type.flags & TypeFlags.StringLiteral && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, (type as StringLiteralType).value) ? [type as StringLiteralType] : emptyArray;
1949-
}
1950-
19511931
function getCandidateSignaturesForStringLiteralCompletions(call: CallLikeExpression, editingArgument: Node) {
19521932
const candidatesSet = new Set<Signature>();
19531933
const candidates: Signature[] = [];
@@ -31565,11 +31545,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3156531545
case SyntaxKind.AmpersandAmpersandToken:
3156631546
case SyntaxKind.CommaToken:
3156731547
return node === right ? getContextualType(binaryExpression, contextFlags) : undefined;
31568-
case SyntaxKind.EqualsEqualsEqualsToken:
31569-
case SyntaxKind.EqualsEqualsToken:
31570-
case SyntaxKind.ExclamationEqualsEqualsToken:
31571-
case SyntaxKind.ExclamationEqualsToken:
31572-
return getTypeOfExpression(node === right ? left : right);
3157331548
default:
3157431549
return undefined;
3157531550
}
@@ -32153,13 +32128,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3215332128
return getContextualTypeForAwaitOperand(parent as AwaitExpression, contextFlags);
3215432129
case SyntaxKind.CallExpression:
3215532130
case SyntaxKind.NewExpression:
32156-
if (node === (parent as CallExpression | NewExpression).expression) {
32157-
if (getImmediatelyInvokedFunctionExpression(skipParentheses(node))) {
32158-
// iifes themselves can't be contextually-typed (unlike their parameters)
32159-
return undefined;
32160-
}
32161-
return getContextualType(parent as CallExpression | NewExpression, contextFlags);
32162-
}
3216332131
return getContextualTypeForArgument(parent as CallExpression | NewExpression, node);
3216432132
case SyntaxKind.Decorator:
3216532133
return getContextualTypeForDecorator(parent as Decorator);

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5175,7 +5175,6 @@ export interface TypeChecker {
51755175
*/
51765176
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
51775177
/** @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
5178-
/** @internal */ getContextualStringLiteralCompletionTypes(expression: Expression): StringLiteralType[];
51795178
/** @internal */ getCandidateSignaturesForStringLiteralCompletions(call: CallLikeExpression, editingArgument: Node): Signature[];
51805179
/** @internal */ getExpandedParameters(sig: Signature): readonly (readonly Symbol[])[];
51815180
/** @internal */ hasEffectiveRestParameter(sig: Signature): boolean;

src/compiler/utilities.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ import {
7878
ContainerFlags,
7979
contains,
8080
containsPath,
81-
ContextFlags,
8281
createGetCanonicalFileName,
8382
createMultiMap,
8483
createScanner,
@@ -119,7 +118,6 @@ import {
119118
EntityNameOrEntityNameExpression,
120119
EnumDeclaration,
121120
EqualityComparer,
122-
EqualityOperator,
123121
equalOwnProperties,
124122
EqualsToken,
125123
equateValues,
@@ -11878,27 +11876,3 @@ export const nodeCoreModules = new Set([
1187811876
...unprefixedNodeCoreModulesList.map(name => `node:${name}`),
1187911877
...exclusivelyPrefixedNodeCoreModules,
1188011878
]);
11881-
11882-
/** @internal */
11883-
export function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator {
11884-
switch (kind) {
11885-
case SyntaxKind.EqualsEqualsEqualsToken:
11886-
case SyntaxKind.EqualsEqualsToken:
11887-
case SyntaxKind.ExclamationEqualsEqualsToken:
11888-
case SyntaxKind.ExclamationEqualsToken:
11889-
return true;
11890-
default:
11891-
return false;
11892-
}
11893-
}
11894-
11895-
/** @internal */
11896-
export function getContextualTypeFromParent(node: Expression, checker: TypeChecker, contextFlags?: ContextFlags): Type | undefined {
11897-
const parent = walkUpParenthesizedExpressions(node.parent);
11898-
switch (parent.kind) {
11899-
case SyntaxKind.CaseClause:
11900-
return checker.getTypeAtLocation((parent as CaseClause).parent.parent.expression);
11901-
default:
11902-
return checker.getContextualType(node, contextFlags);
11903-
}
11904-
}

src/services/completions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {
109109
getResolvePackageJsonExports,
110110
getRootDeclaration,
111111
getSourceFileOfModule,
112+
getSwitchedType,
112113
getSymbolId,
113114
getSynthesizedDeepClone,
114115
getTokenAtPosition,
@@ -3259,7 +3260,7 @@ function getContextualType(previousToken: Node, position: number, sourceFile: So
32593260
return checker.getContextualType(parent as Expression);
32603261
case SyntaxKind.CaseKeyword:
32613262
const caseClause = tryCast(parent, isCaseClause);
3262-
return caseClause ? checker.getTypeAtLocation(caseClause.parent.parent.expression) : undefined;
3263+
return caseClause ? getSwitchedType(caseClause, checker) : undefined;
32633264
case SyntaxKind.OpenBraceToken:
32643265
return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
32653266
default:

src/services/stringCompletions.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
CompletionEntry,
2828
CompletionEntryDetails,
2929
CompletionInfo,
30+
concatenate,
3031
contains,
3132
containsPath,
3233
ContextFlags,
@@ -83,6 +84,7 @@ import {
8384
isApplicableVersionedTypesKey,
8485
isArray,
8586
isCallExpression,
87+
isCallLikeExpression,
8688
isIdentifier,
8789
isIdentifierText,
8890
isImportCall,
@@ -411,7 +413,15 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
411413
// });
412414
return stringLiteralCompletionsForObjectLiteral(typeChecker, parent.parent);
413415
}
414-
return toStringLiteralCompletionsFromTypes(typeChecker.getContextualStringLiteralCompletionTypes(node));
416+
if (findAncestor(parent.parent, isCallLikeExpression)) {
417+
const uniques = new Map<string, true>();
418+
const stringLiteralTypes = concatenate(
419+
getStringLiteralTypes(typeChecker.getContextualType(node, ContextFlags.None), uniques),
420+
getStringLiteralTypes(typeChecker.getContextualType(node, ContextFlags.Completions), uniques),
421+
);
422+
return toStringLiteralCompletionsFromTypes(stringLiteralTypes);
423+
}
424+
return fromContextualType(ContextFlags.None);
415425

416426
case SyntaxKind.ElementAccessExpression: {
417427
const { expression, argumentExpression } = parent as ElementAccessExpression;
@@ -477,7 +487,7 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
477487
return { kind: StringLiteralCompletionKind.Properties, symbols: uniques, hasIndexSignature: false };
478488

479489
default:
480-
return toStringLiteralCompletionsFromTypes(typeChecker.getContextualStringLiteralCompletionTypes(node));
490+
return fromContextualType() || fromContextualType(ContextFlags.None);
481491
}
482492

483493
function fromUnionableLiteralType(grandParent: Node): StringLiteralCompletionsFromTypes | StringLiteralCompletionsFromProperties | undefined {

src/services/utilities.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
CompilerOptions,
3030
ConditionalExpression,
3131
contains,
32+
ContextFlags,
3233
createRange,
3334
createScanner,
3435
createTextSpan,
@@ -57,6 +58,7 @@ import {
5758
endsWith,
5859
ensureScriptKind,
5960
EqualityComparer,
61+
EqualityOperator,
6062
equateStringsCaseInsensitive,
6163
equateStringsCaseSensitive,
6264
escapeString,
@@ -90,7 +92,6 @@ import {
9092
getAssignmentDeclarationKind,
9193
getBaseFileName,
9294
getCombinedNodeFlagsAlwaysIncludeJSDoc,
93-
getContextualTypeFromParent,
9495
getDirectoryPath,
9596
getEmitModuleKind,
9697
getEmitScriptTarget,
@@ -386,6 +387,7 @@ import {
386387
VariableDeclaration,
387388
visitEachChild,
388389
VoidExpression,
390+
walkUpParenthesizedExpressions,
389391
YieldExpression,
390392
} from "./_namespaces/ts.js";
391393

@@ -3369,6 +3371,25 @@ export function needsParentheses(expression: Expression): boolean {
33693371
|| (isAsExpression(expression) || isSatisfiesExpression(expression)) && isObjectLiteralExpression(expression.expression);
33703372
}
33713373

3374+
/** @internal */
3375+
export function getContextualTypeFromParent(node: Expression, checker: TypeChecker, contextFlags?: ContextFlags): Type | undefined {
3376+
const parent = walkUpParenthesizedExpressions(node.parent);
3377+
switch (parent.kind) {
3378+
case SyntaxKind.NewExpression:
3379+
return checker.getContextualType(parent as NewExpression, contextFlags);
3380+
case SyntaxKind.BinaryExpression: {
3381+
const { left, operatorToken, right } = parent as BinaryExpression;
3382+
return isEqualityOperatorKind(operatorToken.kind)
3383+
? checker.getTypeAtLocation(node === right ? left : right)
3384+
: checker.getContextualType(node, contextFlags);
3385+
}
3386+
case SyntaxKind.CaseClause:
3387+
return getSwitchedType(parent as CaseClause, checker);
3388+
default:
3389+
return checker.getContextualType(node, contextFlags);
3390+
}
3391+
}
3392+
33723393
/** @internal */
33733394
export function quote(sourceFile: SourceFile, preferences: UserPreferences, text: string): string {
33743395
// Editors can pass in undefined or empty string - we want to infer the preference in those cases.
@@ -3377,6 +3398,19 @@ export function quote(sourceFile: SourceFile, preferences: UserPreferences, text
33773398
return quotePreference === QuotePreference.Single ? `'${stripQuotes(quoted).replace(/'/g, () => "\\'").replace(/\\"/g, '"')}'` : quoted;
33783399
}
33793400

3401+
/** @internal */
3402+
export function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator {
3403+
switch (kind) {
3404+
case SyntaxKind.EqualsEqualsEqualsToken:
3405+
case SyntaxKind.EqualsEqualsToken:
3406+
case SyntaxKind.ExclamationEqualsEqualsToken:
3407+
case SyntaxKind.ExclamationEqualsToken:
3408+
return true;
3409+
default:
3410+
return false;
3411+
}
3412+
}
3413+
33803414
/** @internal */
33813415
export function isStringLiteralOrTemplate(node: Node): node is StringLiteralLike | TemplateExpression | TaggedTemplateExpression {
33823416
switch (node.kind) {
@@ -3395,6 +3429,11 @@ export function hasIndexSignature(type: Type): boolean {
33953429
return !!type.getStringIndexType() || !!type.getNumberIndexType();
33963430
}
33973431

3432+
/** @internal */
3433+
export function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined {
3434+
return checker.getTypeAtLocation(caseClause.parent.parent.expression);
3435+
}
3436+
33983437
/** @internal */
33993438
export const ANONYMOUS = "anonymous function";
34003439

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
compareTypeParameterConstrainedByLiteralToLiteral.ts(5,5): error TS2367: This comparison appears to be unintentional because the types '"a" | "b"' and '"x"' have no overlap.
1+
compareTypeParameterConstrainedByLiteralToLiteral.ts(5,5): error TS2367: This comparison appears to be unintentional because the types 'T' and '"x"' have no overlap.
22

33

44
==== compareTypeParameterConstrainedByLiteralToLiteral.ts (1 errors) ====
@@ -8,6 +8,6 @@ compareTypeParameterConstrainedByLiteralToLiteral.ts(5,5): error TS2367: This co
88
t === "a"; // Should be allowed
99
t === "x"; // Should be error
1010
~~~~~~~~~
11-
!!! error TS2367: This comparison appears to be unintentional because the types '"a" | "b"' and '"x"' have no overlap.
11+
!!! error TS2367: This comparison appears to be unintentional because the types 'T' and '"x"' have no overlap.
1212
}
1313

tests/baselines/reference/compareTypeParameterConstrainedByLiteralToLiteral.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ function foo<T extends "a" | "b">(t: T) {
1212
t === "a"; // Should be allowed
1313
>t === "a" : boolean
1414
> : ^^^^^^^
15-
>t : "a" | "b"
16-
> : ^^^^^^^^^
15+
>t : T
16+
> : ^
1717
>"a" : "a"
1818
> : ^^^
1919

2020
t === "x"; // Should be error
2121
>t === "x" : boolean
2222
> : ^^^^^^^
23-
>t : "a" | "b"
24-
> : ^^^^^^^^^
23+
>t : T
24+
> : ^
2525
>"x" : "x"
2626
> : ^^^
2727
}

tests/baselines/reference/controlFlowGenericTypes.types

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB {
266266
if (value === 'A') {
267267
>value === 'A' : boolean
268268
> : ^^^^^^^
269-
>value : "A" | "B"
270-
> : ^^^^^^^^^
269+
>value : AB
270+
> : ^^
271271
>'A' : "A"
272272
> : ^^^
273273

@@ -517,8 +517,8 @@ function get<K extends keyof A>(key: K, obj: A): number {
517517
if (value !== null) {
518518
>value !== null : boolean
519519
> : ^^^^^^^
520-
>value : number | null
521-
> : ^^^^^^^^^^^^^
520+
>value : A[K]
521+
> : ^^^^
522522

523523
return value;
524524
>value : number
@@ -729,8 +729,8 @@ class TableBaseEnum<
729729
if (iSpec === undefined) {
730730
>iSpec === undefined : boolean
731731
> : ^^^^^^^
732-
>iSpec : Record<keyof PublicSpec, any> | undefined
733-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
732+
>iSpec : InternalSpec
733+
> : ^^^^^^^^^^^^
734734
>undefined : undefined
735735
> : ^^^^^^^^^
736736

@@ -852,8 +852,8 @@ function update<T extends Control, K extends keyof T>(control : T | undefined, k
852852
if (control !== undefined) {
853853
>control !== undefined : boolean
854854
> : ^^^^^^^
855-
>control : Control | undefined
856-
> : ^^^^^^^^^^^^^^^^^^^
855+
>control : T | undefined
856+
> : ^^^^^^^^^^^^^
857857
>undefined : undefined
858858
> : ^^^^^^^^^
859859

tests/baselines/reference/intersectionNarrowing.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
intersectionNarrowing.ts(36,16): error TS2367: This comparison appears to be unintentional because the types 'number' and 'string' have no overlap.
1+
intersectionNarrowing.ts(36,16): error TS2367: This comparison appears to be unintentional because the types 'T & number' and 'string' have no overlap.
22

33

44
==== intersectionNarrowing.ts (1 errors) ====
@@ -39,6 +39,6 @@ intersectionNarrowing.ts(36,16): error TS2367: This comparison appears to be uni
3939
function f5<T extends string | number>(x: T & number) {
4040
const t1 = x === "hello"; // Should be an error
4141
~~~~~~~~~~~~~
42-
!!! error TS2367: This comparison appears to be unintentional because the types 'number' and 'string' have no overlap.
42+
!!! error TS2367: This comparison appears to be unintentional because the types 'T & number' and 'string' have no overlap.
4343
}
4444

tests/baselines/reference/intersectionNarrowing.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ function f5<T extends string | number>(x: T & number) {
110110
> : ^^^^^^^
111111
>x === "hello" : boolean
112112
> : ^^^^^^^
113-
>x : number
114-
> : ^^^^^^
113+
>x : T & number
114+
> : ^^^^^^^^^^
115115
>"hello" : "hello"
116116
> : ^^^^^^^
117117
}

tests/baselines/reference/intersectionsOfLargeUnions.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export function assertNodeTagName<
7878
> : ^^^^^^^
7979
>nodeTagName : string
8080
> : ^^^^^^
81-
>tagName : "symbol" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "set" | "stop" | "svg" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | keyof HTMLElementTagNameMap
82-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81+
>tagName : T
82+
> : ^
8383
}
8484
return false;
8585
>false : false

0 commit comments

Comments
 (0)