mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'main' into feature/module-controls
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: 'Library change'
|
||||
description: 'Fix or improve issues with built-in type definitions like `lib.dom.d.ts`, `lib.es6.d.ts`, etc.'
|
||||
description: 'Fix or improve issues with built-in type definitions like `lib.es6.d.ts`, etc.'
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
|
||||
uses: github/codeql-action/init@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-configuration.yml
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below).
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
|
||||
uses: github/codeql-action/autobuild@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
|
||||
uses: github/codeql-action/analyze@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
name: Create cherry pick PR
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [create-cherry-pick-pr]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr:
|
||||
description: PR number to cherry-pick
|
||||
required: true
|
||||
type: number
|
||||
target_branch:
|
||||
description: Target branch to cherry-pick to
|
||||
required: true
|
||||
type: string
|
||||
requesting_user:
|
||||
description: User who requested the cherry-pick
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Ensure scripts are run with pipefail. See:
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
open-pr:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
|
||||
fetch-depth: 0 # Default is 1; need to set to 0 to get the benefits of blob:none.
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
PR: ${{ inputs.pr || github.event.client_payload.pr }}
|
||||
TARGET_BRANCH: ${{ inputs.target_branch || github.event.client_payload.target_branch }}
|
||||
REQUESTING_USER: ${{ inputs.requesting_user || github.event.client_payload.requesting_user }}
|
||||
with:
|
||||
retries: 3
|
||||
github-token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { PR, TARGET_BRANCH, REQUESTING_USER } = process.env;
|
||||
|
||||
const pr = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: +PR,
|
||||
});
|
||||
|
||||
if (!pr.data.merge_commit_sha) throw new Error("No merge commit sha found");
|
||||
|
||||
const pickBranch = `cherry-pick/${PR}/${TARGET_BRANCH}`;
|
||||
|
||||
const title = `🤖 Pick PR #${PR} (${pr.data.title.substring(0, 35)}${pr.data.title.length > 35 ? "..." : ""}) into ${TARGET_BRANCH}`;
|
||||
|
||||
await exec.exec("git", ["config", "user.email", "typescriptbot@microsoft.com"]);
|
||||
await exec.exec("git", ["config", "user.name", "TypeScript Bot"]);
|
||||
await exec.exec("git", ["switch", "--detach", `origin/${TARGET_BRANCH}`]);
|
||||
await exec.exec("git", ["switch", "-c", pickBranch]);
|
||||
await exec.exec("git", ["cherry-pick", "-m", "1", pr.data.merge_commit_sha]);
|
||||
await exec.exec("git", ["push", "--force", "--set-upstream", "origin", pickBranch]);
|
||||
|
||||
const existingPulls = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
head: `${context.repo.owner}:${pickBranch}`,
|
||||
});
|
||||
|
||||
if (existingPulls.data.length === 0) {
|
||||
console.log(`No existing PRs found for ${pickBranch}`);
|
||||
|
||||
const body = `This cherry-pick was triggered by a request on #${PR}.\n\nPlease review the diff and merge if no changes are unexpected.`;
|
||||
|
||||
const newPr = await github.rest.pulls.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
base: TARGET_BRANCH,
|
||||
head: pickBranch,
|
||||
title,
|
||||
body,
|
||||
assignees: ["DanielRosenwasser"],
|
||||
reviewers: ["DanielRosenwasser", REQUESTING_USER],
|
||||
});
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: +PR,
|
||||
body: `Hey @${REQUESTING_USER}, I've created #${newPr.data.number} for you.`,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const existing = existingPulls.data[0];
|
||||
console.log(`Found existing PR #${existing.number} for ${pickBranch}`);
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: existing.number,
|
||||
title,
|
||||
});
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: +PR,
|
||||
body: `Hey @${REQUESTING_USER}, I've updated #${existing.number} for you.`,
|
||||
});
|
||||
}
|
||||
|
||||
- run: |
|
||||
MESSAGE="Hey @$REQUESTING_USER, I was unable to cherry-pick this PR."
|
||||
MESSAGE+=$'\n\n'
|
||||
MESSAGE+="Check the logs at: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
||||
gh pr comment "$PR" --repo ${{ github.repository }} --body "$MESSAGE"
|
||||
if: ${{ failure() }}
|
||||
env:
|
||||
PR: ${{ inputs.pr || github.event.client_payload.pr }}
|
||||
TARGET_BRANCH: ${{ inputs.target_branch || github.event.client_payload.target_branch }}
|
||||
REQUESTING_USER: ${{ inputs.requesting_user || github.event.client_payload.requesting_user }}
|
||||
GH_TOKEN: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
@@ -2,7 +2,7 @@ name: New Release Branch
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: new-release-branch
|
||||
types: [new-release-branch]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
# enable users to manually trigger with workflow_dispatch
|
||||
workflow_dispatch: {}
|
||||
repository_dispatch:
|
||||
types: publish-nightly
|
||||
types: [publish-nightly]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -55,6 +55,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.22.7
|
||||
uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Set branch version
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: set-version
|
||||
types: [set-version]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Sync branch with master
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: sync-branch
|
||||
types: [sync-branch]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch_name:
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
schedule:
|
||||
- cron: '0 8 * * *'
|
||||
repository_dispatch:
|
||||
types: run-twoslash-repros
|
||||
types: [run-twoslash-repros]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue:
|
||||
|
||||
Generated
+339
-339
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -78,7 +78,7 @@
|
||||
"playwright": "^1.38.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"tslib": "^2.5.0",
|
||||
"typescript": "^5.0.2",
|
||||
"typescript": "^5.3.2",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"overrides": {
|
||||
|
||||
+26
-2
@@ -89,7 +89,31 @@ assert(sourceFile, "Failed to load source file");
|
||||
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
||||
assert(moduleSymbol, "Failed to get module's symbol");
|
||||
|
||||
const printer = ts.createPrinter({ newLine: newLineKind });
|
||||
/** @type {{ writeNode(hint: ts.EmitHint, node: ts.Node, sourceFile: ts.SourceFile | undefined, writer: any): void }} */
|
||||
const printer = /** @type {any} */ (ts.createPrinter({ newLine: newLineKind }));
|
||||
/** @type {{ writeComment(s: string): void; getText(): string; clear(): void }} */
|
||||
const writer = /** @type {any} */ (ts).createTextWriter("\n");
|
||||
const originalWriteComment = writer.writeComment.bind(writer);
|
||||
writer.writeComment = s => {
|
||||
// Hack; undo https://github.com/microsoft/TypeScript/pull/50097
|
||||
// We printNode directly, so we get all of the original source comments.
|
||||
// If we were using actual declaration emit instead, this wouldn't be needed.
|
||||
if (s.startsWith("//")) {
|
||||
return;
|
||||
}
|
||||
originalWriteComment(s);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ts.Node} node
|
||||
* @param {ts.SourceFile} sourceFile
|
||||
*/
|
||||
function printNode(node, sourceFile) {
|
||||
printer.writeNode(ts.EmitHint.Unspecified, node, sourceFile, writer);
|
||||
const text = writer.getText();
|
||||
writer.clear();
|
||||
return text;
|
||||
}
|
||||
|
||||
/** @type {string[]} */
|
||||
const publicLines = [];
|
||||
@@ -141,7 +165,7 @@ function write(s, target) {
|
||||
* @param {WriteTarget} target
|
||||
*/
|
||||
function writeNode(node, sourceFile, target) {
|
||||
write(printer.printNode(ts.EmitHint.Unspecified, node, sourceFile), target);
|
||||
write(printNode(node, sourceFile), target);
|
||||
}
|
||||
|
||||
/** @type {Map<ts.Symbol, boolean>} */
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
import {
|
||||
Octokit,
|
||||
} from "@octokit/rest";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import url from "url";
|
||||
|
||||
import {
|
||||
runSequence,
|
||||
} from "./run-sequence.mjs";
|
||||
|
||||
const __filename = url.fileURLToPath(new URL(import.meta.url));
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const userName = process.env.GH_USERNAME;
|
||||
const reviewers = process.env.REQUESTING_USER ? [process.env.REQUESTING_USER] : ["weswigham", "RyanCavanaugh"];
|
||||
const branchName = `pick/${process.env.SOURCE_ISSUE}/${process.env.TARGET_BRANCH}`;
|
||||
const remoteUrl = `https://${process.argv[2]}@github.com/${userName}/TypeScript.git`;
|
||||
const produceLKG = !!process.env.PRODUCE_LKG;
|
||||
|
||||
async function main() {
|
||||
if (!process.env.TARGET_BRANCH) {
|
||||
throw new Error("Target branch not specified");
|
||||
}
|
||||
if (!process.env.SOURCE_ISSUE) {
|
||||
throw new Error("Source issue not specified");
|
||||
}
|
||||
const currentSha = runSequence([
|
||||
["git", ["rev-parse", "HEAD"]],
|
||||
]);
|
||||
const currentAuthor = runSequence([
|
||||
["git", ["log", "-1", `--pretty="%aN <%aE>"`]],
|
||||
]);
|
||||
|
||||
const gh = new Octokit({
|
||||
auth: process.argv[2],
|
||||
});
|
||||
|
||||
const inputPR = (await gh.pulls.get({ pull_number: +process.env.SOURCE_ISSUE, owner: "microsoft", repo: "TypeScript" })).data;
|
||||
let remoteName = "origin";
|
||||
if (inputPR.base.repo.git_url !== `git:github.com/microsoft/TypeScript` && inputPR.base.repo.git_url !== `git://github.com/microsoft/TypeScript`) {
|
||||
runSequence([
|
||||
["git", ["remote", "add", "nonlocal", inputPR.base.repo.git_url.replace(/^git:(?:\/\/)?/, "https://")]],
|
||||
]);
|
||||
remoteName = "nonlocal";
|
||||
}
|
||||
const baseBranchName = inputPR.base.ref;
|
||||
runSequence([
|
||||
["git", ["fetch", remoteName, baseBranchName]],
|
||||
]);
|
||||
let logText = runSequence([
|
||||
["git", ["log", `${remoteName}/${baseBranchName}..${currentSha.trim()}`, `--pretty="%h %s%n%b"`, "--reverse"]],
|
||||
]);
|
||||
logText = `Cherry-pick PR #${process.env.SOURCE_ISSUE} into ${process.env.TARGET_BRANCH}
|
||||
|
||||
Component commits:
|
||||
${logText.trim()}`;
|
||||
const logpath = path.join(__dirname, "../", "logmessage.txt");
|
||||
const mergebase = runSequence([["git", ["merge-base", `${remoteName}/${baseBranchName}`, currentSha]]]).trim();
|
||||
runSequence([
|
||||
["git", ["checkout", "-b", "temp-branch"]],
|
||||
["git", ["reset", mergebase, "--soft"]],
|
||||
]);
|
||||
fs.writeFileSync(logpath, logText);
|
||||
runSequence([
|
||||
["git", ["commit", "-F", logpath, `--author="${currentAuthor.trim()}"`]],
|
||||
]);
|
||||
fs.unlinkSync(logpath);
|
||||
const squashSha = runSequence([
|
||||
["git", ["rev-parse", "HEAD"]],
|
||||
]);
|
||||
runSequence([
|
||||
["git", ["checkout", process.env.TARGET_BRANCH]], // checkout the target branch
|
||||
["git", ["checkout", "-b", branchName]], // create a new branch
|
||||
["git", ["cherry-pick", squashSha.trim()]],
|
||||
]);
|
||||
if (produceLKG) {
|
||||
runSequence([
|
||||
["node", ["./node_modules/hereby/dist/cli.js", "LKG"]],
|
||||
["git", ["add", "lib"]],
|
||||
["git", ["commit", "-m", `"Update LKG"`]],
|
||||
]);
|
||||
}
|
||||
runSequence([
|
||||
["git", ["remote", "add", "fork", remoteUrl]], // Add the remote fork
|
||||
["git", ["push", "--set-upstream", "fork", branchName, "-f"]], // push the branch
|
||||
]);
|
||||
|
||||
const r = await gh.pulls.create({
|
||||
owner: "Microsoft",
|
||||
repo: "TypeScript",
|
||||
maintainer_can_modify: true,
|
||||
title: `🤖 Pick PR #${process.env.SOURCE_ISSUE} (${inputPR.title.substring(0, 35)}${inputPR.title.length > 35 ? "..." : ""}) into ${process.env.TARGET_BRANCH}`,
|
||||
head: `${userName}:${branchName}`,
|
||||
base: process.env.TARGET_BRANCH,
|
||||
body: `This cherry-pick was triggered by a request on https://github.com/Microsoft/TypeScript/pull/${process.env.SOURCE_ISSUE}
|
||||
Please review the diff and merge if no changes are unexpected.${produceLKG ? ` An LKG update commit is included separately from the base change.` : ""}
|
||||
You can view the cherry-pick log [here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary).
|
||||
|
||||
cc ${reviewers.map(r => "@" + r).join(" ")}`,
|
||||
});
|
||||
const num = r.data.number;
|
||||
console.log(`Pull request ${num} created.`);
|
||||
|
||||
await gh.issues.createComment({
|
||||
issue_number: +process.env.SOURCE_ISSUE,
|
||||
owner: "Microsoft",
|
||||
repo: "TypeScript",
|
||||
body: `Hey @${process.env.REQUESTING_USER}, I've opened #${num} for you.`,
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(async e => {
|
||||
console.error(e);
|
||||
process.exitCode = 1;
|
||||
if (process.env.SOURCE_ISSUE) {
|
||||
const gh = new Octokit({
|
||||
auth: process.argv[2],
|
||||
});
|
||||
await gh.issues.createComment({
|
||||
issue_number: +process.env.SOURCE_ISSUE,
|
||||
owner: "Microsoft",
|
||||
repo: "TypeScript",
|
||||
body: `Hey @${process.env.REQUESTING_USER}, I couldn't open a PR with the cherry-pick. ([You can check the log here](https://typescript.visualstudio.com/TypeScript/_build/index?buildId=${process.env.BUILD_BUILDID}&_a=summary)). You may need to squash and pick this PR into ${process.env.TARGET_BRANCH} manually.`,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -3309,7 +3309,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
|
||||
function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) {
|
||||
// Class declarations in Typescript do not allow property declarations
|
||||
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer);
|
||||
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer) || lookupSymbolForPropertyAccess(node.left.expression, container);
|
||||
if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) {
|
||||
return;
|
||||
}
|
||||
@@ -3428,7 +3428,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
|
||||
let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) || lookupSymbolForPropertyAccess(name, blockScopeContainer);
|
||||
let namespaceSymbol = lookupSymbolForPropertyAccess(name, blockScopeContainer) || lookupSymbolForPropertyAccess(name, container);
|
||||
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
|
||||
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass);
|
||||
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);
|
||||
|
||||
+316
-138
@@ -598,6 +598,7 @@ import {
|
||||
isJSDocSatisfiesTag,
|
||||
isJSDocSignature,
|
||||
isJSDocTemplateTag,
|
||||
isJSDocThisTag,
|
||||
isJSDocTypeAlias,
|
||||
isJSDocTypeAssertion,
|
||||
isJSDocTypedefTag,
|
||||
@@ -1306,6 +1307,12 @@ const enum MappedTypeModifiers {
|
||||
ExcludeOptional = 1 << 3,
|
||||
}
|
||||
|
||||
const enum MappedTypeNameTypeKind {
|
||||
None,
|
||||
Filtering,
|
||||
Remapping,
|
||||
}
|
||||
|
||||
const enum ExpandingFlags {
|
||||
None = 0,
|
||||
Source = 1,
|
||||
@@ -2833,7 +2840,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// still might be illegal if usage is in the initializer of the variable declaration (eg var a = a)
|
||||
return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration as VariableDeclaration, usage);
|
||||
}
|
||||
else if (isClassDeclaration(declaration)) {
|
||||
else if (isClassLike(declaration)) {
|
||||
// still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} })
|
||||
return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration);
|
||||
}
|
||||
@@ -3149,7 +3156,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
else if (location.kind === SyntaxKind.ConditionalType) {
|
||||
// A type parameter declared using 'infer T' in a conditional type is visible only in
|
||||
// the true branch of the conditional type.
|
||||
useResult = lastLocation === (location as ConditionalTypeNode).trueType;
|
||||
useResult = lastLocation === location.trueType;
|
||||
}
|
||||
|
||||
if (useResult) {
|
||||
@@ -5526,6 +5533,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent));
|
||||
}
|
||||
|
||||
function getFunctionExpressionParentSymbolOrSymbol(symbol: Symbol) {
|
||||
return symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression
|
||||
? getSymbolOfNode(symbol.valueDeclaration.parent) || symbol
|
||||
: symbol;
|
||||
}
|
||||
|
||||
function getAlternativeContainingModules(symbol: Symbol, enclosingDeclaration: Node): Symbol[] {
|
||||
const containingFile = getSourceFileOfNode(enclosingDeclaration);
|
||||
const id = getNodeId(containingFile);
|
||||
@@ -11236,11 +11249,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
if (symbol.parent?.valueDeclaration) {
|
||||
const typeNode = getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration);
|
||||
if (typeNode) {
|
||||
const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName);
|
||||
if (annotationSymbol) {
|
||||
return getNonMissingTypeOfSymbol(annotationSymbol);
|
||||
const possiblyAnnotatedSymbol = getFunctionExpressionParentSymbolOrSymbol(symbol.parent);
|
||||
if (possiblyAnnotatedSymbol.valueDeclaration) {
|
||||
const typeNode = getEffectiveTypeAnnotationNode(possiblyAnnotatedSymbol.valueDeclaration);
|
||||
if (typeNode) {
|
||||
const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName);
|
||||
if (annotationSymbol) {
|
||||
return getNonMissingTypeOfSymbol(annotationSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12932,9 +12948,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
const assignments = (symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression) &&
|
||||
getSymbolOfNode(symbol.valueDeclaration.parent)?.assignmentDeclarationMembers ||
|
||||
symbol.assignmentDeclarationMembers;
|
||||
const assignments = getFunctionExpressionParentSymbolOrSymbol(symbol).assignmentDeclarationMembers;
|
||||
|
||||
if (assignments) {
|
||||
const decls = arrayFrom(assignments.values());
|
||||
@@ -13242,9 +13256,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
let result: Signature[] | undefined;
|
||||
for (let i = 0; i < signatureLists.length; i++) {
|
||||
// Allow matching non-generic signatures to have excess parameters and different return types.
|
||||
// Allow matching non-generic signatures to have excess parameters (as a fallback if exact parameter match is not found) and different return types.
|
||||
// Prefer matching this types if possible.
|
||||
const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true);
|
||||
const match = i === listIndex
|
||||
? signature
|
||||
: findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true)
|
||||
|| findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -13631,6 +13648,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])]));
|
||||
}
|
||||
|
||||
// If the original mapped type had an intersection constraint we extract its components,
|
||||
// and we make an attempt to do so even if the intersection has been reduced to a union.
|
||||
// This entire process allows us to possibly retrieve the filtering type literals.
|
||||
// e.g. { [K in keyof U & ("a" | "b") ] } -> "a" | "b"
|
||||
function getLimitedConstraint(type: ReverseMappedType) {
|
||||
const constraint = getConstraintTypeFromMappedType(type.mappedType);
|
||||
if (!(constraint.flags & TypeFlags.Union || constraint.flags & TypeFlags.Intersection)) {
|
||||
return;
|
||||
}
|
||||
const origin = (constraint.flags & TypeFlags.Union) ? (constraint as UnionType).origin : (constraint as IntersectionType);
|
||||
if (!origin || !(origin.flags & TypeFlags.Intersection)) {
|
||||
return;
|
||||
}
|
||||
const limitedConstraint = getIntersectionType((origin as IntersectionType).types.filter(t => t !== type.constraintType));
|
||||
return limitedConstraint !== neverType ? limitedConstraint : undefined;
|
||||
}
|
||||
|
||||
function resolveReverseMappedTypeMembers(type: ReverseMappedType) {
|
||||
const indexInfo = getIndexInfoOfType(type.source, stringType);
|
||||
const modifiers = getMappedTypeModifiers(type.mappedType);
|
||||
@@ -13638,7 +13672,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional;
|
||||
const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray;
|
||||
const members = createSymbolTable();
|
||||
const limitedConstraint = getLimitedConstraint(type);
|
||||
for (const prop of getPropertiesOfType(type.source)) {
|
||||
// In case of a reverse mapped type with an intersection constraint, if we were able to
|
||||
// extract the filtering type literals we skip those properties that are not assignable to them,
|
||||
// because the extra properties wouldn't get through the application of the mapped type anyway
|
||||
if (limitedConstraint) {
|
||||
const propertyNameType = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique);
|
||||
if (!isTypeAssignableTo(propertyNameType, limitedConstraint)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0);
|
||||
const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol;
|
||||
inferredProp.declarations = prop.declarations;
|
||||
@@ -13679,7 +13723,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const checkType = (type as ConditionalType).checkType;
|
||||
const constraint = getLowerBoundOfKeyType(checkType);
|
||||
if (constraint !== checkType) {
|
||||
return getConditionalTypeInstantiation(type as ConditionalType, prependTypeMapping((type as ConditionalType).root.checkType, constraint, (type as ConditionalType).mapper));
|
||||
return getConditionalTypeInstantiation(type as ConditionalType, prependTypeMapping((type as ConditionalType).root.checkType, constraint, (type as ConditionalType).mapper), /*forConstraint*/ false);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
@@ -13731,7 +13775,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const constraintType = getConstraintTypeFromMappedType(type);
|
||||
const mappedType = (type.target as MappedType) || type;
|
||||
const nameType = getNameTypeFromMappedType(mappedType);
|
||||
const shouldLinkPropDeclarations = !nameType || isFilteringMappedType(mappedType);
|
||||
const shouldLinkPropDeclarations = getMappedTypeNameTypeKind(mappedType) !== MappedTypeNameTypeKind.Remapping;
|
||||
const templateType = getTemplateTypeFromMappedType(mappedType);
|
||||
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
|
||||
const templateModifiers = getMappedTypeModifiers(type);
|
||||
@@ -13913,9 +13957,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isFilteringMappedType(type: MappedType): boolean {
|
||||
function getMappedTypeNameTypeKind(type: MappedType): MappedTypeNameTypeKind {
|
||||
const nameType = getNameTypeFromMappedType(type);
|
||||
return !!nameType && isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type));
|
||||
if (!nameType) {
|
||||
return MappedTypeNameTypeKind.None;
|
||||
}
|
||||
return isTypeAssignableTo(nameType, getTypeParameterFromMappedType(type)) ? MappedTypeNameTypeKind.Filtering : MappedTypeNameTypeKind.Remapping;
|
||||
}
|
||||
|
||||
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
|
||||
@@ -13980,7 +14027,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (const current of type.types) {
|
||||
for (const prop of getPropertiesOfType(current)) {
|
||||
if (!members.has(prop.escapedName)) {
|
||||
const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName);
|
||||
const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName, /*skipObjectFunctionPropertyAugment*/ !!(type.flags & TypeFlags.Intersection));
|
||||
if (combinedProp) {
|
||||
members.set(prop.escapedName, combinedProp);
|
||||
}
|
||||
@@ -14055,6 +14102,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
|
||||
}
|
||||
|
||||
function isConstMappedType(type: MappedType, depth: number): boolean {
|
||||
const typeVariable = getHomomorphicTypeVariable(type);
|
||||
return !!typeVariable && isConstTypeVariable(typeVariable, depth);
|
||||
}
|
||||
|
||||
function isConstTypeVariable(type: Type | undefined, depth = 0): boolean {
|
||||
return depth < 5 && !!(type && (
|
||||
type.flags & TypeFlags.TypeParameter && some((type as TypeParameter).symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.Const)) ||
|
||||
@@ -14062,6 +14114,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
type.flags & TypeFlags.IndexedAccess && isConstTypeVariable((type as IndexedAccessType).objectType, depth + 1) ||
|
||||
type.flags & TypeFlags.Conditional && isConstTypeVariable(getConstraintOfConditionalType(type as ConditionalType), depth + 1) ||
|
||||
type.flags & TypeFlags.Substitution && isConstTypeVariable((type as SubstitutionType).baseType, depth) ||
|
||||
getObjectFlags(type) & ObjectFlags.Mapped && isConstMappedType(type as MappedType, depth) ||
|
||||
isGenericTupleType(type) && findIndex(getElementTypes(type), (t, i) => !!(type.target.elementFlags[i] & ElementFlags.Variadic) && isConstTypeVariable(t, depth)) >= 0
|
||||
));
|
||||
}
|
||||
@@ -14128,7 +14181,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const simplified = getSimplifiedType(type.checkType, /*writing*/ false);
|
||||
const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
|
||||
if (constraint && constraint !== type.checkType) {
|
||||
const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper));
|
||||
const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper), /*forConstraint*/ true);
|
||||
if (!(instantiated.flags & TypeFlags.Never)) {
|
||||
type.resolvedConstraintOfDistributive = instantiated;
|
||||
return instantiated;
|
||||
@@ -14623,6 +14676,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() :
|
||||
type.propertyCache ||= createSymbolTable();
|
||||
properties.set(name, property);
|
||||
if (skipObjectFunctionPropertyAugment && !type.propertyCache?.get(name)) {
|
||||
const properties = type.propertyCache ||= createSymbolTable();
|
||||
properties.set(name, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
return property;
|
||||
@@ -14765,7 +14822,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
return getPropertyOfObjectType(globalObjectType, name);
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
const prop = getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, /*skipObjectFunctionPropertyAugment*/ true);
|
||||
if (prop) {
|
||||
return prop;
|
||||
}
|
||||
if (!skipObjectFunctionPropertyAugment) {
|
||||
return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment);
|
||||
}
|
||||
return undefined;
|
||||
@@ -15013,6 +15080,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let flags = SignatureFlags.None;
|
||||
let minArgumentCount = 0;
|
||||
let thisParameter: Symbol | undefined;
|
||||
let thisTag: JSDocThisTag | undefined = isInJSFile(declaration) ? getJSDocThisTag(declaration) : undefined;
|
||||
let hasThisParameter = false;
|
||||
const iife = getImmediatelyInvokedFunctionExpression(declaration);
|
||||
const isJSConstructSignature = isJSDocConstructSignature(declaration);
|
||||
@@ -15030,6 +15098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// signature.
|
||||
for (let i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) {
|
||||
const param = declaration.parameters[i];
|
||||
if (isInJSFile(param) && isJSDocThisTag(param)) {
|
||||
thisTag = param;
|
||||
continue;
|
||||
}
|
||||
|
||||
let paramSymbol = param.symbol;
|
||||
const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type;
|
||||
@@ -15073,11 +15145,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
if (isInJSFile(declaration)) {
|
||||
const thisTag = getJSDocThisTag(declaration);
|
||||
if (thisTag && thisTag.typeExpression) {
|
||||
thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression));
|
||||
}
|
||||
if (thisTag && thisTag.typeExpression) {
|
||||
thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression));
|
||||
}
|
||||
|
||||
const hostDeclaration = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration;
|
||||
@@ -16794,6 +16863,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!(flags & TypeFlags.Never)) {
|
||||
includes |= flags & TypeFlags.IncludesMask;
|
||||
if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable;
|
||||
if (flags & TypeFlags.Intersection && getObjectFlags(type) & ObjectFlags.IsConstrainedTypeVariable) includes |= TypeFlags.IncludesConstrainedTypeVariable;
|
||||
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
|
||||
if (!strictNullChecks && flags & TypeFlags.Nullable) {
|
||||
if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType;
|
||||
@@ -16925,10 +16995,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) {
|
||||
const templates = filter(types, t =>
|
||||
!!(t.flags & TypeFlags.TemplateLiteral) &&
|
||||
isPatternLiteralType(t) &&
|
||||
(t as TemplateLiteralType).types.every(t => !(t.flags & TypeFlags.Intersection) || !areIntersectedTypesAvoidingPrimitiveReduction((t as IntersectionType).types))) as TemplateLiteralType[];
|
||||
const templates = filter(types, t => !!(t.flags & TypeFlags.TemplateLiteral) && isPatternLiteralType(t)) as TemplateLiteralType[];
|
||||
if (templates.length) {
|
||||
let i = types.length;
|
||||
while (i > 0) {
|
||||
@@ -16941,6 +17008,49 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function removeConstrainedTypeVariables(types: Type[]) {
|
||||
const typeVariables: TypeVariable[] = [];
|
||||
// First collect a list of the type variables occurring in constraining intersections.
|
||||
for (const type of types) {
|
||||
if (getObjectFlags(type) & ObjectFlags.IsConstrainedTypeVariable) {
|
||||
const index = (type as IntersectionType).types[0].flags & TypeFlags.TypeVariable ? 0 : 1;
|
||||
pushIfUnique(typeVariables, (type as IntersectionType).types[index]);
|
||||
}
|
||||
}
|
||||
// For each type variable, check if the constraining intersections for that type variable fully
|
||||
// cover the constraint of the type variable; if so, remove the constraining intersections and
|
||||
// substitute the type variable.
|
||||
for (const typeVariable of typeVariables) {
|
||||
const primitives: Type[] = [];
|
||||
// First collect the primitive types from the constraining intersections.
|
||||
for (const type of types) {
|
||||
if (getObjectFlags(type) & ObjectFlags.IsConstrainedTypeVariable) {
|
||||
const index = (type as IntersectionType).types[0].flags & TypeFlags.TypeVariable ? 0 : 1;
|
||||
if ((type as IntersectionType).types[index] === typeVariable) {
|
||||
insertType(primitives, (type as IntersectionType).types[1 - index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If every constituent in the type variable's constraint is covered by an intersection of the type
|
||||
// variable and that constituent, remove those intersections and substitute the type variable.
|
||||
const constraint = getBaseConstraintOfType(typeVariable)!;
|
||||
if (everyType(constraint, t => containsType(primitives, t))) {
|
||||
let i = types.length;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
const type = types[i];
|
||||
if (getObjectFlags(type) & ObjectFlags.IsConstrainedTypeVariable) {
|
||||
const index = (type as IntersectionType).types[0].flags & TypeFlags.TypeVariable ? 0 : 1;
|
||||
if ((type as IntersectionType).types[index] === typeVariable && containsType(primitives, (type as IntersectionType).types[1 - index])) {
|
||||
orderedRemoveItemAt(types, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
insertType(types, typeVariable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isNamedUnionType(type: Type) {
|
||||
return !!(type.flags & TypeFlags.Union && (type.aliasSymbol || (type as UnionType).origin));
|
||||
}
|
||||
@@ -17015,6 +17125,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) {
|
||||
removeStringLiteralsMatchedByTemplateLiterals(typeSet);
|
||||
}
|
||||
if (includes & TypeFlags.IncludesConstrainedTypeVariable) {
|
||||
removeConstrainedTypeVariables(typeSet);
|
||||
}
|
||||
if (unionReduction === UnionReduction.Subtype) {
|
||||
typeSet = removeSubtypes(typeSet, !!(includes & TypeFlags.Object));
|
||||
if (!typeSet) {
|
||||
@@ -17279,9 +17392,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return true;
|
||||
}
|
||||
|
||||
function createIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) {
|
||||
function createIntersectionType(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) {
|
||||
const result = createType(TypeFlags.Intersection) as IntersectionType;
|
||||
result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
result.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
result.types = types;
|
||||
result.aliasSymbol = aliasSymbol;
|
||||
result.aliasTypeArguments = aliasTypeArguments;
|
||||
@@ -17302,6 +17415,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const typeMembershipMap = new Map<string, Type>();
|
||||
const includes = addTypesToIntersection(typeMembershipMap, 0 as TypeFlags, types);
|
||||
const typeSet: Type[] = arrayFrom(typeMembershipMap.values());
|
||||
let objectFlags = ObjectFlags.None;
|
||||
// An intersection type is considered empty if it contains
|
||||
// the type never, or
|
||||
// more than one unit type or,
|
||||
@@ -17353,6 +17467,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (typeSet.length === 1) {
|
||||
return typeSet[0];
|
||||
}
|
||||
if (typeSet.length === 2) {
|
||||
const typeVarIndex = typeSet[0].flags & TypeFlags.TypeVariable ? 0 : 1;
|
||||
const typeVariable = typeSet[typeVarIndex];
|
||||
const primitiveType = typeSet[1 - typeVarIndex];
|
||||
if (typeVariable.flags & TypeFlags.TypeVariable && (primitiveType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || includes & TypeFlags.IncludesEmptyObject)) {
|
||||
// We have an intersection T & P or P & T, where T is a type variable and P is a primitive type, the object type, or {}.
|
||||
const constraint = getBaseConstraintOfType(typeVariable);
|
||||
// Check that T's constraint is similarly composed of primitive types, the object type, or {}.
|
||||
if (constraint && everyType(constraint, t => !!(t.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) || isEmptyAnonymousObjectType(t))) {
|
||||
// If T's constraint is a subtype of P, simply return T. For example, given `T extends "a" | "b"`,
|
||||
// the intersection `T & string` reduces to just T.
|
||||
if (isTypeStrictSubtypeOf(constraint, primitiveType)) {
|
||||
return typeVariable;
|
||||
}
|
||||
if (!(constraint.flags & TypeFlags.Union && someType(constraint, c => isTypeStrictSubtypeOf(c, primitiveType)))) {
|
||||
// No constituent of T's constraint is a subtype of P. If P is also not a subtype of T's constraint,
|
||||
// then the constraint and P are unrelated, and the intersection reduces to never. For example, given
|
||||
// `T extends "a" | "b"`, the intersection `T & number` reduces to never.
|
||||
if (!isTypeStrictSubtypeOf(primitiveType, constraint)) {
|
||||
return neverType;
|
||||
}
|
||||
}
|
||||
// Some constituent of T's constraint is a subtype of P, or P is a subtype of T's constraint. Thus,
|
||||
// the intersection further constrains the type variable. For example, given `T extends string | number`,
|
||||
// the intersection `T & "a"` is marked as a constrained type variable. Likewise, given `T extends "a" | 1`,
|
||||
// the intersection `T & number` is marked as a constrained type variable.
|
||||
objectFlags = ObjectFlags.IsConstrainedTypeVariable;
|
||||
}
|
||||
}
|
||||
}
|
||||
const id = getTypeListId(typeSet) + getAliasId(aliasSymbol, aliasTypeArguments);
|
||||
let result = intersectionTypes.get(id);
|
||||
if (!result) {
|
||||
@@ -17388,7 +17532,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = createIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
|
||||
result = createIntersectionType(typeSet, objectFlags, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
intersectionTypes.set(id, result);
|
||||
}
|
||||
@@ -17439,20 +17583,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0);
|
||||
}
|
||||
|
||||
function areIntersectedTypesAvoidingPrimitiveReduction(types: Type[], primitiveFlags = TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt): boolean {
|
||||
if (types.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
const [t1, t2] = types;
|
||||
return !!(t1.flags & primitiveFlags) && t2 === emptyTypeLiteralType || !!(t2.flags & primitiveFlags) && t1 === emptyTypeLiteralType;
|
||||
}
|
||||
|
||||
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
const aliasSymbol = getAliasSymbolForTypeNode(node);
|
||||
const types = map(node.types, getTypeFromTypeNode);
|
||||
const noSupertypeReduction = areIntersectedTypesAvoidingPrimitiveReduction(types);
|
||||
// We perform no supertype reduction for X & {} or {} & X, where X is one of string, number, bigint,
|
||||
// or a pattern literal template type. This enables union types like "a" | "b" | string & {} or
|
||||
// "aa" | "ab" | `a${string}` which preserve the literal types for purposes of statement completion.
|
||||
const emptyIndex = types.length === 2 ? types.indexOf(emptyTypeLiteralType) : -1;
|
||||
const t = emptyIndex >= 0 ? types[1 - emptyIndex] : unknownType;
|
||||
const noSupertypeReduction = !!(t.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt) || t.flags & TypeFlags.TemplateLiteral && isPatternLiteralType(t));
|
||||
links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
|
||||
}
|
||||
return links.resolvedType;
|
||||
@@ -17493,30 +17634,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return constraintType;
|
||||
}
|
||||
const keyTypes: Type[] = [];
|
||||
if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
|
||||
// We have a { [P in keyof T]: X }
|
||||
|
||||
// `getApparentType` on the T in a generic mapped type can trigger a circularity
|
||||
// (conditionals and `infer` types create a circular dependency in the constraint resolution)
|
||||
// so we only eagerly manifest the keys if the constraint is nongeneric
|
||||
if (!isGenericIndexType(constraintType)) {
|
||||
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
|
||||
forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, !!(indexFlags & IndexFlags.StringsOnly), addMemberForKeyType);
|
||||
}
|
||||
else {
|
||||
// we have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer the whole `keyof whatever` for later
|
||||
// since it's not safe to resolve the shape of modifier type
|
||||
// Calling getApparentType on the `T` of a `keyof T` in the constraint type of a generic mapped type can
|
||||
// trigger a circularity. For example, `T extends { [P in keyof T & string as Captitalize<P>]: any }` is
|
||||
// a circular definition. For this reason, we only eagerly manifest the keys if the constraint is non-generic.
|
||||
if (isGenericIndexType(constraintType)) {
|
||||
if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
|
||||
// We have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer
|
||||
// the whole `keyof whatever` for later since it's not safe to resolve the shape of modifier type.
|
||||
return getIndexTypeForGenericType(type, indexFlags);
|
||||
}
|
||||
// Include the generic component in the resulting type.
|
||||
forEachType(constraintType, addMemberForKeyType);
|
||||
}
|
||||
else if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
|
||||
const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
|
||||
forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, !!(indexFlags & IndexFlags.StringsOnly), addMemberForKeyType);
|
||||
}
|
||||
else {
|
||||
forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
|
||||
}
|
||||
if (isGenericIndexType(constraintType)) { // include the generic component in the resulting type
|
||||
forEachType(constraintType, addMemberForKeyType);
|
||||
}
|
||||
// we had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the original constraintType,
|
||||
// so we can return the union that preserves aliases/origin data if possible
|
||||
// We had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the
|
||||
// original constraintType, so we can return the union that preserves aliases/origin data if possible.
|
||||
const result = indexFlags & IndexFlags.NoIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) : getUnionType(keyTypes);
|
||||
if (result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types)) {
|
||||
return constraintType;
|
||||
@@ -17601,7 +17739,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function shouldDeferIndexType(type: Type, indexFlags = IndexFlags.None) {
|
||||
return !!(type.flags & TypeFlags.InstantiableNonPrimitive ||
|
||||
isGenericTupleType(type) ||
|
||||
isGenericMappedType(type) && !hasDistributiveNameType(type) ||
|
||||
isGenericMappedType(type) && (!hasDistributiveNameType(type) || getMappedTypeNameTypeKind(type) === MappedTypeNameTypeKind.Remapping) ||
|
||||
type.flags & TypeFlags.Union && !(indexFlags & IndexFlags.NoReducibleCheck) && isGenericReducibleType(type) ||
|
||||
type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType));
|
||||
}
|
||||
@@ -17735,7 +17873,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function createTemplateLiteralType(texts: readonly string[], types: readonly Type[]) {
|
||||
const type = createType(TypeFlags.TemplateLiteral) as TemplateLiteralType;
|
||||
type.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type.texts = texts;
|
||||
type.types = types;
|
||||
return type;
|
||||
@@ -18060,12 +18197,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function isPatternLiteralPlaceholderType(type: Type): boolean {
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return !isGenericType(type) && some((type as IntersectionType).types, t => !!(t.flags & (TypeFlags.Literal | TypeFlags.Nullable)) || isPatternLiteralPlaceholderType(t));
|
||||
// Return true if the intersection consists of one or more placeholders and zero or
|
||||
// more object type tags.
|
||||
let seenPlaceholder = false;
|
||||
for (const t of (type as IntersectionType).types) {
|
||||
if (t.flags & (TypeFlags.Literal | TypeFlags.Nullable) || isPatternLiteralPlaceholderType(t)) {
|
||||
seenPlaceholder = true;
|
||||
}
|
||||
else if (!(t.flags & TypeFlags.Object)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return seenPlaceholder;
|
||||
}
|
||||
return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || isPatternLiteralType(type);
|
||||
}
|
||||
|
||||
function isPatternLiteralType(type: Type) {
|
||||
// A pattern literal type is a template literal or a string mapping type that contains only
|
||||
// non-generic pattern literal placeholders.
|
||||
return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) ||
|
||||
!!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type);
|
||||
}
|
||||
@@ -18083,12 +18233,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getGenericObjectFlags(type: Type): ObjectFlags {
|
||||
if (type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral)) {
|
||||
if (!((type as UnionOrIntersectionType | TemplateLiteralType).objectFlags & ObjectFlags.IsGenericTypeComputed)) {
|
||||
(type as UnionOrIntersectionType | TemplateLiteralType).objectFlags |= ObjectFlags.IsGenericTypeComputed |
|
||||
reduceLeft((type as UnionOrIntersectionType | TemplateLiteralType).types, (flags, t) => flags | getGenericObjectFlags(t), 0);
|
||||
if (type.flags & (TypeFlags.UnionOrIntersection)) {
|
||||
if (!((type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) {
|
||||
(type as UnionOrIntersectionType).objectFlags |= ObjectFlags.IsGenericTypeComputed |
|
||||
reduceLeft((type as UnionOrIntersectionType).types, (flags, t) => flags | getGenericObjectFlags(t), 0);
|
||||
}
|
||||
return (type as UnionOrIntersectionType | TemplateLiteralType).objectFlags & ObjectFlags.IsGenericType;
|
||||
return (type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericType;
|
||||
}
|
||||
if (type.flags & TypeFlags.Substitution) {
|
||||
if (!((type as SubstitutionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) {
|
||||
@@ -18098,7 +18248,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType;
|
||||
}
|
||||
return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) |
|
||||
(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0);
|
||||
(type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0);
|
||||
}
|
||||
|
||||
function getSimplifiedType(type: Type, writing: boolean): Type {
|
||||
@@ -18171,7 +18321,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P.
|
||||
// For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
|
||||
if (isGenericMappedType(objectType)) {
|
||||
if (!getNameTypeFromMappedType(objectType) || isFilteringMappedType(objectType)) {
|
||||
if (getMappedTypeNameTypeKind(objectType) !== MappedTypeNameTypeKind.Remapping) {
|
||||
return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
|
||||
}
|
||||
}
|
||||
@@ -18356,7 +18506,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return isGenericType(type) || checkTuples && isTupleType(type) && some(getElementTypes(type), isGenericType);
|
||||
}
|
||||
|
||||
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
|
||||
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, forConstraint: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
|
||||
let result;
|
||||
let extraTypes: Type[] | undefined;
|
||||
let tailCount = 0;
|
||||
@@ -18435,8 +18585,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// possible (the wildcard type is assignable to and from all types). If those are not related,
|
||||
// then no instantiations will be and we can just return the false branch type.
|
||||
if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && (checkType.flags & TypeFlags.Any || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
|
||||
// Return union of trueType and falseType for 'any' since it matches anything
|
||||
if (checkType.flags & TypeFlags.Any) {
|
||||
// Return union of trueType and falseType for 'any' since it matches anything. Furthermore, for a
|
||||
// distributive conditional type applied to the constraint of a type variable, include trueType if
|
||||
// there are possible values of the check type that are also possible values of the extends type.
|
||||
// We use a reverse assignability check as it is less expensive than the comparable relationship
|
||||
// and avoids false positives of a non-empty intersection check.
|
||||
if (checkType.flags & TypeFlags.Any || forConstraint && !(inferredExtendsType.flags & TypeFlags.Never) && someType(getPermissiveInstantiation(inferredExtendsType), t => isTypeAssignableTo(t, getPermissiveInstantiation(checkType)))) {
|
||||
(extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper));
|
||||
}
|
||||
// If falseType is an immediately nested conditional type that isn't distributive or has an
|
||||
@@ -18560,7 +18714,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
aliasSymbol,
|
||||
aliasTypeArguments,
|
||||
};
|
||||
links.resolvedType = getConditionalType(root, /*mapper*/ undefined);
|
||||
links.resolvedType = getConditionalType(root, /*mapper*/ undefined, /*forConstraint*/ false);
|
||||
if (outerTypeParameters) {
|
||||
root.instantiations = new Map<string, Type>();
|
||||
root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType);
|
||||
@@ -19568,14 +19722,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
|
||||
function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, forConstraint: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
|
||||
const root = type.root;
|
||||
if (root.outerTypeParameters) {
|
||||
// We are instantiating a conditional type that has one or more type parameters in scope. Apply the
|
||||
// mapper to the type parameters to produce the effective list of type arguments, and compute the
|
||||
// instantiation cache key from the type IDs of the type arguments.
|
||||
const typeArguments = map(root.outerTypeParameters, t => getMappedType(t, mapper));
|
||||
const id = getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments);
|
||||
const id = (forConstraint ? "C" : "") + getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments);
|
||||
let result = root.instantiations!.get(id);
|
||||
if (!result) {
|
||||
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
|
||||
@@ -19585,8 +19739,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
|
||||
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
|
||||
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
|
||||
mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
|
||||
getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
|
||||
mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper), forConstraint), aliasSymbol, aliasTypeArguments) :
|
||||
getConditionalType(root, newMapper, forConstraint, aliasSymbol, aliasTypeArguments);
|
||||
root.instantiations!.set(id, result);
|
||||
}
|
||||
return result;
|
||||
@@ -19668,7 +19822,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return getIndexedAccessType(instantiateType((type as IndexedAccessType).objectType, mapper), instantiateType((type as IndexedAccessType).indexType, mapper), (type as IndexedAccessType).accessFlags, /*accessNode*/ undefined, newAliasSymbol, newAliasTypeArguments);
|
||||
}
|
||||
if (flags & TypeFlags.Conditional) {
|
||||
return getConditionalTypeInstantiation(type as ConditionalType, combineTypeMappers((type as ConditionalType).mapper, mapper), aliasSymbol, aliasTypeArguments);
|
||||
return getConditionalTypeInstantiation(type as ConditionalType, combineTypeMappers((type as ConditionalType).mapper, mapper), /*forConstraint*/ false, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
if (flags & TypeFlags.Substitution) {
|
||||
const newBaseType = instantiateType((type as SubstitutionType).baseType, mapper);
|
||||
@@ -20540,8 +20694,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// similar to return values, callback parameters are output positions. This means that a Promise<T>,
|
||||
// where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
|
||||
// with respect to T.
|
||||
const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
|
||||
const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType));
|
||||
const sourceSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(source, i) ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
|
||||
const targetSig = checkMode & SignatureCheckMode.Callback || isInstantiatedGenericParameter(target, i) ? undefined : getSingleCallSignature(getNonNullableType(targetType));
|
||||
const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
|
||||
getTypeFacts(sourceType, TypeFacts.IsUndefinedOrNull) === getTypeFacts(targetType, TypeFacts.IsUndefinedOrNull);
|
||||
let related = callbacks ?
|
||||
@@ -21565,7 +21719,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState);
|
||||
}
|
||||
if (target.flags & TypeFlags.Union) {
|
||||
return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
|
||||
return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive), intersectionState);
|
||||
}
|
||||
if (target.flags & TypeFlags.Intersection) {
|
||||
return typeRelatedToEachType(source, target as IntersectionType, reportErrors, IntersectionState.Target);
|
||||
@@ -21599,7 +21753,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false);
|
||||
const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false, IntersectionState.None);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
}
|
||||
@@ -21608,7 +21762,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return result;
|
||||
}
|
||||
|
||||
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
|
||||
const targetTypes = target.types;
|
||||
if (target.flags & TypeFlags.Union) {
|
||||
if (containsType(targetTypes, source)) {
|
||||
@@ -21635,14 +21789,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
const match = getMatchingUnionConstituentForType(target as UnionType, source);
|
||||
if (match) {
|
||||
const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false);
|
||||
const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
|
||||
if (related) {
|
||||
return related;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const type of targetTypes) {
|
||||
const related = isRelatedTo(source, type, RecursionFlags.Target, /*reportErrors*/ false);
|
||||
const related = isRelatedTo(source, type, RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
|
||||
if (related) {
|
||||
return related;
|
||||
}
|
||||
@@ -21651,7 +21805,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// Elaborate only if we can find a best matching type in the target union
|
||||
const bestMatchingType = getBestMatchingType(source, target, isRelatedTo);
|
||||
if (bestMatchingType) {
|
||||
isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true);
|
||||
isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
@@ -22417,18 +22571,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// conditionals aren't related to one another via distributive constraint as it is much too inaccurate and allows way
|
||||
// more assignments than are desirable (since it maps the source check type to its constraint, it loses information)
|
||||
const distributiveConstraint = hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined;
|
||||
if (distributiveConstraint) {
|
||||
if (result = isRelatedTo(distributiveConstraint, target, RecursionFlags.Source, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// conditionals _can_ be related to one another via normal constraint, as, eg, `A extends B ? O : never` should be assignable to `O`
|
||||
// conditionals can be related to one another via normal constraint, as, eg, `A extends B ? O : never` should be assignable to `O`
|
||||
// when `O` is a conditional (`never` is trivially assignable to `O`, as is `O`!).
|
||||
const defaultConstraint = getDefaultConstraintOfConditionalType(source as ConditionalType);
|
||||
if (defaultConstraint) {
|
||||
@@ -22436,6 +22579,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// conditionals aren't related to one another via distributive constraint as it is much too inaccurate and allows way
|
||||
// more assignments than are desirable (since it maps the source check type to its constraint, it loses information).
|
||||
const distributiveConstraint = !(targetFlags & TypeFlags.Conditional) && hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined;
|
||||
if (distributiveConstraint) {
|
||||
resetErrorInfo(saveErrorInfo);
|
||||
if (result = isRelatedTo(distributiveConstraint, target, RecursionFlags.Source, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// An empty object type is related to any mapped type that includes a '?' modifier.
|
||||
@@ -24768,7 +24920,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
|
||||
objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)
|
||||
) ||
|
||||
type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType | TemplateLiteralType).types, couldContainTypeVariables));
|
||||
type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType).types, couldContainTypeVariables));
|
||||
if (type.flags & TypeFlags.ObjectFlagsType) {
|
||||
(type as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (result ? ObjectFlags.CouldContainTypeVariables : 0);
|
||||
}
|
||||
@@ -25006,12 +25158,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean {
|
||||
if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) {
|
||||
return true;
|
||||
}
|
||||
if (target.flags & TypeFlags.Intersection) {
|
||||
return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t));
|
||||
}
|
||||
if (target.flags & TypeFlags.String || isTypeAssignableTo(source, target)) {
|
||||
return true;
|
||||
}
|
||||
if (source.flags & TypeFlags.StringLiteral) {
|
||||
const value = (source as StringLiteralType).value;
|
||||
return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
|
||||
@@ -25024,7 +25176,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const texts = (source as TemplateLiteralType).texts;
|
||||
return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target);
|
||||
}
|
||||
return isTypeAssignableTo(source, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined {
|
||||
@@ -25205,7 +25357,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
target = getIntersectionType(targets);
|
||||
}
|
||||
}
|
||||
else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) {
|
||||
if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) {
|
||||
target = getActualTypeVariable(target);
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeVariable) {
|
||||
@@ -25543,9 +25695,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean {
|
||||
if (constraintType.flags & TypeFlags.Union) {
|
||||
if ((constraintType.flags & TypeFlags.Union) || (constraintType.flags & TypeFlags.Intersection)) {
|
||||
let result = false;
|
||||
for (const type of (constraintType as UnionType).types) {
|
||||
for (const type of (constraintType as (UnionType | IntersectionType)).types) {
|
||||
result = inferToMappedType(source, target, type) || result;
|
||||
}
|
||||
return result;
|
||||
@@ -26209,7 +26361,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node)) {
|
||||
const initializer = getEffectiveInitializer(declaration);
|
||||
if (initializer) {
|
||||
return tryGetNameFromType(getTypeOfExpression(initializer));
|
||||
const initializerType = isBindingPattern(declaration.parent) ? getTypeForBindingElement(declaration as BindingElement) : getTypeOfExpression(initializer);
|
||||
return initializerType && tryGetNameFromType(initializerType);
|
||||
}
|
||||
if (isEnumMember(declaration)) {
|
||||
return getTextOfPropertyName(declaration.name);
|
||||
@@ -27924,10 +28077,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (isMatchingConstructorReference(right)) {
|
||||
return narrowTypeByConstructor(type, operator, left, assumeTrue);
|
||||
}
|
||||
if (isBooleanLiteral(right)) {
|
||||
if (isBooleanLiteral(right) && !isAccessExpression(left)) {
|
||||
return narrowTypeByBooleanComparison(type, left, right, operator, assumeTrue);
|
||||
}
|
||||
if (isBooleanLiteral(left)) {
|
||||
if (isBooleanLiteral(left) && !isAccessExpression(right)) {
|
||||
return narrowTypeByBooleanComparison(type, right, left, operator, assumeTrue);
|
||||
}
|
||||
break;
|
||||
@@ -28706,14 +28859,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// destructuring from the narrowed parent type.
|
||||
if (isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) {
|
||||
const parent = declaration.parent.parent;
|
||||
if (parent.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || parent.kind === SyntaxKind.Parameter) {
|
||||
const rootDeclaration = getRootDeclaration(parent);
|
||||
if (rootDeclaration.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlagsCached(rootDeclaration) & NodeFlags.Constant || rootDeclaration.kind === SyntaxKind.Parameter) {
|
||||
const links = getNodeLinks(parent);
|
||||
if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) {
|
||||
links.flags |= NodeCheckFlags.InCheckIdentifier;
|
||||
const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal);
|
||||
const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType);
|
||||
links.flags &= ~NodeCheckFlags.InCheckIdentifier;
|
||||
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
|
||||
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(rootDeclaration.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
|
||||
const pattern = declaration.parent;
|
||||
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & TypeFlags.Never) {
|
||||
@@ -33335,6 +33489,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
(typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters);
|
||||
}
|
||||
|
||||
function isInstantiatedGenericParameter(signature: Signature, pos: number) {
|
||||
let type;
|
||||
return !!(signature.target && (type = tryGetTypeAtPosition(signature.target, pos)) && isGenericType(type));
|
||||
}
|
||||
|
||||
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
|
||||
function getSingleCallSignature(type: Type): Signature | undefined {
|
||||
return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false);
|
||||
@@ -33909,21 +34068,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function getDiagnosticSpanForCallNode(node: CallExpression, doNotIncludeArguments?: boolean) {
|
||||
let start: number;
|
||||
let length: number;
|
||||
function getDiagnosticSpanForCallNode(node: CallExpression) {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
|
||||
if (isPropertyAccessExpression(node.expression)) {
|
||||
const nameSpan = getErrorSpanForNode(sourceFile, node.expression.name);
|
||||
start = nameSpan.start;
|
||||
length = doNotIncludeArguments ? nameSpan.length : node.end - start;
|
||||
}
|
||||
else {
|
||||
const expressionSpan = getErrorSpanForNode(sourceFile, node.expression);
|
||||
start = expressionSpan.start;
|
||||
length = doNotIncludeArguments ? expressionSpan.length : node.end - start;
|
||||
}
|
||||
const { start, length } = getErrorSpanForNode(sourceFile, isPropertyAccessExpression(node.expression) ? node.expression.name : node.expression);
|
||||
return { start, length, sourceFile };
|
||||
}
|
||||
|
||||
@@ -33943,6 +34090,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function getErrorNodeForCallNode(callLike: CallLikeExpression): Node {
|
||||
if (isCallOrNewExpression(callLike)) {
|
||||
return isPropertyAccessExpression(callLike.expression) ? callLike.expression.name : callLike.expression;
|
||||
}
|
||||
if (isTaggedTemplateExpression(callLike)) {
|
||||
return isPropertyAccessExpression(callLike.tag) ? callLike.tag.name : callLike.tag;
|
||||
}
|
||||
if (isJsxOpeningLikeElement(callLike)) {
|
||||
return callLike.tagName;
|
||||
}
|
||||
return callLike;
|
||||
}
|
||||
|
||||
function isPromiseResolveArityError(node: CallLikeExpression) {
|
||||
if (!isCallExpression(node) || !isIdentifier(node.expression)) return false;
|
||||
|
||||
@@ -34266,7 +34426,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
diag = { file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related };
|
||||
}
|
||||
else {
|
||||
diag = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(node), node, chain, related);
|
||||
diag = createDiagnosticForNodeFromMessageChain(getSourceFileOfNode(node), getErrorNodeForCallNode(node), chain, related);
|
||||
}
|
||||
addImplementationSuccessElaboration(candidatesForArgumentError[0], diag);
|
||||
diagnostics.add(diag);
|
||||
@@ -34624,7 +34784,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// use the resolvingSignature singleton to indicate that we deferred processing. This result will be
|
||||
// propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
|
||||
// from which we never make inferences).
|
||||
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
|
||||
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) {
|
||||
skippedGenericFunction(node, checkMode);
|
||||
return resolvingSignature;
|
||||
}
|
||||
@@ -34637,8 +34797,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags);
|
||||
}
|
||||
|
||||
function isGenericFunctionReturningFunction(signature: Signature) {
|
||||
return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature)));
|
||||
function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) {
|
||||
if (!signature.typeParameters) {
|
||||
return false;
|
||||
}
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
return isFunctionType(returnType) || isConstructorType(returnType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34902,7 +35066,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo));
|
||||
}
|
||||
if (isCallExpression(errorTarget.parent)) {
|
||||
const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent, /*doNotIncludeArguments*/ true);
|
||||
const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent);
|
||||
diagnostic.start = start;
|
||||
diagnostic.length = length;
|
||||
}
|
||||
@@ -36057,9 +36221,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const parameter = signature.parameters[i];
|
||||
if (!getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)) {
|
||||
const contextualParameterType = tryGetTypeAtPosition(context, i);
|
||||
assignParameterType(parameter, contextualParameterType);
|
||||
const declaration = parameter.valueDeclaration as ParameterDeclaration;
|
||||
if (!getEffectiveTypeAnnotationNode(declaration)) {
|
||||
let type = tryGetTypeAtPosition(context, i);
|
||||
if (type && declaration.initializer) {
|
||||
let initializerType = checkDeclarationInitializer(declaration, CheckMode.Normal);
|
||||
if (!isTypeAssignableTo(initializerType, type) && isTypeAssignableTo(type, initializerType = widenTypeInferredFromInitializer(declaration, initializerType))) {
|
||||
type = initializerType;
|
||||
}
|
||||
}
|
||||
assignParameterType(parameter, type);
|
||||
}
|
||||
}
|
||||
if (signatureHasRestParameter(signature)) {
|
||||
@@ -38842,17 +39013,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function getReturnTypeOfSingleNonGenericCallSignature(funcType: Type) {
|
||||
function getNonGenericReturnTypeOfSingleCallSignature(funcType: Type) {
|
||||
const signature = getSingleCallSignature(funcType);
|
||||
if (signature && !signature.typeParameters) {
|
||||
return getReturnTypeOfSignature(signature);
|
||||
if (signature) {
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
if (!signature.typeParameters || !couldContainTypeVariables(returnType)) {
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr: CallChain) {
|
||||
const funcType = checkExpression(expr.expression);
|
||||
const nonOptionalType = getOptionalExpressionType(funcType, expr.expression);
|
||||
const returnType = getReturnTypeOfSingleNonGenericCallSignature(funcType);
|
||||
const returnType = getNonGenericReturnTypeOfSingleCallSignature(funcType);
|
||||
return returnType && propagateOptionalTypeMarker(returnType, expr, nonOptionalType !== funcType);
|
||||
}
|
||||
|
||||
@@ -38901,7 +39075,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// signature where we can just fetch the return type without checking the arguments.
|
||||
if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*requireStringLiteralLikeArgument*/ true) && !isSymbolOrSymbolForCall(expr)) {
|
||||
return isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) :
|
||||
getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression));
|
||||
getNonGenericReturnTypeOfSingleCallSignature(checkNonNullExpression(expr.expression));
|
||||
}
|
||||
else if (isAssertionExpression(expr) && !isConstTypeReference(expr.type)) {
|
||||
return getTypeFromTypeNode((expr as TypeAssertion).type);
|
||||
@@ -39989,7 +40163,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// Check if the index type is assignable to 'keyof T' for the object type.
|
||||
const objectType = (type as IndexedAccessType).objectType;
|
||||
const indexType = (type as IndexedAccessType).indexType;
|
||||
if (isTypeAssignableTo(indexType, getIndexType(objectType, IndexFlags.None))) {
|
||||
// skip index type deferral on remapping mapped types
|
||||
const objectIndexType = isGenericMappedType(objectType) && getMappedTypeNameTypeKind(objectType) === MappedTypeNameTypeKind.Remapping
|
||||
? getIndexTypeForMappedType(objectType, IndexFlags.None)
|
||||
: getIndexType(objectType, IndexFlags.None);
|
||||
if (isTypeAssignableTo(indexType, objectIndexType)) {
|
||||
if (
|
||||
accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
|
||||
getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly
|
||||
|
||||
@@ -227,7 +227,7 @@ const libEntries: [string, string][] = [
|
||||
["esnext.disposable", "lib.esnext.disposable.d.ts"],
|
||||
["esnext.bigint", "lib.es2020.bigint.d.ts"],
|
||||
["esnext.string", "lib.es2022.string.d.ts"],
|
||||
["esnext.promise", "lib.es2021.promise.d.ts"],
|
||||
["esnext.promise", "lib.esnext.promise.d.ts"],
|
||||
["esnext.weakref", "lib.es2021.weakref.d.ts"],
|
||||
["esnext.decorators", "lib.esnext.decorators.d.ts"],
|
||||
["decorators", "lib.decorators.d.ts"],
|
||||
@@ -3892,7 +3892,7 @@ function specToDiagnostic(spec: CompilerOptionsValue, disallowTrailingRecursion?
|
||||
/**
|
||||
* Gets directories in a set of include patterns that should be watched for changes.
|
||||
*/
|
||||
function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
|
||||
function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, basePath: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
|
||||
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
|
||||
// of the pattern:
|
||||
//
|
||||
@@ -3905,23 +3905,26 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu
|
||||
//
|
||||
// /a/b/* - Watch /a/b directly to catch any new file
|
||||
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
|
||||
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
|
||||
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, basePath, "exclude");
|
||||
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
|
||||
const wildcardDirectories: MapLike<WatchDirectoryFlags> = {};
|
||||
const wildCardKeyToPath = new Map<CanonicalKey, string>();
|
||||
if (include !== undefined) {
|
||||
const recursiveKeys: string[] = [];
|
||||
const recursiveKeys: CanonicalKey[] = [];
|
||||
for (const file of include) {
|
||||
const spec = normalizePath(combinePaths(path, file));
|
||||
const spec = normalizePath(combinePaths(basePath, file));
|
||||
if (excludeRegex && excludeRegex.test(spec)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const match = getWildcardDirectoryFromSpec(spec, useCaseSensitiveFileNames);
|
||||
if (match) {
|
||||
const { key, flags } = match;
|
||||
const existingFlags = wildcardDirectories[key];
|
||||
const { key, path, flags } = match;
|
||||
const existingPath = wildCardKeyToPath.get(key);
|
||||
const existingFlags = existingPath !== undefined ? wildcardDirectories[existingPath] : undefined;
|
||||
if (existingFlags === undefined || existingFlags < flags) {
|
||||
wildcardDirectories[key] = flags;
|
||||
wildcardDirectories[existingPath !== undefined ? existingPath : path] = flags;
|
||||
if (existingPath === undefined) wildCardKeyToPath.set(key, path);
|
||||
if (flags === WatchDirectoryFlags.Recursive) {
|
||||
recursiveKeys.push(key);
|
||||
}
|
||||
@@ -3930,11 +3933,12 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu
|
||||
}
|
||||
|
||||
// Remove any subpaths under an existing recursively watched directory.
|
||||
for (const key in wildcardDirectories) {
|
||||
if (hasProperty(wildcardDirectories, key)) {
|
||||
for (const path in wildcardDirectories) {
|
||||
if (hasProperty(wildcardDirectories, path)) {
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
const key = toCanonicalKey(path, useCaseSensitiveFileNames);
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, basePath, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[path];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3944,7 +3948,12 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu
|
||||
return wildcardDirectories;
|
||||
}
|
||||
|
||||
function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string; flags: WatchDirectoryFlags; } | undefined {
|
||||
type CanonicalKey = string & { __canonicalKey: never; };
|
||||
function toCanonicalKey(path: string, useCaseSensitiveFileNames: boolean): CanonicalKey {
|
||||
return (useCaseSensitiveFileNames ? path : toFileNameLowerCase(path)) as CanonicalKey;
|
||||
}
|
||||
|
||||
function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: CanonicalKey; path: string; flags: WatchDirectoryFlags; } | undefined {
|
||||
const match = wildcardDirectoryPattern.exec(spec);
|
||||
if (match) {
|
||||
// We check this with a few `indexOf` calls because 3 `indexOf`/`lastIndexOf` calls is
|
||||
@@ -3955,15 +3964,18 @@ function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: b
|
||||
const starWildcardIndex = spec.indexOf("*");
|
||||
const lastDirectorySeperatorIndex = spec.lastIndexOf(directorySeparator);
|
||||
return {
|
||||
key: useCaseSensitiveFileNames ? match[0] : toFileNameLowerCase(match[0]),
|
||||
key: toCanonicalKey(match[0], useCaseSensitiveFileNames),
|
||||
path: match[0],
|
||||
flags: (questionWildcardIndex !== -1 && questionWildcardIndex < lastDirectorySeperatorIndex)
|
||||
|| (starWildcardIndex !== -1 && starWildcardIndex < lastDirectorySeperatorIndex)
|
||||
? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None,
|
||||
};
|
||||
}
|
||||
if (isImplicitGlob(spec.substring(spec.lastIndexOf(directorySeparator) + 1))) {
|
||||
const path = removeTrailingDirectorySeparator(spec);
|
||||
return {
|
||||
key: removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec)),
|
||||
key: toCanonicalKey(path, useCaseSensitiveFileNames),
|
||||
path,
|
||||
flags: WatchDirectoryFlags.Recursive,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ import {
|
||||
hasSyntacticModifier,
|
||||
HeritageClause,
|
||||
Identifier,
|
||||
identity,
|
||||
idText,
|
||||
IfStatement,
|
||||
ImmediatelyInvokedArrowFunction,
|
||||
@@ -509,7 +510,7 @@ export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) {
|
||||
* @internal
|
||||
*/
|
||||
export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory {
|
||||
const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal;
|
||||
const setOriginal = flags & NodeFactoryFlags.NoOriginalNode ? identity : setOriginalNode;
|
||||
|
||||
// Lazily load the parenthesizer, node converters, and some factory methods until they are used.
|
||||
const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory));
|
||||
@@ -6135,7 +6136,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
|
||||
function cloneSourceFile(source: SourceFile) {
|
||||
const node = source.redirectInfo ? cloneRedirectedSourceFile(source) : cloneSourceFileWorker(source);
|
||||
setOriginalNode(node, source);
|
||||
setOriginal(node, source);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -6365,7 +6366,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
const clone = createBaseIdentifier(node.escapedText) as Mutable<GeneratedIdentifier>;
|
||||
clone.flags |= node.flags & ~NodeFlags.Synthesized;
|
||||
clone.transformFlags = node.transformFlags;
|
||||
setOriginalNode(clone, node);
|
||||
setOriginal(clone, node);
|
||||
setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate });
|
||||
return clone;
|
||||
}
|
||||
@@ -6377,7 +6378,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
clone.flowNode = node.flowNode;
|
||||
clone.symbol = node.symbol;
|
||||
clone.transformFlags = node.transformFlags;
|
||||
setOriginalNode(clone, node);
|
||||
setOriginal(clone, node);
|
||||
|
||||
// clone type arguments for emitter/typeWriter
|
||||
const typeArguments = getIdentifierTypeArguments(node);
|
||||
@@ -6389,7 +6390,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
const clone = createBasePrivateIdentifier(node.escapedText) as Mutable<GeneratedPrivateIdentifier>;
|
||||
clone.flags |= node.flags & ~NodeFlags.Synthesized;
|
||||
clone.transformFlags = node.transformFlags;
|
||||
setOriginalNode(clone, node);
|
||||
setOriginal(clone, node);
|
||||
setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate });
|
||||
return clone;
|
||||
}
|
||||
@@ -6398,7 +6399,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
const clone = createBasePrivateIdentifier(node.escapedText);
|
||||
clone.flags |= node.flags & ~NodeFlags.Synthesized;
|
||||
clone.transformFlags = node.transformFlags;
|
||||
setOriginalNode(clone, node);
|
||||
setOriginal(clone, node);
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -6432,7 +6433,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
|
||||
(clone as Mutable<T>).flags |= node.flags & ~NodeFlags.Synthesized;
|
||||
(clone as Mutable<T>).transformFlags = node.transformFlags;
|
||||
setOriginalNode(clone, node);
|
||||
setOriginal(clone, node);
|
||||
|
||||
for (const key in node) {
|
||||
if (hasProperty(clone, key) || !hasProperty(node, key)) {
|
||||
@@ -7197,7 +7198,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement;
|
||||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined;
|
||||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined {
|
||||
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement;
|
||||
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginal(createEmptyStatement(), statement), statement) : statement;
|
||||
}
|
||||
|
||||
function asVariableDeclaration(variableDeclaration: string | BindingName | VariableDeclaration | undefined) {
|
||||
@@ -7211,21 +7212,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
}
|
||||
return variableDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
function updateWithoutOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
|
||||
if (updated !== original) {
|
||||
setTextRange(updated, original);
|
||||
function update<T extends Node>(updated: Mutable<T>, original: T): T {
|
||||
if (updated !== original) {
|
||||
setOriginal(updated, original);
|
||||
setTextRange(updated, original);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
function updateWithOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
|
||||
if (updated !== original) {
|
||||
setOriginalNode(updated, original);
|
||||
setTextRange(updated, original);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
append,
|
||||
appendIfUnique,
|
||||
arrayFrom,
|
||||
arrayIsEqualTo,
|
||||
changeAnyExtension,
|
||||
CharacterCodes,
|
||||
@@ -901,11 +900,24 @@ export interface NonRelativeModuleNameResolutionCache extends NonRelativeNameRes
|
||||
getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ResolutionMode, redirectedReference?: ResolvedProjectReference): PerModuleNameCache;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MissingPackageJsonInfo {
|
||||
packageDirectory: string;
|
||||
directoryExists: boolean;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type PackageJsonInfoCacheEntry = PackageJsonInfo | MissingPackageJsonInfo;
|
||||
|
||||
/** @internal */
|
||||
export function isPackageJsonInfo(entry: PackageJsonInfoCacheEntry | undefined): entry is PackageJsonInfo {
|
||||
return !!(entry as PackageJsonInfo | undefined)?.contents;
|
||||
}
|
||||
|
||||
export interface PackageJsonInfoCache {
|
||||
/** @internal */ getPackageJsonInfo(packageJsonPath: string): PackageJsonInfo | boolean | undefined;
|
||||
/** @internal */ setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | boolean): void;
|
||||
/** @internal */ entries(): [Path, PackageJsonInfo | boolean][];
|
||||
/** @internal */ getInternalMap(): Map<Path, PackageJsonInfo | boolean> | undefined;
|
||||
/** @internal */ getPackageJsonInfo(packageJsonPath: string): PackageJsonInfoCacheEntry | undefined;
|
||||
/** @internal */ setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfoCacheEntry): void;
|
||||
/** @internal */ getInternalMap(): Map<Path, PackageJsonInfoCacheEntry> | undefined;
|
||||
clear(): void;
|
||||
/** @internal */ isReadonly?: boolean;
|
||||
}
|
||||
@@ -1021,21 +1033,17 @@ export function createCacheWithRedirects<K, V>(ownOptions: CompilerOptions | und
|
||||
}
|
||||
|
||||
function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache {
|
||||
let cache: Map<Path, PackageJsonInfo | boolean> | undefined;
|
||||
return { getPackageJsonInfo, setPackageJsonInfo, clear, entries, getInternalMap };
|
||||
let cache: Map<Path, PackageJsonInfoCacheEntry> | undefined;
|
||||
return { getPackageJsonInfo, setPackageJsonInfo, clear, getInternalMap };
|
||||
function getPackageJsonInfo(packageJsonPath: string) {
|
||||
return cache?.get(toPath(packageJsonPath, currentDirectory, getCanonicalFileName));
|
||||
}
|
||||
function setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | boolean) {
|
||||
function setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfoCacheEntry) {
|
||||
(cache ||= new Map()).set(toPath(packageJsonPath, currentDirectory, getCanonicalFileName), info);
|
||||
}
|
||||
function clear() {
|
||||
cache = undefined;
|
||||
}
|
||||
function entries() {
|
||||
const iter = cache?.entries();
|
||||
return iter ? arrayFrom(iter) : [];
|
||||
}
|
||||
function getInternalMap() {
|
||||
return cache;
|
||||
}
|
||||
@@ -2391,7 +2399,7 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures:
|
||||
|
||||
const existing = state.packageJsonInfoCache?.getPackageJsonInfo(packageJsonPath);
|
||||
if (existing !== undefined) {
|
||||
if (typeof existing !== "boolean") {
|
||||
if (isPackageJsonInfo(existing)) {
|
||||
if (traceEnabled) trace(host, Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath);
|
||||
state.affectingLocations?.push(packageJsonPath);
|
||||
return existing.packageDirectory === packageDirectory ?
|
||||
@@ -2399,7 +2407,7 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures:
|
||||
{ packageDirectory, contents: existing.contents };
|
||||
}
|
||||
else {
|
||||
if (existing && traceEnabled) trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath);
|
||||
if (existing.directoryExists && traceEnabled) trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath);
|
||||
state.failedLookupLocations?.push(packageJsonPath);
|
||||
return undefined;
|
||||
}
|
||||
@@ -2419,7 +2427,7 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures:
|
||||
if (directoryExists && traceEnabled) {
|
||||
trace(host, Diagnostics.File_0_does_not_exist, packageJsonPath);
|
||||
}
|
||||
if (state.packageJsonInfoCache && !state.packageJsonInfoCache.isReadonly) state.packageJsonInfoCache.setPackageJsonInfo(packageJsonPath, directoryExists);
|
||||
if (state.packageJsonInfoCache && !state.packageJsonInfoCache.isReadonly) state.packageJsonInfoCache.setPackageJsonInfo(packageJsonPath, { packageDirectory, directoryExists });
|
||||
// record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
|
||||
state.failedLookupLocations?.push(packageJsonPath);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import {
|
||||
isModuleBlock,
|
||||
isModuleDeclaration,
|
||||
isNonGlobalAmbientModule,
|
||||
isPackageJsonInfo,
|
||||
isRootedDiskPath,
|
||||
isSourceFile,
|
||||
isString,
|
||||
@@ -84,7 +85,6 @@ import {
|
||||
NodeFlags,
|
||||
NodeModulePathParts,
|
||||
normalizePath,
|
||||
Path,
|
||||
pathContainsNodeModules,
|
||||
pathIsBareSpecifier,
|
||||
pathIsRelative,
|
||||
@@ -200,7 +200,7 @@ function getPreferences(
|
||||
export function updateModuleSpecifier(
|
||||
compilerOptions: CompilerOptions,
|
||||
importingSourceFile: SourceFile,
|
||||
importingSourceFileName: Path,
|
||||
importingSourceFileName: string,
|
||||
toFileName: string,
|
||||
host: ModuleSpecifierResolutionHost,
|
||||
oldImportSpecifier: string,
|
||||
@@ -221,7 +221,7 @@ export function updateModuleSpecifier(
|
||||
export function getModuleSpecifier(
|
||||
compilerOptions: CompilerOptions,
|
||||
importingSourceFile: SourceFile,
|
||||
importingSourceFileName: Path,
|
||||
importingSourceFileName: string,
|
||||
toFileName: string,
|
||||
host: ModuleSpecifierResolutionHost,
|
||||
options: ModuleSpecifierOptions = {},
|
||||
@@ -238,15 +238,15 @@ export function getNodeModulesPackageName(
|
||||
preferences: UserPreferences,
|
||||
options: ModuleSpecifierOptions = {},
|
||||
): string | undefined {
|
||||
const info = getInfo(importingSourceFile.path, host);
|
||||
const modulePaths = getAllModulePaths(importingSourceFile.path, nodeModulesFileName, host, preferences, options);
|
||||
const info = getInfo(importingSourceFile.fileName, host);
|
||||
const modulePaths = getAllModulePaths(info, nodeModulesFileName, host, preferences, options);
|
||||
return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, preferences, /*packageNameOnly*/ true, options.overrideImportMode));
|
||||
}
|
||||
|
||||
function getModuleSpecifierWorker(
|
||||
compilerOptions: CompilerOptions,
|
||||
importingSourceFile: SourceFile,
|
||||
importingSourceFileName: Path,
|
||||
importingSourceFileName: string,
|
||||
toFileName: string,
|
||||
host: ModuleSpecifierResolutionHost,
|
||||
preferences: Preferences,
|
||||
@@ -254,7 +254,7 @@ function getModuleSpecifierWorker(
|
||||
options: ModuleSpecifierOptions = {},
|
||||
): string {
|
||||
const info = getInfo(importingSourceFileName, host);
|
||||
const modulePaths = getAllModulePaths(importingSourceFileName, toFileName, host, userPreferences, options);
|
||||
const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, options);
|
||||
return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) ||
|
||||
getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences);
|
||||
}
|
||||
@@ -346,7 +346,7 @@ export function getModuleSpecifiersWithCacheInfo(
|
||||
if (!moduleSourceFile) return { moduleSpecifiers: emptyArray, computedWithoutCache };
|
||||
|
||||
computedWithoutCache = true;
|
||||
modulePaths ||= getAllModulePathsWorker(importingSourceFile.path, moduleSourceFile.originalFileName, host);
|
||||
modulePaths ||= getAllModulePathsWorker(getInfo(importingSourceFile.fileName, host), moduleSourceFile.originalFileName, host);
|
||||
const result = computeModuleSpecifiers(
|
||||
modulePaths,
|
||||
compilerOptions,
|
||||
@@ -369,7 +369,7 @@ function computeModuleSpecifiers(
|
||||
options: ModuleSpecifierOptions = {},
|
||||
forAutoImport: boolean,
|
||||
): readonly string[] {
|
||||
const info = getInfo(importingSourceFile.path, host);
|
||||
const info = getInfo(importingSourceFile.fileName, host);
|
||||
const preferences = getPreferences(userPreferences, compilerOptions, importingSourceFile);
|
||||
const existingSpecifier = forEach(modulePaths, modulePath =>
|
||||
forEach(
|
||||
@@ -455,14 +455,21 @@ function computeModuleSpecifiers(
|
||||
|
||||
interface Info {
|
||||
readonly getCanonicalFileName: GetCanonicalFileName;
|
||||
readonly importingSourceFileName: Path;
|
||||
readonly sourceDirectory: Path;
|
||||
readonly importingSourceFileName: string;
|
||||
readonly sourceDirectory: string;
|
||||
readonly canonicalSourceDirectory: string;
|
||||
}
|
||||
// importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path
|
||||
function getInfo(importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info {
|
||||
function getInfo(importingSourceFileName: string, host: ModuleSpecifierResolutionHost): Info {
|
||||
importingSourceFileName = getNormalizedAbsolutePath(importingSourceFileName, host.getCurrentDirectory());
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true);
|
||||
const sourceDirectory = getDirectoryPath(importingSourceFileName);
|
||||
return { getCanonicalFileName, importingSourceFileName, sourceDirectory };
|
||||
return {
|
||||
getCanonicalFileName,
|
||||
importingSourceFileName,
|
||||
sourceDirectory,
|
||||
canonicalSourceDirectory: getCanonicalFileName(sourceDirectory),
|
||||
};
|
||||
}
|
||||
|
||||
function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: ResolutionMode, preferences: Preferences): string;
|
||||
@@ -473,7 +480,7 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { sourceDirectory, getCanonicalFileName } = info;
|
||||
const { sourceDirectory, canonicalSourceDirectory, getCanonicalFileName } = info;
|
||||
const allowedEndings = getAllowedEndingsInPrefererredOrder(importMode);
|
||||
const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName, allowedEndings, compilerOptions) ||
|
||||
processEnding(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), allowedEndings, compilerOptions);
|
||||
@@ -506,7 +513,7 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt
|
||||
toPath(getDirectoryPath(compilerOptions.configFilePath), host.getCurrentDirectory(), info.getCanonicalFileName) :
|
||||
info.getCanonicalFileName(host.getCurrentDirectory());
|
||||
const modulePath = toPath(moduleFileName, projectDirectory, getCanonicalFileName);
|
||||
const sourceIsInternal = startsWith(sourceDirectory, projectDirectory);
|
||||
const sourceIsInternal = startsWith(canonicalSourceDirectory, projectDirectory);
|
||||
const targetIsInternal = startsWith(modulePath, projectDirectory);
|
||||
if (sourceIsInternal && !targetIsInternal || !sourceIsInternal && targetIsInternal) {
|
||||
// 1. The import path crosses the boundary of the tsconfig.json-containing directory.
|
||||
@@ -623,37 +630,37 @@ export function forEachFileNameOfModule<T>(
|
||||
* Symlinks will be returned first so they are preferred over the real path.
|
||||
*/
|
||||
function getAllModulePaths(
|
||||
importingFilePath: Path,
|
||||
info: Info,
|
||||
importedFileName: string,
|
||||
host: ModuleSpecifierResolutionHost,
|
||||
preferences: UserPreferences,
|
||||
options: ModuleSpecifierOptions = {},
|
||||
) {
|
||||
const importingFilePath = toPath(info.importingSourceFileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host));
|
||||
const importedFilePath = toPath(importedFileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host));
|
||||
const cache = host.getModuleSpecifierCache?.();
|
||||
if (cache) {
|
||||
const cached = cache.get(importingFilePath, importedFilePath, preferences, options);
|
||||
if (cached?.modulePaths) return cached.modulePaths;
|
||||
}
|
||||
const modulePaths = getAllModulePathsWorker(importingFilePath, importedFileName, host);
|
||||
const modulePaths = getAllModulePathsWorker(info, importedFileName, host);
|
||||
if (cache) {
|
||||
cache.setModulePaths(importingFilePath, importedFilePath, preferences, options, modulePaths);
|
||||
}
|
||||
return modulePaths;
|
||||
}
|
||||
|
||||
function getAllModulePathsWorker(importingFileName: Path, importedFileName: string, host: ModuleSpecifierResolutionHost): readonly ModulePath[] {
|
||||
const getCanonicalFileName = hostGetCanonicalFileName(host);
|
||||
function getAllModulePathsWorker(info: Info, importedFileName: string, host: ModuleSpecifierResolutionHost): readonly ModulePath[] {
|
||||
const allFileNames = new Map<string, { path: string; isRedirect: boolean; isInNodeModules: boolean; }>();
|
||||
let importedFileFromNodeModules = false;
|
||||
forEachFileNameOfModule(
|
||||
importingFileName,
|
||||
info.importingSourceFileName,
|
||||
importedFileName,
|
||||
host,
|
||||
/*preferSymlinks*/ true,
|
||||
(path, isRedirect) => {
|
||||
const isInNodeModules = pathContainsNodeModules(path);
|
||||
allFileNames.set(path, { path: getCanonicalFileName(path), isRedirect, isInNodeModules });
|
||||
allFileNames.set(path, { path: info.getCanonicalFileName(path), isRedirect, isInNodeModules });
|
||||
importedFileFromNodeModules = importedFileFromNodeModules || isInNodeModules;
|
||||
// don't return value, so we collect everything
|
||||
},
|
||||
@@ -662,7 +669,7 @@ function getAllModulePathsWorker(importingFileName: Path, importedFileName: stri
|
||||
// Sort by paths closest to importing file Name directory
|
||||
const sortedPaths: ModulePath[] = [];
|
||||
for (
|
||||
let directory = getDirectoryPath(importingFileName);
|
||||
let directory = info.canonicalSourceDirectory;
|
||||
allFileNames.size !== 0;
|
||||
) {
|
||||
const directoryStart = ensureTrailingDirectorySeparator(directory);
|
||||
@@ -684,7 +691,10 @@ function getAllModulePathsWorker(importingFileName: Path, importedFileName: stri
|
||||
directory = newDirectory;
|
||||
}
|
||||
if (allFileNames.size) {
|
||||
const remainingPaths = arrayFrom(allFileNames.values());
|
||||
const remainingPaths = arrayFrom(
|
||||
allFileNames.entries(),
|
||||
([fileName, { isRedirect, isInNodeModules }]): ModulePath => ({ path: fileName, isRedirect, isInNodeModules }),
|
||||
);
|
||||
if (remainingPaths.length > 1) remainingPaths.sort(comparePathsByRedirectAndNumberOfDirectorySeparators);
|
||||
sortedPaths.push(...remainingPaths);
|
||||
}
|
||||
@@ -914,7 +924,7 @@ function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileNam
|
||||
return processEnding(shortest, allowedEndings, compilerOptions);
|
||||
}
|
||||
|
||||
function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ResolutionMode): string | undefined {
|
||||
function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, canonicalSourceDirectory }: Info, importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ResolutionMode): string | undefined {
|
||||
if (!host.fileExists || !host.readFile) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -967,7 +977,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
|
||||
// Get a path that's relative to node_modules or the importing file's path
|
||||
// if node_modules folder is in this folder or any of its parent folders, no need to keep it.
|
||||
const pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex));
|
||||
if (!(startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) {
|
||||
if (!(startsWith(canonicalSourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -983,7 +993,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
|
||||
let moduleFileToTry = path;
|
||||
let maybeBlockedByTypesVersions = false;
|
||||
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
|
||||
if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
|
||||
if (isPackageJsonInfo(cachedPackageJson) || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
|
||||
const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
|
||||
const importMode = overrideMode || importingSourceFile.impliedNodeFormat;
|
||||
if (getResolvePackageJsonExports(options)) {
|
||||
|
||||
+30
-19
@@ -1971,8 +1971,9 @@ namespace Parser {
|
||||
|
||||
// If we parsed this as an external module, it may contain top-level await
|
||||
if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) {
|
||||
const oldSourceFile = sourceFile;
|
||||
sourceFile = reparseTopLevelAwait(sourceFile);
|
||||
setFields(sourceFile);
|
||||
if (oldSourceFile !== sourceFile) setFields(sourceFile);
|
||||
}
|
||||
|
||||
return sourceFile;
|
||||
@@ -7497,8 +7498,9 @@ namespace Parser {
|
||||
return nextToken() === SyntaxKind.StringLiteral;
|
||||
}
|
||||
|
||||
function nextTokenIsFromKeyword() {
|
||||
return nextToken() === SyntaxKind.FromKeyword;
|
||||
function nextTokenIsFromKeywordOrEqualsToken() {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.FromKeyword || token() === SyntaxKind.EqualsToken;
|
||||
}
|
||||
|
||||
function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
|
||||
@@ -8334,7 +8336,7 @@ namespace Parser {
|
||||
let isTypeOnly = false;
|
||||
if (
|
||||
identifier?.escapedText === "type" &&
|
||||
(token() !== SyntaxKind.FromKeyword || isIdentifier() && lookAhead(nextTokenIsFromKeyword)) &&
|
||||
(token() !== SyntaxKind.FromKeyword || isIdentifier() && lookAhead(nextTokenIsFromKeywordOrEqualsToken)) &&
|
||||
(isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration())
|
||||
) {
|
||||
isTypeOnly = true;
|
||||
@@ -9208,18 +9210,7 @@ namespace Parser {
|
||||
}
|
||||
nextTokenJSDoc(); // start at token after link, then skip any whitespace
|
||||
skipWhitespace();
|
||||
// parseEntityName logs an error for non-identifier, so create a MissingNode ourselves to avoid the error
|
||||
const p2 = getNodePos();
|
||||
let name: EntityName | JSDocMemberName | undefined = tokenIsIdentifierOrKeyword(token())
|
||||
? parseEntityName(/*allowReservedWords*/ true)
|
||||
: undefined;
|
||||
if (name) {
|
||||
while (token() === SyntaxKind.PrivateIdentifier) {
|
||||
reScanHashToken(); // rescan #id as # id
|
||||
nextTokenJSDoc(); // then skip the #
|
||||
name = finishNode(factory.createJSDocMemberName(name, parseIdentifier()), p2);
|
||||
}
|
||||
}
|
||||
const name = parseJSDocLinkName();
|
||||
const text = [];
|
||||
while (token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia && token() !== SyntaxKind.EndOfFileToken) {
|
||||
text.push(scanner.getTokenText());
|
||||
@@ -9231,6 +9222,24 @@ namespace Parser {
|
||||
return finishNode(create(name, text.join("")), start, scanner.getTokenEnd());
|
||||
}
|
||||
|
||||
function parseJSDocLinkName() {
|
||||
if (tokenIsIdentifierOrKeyword(token())) {
|
||||
const pos = getNodePos();
|
||||
|
||||
let name: EntityName | JSDocMemberName = parseIdentifierName();
|
||||
while (parseOptional(SyntaxKind.DotToken)) {
|
||||
name = finishNode(factory.createQualifiedName(name, token() === SyntaxKind.PrivateIdentifier ? createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false) : parseIdentifier()), pos);
|
||||
}
|
||||
while (token() === SyntaxKind.PrivateIdentifier) {
|
||||
reScanHashToken();
|
||||
nextTokenJSDoc();
|
||||
name = finishNode(factory.createJSDocMemberName(name, parseIdentifier()), pos);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseJSDocLinkPrefix() {
|
||||
skipWhitespaceOrAsterisk();
|
||||
if (
|
||||
@@ -9334,7 +9343,7 @@ namespace Parser {
|
||||
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) {
|
||||
if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
|
||||
const pos = getNodePos();
|
||||
let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | false;
|
||||
let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | JSDocThisTag | false;
|
||||
let children: JSDocPropertyLikeTag[] | undefined;
|
||||
while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) {
|
||||
if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
|
||||
@@ -9626,7 +9635,7 @@ namespace Parser {
|
||||
return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false;
|
||||
}
|
||||
|
||||
function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false {
|
||||
function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false {
|
||||
let canParseTag = true;
|
||||
let seenAsterisk = false;
|
||||
while (true) {
|
||||
@@ -9663,7 +9672,7 @@ namespace Parser {
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false {
|
||||
function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false {
|
||||
Debug.assert(token() === SyntaxKind.AtToken);
|
||||
const start = scanner.getTokenFullStart();
|
||||
nextTokenJSDoc();
|
||||
@@ -9685,6 +9694,8 @@ namespace Parser {
|
||||
break;
|
||||
case "template":
|
||||
return parseTemplateTag(start, tagName, indent, indentText);
|
||||
case "this":
|
||||
return parseThisTag(start, tagName, indent, indentText);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
+23
-22
@@ -4,7 +4,6 @@ import {
|
||||
addRange,
|
||||
addRelatedInfo,
|
||||
append,
|
||||
arrayFrom,
|
||||
arrayIsEqualTo,
|
||||
AsExpression,
|
||||
BuilderProgram,
|
||||
@@ -216,7 +215,6 @@ import {
|
||||
LibResolution,
|
||||
libs,
|
||||
mapDefined,
|
||||
mapDefinedIterator,
|
||||
maybeBind,
|
||||
memoize,
|
||||
MethodDeclaration,
|
||||
@@ -1240,7 +1238,8 @@ export function isProgramUptoDate(
|
||||
if (program.getSourceFiles().some(sourceFileNotUptoDate)) return false;
|
||||
|
||||
// If any of the missing file paths are now created
|
||||
if (program.getMissingFilePaths().some(fileExists)) return false;
|
||||
const missingPaths = program.getMissingFilePaths();
|
||||
if (missingPaths && forEachEntry(missingPaths, fileExists)) return false;
|
||||
|
||||
const currentOptions = program.getCompilerOptions();
|
||||
// If the compilation settings do no match, then the program is not up-to-date
|
||||
@@ -1694,8 +1693,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
* - false if sourceFile missing for source of project reference redirect
|
||||
* - undefined otherwise
|
||||
*/
|
||||
const filesByName = new Map<string, SourceFile | false | undefined>();
|
||||
let missingFilePaths: readonly Path[] | undefined;
|
||||
const filesByName = new Map<Path, SourceFile | false | undefined>();
|
||||
let missingFileNames = new Map<Path, string>();
|
||||
// stores 'filename -> file association' ignoring case
|
||||
// used to track cases when two file names differ only in casing
|
||||
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? new Map<string, SourceFile>() : undefined;
|
||||
@@ -1812,14 +1811,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
}
|
||||
|
||||
missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined));
|
||||
files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles);
|
||||
processingDefaultLibFiles = undefined;
|
||||
processingOtherFiles = undefined;
|
||||
}
|
||||
|
||||
Debug.assert(!!missingFilePaths);
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
// not part of the new program.
|
||||
if (oldProgram && host.onReleaseOldSourceFile) {
|
||||
@@ -1869,7 +1865,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
getSourceFile,
|
||||
getSourceFileByPath,
|
||||
getSourceFiles: () => files,
|
||||
getMissingFilePaths: () => missingFilePaths!, // TODO: GH#18217
|
||||
getMissingFilePaths: () => missingFileNames,
|
||||
getModuleResolutionCache: () => moduleResolutionCache,
|
||||
getFilesByNameMap: () => filesByName,
|
||||
getCompilerOptions: () => options,
|
||||
@@ -2398,7 +2394,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// If the missing file paths are now present, it can change the progam structure,
|
||||
// and hence cant reuse the structure.
|
||||
// This is same as how we dont reuse the structure if one of the file from old program is now missing
|
||||
if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) {
|
||||
if (forEachEntry(oldProgram.getMissingFilePaths(), missingFileName => host.fileExists(missingFileName))) {
|
||||
return StructureIsReused.Not;
|
||||
}
|
||||
|
||||
@@ -2579,7 +2575,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
automaticTypeDirectiveNames = getAutomaticTypeDirectiveNames(options, host);
|
||||
if (!arrayIsEqualTo(oldProgram.getAutomaticTypeDirectiveNames(), automaticTypeDirectiveNames)) return StructureIsReused.SafeModules;
|
||||
}
|
||||
missingFilePaths = oldProgram.getMissingFilePaths();
|
||||
missingFileNames = oldProgram.getMissingFilePaths();
|
||||
|
||||
// update fileName -> file mapping
|
||||
Debug.assert(newSourceFiles.length === oldProgram.getSourceFiles().length);
|
||||
@@ -2643,7 +2639,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// Use local caches
|
||||
const path = toPath(f);
|
||||
if (getSourceFileByPath(path)) return true;
|
||||
if (contains(missingFilePaths, path)) return false;
|
||||
if (missingFileNames.has(path)) return false;
|
||||
// Before falling back to the host
|
||||
return host.fileExists(f);
|
||||
},
|
||||
@@ -3602,7 +3598,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
const file = isString(source) ?
|
||||
findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId) :
|
||||
undefined;
|
||||
if (file) addFileToFilesByName(file, path, /*redirectedPath*/ undefined);
|
||||
if (file) addFileToFilesByName(file, path, fileName, /*redirectedPath*/ undefined);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -3688,7 +3684,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// Instead of creating a duplicate, just redirect to the existing one.
|
||||
const dupFile = createRedirectedSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName, sourceFileOptions);
|
||||
redirectTargetsMap.add(fileFromPackageId.path, fileName);
|
||||
addFileToFilesByName(dupFile, path, redirectedPath);
|
||||
addFileToFilesByName(dupFile, path, fileName, redirectedPath);
|
||||
addFileIncludeReason(dupFile, reason);
|
||||
sourceFileToPackageName.set(path, packageIdToPackageName(packageId));
|
||||
processingOtherFiles!.push(dupFile);
|
||||
@@ -3700,7 +3696,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
sourceFileToPackageName.set(path, packageIdToPackageName(packageId));
|
||||
}
|
||||
}
|
||||
addFileToFilesByName(file, path, redirectedPath);
|
||||
addFileToFilesByName(file, path, fileName, redirectedPath);
|
||||
|
||||
if (file) {
|
||||
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
|
||||
@@ -3751,15 +3747,20 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (file) fileReasons.add(file.path, reason);
|
||||
}
|
||||
|
||||
function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
|
||||
function addFileToFilesByName(file: SourceFile | undefined, path: Path, fileName: string, redirectedPath: Path | undefined) {
|
||||
if (redirectedPath) {
|
||||
filesByName.set(redirectedPath, file);
|
||||
filesByName.set(path, file || false);
|
||||
updateFilesByNameMap(fileName, redirectedPath, file);
|
||||
updateFilesByNameMap(fileName, path, file || false);
|
||||
}
|
||||
else {
|
||||
filesByName.set(path, file);
|
||||
updateFilesByNameMap(fileName, path, file);
|
||||
}
|
||||
}
|
||||
function updateFilesByNameMap(fileName: string, path: Path, file: SourceFile | false | undefined) {
|
||||
filesByName.set(path, file);
|
||||
if (file !== undefined) missingFileNames.delete(path);
|
||||
else missingFileNames.set(path, fileName);
|
||||
}
|
||||
|
||||
function getProjectReferenceRedirect(fileName: string): string | undefined {
|
||||
const referencedProject = getProjectReferenceRedirectProject(fileName);
|
||||
@@ -4130,19 +4131,19 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (host.getParsedCommandLine) {
|
||||
commandLine = host.getParsedCommandLine(refPath);
|
||||
if (!commandLine) {
|
||||
addFileToFilesByName(/*file*/ undefined, sourceFilePath, /*redirectedPath*/ undefined);
|
||||
addFileToFilesByName(/*file*/ undefined, sourceFilePath, refPath, /*redirectedPath*/ undefined);
|
||||
projectReferenceRedirects.set(sourceFilePath, false);
|
||||
return undefined;
|
||||
}
|
||||
sourceFile = Debug.checkDefined(commandLine.options.configFile);
|
||||
Debug.assert(!sourceFile.path || sourceFile.path === sourceFilePath);
|
||||
addFileToFilesByName(sourceFile, sourceFilePath, /*redirectedPath*/ undefined);
|
||||
addFileToFilesByName(sourceFile, sourceFilePath, refPath, /*redirectedPath*/ undefined);
|
||||
}
|
||||
else {
|
||||
// An absolute path pointing to the containing directory of the config file
|
||||
const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), currentDirectory);
|
||||
sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined;
|
||||
addFileToFilesByName(sourceFile, sourceFilePath, /*redirectedPath*/ undefined);
|
||||
addFileToFilesByName(sourceFile, sourceFilePath, refPath, /*redirectedPath*/ undefined);
|
||||
if (sourceFile === undefined) {
|
||||
projectReferenceRedirects.set(sourceFilePath, false);
|
||||
return undefined;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
arrayToMap,
|
||||
CachedDirectoryStructureHost,
|
||||
clearMap,
|
||||
closeFileWatcher,
|
||||
@@ -54,7 +53,7 @@ import {
|
||||
normalizePath,
|
||||
PackageId,
|
||||
packageIdToString,
|
||||
PackageJsonInfo,
|
||||
PackageJsonInfoCacheEntry,
|
||||
parseNodeModuleFromPath,
|
||||
Path,
|
||||
PathPathComponents,
|
||||
@@ -1179,7 +1178,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
}
|
||||
|
||||
function invalidateAffectingFileWatcher(path: string, packageJsonMap: Map<Path, PackageJsonInfo | boolean> | undefined) {
|
||||
function invalidateAffectingFileWatcher(path: string, packageJsonMap: Map<Path, PackageJsonInfoCacheEntry> | undefined) {
|
||||
const watcher = fileWatchesOfAffectingLocations.get(path);
|
||||
if (watcher?.resolutions) (affectingPathChecks ??= new Set()).add(path);
|
||||
if (watcher?.files) (affectingPathChecksForFile ??= new Set()).add(path);
|
||||
@@ -1482,9 +1481,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
clearMap(typeRootsWatches, closeFileWatcher);
|
||||
}
|
||||
|
||||
function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher {
|
||||
function createTypeRootsWatch(typeRoot: string): FileWatcher {
|
||||
// Create new watch and recursive info
|
||||
return canWatchTypeRootPath(typeRootPath) ?
|
||||
return canWatchTypeRootPath(typeRoot) ?
|
||||
resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => {
|
||||
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
|
||||
if (cachedDirectoryStructureHost) {
|
||||
@@ -1502,7 +1501,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
// So handle to failed lookup locations here as well to ensure we are invalidating resolutions
|
||||
const dirPath = getDirectoryToWatchFailedLookupLocationFromTypeRoot(
|
||||
typeRoot,
|
||||
typeRootPath,
|
||||
resolutionHost.toPath(typeRoot),
|
||||
rootPath,
|
||||
rootPathComponents,
|
||||
getCurrentDirectory,
|
||||
@@ -1534,7 +1533,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
if (typeRoots) {
|
||||
mutateMap(
|
||||
typeRootsWatches,
|
||||
arrayToMap(typeRoots, tr => resolutionHost.toPath(tr)),
|
||||
new Set(typeRoots),
|
||||
{
|
||||
createNewValue: createTypeRootsWatch,
|
||||
onDeleteValue: closeFileWatcher,
|
||||
|
||||
@@ -65,6 +65,7 @@ import {
|
||||
getLeadingCommentRangesOfNode,
|
||||
getLineAndCharacterOfPosition,
|
||||
getNameOfDeclaration,
|
||||
getNormalizedAbsolutePath,
|
||||
getOriginalNodeId,
|
||||
getOutputPathsFor,
|
||||
getParseTreeNode,
|
||||
@@ -208,7 +209,6 @@ import {
|
||||
SymbolTracker,
|
||||
SyntaxKind,
|
||||
toFileNameLowerCase,
|
||||
toPath,
|
||||
TransformationContext,
|
||||
transformNodes,
|
||||
tryCast,
|
||||
@@ -631,8 +631,8 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
const specifier = moduleSpecifiers.getModuleSpecifier(
|
||||
options,
|
||||
currentSourceFile,
|
||||
toPath(outputFilePath, host.getCurrentDirectory(), host.getCanonicalFileName),
|
||||
toPath(declFileName, host.getCurrentDirectory(), host.getCanonicalFileName),
|
||||
getNormalizedAbsolutePath(outputFilePath, host.getCurrentDirectory()),
|
||||
getNormalizedAbsolutePath(declFileName, host.getCurrentDirectory()),
|
||||
host,
|
||||
);
|
||||
if (!pathIsRelative(specifier)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
AffectedFileResult,
|
||||
arrayToMap,
|
||||
arrayFrom,
|
||||
assertType,
|
||||
BuilderProgram,
|
||||
BuildInfo,
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
clearMap,
|
||||
closeFileWatcher,
|
||||
closeFileWatcherOf,
|
||||
combinePaths,
|
||||
commonOptionsWithBuild,
|
||||
CompilerHost,
|
||||
CompilerOptions,
|
||||
@@ -48,6 +49,7 @@ import {
|
||||
findIndex,
|
||||
flattenDiagnosticMessageText,
|
||||
forEach,
|
||||
forEachKey,
|
||||
ForegroundColorEscapeSequences,
|
||||
formatColorAndReset,
|
||||
getAllProjectOutputs,
|
||||
@@ -72,10 +74,10 @@ import {
|
||||
isArray,
|
||||
isIgnoredFileFromWildCardWatching,
|
||||
isIncrementalCompilation,
|
||||
isPackageJsonInfo,
|
||||
isString,
|
||||
listFiles,
|
||||
loadWithModeAwareCache,
|
||||
map,
|
||||
maybeBind,
|
||||
missingFileModifiedTime,
|
||||
ModuleResolutionCache,
|
||||
@@ -409,14 +411,14 @@ interface SolutionBuilderState<T extends BuilderProgram> extends WatchFactory<Wa
|
||||
// Watch state
|
||||
readonly watch: boolean;
|
||||
readonly allWatchedWildcardDirectories: Map<ResolvedConfigFilePath, Map<string, WildcardDirectoryWatcher>>;
|
||||
readonly allWatchedInputFiles: Map<ResolvedConfigFilePath, Map<Path, FileWatcher>>;
|
||||
readonly allWatchedInputFiles: Map<ResolvedConfigFilePath, Map<string, FileWatcher>>;
|
||||
readonly allWatchedConfigFiles: Map<ResolvedConfigFilePath, FileWatcher>;
|
||||
readonly allWatchedExtendedConfigFiles: Map<Path, SharedExtendedConfigFileWatcher<ResolvedConfigFilePath>>;
|
||||
readonly allWatchedPackageJsonFiles: Map<ResolvedConfigFilePath, Map<Path, FileWatcher>>;
|
||||
readonly filesWatched: Map<Path, FileWatcherWithModifiedTime | Date>;
|
||||
readonly outputTimeStamps: Map<ResolvedConfigFilePath, Map<Path, Date>>;
|
||||
|
||||
readonly lastCachedPackageJsonLookups: Map<ResolvedConfigFilePath, readonly (readonly [Path, object | boolean])[] | undefined>;
|
||||
readonly lastCachedPackageJsonLookups: Map<ResolvedConfigFilePath, Set<string> | undefined>;
|
||||
|
||||
timerToBuildInvalidatedProject: any;
|
||||
reportFileChangeDetected: boolean;
|
||||
@@ -660,9 +662,9 @@ function createStateBuildOrder<T extends BuilderProgram>(state: SolutionBuilderS
|
||||
state.resolvedConfigFilePaths.clear();
|
||||
|
||||
// TODO(rbuckton): Should be a `Set`, but that requires changing the code below that uses `mutateMapSkippingNewValues`
|
||||
const currentProjects = new Map(
|
||||
const currentProjects = new Set(
|
||||
getBuildOrderFromAnyBuildOrder(buildOrder).map(
|
||||
resolved => [toResolvedConfigFilePath(state, resolved), true as const],
|
||||
resolved => toResolvedConfigFilePath(state, resolved),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -676,6 +678,7 @@ function createStateBuildOrder<T extends BuilderProgram>(state: SolutionBuilderS
|
||||
mutateMapSkippingNewValues(state.projectErrorsReported, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.buildInfoCache, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.outputTimeStamps, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.lastCachedPackageJsonLookups, currentProjects, noopOnDelete);
|
||||
|
||||
// Remove watches for the program no longer in the solution
|
||||
if (state.watch) {
|
||||
@@ -1083,14 +1086,17 @@ function createBuildOrUpdateInvalidedProject<T extends BuilderProgram>(
|
||||
config.projectReferences,
|
||||
);
|
||||
if (state.watch) {
|
||||
const internalMap = state.moduleResolutionCache?.getPackageJsonInfoCache().getInternalMap();
|
||||
state.lastCachedPackageJsonLookups.set(
|
||||
projectPath,
|
||||
state.moduleResolutionCache && map(
|
||||
state.moduleResolutionCache.getPackageJsonInfoCache().entries(),
|
||||
([path, data]) => ([state.host.realpath && data ? toPath(state, state.host.realpath(path)) : path, data] as const),
|
||||
),
|
||||
internalMap && new Set(arrayFrom(
|
||||
internalMap.values(),
|
||||
data =>
|
||||
state.host.realpath && (isPackageJsonInfo(data) || data.directoryExists) ?
|
||||
state.host.realpath(combinePaths(data.packageDirectory, "package.json")) :
|
||||
combinePaths(data.packageDirectory, "package.json"),
|
||||
)),
|
||||
);
|
||||
|
||||
state.builderPrograms.set(projectPath, program);
|
||||
}
|
||||
step++;
|
||||
@@ -1983,9 +1989,10 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
|
||||
if (extendedConfigStatus) return extendedConfigStatus;
|
||||
|
||||
// Check package file time
|
||||
const dependentPackageFileStatus = forEach(
|
||||
state.lastCachedPackageJsonLookups.get(resolvedPath) || emptyArray,
|
||||
([path]) => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName!),
|
||||
const packageJsonLookups = state.lastCachedPackageJsonLookups.get(resolvedPath);
|
||||
const dependentPackageFileStatus = packageJsonLookups && forEachKey(
|
||||
packageJsonLookups,
|
||||
path => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName!),
|
||||
);
|
||||
if (dependentPackageFileStatus) return dependentPackageFileStatus;
|
||||
|
||||
@@ -2376,7 +2383,7 @@ function watchWildCardDirectories<T extends BuilderProgram>(state: SolutionBuild
|
||||
if (!state.watch) return;
|
||||
updateWatchingWildcardDirectories(
|
||||
getOrCreateValueMapFromConfigFileMap(state.allWatchedWildcardDirectories, resolvedPath),
|
||||
new Map(Object.entries(parsed.wildcardDirectories!)),
|
||||
parsed.wildcardDirectories,
|
||||
(dir, flags) =>
|
||||
state.watchDirectory(
|
||||
dir,
|
||||
@@ -2410,9 +2417,9 @@ function watchInputFiles<T extends BuilderProgram>(state: SolutionBuilderState<T
|
||||
if (!state.watch) return;
|
||||
mutateMap(
|
||||
getOrCreateValueMapFromConfigFileMap(state.allWatchedInputFiles, resolvedPath),
|
||||
arrayToMap(parsed.fileNames, fileName => toPath(state, fileName)),
|
||||
new Set(parsed.fileNames),
|
||||
{
|
||||
createNewValue: (_path, input) =>
|
||||
createNewValue: input =>
|
||||
watchFile(
|
||||
state,
|
||||
input,
|
||||
@@ -2431,12 +2438,12 @@ function watchPackageJsonFiles<T extends BuilderProgram>(state: SolutionBuilderS
|
||||
if (!state.watch || !state.lastCachedPackageJsonLookups) return;
|
||||
mutateMap(
|
||||
getOrCreateValueMapFromConfigFileMap(state.allWatchedPackageJsonFiles, resolvedPath),
|
||||
new Map(state.lastCachedPackageJsonLookups.get(resolvedPath)),
|
||||
state.lastCachedPackageJsonLookups.get(resolvedPath),
|
||||
{
|
||||
createNewValue: (path, _input) =>
|
||||
createNewValue: input =>
|
||||
watchFile(
|
||||
state,
|
||||
path,
|
||||
input,
|
||||
() => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Update),
|
||||
PollingInterval.High,
|
||||
parsed?.watchOptions,
|
||||
|
||||
+12
-10
@@ -3663,10 +3663,10 @@ export interface ImportClause extends NamedDeclaration {
|
||||
export type AssertionKey = ImportAttributeName;
|
||||
|
||||
/** @deprecated */
|
||||
export type AssertEntry = ImportAttribute;
|
||||
export interface AssertEntry extends ImportAttribute {}
|
||||
|
||||
/** @deprecated */
|
||||
export type AssertClause = ImportAttributes;
|
||||
export interface AssertClause extends ImportAttributes {}
|
||||
|
||||
export type ImportAttributeName = Identifier | StringLiteral;
|
||||
|
||||
@@ -4684,11 +4684,11 @@ export interface Program extends ScriptReferenceHost {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
getMissingFilePaths(): readonly Path[];
|
||||
getMissingFilePaths(): Map<Path, string>;
|
||||
/** @internal */
|
||||
getModuleResolutionCache(): ModuleResolutionCache | undefined;
|
||||
/** @internal */
|
||||
getFilesByNameMap(): Map<string, SourceFile | false | undefined>;
|
||||
getFilesByNameMap(): Map<Path, SourceFile | false | undefined>;
|
||||
|
||||
/** @internal */
|
||||
resolvedModules: Map<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
|
||||
@@ -6130,7 +6130,7 @@ export const enum TypeFlags {
|
||||
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
|
||||
StructuredOrInstantiable = StructuredType | Instantiable,
|
||||
/** @internal */
|
||||
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection | TemplateLiteral,
|
||||
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection,
|
||||
/** @internal */
|
||||
Simplifiable = IndexedAccess | Conditional,
|
||||
/** @internal */
|
||||
@@ -6153,6 +6153,8 @@ export const enum TypeFlags {
|
||||
/** @internal */
|
||||
IncludesInstantiable = Substitution,
|
||||
/** @internal */
|
||||
IncludesConstrainedTypeVariable = StringMapping,
|
||||
/** @internal */
|
||||
NotPrimitiveUnion = Any | Unknown | Void | Never | Object | Intersection | IncludesInstantiable,
|
||||
}
|
||||
|
||||
@@ -6289,7 +6291,7 @@ export const enum ObjectFlags {
|
||||
/** @internal */
|
||||
IdenticalBaseTypeExists = 1 << 26, // has a defined cachedEquivalentBaseType member
|
||||
|
||||
// Flags that require TypeFlags.UnionOrIntersection, TypeFlags.Substitution, or TypeFlags.TemplateLiteral
|
||||
// Flags that require TypeFlags.UnionOrIntersection or TypeFlags.Substitution
|
||||
/** @internal */
|
||||
IsGenericTypeComputed = 1 << 21, // IsGenericObjectType flag has been computed
|
||||
/** @internal */
|
||||
@@ -6313,10 +6315,12 @@ export const enum ObjectFlags {
|
||||
IsNeverIntersectionComputed = 1 << 24, // IsNeverLike flag has been computed
|
||||
/** @internal */
|
||||
IsNeverIntersection = 1 << 25, // Intersection reduces to never
|
||||
/** @internal */
|
||||
IsConstrainedTypeVariable = 1 << 26, // T & C, where T's constraint and C are primitives, object, or {}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type ObjectFlagsType = NullableType | ObjectType | UnionType | IntersectionType | TemplateLiteralType;
|
||||
export type ObjectFlagsType = NullableType | ObjectType | UnionType | IntersectionType;
|
||||
|
||||
// Object types (TypeFlags.ObjectType)
|
||||
// dprint-ignore
|
||||
@@ -6675,8 +6679,6 @@ export interface ConditionalType extends InstantiableType {
|
||||
}
|
||||
|
||||
export interface TemplateLiteralType extends InstantiableType {
|
||||
/** @internal */
|
||||
objectFlags: ObjectFlags;
|
||||
texts: readonly string[]; // Always one element longer than types
|
||||
types: readonly Type[]; // Always at least one element
|
||||
}
|
||||
@@ -7431,7 +7433,7 @@ export interface CommandLineOptionBase {
|
||||
isFilePath?: boolean; // True if option value is a path or fileName
|
||||
shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
|
||||
description?: DiagnosticMessage; // The message describing what the command line switch does.
|
||||
defaultValueDescription?: string | number | boolean | DiagnosticMessage; // The message describing what the dafault value is. string type is prepared for fixed chosen like "false" which do not need I18n.
|
||||
defaultValueDescription?: string | number | boolean | DiagnosticMessage | undefined; // The message describing what the dafault value is. string type is prepared for fixed chosen like "false" which do not need I18n.
|
||||
paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter
|
||||
isTSConfigOnly?: boolean; // True if option can only be specified via tsconfig.json file
|
||||
isCommandLineOnly?: boolean;
|
||||
|
||||
+36
-11
@@ -5825,7 +5825,8 @@ export function createDiagnosticCollection(): DiagnosticCollection {
|
||||
}
|
||||
|
||||
const templateSubstitutionRegExp = /\$\{/g;
|
||||
function escapeTemplateSubstitution(str: string): string {
|
||||
/** @internal */
|
||||
export function escapeTemplateSubstitution(str: string): string {
|
||||
return str.replace(templateSubstitutionRegExp, "\\${");
|
||||
}
|
||||
|
||||
@@ -7831,9 +7832,12 @@ export function clearMap<K, T>(map: { forEach: Map<K, T>["forEach"]; clear: Map<
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MutateMapSkippingNewValuesOptions<K, T, U> {
|
||||
export interface MutateMapSkippingNewValuesDelete<K, T> {
|
||||
onDeleteValue(existingValue: T, key: K): void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MutateMapSkippingNewValuesOptions<K, T, U> extends MutateMapSkippingNewValuesDelete<K, T> {
|
||||
/**
|
||||
* If present this is called with the key when there is value for that key both in new map as well as existing map provided
|
||||
* Caller can then decide to update or remove this key.
|
||||
@@ -7848,47 +7852,68 @@ export interface MutateMapSkippingNewValuesOptions<K, T, U> {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function mutateMapSkippingNewValues<K, T>(
|
||||
map: Map<K, T>,
|
||||
newMap: ReadonlySet<K> | undefined,
|
||||
options: MutateMapSkippingNewValuesDelete<K, T>,
|
||||
): void;
|
||||
/** @internal */
|
||||
export function mutateMapSkippingNewValues<K, T, U>(
|
||||
map: Map<K, T>,
|
||||
newMap: ReadonlyMap<K, U>,
|
||||
newMap: ReadonlyMap<K, U> | undefined,
|
||||
options: MutateMapSkippingNewValuesOptions<K, T, U>,
|
||||
): void;
|
||||
export function mutateMapSkippingNewValues<K, T, U>(
|
||||
map: Map<K, T>,
|
||||
newMap: ReadonlyMap<K, U> | ReadonlySet<K> | undefined,
|
||||
options: MutateMapSkippingNewValuesOptions<K, T, U>,
|
||||
) {
|
||||
const { onDeleteValue, onExistingValue } = options;
|
||||
// Needs update
|
||||
map.forEach((existingValue, key) => {
|
||||
const valueInNewMap = newMap.get(key);
|
||||
// Not present any more in new map, remove it
|
||||
if (valueInNewMap === undefined) {
|
||||
if (!newMap?.has(key)) {
|
||||
map.delete(key);
|
||||
onDeleteValue(existingValue, key);
|
||||
}
|
||||
// If present notify about existing values
|
||||
else if (onExistingValue) {
|
||||
onExistingValue(existingValue, valueInNewMap, key);
|
||||
onExistingValue(existingValue, (newMap as Map<K, U>).get?.(key)!, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MutateMapOptions<K, T, U> extends MutateMapSkippingNewValuesOptions<K, T, U> {
|
||||
export interface MutateMapOptionsCreate<K, T, U> {
|
||||
createNewValue(key: K, valueInNewMap: U): T;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MutateMapWithNewSetOptions<K, T> extends MutateMapSkippingNewValuesDelete<K, T>, MutateMapOptionsCreate<K, T, K> {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MutateMapOptions<K, T, U> extends MutateMapSkippingNewValuesOptions<K, T, U>, MutateMapOptionsCreate<K, T, U> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutates the map with newMap such that keys in map will be same as newMap.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function mutateMap<K, T, U>(map: Map<K, T>, newMap: ReadonlyMap<K, U>, options: MutateMapOptions<K, T, U>) {
|
||||
export function mutateMap<K, T>(map: Map<K, T>, newMap: ReadonlySet<K> | undefined, options: MutateMapWithNewSetOptions<K, T>): void;
|
||||
/** @internal */
|
||||
export function mutateMap<K, T, U>(map: Map<K, T>, newMap: ReadonlyMap<K, U> | undefined, options: MutateMapOptions<K, T, U>): void;
|
||||
export function mutateMap<K, T, U>(map: Map<K, T>, newMap: ReadonlyMap<K, U> | ReadonlySet<K> | undefined, options: MutateMapOptions<K, T, U>) {
|
||||
// Needs update
|
||||
mutateMapSkippingNewValues(map, newMap, options);
|
||||
mutateMapSkippingNewValues(map, newMap as ReadonlyMap<K, U>, options);
|
||||
|
||||
const { createNewValue } = options;
|
||||
// Add new values that are not already present
|
||||
newMap.forEach((valueInNewMap, key) => {
|
||||
newMap?.forEach((valueInNewMap, key) => {
|
||||
if (!map.has(key)) {
|
||||
// New values
|
||||
map.set(key, createNewValue(key, valueInNewMap));
|
||||
map.set(key, createNewValue(key, valueInNewMap as U & K));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+60
-60
@@ -682,7 +682,11 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
resolutionCache.finishCachingPerDirectoryResolution(builderProgram.getProgram(), oldProgram);
|
||||
|
||||
// Update watches
|
||||
updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = new Map()), watchMissingFilePath);
|
||||
updateMissingFilePathsWatch(
|
||||
builderProgram.getProgram(),
|
||||
missingFilesMap || (missingFilesMap = new Map()),
|
||||
watchMissingFilePath,
|
||||
);
|
||||
if (needsUpdateInTypeRootWatch) {
|
||||
resolutionCache.updateTypeRootsWatch();
|
||||
}
|
||||
@@ -1053,11 +1057,18 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
}
|
||||
}
|
||||
|
||||
function watchMissingFilePath(missingFilePath: Path) {
|
||||
function watchMissingFilePath(missingFilePath: Path, missingFileName: string) {
|
||||
// If watching missing referenced config file, we are already watching it so no need for separate watcher
|
||||
return parsedConfigs?.has(missingFilePath) ?
|
||||
noopFileWatcher :
|
||||
watchFilePath(missingFilePath, missingFilePath, onMissingFileChange, PollingInterval.Medium, watchOptions, WatchType.MissingFile);
|
||||
watchFilePath(
|
||||
missingFilePath,
|
||||
missingFileName,
|
||||
onMissingFileChange,
|
||||
PollingInterval.Medium,
|
||||
watchOptions,
|
||||
WatchType.MissingFile,
|
||||
);
|
||||
}
|
||||
|
||||
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
|
||||
@@ -1076,16 +1087,11 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
}
|
||||
|
||||
function watchConfigFileWildCardDirectories() {
|
||||
if (wildcardDirectories) {
|
||||
updateWatchingWildcardDirectories(
|
||||
watchedWildcardDirectories || (watchedWildcardDirectories = new Map()),
|
||||
new Map(Object.entries(wildcardDirectories)),
|
||||
watchWildcardDirectory,
|
||||
);
|
||||
}
|
||||
else if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
}
|
||||
updateWatchingWildcardDirectories(
|
||||
watchedWildcardDirectories || (watchedWildcardDirectories = new Map()),
|
||||
wildcardDirectories,
|
||||
watchWildcardDirectory,
|
||||
);
|
||||
}
|
||||
|
||||
function watchWildcardDirectory(directory: string, flags: WatchDirectoryFlags) {
|
||||
@@ -1187,56 +1193,50 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
WatchType.ConfigFileOfReferencedProject,
|
||||
);
|
||||
// Watch Wild card
|
||||
if (commandLine.parsedCommandLine?.wildcardDirectories) {
|
||||
updateWatchingWildcardDirectories(
|
||||
commandLine.watchedDirectories ||= new Map(),
|
||||
new Map(Object.entries(commandLine.parsedCommandLine?.wildcardDirectories)),
|
||||
(directory, flags) =>
|
||||
watchDirectory(
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
// Since the file existence changed, update the sourceFiles cache
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
|
||||
}
|
||||
nextSourceFileVersion(fileOrDirectoryPath);
|
||||
updateWatchingWildcardDirectories(
|
||||
commandLine.watchedDirectories ||= new Map(),
|
||||
commandLine.parsedCommandLine?.wildcardDirectories,
|
||||
(directory, flags) =>
|
||||
watchDirectory(
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
// Since the file existence changed, update the sourceFiles cache
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
|
||||
}
|
||||
nextSourceFileVersion(fileOrDirectoryPath);
|
||||
|
||||
const config = parsedConfigs?.get(configPath);
|
||||
if (!config?.parsedCommandLine) return;
|
||||
if (
|
||||
isIgnoredFileFromWildCardWatching({
|
||||
watchedDirPath: toPath(directory),
|
||||
fileOrDirectory,
|
||||
fileOrDirectoryPath,
|
||||
configFileName,
|
||||
options: config.parsedCommandLine.options,
|
||||
program: config.parsedCommandLine.fileNames,
|
||||
currentDirectory,
|
||||
useCaseSensitiveFileNames,
|
||||
writeLog,
|
||||
toPath,
|
||||
})
|
||||
) return;
|
||||
const config = parsedConfigs?.get(configPath);
|
||||
if (!config?.parsedCommandLine) return;
|
||||
if (
|
||||
isIgnoredFileFromWildCardWatching({
|
||||
watchedDirPath: toPath(directory),
|
||||
fileOrDirectory,
|
||||
fileOrDirectoryPath,
|
||||
configFileName,
|
||||
options: config.parsedCommandLine.options,
|
||||
program: config.parsedCommandLine.fileNames,
|
||||
currentDirectory,
|
||||
useCaseSensitiveFileNames,
|
||||
writeLog,
|
||||
toPath,
|
||||
})
|
||||
) return;
|
||||
|
||||
// Reload is pending, do the reload
|
||||
if (config.updateLevel !== ProgramUpdateLevel.Full) {
|
||||
config.updateLevel = ProgramUpdateLevel.RootNamesAndUpdate;
|
||||
// Reload is pending, do the reload
|
||||
if (config.updateLevel !== ProgramUpdateLevel.Full) {
|
||||
config.updateLevel = ProgramUpdateLevel.RootNamesAndUpdate;
|
||||
|
||||
// Schedule Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
},
|
||||
flags,
|
||||
commandLine.parsedCommandLine?.watchOptions || watchOptions,
|
||||
WatchType.WildcardDirectoryOfReferencedProject,
|
||||
),
|
||||
);
|
||||
}
|
||||
else if (commandLine.watchedDirectories) {
|
||||
clearMap(commandLine.watchedDirectories, closeFileWatcherOf);
|
||||
commandLine.watchedDirectories = undefined;
|
||||
}
|
||||
// Schedule Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
},
|
||||
flags,
|
||||
commandLine.parsedCommandLine?.watchOptions || watchOptions,
|
||||
WatchType.WildcardDirectoryOfReferencedProject,
|
||||
),
|
||||
);
|
||||
// Watch extended config files
|
||||
updateExtendedConfigFilesWatches(
|
||||
configPath,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
arrayToMap,
|
||||
binarySearch,
|
||||
BuilderProgram,
|
||||
clearMap,
|
||||
closeFileWatcher,
|
||||
compareStringsCaseSensitive,
|
||||
CompilerOptions,
|
||||
@@ -33,6 +34,7 @@ import {
|
||||
isExcludedFile,
|
||||
isSupportedSourceFileName,
|
||||
map,
|
||||
MapLike,
|
||||
matchesExclude,
|
||||
matchFiles,
|
||||
mutateMap,
|
||||
@@ -45,7 +47,6 @@ import {
|
||||
removeFileExtension,
|
||||
removeIgnoredPath,
|
||||
returnNoopFileWatcher,
|
||||
returnTrue,
|
||||
ScriptKind,
|
||||
setSysLog,
|
||||
SortedArray,
|
||||
@@ -315,8 +316,8 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost,
|
||||
|
||||
const baseName = getBaseNameOfFileName(fileOrDirectory);
|
||||
const fsQueryResult: FileAndDirectoryExistence = {
|
||||
fileExists: host.fileExists(fileOrDirectoryPath),
|
||||
directoryExists: host.directoryExists(fileOrDirectoryPath),
|
||||
fileExists: host.fileExists(fileOrDirectory),
|
||||
directoryExists: host.directoryExists(fileOrDirectory),
|
||||
};
|
||||
if (fsQueryResult.directoryExists || hasEntry(parentResult.sortedAndCanonicalizedDirectories, getCanonicalFileName(baseName))) {
|
||||
// Folder added or removed, clear the cache instead of updating the folder and its structure
|
||||
@@ -460,27 +461,6 @@ export function cleanExtendedConfigCache(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates watchers based on the package json files used in module resolution
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function updatePackageJsonWatch(
|
||||
lookups: readonly (readonly [Path, object | boolean])[],
|
||||
packageJsonWatches: Map<Path, FileWatcher>,
|
||||
createPackageJsonWatch: (packageJsonPath: Path, data: object | boolean) => FileWatcher,
|
||||
) {
|
||||
const newMap = new Map(lookups);
|
||||
mutateMap(
|
||||
packageJsonWatches,
|
||||
newMap,
|
||||
{
|
||||
createNewValue: createPackageJsonWatch,
|
||||
onDeleteValue: closeFileWatcher,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the existing missing file watches with the new set of missing files after new program is created
|
||||
*
|
||||
@@ -489,15 +469,12 @@ export function updatePackageJsonWatch(
|
||||
export function updateMissingFilePathsWatch(
|
||||
program: Program,
|
||||
missingFileWatches: Map<Path, FileWatcher>,
|
||||
createMissingFileWatch: (missingFilePath: Path) => FileWatcher,
|
||||
createMissingFileWatch: (missingFilePath: Path, missingFileName: string) => FileWatcher,
|
||||
) {
|
||||
const missingFilePaths = program.getMissingFilePaths();
|
||||
// TODO(rbuckton): Should be a `Set` but that requires changing the below code that uses `mutateMap`
|
||||
const newMissingFilePathMap = arrayToMap(missingFilePaths, identity, returnTrue);
|
||||
// Update the missing file paths watcher
|
||||
mutateMap(
|
||||
missingFileWatches,
|
||||
newMissingFilePathMap,
|
||||
program.getMissingFilePaths(),
|
||||
{
|
||||
// Watch the missing files
|
||||
createNewValue: createMissingFileWatch,
|
||||
@@ -524,21 +501,26 @@ export interface WildcardDirectoryWatcher {
|
||||
*/
|
||||
export function updateWatchingWildcardDirectories(
|
||||
existingWatchedForWildcards: Map<string, WildcardDirectoryWatcher>,
|
||||
wildcardDirectories: Map<string, WatchDirectoryFlags>,
|
||||
wildcardDirectories: MapLike<WatchDirectoryFlags> | undefined,
|
||||
watchDirectory: (directory: string, flags: WatchDirectoryFlags) => FileWatcher,
|
||||
) {
|
||||
mutateMap(
|
||||
existingWatchedForWildcards,
|
||||
wildcardDirectories,
|
||||
{
|
||||
// Create new watch and recursive info
|
||||
createNewValue: createWildcardDirectoryWatcher,
|
||||
// Close existing watch thats not needed any more
|
||||
onDeleteValue: closeFileWatcherOf,
|
||||
// Close existing watch that doesnt match in the flags
|
||||
onExistingValue: updateWildcardDirectoryWatcher,
|
||||
},
|
||||
);
|
||||
if (wildcardDirectories) {
|
||||
mutateMap(
|
||||
existingWatchedForWildcards,
|
||||
new Map(Object.entries(wildcardDirectories)),
|
||||
{
|
||||
// Create new watch and recursive info
|
||||
createNewValue: createWildcardDirectoryWatcher,
|
||||
// Close existing watch thats not needed any more
|
||||
onDeleteValue: closeFileWatcherOf,
|
||||
// Close existing watch that doesnt match in the flags
|
||||
onExistingValue: updateWildcardDirectoryWatcher,
|
||||
},
|
||||
);
|
||||
}
|
||||
else {
|
||||
clearMap(existingWatchedForWildcards, closeFileWatcherOf);
|
||||
}
|
||||
|
||||
function createWildcardDirectoryWatcher(directory: string, flags: WatchDirectoryFlags): WildcardDirectoryWatcher {
|
||||
// Create new watch and recursive info
|
||||
|
||||
@@ -1569,7 +1569,7 @@ export class TestState {
|
||||
details.push({ location: contextSpanEnd, locationMarker: "|>", span, type: "contextEnd" });
|
||||
}
|
||||
|
||||
if (additionalSpan && ts.documentSpansEqual(additionalSpan, span)) {
|
||||
if (additionalSpan && ts.documentSpansEqual(additionalSpan, span, this.languageServiceAdapterHost.useCaseSensitiveFileNames())) {
|
||||
// This span is same as text span
|
||||
groupedSpanForAdditionalSpan = span;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,11 @@ class SessionServerHost implements ts.server.ServerHost {
|
||||
args: string[] = [];
|
||||
newLine: string;
|
||||
useCaseSensitiveFileNames = false;
|
||||
watchUtils = createWatchUtils<ServerHostFileWatcher, ServerHostDirectoryWatcher>("watchedFiles", "watchedDirectories");
|
||||
watchUtils = createWatchUtils<ServerHostFileWatcher, ServerHostDirectoryWatcher>(
|
||||
"watchedFiles",
|
||||
"watchedDirectories",
|
||||
ts.createGetCanonicalFileName(this.useCaseSensitiveFileNames),
|
||||
);
|
||||
|
||||
constructor(private host: NativeLanguageServiceHost) {
|
||||
this.newLine = this.host.getNewLine();
|
||||
|
||||
@@ -514,7 +514,7 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
|
||||
|
||||
interface ResolveSingleModuleNameWithoutWatchingData {
|
||||
resolutionToData: Map<ts.ResolutionWithFailedLookupLocations, Pick<ts.ResolvedModuleWithFailedLookupLocations, "failedLookupLocations" | "affectingLocations" | "resolutionDiagnostics">>;
|
||||
packageJsonMap: Map<ts.Path, ts.PackageJsonInfo | boolean> | undefined;
|
||||
packageJsonMap: Map<ts.Path, ts.PackageJsonInfoCacheEntry> | undefined;
|
||||
}
|
||||
|
||||
function beforeResolveSingleModuleNameWithoutWatching(
|
||||
|
||||
+83
-25
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
addRange,
|
||||
arrayFrom,
|
||||
compareStringsCaseSensitive,
|
||||
contains,
|
||||
@@ -6,6 +7,7 @@ import {
|
||||
Debug,
|
||||
FileWatcher,
|
||||
FileWatcherCallback,
|
||||
GetCanonicalFileName,
|
||||
MultiMap,
|
||||
PollingInterval,
|
||||
} from "./_namespaces/ts";
|
||||
@@ -20,31 +22,33 @@ export interface TestFsWatcher<DirCallback> {
|
||||
inode: number | undefined;
|
||||
}
|
||||
|
||||
export interface WatchUtils<PollingWatcherData, FsWatcherData, Path extends string = string> {
|
||||
pollingWatches: MultiMap<Path, PollingWatcherData>;
|
||||
fsWatches: MultiMap<Path, FsWatcherData>;
|
||||
fsWatchesRecursive: MultiMap<Path, FsWatcherData>;
|
||||
pollingWatch(path: Path, data: PollingWatcherData): FileWatcher;
|
||||
fsWatch(path: Path, recursive: boolean, data: FsWatcherData): FileWatcher;
|
||||
export interface Watches<Data> {
|
||||
add(path: string, data: Data): void;
|
||||
remove(path: string, data: Data): void;
|
||||
forEach(path: string, cb: (data: Data) => void): void;
|
||||
serialize(baseline: string[]): void;
|
||||
}
|
||||
|
||||
export interface WatchUtils<PollingWatcherData, FsWatcherData> {
|
||||
pollingWatches: Watches<PollingWatcherData>;
|
||||
fsWatches: Watches<FsWatcherData>;
|
||||
fsWatchesRecursive: Watches<FsWatcherData>;
|
||||
pollingWatch(path: string, data: PollingWatcherData): FileWatcher;
|
||||
fsWatch(path: string, recursive: boolean, data: FsWatcherData): FileWatcher;
|
||||
serializeWatches(baseline?: string[]): string[];
|
||||
getHasWatchChanges(): boolean;
|
||||
setHasWatchChanges(): void;
|
||||
}
|
||||
|
||||
export function createWatchUtils<PollingWatcherData, FsWatcherData, Path extends string = string>(
|
||||
export function createWatchUtils<PollingWatcherData, FsWatcherData>(
|
||||
pollingWatchesName: string,
|
||||
fsWatchesName: string,
|
||||
): WatchUtils<PollingWatcherData, FsWatcherData, Path> {
|
||||
const pollingWatches = createMultiMap<Path, PollingWatcherData>();
|
||||
const fsWatches = createMultiMap<Path, FsWatcherData>();
|
||||
const fsWatchesRecursive = createMultiMap<Path, FsWatcherData>();
|
||||
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
): WatchUtils<PollingWatcherData, FsWatcherData> {
|
||||
const pollingWatches = initializeWatches<PollingWatcherData>(pollingWatchesName);
|
||||
const fsWatches = initializeWatches<FsWatcherData>(fsWatchesName);
|
||||
const fsWatchesRecursive = initializeWatches<FsWatcherData>(`${fsWatchesName}Recursive`);
|
||||
let hasWatchChanges = false;
|
||||
|
||||
let serializedPollingWatches: Map<string, PollingWatcherData[]> | undefined;
|
||||
let serializedFsWatches: Map<string, FsWatcherData[]> | undefined;
|
||||
let serializedFsWatchesRecursive: Map<string, FsWatcherData[]> | undefined;
|
||||
|
||||
return {
|
||||
pollingWatches,
|
||||
fsWatches,
|
||||
@@ -56,21 +60,75 @@ export function createWatchUtils<PollingWatcherData, FsWatcherData, Path extends
|
||||
setHasWatchChanges: () => hasWatchChanges = true,
|
||||
};
|
||||
|
||||
function createWatcher<T>(map: MultiMap<Path, T>, path: Path, callback: T): FileWatcher {
|
||||
function initializeWatches<Data>(name: string): Watches<Data> {
|
||||
const actuals = createMultiMap<string, Data>();
|
||||
let serialized: Map<string, Data[]> | undefined;
|
||||
let canonicalPathsToStrings: Map<string, Set<string>> | undefined;
|
||||
return {
|
||||
add,
|
||||
remove,
|
||||
forEach,
|
||||
serialize,
|
||||
};
|
||||
|
||||
function add(path: string, data: Data) {
|
||||
actuals.add(path, data);
|
||||
if (actuals.get(path)!.length === 1) {
|
||||
const canonicalPath = getCanonicalFileName(path);
|
||||
if (canonicalPath !== path) {
|
||||
(canonicalPathsToStrings ??= new Map()).set(
|
||||
canonicalPath,
|
||||
(canonicalPathsToStrings?.get(canonicalPath) ?? new Set()).add(path),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function remove(path: string, data: Data) {
|
||||
actuals.remove(path, data);
|
||||
if (!actuals.has(path)) {
|
||||
const canonicalPath = getCanonicalFileName(path);
|
||||
if (canonicalPath !== path) {
|
||||
const existing = canonicalPathsToStrings!.get(canonicalPath);
|
||||
if (existing!.size === 1) canonicalPathsToStrings!.delete(canonicalPath);
|
||||
else existing!.delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function forEach(path: string, cb: (data: Data) => void) {
|
||||
let allData: Data[] | undefined;
|
||||
allData = addRange(allData, actuals.get(path));
|
||||
const canonicalPath = getCanonicalFileName(path);
|
||||
if (canonicalPath !== path) allData = addRange(allData, actuals.get(canonicalPath));
|
||||
canonicalPathsToStrings?.get(canonicalPath)?.forEach(canonicalSamePath => {
|
||||
if (canonicalSamePath !== path && canonicalSamePath !== canonicalPath) {
|
||||
allData = addRange(allData, actuals.get(canonicalSamePath));
|
||||
}
|
||||
});
|
||||
allData?.forEach(cb);
|
||||
}
|
||||
|
||||
function serialize(baseline: string[]) {
|
||||
serialized = serializeMultiMap(baseline, name, actuals, serialized);
|
||||
}
|
||||
}
|
||||
|
||||
function createWatcher<T>(watches: Watches<T>, path: string, callback: T): FileWatcher {
|
||||
hasWatchChanges = true;
|
||||
map.add(path, callback);
|
||||
watches.add(path, callback);
|
||||
let closed = false;
|
||||
return {
|
||||
close: () => {
|
||||
Debug.assert(!closed);
|
||||
map.remove(path, callback);
|
||||
watches.remove(path, callback);
|
||||
hasWatchChanges = true;
|
||||
closed = true;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function pollingWatch(path: Path, data: PollingWatcherData) {
|
||||
function pollingWatch(path: string, data: PollingWatcherData) {
|
||||
return createWatcher(
|
||||
pollingWatches,
|
||||
path,
|
||||
@@ -78,7 +136,7 @@ export function createWatchUtils<PollingWatcherData, FsWatcherData, Path extends
|
||||
);
|
||||
}
|
||||
|
||||
function fsWatch(path: Path, recursive: boolean, data: FsWatcherData) {
|
||||
function fsWatch(path: string, recursive: boolean, data: FsWatcherData) {
|
||||
return createWatcher(
|
||||
recursive ? fsWatchesRecursive : fsWatches,
|
||||
path,
|
||||
@@ -88,9 +146,9 @@ export function createWatchUtils<PollingWatcherData, FsWatcherData, Path extends
|
||||
|
||||
function serializeWatches(baseline: string[] = []) {
|
||||
if (!hasWatchChanges) return baseline;
|
||||
serializedPollingWatches = serializeMultiMap(baseline, pollingWatchesName, pollingWatches, serializedPollingWatches);
|
||||
serializedFsWatches = serializeMultiMap(baseline, fsWatchesName, fsWatches, serializedFsWatches);
|
||||
serializedFsWatchesRecursive = serializeMultiMap(baseline, `${fsWatchesName}Recursive`, fsWatchesRecursive, serializedFsWatchesRecursive);
|
||||
pollingWatches.serialize(baseline);
|
||||
fsWatches.serialize(baseline);
|
||||
fsWatchesRecursive.serialize(baseline);
|
||||
hasWatchChanges = false;
|
||||
return baseline;
|
||||
}
|
||||
|
||||
Vendored
+4
-3
@@ -29,12 +29,13 @@ declare namespace Intl {
|
||||
select(n: number): LDMLPluralRule;
|
||||
}
|
||||
|
||||
const PluralRules: {
|
||||
interface PluralRulesConstructor {
|
||||
new (locales?: string | string[], options?: PluralRulesOptions): PluralRules;
|
||||
(locales?: string | string[], options?: PluralRulesOptions): PluralRules;
|
||||
|
||||
supportedLocalesOf(locales: string | string[], options?: { localeMatcher?: "lookup" | "best fit"; }): string[];
|
||||
};
|
||||
}
|
||||
|
||||
const PluralRules: PluralRulesConstructor;
|
||||
|
||||
// We can only have one definition for 'type' in TypeScript, and so you can learn where the keys come from here:
|
||||
type ES2018NumberFormatPartType = "literal" | "nan" | "infinity" | "percent" | "integer" | "group" | "decimal" | "fraction" | "plusSign" | "minusSign" | "percentSign" | "currency" | "code" | "symbol" | "name";
|
||||
|
||||
Vendored
+36
-16
@@ -1,9 +1,11 @@
|
||||
/// <reference lib="es2018.intl" />
|
||||
declare namespace Intl {
|
||||
/**
|
||||
* [Unicode BCP 47 Locale Identifiers](https://unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers) definition.
|
||||
* A string that is a valid [Unicode BCP 47 Locale Identifier](https://unicode.org/reports/tr35/#Unicode_locale_identifier).
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
* For example: "fa", "es-MX", "zh-Hant-TW".
|
||||
*
|
||||
* See [MDN - Intl - locales argument](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
*/
|
||||
type UnicodeBCP47LocaleIdentifier = string;
|
||||
|
||||
@@ -71,16 +73,9 @@ declare namespace Intl {
|
||||
type RelativeTimeFormatStyle = "long" | "short" | "narrow";
|
||||
|
||||
/**
|
||||
* [BCP 47 language tag](http://tools.ietf.org/html/rfc5646) definition.
|
||||
* The locale or locales to use
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
*/
|
||||
type BCP47LanguageTag = string;
|
||||
|
||||
/**
|
||||
* The locale(s) to use
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
* See [MDN - Intl - locales argument](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
*/
|
||||
type LocalesArgument = UnicodeBCP47LocaleIdentifier | Locale | readonly (UnicodeBCP47LocaleIdentifier | Locale)[] | undefined;
|
||||
|
||||
@@ -200,7 +195,7 @@ declare namespace Intl {
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat).
|
||||
*/
|
||||
new (
|
||||
locales?: UnicodeBCP47LocaleIdentifier | UnicodeBCP47LocaleIdentifier[],
|
||||
locales?: LocalesArgument,
|
||||
options?: RelativeTimeFormatOptions,
|
||||
): RelativeTimeFormat;
|
||||
|
||||
@@ -223,7 +218,7 @@ declare namespace Intl {
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/supportedLocalesOf).
|
||||
*/
|
||||
supportedLocalesOf(
|
||||
locales?: UnicodeBCP47LocaleIdentifier | UnicodeBCP47LocaleIdentifier[],
|
||||
locales?: LocalesArgument,
|
||||
options?: RelativeTimeFormatOptions,
|
||||
): UnicodeBCP47LocaleIdentifier[];
|
||||
};
|
||||
@@ -294,7 +289,7 @@ declare namespace Intl {
|
||||
/** Attempts to remove information about the locale that would be added by calling `Locale.maximize()`. */
|
||||
minimize(): Locale;
|
||||
/** Returns the locale's full locale identifier string. */
|
||||
toString(): BCP47LanguageTag;
|
||||
toString(): UnicodeBCP47LocaleIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +307,7 @@ declare namespace Intl {
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale).
|
||||
*/
|
||||
const Locale: {
|
||||
new (tag: BCP47LanguageTag | Locale, options?: LocaleOptions): Locale;
|
||||
new (tag: UnicodeBCP47LocaleIdentifier | Locale, options?: LocaleOptions): Locale;
|
||||
};
|
||||
|
||||
type DisplayNamesFallback =
|
||||
@@ -406,6 +401,31 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/supportedLocalesOf).
|
||||
*/
|
||||
supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher; }): BCP47LanguageTag[];
|
||||
supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher; }): UnicodeBCP47LocaleIdentifier[];
|
||||
};
|
||||
|
||||
interface CollatorConstructor {
|
||||
new (locales?: LocalesArgument, options?: CollatorOptions): Collator;
|
||||
(locales?: LocalesArgument, options?: CollatorOptions): Collator;
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: CollatorOptions): string[];
|
||||
}
|
||||
|
||||
interface DateTimeFormatConstructor {
|
||||
new (locales?: LocalesArgument, options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
(locales?: LocalesArgument, options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: DateTimeFormatOptions): string[];
|
||||
}
|
||||
|
||||
interface NumberFormatConstructor {
|
||||
new (locales?: LocalesArgument, options?: NumberFormatOptions): NumberFormat;
|
||||
(locales?: LocalesArgument, options?: NumberFormatOptions): NumberFormat;
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: NumberFormatOptions): string[];
|
||||
}
|
||||
|
||||
interface PluralRulesConstructor {
|
||||
new (locales?: LocalesArgument, options?: PluralRulesOptions): PluralRules;
|
||||
(locales?: LocalesArgument, options?: PluralRulesOptions): PluralRules;
|
||||
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: { localeMatcher?: "lookup" | "best fit"; }): string[];
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+15
-1
@@ -6,5 +6,19 @@ interface String {
|
||||
* containing the results of that search.
|
||||
* @param regexp A variable name or string literal containing the regular expression pattern and flags.
|
||||
*/
|
||||
matchAll(regexp: RegExp): IterableIterator<RegExpMatchArray>;
|
||||
matchAll(regexp: RegExp): IterableIterator<RegExpExecArray>;
|
||||
|
||||
/** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */
|
||||
toLocaleLowerCase(locales?: Intl.LocalesArgument): string;
|
||||
|
||||
/** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */
|
||||
toLocaleUpperCase(locales?: Intl.LocalesArgument): string;
|
||||
|
||||
/**
|
||||
* Determines whether two strings are equivalent in the current or specified locale.
|
||||
* @param that String to compare to target string
|
||||
* @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.
|
||||
* @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details.
|
||||
*/
|
||||
localeCompare(that: string, locales?: Intl.LocalesArgument, options?: Intl.CollatorOptions): number;
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -125,7 +125,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat).
|
||||
*/
|
||||
new (locales?: BCP47LanguageTag | BCP47LanguageTag[], options?: ListFormatOptions): ListFormat;
|
||||
new (locales?: LocalesArgument, options?: ListFormatOptions): ListFormat;
|
||||
|
||||
/**
|
||||
* Returns an array containing those of the provided locales that are
|
||||
@@ -143,6 +143,6 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf).
|
||||
*/
|
||||
supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick<ListFormatOptions, "localeMatcher">): BCP47LanguageTag[];
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: Pick<ListFormatOptions, "localeMatcher">): UnicodeBCP47LocaleIdentifier[];
|
||||
};
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -71,7 +71,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter).
|
||||
*/
|
||||
new (locales?: BCP47LanguageTag | BCP47LanguageTag[], options?: SegmenterOptions): Segmenter;
|
||||
new (locales?: LocalesArgument, options?: SegmenterOptions): Segmenter;
|
||||
|
||||
/**
|
||||
* Returns an array containing those of the provided locales that are supported without having to fall back to the runtime's default locale.
|
||||
@@ -85,7 +85,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/supportedLocalesOf)
|
||||
*/
|
||||
supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick<SegmenterOptions, "localeMatcher">): BCP47LanguageTag[];
|
||||
supportedLocalesOf(locales: LocalesArgument, options?: Pick<SegmenterOptions, "localeMatcher">): UnicodeBCP47LocaleIdentifier[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+15
-6
@@ -4400,11 +4400,14 @@ declare namespace Intl {
|
||||
compare(x: string, y: string): number;
|
||||
resolvedOptions(): ResolvedCollatorOptions;
|
||||
}
|
||||
var Collator: {
|
||||
|
||||
interface CollatorConstructor {
|
||||
new (locales?: string | string[], options?: CollatorOptions): Collator;
|
||||
(locales?: string | string[], options?: CollatorOptions): Collator;
|
||||
supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[];
|
||||
};
|
||||
}
|
||||
|
||||
var Collator: CollatorConstructor;
|
||||
|
||||
interface NumberFormatOptions {
|
||||
localeMatcher?: string | undefined;
|
||||
@@ -4436,12 +4439,15 @@ declare namespace Intl {
|
||||
format(value: number): string;
|
||||
resolvedOptions(): ResolvedNumberFormatOptions;
|
||||
}
|
||||
var NumberFormat: {
|
||||
|
||||
interface NumberFormatConstructor {
|
||||
new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat;
|
||||
(locales?: string | string[], options?: NumberFormatOptions): NumberFormat;
|
||||
supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[];
|
||||
readonly prototype: NumberFormat;
|
||||
};
|
||||
}
|
||||
|
||||
var NumberFormat: NumberFormatConstructor;
|
||||
|
||||
interface DateTimeFormatOptions {
|
||||
localeMatcher?: "best fit" | "lookup" | undefined;
|
||||
@@ -4480,12 +4486,15 @@ declare namespace Intl {
|
||||
format(date?: Date | number): string;
|
||||
resolvedOptions(): ResolvedDateTimeFormatOptions;
|
||||
}
|
||||
var DateTimeFormat: {
|
||||
|
||||
interface DateTimeFormatConstructor {
|
||||
new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
(locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;
|
||||
supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[];
|
||||
readonly prototype: DateTimeFormat;
|
||||
};
|
||||
}
|
||||
|
||||
var DateTimeFormat: DateTimeFormatConstructor;
|
||||
}
|
||||
|
||||
interface String {
|
||||
|
||||
Vendored
+1
@@ -2,3 +2,4 @@
|
||||
/// <reference lib="esnext.intl" />
|
||||
/// <reference lib="esnext.decorators" />
|
||||
/// <reference lib="esnext.disposable" />
|
||||
/// <reference lib="esnext.promise" />
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
interface PromiseWithResolvers<T> {
|
||||
promise: Promise<T>;
|
||||
resolve: (value: T | PromiseLike<T>) => void;
|
||||
reject: (reason?: any) => void;
|
||||
}
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* Creates a new Promise and returns it in an object, along with its resolve and reject functions.
|
||||
* @returns An object with the properties `promise`, `resolve`, and `reject`.
|
||||
*
|
||||
* ```ts
|
||||
* const { promise, resolve, reject } = Promise.withResolvers<T>();
|
||||
* ```
|
||||
*/
|
||||
withResolvers<T>(): PromiseWithResolvers<T>;
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
"esnext.decorators",
|
||||
"esnext.intl",
|
||||
"esnext.disposable",
|
||||
"esnext.promise",
|
||||
"decorators",
|
||||
"decorators.legacy",
|
||||
// Default libraries
|
||||
|
||||
+111
-84
@@ -810,7 +810,17 @@ interface NodeModulesWatcher extends FileWatcher {
|
||||
/** How many watchers of this directory were for closed ScriptInfo */
|
||||
refreshScriptInfoRefCount: number;
|
||||
/** List of project names whose module specifier cache should be cleared when package.jsons change */
|
||||
affectedModuleSpecifierCacheProjects?: Set<string>;
|
||||
affectedModuleSpecifierCacheProjects?: Set<Project>;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface PackageJsonWatcher extends FileWatcher {
|
||||
projects: Set<Project | WildcardWatcher>;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface WildcardWatcher extends FileWatcher {
|
||||
packageJsonWatches: Set<PackageJsonWatcher> | undefined;
|
||||
}
|
||||
|
||||
function getDetailWatchInfo(watchType: WatchType, project: Project | NormalizedPath | undefined) {
|
||||
@@ -1002,7 +1012,7 @@ export class ProjectService {
|
||||
* @internal
|
||||
*/
|
||||
readonly filenameToScriptInfo = new Map<string, ScriptInfo>();
|
||||
private readonly nodeModulesWatchers = new Map<string, NodeModulesWatcher>();
|
||||
private readonly nodeModulesWatchers = new Map<Path, NodeModulesWatcher>();
|
||||
/**
|
||||
* Contains all the deleted script info's version information so that
|
||||
* it does not reset when creating script info again
|
||||
@@ -1120,7 +1130,7 @@ export class ProjectService {
|
||||
/** @internal */
|
||||
readonly packageJsonCache: PackageJsonCache;
|
||||
/** @internal */
|
||||
private packageJsonFilesMap: Map<Path, FileWatcher> | undefined;
|
||||
private packageJsonFilesMap: Map<Path, PackageJsonWatcher> | undefined;
|
||||
/** @internal */
|
||||
private incompleteCompletionsCache: IncompleteCompletionsCache | undefined;
|
||||
/** @internal */
|
||||
@@ -1642,24 +1652,26 @@ export class ProjectService {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, configFileName: NormalizedPath, config: ParsedConfig) {
|
||||
return this.watchFactory.watchDirectory(
|
||||
private watchWildcardDirectory(directory: string, flags: WatchDirectoryFlags, configFileName: NormalizedPath, config: ParsedConfig) {
|
||||
let watcher: FileWatcher | undefined = this.watchFactory.watchDirectory(
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
|
||||
const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
|
||||
if (
|
||||
getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) &&
|
||||
(fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectoryPath))
|
||||
(fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectory))
|
||||
) {
|
||||
this.logger.info(`Config: ${configFileName} Detected new package.json: ${fileOrDirectory}`);
|
||||
this.onAddPackageJson(fileOrDirectoryPath);
|
||||
const file = this.getNormalizedAbsolutePath(fileOrDirectory);
|
||||
this.logger.info(`Config: ${configFileName} Detected new package.json: ${file}`);
|
||||
this.packageJsonCache.addOrUpdate(file, fileOrDirectoryPath);
|
||||
this.watchPackageJsonFile(file, fileOrDirectoryPath, result);
|
||||
}
|
||||
|
||||
const configuredProjectForConfig = this.findConfiguredProjectByProjectName(configFileName);
|
||||
if (
|
||||
isIgnoredFileFromWildCardWatching({
|
||||
watchedDirPath: directory,
|
||||
watchedDirPath: this.toPath(directory),
|
||||
fileOrDirectory,
|
||||
fileOrDirectoryPath,
|
||||
configFileName,
|
||||
@@ -1709,6 +1721,22 @@ export class ProjectService {
|
||||
WatchType.WildcardDirectory,
|
||||
configFileName,
|
||||
);
|
||||
|
||||
const result: WildcardWatcher = {
|
||||
packageJsonWatches: undefined,
|
||||
close() {
|
||||
if (watcher) {
|
||||
watcher.close();
|
||||
watcher = undefined;
|
||||
result.packageJsonWatches?.forEach(watcher => {
|
||||
watcher.projects.delete(result);
|
||||
watcher.close();
|
||||
});
|
||||
result.packageJsonWatches = undefined;
|
||||
}
|
||||
},
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -2640,9 +2668,9 @@ export class ProjectService {
|
||||
config!.watchedDirectoriesStale = false;
|
||||
updateWatchingWildcardDirectories(
|
||||
config!.watchedDirectories ||= new Map(),
|
||||
new Map(Object.entries(config!.parsedCommandLine!.wildcardDirectories!)),
|
||||
config!.parsedCommandLine!.wildcardDirectories,
|
||||
// Create new directory watcher
|
||||
(directory, flags) => this.watchWildcardDirectory(directory as Path, flags, configFileName, config!),
|
||||
(directory, flags) => this.watchWildcardDirectory(directory, flags, configFileName, config!),
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -2733,7 +2761,7 @@ export class ProjectService {
|
||||
projectRootFilesMap.forEach((value, path) => {
|
||||
if (!newRootScriptInfoMap.has(path)) {
|
||||
if (value.info) {
|
||||
project.removeFile(value.info, project.fileExists(path), /*detachFromProject*/ true);
|
||||
project.removeFile(value.info, project.fileExists(value.info.fileName), /*detachFromProject*/ true);
|
||||
}
|
||||
else {
|
||||
projectRootFilesMap.delete(path);
|
||||
@@ -3014,7 +3042,7 @@ export class ProjectService {
|
||||
(!this.globalCacheLocationDirectoryPath ||
|
||||
!startsWith(info.path, this.globalCacheLocationDirectoryPath))
|
||||
) {
|
||||
const indexOfNodeModules = info.path.indexOf("/node_modules/");
|
||||
const indexOfNodeModules = info.fileName.indexOf("/node_modules/");
|
||||
if (!this.host.getModifiedTime || indexOfNodeModules === -1) {
|
||||
info.fileWatcher = this.watchFactory.watchFile(
|
||||
info.fileName,
|
||||
@@ -3026,13 +3054,13 @@ export class ProjectService {
|
||||
}
|
||||
else {
|
||||
info.mTime = this.getModifiedTime(info);
|
||||
info.fileWatcher = this.watchClosedScriptInfoInNodeModules(info.path.substr(0, indexOfNodeModules) as Path);
|
||||
info.fileWatcher = this.watchClosedScriptInfoInNodeModules(info.fileName.substring(0, indexOfNodeModules));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private createNodeModulesWatcher(dir: Path) {
|
||||
const watcher = this.watchFactory.watchDirectory(
|
||||
private createNodeModulesWatcher(dir: string, dirPath: Path) {
|
||||
let watcher: FileWatcher | undefined = this.watchFactory.watchDirectory(
|
||||
dir,
|
||||
fileOrDirectory => {
|
||||
const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
|
||||
@@ -3046,15 +3074,15 @@ export class ProjectService {
|
||||
basename === "package.json" || basename === "node_modules"
|
||||
)
|
||||
) {
|
||||
result.affectedModuleSpecifierCacheProjects.forEach(projectName => {
|
||||
this.findProject(projectName)?.getModuleSpecifierCache()?.clear();
|
||||
result.affectedModuleSpecifierCacheProjects.forEach(project => {
|
||||
project.getModuleSpecifierCache()?.clear();
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh closed script info after an npm install
|
||||
if (result.refreshScriptInfoRefCount) {
|
||||
if (dir === fileOrDirectoryPath) {
|
||||
this.refreshScriptInfosInDirectory(dir);
|
||||
if (dirPath === fileOrDirectoryPath) {
|
||||
this.refreshScriptInfosInDirectory(dirPath);
|
||||
}
|
||||
else {
|
||||
const info = this.getScriptInfoForPath(fileOrDirectoryPath);
|
||||
@@ -3078,32 +3106,36 @@ export class ProjectService {
|
||||
refreshScriptInfoRefCount: 0,
|
||||
affectedModuleSpecifierCacheProjects: undefined,
|
||||
close: () => {
|
||||
if (!result.refreshScriptInfoRefCount && !result.affectedModuleSpecifierCacheProjects?.size) {
|
||||
if (watcher && !result.refreshScriptInfoRefCount && !result.affectedModuleSpecifierCacheProjects?.size) {
|
||||
watcher.close();
|
||||
this.nodeModulesWatchers.delete(dir);
|
||||
watcher = undefined;
|
||||
this.nodeModulesWatchers.delete(dirPath);
|
||||
}
|
||||
},
|
||||
};
|
||||
this.nodeModulesWatchers.set(dir, result);
|
||||
this.nodeModulesWatchers.set(dirPath, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
watchPackageJsonsInNodeModules(dir: Path, project: Project): FileWatcher {
|
||||
const watcher = this.nodeModulesWatchers.get(dir) || this.createNodeModulesWatcher(dir);
|
||||
(watcher.affectedModuleSpecifierCacheProjects ||= new Set()).add(project.getProjectName());
|
||||
watchPackageJsonsInNodeModules(dir: string, project: Project): FileWatcher {
|
||||
const dirPath = this.toPath(dir);
|
||||
const watcher = this.nodeModulesWatchers.get(dirPath) || this.createNodeModulesWatcher(dir, dirPath);
|
||||
Debug.assert(!watcher.affectedModuleSpecifierCacheProjects?.has(project));
|
||||
(watcher.affectedModuleSpecifierCacheProjects ||= new Set()).add(project);
|
||||
|
||||
return {
|
||||
close: () => {
|
||||
watcher.affectedModuleSpecifierCacheProjects?.delete(project.getProjectName());
|
||||
watcher.affectedModuleSpecifierCacheProjects?.delete(project);
|
||||
watcher.close();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private watchClosedScriptInfoInNodeModules(dir: Path): FileWatcher {
|
||||
const watchDir = dir + "/node_modules" as Path;
|
||||
const watcher = this.nodeModulesWatchers.get(watchDir) || this.createNodeModulesWatcher(watchDir);
|
||||
private watchClosedScriptInfoInNodeModules(dir: string): FileWatcher {
|
||||
const watchDir = dir + "/node_modules";
|
||||
const watchDirPath = this.toPath(watchDir);
|
||||
const watcher = this.nodeModulesWatchers.get(watchDirPath) || this.createNodeModulesWatcher(watchDir, watchDirPath);
|
||||
watcher.refreshScriptInfoRefCount++;
|
||||
|
||||
return {
|
||||
@@ -3115,7 +3147,7 @@ export class ProjectService {
|
||||
}
|
||||
|
||||
private getModifiedTime(info: ScriptInfo) {
|
||||
return (this.host.getModifiedTime!(info.path) || missingFileModifiedTime).getTime();
|
||||
return (this.host.getModifiedTime!(info.fileName) || missingFileModifiedTime).getTime();
|
||||
}
|
||||
|
||||
private refreshScriptInfo(info: ScriptInfo) {
|
||||
@@ -3408,7 +3440,9 @@ export class ProjectService {
|
||||
});
|
||||
}
|
||||
if (includePackageJsonAutoImports !== args.preferences.includePackageJsonAutoImports) {
|
||||
this.invalidateProjectPackageJson(/*packageJsonPath*/ undefined);
|
||||
this.forEachProject(project => {
|
||||
project.onAutoImportProviderSettingsChanged();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (args.extraFileExtensions) {
|
||||
@@ -4602,12 +4636,11 @@ export class ProjectService {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getPackageJsonsVisibleToFile(fileName: string, rootDir?: string): readonly ProjectPackageJsonInfo[] {
|
||||
getPackageJsonsVisibleToFile(fileName: string, project: Project, rootDir?: string): readonly ProjectPackageJsonInfo[] {
|
||||
const packageJsonCache = this.packageJsonCache;
|
||||
const rootPath = rootDir && this.toPath(rootDir);
|
||||
const filePath = this.toPath(fileName);
|
||||
const result: ProjectPackageJsonInfo[] = [];
|
||||
const processDirectory = (directory: Path): boolean | undefined => {
|
||||
const processDirectory = (directory: string): boolean | undefined => {
|
||||
switch (packageJsonCache.directoryHasPackageJson(directory)) {
|
||||
// Sync and check same directory again
|
||||
case Ternary.Maybe:
|
||||
@@ -4616,7 +4649,7 @@ export class ProjectService {
|
||||
// Check package.json
|
||||
case Ternary.True:
|
||||
const packageJsonFileName = combinePaths(directory, "package.json");
|
||||
this.watchPackageJsonFile(packageJsonFileName as Path);
|
||||
this.watchPackageJsonFile(packageJsonFileName, this.toPath(packageJsonFileName), project);
|
||||
const info = packageJsonCache.getInDirectory(directory);
|
||||
if (info) result.push(info);
|
||||
}
|
||||
@@ -4625,14 +4658,14 @@ export class ProjectService {
|
||||
}
|
||||
};
|
||||
|
||||
forEachAncestorDirectory(getDirectoryPath(filePath), processDirectory);
|
||||
forEachAncestorDirectory(getDirectoryPath(fileName), processDirectory);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getNearestAncestorDirectoryWithPackageJson(fileName: string): string | undefined {
|
||||
return forEachAncestorDirectory(fileName, directory => {
|
||||
switch (this.packageJsonCache.directoryHasPackageJson(this.toPath(directory))) {
|
||||
switch (this.packageJsonCache.directoryHasPackageJson(directory)) {
|
||||
case Ternary.True:
|
||||
return directory;
|
||||
case Ternary.False:
|
||||
@@ -4646,42 +4679,51 @@ export class ProjectService {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
private watchPackageJsonFile(path: Path) {
|
||||
const watchers = this.packageJsonFilesMap || (this.packageJsonFilesMap = new Map());
|
||||
if (!watchers.has(path)) {
|
||||
this.invalidateProjectPackageJson(path);
|
||||
watchers.set(
|
||||
path,
|
||||
this.watchFactory.watchFile(
|
||||
path,
|
||||
(fileName, eventKind) => {
|
||||
const path = this.toPath(fileName);
|
||||
switch (eventKind) {
|
||||
case FileWatcherEventKind.Created:
|
||||
return Debug.fail();
|
||||
case FileWatcherEventKind.Changed:
|
||||
this.packageJsonCache.addOrUpdate(path);
|
||||
this.invalidateProjectPackageJson(path);
|
||||
break;
|
||||
case FileWatcherEventKind.Deleted:
|
||||
this.packageJsonCache.delete(path);
|
||||
this.invalidateProjectPackageJson(path);
|
||||
watchers.get(path)!.close();
|
||||
watchers.delete(path);
|
||||
}
|
||||
},
|
||||
PollingInterval.Low,
|
||||
this.hostConfiguration.watchOptions,
|
||||
WatchType.PackageJson,
|
||||
),
|
||||
private watchPackageJsonFile(file: string, path: Path, project: Project | WildcardWatcher) {
|
||||
Debug.assert(project !== undefined);
|
||||
let result = (this.packageJsonFilesMap ??= new Map()).get(path);
|
||||
if (!result) {
|
||||
// this.invalidateProjectPackageJson(path);
|
||||
let watcher: FileWatcher | undefined = this.watchFactory.watchFile(
|
||||
file,
|
||||
(fileName, eventKind) => {
|
||||
switch (eventKind) {
|
||||
case FileWatcherEventKind.Created:
|
||||
return Debug.fail();
|
||||
case FileWatcherEventKind.Changed:
|
||||
this.packageJsonCache.addOrUpdate(fileName, path);
|
||||
this.onPackageJsonChange(result);
|
||||
break;
|
||||
case FileWatcherEventKind.Deleted:
|
||||
this.packageJsonCache.delete(path);
|
||||
this.onPackageJsonChange(result);
|
||||
result.projects.clear();
|
||||
result.close();
|
||||
}
|
||||
},
|
||||
PollingInterval.Low,
|
||||
this.hostConfiguration.watchOptions,
|
||||
WatchType.PackageJson,
|
||||
);
|
||||
result = {
|
||||
projects: new Set(),
|
||||
close: () => {
|
||||
if (result.projects.size || !watcher) return;
|
||||
watcher.close();
|
||||
watcher = undefined;
|
||||
this.packageJsonFilesMap?.delete(path);
|
||||
this.packageJsonCache.invalidate(path);
|
||||
},
|
||||
};
|
||||
this.packageJsonFilesMap.set(path, result);
|
||||
}
|
||||
result.projects.add(project);
|
||||
(project.packageJsonWatches ??= new Set()).add(result);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
private onAddPackageJson(path: Path) {
|
||||
this.packageJsonCache.addOrUpdate(path);
|
||||
this.watchPackageJsonFile(path);
|
||||
private onPackageJsonChange(result: PackageJsonWatcher) {
|
||||
result.projects.forEach(project => (project as Project).onPackageJsonChange?.());
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -4696,21 +4738,6 @@ export class ProjectService {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
private invalidateProjectPackageJson(packageJsonPath: Path | undefined) {
|
||||
this.configuredProjects.forEach(invalidate);
|
||||
this.inferredProjects.forEach(invalidate);
|
||||
this.externalProjects.forEach(invalidate);
|
||||
function invalidate(project: Project) {
|
||||
if (packageJsonPath) {
|
||||
project.onPackageJsonChange(packageJsonPath);
|
||||
}
|
||||
else {
|
||||
project.onAutoImportProviderSettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getIncompleteCompletionsCache() {
|
||||
return this.incompleteCompletionsCache ||= createIncompleteCompletionsCache();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
closeFileWatcher,
|
||||
Debug,
|
||||
FileWatcher,
|
||||
ModulePath,
|
||||
@@ -13,11 +14,12 @@ import {
|
||||
/** @internal */
|
||||
export interface ModuleSpecifierResolutionCacheHost {
|
||||
watchNodeModulesForPackageJsonChanges(directoryPath: string): FileWatcher;
|
||||
toPath(fileName: string): Path;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheHost): ModuleSpecifierCache {
|
||||
let containedNodeModulesWatchers: Map<string, FileWatcher> | undefined;
|
||||
let containedNodeModulesWatchers: Map<Path, FileWatcher> | undefined;
|
||||
let cache: Map<Path, ResolvedModuleSpecifierInfo> | undefined;
|
||||
let currentKey: string | undefined;
|
||||
const result: ModuleSpecifierCache = {
|
||||
@@ -38,9 +40,10 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH
|
||||
if (p.isInNodeModules) {
|
||||
// No trailing slash
|
||||
const nodeModulesPath = p.path.substring(0, p.path.indexOf(nodeModulesPathPart) + nodeModulesPathPart.length - 1);
|
||||
if (!containedNodeModulesWatchers?.has(nodeModulesPath)) {
|
||||
const key = host.toPath(nodeModulesPath);
|
||||
if (!containedNodeModulesWatchers?.has(key)) {
|
||||
(containedNodeModulesWatchers ||= new Map()).set(
|
||||
nodeModulesPath,
|
||||
key,
|
||||
host.watchNodeModulesForPackageJsonChanges(nodeModulesPath),
|
||||
);
|
||||
}
|
||||
@@ -69,7 +72,7 @@ export function createModuleSpecifierCache(host: ModuleSpecifierResolutionCacheH
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
containedNodeModulesWatchers?.forEach(watcher => watcher.close());
|
||||
containedNodeModulesWatchers?.forEach(closeFileWatcher);
|
||||
cache?.clear();
|
||||
containedNodeModulesWatchers?.clear();
|
||||
currentKey = undefined;
|
||||
|
||||
@@ -15,55 +15,59 @@ import {
|
||||
|
||||
/** @internal */
|
||||
export interface PackageJsonCache {
|
||||
addOrUpdate(fileName: Path): void;
|
||||
forEach(action: (info: ProjectPackageJsonInfo, fileName: Path) => void): void;
|
||||
addOrUpdate(fileName: string, path: Path): void;
|
||||
invalidate(path: Path): void;
|
||||
delete(fileName: Path): void;
|
||||
get(fileName: Path): ProjectPackageJsonInfo | false | undefined;
|
||||
getInDirectory(directory: Path): ProjectPackageJsonInfo | undefined;
|
||||
directoryHasPackageJson(directory: Path): Ternary;
|
||||
searchDirectoryAndAncestors(directory: Path): void;
|
||||
getInDirectory(directory: string): ProjectPackageJsonInfo | undefined;
|
||||
directoryHasPackageJson(directory: string): Ternary;
|
||||
searchDirectoryAndAncestors(directory: string): void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createPackageJsonCache(host: ProjectService): PackageJsonCache {
|
||||
const packageJsons = new Map<string, ProjectPackageJsonInfo>();
|
||||
const directoriesWithoutPackageJson = new Map<string, true>();
|
||||
const packageJsons = new Map<Path, ProjectPackageJsonInfo>();
|
||||
const directoriesWithoutPackageJson = new Map<Path, true>();
|
||||
return {
|
||||
addOrUpdate,
|
||||
forEach: packageJsons.forEach.bind(packageJsons),
|
||||
get: packageJsons.get.bind(packageJsons),
|
||||
invalidate,
|
||||
delete: fileName => {
|
||||
packageJsons.delete(fileName);
|
||||
directoriesWithoutPackageJson.set(getDirectoryPath(fileName), true);
|
||||
},
|
||||
getInDirectory: directory => {
|
||||
return packageJsons.get(combinePaths(directory, "package.json")) || undefined;
|
||||
return packageJsons.get(host.toPath(combinePaths(directory, "package.json"))) || undefined;
|
||||
},
|
||||
directoryHasPackageJson,
|
||||
directoryHasPackageJson: directory => directoryHasPackageJson(host.toPath(directory)),
|
||||
searchDirectoryAndAncestors: directory => {
|
||||
forEachAncestorDirectory(directory, ancestor => {
|
||||
if (directoryHasPackageJson(ancestor) !== Ternary.Maybe) {
|
||||
const ancestorPath = host.toPath(ancestor);
|
||||
if (directoryHasPackageJson(ancestorPath) !== Ternary.Maybe) {
|
||||
return true;
|
||||
}
|
||||
const packageJsonFileName = host.toPath(combinePaths(ancestor, "package.json"));
|
||||
const packageJsonFileName = combinePaths(ancestor, "package.json");
|
||||
if (tryFileExists(host, packageJsonFileName)) {
|
||||
addOrUpdate(packageJsonFileName);
|
||||
addOrUpdate(packageJsonFileName, combinePaths(ancestorPath, "package.json") as Path);
|
||||
}
|
||||
else {
|
||||
directoriesWithoutPackageJson.set(ancestor, true);
|
||||
directoriesWithoutPackageJson.set(ancestorPath, true);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function addOrUpdate(fileName: Path) {
|
||||
function addOrUpdate(fileName: string, path: Path) {
|
||||
const packageJsonInfo = Debug.checkDefined(createPackageJsonInfo(fileName, host.host));
|
||||
packageJsons.set(fileName, packageJsonInfo);
|
||||
directoriesWithoutPackageJson.delete(getDirectoryPath(fileName));
|
||||
packageJsons.set(path, packageJsonInfo);
|
||||
directoriesWithoutPackageJson.delete(getDirectoryPath(path));
|
||||
}
|
||||
|
||||
function invalidate(path: Path) {
|
||||
packageJsons.delete(path);
|
||||
directoriesWithoutPackageJson.delete(getDirectoryPath(path));
|
||||
}
|
||||
|
||||
function directoryHasPackageJson(directory: Path) {
|
||||
return packageJsons.has(combinePaths(directory, "package.json")) ? Ternary.True :
|
||||
return packageJsons.has(combinePaths(directory, "package.json") as Path) ? Ternary.True :
|
||||
directoriesWithoutPackageJson.has(directory) ? Ternary.False :
|
||||
Ternary.Maybe;
|
||||
}
|
||||
|
||||
+19
-16
@@ -144,6 +144,7 @@ import {
|
||||
ModuleImportResult,
|
||||
Msg,
|
||||
NormalizedPath,
|
||||
PackageJsonWatcher,
|
||||
projectContainsInfoDirectly,
|
||||
ProjectOptions,
|
||||
ProjectReferenceProjectLoadKind,
|
||||
@@ -347,7 +348,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
readonly realpath?: (path: string) => string;
|
||||
|
||||
/** @internal */
|
||||
hasInvalidatedResolutions: HasInvalidatedResolutions | undefined;
|
||||
hasInvalidatedResolutions?: HasInvalidatedResolutions | undefined;
|
||||
|
||||
/** @internal */
|
||||
hasInvalidatedLibResolutions: HasInvalidatedLibResolutions | undefined;
|
||||
@@ -398,7 +399,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
originalConfiguredProjects: Set<NormalizedPath> | undefined;
|
||||
|
||||
/** @internal */
|
||||
private packageJsonsForAutoImport: Set<string> | undefined;
|
||||
packageJsonWatches: Set<PackageJsonWatcher> | undefined;
|
||||
|
||||
/** @internal */
|
||||
noDtsResolutionProject?: AuxiliaryProject | undefined;
|
||||
@@ -1080,6 +1081,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.resolutionCache.clear();
|
||||
this.resolutionCache = undefined!;
|
||||
this.cachedUnresolvedImportsPerFile = undefined!;
|
||||
this.packageJsonWatches?.forEach(watcher => {
|
||||
watcher.projects.delete(this);
|
||||
watcher.close();
|
||||
});
|
||||
this.packageJsonWatches = undefined;
|
||||
this.moduleSpecifierCache.clear();
|
||||
this.moduleSpecifierCache = undefined!;
|
||||
this.directoryStructureHost = undefined!;
|
||||
this.exportMapCache = undefined;
|
||||
@@ -1308,12 +1315,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
onPackageJsonChange(packageJsonPath: Path) {
|
||||
if (this.packageJsonsForAutoImport?.has(packageJsonPath)) {
|
||||
this.moduleSpecifierCache.clear();
|
||||
if (this.autoImportProviderHost) {
|
||||
this.autoImportProviderHost.markAsDirty();
|
||||
}
|
||||
onPackageJsonChange() {
|
||||
this.moduleSpecifierCache.clear();
|
||||
if (this.autoImportProviderHost) {
|
||||
this.autoImportProviderHost.markAsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1569,7 +1574,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.program,
|
||||
this.missingFilesMap || (this.missingFilesMap = new Map()),
|
||||
// Watch the missing files
|
||||
missingFilePath => this.addMissingFileWatcher(missingFilePath),
|
||||
(missingFilePath, missingFileName) => this.addMissingFileWatcher(missingFilePath, missingFileName),
|
||||
);
|
||||
|
||||
if (this.generatedFilesMap) {
|
||||
@@ -1694,14 +1699,14 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
}
|
||||
}
|
||||
|
||||
private addMissingFileWatcher(missingFilePath: Path): FileWatcher {
|
||||
private addMissingFileWatcher(missingFilePath: Path, missingFileName: string): FileWatcher {
|
||||
if (isConfiguredProject(this)) {
|
||||
// If this file is referenced config file, we are already watching it, no need to watch again
|
||||
const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(missingFilePath as string as NormalizedPath);
|
||||
if (configFileExistenceInfo?.config?.projects.has(this.canonicalConfigFilePath)) return noopFileWatcher;
|
||||
}
|
||||
const fileWatcher = this.projectService.watchFactory.watchFile(
|
||||
missingFilePath,
|
||||
getNormalizedAbsolutePath(missingFileName, this.currentDirectory),
|
||||
(fileName, eventKind) => {
|
||||
if (isConfiguredProject(this)) {
|
||||
this.getCachedDirectoryStructureHost().addOrDeleteFile(fileName, missingFilePath, eventKind);
|
||||
@@ -2078,7 +2083,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
/** @internal */
|
||||
getPackageJsonsVisibleToFile(fileName: string, rootDir?: string): readonly ProjectPackageJsonInfo[] {
|
||||
if (this.projectService.serverMode !== LanguageServiceMode.Semantic) return emptyArray;
|
||||
return this.projectService.getPackageJsonsVisibleToFile(fileName, rootDir);
|
||||
return this.projectService.getPackageJsonsVisibleToFile(fileName, this, rootDir);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -2088,9 +2093,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
|
||||
/** @internal */
|
||||
getPackageJsonsForAutoImport(rootDir?: string): readonly ProjectPackageJsonInfo[] {
|
||||
const packageJsons = this.getPackageJsonsVisibleToFile(combinePaths(this.currentDirectory, inferredTypesContainingFile), rootDir);
|
||||
this.packageJsonsForAutoImport = new Set(packageJsons.map(p => p.fileName));
|
||||
return packageJsons;
|
||||
return this.getPackageJsonsVisibleToFile(combinePaths(this.currentDirectory, inferredTypesContainingFile), rootDir);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -2188,7 +2191,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
|
||||
/** @internal */
|
||||
watchNodeModulesForPackageJsonChanges(directoryPath: string) {
|
||||
return this.projectService.watchPackageJsonsInNodeModules(this.toPath(directoryPath), this);
|
||||
return this.projectService.watchPackageJsonsInNodeModules(directoryPath, this);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
+16
-8
@@ -53,6 +53,7 @@ import {
|
||||
formatting,
|
||||
getDeclarationFromName,
|
||||
getDeclarationOfKind,
|
||||
getDocumentSpansEqualityComparer,
|
||||
getEmitDeclarations,
|
||||
getEntrypointsFromPackageJsonInfo,
|
||||
getLineAndCharacterOfPosition,
|
||||
@@ -498,8 +499,8 @@ interface ProjectNavigateToItems {
|
||||
navigateToItems: readonly NavigateToItem[];
|
||||
}
|
||||
|
||||
function createDocumentSpanSet(): Set<DocumentSpan> {
|
||||
return createSet(({ textSpan }) => textSpan.start + 100003 * textSpan.length, documentSpansEqual);
|
||||
function createDocumentSpanSet(useCaseSensitiveFileNames: boolean): Set<DocumentSpan> {
|
||||
return createSet(({ textSpan }) => textSpan.start + 100003 * textSpan.length, getDocumentSpansEqualityComparer(useCaseSensitiveFileNames));
|
||||
}
|
||||
|
||||
function getRenameLocationsWorker(
|
||||
@@ -509,6 +510,7 @@ function getRenameLocationsWorker(
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean,
|
||||
preferences: protocol.UserPreferences,
|
||||
useCaseSensitiveFileNames: boolean,
|
||||
): readonly RenameLocation[] {
|
||||
const perProjectResults = getPerProjectReferences(
|
||||
projects,
|
||||
@@ -525,7 +527,7 @@ function getRenameLocationsWorker(
|
||||
}
|
||||
|
||||
const results: RenameLocation[] = [];
|
||||
const seen = createDocumentSpanSet();
|
||||
const seen = createDocumentSpanSet(useCaseSensitiveFileNames);
|
||||
|
||||
perProjectResults.forEach((projectResults, project) => {
|
||||
for (const result of projectResults) {
|
||||
@@ -552,6 +554,7 @@ function getReferencesWorker(
|
||||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
initialLocation: DocumentPosition,
|
||||
useCaseSensitiveFileNames: boolean,
|
||||
logger: Logger,
|
||||
): readonly ReferencedSymbol[] {
|
||||
const perProjectResults = getPerProjectReferences(
|
||||
@@ -593,7 +596,7 @@ function getReferencesWorker(
|
||||
}
|
||||
else {
|
||||
// Correct isDefinition properties from projects other than defaultProject
|
||||
const knownSymbolSpans = createDocumentSpanSet();
|
||||
const knownSymbolSpans = createDocumentSpanSet(useCaseSensitiveFileNames);
|
||||
for (const referencedSymbol of defaultProjectResults) {
|
||||
for (const ref of referencedSymbol.references) {
|
||||
if (ref.isDefinition) {
|
||||
@@ -632,7 +635,7 @@ function getReferencesWorker(
|
||||
// of each definition and merging references from all the projects where they appear.
|
||||
|
||||
const results: ReferencedSymbol[] = [];
|
||||
const seenRefs = createDocumentSpanSet(); // It doesn't make sense to have a reference in two definition lists, so we de-dup globally
|
||||
const seenRefs = createDocumentSpanSet(useCaseSensitiveFileNames); // It doesn't make sense to have a reference in two definition lists, so we de-dup globally
|
||||
|
||||
// TODO: We might end up with a more logical allocation of refs to defs if we pre-sorted the defs by descending ref-count.
|
||||
// Otherwise, it just ends up attached to the first corresponding def we happen to process. The others may or may not be
|
||||
@@ -649,7 +652,7 @@ function getReferencesWorker(
|
||||
contextSpan: getMappedContextSpanForProject(referencedSymbol.definition, project),
|
||||
};
|
||||
|
||||
let symbolToAddTo = find(results, o => documentSpansEqual(o.definition, definition));
|
||||
let symbolToAddTo = find(results, o => documentSpansEqual(o.definition, definition, useCaseSensitiveFileNames));
|
||||
if (!symbolToAddTo) {
|
||||
symbolToAddTo = { definition, references: [] };
|
||||
results.push(symbolToAddTo);
|
||||
@@ -1542,7 +1545,10 @@ export class Session<TMessage = string> implements EventSender {
|
||||
);
|
||||
|
||||
if (needsJsResolution) {
|
||||
const definitionSet = createSet<DefinitionInfo>(d => d.textSpan.start, documentSpansEqual);
|
||||
const definitionSet = createSet<DefinitionInfo>(
|
||||
d => d.textSpan.start,
|
||||
getDocumentSpansEqualityComparer(this.host.useCaseSensitiveFileNames),
|
||||
);
|
||||
definitions?.forEach(d => definitionSet.add(d));
|
||||
const noDtsProject = project.getNoDtsResolutionProject(file);
|
||||
const ls = noDtsProject.getLanguageService();
|
||||
@@ -1993,6 +1999,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
!!args.findInStrings,
|
||||
!!args.findInComments,
|
||||
preferences,
|
||||
this.host.useCaseSensitiveFileNames,
|
||||
);
|
||||
if (!simplifiedResult) return locations;
|
||||
return { info: renameInfo, locs: this.toSpanGroups(locations) };
|
||||
@@ -2029,6 +2036,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
projects,
|
||||
this.getDefaultProject(args),
|
||||
{ fileName: args.file, pos: position },
|
||||
this.host.useCaseSensitiveFileNames,
|
||||
this.logger,
|
||||
);
|
||||
|
||||
@@ -2054,7 +2062,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
const preferences = this.getPreferences(toNormalizedPath(fileName));
|
||||
|
||||
const references: ReferenceEntry[] = [];
|
||||
const seen = createDocumentSpanSet();
|
||||
const seen = createDocumentSpanSet(this.host.useCaseSensitiveFileNames);
|
||||
|
||||
forEachProjectInProjects(projects, /*path*/ undefined, project => {
|
||||
if (project.getCancellationToken().isCancellationRequested()) return;
|
||||
|
||||
@@ -3122,7 +3122,7 @@ function getContextualType(previousToken: Node, position: number, sourceFile: So
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
|
||||
default:
|
||||
const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile);
|
||||
const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile, checker);
|
||||
return argInfo ?
|
||||
// At `,`, treat this as the next argument after the comma.
|
||||
checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) :
|
||||
|
||||
@@ -163,6 +163,7 @@ import {
|
||||
isParameterPropertyDeclaration,
|
||||
isPrivateIdentifierClassElementDeclaration,
|
||||
isPropertyAccessExpression,
|
||||
isPropertySignature,
|
||||
isQualifiedName,
|
||||
isReferencedFile,
|
||||
isReferenceFileLocation,
|
||||
@@ -2471,7 +2472,7 @@ export namespace Core {
|
||||
if (isStringLiteralLike(ref) && ref.text === node.text) {
|
||||
if (type) {
|
||||
const refType = getContextualTypeFromParentOrAncestorTypeNode(ref, checker);
|
||||
if (type !== checker.getStringType() && type === refType) {
|
||||
if (type !== checker.getStringType() && (type === refType || isStringLiteralPropertyReference(ref, checker))) {
|
||||
return nodeEntry(ref, EntryKind.StringLiteral);
|
||||
}
|
||||
}
|
||||
@@ -2489,6 +2490,12 @@ export namespace Core {
|
||||
}];
|
||||
}
|
||||
|
||||
function isStringLiteralPropertyReference(node: StringLiteralLike, checker: TypeChecker) {
|
||||
if (isPropertySignature(node.parent)) {
|
||||
return checker.getPropertyOfType(checker.getTypeAtLocation(node.parent.parent), node.text);
|
||||
}
|
||||
}
|
||||
|
||||
// For certain symbol kinds, we need to include other symbols in the search set.
|
||||
// This is not needed when searching for re-exports.
|
||||
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): Symbol[] {
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
ModuleResolutionHost,
|
||||
moduleSpecifiers,
|
||||
normalizePath,
|
||||
Path,
|
||||
pathIsRelative,
|
||||
Program,
|
||||
PropertyAssignment,
|
||||
@@ -214,7 +213,7 @@ function updateImports(
|
||||
|
||||
// Need an update if the imported file moved, or the importing file moved and was using a relative path.
|
||||
return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && pathIsRelative(importLiteral.text)))
|
||||
? moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), sourceFile, getCanonicalFileName(newImportFromPath) as Path, toImport.newFileName, createModuleSpecifierResolutionHost(program, host), importLiteral.text)
|
||||
? moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), sourceFile, newImportFromPath, toImport.newFileName, createModuleSpecifierResolutionHost(program, host), importLiteral.text)
|
||||
: undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
EnumMember,
|
||||
equateStringsCaseInsensitive,
|
||||
escapeString,
|
||||
escapeTemplateSubstitution,
|
||||
Expression,
|
||||
findChildOfKind,
|
||||
findIndex,
|
||||
@@ -53,6 +54,7 @@ import {
|
||||
isIdentifierText,
|
||||
isImportTypeNode,
|
||||
isIndexedAccessTypeNode,
|
||||
isIndexSignatureDeclaration,
|
||||
isInferTypeNode,
|
||||
isInfinityOrNaNString,
|
||||
isIntersectionTypeNode,
|
||||
@@ -76,7 +78,12 @@ import {
|
||||
isQualifiedName,
|
||||
isRestTypeNode,
|
||||
isSpreadElement,
|
||||
isStringLiteral,
|
||||
isTemplateHead,
|
||||
isTemplateLiteralTypeNode,
|
||||
isTemplateLiteralTypeSpan,
|
||||
isTemplateMiddle,
|
||||
isTemplateTail,
|
||||
isThisTypeNode,
|
||||
isTupleTypeNode,
|
||||
isTypeLiteralNode,
|
||||
isTypeNode,
|
||||
@@ -88,7 +95,7 @@ import {
|
||||
isUnionTypeNode,
|
||||
isVarConst,
|
||||
isVariableDeclaration,
|
||||
LiteralExpression,
|
||||
LiteralLikeNode,
|
||||
MethodDeclaration,
|
||||
NewExpression,
|
||||
Node,
|
||||
@@ -105,6 +112,7 @@ import {
|
||||
Symbol,
|
||||
SymbolFlags,
|
||||
SyntaxKind,
|
||||
TemplateLiteralLikeNode,
|
||||
textSpanIntersectsWith,
|
||||
tokenToString,
|
||||
TupleTypeReference,
|
||||
@@ -743,6 +751,17 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
|
||||
visitForDisplayParts(node.type);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.IndexSignature:
|
||||
Debug.assertNode(node, isIndexSignatureDeclaration);
|
||||
Debug.assertEqual(node.parameters.length, 1);
|
||||
parts.push({ text: "[" });
|
||||
visitForDisplayParts(node.parameters[0]);
|
||||
parts.push({ text: "]" });
|
||||
if (node.type) {
|
||||
parts.push({ text: ": " });
|
||||
visitForDisplayParts(node.type);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.MethodSignature:
|
||||
Debug.assertNode(node, isMethodSignature);
|
||||
if (node.modifiers?.length) {
|
||||
@@ -792,6 +811,32 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
|
||||
parts.push({ text: tokenToString(node.operator) });
|
||||
visitForDisplayParts(node.operand);
|
||||
break;
|
||||
case SyntaxKind.TemplateLiteralType:
|
||||
Debug.assertNode(node, isTemplateLiteralTypeNode);
|
||||
visitForDisplayParts(node.head);
|
||||
node.templateSpans.forEach(visitForDisplayParts);
|
||||
break;
|
||||
case SyntaxKind.TemplateHead:
|
||||
Debug.assertNode(node, isTemplateHead);
|
||||
parts.push({ text: getLiteralText(node) });
|
||||
break;
|
||||
case SyntaxKind.TemplateLiteralTypeSpan:
|
||||
Debug.assertNode(node, isTemplateLiteralTypeSpan);
|
||||
visitForDisplayParts(node.type);
|
||||
visitForDisplayParts(node.literal);
|
||||
break;
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
Debug.assertNode(node, isTemplateMiddle);
|
||||
parts.push({ text: getLiteralText(node) });
|
||||
break;
|
||||
case SyntaxKind.TemplateTail:
|
||||
Debug.assertNode(node, isTemplateTail);
|
||||
parts.push({ text: getLiteralText(node) });
|
||||
break;
|
||||
case SyntaxKind.ThisType:
|
||||
Debug.assertNode(node, isThisTypeNode);
|
||||
parts.push({ text: "this" });
|
||||
break;
|
||||
default:
|
||||
Debug.failBadSyntaxKind(node);
|
||||
}
|
||||
@@ -823,9 +868,23 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
|
||||
});
|
||||
}
|
||||
|
||||
function getLiteralText(node: LiteralExpression) {
|
||||
if (isStringLiteral(node)) {
|
||||
return quotePreference === QuotePreference.Single ? `'${escapeString(node.text, CharacterCodes.singleQuote)}'` : `"${escapeString(node.text, CharacterCodes.doubleQuote)}"`;
|
||||
function getLiteralText(node: LiteralLikeNode) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.StringLiteral:
|
||||
return quotePreference === QuotePreference.Single ? `'${escapeString(node.text, CharacterCodes.singleQuote)}'` : `"${escapeString(node.text, CharacterCodes.doubleQuote)}"`;
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
case SyntaxKind.TemplateTail: {
|
||||
const rawText = (node as TemplateLiteralLikeNode).rawText ?? escapeTemplateSubstitution(escapeString(node.text, CharacterCodes.backtick));
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TemplateHead:
|
||||
return "`" + rawText + "${";
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
return "}" + rawText + "${";
|
||||
case SyntaxKind.TemplateTail:
|
||||
return "}" + rawText + "`";
|
||||
}
|
||||
}
|
||||
}
|
||||
return node.text;
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ function getTargetFileImportsAndAddExportInOldFile(
|
||||
const resolved = program.getResolvedModule(oldFile, moduleSpecifier.text, getModeForUsageLocation(oldFile, moduleSpecifier));
|
||||
const fileName = resolved?.resolvedModule?.resolvedFileName;
|
||||
if (fileName && targetSourceFile) {
|
||||
const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), targetSourceFile, targetSourceFile.path, fileName, createModuleSpecifierResolutionHost(program, host));
|
||||
const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), targetSourceFile, targetSourceFile.fileName, fileName, createModuleSpecifierResolutionHost(program, host));
|
||||
append(copiedOldImports, filterImport(i, makeStringLiteral(newModuleSpecifier, quotePreference), name => importsToCopy.has(checker.getSymbolAtLocation(name)!)));
|
||||
}
|
||||
else {
|
||||
@@ -418,7 +418,7 @@ export function updateImportsInOtherFiles(
|
||||
deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file
|
||||
|
||||
const pathToTargetFileWithExtension = resolvePath(getDirectoryPath(oldFile.path), targetFileName);
|
||||
const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.path, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host));
|
||||
const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host));
|
||||
const newImportDeclaration = filterImport(importNode, makeStringLiteral(newModuleSpecifier, quotePreference), shouldMove);
|
||||
if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration);
|
||||
|
||||
@@ -570,7 +570,7 @@ export function makeImportOrRequire(
|
||||
quotePreference: QuotePreference,
|
||||
): AnyImportOrRequireStatement | undefined {
|
||||
const pathToTargetFile = resolvePath(getDirectoryPath(sourceFile.path), targetFileNameWithExtension);
|
||||
const pathToTargetFileWithCorrectExtension = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.path, pathToTargetFile, createModuleSpecifierResolutionHost(program, host));
|
||||
const pathToTargetFileWithCorrectExtension = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFile, createModuleSpecifierResolutionHost(program, host));
|
||||
|
||||
if (useEs6Imports) {
|
||||
const specifiers = imports.map(i => factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, factory.createIdentifier(i)));
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
createTextSpanFromBounds,
|
||||
createTextSpanFromNode,
|
||||
Debug,
|
||||
ElementFlags,
|
||||
EmitHint,
|
||||
emptyArray,
|
||||
Expression,
|
||||
@@ -49,6 +50,7 @@ import {
|
||||
isPropertyAccessExpression,
|
||||
isSourceFile,
|
||||
isSourceFileJS,
|
||||
isSpreadElement,
|
||||
isTaggedTemplateExpression,
|
||||
isTemplateHead,
|
||||
isTemplateLiteralToken,
|
||||
@@ -58,6 +60,7 @@ import {
|
||||
JsxTagNameExpression,
|
||||
last,
|
||||
lastOrUndefined,
|
||||
length,
|
||||
ListFormat,
|
||||
map,
|
||||
mapToDisplayParts,
|
||||
@@ -77,6 +80,7 @@ import {
|
||||
skipTrivia,
|
||||
SourceFile,
|
||||
spacePart,
|
||||
SpreadElement,
|
||||
Symbol,
|
||||
SymbolDisplayPart,
|
||||
symbolToDisplayParts,
|
||||
@@ -85,6 +89,7 @@ import {
|
||||
TemplateExpression,
|
||||
TextSpan,
|
||||
tryCast,
|
||||
TupleTypeReference,
|
||||
Type,
|
||||
TypeChecker,
|
||||
TypeParameter,
|
||||
@@ -272,25 +277,25 @@ export interface ArgumentInfoForCompletions {
|
||||
readonly argumentCount: number;
|
||||
}
|
||||
/** @internal */
|
||||
export function getArgumentInfoForCompletions(node: Node, position: number, sourceFile: SourceFile): ArgumentInfoForCompletions | undefined {
|
||||
const info = getImmediatelyContainingArgumentInfo(node, position, sourceFile);
|
||||
export function getArgumentInfoForCompletions(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentInfoForCompletions | undefined {
|
||||
const info = getImmediatelyContainingArgumentInfo(node, position, sourceFile, checker);
|
||||
return !info || info.isTypeParameterList || info.invocation.kind !== InvocationKind.Call ? undefined
|
||||
: { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex };
|
||||
}
|
||||
|
||||
function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile: SourceFile): { readonly list: Node; readonly argumentIndex: number; readonly argumentCount: number; readonly argumentsSpan: TextSpan; } | undefined {
|
||||
const info = getArgumentOrParameterListAndIndex(node, sourceFile);
|
||||
function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): { readonly list: Node; readonly argumentIndex: number; readonly argumentCount: number; readonly argumentsSpan: TextSpan; } | undefined {
|
||||
const info = getArgumentOrParameterListAndIndex(node, sourceFile, checker);
|
||||
if (!info) return undefined;
|
||||
const { list, argumentIndex } = info;
|
||||
|
||||
const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node));
|
||||
const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node), checker);
|
||||
if (argumentIndex !== 0) {
|
||||
Debug.assertLessThan(argumentIndex, argumentCount);
|
||||
}
|
||||
const argumentsSpan = getApplicableSpanForArguments(list, sourceFile);
|
||||
return { list, argumentIndex, argumentCount, argumentsSpan };
|
||||
}
|
||||
function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile): { readonly list: Node; readonly argumentIndex: number; } | undefined {
|
||||
function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile, checker: TypeChecker): { readonly list: Node; readonly argumentIndex: number; } | undefined {
|
||||
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
|
||||
// Find the list that starts right *after* the < or ( token.
|
||||
// If the user has just opened a list, consider this item 0.
|
||||
@@ -304,7 +309,7 @@ function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile):
|
||||
// - On the target of the call (parent.func)
|
||||
// - On the 'new' keyword in a 'new' expression
|
||||
const list = findContainingList(node);
|
||||
return list && { list, argumentIndex: getArgumentIndex(list, node) };
|
||||
return list && { list, argumentIndex: getArgumentIndex(list, node, checker) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +317,7 @@ function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile):
|
||||
* Returns relevant information for the argument list and the current argument if we are
|
||||
* in the argument of an invocation; returns undefined otherwise.
|
||||
*/
|
||||
function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined {
|
||||
function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined {
|
||||
const { parent } = node;
|
||||
if (isCallOrNewExpression(parent)) {
|
||||
const invocation = parent;
|
||||
@@ -331,7 +336,7 @@ function getImmediatelyContainingArgumentInfo(node: Node, position: number, sour
|
||||
// Case 3:
|
||||
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give signature help
|
||||
// Find out if 'node' is an argument, a type argument, or neither
|
||||
const info = getArgumentOrParameterListInfo(node, position, sourceFile);
|
||||
const info = getArgumentOrParameterListInfo(node, position, sourceFile, checker);
|
||||
if (!info) return undefined;
|
||||
const { list, argumentIndex, argumentCount, argumentsSpan } = info;
|
||||
const isTypeParameterList = !!parent.typeArguments && parent.typeArguments.pos === list.pos;
|
||||
@@ -397,7 +402,7 @@ function getImmediatelyContainingArgumentInfo(node: Node, position: number, sour
|
||||
}
|
||||
|
||||
function getImmediatelyContainingArgumentOrContextualParameterInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined {
|
||||
return tryGetParameterInfo(node, position, sourceFile, checker) || getImmediatelyContainingArgumentInfo(node, position, sourceFile);
|
||||
return tryGetParameterInfo(node, position, sourceFile, checker) || getImmediatelyContainingArgumentInfo(node, position, sourceFile, checker);
|
||||
}
|
||||
|
||||
function getHighestBinary(b: BinaryExpression): BinaryExpression {
|
||||
@@ -452,7 +457,7 @@ function getContextualSignatureLocationInfo(node: Node, sourceFile: SourceFile,
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
const info = getArgumentOrParameterListInfo(node, position, sourceFile);
|
||||
const info = getArgumentOrParameterListInfo(node, position, sourceFile, checker);
|
||||
if (!info) return undefined;
|
||||
const { argumentIndex, argumentCount, argumentsSpan } = info;
|
||||
const contextualType = isMethodDeclaration(parent) ? checker.getContextualTypeForObjectLiteralElement(parent) : checker.getContextualType(parent as ParenthesizedExpression | FunctionExpression | ArrowFunction);
|
||||
@@ -476,7 +481,7 @@ function chooseBetterSymbol(s: Symbol): Symbol {
|
||||
: s;
|
||||
}
|
||||
|
||||
function getArgumentIndex(argumentsList: Node, node: Node) {
|
||||
function getArgumentIndex(argumentsList: Node, node: Node, checker: TypeChecker) {
|
||||
// The list we got back can include commas. In the presence of errors it may
|
||||
// also just have nodes without commas. For example "Foo(a b c)" will have 3
|
||||
// args without commas. We want to find what index we're at. So we count
|
||||
@@ -488,20 +493,39 @@ function getArgumentIndex(argumentsList: Node, node: Node) {
|
||||
// on. In that case, even if we're after the trailing comma, we'll still see
|
||||
// that trailing comma in the list, and we'll have generated the appropriate
|
||||
// arg index.
|
||||
const args = argumentsList.getChildren();
|
||||
let argumentIndex = 0;
|
||||
for (const child of argumentsList.getChildren()) {
|
||||
for (let pos = 0; pos < length(args); pos++) {
|
||||
const child = args[pos];
|
||||
if (child === node) {
|
||||
break;
|
||||
}
|
||||
if (child.kind !== SyntaxKind.CommaToken) {
|
||||
argumentIndex++;
|
||||
if (isSpreadElement(child)) {
|
||||
argumentIndex = argumentIndex + getSpreadElementCount(child, checker) + (pos > 0 ? pos : 0);
|
||||
}
|
||||
else {
|
||||
if (child.kind !== SyntaxKind.CommaToken) {
|
||||
argumentIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return argumentIndex;
|
||||
}
|
||||
|
||||
function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean) {
|
||||
function getSpreadElementCount(node: SpreadElement, checker: TypeChecker) {
|
||||
const spreadType = checker.getTypeAtLocation(node.expression);
|
||||
if (checker.isTupleType(spreadType)) {
|
||||
const { elementFlags, fixedLength } = (spreadType as TupleTypeReference).target;
|
||||
if (fixedLength === 0) {
|
||||
return 0;
|
||||
}
|
||||
const firstOptionalIndex = findIndex(elementFlags, f => !(f & ElementFlags.Required));
|
||||
return firstOptionalIndex < 0 ? fixedLength : firstOptionalIndex;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean, checker: TypeChecker) {
|
||||
// The argument count for a list is normally the number of non-comma children it has.
|
||||
// For example, if you have "Foo(a,b)" then there will be three children of the arg
|
||||
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
|
||||
@@ -515,7 +539,14 @@ function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean) {
|
||||
// arg count of 3.
|
||||
const listChildren = argumentsList.getChildren();
|
||||
|
||||
let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
|
||||
let argumentCount = 0;
|
||||
for (const child of listChildren) {
|
||||
if (isSpreadElement(child)) {
|
||||
argumentCount = argumentCount + getSpreadElementCount(child, checker);
|
||||
}
|
||||
}
|
||||
|
||||
argumentCount = argumentCount + countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
|
||||
if (!ignoreTrailingComma && listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) {
|
||||
argumentCount++;
|
||||
}
|
||||
|
||||
@@ -133,13 +133,13 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper {
|
||||
const fileFromCache = sourceFileLike.get(path);
|
||||
if (fileFromCache !== undefined) return fileFromCache ? fileFromCache : undefined;
|
||||
|
||||
if (!host.readFile || host.fileExists && !host.fileExists(path)) {
|
||||
if (!host.readFile || host.fileExists && !host.fileExists(fileName)) {
|
||||
sourceFileLike.set(path, false);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// And failing that, check the disk
|
||||
const text = host.readFile(path);
|
||||
const text = host.readFile(fileName);
|
||||
const file = text ? createSourceFileLike(text) : false;
|
||||
sourceFileLike.set(path, file);
|
||||
return file ? file : undefined;
|
||||
|
||||
@@ -407,7 +407,7 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
if (!isRequireCallArgument(node) && !isImportCall(parent)) {
|
||||
const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile);
|
||||
const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile, typeChecker);
|
||||
// Get string literal completions from specialized signatures of the target
|
||||
// i.e. declare function f(a: 'A');
|
||||
// f("/*completion position*/")
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface TranspileOptions {
|
||||
moduleName?: string;
|
||||
renamedDependencies?: MapLike<string>;
|
||||
transformers?: CustomTransformers;
|
||||
jsDocParsingMode?: JSDocParsingMode;
|
||||
}
|
||||
|
||||
export interface TranspileOutput {
|
||||
@@ -121,7 +122,7 @@ export function transpileModule(input: string, transpileOptions: TranspileOption
|
||||
languageVersion: getEmitScriptTarget(options),
|
||||
impliedNodeFormat: getImpliedNodeFormatForFile(toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*packageJsonInfoCache*/ undefined, compilerHost, options),
|
||||
setExternalModuleIndicator: getSetExternalModuleIndicator(options),
|
||||
jsDocParsingMode: JSDocParsingMode.ParseNone,
|
||||
jsDocParsingMode: transpileOptions.jsDocParsingMode ?? JSDocParsingMode.ParseAll,
|
||||
},
|
||||
);
|
||||
if (transpileOptions.moduleName) {
|
||||
|
||||
@@ -340,7 +340,7 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR
|
||||
*/
|
||||
readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
|
||||
realpath?(path: string): string;
|
||||
/** @internal */ createHash?(data: string): string;
|
||||
/** @internal */ createHash?: ((data: string) => string) | undefined;
|
||||
|
||||
/*
|
||||
* Unlike `realpath and `readDirectory`, `readFile` and `fileExists` are now _required_
|
||||
@@ -393,9 +393,9 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR
|
||||
* If provided along with custom resolveLibrary, used to determine if we should redo library resolutions
|
||||
* @internal
|
||||
*/
|
||||
hasInvalidatedLibResolutions?(libFileName: string): boolean;
|
||||
hasInvalidatedLibResolutions?: ((libFileName: string) => boolean) | undefined;
|
||||
|
||||
/** @internal */ hasInvalidatedResolutions?: HasInvalidatedResolutions;
|
||||
/** @internal */ hasInvalidatedResolutions?: HasInvalidatedResolutions | undefined;
|
||||
/** @internal */ hasChangedAutomaticTypeDirectiveNames?: HasChangedAutomaticTypeDirectiveNames;
|
||||
/** @internal */ getGlobalTypingsCacheLocation?(): string | undefined;
|
||||
/** @internal */ getSymlinkCache?(files?: readonly SourceFile[]): SymlinkCache;
|
||||
@@ -432,7 +432,7 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR
|
||||
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
|
||||
/** @internal */ getIncompleteCompletionsCache?(): IncompleteCompletionsCache;
|
||||
|
||||
jsDocParsingMode?: JSDocParsingMode;
|
||||
jsDocParsingMode?: JSDocParsingMode | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -59,7 +59,10 @@ import {
|
||||
EndOfFileToken,
|
||||
endsWith,
|
||||
ensureScriptKind,
|
||||
EqualityComparer,
|
||||
EqualityOperator,
|
||||
equateStringsCaseInsensitive,
|
||||
equateStringsCaseSensitive,
|
||||
escapeString,
|
||||
ExportAssignment,
|
||||
ExportDeclaration,
|
||||
@@ -2663,8 +2666,14 @@ export function textSpansEqual(a: TextSpan | undefined, b: TextSpan | undefined)
|
||||
return !!a && !!b && a.start === b.start && a.length === b.length;
|
||||
}
|
||||
/** @internal */
|
||||
export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean {
|
||||
return a.fileName === b.fileName && textSpansEqual(a.textSpan, b.textSpan);
|
||||
export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan, useCaseSensitiveFileNames: boolean): boolean {
|
||||
return (useCaseSensitiveFileNames ? equateStringsCaseSensitive : equateStringsCaseInsensitive)(a.fileName, b.fileName) &&
|
||||
textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getDocumentSpansEqualityComparer(useCaseSensitiveFileNames: boolean): EqualityComparer<DocumentSpan> {
|
||||
return (a, b) => documentSpansEqual(a, b, useCaseSensitiveFileNames);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {
|
||||
createWatchUtils,
|
||||
Watches,
|
||||
WatchUtils,
|
||||
} from "../../../harness/watchUtils";
|
||||
import {
|
||||
arrayFrom,
|
||||
@@ -33,7 +35,6 @@ import {
|
||||
matchFiles,
|
||||
ModuleImportResult,
|
||||
ModuleResolutionHost,
|
||||
MultiMap,
|
||||
noop,
|
||||
patchWriteFileEnsuringDirectory,
|
||||
Path,
|
||||
@@ -155,17 +156,6 @@ function isFsSymLink(s: FSEntry | undefined): s is FsSymLink {
|
||||
return !!s && isString((s as FsSymLink).symLink);
|
||||
}
|
||||
|
||||
function invokeWatcherCallbacks<T>(callbacks: readonly T[] | undefined, invokeCallback: (cb: T) => void): void {
|
||||
if (callbacks) {
|
||||
// The array copy is made to ensure that even if one of the callback removes the callbacks,
|
||||
// we dont miss any callbacks following it
|
||||
const cbs = callbacks.slice();
|
||||
for (const cb of cbs) {
|
||||
invokeCallback(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface StateLogger {
|
||||
log(s: string): void;
|
||||
logs: string[];
|
||||
@@ -351,7 +341,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
readonly pendingInstalls = new Callbacks(this, "PendingInstalls");
|
||||
readonly screenClears: number[] = [];
|
||||
|
||||
readonly watchUtils = createWatchUtils<TestFileWatcher, TestFsWatcher, Path>("PolledWatches", "FsWatches");
|
||||
readonly watchUtils: WatchUtils<TestFileWatcher, TestFsWatcher>;
|
||||
runWithFallbackPolling: boolean;
|
||||
public readonly useCaseSensitiveFileNames: boolean;
|
||||
public readonly newLine: string;
|
||||
@@ -387,6 +377,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.environmentVariables = environmentVariables;
|
||||
currentDirectory = currentDirectory || "/";
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
this.watchUtils = createWatchUtils("PolledWatches", "FsWatches", s => this.getCanonicalFileName(s));
|
||||
this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath || getExecutingFilePathFromLibFile());
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
|
||||
@@ -691,7 +682,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
|
||||
private watchFileWorker(fileName: string, cb: FileWatcherCallback, pollingInterval: PollingInterval) {
|
||||
return this.watchUtils.pollingWatch(
|
||||
this.toFullPath(fileName),
|
||||
this.toNormalizedAbsolutePath(fileName),
|
||||
{ cb, pollingInterval },
|
||||
);
|
||||
}
|
||||
@@ -702,11 +693,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
cb: FsWatchCallback,
|
||||
) {
|
||||
if (this.runWithFallbackPolling) throw new Error("Need to use fallback polling instead of file system native watching");
|
||||
const path = this.toFullPath(fileOrDirectory);
|
||||
const path = this.toPath(fileOrDirectory);
|
||||
// Error if the path does not exist
|
||||
if (this.inodeWatching && !this.inodes?.has(path)) throw new Error();
|
||||
const result = this.watchUtils.fsWatch(
|
||||
path,
|
||||
this.toNormalizedAbsolutePath(fileOrDirectory),
|
||||
recursive,
|
||||
{
|
||||
cb,
|
||||
@@ -718,13 +709,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
|
||||
invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, modifiedTime: Date | undefined) {
|
||||
invokeWatcherCallbacks(this.watchUtils.pollingWatches.get(this.toPath(fileFullPath)), ({ cb }) => cb(fileFullPath, eventKind, modifiedTime));
|
||||
this.watchUtils.pollingWatches.forEach(fileFullPath, ({ cb }) => cb(fileFullPath, eventKind, modifiedTime));
|
||||
}
|
||||
|
||||
private fsWatchCallback(map: MultiMap<Path, TestFsWatcher>, fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, entryFullPath: string | undefined, useTildeSuffix: boolean | undefined) {
|
||||
private fsWatchCallback(watches: Watches<TestFsWatcher>, fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, entryFullPath: string | undefined, useTildeSuffix: boolean | undefined) {
|
||||
const path = this.toPath(fullPath);
|
||||
const currentInode = this.inodes?.get(path);
|
||||
invokeWatcherCallbacks(map.get(path), ({ cb, inode }) => {
|
||||
watches.forEach(path, ({ cb, inode }) => {
|
||||
// TODO::
|
||||
if (this.inodeWatching && inode !== undefined && inode !== currentInode) return;
|
||||
let relativeFileName = entryFullPath ? this.getRelativePathToDirectory(fullPath, entryFullPath) : "";
|
||||
|
||||
@@ -7,8 +7,9 @@ import {
|
||||
jsonToReadableText,
|
||||
} from "./helpers";
|
||||
|
||||
function verifyMissingFilePaths(missingPaths: readonly ts.Path[], expected: readonly string[]) {
|
||||
assert.isDefined(missingPaths);
|
||||
function verifyMissingFilePaths(missing: ReturnType<ts.Program["getMissingFilePaths"]>, expected: readonly string[]) {
|
||||
assert.isDefined(missing);
|
||||
const missingPaths = ts.arrayFrom(missing.keys());
|
||||
const map = new Set(expected);
|
||||
for (const missing of missingPaths) {
|
||||
const value = map.has(missing);
|
||||
@@ -82,8 +83,8 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => {
|
||||
it("normalizes file paths", () => {
|
||||
const program0 = ts.createProgram(["./nonexistent.ts", "./NONEXISTENT.ts"], options, testCompilerHost);
|
||||
const program1 = ts.createProgram(["./NONEXISTENT.ts", "./nonexistent.ts"], options, testCompilerHost);
|
||||
const missing0 = program0.getMissingFilePaths();
|
||||
const missing1 = program1.getMissingFilePaths();
|
||||
const missing0 = ts.arrayFrom(program0.getMissingFilePaths().keys());
|
||||
const missing1 = ts.arrayFrom(program1.getMissingFilePaths().keys());
|
||||
assert.equal(missing0.length, 1);
|
||||
assert.deepEqual(missing0, missing1);
|
||||
});
|
||||
@@ -138,7 +139,7 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => {
|
||||
|
||||
const program = ts.createProgram(["test.ts"], { module: ts.ModuleKind.ES2015 }, host);
|
||||
assert(program.getSourceFiles().length === 1, "expected 'getSourceFiles' length to be 1");
|
||||
assert(program.getMissingFilePaths().length === 0, "expected 'getMissingFilePaths' length to be 0");
|
||||
assert(program.getMissingFilePaths().size === 0, "expected 'getMissingFilePaths' length to be 0");
|
||||
assert((program.getFileProcessingDiagnostics()?.length || 0) === 0, "expected 'getFileProcessingDiagnostics' length to be 0");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ describe("unittests:: Reuse program structure:: General", () => {
|
||||
host.getTrace().forEach(trace => baselines.push(Utils.sanitizeTraceResolutionLogEntry(trace)));
|
||||
host.clearTrace();
|
||||
baselines.push("");
|
||||
baselines.push(`MissingPaths:: ${jsonToReadableText(program.getMissingFilePaths())}`);
|
||||
baselines.push(`MissingPaths:: ${jsonToReadableText(ts.arrayFrom(program.getMissingFilePaths().values()))}`);
|
||||
baselines.push("");
|
||||
baselines.push(ts.formatDiagnostics(program.getSemanticDiagnostics(), {
|
||||
getCurrentDirectory: () => program.getCurrentDirectory(),
|
||||
|
||||
@@ -38,7 +38,11 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
const originalSerializeWatches = host.serializeWatches;
|
||||
host.serializeWatches = serializeWatches;
|
||||
host.factoryData = {
|
||||
watchUtils: createWatchUtils<ts.server.protocol.CreateFileWatcherEventBody, ts.server.protocol.CreateDirectoryWatcherEventBody>(`Custom WatchedFiles`, `Custom WatchedDirectories`),
|
||||
watchUtils: createWatchUtils<ts.server.protocol.CreateFileWatcherEventBody, ts.server.protocol.CreateDirectoryWatcherEventBody>(
|
||||
"Custom WatchedFiles",
|
||||
"Custom WatchedDirectories",
|
||||
host.getCanonicalFileName,
|
||||
),
|
||||
watchFile,
|
||||
watchDirectory,
|
||||
closeWatcher,
|
||||
@@ -95,11 +99,13 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
function addFile(session: TestSession, path: string) {
|
||||
updateFileOnHost(session, path, "Add file");
|
||||
session.logger.log("Custom watch");
|
||||
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchUtils.fsWatchesRecursive.get("/user/username/projects/myproject")?.forEach(data =>
|
||||
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.WatchChange,
|
||||
arguments: { id: data.id, path, eventType: "create" },
|
||||
})
|
||||
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchUtils.fsWatchesRecursive.forEach(
|
||||
"/user/username/projects/myproject",
|
||||
data =>
|
||||
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.WatchChange,
|
||||
arguments: { id: data.id, path, eventType: "create" },
|
||||
}),
|
||||
);
|
||||
session.host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
@@ -107,11 +113,13 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
function changeFile(session: TestSession, path: string) {
|
||||
updateFileOnHost(session, path, "Change File");
|
||||
session.logger.log("Custom watch");
|
||||
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchUtils.pollingWatches.get(path)?.forEach(data =>
|
||||
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.WatchChange,
|
||||
arguments: { id: data.id, path, eventType: "update" },
|
||||
})
|
||||
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchUtils.pollingWatches.forEach(
|
||||
path,
|
||||
data =>
|
||||
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.WatchChange,
|
||||
arguments: { id: data.id, path, eventType: "update" },
|
||||
}),
|
||||
);
|
||||
session.host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
@@ -39,12 +38,12 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
it("detects new package.json files that are added, caches them, and watches them", () => {
|
||||
// Initialize project without package.json
|
||||
const { session, projectService, host } = setup([tsConfig]);
|
||||
assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path));
|
||||
assert.isUndefined(projectService.packageJsonCache.getInDirectory("/"));
|
||||
|
||||
// Add package.json
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.host.baselineHost("Add package.json");
|
||||
let packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
let packageJsonInfo = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.ok(packageJsonInfo);
|
||||
assert.ok(packageJsonInfo.dependencies);
|
||||
assert.ok(packageJsonInfo.devDependencies);
|
||||
@@ -60,7 +59,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
}),
|
||||
);
|
||||
session.host.baselineHost("Edit package.json");
|
||||
packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
packageJsonInfo = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.isUndefined(packageJsonInfo.dependencies);
|
||||
|
||||
baselineTsserverLogs("packageJsonInfo", "detects new package.json files that are added, caches them, and watches them", session);
|
||||
@@ -68,39 +67,39 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
|
||||
it("finds package.json on demand, watches for deletion, and removes them from cache", () => {
|
||||
// Initialize project with package.json
|
||||
const { session, projectService, host } = setup();
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
assert.ok(projectService.packageJsonCache.getInDirectory("/" as ts.Path));
|
||||
const { session, projectService, host, project } = setup();
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts", project);
|
||||
assert.ok(projectService.packageJsonCache.getInDirectory("/"));
|
||||
|
||||
// Delete package.json
|
||||
host.deleteFile(packageJson.path);
|
||||
session.host.baselineHost("delete packageJson");
|
||||
assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path));
|
||||
assert.isUndefined(projectService.packageJsonCache.getInDirectory("/"));
|
||||
baselineTsserverLogs("packageJsonInfo", "finds package.json on demand, watches for deletion, and removes them from cache", session);
|
||||
});
|
||||
|
||||
it("finds multiple package.json files when present", () => {
|
||||
// Initialize project with package.json at root
|
||||
const { session, projectService, host } = setup();
|
||||
const { session, projectService, host, project } = setup();
|
||||
// Add package.json in /src
|
||||
host.writeFile("/src/package.json", packageJson.content);
|
||||
session.host.baselineHost("packageJson");
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/a.ts" as ts.Path), 1);
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/src/b.ts" as ts.Path), 2);
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/a.ts", project), 1);
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/src/b.ts", project), 2);
|
||||
baselineTsserverLogs("packageJsonInfo", "finds multiple package.json files when present", session);
|
||||
});
|
||||
|
||||
it("handles errors in json parsing of package.json", () => {
|
||||
const packageJsonContent = `{ "mod" }`;
|
||||
const { session, projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]);
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
const { session, projectService, host, project } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]);
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts", project);
|
||||
const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.isFalse(packageJsonInfo.parseable);
|
||||
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.host.baselineHost("packageJson");
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts", project);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.ok(packageJsonInfo2);
|
||||
assert.ok(packageJsonInfo2.dependencies);
|
||||
assert.ok(packageJsonInfo2.devDependencies);
|
||||
@@ -111,15 +110,15 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
|
||||
it("handles empty package.json", () => {
|
||||
const packageJsonContent = "";
|
||||
const { session, projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]);
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
const { session, projectService, host, project } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]);
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts", project);
|
||||
const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.isFalse(packageJsonInfo.parseable);
|
||||
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.host.baselineHost("PackageJson");
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts", project);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/")!;
|
||||
assert.ok(packageJsonInfo2);
|
||||
assert.ok(packageJsonInfo2.dependencies);
|
||||
assert.ok(packageJsonInfo2.devDependencies);
|
||||
@@ -133,5 +132,13 @@ function setup(files: readonly File[] = [tsConfig, packageJson]) {
|
||||
const host = createServerHost(files);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([files[0]], session);
|
||||
return { host, session, projectService: session.getProjectService() };
|
||||
const projectService = session.getProjectService();
|
||||
const getPackageJsonsVisibleToFile = projectService.getPackageJsonsVisibleToFile;
|
||||
projectService.getPackageJsonsVisibleToFile = (fileName, project, rootDir) => {
|
||||
session.host.baselineHost(`getPackageJsonsVisibleToFile:: ${fileName} ${rootDir}`);
|
||||
const result = getPackageJsonsVisibleToFile.call(projectService, fileName, project, rootDir);
|
||||
session.host.baselineHost(`getPackageJsonsVisibleToFile:: ${fileName} ${rootDir}:: Result:: ${jsonToReadableText(result)}`);
|
||||
return result;
|
||||
};
|
||||
return { host, session, projectService, project: projectService.inferredProjects[0] };
|
||||
}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
} from "../../_namespaces/Utils";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
libContent,
|
||||
} from "../helpers/contents";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
openFilesForSession,
|
||||
@@ -8,6 +17,7 @@ import {
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch";
|
||||
|
||||
describe("unittests:: tsserver:: rename", () => {
|
||||
@@ -131,4 +141,56 @@ describe("unittests:: tsserver:: rename", () => {
|
||||
});
|
||||
baselineTsserverLogs("rename", "rename behavior is based on file of rename initiation", session);
|
||||
});
|
||||
|
||||
it("with symlinks and case difference", () => {
|
||||
const file: File = {
|
||||
path: "C:/temp/test/project1/index.ts",
|
||||
content: dedent`
|
||||
export function myFunc() {
|
||||
}
|
||||
`,
|
||||
};
|
||||
const host = createServerHost({
|
||||
[file.path]: file.content,
|
||||
"C:/temp/test/project1/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"C:/temp/test/project1/package.json": jsonToReadableText({
|
||||
name: "project1",
|
||||
version: "1.0.0",
|
||||
main: "index.js",
|
||||
}),
|
||||
"C:/temp/test/project2/index.ts": dedent`
|
||||
import { myFunc } from 'project1'
|
||||
myFunc();
|
||||
`,
|
||||
"C:/temp/test/project2/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../project1" },
|
||||
],
|
||||
}),
|
||||
"C:/temp/test/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "./project1" },
|
||||
{ path: "./project2" },
|
||||
],
|
||||
files: [],
|
||||
include: [],
|
||||
}),
|
||||
"C:/temp/test/node_modules/project1": { symLink: "c:/temp/test/project1" },
|
||||
[libFile.path]: libContent,
|
||||
}, { windowsStyleRoot: "C:/" });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file.path.toLowerCase()], session);
|
||||
session.executeCommandSeq<ts.server.protocol.RenameRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Rename,
|
||||
arguments: protocolFileLocationFromSubstring(file, "myFunc"),
|
||||
});
|
||||
baselineTsserverLogs("rename", "with symlinks and case difference", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,91 +119,95 @@ describe("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem Watche
|
||||
verifyWatchedDirectories("files not at root", "c:/", /*useProjectAtRoot*/ false);
|
||||
});
|
||||
|
||||
it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive watch directory implementation does not watch files/directories in node_modules starting with "."`, () => {
|
||||
const projectFolder = "/a/username/project";
|
||||
const projectSrcFolder = `${projectFolder}/src`;
|
||||
const configFile: File = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
content: "{}",
|
||||
};
|
||||
const index: File = {
|
||||
path: `${projectSrcFolder}/index.ts`,
|
||||
content: `import {} from "file"`,
|
||||
};
|
||||
const file1: File = {
|
||||
path: `${projectSrcFolder}/file1.ts`,
|
||||
content: "",
|
||||
};
|
||||
const nodeModulesExistingUnusedFile: File = {
|
||||
path: `${projectFolder}/node_modules/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const environmentVariables = new Map<string, string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
|
||||
const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([index], session);
|
||||
describe("unittests:: tsserver:: watchEnvironment:: recursiveWatchDirectory", () => {
|
||||
it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive watch directory implementation does not watch files/directories in node_modules starting with "."`, () => {
|
||||
const projectFolder = "/a/username/project";
|
||||
const projectSrcFolder = `${projectFolder}/src`;
|
||||
const configFile: File = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
content: "{}",
|
||||
};
|
||||
const index: File = {
|
||||
path: `${projectSrcFolder}/index.ts`,
|
||||
content: `import {} from "file"`,
|
||||
};
|
||||
const file1: File = {
|
||||
path: `${projectSrcFolder}/file1.ts`,
|
||||
content: "",
|
||||
};
|
||||
const nodeModulesExistingUnusedFile: File = {
|
||||
path: `${projectFolder}/node_modules/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const environmentVariables = new Map<string, string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
|
||||
const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([index], session);
|
||||
|
||||
const nodeModulesIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/node_modules/.cache/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const nodeModulesIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/node_modules/.cache/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
|
||||
const nodeModulesIgnoredFile: File = {
|
||||
path: `${projectFolder}/node_modules/.cacheFile.ts`,
|
||||
content: "",
|
||||
};
|
||||
const nodeModulesIgnoredFile: File = {
|
||||
path: `${projectFolder}/node_modules/.cacheFile.ts`,
|
||||
content: "",
|
||||
};
|
||||
|
||||
const gitIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/.git/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const gitIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/.git/someFile.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
|
||||
const gitIgnoredFile: File = {
|
||||
path: `${projectFolder}/.gitCache.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const emacsIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/src/.#field.ts`,
|
||||
content: "",
|
||||
};
|
||||
const gitIgnoredFile: File = {
|
||||
path: `${projectFolder}/.gitCache.d.ts`,
|
||||
content: "",
|
||||
};
|
||||
const emacsIgnoredFileFromIgnoreDirectory: File = {
|
||||
path: `${projectFolder}/src/.#field.ts`,
|
||||
content: "",
|
||||
};
|
||||
|
||||
[
|
||||
nodeModulesIgnoredFileFromIgnoreDirectory,
|
||||
nodeModulesIgnoredFile,
|
||||
gitIgnoredFileFromIgnoreDirectory,
|
||||
gitIgnoredFile,
|
||||
emacsIgnoredFileFromIgnoreDirectory,
|
||||
].forEach(ignoredEntity => {
|
||||
host.ensureFileOrFolder(ignoredEntity);
|
||||
session.host.baselineHost("After writing ignored file or folder");
|
||||
[
|
||||
nodeModulesIgnoredFileFromIgnoreDirectory,
|
||||
nodeModulesIgnoredFile,
|
||||
gitIgnoredFileFromIgnoreDirectory,
|
||||
gitIgnoredFile,
|
||||
emacsIgnoredFileFromIgnoreDirectory,
|
||||
].forEach(ignoredEntity => {
|
||||
host.ensureFileOrFolder(ignoredEntity);
|
||||
session.host.baselineHost("After writing ignored file or folder");
|
||||
});
|
||||
|
||||
baselineTsserverLogs("watchEnvironment", `recursive directory does not watch files starting with dot in node_modules`, session);
|
||||
});
|
||||
|
||||
baselineTsserverLogs("watchEnvironment", `recursive directory does not watch files starting with dot in node_modules`, session);
|
||||
});
|
||||
|
||||
it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching files with network style paths", () => {
|
||||
const logger = createLoggerWithInMemoryLogs(/*host*/ undefined!); // Special handling to ensure same logger is used
|
||||
verifyFilePathStyle("c:/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/c$/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("c:/users/username/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/c$/users/username/myprojects/project/x.js", logger);
|
||||
baselineTsserverLogs("watchEnvironment", `watching files with network style paths`, { logger });
|
||||
describe("unittests:: tsserver:: watchEnvironment:: networkStylePaths", () => {
|
||||
it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching files with network style paths", () => {
|
||||
const logger = createLoggerWithInMemoryLogs(/*host*/ undefined!); // Special handling to ensure same logger is used
|
||||
verifyFilePathStyle("c:/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/c$/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("c:/users/username/myprojects/project/x.js", logger);
|
||||
verifyFilePathStyle("//vda1cs4850/c$/users/username/myprojects/project/x.js", logger);
|
||||
baselineTsserverLogs("watchEnvironment", `watching files with network style paths`, { logger });
|
||||
|
||||
function verifyFilePathStyle(path: string, logger: LoggerWithInMemoryLogs) {
|
||||
const windowsStyleRoot = path.substring(0, ts.getRootLength(path));
|
||||
const file: File = { path, content: "const x = 10" };
|
||||
const host = createServerHost(
|
||||
[libFile, file],
|
||||
{ windowsStyleRoot },
|
||||
);
|
||||
logger.host = host;
|
||||
logger.info(`For files of style ${path}`);
|
||||
logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
const session = new TestSession({ host, logger });
|
||||
openFilesForSession([file], session);
|
||||
}
|
||||
function verifyFilePathStyle(path: string, logger: LoggerWithInMemoryLogs) {
|
||||
const windowsStyleRoot = path.substring(0, ts.getRootLength(path));
|
||||
const file: File = { path, content: "const x = 10" };
|
||||
const host = createServerHost(
|
||||
[libFile, file],
|
||||
{ windowsStyleRoot },
|
||||
);
|
||||
logger.host = host;
|
||||
logger.info(`For files of style ${path}`);
|
||||
logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
const session = new TestSession({ host, logger });
|
||||
openFilesForSession([file], session);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler options", () => {
|
||||
@@ -527,3 +531,19 @@ describe("unittests:: tsserver:: watchEnvironment:: watching at workspaces codes
|
||||
baselineTsserverLogs("watchEnvironment", "watching npm install in codespaces where workspaces folder is hosted at root", session);
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: watchEnvironment:: perVolumeCasing", () => {
|
||||
it("new file addition", () => {
|
||||
const host = createServerHost([libFile]);
|
||||
// Make /Volumes case sensitive
|
||||
host.getCanonicalFileName = s => ts.startsWith(s, "/Volumes/") ? s : ts.toFileNameLowerCase(s);
|
||||
host.ensureFileOrFolder({ path: "/Volumes/git/projects/project/foo.ts", content: `export const foo = "foo";` });
|
||||
host.writeFile("/Volumes/git/projects/project/tsconfig.json", "{ }");
|
||||
host.writeFile("/Volumes/git/projects/project/package.json", jsonToReadableText({ name: "project", version: "1.0.0" }));
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/Volumes/git/projects/project/foo.ts"], session);
|
||||
host.writeFile("/Volumes/git/projects/project/Bar.ts", `export const bar = "bar";`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("watchEnvironment", "perVolumeCasing and new file addition", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
=== DateTimeFormatAndNumberFormatES2021.ts ===
|
||||
Intl.NumberFormat.prototype.formatRange
|
||||
>Intl.NumberFormat.prototype : Symbol(prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Intl.NumberFormat.prototype : Symbol(Intl.NumberFormatConstructor.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Intl.NumberFormat : Symbol(Intl.NumberFormat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2018.intl.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
>Intl : Symbol(Intl, Decl(lib.es5.d.ts, --, --), Decl(lib.es2016.intl.d.ts, --, --), Decl(lib.es2017.intl.d.ts, --, --), Decl(lib.es2018.intl.d.ts, --, --), Decl(lib.es2019.intl.d.ts, --, --) ... and 3 more)
|
||||
>NumberFormat : Symbol(Intl.NumberFormat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2018.intl.d.ts, --, --), Decl(lib.es2020.bigint.d.ts, --, --))
|
||||
>prototype : Symbol(prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>prototype : Symbol(Intl.NumberFormatConstructor.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
Intl.DateTimeFormat.prototype.formatRange
|
||||
>Intl.DateTimeFormat.prototype.formatRange : Symbol(Intl.DateTimeFormat.formatRange, Decl(lib.es2021.intl.d.ts, --, --))
|
||||
>Intl.DateTimeFormat.prototype : Symbol(prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Intl.DateTimeFormat.prototype : Symbol(Intl.DateTimeFormatConstructor.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Intl.DateTimeFormat : Symbol(Intl.DateTimeFormat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2017.intl.d.ts, --, --), Decl(lib.es2021.intl.d.ts, --, --))
|
||||
>Intl : Symbol(Intl, Decl(lib.es5.d.ts, --, --), Decl(lib.es2016.intl.d.ts, --, --), Decl(lib.es2017.intl.d.ts, --, --), Decl(lib.es2018.intl.d.ts, --, --), Decl(lib.es2019.intl.d.ts, --, --) ... and 3 more)
|
||||
>DateTimeFormat : Symbol(Intl.DateTimeFormat, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2017.intl.d.ts, --, --), Decl(lib.es2021.intl.d.ts, --, --))
|
||||
>prototype : Symbol(prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>prototype : Symbol(Intl.DateTimeFormatConstructor.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>formatRange : Symbol(Intl.DateTimeFormat.formatRange, Decl(lib.es2021.intl.d.ts, --, --))
|
||||
|
||||
new Intl.NumberFormat().formatRange
|
||||
|
||||
@@ -4,50 +4,50 @@
|
||||
Intl.NumberFormat.prototype.formatRange
|
||||
>Intl.NumberFormat.prototype.formatRange : any
|
||||
>Intl.NumberFormat.prototype : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>prototype : Intl.NumberFormat
|
||||
>formatRange : any
|
||||
|
||||
Intl.DateTimeFormat.prototype.formatRange
|
||||
>Intl.DateTimeFormat.prototype.formatRange : (startDate: number | bigint | Date, endDate: number | bigint | Date) => string
|
||||
>Intl.DateTimeFormat.prototype : Intl.DateTimeFormat
|
||||
>Intl.DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>Intl.DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>prototype : Intl.DateTimeFormat
|
||||
>formatRange : (startDate: number | bigint | Date, endDate: number | bigint | Date) => string
|
||||
|
||||
new Intl.NumberFormat().formatRange
|
||||
>new Intl.NumberFormat().formatRange : any
|
||||
>new Intl.NumberFormat() : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>formatRange : any
|
||||
|
||||
new Intl.NumberFormat().formatRangeToParts
|
||||
>new Intl.NumberFormat().formatRangeToParts : any
|
||||
>new Intl.NumberFormat() : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>formatRangeToParts : any
|
||||
|
||||
new Intl.DateTimeFormat().formatRange
|
||||
>new Intl.DateTimeFormat().formatRange : (startDate: number | bigint | Date, endDate: number | bigint | Date) => string
|
||||
>new Intl.DateTimeFormat() : Intl.DateTimeFormat
|
||||
>Intl.DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>Intl.DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>formatRange : (startDate: number | bigint | Date, endDate: number | bigint | Date) => string
|
||||
|
||||
new Intl.DateTimeFormat().formatRangeToParts
|
||||
>new Intl.DateTimeFormat().formatRangeToParts : (startDate: number | bigint | Date, endDate: number | bigint | Date) => Intl.DateTimeRangeFormatPart[]
|
||||
>new Intl.DateTimeFormat() : Intl.DateTimeFormat
|
||||
>Intl.DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>Intl.DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>DateTimeFormat : { (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; new (locales?: string | string[], options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat; supportedLocalesOf(locales: string | string[], options?: Intl.DateTimeFormatOptions): string[]; readonly prototype: Intl.DateTimeFormat; }
|
||||
>DateTimeFormat : Intl.DateTimeFormatConstructor
|
||||
>formatRangeToParts : (startDate: number | bigint | Date, endDate: number | bigint | Date) => Intl.DateTimeRangeFormatPart[]
|
||||
|
||||
|
||||
+6
-3
@@ -6020,9 +6020,11 @@ declare namespace ts {
|
||||
/** @deprecated */
|
||||
type AssertionKey = ImportAttributeName;
|
||||
/** @deprecated */
|
||||
type AssertEntry = ImportAttribute;
|
||||
interface AssertEntry extends ImportAttribute {
|
||||
}
|
||||
/** @deprecated */
|
||||
type AssertClause = ImportAttributes;
|
||||
interface AssertClause extends ImportAttributes {
|
||||
}
|
||||
type ImportAttributeName = Identifier | StringLiteral;
|
||||
interface ImportAttribute extends Node {
|
||||
readonly kind: SyntaxKind.ImportAttribute;
|
||||
@@ -10442,7 +10444,7 @@ declare namespace ts {
|
||||
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
|
||||
writeFile?(fileName: string, content: string): void;
|
||||
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
|
||||
jsDocParsingMode?: JSDocParsingMode;
|
||||
jsDocParsingMode?: JSDocParsingMode | undefined;
|
||||
}
|
||||
type WithMetadata<T> = T & {
|
||||
metadata?: unknown;
|
||||
@@ -11638,6 +11640,7 @@ declare namespace ts {
|
||||
moduleName?: string;
|
||||
renamedDependencies?: MapLike<string>;
|
||||
transformers?: CustomTransformers;
|
||||
jsDocParsingMode?: JSDocParsingMode;
|
||||
}
|
||||
interface TranspileOutput {
|
||||
outputText: string;
|
||||
|
||||
@@ -8,12 +8,12 @@ arityErrorRelatedSpanBindingPattern.ts(7,1): error TS2554: Expected 3 arguments,
|
||||
function bar(a, b, [c]): void {}
|
||||
|
||||
foo("", 0);
|
||||
~~~~~~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 3 arguments, but got 2.
|
||||
!!! related TS6211 arityErrorRelatedSpanBindingPattern.ts:1:20: An argument matching this binding pattern was not provided.
|
||||
|
||||
bar("", 0);
|
||||
~~~~~~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 3 arguments, but got 2.
|
||||
!!! related TS6211 arityErrorRelatedSpanBindingPattern.ts:3:20: An argument matching this binding pattern was not provided.
|
||||
|
||||
@@ -31,7 +31,7 @@ const inputALike: ArrayLike<A> = { length: 0 };
|
||||
const inputARand = getEither(inputA, inputALike);
|
||||
>inputARand : ArrayLike<A> | Iterable<A>
|
||||
>getEither(inputA, inputALike) : ArrayLike<A> | Iterable<A>
|
||||
>getEither : <T>(in1: Iterable<T>, in2: ArrayLike<T>) => ArrayLike<T> | Iterable<T>
|
||||
>getEither : <T>(in1: Iterable<T>, in2: ArrayLike<T>) => Iterable<T> | ArrayLike<T>
|
||||
>inputA : A[]
|
||||
>inputALike : ArrayLike<A>
|
||||
|
||||
@@ -163,12 +163,12 @@ const result11: B[] = Array.from(inputASet, ({ a }): B => ({ b: a }));
|
||||
// the ?: as always taking the false branch, narrowing to ArrayLike<T>,
|
||||
// even when the type is written as : Iterable<T>|ArrayLike<T>
|
||||
function getEither<T> (in1: Iterable<T>, in2: ArrayLike<T>) {
|
||||
>getEither : <T>(in1: Iterable<T>, in2: ArrayLike<T>) => ArrayLike<T> | Iterable<T>
|
||||
>getEither : <T>(in1: Iterable<T>, in2: ArrayLike<T>) => Iterable<T> | ArrayLike<T>
|
||||
>in1 : Iterable<T>
|
||||
>in2 : ArrayLike<T>
|
||||
|
||||
return Math.random() > 0.5 ? in1 : in2;
|
||||
>Math.random() > 0.5 ? in1 : in2 : ArrayLike<T> | Iterable<T>
|
||||
>Math.random() > 0.5 ? in1 : in2 : Iterable<T> | ArrayLike<T>
|
||||
>Math.random() > 0.5 : boolean
|
||||
>Math.random() : number
|
||||
>Math.random : () => number
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
//// [tests/cases/compiler/avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts] ////
|
||||
|
||||
=== avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts ===
|
||||
declare const foo: ["a", string, number] | ["b", string, boolean];
|
||||
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
|
||||
|
||||
export function test(arg: { index?: number }) {
|
||||
>test : Symbol(test, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 66))
|
||||
>arg : Symbol(arg, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 21))
|
||||
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 27))
|
||||
|
||||
const { index = 0 } = arg;
|
||||
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 3, 9))
|
||||
>arg : Symbol(arg, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 21))
|
||||
|
||||
if (foo[index] === "a") {
|
||||
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
|
||||
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 3, 9))
|
||||
|
||||
foo;
|
||||
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
//// [tests/cases/compiler/avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts] ////
|
||||
|
||||
=== avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts ===
|
||||
declare const foo: ["a", string, number] | ["b", string, boolean];
|
||||
>foo : ["a", string, number] | ["b", string, boolean]
|
||||
|
||||
export function test(arg: { index?: number }) {
|
||||
>test : (arg: { index?: number | undefined; }) => void
|
||||
>arg : { index?: number | undefined; }
|
||||
>index : number | undefined
|
||||
|
||||
const { index = 0 } = arg;
|
||||
>index : number
|
||||
>0 : 0
|
||||
>arg : { index?: number | undefined; }
|
||||
|
||||
if (foo[index] === "a") {
|
||||
>foo[index] === "a" : boolean
|
||||
>foo[index] : string | number | boolean
|
||||
>foo : ["a", string, number] | ["b", string, boolean]
|
||||
>index : number
|
||||
>"a" : "a"
|
||||
|
||||
foo;
|
||||
>foo : ["a", string, number] | ["b", string, boolean]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ baseCheck.ts(26,9): error TS2304: Cannot find name 'x'.
|
||||
}
|
||||
|
||||
class D extends C { constructor(public z: number) { super(this.z) } } // too few params
|
||||
~~~~~~~~~~~~~
|
||||
~~~~~
|
||||
!!! error TS2554: Expected 2 arguments, but got 1.
|
||||
!!! related TS6210 baseCheck.ts:1:34: An argument for 'y' was not provided.
|
||||
~~~~
|
||||
|
||||
@@ -392,9 +392,9 @@ new Intl.NumberFormat("fr").format(3000n);
|
||||
>new Intl.NumberFormat("fr").format(3000n) : string
|
||||
>new Intl.NumberFormat("fr").format : { (value: number): string; (value: number | bigint): string; }
|
||||
>new Intl.NumberFormat("fr") : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>"fr" : "fr"
|
||||
>format : { (value: number): string; (value: number | bigint): string; }
|
||||
>3000n : 3000n
|
||||
@@ -403,9 +403,9 @@ new Intl.NumberFormat("fr").format(bigintVal);
|
||||
>new Intl.NumberFormat("fr").format(bigintVal) : string
|
||||
>new Intl.NumberFormat("fr").format : { (value: number): string; (value: number | bigint): string; }
|
||||
>new Intl.NumberFormat("fr") : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>"fr" : "fr"
|
||||
>format : { (value: number): string; (value: number | bigint): string; }
|
||||
>bigintVal : bigint
|
||||
|
||||
@@ -376,9 +376,9 @@ new Intl.NumberFormat("fr").format(3000n);
|
||||
>new Intl.NumberFormat("fr").format(3000n) : string
|
||||
>new Intl.NumberFormat("fr").format : (value: number) => string
|
||||
>new Intl.NumberFormat("fr") : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>"fr" : "fr"
|
||||
>format : (value: number) => string
|
||||
>3000n : 3000n
|
||||
@@ -387,9 +387,9 @@ new Intl.NumberFormat("fr").format(bigintVal);
|
||||
>new Intl.NumberFormat("fr").format(bigintVal) : string
|
||||
>new Intl.NumberFormat("fr").format : (value: number) => string
|
||||
>new Intl.NumberFormat("fr") : Intl.NumberFormat
|
||||
>Intl.NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>Intl.NumberFormat : Intl.NumberFormatConstructor
|
||||
>Intl : typeof Intl
|
||||
>NumberFormat : { (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; new (locales?: string | string[], options?: Intl.NumberFormatOptions): Intl.NumberFormat; supportedLocalesOf(locales: string | string[], options?: Intl.NumberFormatOptions): string[]; readonly prototype: Intl.NumberFormat; }
|
||||
>NumberFormat : Intl.NumberFormatConstructor
|
||||
>"fr" : "fr"
|
||||
>format : (value: number) => string
|
||||
>bigintVal : bigint
|
||||
|
||||
@@ -33,6 +33,6 @@ blockScopedSameNameFunctionDeclarationES5.ts(16,1): error TS2554: Expected 1 arg
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok - needs number
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationES5.ts:1:14: An argument for 'a' was not provided.
|
||||
@@ -33,6 +33,6 @@ blockScopedSameNameFunctionDeclarationES6.ts(16,1): error TS2554: Expected 1 arg
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok - needs number
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationES6.ts:1:14: An argument for 'a' was not provided.
|
||||
+2
-2
@@ -29,12 +29,12 @@ blockScopedSameNameFunctionDeclarationStrictES5.ts(17,1): error TS2554: Expected
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok - needs number
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationStrictES5.ts:2:14: An argument for 'a' was not provided.
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok - needs number
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationStrictES5.ts:2:14: An argument for 'a' was not provided.
|
||||
+2
-2
@@ -23,12 +23,12 @@ blockScopedSameNameFunctionDeclarationStrictES6.ts(17,1): error TS2554: Expected
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationStrictES6.ts:2:14: An argument for 'a' was not provided.
|
||||
}
|
||||
foo(10);
|
||||
foo(); // not ok - needs number
|
||||
~~~~~
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 blockScopedSameNameFunctionDeclarationStrictES6.ts:2:14: An argument for 'a' was not provided.
|
||||
@@ -19,7 +19,7 @@ callOverload.ts(11,10): error TS2556: A spread argument must either have a tuple
|
||||
!!! error TS2554: Expected 2 arguments, but got 4.
|
||||
withRest('a', ...n); // no error
|
||||
withRest();
|
||||
~~~~~~~~~~
|
||||
~~~~~~~~
|
||||
!!! error TS2555: Expected at least 1 arguments, but got 0.
|
||||
!!! related TS6210 callOverload.ts:3:27: An argument for 'a' was not provided.
|
||||
withRest(...n);
|
||||
|
||||
@@ -28,19 +28,19 @@ callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
|
||||
declare const xAny: X<any>;
|
||||
xAny.f() // error, any still expects an argument
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
declare const xUnknown: X<unknown>;
|
||||
xUnknown.f() // error, unknown still expects an argument
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
declare const xNever: X<never>;
|
||||
xNever.f() // error, never still expects an argument
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:3:7: An argument for 't' was not provided.
|
||||
|
||||
@@ -56,15 +56,15 @@ callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
new MyPromise<void>(resolve => resolve()); // no error
|
||||
new MyPromise<void | number>(resolve => resolve()); // no error
|
||||
new MyPromise<any>(resolve => resolve()); // error, `any` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
new MyPromise<unknown>(resolve => resolve()); // error, `unknown` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
new MyPromise<never>(resolve => resolve()); // error, `never` arguments cannot be omitted
|
||||
~~~~~~~~~
|
||||
~~~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 callWithMissingVoid.ts:28:38: An argument for 'value' was not provided.
|
||||
|
||||
@@ -78,7 +78,7 @@ callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
a(4, "hello"); // ok
|
||||
a(4, "hello", void 0); // ok
|
||||
a(4); // not ok
|
||||
~~~~
|
||||
~
|
||||
!!! error TS2554: Expected 2-3 arguments, but got 1.
|
||||
!!! related TS6210 callWithMissingVoid.ts:42:23: An argument for 'y' was not provided.
|
||||
|
||||
@@ -88,15 +88,15 @@ callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
|
||||
b(4, "hello", void 0, 2); // ok
|
||||
b(4, "hello"); // not ok
|
||||
~~~~~~~~~~~~~
|
||||
~
|
||||
!!! error TS2554: Expected 4 arguments, but got 2.
|
||||
!!! related TS6210 callWithMissingVoid.ts:50:34: An argument for 'z' was not provided.
|
||||
b(4, "hello", void 0); // not ok
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
~
|
||||
!!! error TS2554: Expected 4 arguments, but got 3.
|
||||
!!! related TS6210 callWithMissingVoid.ts:50:43: An argument for 'what' was not provided.
|
||||
b(4); // not ok
|
||||
~~~~
|
||||
~
|
||||
!!! error TS2554: Expected 4 arguments, but got 1.
|
||||
!!! related TS6210 callWithMissingVoid.ts:50:23: An argument for 'y' was not provided.
|
||||
|
||||
@@ -117,7 +117,7 @@ callWithMissingVoid.ts(75,1): error TS2554: Expected 3 arguments, but got 1.
|
||||
...args: TS): void;
|
||||
|
||||
call((x: number, y: number) => x + y) // error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~
|
||||
!!! error TS2554: Expected 3 arguments, but got 1.
|
||||
!!! related TS6236 callWithMissingVoid.ts:73:5: Arguments for the rest parameter 'args' were not provided.
|
||||
call((x: number, y: number) => x + y, 4, 2) // ok
|
||||
|
||||
+6
-6
@@ -39,28 +39,28 @@ tsfile.ts(12,4): error TS2554: Expected 1 arguments, but got 0.
|
||||
|
||||
// no change in behavior
|
||||
f2();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:2:21: An argument for 'p' was not provided.
|
||||
f3();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:3:21: An argument for 'p' was not provided.
|
||||
f4();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:4:21: An argument for 'p' was not provided.
|
||||
|
||||
o2.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o3.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o4.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
|
||||
+12
-12
@@ -31,28 +31,28 @@ tsfile.ts(12,4): error TS2554: Expected 1 arguments, but got 0.
|
||||
|
||||
// new behavior: treat 'undefined', 'unknown', and 'any' as optional in non-strict mode
|
||||
f2();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:2:21: An argument for 'p' was not provided.
|
||||
f3();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:3:21: An argument for 'p' was not provided.
|
||||
f4();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:4:21: An argument for 'p' was not provided.
|
||||
|
||||
o2.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o3.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o4.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
|
||||
@@ -63,28 +63,28 @@ tsfile.ts(12,4): error TS2554: Expected 1 arguments, but got 0.
|
||||
|
||||
// no change in behavior
|
||||
f2();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:2:21: An argument for 'p' was not provided.
|
||||
f3();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:3:21: An argument for 'p' was not provided.
|
||||
f4();
|
||||
~~~~
|
||||
~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:4:21: An argument for 'p' was not provided.
|
||||
|
||||
o2.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o3.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
o4.m();
|
||||
~~~
|
||||
~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 defs.d.ts:6:20: An argument for 'p' was not provided.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//// [tests/cases/conformance/jsdoc/callbackTag4.ts] ////
|
||||
|
||||
=== ./a.js ===
|
||||
/**
|
||||
* @callback C
|
||||
* @this {{ a: string, b: number }}
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/** @type {C} */
|
||||
const cb = function (a, b) {
|
||||
>cb : Symbol(cb, Decl(a.js, 9, 5))
|
||||
>a : Symbol(a, Decl(a.js, 9, 21))
|
||||
>b : Symbol(b, Decl(a.js, 9, 23))
|
||||
|
||||
this
|
||||
>this : Symbol(this)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//// [tests/cases/conformance/jsdoc/callbackTag4.ts] ////
|
||||
|
||||
=== ./a.js ===
|
||||
/**
|
||||
* @callback C
|
||||
* @this {{ a: string, b: number }}
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/** @type {C} */
|
||||
const cb = function (a, b) {
|
||||
>cb : C
|
||||
>function (a, b) { this return true} : (this: { a: string; b: number; }, a: string, b: number) => boolean
|
||||
>a : string
|
||||
>b : number
|
||||
|
||||
this
|
||||
>this : { a: string; b: number; }
|
||||
|
||||
return true
|
||||
>true : true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//// [tests/cases/compiler/circularMappedTypeConstraint.ts] ////
|
||||
|
||||
=== circularMappedTypeConstraint.ts ===
|
||||
// Repro from #56232
|
||||
|
||||
declare function foo2<T extends { [P in keyof T & string as Capitalize<P>]: V }, V extends string>(a: T): T;
|
||||
>foo2 : Symbol(foo2, Decl(circularMappedTypeConstraint.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(circularMappedTypeConstraint.ts, 2, 22))
|
||||
>P : Symbol(P, Decl(circularMappedTypeConstraint.ts, 2, 35))
|
||||
>T : Symbol(T, Decl(circularMappedTypeConstraint.ts, 2, 22))
|
||||
>Capitalize : Symbol(Capitalize, Decl(lib.es5.d.ts, --, --))
|
||||
>P : Symbol(P, Decl(circularMappedTypeConstraint.ts, 2, 35))
|
||||
>V : Symbol(V, Decl(circularMappedTypeConstraint.ts, 2, 80))
|
||||
>V : Symbol(V, Decl(circularMappedTypeConstraint.ts, 2, 80))
|
||||
>a : Symbol(a, Decl(circularMappedTypeConstraint.ts, 2, 99))
|
||||
>T : Symbol(T, Decl(circularMappedTypeConstraint.ts, 2, 22))
|
||||
>T : Symbol(T, Decl(circularMappedTypeConstraint.ts, 2, 22))
|
||||
|
||||
export const r2 = foo2({A: "a"});
|
||||
>r2 : Symbol(r2, Decl(circularMappedTypeConstraint.ts, 3, 12))
|
||||
>foo2 : Symbol(foo2, Decl(circularMappedTypeConstraint.ts, 0, 0))
|
||||
>A : Symbol(A, Decl(circularMappedTypeConstraint.ts, 3, 24))
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//// [tests/cases/compiler/circularMappedTypeConstraint.ts] ////
|
||||
|
||||
=== circularMappedTypeConstraint.ts ===
|
||||
// Repro from #56232
|
||||
|
||||
declare function foo2<T extends { [P in keyof T & string as Capitalize<P>]: V }, V extends string>(a: T): T;
|
||||
>foo2 : <T extends { [P in keyof T & string as Capitalize<P>]: V; }, V extends string>(a: T) => T
|
||||
>a : T
|
||||
|
||||
export const r2 = foo2({A: "a"});
|
||||
>r2 : { A: string; }
|
||||
>foo2({A: "a"}) : { A: string; }
|
||||
>foo2 : <T extends { [P in keyof T & string as Capitalize<P>]: V; }, V extends string>(a: T) => T
|
||||
>{A: "a"} : { A: string; }
|
||||
>A : string
|
||||
>"a" : "a"
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//// [tests/cases/compiler/circularReferenceInReturnType.ts] ////
|
||||
|
||||
=== circularReferenceInReturnType.ts ===
|
||||
declare function fn1<T>(cb: () => T): string;
|
||||
>fn1 : Symbol(fn1, Decl(circularReferenceInReturnType.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 0, 21))
|
||||
>cb : Symbol(cb, Decl(circularReferenceInReturnType.ts, 0, 24))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 0, 21))
|
||||
|
||||
const res1 = fn1(() => res1);
|
||||
>res1 : Symbol(res1, Decl(circularReferenceInReturnType.ts, 1, 5))
|
||||
>fn1 : Symbol(fn1, Decl(circularReferenceInReturnType.ts, 0, 0))
|
||||
>res1 : Symbol(res1, Decl(circularReferenceInReturnType.ts, 1, 5))
|
||||
|
||||
declare function fn2<T>(): (cb: () => any) => (a: T) => void;
|
||||
>fn2 : Symbol(fn2, Decl(circularReferenceInReturnType.ts, 1, 29))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 3, 21))
|
||||
>cb : Symbol(cb, Decl(circularReferenceInReturnType.ts, 3, 28))
|
||||
>a : Symbol(a, Decl(circularReferenceInReturnType.ts, 3, 47))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 3, 21))
|
||||
|
||||
const res2 = fn2()(() => res2);
|
||||
>res2 : Symbol(res2, Decl(circularReferenceInReturnType.ts, 4, 5))
|
||||
>fn2 : Symbol(fn2, Decl(circularReferenceInReturnType.ts, 1, 29))
|
||||
>res2 : Symbol(res2, Decl(circularReferenceInReturnType.ts, 4, 5))
|
||||
|
||||
declare function fn3<T>(): <T2>(cb: (arg: T2) => any) => (a: T) => void;
|
||||
>fn3 : Symbol(fn3, Decl(circularReferenceInReturnType.ts, 4, 31))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 6, 21))
|
||||
>T2 : Symbol(T2, Decl(circularReferenceInReturnType.ts, 6, 28))
|
||||
>cb : Symbol(cb, Decl(circularReferenceInReturnType.ts, 6, 32))
|
||||
>arg : Symbol(arg, Decl(circularReferenceInReturnType.ts, 6, 37))
|
||||
>T2 : Symbol(T2, Decl(circularReferenceInReturnType.ts, 6, 28))
|
||||
>a : Symbol(a, Decl(circularReferenceInReturnType.ts, 6, 58))
|
||||
>T : Symbol(T, Decl(circularReferenceInReturnType.ts, 6, 21))
|
||||
|
||||
const res3 = fn3()(() => res3);
|
||||
>res3 : Symbol(res3, Decl(circularReferenceInReturnType.ts, 7, 5))
|
||||
>fn3 : Symbol(fn3, Decl(circularReferenceInReturnType.ts, 4, 31))
|
||||
>res3 : Symbol(res3, Decl(circularReferenceInReturnType.ts, 7, 5))
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//// [tests/cases/compiler/circularReferenceInReturnType.ts] ////
|
||||
|
||||
=== circularReferenceInReturnType.ts ===
|
||||
declare function fn1<T>(cb: () => T): string;
|
||||
>fn1 : <T>(cb: () => T) => string
|
||||
>cb : () => T
|
||||
|
||||
const res1 = fn1(() => res1);
|
||||
>res1 : string
|
||||
>fn1(() => res1) : string
|
||||
>fn1 : <T>(cb: () => T) => string
|
||||
>() => res1 : () => string
|
||||
>res1 : string
|
||||
|
||||
declare function fn2<T>(): (cb: () => any) => (a: T) => void;
|
||||
>fn2 : <T>() => (cb: () => any) => (a: T) => void
|
||||
>cb : () => any
|
||||
>a : T
|
||||
|
||||
const res2 = fn2()(() => res2);
|
||||
>res2 : (a: unknown) => void
|
||||
>fn2()(() => res2) : (a: unknown) => void
|
||||
>fn2() : (cb: () => any) => (a: unknown) => void
|
||||
>fn2 : <T>() => (cb: () => any) => (a: T) => void
|
||||
>() => res2 : () => (a: unknown) => void
|
||||
>res2 : (a: unknown) => void
|
||||
|
||||
declare function fn3<T>(): <T2>(cb: (arg: T2) => any) => (a: T) => void;
|
||||
>fn3 : <T>() => <T2>(cb: (arg: T2) => any) => (a: T) => void
|
||||
>cb : (arg: T2) => any
|
||||
>arg : T2
|
||||
>a : T
|
||||
|
||||
const res3 = fn3()(() => res3);
|
||||
>res3 : (a: unknown) => void
|
||||
>fn3()(() => res3) : (a: unknown) => void
|
||||
>fn3() : <T2>(cb: (arg: T2) => any) => (a: unknown) => void
|
||||
>fn3 : <T>() => <T2>(cb: (arg: T2) => any) => (a: T) => void
|
||||
>() => res3 : () => (a: unknown) => void
|
||||
>res3 : (a: unknown) => void
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
//// [tests/cases/compiler/circularReferenceInReturnType2.ts] ////
|
||||
|
||||
=== circularReferenceInReturnType2.ts ===
|
||||
type ObjectType<Source> = {
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 0, 16))
|
||||
|
||||
kind: "object";
|
||||
>kind : Symbol(kind, Decl(circularReferenceInReturnType2.ts, 0, 27))
|
||||
|
||||
__source: (source: Source) => void;
|
||||
>__source : Symbol(__source, Decl(circularReferenceInReturnType2.ts, 1, 17))
|
||||
>source : Symbol(source, Decl(circularReferenceInReturnType2.ts, 2, 13))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 0, 16))
|
||||
|
||||
};
|
||||
|
||||
type Field<Source, Key extends string> = {
|
||||
>Field : Symbol(Field, Decl(circularReferenceInReturnType2.ts, 3, 2))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 5, 11))
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 5, 18))
|
||||
|
||||
__key: (key: Key) => void;
|
||||
>__key : Symbol(__key, Decl(circularReferenceInReturnType2.ts, 5, 42))
|
||||
>key : Symbol(key, Decl(circularReferenceInReturnType2.ts, 6, 10))
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 5, 18))
|
||||
|
||||
__source: (source: Source) => void;
|
||||
>__source : Symbol(__source, Decl(circularReferenceInReturnType2.ts, 6, 28))
|
||||
>source : Symbol(source, Decl(circularReferenceInReturnType2.ts, 7, 13))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 5, 11))
|
||||
|
||||
};
|
||||
|
||||
declare const object: <Source>() => <
|
||||
>object : Symbol(object, Decl(circularReferenceInReturnType2.ts, 10, 13))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 10, 23))
|
||||
|
||||
Fields extends {
|
||||
>Fields : Symbol(Fields, Decl(circularReferenceInReturnType2.ts, 10, 37))
|
||||
|
||||
[Key in keyof Fields]: Field<Source, Key & string>;
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 12, 5))
|
||||
>Fields : Symbol(Fields, Decl(circularReferenceInReturnType2.ts, 10, 37))
|
||||
>Field : Symbol(Field, Decl(circularReferenceInReturnType2.ts, 3, 2))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 10, 23))
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 12, 5))
|
||||
}
|
||||
>(config: {
|
||||
>config : Symbol(config, Decl(circularReferenceInReturnType2.ts, 14, 2))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(name, Decl(circularReferenceInReturnType2.ts, 14, 11))
|
||||
|
||||
fields: Fields | (() => Fields);
|
||||
>fields : Symbol(fields, Decl(circularReferenceInReturnType2.ts, 15, 15))
|
||||
>Fields : Symbol(Fields, Decl(circularReferenceInReturnType2.ts, 10, 37))
|
||||
>Fields : Symbol(Fields, Decl(circularReferenceInReturnType2.ts, 10, 37))
|
||||
|
||||
}) => ObjectType<Source>;
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 10, 23))
|
||||
|
||||
type InferValueFromObjectType<Type extends ObjectType<any>> =
|
||||
>InferValueFromObjectType : Symbol(InferValueFromObjectType, Decl(circularReferenceInReturnType2.ts, 17, 25))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 19, 30))
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
|
||||
Type extends ObjectType<infer Source> ? Source : never;
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 19, 30))
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 20, 31))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 20, 31))
|
||||
|
||||
type FieldResolver<Source, TType extends ObjectType<any>> = (
|
||||
>FieldResolver : Symbol(FieldResolver, Decl(circularReferenceInReturnType2.ts, 20, 57))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 22, 19))
|
||||
>TType : Symbol(TType, Decl(circularReferenceInReturnType2.ts, 22, 26))
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
|
||||
source: Source
|
||||
>source : Symbol(source, Decl(circularReferenceInReturnType2.ts, 22, 61))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 22, 19))
|
||||
|
||||
) => InferValueFromObjectType<TType>;
|
||||
>InferValueFromObjectType : Symbol(InferValueFromObjectType, Decl(circularReferenceInReturnType2.ts, 17, 25))
|
||||
>TType : Symbol(TType, Decl(circularReferenceInReturnType2.ts, 22, 26))
|
||||
|
||||
type FieldFuncArgs<Source, Type extends ObjectType<any>> = {
|
||||
>FieldFuncArgs : Symbol(FieldFuncArgs, Decl(circularReferenceInReturnType2.ts, 24, 37))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 26, 19))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 26, 26))
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
|
||||
type: Type;
|
||||
>type : Symbol(type, Decl(circularReferenceInReturnType2.ts, 26, 60))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 26, 26))
|
||||
|
||||
resolve: FieldResolver<Source, Type>;
|
||||
>resolve : Symbol(resolve, Decl(circularReferenceInReturnType2.ts, 27, 13))
|
||||
>FieldResolver : Symbol(FieldResolver, Decl(circularReferenceInReturnType2.ts, 20, 57))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 26, 19))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 26, 26))
|
||||
|
||||
};
|
||||
|
||||
declare const field: <Source, Type extends ObjectType<any>, Key extends string>(
|
||||
>field : Symbol(field, Decl(circularReferenceInReturnType2.ts, 31, 13))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 31, 22))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 31, 29))
|
||||
>ObjectType : Symbol(ObjectType, Decl(circularReferenceInReturnType2.ts, 0, 0))
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 31, 59))
|
||||
|
||||
field: FieldFuncArgs<Source, Type>
|
||||
>field : Symbol(field, Decl(circularReferenceInReturnType2.ts, 31, 80))
|
||||
>FieldFuncArgs : Symbol(FieldFuncArgs, Decl(circularReferenceInReturnType2.ts, 24, 37))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 31, 22))
|
||||
>Type : Symbol(Type, Decl(circularReferenceInReturnType2.ts, 31, 29))
|
||||
|
||||
) => Field<Source, Key>;
|
||||
>Field : Symbol(Field, Decl(circularReferenceInReturnType2.ts, 3, 2))
|
||||
>Source : Symbol(Source, Decl(circularReferenceInReturnType2.ts, 31, 22))
|
||||
>Key : Symbol(Key, Decl(circularReferenceInReturnType2.ts, 31, 59))
|
||||
|
||||
type Something = { foo: number };
|
||||
>Something : Symbol(Something, Decl(circularReferenceInReturnType2.ts, 33, 24))
|
||||
>foo : Symbol(foo, Decl(circularReferenceInReturnType2.ts, 35, 18))
|
||||
|
||||
const A = object<Something>()({
|
||||
>A : Symbol(A, Decl(circularReferenceInReturnType2.ts, 37, 5))
|
||||
>object : Symbol(object, Decl(circularReferenceInReturnType2.ts, 10, 13))
|
||||
>Something : Symbol(Something, Decl(circularReferenceInReturnType2.ts, 33, 24))
|
||||
|
||||
name: "A",
|
||||
>name : Symbol(name, Decl(circularReferenceInReturnType2.ts, 37, 31))
|
||||
|
||||
fields: () => ({
|
||||
>fields : Symbol(fields, Decl(circularReferenceInReturnType2.ts, 38, 12))
|
||||
|
||||
a: field({
|
||||
>a : Symbol(a, Decl(circularReferenceInReturnType2.ts, 39, 18))
|
||||
>field : Symbol(field, Decl(circularReferenceInReturnType2.ts, 31, 13))
|
||||
|
||||
type: A,
|
||||
>type : Symbol(type, Decl(circularReferenceInReturnType2.ts, 40, 14))
|
||||
>A : Symbol(A, Decl(circularReferenceInReturnType2.ts, 37, 5))
|
||||
|
||||
resolve() {
|
||||
>resolve : Symbol(resolve, Decl(circularReferenceInReturnType2.ts, 41, 14))
|
||||
|
||||
return {
|
||||
foo: 100,
|
||||
>foo : Symbol(foo, Decl(circularReferenceInReturnType2.ts, 43, 16))
|
||||
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
//// [tests/cases/compiler/circularReferenceInReturnType2.ts] ////
|
||||
|
||||
=== circularReferenceInReturnType2.ts ===
|
||||
type ObjectType<Source> = {
|
||||
>ObjectType : ObjectType<Source>
|
||||
|
||||
kind: "object";
|
||||
>kind : "object"
|
||||
|
||||
__source: (source: Source) => void;
|
||||
>__source : (source: Source) => void
|
||||
>source : Source
|
||||
|
||||
};
|
||||
|
||||
type Field<Source, Key extends string> = {
|
||||
>Field : Field<Source, Key>
|
||||
|
||||
__key: (key: Key) => void;
|
||||
>__key : (key: Key) => void
|
||||
>key : Key
|
||||
|
||||
__source: (source: Source) => void;
|
||||
>__source : (source: Source) => void
|
||||
>source : Source
|
||||
|
||||
};
|
||||
|
||||
declare const object: <Source>() => <
|
||||
>object : <Source>() => <Fields extends { [Key in keyof Fields]: Field<Source, Key & string>; }>(config: { name: string; fields: Fields | (() => Fields);}) => ObjectType<Source>
|
||||
|
||||
Fields extends {
|
||||
[Key in keyof Fields]: Field<Source, Key & string>;
|
||||
}
|
||||
>(config: {
|
||||
>config : { name: string; fields: Fields | (() => Fields); }
|
||||
|
||||
name: string;
|
||||
>name : string
|
||||
|
||||
fields: Fields | (() => Fields);
|
||||
>fields : Fields | (() => Fields)
|
||||
|
||||
}) => ObjectType<Source>;
|
||||
|
||||
type InferValueFromObjectType<Type extends ObjectType<any>> =
|
||||
>InferValueFromObjectType : InferValueFromObjectType<Type>
|
||||
|
||||
Type extends ObjectType<infer Source> ? Source : never;
|
||||
|
||||
type FieldResolver<Source, TType extends ObjectType<any>> = (
|
||||
>FieldResolver : FieldResolver<Source, TType>
|
||||
|
||||
source: Source
|
||||
>source : Source
|
||||
|
||||
) => InferValueFromObjectType<TType>;
|
||||
|
||||
type FieldFuncArgs<Source, Type extends ObjectType<any>> = {
|
||||
>FieldFuncArgs : FieldFuncArgs<Source, Type>
|
||||
|
||||
type: Type;
|
||||
>type : Type
|
||||
|
||||
resolve: FieldResolver<Source, Type>;
|
||||
>resolve : FieldResolver<Source, Type>
|
||||
|
||||
};
|
||||
|
||||
declare const field: <Source, Type extends ObjectType<any>, Key extends string>(
|
||||
>field : <Source, Type extends ObjectType<any>, Key extends string>(field: FieldFuncArgs<Source, Type>) => Field<Source, Key>
|
||||
|
||||
field: FieldFuncArgs<Source, Type>
|
||||
>field : FieldFuncArgs<Source, Type>
|
||||
|
||||
) => Field<Source, Key>;
|
||||
|
||||
type Something = { foo: number };
|
||||
>Something : { foo: number; }
|
||||
>foo : number
|
||||
|
||||
const A = object<Something>()({
|
||||
>A : ObjectType<Something>
|
||||
>object<Something>()({ name: "A", fields: () => ({ a: field({ type: A, resolve() { return { foo: 100, }; }, }), }),}) : ObjectType<Something>
|
||||
>object<Something>() : <Fields extends { [Key in keyof Fields]: Field<Something, Key & string>; }>(config: { name: string; fields: Fields | (() => Fields); }) => ObjectType<Something>
|
||||
>object : <Source>() => <Fields extends { [Key in keyof Fields]: Field<Source, Key & string>; }>(config: { name: string; fields: Fields | (() => Fields); }) => ObjectType<Source>
|
||||
>{ name: "A", fields: () => ({ a: field({ type: A, resolve() { return { foo: 100, }; }, }), }),} : { name: string; fields: () => { a: Field<Something, "a">; }; }
|
||||
|
||||
name: "A",
|
||||
>name : string
|
||||
>"A" : "A"
|
||||
|
||||
fields: () => ({
|
||||
>fields : () => { a: Field<Something, "a">; }
|
||||
>() => ({ a: field({ type: A, resolve() { return { foo: 100, }; }, }), }) : () => { a: Field<Something, "a">; }
|
||||
>({ a: field({ type: A, resolve() { return { foo: 100, }; }, }), }) : { a: Field<Something, "a">; }
|
||||
>{ a: field({ type: A, resolve() { return { foo: 100, }; }, }), } : { a: Field<Something, "a">; }
|
||||
|
||||
a: field({
|
||||
>a : Field<Something, "a">
|
||||
>field({ type: A, resolve() { return { foo: 100, }; }, }) : Field<Something, "a">
|
||||
>field : <Source, Type extends ObjectType<any>, Key extends string>(field: FieldFuncArgs<Source, Type>) => Field<Source, Key>
|
||||
>{ type: A, resolve() { return { foo: 100, }; }, } : { type: ObjectType<Something>; resolve(): { foo: number; }; }
|
||||
|
||||
type: A,
|
||||
>type : ObjectType<Something>
|
||||
>A : ObjectType<Something>
|
||||
|
||||
resolve() {
|
||||
>resolve : () => { foo: number; }
|
||||
|
||||
return {
|
||||
>{ foo: 100, } : { foo: number; }
|
||||
|
||||
foo: 100,
|
||||
>foo : number
|
||||
>100 : 100
|
||||
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
+16
-54
@@ -1,31 +1,12 @@
|
||||
circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts(63,84): error TS2344: Type 'GetProps<C>' does not satisfy the constraint 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
Type 'unknown' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
Type 'Matching<TInjectedProps, GetProps<C>>' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P] : GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[P] | (TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'Extract<keyof TInjectedProps, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] : GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] | (TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[Extract<string, keyof GetProps<C>>] | GetProps<C>[Extract<number, keyof GetProps<C>>] | GetProps<C>[Extract<symbol, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type '(Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]) | (Extract<number, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : GetProps<C>[Extract<number, keyof GetProps<C>>]) | (Extract<symbol, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : GetProps<C>[Extract<symbol, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type '(TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]) | GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] | TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'keyof GetProps<C> & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] : GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]) | GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'Matching<TInjectedProps, GetProps<C>>' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P] : GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'Extract<keyof TInjectedProps, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] : GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type '(Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]) | (Extract<number, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : GetProps<C>[Extract<number, keyof GetProps<C>>]) | (Extract<symbol, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : GetProps<C>[Extract<symbol, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'keyof GetProps<C> & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] : GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
Type '(TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string]) | GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
|
||||
|
||||
==== circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts (1 errors) ====
|
||||
@@ -94,31 +75,12 @@ circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth
|
||||
) => ConnectedComponentClass<C, Omit<GetProps<C>, keyof Shared<TInjectedProps, GetProps<C>>> & TNeedsProps>;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2344: Type 'GetProps<C>' does not satisfy the constraint 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
!!! error TS2344: Type 'unknown' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
!!! error TS2344: Type 'Matching<TInjectedProps, GetProps<C>>' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
!!! error TS2344: Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P] : GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[P] | (TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'Extract<keyof TInjectedProps, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] : GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] | (TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[Extract<string, keyof GetProps<C>>] | GetProps<C>[Extract<number, keyof GetProps<C>>] | GetProps<C>[Extract<symbol, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type '(Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]) | (Extract<number, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : GetProps<C>[Extract<number, keyof GetProps<C>>]) | (Extract<symbol, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : GetProps<C>[Extract<symbol, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]) | GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] | TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'keyof GetProps<C> & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] : GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]) | GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'Matching<TInjectedProps, GetProps<C>>' is not assignable to type 'Shared<TInjectedProps, GetProps<C>>'.
|
||||
!!! error TS2344: Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : TInjectedProps[P] : GetProps<C>[P]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'Extract<keyof TInjectedProps, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] extends GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] ? GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>] : TInjectedProps[Extract<keyof TInjectedProps, keyof GetProps<C>>] : GetProps<C>[Extract<keyof TInjectedProps, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type '(Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]) | (Extract<number, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<number, keyof GetProps<C>>] : GetProps<C>[Extract<number, keyof GetProps<C>>]) | (Extract<symbol, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<symbol, keyof GetProps<C>>] : GetProps<C>[Extract<symbol, keyof GetProps<C>>])' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'Extract<string, keyof GetProps<C>> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] extends GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] ? GetProps<C>[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : TInjectedProps[keyof TInjectedProps & Extract<string, keyof GetProps<C>>] : GetProps<C>[Extract<string, keyof GetProps<C>>]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'keyof GetProps<C> & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] extends GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] ? GetProps<C>[keyof TInjectedProps & keyof GetProps<C> & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps<C> & string] : GetProps<C>[keyof GetProps<C> & string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & string] extends GetProps<C>[keyof TInjectedProps & string] ? GetProps<C>[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string]) | GetProps<C>[string]' is not assignable to type '(TInjectedProps[P] extends GetProps<C>[P] ? GetProps<C>[P] : never) | undefined'.
|
||||
|
||||
@@ -39,7 +39,7 @@ second.ts(17,15): error TS2345: Argument of type 'string' is not assignable to p
|
||||
class Sql extends Wagon {
|
||||
constructor() {
|
||||
super(); // error: not enough arguments
|
||||
~~~~~~~
|
||||
~~~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 first.js:5:16: An argument for 'numberOxen' was not provided.
|
||||
this.foonly = 12
|
||||
|
||||
@@ -1,25 +1,49 @@
|
||||
computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(3,10): error TS2449: Class 'C1' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(6,10): error TS2449: Class 'C1' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(9,6): error TS2449: Class 'C1' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(14,10): error TS2449: Class 'C2' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(17,10): error TS2449: Class 'C2' used before its declaration.
|
||||
computedPropertyNamesWithStaticProperty.ts(20,6): error TS2449: Class 'C2' used before its declaration.
|
||||
|
||||
|
||||
==== computedPropertyNamesWithStaticProperty.ts (3 errors) ====
|
||||
class C {
|
||||
==== computedPropertyNamesWithStaticProperty.ts (6 errors) ====
|
||||
class C1 {
|
||||
static staticProp = 10;
|
||||
get [C.staticProp]() {
|
||||
~
|
||||
!!! error TS2449: Class 'C' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here.
|
||||
get [C1.staticProp]() {
|
||||
~~
|
||||
!!! error TS2449: Class 'C1' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here.
|
||||
return "hello";
|
||||
}
|
||||
set [C.staticProp](x: string) {
|
||||
~
|
||||
!!! error TS2449: Class 'C' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here.
|
||||
set [C1.staticProp](x: string) {
|
||||
~~
|
||||
!!! error TS2449: Class 'C1' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here.
|
||||
var y = x;
|
||||
}
|
||||
[C.staticProp]() { }
|
||||
~
|
||||
!!! error TS2449: Class 'C' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C' is declared here.
|
||||
}
|
||||
[C1.staticProp]() { }
|
||||
~~
|
||||
!!! error TS2449: Class 'C1' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:1:7: 'C1' is declared here.
|
||||
}
|
||||
|
||||
(class C2 {
|
||||
static staticProp = 10;
|
||||
get [C2.staticProp]() {
|
||||
~~
|
||||
!!! error TS2449: Class 'C2' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here.
|
||||
return "hello";
|
||||
}
|
||||
set [C2.staticProp](x: string) {
|
||||
~~
|
||||
!!! error TS2449: Class 'C2' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here.
|
||||
var y = x;
|
||||
}
|
||||
[C2.staticProp]() { }
|
||||
~~
|
||||
!!! error TS2449: Class 'C2' used before its declaration.
|
||||
!!! related TS2728 computedPropertyNamesWithStaticProperty.ts:12:8: 'C2' is declared here.
|
||||
})
|
||||
|
||||
@@ -1,25 +1,49 @@
|
||||
//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] ////
|
||||
|
||||
//// [computedPropertyNamesWithStaticProperty.ts]
|
||||
class C {
|
||||
class C1 {
|
||||
static staticProp = 10;
|
||||
get [C.staticProp]() {
|
||||
get [C1.staticProp]() {
|
||||
return "hello";
|
||||
}
|
||||
set [C.staticProp](x: string) {
|
||||
set [C1.staticProp](x: string) {
|
||||
var y = x;
|
||||
}
|
||||
[C.staticProp]() { }
|
||||
}
|
||||
[C1.staticProp]() { }
|
||||
}
|
||||
|
||||
(class C2 {
|
||||
static staticProp = 10;
|
||||
get [C2.staticProp]() {
|
||||
return "hello";
|
||||
}
|
||||
set [C2.staticProp](x: string) {
|
||||
var y = x;
|
||||
}
|
||||
[C2.staticProp]() { }
|
||||
})
|
||||
|
||||
|
||||
//// [computedPropertyNamesWithStaticProperty.js]
|
||||
class C {
|
||||
get [C.staticProp]() {
|
||||
var _a;
|
||||
class C1 {
|
||||
get [C1.staticProp]() {
|
||||
return "hello";
|
||||
}
|
||||
set [C.staticProp](x) {
|
||||
set [C1.staticProp](x) {
|
||||
var y = x;
|
||||
}
|
||||
[C.staticProp]() { }
|
||||
[C1.staticProp]() { }
|
||||
}
|
||||
C.staticProp = 10;
|
||||
C1.staticProp = 10;
|
||||
(_a = class C2 {
|
||||
get [C2.staticProp]() {
|
||||
return "hello";
|
||||
}
|
||||
set [C2.staticProp](x) {
|
||||
var y = x;
|
||||
}
|
||||
[C2.staticProp]() { }
|
||||
},
|
||||
_a.staticProp = 10,
|
||||
_a);
|
||||
|
||||
@@ -1,34 +1,68 @@
|
||||
//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] ////
|
||||
|
||||
=== computedPropertyNamesWithStaticProperty.ts ===
|
||||
class C {
|
||||
>C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
class C1 {
|
||||
>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
|
||||
static staticProp = 10;
|
||||
>staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
|
||||
get [C.staticProp]() {
|
||||
>[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 1, 27))
|
||||
>C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
>C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
get [C1.staticProp]() {
|
||||
>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 1, 27))
|
||||
>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
|
||||
return "hello";
|
||||
}
|
||||
set [C.staticProp](x: string) {
|
||||
>[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 4, 5))
|
||||
>C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
>C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 23))
|
||||
set [C1.staticProp](x: string) {
|
||||
>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 4, 5))
|
||||
>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 24))
|
||||
|
||||
var y = x;
|
||||
>y : Symbol(y, Decl(computedPropertyNamesWithStaticProperty.ts, 6, 11))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 23))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 5, 24))
|
||||
}
|
||||
[C.staticProp]() { }
|
||||
>[C.staticProp] : Symbol(C[C.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 7, 5))
|
||||
>C.staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
>C : Symbol(C, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 9))
|
||||
[C1.staticProp]() { }
|
||||
>[C1.staticProp] : Symbol(C1[C1.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 7, 5))
|
||||
>C1.staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
>C1 : Symbol(C1, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 0))
|
||||
>staticProp : Symbol(C1.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 0, 10))
|
||||
}
|
||||
|
||||
(class C2 {
|
||||
>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1))
|
||||
|
||||
static staticProp = 10;
|
||||
>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
|
||||
get [C2.staticProp]() {
|
||||
>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 12, 27))
|
||||
>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1))
|
||||
>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
|
||||
return "hello";
|
||||
}
|
||||
set [C2.staticProp](x: string) {
|
||||
>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 15, 5))
|
||||
>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1))
|
||||
>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 16, 24))
|
||||
|
||||
var y = x;
|
||||
>y : Symbol(y, Decl(computedPropertyNamesWithStaticProperty.ts, 17, 11))
|
||||
>x : Symbol(x, Decl(computedPropertyNamesWithStaticProperty.ts, 16, 24))
|
||||
}
|
||||
[C2.staticProp]() { }
|
||||
>[C2.staticProp] : Symbol(C2[C2.staticProp], Decl(computedPropertyNamesWithStaticProperty.ts, 18, 5))
|
||||
>C2.staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
>C2 : Symbol(C2, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 1))
|
||||
>staticProp : Symbol(C2.staticProp, Decl(computedPropertyNamesWithStaticProperty.ts, 11, 11))
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
//// [tests/cases/conformance/es6/computedProperties/computedPropertyNamesWithStaticProperty.ts] ////
|
||||
|
||||
=== computedPropertyNamesWithStaticProperty.ts ===
|
||||
class C {
|
||||
>C : C
|
||||
class C1 {
|
||||
>C1 : C1
|
||||
|
||||
static staticProp = 10;
|
||||
>staticProp : number
|
||||
>10 : 10
|
||||
|
||||
get [C.staticProp]() {
|
||||
>[C.staticProp] : string
|
||||
>C.staticProp : number
|
||||
>C : typeof C
|
||||
get [C1.staticProp]() {
|
||||
>[C1.staticProp] : string
|
||||
>C1.staticProp : number
|
||||
>C1 : typeof C1
|
||||
>staticProp : number
|
||||
|
||||
return "hello";
|
||||
>"hello" : "hello"
|
||||
}
|
||||
set [C.staticProp](x: string) {
|
||||
>[C.staticProp] : string
|
||||
>C.staticProp : number
|
||||
>C : typeof C
|
||||
set [C1.staticProp](x: string) {
|
||||
>[C1.staticProp] : string
|
||||
>C1.staticProp : number
|
||||
>C1 : typeof C1
|
||||
>staticProp : number
|
||||
>x : string
|
||||
|
||||
@@ -28,9 +28,47 @@ class C {
|
||||
>y : string
|
||||
>x : string
|
||||
}
|
||||
[C.staticProp]() { }
|
||||
>[C.staticProp] : () => void
|
||||
>C.staticProp : number
|
||||
>C : typeof C
|
||||
[C1.staticProp]() { }
|
||||
>[C1.staticProp] : () => void
|
||||
>C1.staticProp : number
|
||||
>C1 : typeof C1
|
||||
>staticProp : number
|
||||
}
|
||||
|
||||
(class C2 {
|
||||
>(class C2 { static staticProp = 10; get [C2.staticProp]() { return "hello"; } set [C2.staticProp](x: string) { var y = x; } [C2.staticProp]() { }}) : typeof C2
|
||||
>class C2 { static staticProp = 10; get [C2.staticProp]() { return "hello"; } set [C2.staticProp](x: string) { var y = x; } [C2.staticProp]() { }} : typeof C2
|
||||
>C2 : typeof C2
|
||||
|
||||
static staticProp = 10;
|
||||
>staticProp : number
|
||||
>10 : 10
|
||||
|
||||
get [C2.staticProp]() {
|
||||
>[C2.staticProp] : string
|
||||
>C2.staticProp : number
|
||||
>C2 : typeof C2
|
||||
>staticProp : number
|
||||
|
||||
return "hello";
|
||||
>"hello" : "hello"
|
||||
}
|
||||
set [C2.staticProp](x: string) {
|
||||
>[C2.staticProp] : string
|
||||
>C2.staticProp : number
|
||||
>C2 : typeof C2
|
||||
>staticProp : number
|
||||
>x : string
|
||||
|
||||
var y = x;
|
||||
>y : string
|
||||
>x : string
|
||||
}
|
||||
[C2.staticProp]() { }
|
||||
>[C2.staticProp] : () => void
|
||||
>C2.staticProp : number
|
||||
>C2 : typeof C2
|
||||
>staticProp : number
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -57,8 +57,10 @@ conditionalTypes1.ts(136,22): error TS2540: Cannot assign to 'id' because it is
|
||||
conditionalTypes1.ts(137,10): error TS2339: Property 'updatePart' does not exist on type 'DeepReadonlyObject<Part>'.
|
||||
conditionalTypes1.ts(159,5): error TS2322: Type 'ZeroOf<T>' is not assignable to type 'T'.
|
||||
'ZeroOf<T>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
Type '0 | (T extends string ? "" : false)' is not assignable to type 'T'.
|
||||
'T' could be instantiated with an arbitrary type which could be unrelated to '0 | (T extends string ? "" : false)'.
|
||||
Type 'string | number' is not assignable to type 'T'.
|
||||
'string | number' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
Type 'string' is not assignable to type 'T'.
|
||||
'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
conditionalTypes1.ts(160,5): error TS2322: Type 'T' is not assignable to type 'ZeroOf<T>'.
|
||||
Type 'string | number' is not assignable to type 'ZeroOf<T>'.
|
||||
Type 'string' is not assignable to type 'ZeroOf<T>'.
|
||||
@@ -86,6 +88,7 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'NonNullable<T>'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type '{}'.
|
||||
!!! related TS2208 conditionalTypes1.ts:10:13: This type parameter might need an `extends {}` constraint.
|
||||
!!! related TS2208 conditionalTypes1.ts:10:13: This type parameter might need an `extends NonNullable<T>` constraint.
|
||||
}
|
||||
|
||||
function f2<T extends string | undefined>(x: T, y: NonNullable<T>) {
|
||||
@@ -306,8 +309,10 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
|
||||
~
|
||||
!!! error TS2322: Type 'ZeroOf<T>' is not assignable to type 'T'.
|
||||
!!! error TS2322: 'ZeroOf<T>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
!!! error TS2322: Type '0 | (T extends string ? "" : false)' is not assignable to type 'T'.
|
||||
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to '0 | (T extends string ? "" : false)'.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'T'.
|
||||
!!! error TS2322: 'string | number' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'T'.
|
||||
!!! error TS2322: 'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'string | number'.
|
||||
y = x; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'ZeroOf<T>'.
|
||||
|
||||
@@ -25,9 +25,8 @@ conditionalTypes2.ts(25,5): error TS2322: Type 'Invariant<A>' is not assignable
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
'B' could be instantiated with an arbitrary type which could be unrelated to 'A'.
|
||||
conditionalTypes2.ts(73,12): error TS2345: Argument of type 'Extract<Extract<T, Foo>, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
Type 'Extract<T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
Type 'Extract<T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
conditionalTypes2.ts(74,12): error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
|
||||
conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
@@ -145,10 +144,8 @@ conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2<T, Foo, Ba
|
||||
fooBat(x); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'Extract<Extract<T, Foo>, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Type 'Extract<T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! related TS2728 conditionalTypes2.ts:62:43: 'bat' is declared here.
|
||||
!!! error TS2345: Type 'Extract<T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! related TS2728 conditionalTypes2.ts:62:43: 'bat' is declared here.
|
||||
fooBat(y); // Error
|
||||
~
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
contextuallyTypedParametersWithInitializers.ts(24,24): error TS7006: Parameter 'x' implicitly has an 'any' type.
|
||||
contextuallyTypedParametersWithInitializers.ts(40,5): error TS7006: Parameter 'x' implicitly has an 'any' type.
|
||||
contextuallyTypedParametersWithInitializers1.ts(24,24): error TS7006: Parameter 'x' implicitly has an 'any' type.
|
||||
contextuallyTypedParametersWithInitializers1.ts(40,5): error TS7006: Parameter 'x' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== contextuallyTypedParametersWithInitializers.ts (2 errors) ====
|
||||
==== contextuallyTypedParametersWithInitializers1.ts (2 errors) ====
|
||||
declare function id1<T>(input: T): T;
|
||||
declare function id2<T extends (x: any) => any>(input: T): T;
|
||||
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
//// [tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts] ////
|
||||
//// [tests/cases/compiler/contextuallyTypedParametersWithInitializers1.ts] ////
|
||||
|
||||
//// [contextuallyTypedParametersWithInitializers.ts]
|
||||
//// [contextuallyTypedParametersWithInitializers1.ts]
|
||||
declare function id1<T>(input: T): T;
|
||||
declare function id2<T extends (x: any) => any>(input: T): T;
|
||||
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
|
||||
@@ -86,7 +86,7 @@ const fz1 = (debug = true) => false;
|
||||
const fz2: Function = (debug = true) => false;
|
||||
|
||||
|
||||
//// [contextuallyTypedParametersWithInitializers.js]
|
||||
//// [contextuallyTypedParametersWithInitializers1.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.executeSomething = void 0;
|
||||
@@ -234,5 +234,5 @@ var fz2 = function (debug) {
|
||||
};
|
||||
|
||||
|
||||
//// [contextuallyTypedParametersWithInitializers.d.ts]
|
||||
//// [contextuallyTypedParametersWithInitializers1.d.ts]
|
||||
export declare function executeSomething(): Promise<string>;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user