Skip to content

Commit 8e79035

Browse files
committed
Merge branch 'main' into staleErrors
2 parents 8e036e5 + 0ad5f82 commit 8e79035

File tree

61 files changed

+1625
-103
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1625
-103
lines changed

src/compiler/checker.ts

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26519,7 +26519,7 @@ namespace ts {
2651926519
if (result) {
2652026520
return result;
2652126521
}
26522-
if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name)) { // This is less a contextual type and more an implied shape - in some cases, this may be undesirable
26522+
if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) && declaration.name.elements.length > 0) {
2652326523
return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false);
2652426524
}
2652526525
}
@@ -27053,22 +27053,20 @@ namespace ts {
2705327053
const inferenceContext = getInferenceContext(node);
2705427054
// If no inferences have been made, nothing is gained from instantiating as type parameters
2705527055
// would just be replaced with their defaults similar to the apparent type.
27056-
if (inferenceContext && some(inferenceContext.inferences, hasInferenceCandidates)) {
27056+
if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidates)) {
2705727057
// For contextual signatures we incorporate all inferences made so far, e.g. from return
2705827058
// types as well as arguments to the left in a function call.
27059-
if (contextFlags && contextFlags & ContextFlags.Signature) {
27060-
return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
27061-
}
27059+
return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
27060+
}
27061+
if (inferenceContext?.returnMapper) {
2706227062
// For other purposes (e.g. determining whether to produce literal types) we only
2706327063
// incorporate inferences made from the return type in a function call. We remove
2706427064
// the 'boolean' type from the contextual type such that contextually typed boolean
2706527065
// literals actually end up widening to 'boolean' (see #48363).
27066-
if (inferenceContext.returnMapper) {
27067-
const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
27068-
return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
27069-
filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
27070-
type;
27071-
}
27066+
const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
27067+
return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
27068+
filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
27069+
type;
2707227070
}
2707327071
}
2707427072
return contextualType;
@@ -29904,29 +29902,43 @@ namespace ts {
2990429902
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
2990529903
// return type of 'wrap'.
2990629904
if (node.kind !== SyntaxKind.Decorator) {
29907-
const contextualType = getContextualType(node, every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
29905+
const skipBindingPatterns = every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p));
29906+
const contextualType = getContextualType(node, skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
2990829907
if (contextualType) {
2990929908
const inferenceTargetType = getReturnTypeOfSignature(signature);
2991029909
if (couldContainTypeVariables(inferenceTargetType)) {
29911-
// We clone the inference context to avoid disturbing a resolution in progress for an
29912-
// outer call expression. Effectively we just want a snapshot of whatever has been
29913-
// inferred for any outer call expression so far.
2991429910
const outerContext = getInferenceContext(node);
29915-
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
29916-
const instantiatedType = instantiateType(contextualType, outerMapper);
29917-
// If the contextual type is a generic function type with a single call signature, we
29918-
// instantiate the type with its own type parameters and type arguments. This ensures that
29919-
// the type parameters are not erased to type any during type inference such that they can
29920-
// be inferred as actual types from the contextual type. For example:
29921-
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
29922-
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
29923-
// Above, the type of the 'value' parameter is inferred to be 'A'.
29924-
const contextualSignature = getSingleCallSignature(instantiatedType);
29925-
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
29926-
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
29927-
instantiatedType;
29928-
// Inferences made from return types have lower priority than all other inferences.
29929-
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
29911+
const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType;
29912+
// A return type inference from a binding pattern can be used in instantiating the contextual
29913+
// type of an argument later in inference, but cannot stand on its own as the final return type.
29914+
// It is incorporated into `context.returnMapper` which is used in `instantiateContextualType`,
29915+
// but doesn't need to go into `context.inferences`. This allows a an array binding pattern to
29916+
// produce a tuple for `T` in
29917+
// declare function f<T>(cb: () => T): T;
29918+
// const [e1, e2, e3] = f(() => [1, "hi", true]);
29919+
// but does not produce any inference for `T` in
29920+
// declare function f<T>(): T;
29921+
// const [e1, e2, e3] = f();
29922+
if (!isFromBindingPattern) {
29923+
// We clone the inference context to avoid disturbing a resolution in progress for an
29924+
// outer call expression. Effectively we just want a snapshot of whatever has been
29925+
// inferred for any outer call expression so far.
29926+
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
29927+
const instantiatedType = instantiateType(contextualType, outerMapper);
29928+
// If the contextual type is a generic function type with a single call signature, we
29929+
// instantiate the type with its own type parameters and type arguments. This ensures that
29930+
// the type parameters are not erased to type any during type inference such that they can
29931+
// be inferred as actual types from the contextual type. For example:
29932+
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
29933+
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
29934+
// Above, the type of the 'value' parameter is inferred to be 'A'.
29935+
const contextualSignature = getSingleCallSignature(instantiatedType);
29936+
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
29937+
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
29938+
instantiatedType;
29939+
// Inferences made from return types have lower priority than all other inferences.
29940+
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
29941+
}
2993029942
// Create a type mapper for instantiating generic contextual types using the inferences made
2993129943
// from the return type. We need a separate inference pass here because (a) instantiation of
2993229944
// the source type uses the outer context's return mapper (which excludes inferences made from

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3548,7 +3548,7 @@ namespace ts {
35483548
}
35493549
if (isImplicitGlob(spec.substring(spec.lastIndexOf(directorySeparator) + 1))) {
35503550
return {
3551-
key: useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec),
3551+
key: removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec)),
35523552
flags: WatchDirectoryFlags.Recursive
35533553
};
35543554
}

src/compiler/transformers/module/esnextAnd2015.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ namespace ts {
7272
// Though an error in es2020 modules, in node-flavor es2020 modules, we can helpfully transform this to a synthetic `require` call
7373
// To give easy access to a synchronous `require` in node-flavor esm. We do the transform even in scenarios where we error, but `import.meta.url`
7474
// is available, just because the output is reasonable for a node-like runtime.
75-
return getEmitScriptTarget(compilerOptions) >= ModuleKind.ES2020 ? visitImportEqualsDeclaration(node as ImportEqualsDeclaration) : undefined;
75+
return getEmitModuleKind(compilerOptions) >= ModuleKind.Node16 ? visitImportEqualsDeclaration(node as ImportEqualsDeclaration) : undefined;
7676
case SyntaxKind.ExportAssignment:
7777
return visitExportAssignment(node as ExportAssignment);
7878
case SyntaxKind.ExportDeclaration:

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5874,7 +5874,7 @@ namespace ts {
58745874
ReturnType = 1 << 7, // Inference made from return type of generic function
58755875
LiteralKeyof = 1 << 8, // Inference made from a string literal to a keyof T
58765876
NoConstraints = 1 << 9, // Don't infer from constraints of instantiable types
5877-
AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences
5877+
AlwaysStrict = 1 << 10, // Always use strict rules for contravariant inferences
58785878
MaxValue = 1 << 11, // Seed for inference priority tracking
58795879

58805880
PriorityImpliesCombination = ReturnType | MappedTypeConstraint | LiteralKeyof, // These priorities imply that the resulting type should be a combination of all candidates
@@ -8813,6 +8813,7 @@ namespace ts {
88138813
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
88148814
readonly includeInlayFunctionParameterTypeHints?: boolean,
88158815
readonly includeInlayVariableTypeHints?: boolean;
8816+
readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean;
88168817
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
88178818
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
88188819
readonly includeInlayEnumMemberValueHints?: boolean;

src/compiler/watchPublic.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ namespace ts {
700700

701701
function reloadFileNamesFromConfigFile() {
702702
writeLog("Reloading new file names and options");
703+
reloadLevel = ConfigFileProgramReloadLevel.None;
703704
rootFileNames = getFileNamesFromConfigSpecs(compilerOptions.configFile!.configFileSpecs!, getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), compilerOptions, parseConfigFileHost, extraFileExtensions);
704705
if (updateErrorForNoInputFiles(rootFileNames, getNormalizedAbsolutePath(configFileName, currentDirectory), compilerOptions.configFile!.configFileSpecs!, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) {
705706
hasChangedConfigFileParsingErrors = true;

src/harness/fourslashInterfaceImpl.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,7 @@ namespace FourSlashInterface {
14981498
"throw",
14991499
"true",
15001500
"try",
1501+
"type",
15011502
"typeof",
15021503
"var",
15031504
"void",
@@ -1649,6 +1650,7 @@ namespace FourSlashInterface {
16491650
"throw",
16501651
"true",
16511652
"try",
1653+
"type",
16521654
"typeof",
16531655
"var",
16541656
"void",

src/server/protocol.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ namespace ts.server.protocol {
728728
}
729729

730730
// All we need is the `success` and `message` fields of Response.
731-
export interface ApplyCodeActionCommandResponse extends Response {}
731+
export interface ApplyCodeActionCommandResponse extends Response { }
732732

733733
export interface FileRangeRequestArgs extends FileRequestArgs {
734734
/**
@@ -1067,7 +1067,7 @@ namespace ts.server.protocol {
10671067
readonly arguments: JsxClosingTagRequestArgs;
10681068
}
10691069

1070-
export interface JsxClosingTagRequestArgs extends FileLocationRequestArgs {}
1070+
export interface JsxClosingTagRequestArgs extends FileLocationRequestArgs { }
10711071

10721072
export interface JsxClosingTagResponse extends Response {
10731073
readonly body: TextInsertion;
@@ -2390,7 +2390,7 @@ namespace ts.server.protocol {
23902390
/**
23912391
* Human-readable description of the `source` from the CompletionEntry.
23922392
*/
2393-
sourceDisplay?: SymbolDisplayPart[];
2393+
sourceDisplay?: SymbolDisplayPart[];
23942394
}
23952395

23962396
/** @deprecated Prefer CompletionInfoResponse, which supports several top-level fields in addition to the array of entries. */
@@ -3415,7 +3415,7 @@ namespace ts.server.protocol {
34153415
/**
34163416
* Allows completions to be formatted with snippet text, indicated by `CompletionItem["isSnippet"]`.
34173417
*/
3418-
readonly includeCompletionsWithSnippetText?: boolean;
3418+
readonly includeCompletionsWithSnippetText?: boolean;
34193419
/**
34203420
* If enabled, the completion list will include completions with invalid identifier names.
34213421
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`.
@@ -3465,6 +3465,7 @@ namespace ts.server.protocol {
34653465
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
34663466
readonly includeInlayFunctionParameterTypeHints?: boolean,
34673467
readonly includeInlayVariableTypeHints?: boolean;
3468+
readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean;
34683469
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
34693470
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
34703471
readonly includeInlayEnumMemberValueHints?: boolean;

src/services/completions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3988,6 +3988,7 @@ namespace ts.Completions {
39883988
return kind === SyntaxKind.AsyncKeyword
39893989
|| kind === SyntaxKind.AwaitKeyword
39903990
|| kind === SyntaxKind.AsKeyword
3991+
|| kind === SyntaxKind.TypeKeyword
39913992
|| !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
39923993
}
39933994

src/services/inlayHints.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ namespace ts.InlayHints {
137137

138138
const typeDisplayString = printTypeInSingleLine(declarationType);
139139
if (typeDisplayString) {
140+
const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false && equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString);
141+
if (isVariableNameMatchesType) {
142+
return;
143+
}
140144
addTypeHints(typeDisplayString, decl.name.end);
141145
}
142146
}

src/testRunner/unittests/config/tsconfigParsing.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,5 +421,14 @@ namespace ts {
421421
const parsedCommand = parseJsonConfigFileContent(parsed.config, sys, "/foo.bar");
422422
assert.deepEqual(parsedCommand.wildcardDirectories, { "/foo.bar/src": WatchDirectoryFlags.Recursive });
423423
});
424+
425+
it("correctly parses wild card directories from implicit glob when two keys differ only in directory seperator", () => {
426+
const parsed = parseConfigFileTextToJson("/foo.bar/tsconfig.json", JSON.stringify({
427+
include: ["./", "./**/*.json"]
428+
}));
429+
430+
const parsedCommand = parseJsonConfigFileContent(parsed.config, sys, "/foo");
431+
assert.deepEqual(parsedCommand.wildcardDirectories, { "/foo": WatchDirectoryFlags.Recursive });
432+
});
424433
});
425434
}

src/testRunner/unittests/tscWatch/programUpdates.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,39 @@ export class A {
616616
]
617617
});
618618

619+
verifyTscWatch({
620+
scenario,
621+
subScenario: "correctly parses wild card directories from implicit glob when two keys differ only in directory seperator",
622+
commandLineArgs: ["-w", "--extendedDiagnostics"],
623+
sys: () => {
624+
const file1 = {
625+
path: `${projectRoot}/f1.ts`,
626+
content: "export const x = 1"
627+
};
628+
const file2 = {
629+
path: `${projectRoot}/f2.ts`,
630+
content: "export const y = 1"
631+
};
632+
const configFile = {
633+
path: `${projectRoot}/tsconfig.json`,
634+
content: JSON.stringify({ compilerOptions: { composite: true }, include: ["./", "./**/*.json"] })
635+
};
636+
return createWatchedSystem([file1, file2, libFile, configFile], { currentDirectory: projectRoot });
637+
},
638+
changes: [
639+
{
640+
caption: "Add new file",
641+
change: sys => sys.writeFile(`${projectRoot}/new-file.ts`, "export const z = 1;"),
642+
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
643+
},
644+
{
645+
caption: "Import new file",
646+
change: sys => sys.prependFile(`${projectRoot}/f1.ts`, `import { z } from "./new-file";`),
647+
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(1),
648+
}
649+
]
650+
});
651+
619652
verifyTscWatch({
620653
scenario,
621654
subScenario: "can correctly update configured project when set of root files has changed through include",

0 commit comments

Comments
 (0)