mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'main' into fix11498
# Conflicts: # tests/baselines/reference/asyncYieldStarContextualType.types # tests/baselines/reference/awaitedType.types # tests/baselines/reference/contextuallyTypeAsyncFunctionReturnTypeFromUnion.types # tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.types # tests/baselines/reference/declarationEmitUsingAlternativeContainingModules1.types # tests/baselines/reference/declarationEmitUsingAlternativeContainingModules2.types # tests/baselines/reference/destructureOfVariableSameAsShorthand.types # tests/baselines/reference/es2018ObjectAssign.types # tests/baselines/reference/esModuleInteropImportCall.types # tests/baselines/reference/genericFunctionInference1.types # tests/baselines/reference/importCallExpression1ES2020.types # tests/baselines/reference/importCallExpression2ES2020.types # tests/baselines/reference/importCallExpression4ES2020.types # tests/baselines/reference/importCallExpressionES5AMD.types # tests/baselines/reference/importCallExpressionES5CJS.types # tests/baselines/reference/importCallExpressionES5System.types # tests/baselines/reference/importCallExpressionES5UMD.types # tests/baselines/reference/importCallExpressionES6AMD.types # tests/baselines/reference/importCallExpressionES6CJS.types # tests/baselines/reference/importCallExpressionES6System.types # tests/baselines/reference/importCallExpressionES6UMD.types # tests/baselines/reference/importCallExpressionErrorInES2015.types # tests/baselines/reference/importCallExpressionInAMD1.types # tests/baselines/reference/importCallExpressionInAMD2.types # tests/baselines/reference/importCallExpressionInAMD4.types # tests/baselines/reference/importCallExpressionInCJS1.types # tests/baselines/reference/importCallExpressionInCJS3.types # tests/baselines/reference/importCallExpressionInCJS5.types # tests/baselines/reference/importCallExpressionInSystem1.types # tests/baselines/reference/importCallExpressionInSystem2.types # tests/baselines/reference/importCallExpressionInSystem4.types # tests/baselines/reference/importCallExpressionInUMD1.types # tests/baselines/reference/importCallExpressionInUMD2.types # tests/baselines/reference/importCallExpressionInUMD4.types # tests/baselines/reference/importCallExpressionNoModuleKindSpecified.types # tests/baselines/reference/importCallExpressionReturnPromiseOfAny.types # tests/baselines/reference/importCallExpressionShouldNotGetParen.types # tests/baselines/reference/importCallExpressionSpecifierNotStringTypeError.types # tests/baselines/reference/inferenceLimit.types # tests/baselines/reference/instantiateContextualTypes.types # tests/baselines/reference/mappedTypesGenericTuples2.types # tests/baselines/reference/modularizeLibrary_Dom.asynciterable.types # tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions1.types # tests/baselines/reference/modularizeLibrary_NoErrorDuplicateLibOptions2.types # tests/baselines/reference/modularizeLibrary_TargetES5UsingES6Lib.types # tests/baselines/reference/modularizeLibrary_Worker.asynciterable.types # tests/baselines/reference/moduleResolutionWithoutExtension5.types # tests/baselines/reference/moduleResolutionWithoutExtension8.types # tests/baselines/reference/privateNameMethodAsync.types # tests/baselines/reference/promisePermutations.types # tests/baselines/reference/promisePermutations2.types # tests/baselines/reference/promisePermutations3.types # tests/baselines/reference/promiseTest.types # tests/baselines/reference/promiseType.types # tests/baselines/reference/promiseTypeStrictNull.types # tests/baselines/reference/promiseVoidErrorCallback.types # tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types # tests/baselines/reference/truthinessPromiseCoercion.types # tests/baselines/reference/unionAndIntersectionInference1.types # tests/baselines/reference/unionOfClassCalls.types # tests/baselines/reference/usePromiseFinally.types
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const rulesDir = path.join(__dirname, "scripts", "eslint", "rules");
|
||||
const ext = ".cjs";
|
||||
const ruleFiles = fs.readdirSync(rulesDir).filter(p => p.endsWith(ext));
|
||||
|
||||
module.exports = {
|
||||
rules: Object.fromEntries(ruleFiles.map(p => {
|
||||
return [p.slice(0, -ext.length), require(path.join(rulesDir, p))];
|
||||
})),
|
||||
};
|
||||
-177
@@ -1,177 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"warnOnUnsupportedTypeScriptVersion": false,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"browser": false,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/stylistic"
|
||||
],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"eslint-plugin-local"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"**/node_modules/**",
|
||||
"/built/**",
|
||||
"/tests/**",
|
||||
"/lib/**",
|
||||
"/src/lib/*.generated.d.ts",
|
||||
"/scripts/**/*.js",
|
||||
"/scripts/**/*.d.*",
|
||||
"/internal/**",
|
||||
"/coverage/**"
|
||||
],
|
||||
"rules": {
|
||||
// eslint
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": "error",
|
||||
"no-caller": "error",
|
||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||
"no-eval": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-return-await": "error",
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{ "name": "setTimeout" },
|
||||
{ "name": "clearTimeout" },
|
||||
{ "name": "setInterval" },
|
||||
{ "name": "clearInterval" },
|
||||
{ "name": "setImmediate" },
|
||||
{ "name": "clearImmediate" }
|
||||
],
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-var": "error",
|
||||
"object-shorthand": "error",
|
||||
"prefer-const": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"unicode-bom": ["error", "never"],
|
||||
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Literal[raw=null]",
|
||||
"message": "Avoid using null; use undefined instead."
|
||||
},
|
||||
{
|
||||
"selector": "TSNullKeyword",
|
||||
"message": "Avoid using null; use undefined instead."
|
||||
}
|
||||
],
|
||||
|
||||
// Enabled in eslint:recommended, but not applicable here
|
||||
"no-extra-boolean-cast": "off",
|
||||
"no-case-declarations": "off",
|
||||
"no-cond-assign": "off",
|
||||
"no-control-regex": "off",
|
||||
"no-inner-declarations": "off",
|
||||
|
||||
// @typescript-eslint/eslint-plugin
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{ "selector": "typeLike", "format": ["PascalCase"], "filter": { "regex": "^(__String|[A-Za-z]+_[A-Za-z]+)$", "match": false } },
|
||||
{ "selector": "interface", "format": ["PascalCase"], "custom": { "regex": "^I[A-Z]", "match": false }, "filter": { "regex": "^I(Arguments|TextWriter|O([A-Z][a-z]+[A-Za-z]*)?)$", "match": false } },
|
||||
{ "selector": "variable", "format": ["camelCase", "PascalCase", "UPPER_CASE"], "leadingUnderscore": "allow", "filter": { "regex": "^(_{1,2}filename|_{1,2}dirname|_+|[A-Za-z]+_[A-Za-z]+)$", "match": false } },
|
||||
{ "selector": "function", "format": ["camelCase", "PascalCase"], "leadingUnderscore": "allow", "filter": { "regex": "^[A-Za-z]+_[A-Za-z]+$", "match": false } },
|
||||
{ "selector": "parameter", "format": ["camelCase"], "leadingUnderscore": "allow", "filter": { "regex": "^(_+|[A-Za-z]+_[A-Z][a-z]+)$", "match": false } },
|
||||
{ "selector": "method", "format": ["camelCase", "PascalCase"], "leadingUnderscore": "allow", "filter": { "regex": "^([0-9]+|[A-Za-z]+_[A-Za-z]+)$", "match": false } },
|
||||
{ "selector": "memberLike", "format": ["camelCase"], "leadingUnderscore": "allow", "filter": { "regex": "^([0-9]+|[A-Za-z]+_[A-Za-z]+)$", "match": false } },
|
||||
{ "selector": "enumMember", "format": ["camelCase", "PascalCase"], "leadingUnderscore": "allow", "filter": { "regex": "^[A-Za-z]+_[A-Za-z]+$", "match": false } },
|
||||
{ "selector": "property", "format": null }
|
||||
],
|
||||
|
||||
"@typescript-eslint/unified-signatures": "error",
|
||||
"no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }],
|
||||
|
||||
// Rules enabled in typescript-eslint configs that are not applicable here
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/class-literal-property-style": "off",
|
||||
"@typescript-eslint/consistent-indexed-object-style": "off",
|
||||
"@typescript-eslint/no-duplicate-enum-values": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"extendDefaults": true,
|
||||
"types": {
|
||||
// This is theoretically good, but ts-eslint appears to mistake our declaration of Symbol for the global Symbol type.
|
||||
// See: https://github.com/typescript-eslint/typescript-eslint/issues/7306
|
||||
"Symbol": false,
|
||||
"{}": false // {} is a totally useful and valid type.
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
// Ignore: (solely underscores | starting with exactly one underscore)
|
||||
"argsIgnorePattern": "^(_+$|_[^_])",
|
||||
"varsIgnorePattern": "^(_+$|_[^_])"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
|
||||
// Pending https://github.com/typescript-eslint/typescript-eslint/issues/4820
|
||||
"@typescript-eslint/prefer-optional-chain": "off",
|
||||
|
||||
// scripts/eslint/rules
|
||||
"local/only-arrow-functions": [
|
||||
"error",
|
||||
{
|
||||
"allowNamedFunctions": true,
|
||||
"allowDeclarations": true
|
||||
}
|
||||
],
|
||||
"local/argument-trivia": "error",
|
||||
"local/no-in-operator": "error",
|
||||
"local/debug-assert": "error",
|
||||
"local/no-keywords": "error",
|
||||
"local/jsdoc-format": "error",
|
||||
"local/js-extensions": "error"
|
||||
},
|
||||
"overrides": [
|
||||
// By default, the ESLint CLI only looks at .js files. But, it will also look at
|
||||
// any files which are referenced in an override config. Most users of typescript-eslint
|
||||
// get this behavior by default by extending a recommended typescript-eslint config, which
|
||||
// just so happens to override some core ESLint rules. We don't extend from any config, so
|
||||
// explicitly reference TS files here so the CLI picks them up.
|
||||
//
|
||||
// ESLint in VS Code will lint any opened file (so long as it's not eslintignore'd), so
|
||||
// that will work regardless of the below.
|
||||
//
|
||||
// The same applies to mjs files; ESLint appears to not scan those either.
|
||||
{ "files": ["*.ts", "*.mts", "*.cts", "*.mjs", "*.cjs"] },
|
||||
{
|
||||
"files": ["*.mjs", "*.mts"],
|
||||
"rules": {
|
||||
// These globals don't exist outside of CJS files.
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{ "name": "__filename" },
|
||||
{ "name": "__dirname" },
|
||||
{ "name": "require" },
|
||||
{ "name": "module" },
|
||||
{ "name": "exports" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
+25
-11
@@ -49,7 +49,7 @@ jobs:
|
||||
name: Test Node ${{ matrix.node-version }} on ${{ matrix.os }}${{ (!matrix.bundle && ' with --no-bundle') || '' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Use node version ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -83,11 +83,25 @@ jobs:
|
||||
- name: Linter
|
||||
run: npm run lint
|
||||
|
||||
knip:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
check-latest: true
|
||||
- run: npm ci
|
||||
|
||||
- name: Unused exports
|
||||
run: npm run knip
|
||||
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -108,7 +122,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -125,7 +139,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -139,7 +153,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
@@ -181,11 +195,11 @@ jobs:
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
path: pr
|
||||
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
path: base
|
||||
ref: ${{ github.base_ref }}
|
||||
@@ -223,7 +237,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -240,7 +254,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
@@ -260,7 +274,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: '*'
|
||||
|
||||
@@ -42,11 +42,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
||||
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@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/autobuild@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
||||
|
||||
# ℹ️ 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@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
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.
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ inputs.branch_name }}
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
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.
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -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@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ inputs.branch_name }}
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ inputs.branch_name }}
|
||||
filter: blob:none # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Get repo name
|
||||
run: R=${GITHUB_REPOSITORY%?wiki}; echo "BASENAME=${R##*/}" >> $GITHUB_ENV
|
||||
- name: Checkout ${{ env.BASENAME }}-wiki
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: '${{ GITHUB.repository_owner }}/${{ env.BASENAME }}-wiki'
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
|
||||
@@ -49,12 +49,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- if: ${{ github.event.inputs.bisect }}
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
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.
|
||||
- if: ${{ !github.event.inputs.bisect }}
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
if: github.repository == 'microsoft/TypeScript'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
token: ${{ secrets.TS_BOT_GITHUB_TOKEN }}
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
||||
@@ -565,6 +565,13 @@ export const checkFormat = task({
|
||||
run: () => exec(process.execPath, ["node_modules/dprint/bin.js", "check"], { ignoreStdout: true }),
|
||||
});
|
||||
|
||||
export const knip = task({
|
||||
name: "knip",
|
||||
description: "Runs knip.",
|
||||
dependencies: [generateDiagnostics],
|
||||
run: () => exec(process.execPath, ["node_modules/knip/bin/knip.js", "--tags=+internal,-knipignore", "--exclude=duplicates,enumMembers", ...(cmdLineOptions.fix ? ["--fix"] : [])]),
|
||||
});
|
||||
|
||||
const { main: cancellationToken, watch: watchCancellationToken } = entrypointBuildTask({
|
||||
name: "cancellation-token",
|
||||
project: "src/cancellationToken",
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
// @ts-check
|
||||
import eslint from "@eslint/js";
|
||||
import fs from "fs";
|
||||
import globals from "globals";
|
||||
import { createRequire } from "module";
|
||||
import path from "path";
|
||||
import tseslint from "typescript-eslint";
|
||||
import url from "url";
|
||||
|
||||
const __filename = url.fileURLToPath(new URL(import.meta.url));
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const rulesDir = path.join(__dirname, "scripts", "eslint", "rules");
|
||||
const ext = ".cjs";
|
||||
const ruleFiles = fs.readdirSync(rulesDir).filter(p => p.endsWith(ext));
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
files: ["**/*.{ts,tsx,cts,mts,js,cjs,mjs}"],
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
"**/node_modules/**",
|
||||
"built/**",
|
||||
"tests/**",
|
||||
"lib/**",
|
||||
"src/lib/*.generated.d.ts",
|
||||
"scripts/**/*.js",
|
||||
"scripts/**/*.d.*",
|
||||
"internal/**",
|
||||
"coverage/**",
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
...tseslint.configs.stylistic,
|
||||
{
|
||||
plugins: {
|
||||
local: {
|
||||
rules: Object.fromEntries(ruleFiles.map(p => {
|
||||
return [p.slice(0, -ext.length), require(path.join(rulesDir, p))];
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
globals: globals.node,
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
// eslint
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": "error",
|
||||
"no-caller": "error",
|
||||
"no-constant-condition": ["error", { checkLoops: false }],
|
||||
"no-eval": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-return-await": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-var": "error",
|
||||
"object-shorthand": "error",
|
||||
"prefer-const": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"unicode-bom": ["error", "never"],
|
||||
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector: "Literal[raw=null]",
|
||||
message: "Avoid using null; use undefined instead.",
|
||||
},
|
||||
{
|
||||
selector: "TSNullKeyword",
|
||||
message: "Avoid using null; use undefined instead.",
|
||||
},
|
||||
],
|
||||
|
||||
// Enabled in eslint:recommended, but not applicable here
|
||||
"no-extra-boolean-cast": "off",
|
||||
"no-case-declarations": "off",
|
||||
"no-cond-assign": "off",
|
||||
"no-control-regex": "off",
|
||||
"no-inner-declarations": "off",
|
||||
|
||||
// @typescript-eslint/eslint-plugin
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{ selector: "typeLike", format: ["PascalCase"], filter: { regex: "^(__String|[A-Za-z]+_[A-Za-z]+)$", match: false } },
|
||||
{ selector: "interface", format: ["PascalCase"], custom: { regex: "^I[A-Z]", match: false }, filter: { regex: "^I(Arguments|TextWriter|O([A-Z][a-z]+[A-Za-z]*)?)$", match: false } },
|
||||
{ selector: "variable", format: ["camelCase", "PascalCase", "UPPER_CASE"], leadingUnderscore: "allow", filter: { regex: "^(_{1,2}filename|_{1,2}dirname|_+|[A-Za-z]+_[A-Za-z]+)$", match: false } },
|
||||
{ selector: "function", format: ["camelCase", "PascalCase"], leadingUnderscore: "allow", filter: { regex: "^[A-Za-z]+_[A-Za-z]+$", match: false } },
|
||||
{ selector: "parameter", format: ["camelCase"], leadingUnderscore: "allow", filter: { regex: "^(_+|[A-Za-z]+_[A-Z][a-z]+)$", match: false } },
|
||||
{ selector: "method", format: ["camelCase", "PascalCase"], leadingUnderscore: "allow", filter: { regex: "^([0-9]+|[A-Za-z]+_[A-Za-z]+)$", match: false } },
|
||||
{ selector: "memberLike", format: ["camelCase"], leadingUnderscore: "allow", filter: { regex: "^([0-9]+|[A-Za-z]+_[A-Za-z]+)$", match: false } },
|
||||
{ selector: "enumMember", format: ["camelCase", "PascalCase"], leadingUnderscore: "allow", filter: { regex: "^[A-Za-z]+_[A-Za-z]+$", match: false } },
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
{ selector: "property", format: null },
|
||||
],
|
||||
|
||||
"@typescript-eslint/unified-signatures": "error",
|
||||
"no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-expressions": ["error", { allowTernary: true }],
|
||||
|
||||
// Rules enabled in typescript-eslint configs that are not applicable here
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/class-literal-property-style": "off",
|
||||
"@typescript-eslint/consistent-indexed-object-style": "off",
|
||||
"@typescript-eslint/no-duplicate-enum-values": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
extendDefaults: true,
|
||||
types: {
|
||||
// This is theoretically good, but ts-eslint appears to mistake our declaration of Symbol for the global Symbol type.
|
||||
// See: https://github.com/typescript-eslint/typescript-eslint/issues/7306
|
||||
"Symbol": false,
|
||||
"{}": false, // {} is a totally useful and valid type.
|
||||
},
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
// Ignore: (solely underscores | starting with exactly one underscore)
|
||||
argsIgnorePattern: "^(_+$|_[^_])",
|
||||
varsIgnorePattern: "^(_+$|_[^_])",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
|
||||
// Pending https://github.com/typescript-eslint/typescript-eslint/issues/4820
|
||||
"@typescript-eslint/prefer-optional-chain": "off",
|
||||
|
||||
// scripts/eslint/rules
|
||||
"local/only-arrow-functions": [
|
||||
"error",
|
||||
{
|
||||
allowNamedFunctions: true,
|
||||
allowDeclarations: true,
|
||||
},
|
||||
],
|
||||
"local/argument-trivia": "error",
|
||||
"local/no-in-operator": "error",
|
||||
"local/debug-assert": "error",
|
||||
"local/no-keywords": "error",
|
||||
"local/jsdoc-format": "error",
|
||||
"local/js-extensions": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*.mjs", "**/*.mts"],
|
||||
rules: {
|
||||
// These globals don't exist outside of CJS files.
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{ name: "__filename" },
|
||||
{ name: "__dirname" },
|
||||
{ name: "require" },
|
||||
{ name: "module" },
|
||||
{ name: "exports" },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/**"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: "./src/tsconfig-eslint.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["scripts/**"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: "./scripts/tsconfig.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/**"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{ name: "setTimeout" },
|
||||
{ name: "clearTimeout" },
|
||||
{ name: "setInterval" },
|
||||
{ name: "clearInterval" },
|
||||
{ name: "setImmediate" },
|
||||
{ name: "clearImmediate" },
|
||||
{ name: "performance" },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/harness/**", "src/testRunner/**"],
|
||||
rules: {
|
||||
"no-restricted-globals": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/lib/*.d.ts"],
|
||||
...tseslint.configs.disableTypeChecked,
|
||||
},
|
||||
{
|
||||
files: ["src/lib/*.d.ts"],
|
||||
languageOptions: {
|
||||
globals: {},
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/prefer-function-type": "off",
|
||||
"@typescript-eslint/unified-signatures": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
|
||||
// scripts/eslint/rules
|
||||
"local/no-keywords": "off",
|
||||
|
||||
// eslint
|
||||
"no-var": "off",
|
||||
"no-restricted-globals": "off",
|
||||
"no-shadow-restricted-names": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/lib/es2019.array.d.ts"],
|
||||
rules: {
|
||||
"@typescript-eslint/array-type": "off",
|
||||
},
|
||||
},
|
||||
);
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/knip@5/schema.json",
|
||||
"includeEntryExports": true,
|
||||
"entry": [
|
||||
"Herebyfile.mjs",
|
||||
"src/cancellationToken/cancellationToken.ts",
|
||||
"src/testRunner/_namespaces/Harness.ts",
|
||||
"src/tsc/tsc.ts",
|
||||
"src/tsserver/server.ts",
|
||||
"src/typescript/typescript.ts",
|
||||
"src/typingsInstaller/nodeTypingsInstaller.ts",
|
||||
"src/watchGuard/watchGuard.ts",
|
||||
|
||||
"src/testRunner/tests.ts",
|
||||
"src/testRunner/_namespaces/Harness.ts",
|
||||
|
||||
// The rest of the entry files, mostly to track used dependencies:
|
||||
".eslint-plugin-local.cjs",
|
||||
".gulp.js",
|
||||
"scripts/eslint/{rules,tests}/*.cjs",
|
||||
"scripts/*.{cjs,mjs}"
|
||||
],
|
||||
"project": [
|
||||
"src/**",
|
||||
"scripts/**",
|
||||
"!src/lib/**/*.d.ts"
|
||||
],
|
||||
"ignore": [
|
||||
"scripts/failed-tests.d.cts"
|
||||
],
|
||||
"ignoreDependencies": ["c8", "eslint-formatter-autolinkable-stylish", "mocha-fivemat-progress-reporter"],
|
||||
"ignoreExportsUsedInFile": {
|
||||
"enum": true,
|
||||
"interface": true,
|
||||
"type": true
|
||||
},
|
||||
"mocha": false
|
||||
}
|
||||
Generated
+1216
-616
File diff suppressed because it is too large
Load Diff
+18
-15
@@ -13,11 +13,11 @@
|
||||
"javascript"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/TypeScript/issues"
|
||||
"url": "https://github.com/microsoft/TypeScript/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/TypeScript.git"
|
||||
"url": "https://github.com/microsoft/TypeScript.git"
|
||||
},
|
||||
"main": "./lib/typescript.js",
|
||||
"typings": "./lib/typescript.d.ts",
|
||||
@@ -42,41 +42,43 @@
|
||||
"@dprint/formatter": "^0.3.0",
|
||||
"@dprint/typescript": "0.91.1",
|
||||
"@esfx/canceltoken": "^1.0.0",
|
||||
"@octokit/rest": "^20.1.1",
|
||||
"@eslint/js": "^8.57.0",
|
||||
"@octokit/rest": "^21.0.0",
|
||||
"@types/chai": "^4.3.16",
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/minimist": "^1.2.5",
|
||||
"@types/mocha": "^10.0.6",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@types/ms": "^0.7.34",
|
||||
"@types/node": "latest",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/which": "^3.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@typescript-eslint/utils": "^7.13.1",
|
||||
"azure-devops-node-api": "^13.0.0",
|
||||
"@typescript-eslint/utils": "^7.14.1",
|
||||
"azure-devops-node-api": "^14.0.1",
|
||||
"c8": "^10.1.2",
|
||||
"chai": "^4.4.1",
|
||||
"chalk": "^4.1.2",
|
||||
"chokidar": "^3.6.0",
|
||||
"diff": "^5.2.0",
|
||||
"dprint": "^0.46.3",
|
||||
"esbuild": "^0.21.5",
|
||||
"esbuild": "^0.22.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-formatter-autolinkable-stylish": "^1.3.0",
|
||||
"eslint-plugin-local": "^4.2.2",
|
||||
"fast-xml-parser": "^4.4.0",
|
||||
"glob": "^10.4.1",
|
||||
"glob": "^10.4.2",
|
||||
"globals": "^13.24.0",
|
||||
"hereby": "^1.8.9",
|
||||
"jsonc-parser": "^3.2.1",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"knip": "^5.25.1",
|
||||
"minimist": "^1.2.8",
|
||||
"mocha": "^10.4.0",
|
||||
"mocha": "^10.5.2",
|
||||
"mocha-fivemat-progress-reporter": "^0.1.0",
|
||||
"ms": "^2.1.3",
|
||||
"node-fetch": "^3.3.2",
|
||||
"playwright": "^1.44.1",
|
||||
"playwright": "^1.45.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript": "^5.5.2",
|
||||
"typescript-eslint": "^7.14.1",
|
||||
"which": "^3.0.1"
|
||||
},
|
||||
"overrides": {
|
||||
@@ -92,6 +94,7 @@
|
||||
"clean": "hereby clean",
|
||||
"gulp": "hereby",
|
||||
"lint": "hereby lint",
|
||||
"knip": "hereby knip",
|
||||
"format": "dprint fmt",
|
||||
"setup-hooks": "node scripts/link-hooks.mjs"
|
||||
},
|
||||
|
||||
@@ -68,6 +68,7 @@ export default options;
|
||||
* @property {boolean} fix
|
||||
* @property {string} browser
|
||||
* @property {string} tests
|
||||
* @property {boolean} skipSysTests
|
||||
* @property {string | boolean} break
|
||||
* @property {string | boolean} inspect
|
||||
* @property {string} runners
|
||||
|
||||
+10
-4
@@ -15,6 +15,9 @@ import {
|
||||
rimraf,
|
||||
} from "./utils.mjs";
|
||||
|
||||
/** @import { CancelToken } from "@esfx/canceltoken" */
|
||||
void 0;
|
||||
|
||||
const mochaJs = path.resolve(findUpRoot(), "node_modules", "mocha", "bin", "_mocha");
|
||||
export const localBaseline = "tests/baselines/local/";
|
||||
export const refBaseline = "tests/baselines/reference/";
|
||||
@@ -25,12 +28,13 @@ export const coverageDir = "coverage";
|
||||
* @param {string} defaultReporter
|
||||
* @param {boolean} runInParallel
|
||||
* @param {object} options
|
||||
* @param {import("@esfx/canceltoken").CancelToken} [options.token]
|
||||
* @param {CancelToken} [options.token]
|
||||
* @param {boolean} [options.watching]
|
||||
*/
|
||||
export async function runConsoleTests(runJs, defaultReporter, runInParallel, options = {}) {
|
||||
const testTimeout = cmdLineOptions.timeout;
|
||||
const tests = cmdLineOptions.tests;
|
||||
const skipSysTests = cmdLineOptions.skipSysTests;
|
||||
const inspect = cmdLineOptions.break || cmdLineOptions.inspect;
|
||||
const runners = cmdLineOptions.runners;
|
||||
const light = cmdLineOptions.light;
|
||||
@@ -74,8 +78,8 @@ export async function runConsoleTests(runJs, defaultReporter, runInParallel, opt
|
||||
console.log(chalk.yellowBright(`[watch] running tests...`));
|
||||
}
|
||||
|
||||
if (tests || runners || light || testTimeout || taskConfigsFolder || keepFailed || shards || shardId) {
|
||||
writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout, keepFailed, shards, shardId);
|
||||
if (tests || skipSysTests || runners || light || testTimeout || taskConfigsFolder || keepFailed || shards || shardId) {
|
||||
writeTestConfigFile(tests, skipSysTests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, testTimeout, keepFailed, shards, shardId);
|
||||
}
|
||||
|
||||
const colors = cmdLineOptions.colors;
|
||||
@@ -180,6 +184,7 @@ export async function cleanTestDirs() {
|
||||
/**
|
||||
* used to pass data from command line directly to run.js
|
||||
* @param {string} tests
|
||||
* @param {boolean} skipSysTests
|
||||
* @param {string} runners
|
||||
* @param {boolean} light
|
||||
* @param {string} [taskConfigsFolder]
|
||||
@@ -190,9 +195,10 @@ export async function cleanTestDirs() {
|
||||
* @param {number | undefined} [shards]
|
||||
* @param {number | undefined} [shardId]
|
||||
*/
|
||||
export function writeTestConfigFile(tests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout, keepFailed, shards, shardId) {
|
||||
export function writeTestConfigFile(tests, skipSysTests, runners, light, taskConfigsFolder, workerCount, stackTraceLimit, timeout, keepFailed, shards, shardId) {
|
||||
const testConfigContents = JSON.stringify({
|
||||
test: tests ? [tests] : undefined,
|
||||
skipSysTests: skipSysTests ? skipSysTests : undefined,
|
||||
runners: runners ? runners.split(",") : undefined,
|
||||
light,
|
||||
workerCount,
|
||||
|
||||
@@ -6,6 +6,9 @@ import fs from "fs";
|
||||
import JSONC from "jsonc-parser";
|
||||
import which from "which";
|
||||
|
||||
/** @import { CancelToken } from "@esfx/canceltoken" */
|
||||
void 0;
|
||||
|
||||
/**
|
||||
* Executes the provided command once with the supplied arguments.
|
||||
* @param {string} cmd
|
||||
@@ -17,7 +20,7 @@ import which from "which";
|
||||
* @property {boolean} [hidePrompt]
|
||||
* @property {boolean} [waitForExit=true]
|
||||
* @property {boolean} [ignoreStdout]
|
||||
* @property {import("@esfx/canceltoken").CancelToken} [token]
|
||||
* @property {CancelToken} [token]
|
||||
*/
|
||||
export async function exec(cmd, args, options = {}) {
|
||||
return /**@type {Promise<{exitCode?: number}>}*/ (new Promise((resolve, reject) => {
|
||||
|
||||
@@ -57,7 +57,7 @@ function main() {
|
||||
// Finally write the changes to disk.
|
||||
// Modify the package.json structure
|
||||
packageJsonValue.version = `${majorMinor}.${prereleasePatch}`;
|
||||
writeFileSync(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4));
|
||||
writeFileSync(packageJsonFilePath, JSON.stringify(packageJsonValue, undefined, 4));
|
||||
writeFileSync(tsFilePath, modifiedTsFileContents);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ const { createRule } = require("./utils.cjs");
|
||||
const ts = require("typescript");
|
||||
|
||||
/**
|
||||
* @typedef {import("@typescript-eslint/utils").TSESTree.CallExpression | import("@typescript-eslint/utils").TSESTree.NewExpression} CallOrNewExpression
|
||||
* @import { TSESTree } from "@typescript-eslint/utils"
|
||||
* @typedef {TSESTree.CallExpression | TSESTree.NewExpression} CallOrNewExpression
|
||||
*/
|
||||
void 0;
|
||||
|
||||
const unset = Symbol();
|
||||
/**
|
||||
@@ -46,7 +48,7 @@ module.exports = createRule({
|
||||
|
||||
/** @type {(name: string) => boolean} */
|
||||
const isSetOrAssert = name => name.startsWith("set") || name.startsWith("assert");
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
|
||||
/** @type {(node: TSESTree.Node) => boolean} */
|
||||
const isTrivia = node => {
|
||||
if (node.type === AST_NODE_TYPES.Identifier) {
|
||||
return node.name === "undefined";
|
||||
@@ -101,7 +103,7 @@ module.exports = createRule({
|
||||
return false;
|
||||
};
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node, i: number, getSignature: () => ts.Signature | undefined) => void} */
|
||||
/** @type {(node: TSESTree.Node, i: number, getSignature: () => ts.Signature | undefined) => void} */
|
||||
const checkArg = (node, i, getSignature) => {
|
||||
if (!isTrivia(node)) {
|
||||
return;
|
||||
@@ -123,7 +125,7 @@ module.exports = createRule({
|
||||
});
|
||||
|
||||
const comments = sourceCode.getCommentsBefore(node);
|
||||
/** @type {import("@typescript-eslint/utils").TSESTree.Comment | undefined} */
|
||||
/** @type {TSESTree.Comment | undefined} */
|
||||
const comment = comments[comments.length - 1];
|
||||
|
||||
if (!comment || comment.type !== "Block") {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
const { AST_NODE_TYPES } = require("@typescript-eslint/utils");
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "debug-assert",
|
||||
meta: {
|
||||
@@ -17,14 +20,14 @@ module.exports = createRule({
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
|
||||
/** @type {(node: TSESTree.Node) => boolean} */
|
||||
const isArrowFunction = node => node.type === AST_NODE_TYPES.ArrowFunctionExpression;
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
|
||||
/** @type {(node: TSESTree.Node) => boolean} */
|
||||
const isStringLiteral = node => (
|
||||
(node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") || node.type === AST_NODE_TYPES.TemplateLiteral
|
||||
);
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.MemberExpression) => boolean} */
|
||||
/** @type {(node: TSESTree.MemberExpression) => boolean} */
|
||||
const isDebugAssert = node => (
|
||||
node.object.type === AST_NODE_TYPES.Identifier
|
||||
&& node.object.name === "Debug"
|
||||
@@ -32,7 +35,7 @@ module.exports = createRule({
|
||||
&& node.property.name === "assert"
|
||||
);
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.CallExpression) => void} */
|
||||
/** @type {(node: TSESTree.CallExpression) => void} */
|
||||
const checkDebugAssert = node => {
|
||||
const args = node.arguments;
|
||||
const argsLen = args.length;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "js-extensions",
|
||||
meta: {
|
||||
@@ -18,11 +21,11 @@ module.exports = createRule({
|
||||
create(context) {
|
||||
/** @type {(
|
||||
* node:
|
||||
* | import("@typescript-eslint/utils").TSESTree.ImportDeclaration
|
||||
* | import("@typescript-eslint/utils").TSESTree.ExportAllDeclaration
|
||||
* | import("@typescript-eslint/utils").TSESTree.ExportNamedDeclaration
|
||||
* | import("@typescript-eslint/utils").TSESTree.TSImportEqualsDeclaration
|
||||
* | import("@typescript-eslint/utils").TSESTree.TSModuleDeclaration
|
||||
* | TSESTree.ImportDeclaration
|
||||
* | TSESTree.ExportAllDeclaration
|
||||
* | TSESTree.ExportNamedDeclaration
|
||||
* | TSESTree.TSImportEqualsDeclaration
|
||||
* | TSESTree.TSModuleDeclaration
|
||||
* ) => void}
|
||||
*/
|
||||
const check = node => {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "jsdoc-format",
|
||||
meta: {
|
||||
@@ -25,17 +28,17 @@ module.exports = createRule({
|
||||
const atInternal = "@internal";
|
||||
const jsdocStart = "/**";
|
||||
|
||||
/** @type {Map<import("@typescript-eslint/utils").TSESTree.Node, boolean>} */
|
||||
/** @type {Map<TSESTree.Node, boolean>} */
|
||||
const isExportedCache = new Map();
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
|
||||
/** @type {(node: TSESTree.Node) => boolean} */
|
||||
function isExported(node) {
|
||||
const exported = isExportedCache.get(node);
|
||||
if (exported !== undefined) {
|
||||
return exported;
|
||||
}
|
||||
|
||||
/** @type {import("@typescript-eslint/utils").TSESTree.Node | undefined} */
|
||||
/** @type {TSESTree.Node | undefined} */
|
||||
let current = node;
|
||||
while (current) {
|
||||
// https://github.com/typescript-eslint/typescript-eslint/blob/e44a1a280f08f9fd0d29f74e5c3e73b7b64a9606/packages/eslint-plugin/src/util/collectUnusedVariables.ts#L440
|
||||
@@ -55,7 +58,7 @@ module.exports = createRule({
|
||||
return text.startsWith(jsdocStart);
|
||||
}
|
||||
|
||||
/** @type {(c: import("@typescript-eslint/utils").TSESTree.Comment, indexInComment: number) => import("@typescript-eslint/utils").TSESTree.SourceLocation} */
|
||||
/** @type {(c: TSESTree.Comment, indexInComment: number) => TSESTree.SourceLocation} */
|
||||
const getAtInternalLoc = (c, indexInComment) => {
|
||||
return {
|
||||
start: context.sourceCode.getLocFromIndex(c.range[0] + indexInComment),
|
||||
@@ -63,7 +66,7 @@ module.exports = createRule({
|
||||
};
|
||||
};
|
||||
|
||||
/** @type {(c: import("@typescript-eslint/utils").TSESTree.Comment) => import("@typescript-eslint/utils").TSESTree.SourceLocation} */
|
||||
/** @type {(c: TSESTree.Comment) => TSESTree.SourceLocation} */
|
||||
const getJSDocStartLoc = c => {
|
||||
return {
|
||||
start: c.loc.start,
|
||||
@@ -74,7 +77,7 @@ module.exports = createRule({
|
||||
};
|
||||
};
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => void} */
|
||||
/** @type {(node: TSESTree.Node) => void} */
|
||||
const checkDeclaration = node => {
|
||||
const blockComments = sourceCode.getCommentsBefore(node).filter(c => c.type === "Block");
|
||||
if (blockComments.length === 0) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "no-in-operator",
|
||||
meta: {
|
||||
@@ -16,7 +19,7 @@ module.exports = createRule({
|
||||
|
||||
create(context) {
|
||||
const IN_OPERATOR = "in";
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.BinaryExpression) => void} */
|
||||
/** @type {(node: TSESTree.BinaryExpression) => void} */
|
||||
const checkInOperator = node => {
|
||||
if (node.operator === IN_OPERATOR) {
|
||||
context.report({ messageId: "noInOperatorError", node });
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
const { AST_NODE_TYPES } = require("@typescript-eslint/utils");
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "no-keywords",
|
||||
meta: {
|
||||
@@ -37,12 +40,12 @@ module.exports = createRule({
|
||||
/** @type {(name: string) => boolean} */
|
||||
const isKeyword = name => keywords.includes(name);
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Identifier) => void} */
|
||||
/** @type {(node: TSESTree.Identifier) => void} */
|
||||
const report = node => {
|
||||
context.report({ messageId: "noKeywordsError", data: { name: node.name }, node });
|
||||
};
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.ObjectPattern) => void} */
|
||||
/** @type {(node: TSESTree.ObjectPattern) => void} */
|
||||
const checkProperties = node => {
|
||||
node.properties.forEach(property => {
|
||||
if (
|
||||
@@ -56,7 +59,7 @@ module.exports = createRule({
|
||||
});
|
||||
};
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.ArrayPattern) => void} */
|
||||
/** @type {(node: TSESTree.ArrayPattern) => void} */
|
||||
const checkElements = node => {
|
||||
node.elements.forEach(element => {
|
||||
if (
|
||||
@@ -69,7 +72,7 @@ module.exports = createRule({
|
||||
});
|
||||
};
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.ArrowFunctionExpression | import("@typescript-eslint/utils").TSESTree.FunctionDeclaration | import("@typescript-eslint/utils").TSESTree.FunctionExpression | import("@typescript-eslint/utils").TSESTree.TSMethodSignature | import("@typescript-eslint/utils").TSESTree.TSFunctionType) => void} */
|
||||
/** @type {(node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.TSMethodSignature | TSESTree.TSFunctionType) => void} */
|
||||
const checkParams = node => {
|
||||
if (!node || !node.params || !node.params.length) {
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
const { AST_NODE_TYPES } = require("@typescript-eslint/utils");
|
||||
const { createRule } = require("./utils.cjs");
|
||||
|
||||
/** @typedef {import("@typescript-eslint/utils").TSESTree.FunctionDeclaration | import("@typescript-eslint/utils").TSESTree.FunctionExpression} FunctionDeclarationOrExpression */
|
||||
/**
|
||||
* @import { TSESTree } from "@typescript-eslint/utils"
|
||||
* @typedef {TSESTree.FunctionDeclaration | TSESTree.FunctionExpression} FunctionDeclarationOrExpression
|
||||
*/
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "only-arrow-functions",
|
||||
@@ -32,7 +36,7 @@ module.exports = createRule({
|
||||
/** @type {(node: FunctionDeclarationOrExpression) => boolean} */
|
||||
const isThisParameter = node => !!node.params.length && !!node.params.find(param => param.type === AST_NODE_TYPES.Identifier && param.name === "this");
|
||||
|
||||
/** @type {(node: import("@typescript-eslint/utils").TSESTree.Node) => boolean} */
|
||||
/** @type {(node: TSESTree.Node) => boolean} */
|
||||
const isMethodType = node => {
|
||||
const types = [
|
||||
AST_NODE_TYPES.MethodDefinition,
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"extends": "../.eslintrc.json",
|
||||
"parserOptions": {
|
||||
"tsconfigRootDir": "src",
|
||||
"project": "./tsconfig-eslint.json"
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{ "name": "setTimeout" },
|
||||
{ "name": "clearTimeout" },
|
||||
{ "name": "setInterval" },
|
||||
{ "name": "clearInterval" },
|
||||
{ "name": "setImmediate" },
|
||||
{ "name": "clearImmediate" },
|
||||
{ "name": "performance" }
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["lib/*.d.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/prefer-function-type": "off",
|
||||
"@typescript-eslint/unified-signatures": "off",
|
||||
|
||||
// scripts/eslint/rules
|
||||
"local/no-keywords": "off",
|
||||
|
||||
// eslint
|
||||
"no-var": "off",
|
||||
"no-restricted-globals": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["lib/es2019.array.d.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/array-type": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["debug/**", "harness/**", "testRunner/**"],
|
||||
"rules": {
|
||||
"no-restricted-globals": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+217
-56
@@ -59,6 +59,7 @@ import {
|
||||
isJsonSourceFile,
|
||||
isNumber,
|
||||
isString,
|
||||
map,
|
||||
mapDefinedIterator,
|
||||
maybeBind,
|
||||
noop,
|
||||
@@ -187,10 +188,13 @@ export const enum BuilderFileEmit {
|
||||
Js = 1 << 0, // emit js file
|
||||
JsMap = 1 << 1, // emit js.map file
|
||||
JsInlineMap = 1 << 2, // emit inline source map in js file
|
||||
Dts = 1 << 3, // emit d.ts file
|
||||
DtsMap = 1 << 4, // emit d.ts.map file
|
||||
DtsErrors = 1 << 3, // emit dts errors
|
||||
DtsEmit = 1 << 4, // emit d.ts file
|
||||
DtsMap = 1 << 5, // emit d.ts.map file
|
||||
|
||||
Dts = DtsErrors | DtsEmit,
|
||||
AllJs = Js | JsMap | JsInlineMap,
|
||||
AllDtsEmit = DtsEmit | DtsMap,
|
||||
AllDts = Dts | DtsMap,
|
||||
All = AllJs | AllDts,
|
||||
}
|
||||
@@ -283,12 +287,7 @@ export function getBuilderFileEmit(options: CompilerOptions) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determining what all is pending to be emitted based on previous options or previous file emit flags
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function getPendingEmitKind(
|
||||
function getPendingEmitKind(
|
||||
optionsOrEmitKind: CompilerOptions | BuilderFileEmit,
|
||||
oldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined,
|
||||
): BuilderFileEmit {
|
||||
@@ -300,8 +299,10 @@ export function getPendingEmitKind(
|
||||
let result = BuilderFileEmit.None;
|
||||
// If there is diff in Js emit, pending emit is js emit flags
|
||||
if (diff & BuilderFileEmit.AllJs) result = emitKind & BuilderFileEmit.AllJs;
|
||||
// If dts errors pending, add dts errors flag
|
||||
if (diff & BuilderFileEmit.DtsErrors) result = result | (emitKind & BuilderFileEmit.DtsErrors);
|
||||
// If there is diff in Dts emit, pending emit is dts emit flags
|
||||
if (diff & BuilderFileEmit.AllDts) result = result | (emitKind & BuilderFileEmit.AllDts);
|
||||
if (diff & BuilderFileEmit.AllDtsEmit) result = result | (emitKind & BuilderFileEmit.AllDtsEmit);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -689,32 +690,61 @@ function getNextAffectedFile(
|
||||
}
|
||||
}
|
||||
|
||||
function clearAffectedFilesPendingEmit(state: BuilderProgramState, emitOnlyDtsFiles: boolean | undefined) {
|
||||
function clearAffectedFilesPendingEmit(
|
||||
state: BuilderProgramState,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
isForDtsErrors: boolean,
|
||||
) {
|
||||
if (!state.affectedFilesPendingEmit?.size && !state.programEmitPending) return;
|
||||
if (!emitOnlyDtsFiles) {
|
||||
if (!emitOnlyDtsFiles && !isForDtsErrors) {
|
||||
state.affectedFilesPendingEmit = undefined;
|
||||
state.programEmitPending = undefined;
|
||||
}
|
||||
state.affectedFilesPendingEmit?.forEach((emitKind, path) => {
|
||||
// Mark the files as pending only if they are pending on js files, remove the dts emit pending flag
|
||||
const pending = emitKind & BuilderFileEmit.AllJs;
|
||||
const pending = !isForDtsErrors ?
|
||||
emitKind & BuilderFileEmit.AllJs :
|
||||
emitKind & (BuilderFileEmit.AllJs | BuilderFileEmit.AllDtsEmit);
|
||||
if (!pending) state.affectedFilesPendingEmit!.delete(path);
|
||||
else state.affectedFilesPendingEmit!.set(path, pending);
|
||||
});
|
||||
// Mark the program as pending only if its pending on js files, remove the dts emit pending flag
|
||||
if (state.programEmitPending) {
|
||||
const pending = state.programEmitPending & BuilderFileEmit.AllJs;
|
||||
const pending = !isForDtsErrors ?
|
||||
state.programEmitPending & BuilderFileEmit.AllJs :
|
||||
state.programEmitPending & (BuilderFileEmit.AllJs | BuilderFileEmit.AllDtsEmit);
|
||||
if (!pending) state.programEmitPending = undefined;
|
||||
else state.programEmitPending = pending;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determining what all is pending to be emitted based on previous options or previous file emit flags
|
||||
* @internal
|
||||
*/
|
||||
export function getPendingEmitKindWithSeen(
|
||||
optionsOrEmitKind: CompilerOptions | BuilderFileEmit,
|
||||
seenOldOptionsOrEmitKind: CompilerOptions | BuilderFileEmit | undefined,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
isForDtsErrors: boolean,
|
||||
) {
|
||||
let pendingKind = getPendingEmitKind(optionsOrEmitKind, seenOldOptionsOrEmitKind);
|
||||
if (emitOnlyDtsFiles) pendingKind = pendingKind & BuilderFileEmit.AllDts;
|
||||
if (isForDtsErrors) pendingKind = pendingKind & BuilderFileEmit.DtsErrors;
|
||||
return pendingKind;
|
||||
}
|
||||
|
||||
function getBuilderFileEmitAllDts(isForDtsErrors: boolean) {
|
||||
return !isForDtsErrors ? BuilderFileEmit.AllDts : BuilderFileEmit.DtsErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next file to be emitted from files that retrieved semantic diagnostics but did not emit yet
|
||||
*/
|
||||
function getNextAffectedFilePendingEmit(
|
||||
state: BuilderProgramStateWithDefinedProgram,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
isForDtsErrors: boolean,
|
||||
) {
|
||||
if (!state.affectedFilesPendingEmit?.size) return undefined;
|
||||
return forEachEntry(state.affectedFilesPendingEmit, (emitKind, path) => {
|
||||
@@ -724,13 +754,20 @@ function getNextAffectedFilePendingEmit(
|
||||
return undefined;
|
||||
}
|
||||
const seenKind = state.seenEmittedFiles?.get(affectedFile.resolvedPath);
|
||||
let pendingKind = getPendingEmitKind(emitKind, seenKind);
|
||||
if (emitOnlyDtsFiles) pendingKind = pendingKind & BuilderFileEmit.AllDts;
|
||||
const pendingKind = getPendingEmitKindWithSeen(
|
||||
emitKind,
|
||||
seenKind,
|
||||
emitOnlyDtsFiles,
|
||||
isForDtsErrors,
|
||||
);
|
||||
if (pendingKind) return { affectedFile, emitKind: pendingKind };
|
||||
});
|
||||
}
|
||||
|
||||
function getNextPendingEmitDiagnosticsFile(state: BuilderProgramStateWithDefinedProgram) {
|
||||
function getNextPendingEmitDiagnosticsFile(
|
||||
state: BuilderProgramStateWithDefinedProgram,
|
||||
isForDtsErrors: boolean,
|
||||
) {
|
||||
if (!state.emitDiagnosticsPerFile?.size) return undefined;
|
||||
return forEachEntry(state.emitDiagnosticsPerFile, (diagnostics, path) => {
|
||||
const affectedFile = state.program.getSourceFileByPath(path);
|
||||
@@ -739,7 +776,7 @@ function getNextPendingEmitDiagnosticsFile(state: BuilderProgramStateWithDefined
|
||||
return undefined;
|
||||
}
|
||||
const seenKind = state.seenEmittedFiles?.get(affectedFile.resolvedPath) || BuilderFileEmit.None;
|
||||
if (!(seenKind & BuilderFileEmit.AllDts)) return { affectedFile, diagnostics, seenKind };
|
||||
if (!(seenKind & getBuilderFileEmitAllDts(isForDtsErrors))) return { affectedFile, diagnostics, seenKind };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1090,6 +1127,7 @@ export interface IncrementalBuildInfoBase extends BuildInfo {
|
||||
options: CompilerOptions | undefined;
|
||||
semanticDiagnosticsPerFile: IncrementalBuildInfoDiagnostic[] | undefined;
|
||||
emitDiagnosticsPerFile: IncrementalBuildInfoEmitDiagnostic[] | undefined;
|
||||
changeFileSet: readonly IncrementalBuildInfoFileId[] | undefined;
|
||||
// Because this is only output file in the program, we dont need fileId to deduplicate name
|
||||
latestChangedDtsFile?: string | undefined;
|
||||
errors: true | undefined;
|
||||
@@ -1144,8 +1182,7 @@ export interface NonIncrementalBuildInfo extends BuildInfo {
|
||||
checkPending: true | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNonIncrementalBuildInfo(info: BuildInfo): info is NonIncrementalBuildInfo {
|
||||
function isNonIncrementalBuildInfo(info: BuildInfo): info is NonIncrementalBuildInfo {
|
||||
return !isIncrementalBuildInfo(info) && !!(info as NonIncrementalBuildInfo).root;
|
||||
}
|
||||
|
||||
@@ -1225,8 +1262,9 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
|
||||
root,
|
||||
resolvedRoot: toResolvedRoot(),
|
||||
options: toIncrementalBuildInfoCompilerOptions(state.compilerOptions),
|
||||
semanticDiagnosticsPerFile: toIncrementalBuildInfoDiagnostics(),
|
||||
semanticDiagnosticsPerFile: !state.changedFilesSet.size ? toIncrementalBuildInfoDiagnostics() : undefined,
|
||||
emitDiagnosticsPerFile: toIncrementalBuildInfoEmitDiagnostics(),
|
||||
changeFileSet: toChangeFileSet(),
|
||||
outSignature: state.outSignature,
|
||||
latestChangedDtsFile,
|
||||
pendingEmit: !state.programEmitPending ?
|
||||
@@ -1322,6 +1360,7 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
|
||||
referencedMap,
|
||||
semanticDiagnosticsPerFile,
|
||||
emitDiagnosticsPerFile: toIncrementalBuildInfoEmitDiagnostics(),
|
||||
changeFileSet: toChangeFileSet(),
|
||||
affectedFilesPendingEmit,
|
||||
emitSignatures,
|
||||
latestChangedDtsFile,
|
||||
@@ -1428,7 +1467,7 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
|
||||
state.fileInfos.forEach((_value, key) => {
|
||||
const value = state.semanticDiagnosticsPerFile.get(key);
|
||||
if (!value) {
|
||||
result = append(result, toFileId(key));
|
||||
if (!state.changedFilesSet.has(key)) result = append(result, toFileId(key));
|
||||
}
|
||||
else if (value.length) {
|
||||
result = append(result, [
|
||||
@@ -1508,6 +1547,16 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
|
||||
return result;
|
||||
}) || array;
|
||||
}
|
||||
|
||||
function toChangeFileSet() {
|
||||
let changeFileSet: IncrementalBuildInfoFileId[] | undefined;
|
||||
if (state.changedFilesSet.size) {
|
||||
for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) {
|
||||
changeFileSet = append(changeFileSet, toFileId(path));
|
||||
}
|
||||
}
|
||||
return changeFileSet;
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -1599,8 +1648,7 @@ export function computeSignatureWithDiagnostics(
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function computeSignature(text: string, host: HostForComputeHash, data?: WriteFileCallbackData) {
|
||||
function computeSignature(text: string, host: HostForComputeHash, data?: WriteFileCallbackData) {
|
||||
return (host.createHash ?? generateDjb2Hash)(getTextHandlingSourceMapForSignature(text, data));
|
||||
}
|
||||
|
||||
@@ -1645,6 +1693,7 @@ export function createBuilderProgram(
|
||||
sourceFile,
|
||||
);
|
||||
builderProgram.getSemanticDiagnostics = getSemanticDiagnostics;
|
||||
builderProgram.getDeclarationDiagnostics = getDeclarationDiagnostics;
|
||||
builderProgram.emit = emit;
|
||||
builderProgram.releaseProgram = () => releaseCache(state);
|
||||
|
||||
@@ -1682,28 +1731,42 @@ export function createBuilderProgram(
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
function emitNextAffectedFile(
|
||||
function emitNextAffectedFileOrDtsErrors(
|
||||
writeFile: WriteFileCallback | undefined,
|
||||
cancellationToken: CancellationToken | undefined,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
customTransformers: CustomTransformers | undefined,
|
||||
isForDtsErrors: boolean,
|
||||
): AffectedFileResult<EmitResult> {
|
||||
Debug.assert(isBuilderProgramStateWithDefinedProgram(state));
|
||||
let affected = getNextAffectedFile(state, cancellationToken, host);
|
||||
const programEmitKind = getBuilderFileEmit(state.compilerOptions);
|
||||
let emitKind: BuilderFileEmit = emitOnlyDtsFiles ?
|
||||
programEmitKind & BuilderFileEmit.AllDts : programEmitKind;
|
||||
let emitKind: BuilderFileEmit = !isForDtsErrors ?
|
||||
emitOnlyDtsFiles ?
|
||||
programEmitKind & BuilderFileEmit.AllDts :
|
||||
programEmitKind :
|
||||
BuilderFileEmit.DtsErrors;
|
||||
if (!affected) {
|
||||
if (!state.compilerOptions.outFile) {
|
||||
const pendingAffectedFile = getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles);
|
||||
const pendingAffectedFile = getNextAffectedFilePendingEmit(
|
||||
state,
|
||||
emitOnlyDtsFiles,
|
||||
isForDtsErrors,
|
||||
);
|
||||
if (pendingAffectedFile) {
|
||||
// Emit pending affected file
|
||||
({ affectedFile: affected, emitKind } = pendingAffectedFile);
|
||||
}
|
||||
else {
|
||||
const pendingForDiagnostics = getNextPendingEmitDiagnosticsFile(state);
|
||||
const pendingForDiagnostics = getNextPendingEmitDiagnosticsFile(
|
||||
state,
|
||||
isForDtsErrors,
|
||||
);
|
||||
if (pendingForDiagnostics) {
|
||||
(state.seenEmittedFiles ??= new Map()).set(pendingForDiagnostics.affectedFile.resolvedPath, pendingForDiagnostics.seenKind | BuilderFileEmit.AllDts);
|
||||
(state.seenEmittedFiles ??= new Map()).set(
|
||||
pendingForDiagnostics.affectedFile.resolvedPath,
|
||||
pendingForDiagnostics.seenKind | getBuilderFileEmitAllDts(isForDtsErrors),
|
||||
);
|
||||
return {
|
||||
result: { emitSkipped: true, diagnostics: pendingForDiagnostics.diagnostics },
|
||||
affected: pendingForDiagnostics.affectedFile,
|
||||
@@ -1714,15 +1777,19 @@ export function createBuilderProgram(
|
||||
else {
|
||||
// Emit program if it was pending emit
|
||||
if (state.programEmitPending) {
|
||||
emitKind = state.programEmitPending;
|
||||
if (emitOnlyDtsFiles) emitKind = emitKind & BuilderFileEmit.AllDts;
|
||||
emitKind = getPendingEmitKindWithSeen(
|
||||
state.programEmitPending,
|
||||
state.seenProgramEmit,
|
||||
emitOnlyDtsFiles,
|
||||
isForDtsErrors,
|
||||
);
|
||||
if (emitKind) affected = state.program!;
|
||||
}
|
||||
// Pending emit diagnostics
|
||||
if (!affected && state.emitDiagnosticsPerFile?.size) {
|
||||
const seenKind = state.seenProgramEmit || BuilderFileEmit.None;
|
||||
if (!(seenKind & BuilderFileEmit.AllDts)) {
|
||||
state.seenProgramEmit = BuilderFileEmit.AllDts | seenKind;
|
||||
if (!(seenKind & getBuilderFileEmitAllDts(isForDtsErrors))) {
|
||||
state.seenProgramEmit = getBuilderFileEmitAllDts(isForDtsErrors) | seenKind;
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
state.emitDiagnosticsPerFile.forEach(d => addRange(diagnostics, d));
|
||||
return {
|
||||
@@ -1735,7 +1802,7 @@ export function createBuilderProgram(
|
||||
|
||||
if (!affected) {
|
||||
// Emit buildinfo if pending
|
||||
if (!getBuildInfoEmitPending(state)) return undefined;
|
||||
if (isForDtsErrors || !getBuildInfoEmitPending(state)) return undefined;
|
||||
const affected = state.program;
|
||||
const result = affected.emitBuildInfo(
|
||||
writeFile || maybeBind(host, host.writeFile),
|
||||
@@ -1750,15 +1817,23 @@ export function createBuilderProgram(
|
||||
if (emitKind & BuilderFileEmit.AllJs) emitOnly = EmitOnly.Js;
|
||||
if (emitKind & BuilderFileEmit.AllDts) emitOnly = emitOnly === undefined ? EmitOnly.Dts : undefined;
|
||||
// Actual emit without buildInfo as we want to emit it later so the state is updated
|
||||
const result = state.program.emit(
|
||||
affected === state.program ? undefined : affected as SourceFile,
|
||||
getWriteFileCallback(writeFile, customTransformers),
|
||||
cancellationToken,
|
||||
emitOnly,
|
||||
customTransformers,
|
||||
/*forceDtsEmit*/ undefined,
|
||||
/*skipBuildInfo*/ true,
|
||||
);
|
||||
const result = !isForDtsErrors ?
|
||||
state.program.emit(
|
||||
affected === state.program ? undefined : affected as SourceFile,
|
||||
getWriteFileCallback(writeFile, customTransformers),
|
||||
cancellationToken,
|
||||
emitOnly,
|
||||
customTransformers,
|
||||
/*forceDtsEmit*/ undefined,
|
||||
/*skipBuildInfo*/ true,
|
||||
) :
|
||||
{
|
||||
emitSkipped: true,
|
||||
diagnostics: state.program.getDeclarationDiagnostics(
|
||||
affected === state.program ? undefined : affected as SourceFile,
|
||||
cancellationToken,
|
||||
),
|
||||
};
|
||||
if (affected !== state.program) {
|
||||
// update affected files
|
||||
const affectedSourceFile = affected as SourceFile;
|
||||
@@ -1785,21 +1860,45 @@ export function createBuilderProgram(
|
||||
getPendingEmitKind(state.programEmitPending, emitKind) :
|
||||
undefined;
|
||||
state.seenProgramEmit = emitKind | (state.seenProgramEmit || BuilderFileEmit.None);
|
||||
// Update the d.ts diagnostics since they always come with Location, skip diagnsotics without file,
|
||||
// they could be semantic diagnsotic with noEmitOnError or other kind of diagnostics
|
||||
let emitDiagnosticsPerFile: Map<Path, Diagnostic[]> | undefined;
|
||||
result.diagnostics.forEach(d => {
|
||||
if (!d.file) return; // Dont cache without fileName
|
||||
let diagnostics = emitDiagnosticsPerFile?.get(d.file.resolvedPath);
|
||||
if (!diagnostics) (emitDiagnosticsPerFile ??= new Map()).set(d.file.resolvedPath, diagnostics = []);
|
||||
diagnostics.push(d);
|
||||
});
|
||||
if (emitDiagnosticsPerFile) state.emitDiagnosticsPerFile = emitDiagnosticsPerFile;
|
||||
setEmitDiagnosticsPerFile(result.diagnostics);
|
||||
state.buildInfoEmitPending = true;
|
||||
}
|
||||
return { result, affected };
|
||||
}
|
||||
|
||||
function setEmitDiagnosticsPerFile(diagnostics: readonly Diagnostic[]) {
|
||||
// Update the d.ts diagnostics since they always come with Location, skip diagnsotics without file,
|
||||
// they could be semantic diagnsotic with noEmitOnError or other kind of diagnostics
|
||||
let emitDiagnosticsPerFile: Map<Path, Diagnostic[]> | undefined;
|
||||
diagnostics.forEach(d => {
|
||||
if (!d.file) return; // Dont cache without fileName
|
||||
let diagnostics = emitDiagnosticsPerFile?.get(d.file.resolvedPath);
|
||||
if (!diagnostics) (emitDiagnosticsPerFile ??= new Map()).set(d.file.resolvedPath, diagnostics = []);
|
||||
diagnostics.push(d);
|
||||
});
|
||||
if (emitDiagnosticsPerFile) state.emitDiagnosticsPerFile = emitDiagnosticsPerFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
function emitNextAffectedFile(
|
||||
writeFile: WriteFileCallback | undefined,
|
||||
cancellationToken: CancellationToken | undefined,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
customTransformers: CustomTransformers | undefined,
|
||||
): AffectedFileResult<EmitResult> {
|
||||
return emitNextAffectedFileOrDtsErrors(
|
||||
writeFile,
|
||||
cancellationToken,
|
||||
emitOnlyDtsFiles,
|
||||
customTransformers,
|
||||
/*isForDtsErrors*/ false,
|
||||
);
|
||||
}
|
||||
|
||||
function getWriteFileCallback(
|
||||
writeFile: WriteFileCallback | undefined,
|
||||
customTransformers: CustomTransformers | undefined,
|
||||
@@ -1942,16 +2041,75 @@ export function createBuilderProgram(
|
||||
}
|
||||
// In non Emit builder, clear affected files pending emit
|
||||
else {
|
||||
clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles);
|
||||
clearAffectedFilesPendingEmit(
|
||||
state,
|
||||
emitOnlyDtsFiles,
|
||||
/*isForDtsErrors*/ false,
|
||||
);
|
||||
}
|
||||
}
|
||||
return state.program.emit(
|
||||
const emitResult = state.program.emit(
|
||||
targetSourceFile,
|
||||
getWriteFileCallback(writeFile, customTransformers),
|
||||
cancellationToken,
|
||||
emitOnlyDtsFiles,
|
||||
customTransformers,
|
||||
);
|
||||
handleNonEmitBuilderWithEmitOrDtsErrors(
|
||||
targetSourceFile,
|
||||
emitOnlyDtsFiles,
|
||||
/*isForDtsErrors*/ false,
|
||||
emitResult.diagnostics,
|
||||
);
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
function handleNonEmitBuilderWithEmitOrDtsErrors(
|
||||
targetSourceFile: SourceFile | undefined,
|
||||
emitOnlyDtsFiles: boolean | undefined,
|
||||
isForDtsErrors: boolean,
|
||||
diagnostics: EmitResult["diagnostics"],
|
||||
) {
|
||||
if (!targetSourceFile && kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
|
||||
clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles, isForDtsErrors);
|
||||
setEmitDiagnosticsPerFile(diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
function getDeclarationDiagnostics(
|
||||
sourceFile?: SourceFile,
|
||||
cancellationToken?: CancellationToken,
|
||||
): readonly DiagnosticWithLocation[] {
|
||||
Debug.assert(isBuilderProgramStateWithDefinedProgram(state));
|
||||
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
|
||||
assertSourceFileOkWithoutNextAffectedCall(state, sourceFile);
|
||||
let affectedEmitResult: AffectedFileResult<EmitResult>;
|
||||
let diagnostics: Diagnostic[] | undefined;
|
||||
while (
|
||||
affectedEmitResult = emitNextAffectedFileOrDtsErrors(
|
||||
/*writeFile*/ undefined,
|
||||
cancellationToken,
|
||||
/*emitOnlyDtsFiles*/ undefined,
|
||||
/*customTransformers*/ undefined,
|
||||
/*isForDtsErrors*/ true,
|
||||
)
|
||||
) {
|
||||
if (!sourceFile) diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics);
|
||||
}
|
||||
return (
|
||||
!sourceFile ? diagnostics : state.emitDiagnosticsPerFile?.get(sourceFile.resolvedPath)
|
||||
) as readonly DiagnosticWithLocation[] | undefined || emptyArray;
|
||||
}
|
||||
else {
|
||||
const result = state.program.getDeclarationDiagnostics(sourceFile, cancellationToken);
|
||||
handleNonEmitBuilderWithEmitOrDtsErrors(
|
||||
sourceFile,
|
||||
/*emitOnlyDtsFiles*/ undefined,
|
||||
/*isForDtsErrors*/ true,
|
||||
result,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2099,6 +2257,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
|
||||
let filePathsSetList: Set<Path>[] | undefined;
|
||||
const latestChangedDtsFile = buildInfo.latestChangedDtsFile ? toAbsolutePath(buildInfo.latestChangedDtsFile) : undefined;
|
||||
const fileInfos = new Map<Path, BuilderState.FileInfo>();
|
||||
const changedFilesSet = new Set(map(buildInfo.changeFileSet, toFilePath));
|
||||
if (isIncrementalBundleEmitBuildInfo(buildInfo)) {
|
||||
buildInfo.fileInfos.forEach((fileInfo, index) => {
|
||||
const path = toFilePath(index + 1 as IncrementalBuildInfoFileId);
|
||||
@@ -2110,6 +2269,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
|
||||
semanticDiagnosticsPerFile: toPerFileSemanticDiagnostics(buildInfo.semanticDiagnosticsPerFile),
|
||||
emitDiagnosticsPerFile: toPerFileEmitDiagnostics(buildInfo.emitDiagnosticsPerFile),
|
||||
hasReusableDiagnostic: true,
|
||||
changedFilesSet,
|
||||
latestChangedDtsFile,
|
||||
outSignature: buildInfo.outSignature,
|
||||
programEmitPending: buildInfo.pendingEmit === undefined ? undefined : toProgramEmitPending(buildInfo.pendingEmit, buildInfo.options),
|
||||
@@ -2147,6 +2307,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
|
||||
semanticDiagnosticsPerFile: toPerFileSemanticDiagnostics(buildInfo.semanticDiagnosticsPerFile),
|
||||
emitDiagnosticsPerFile: toPerFileEmitDiagnostics(buildInfo.emitDiagnosticsPerFile),
|
||||
hasReusableDiagnostic: true,
|
||||
changedFilesSet,
|
||||
affectedFilesPendingEmit: buildInfo.affectedFilesPendingEmit && arrayToMap(buildInfo.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0]), value => toBuilderFileEmit(value, fullEmitForOptions!)),
|
||||
latestChangedDtsFile,
|
||||
emitSignatures: emitSignatures?.size ? emitSignatures : undefined,
|
||||
@@ -2208,7 +2369,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
|
||||
const semanticDiagnostics = new Map<Path, readonly ReusableDiagnostic[]>(
|
||||
mapDefinedIterator(
|
||||
fileInfos.keys(),
|
||||
key => [key, emptyArray],
|
||||
key => !changedFilesSet.has(key) ? [key, emptyArray] : undefined,
|
||||
),
|
||||
);
|
||||
diagnostics?.forEach(value => {
|
||||
|
||||
+48
-29
@@ -2787,7 +2787,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const moduleNotFoundError = !(moduleName.parent.parent.flags & NodeFlags.Ambient)
|
||||
? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found
|
||||
: undefined;
|
||||
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true);
|
||||
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*ignoreErrors*/ false, /*isForAugmentation*/ true);
|
||||
if (!mainModule) {
|
||||
return;
|
||||
}
|
||||
@@ -4551,17 +4551,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const errorMessage = isClassic ?
|
||||
Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option
|
||||
: Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations;
|
||||
return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? undefined : errorMessage);
|
||||
return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? undefined : errorMessage, ignoreErrors);
|
||||
}
|
||||
|
||||
function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, isForAugmentation = false): Symbol | undefined {
|
||||
function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, ignoreErrors = false, isForAugmentation = false): Symbol | undefined {
|
||||
return isStringLiteralLike(moduleReferenceExpression)
|
||||
? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation)
|
||||
? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, !ignoreErrors ? moduleReferenceExpression : undefined, isForAugmentation)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined {
|
||||
if (startsWith(moduleReference, "@types/")) {
|
||||
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node | undefined, isForAugmentation = false): Symbol | undefined {
|
||||
if (errorNode && startsWith(moduleReference, "@types/")) {
|
||||
const diag = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1;
|
||||
const withoutAtTypePrefix = removePrefix(moduleReference, "@types/");
|
||||
error(errorNode, diag, withoutAtTypePrefix, moduleReference);
|
||||
@@ -4585,7 +4585,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? host.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat;
|
||||
const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions);
|
||||
const resolvedModule = host.getResolvedModule(currentSourceFile, moduleReference, mode)?.resolvedModule;
|
||||
const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile);
|
||||
const resolutionDiagnostic = errorNode && resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule, currentSourceFile);
|
||||
const sourceFile = resolvedModule
|
||||
&& (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set)
|
||||
&& host.getSourceFile(resolvedModule.resolvedFileName);
|
||||
@@ -4598,7 +4598,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (resolvedModule.resolvedUsingTsExtension && isDeclarationFileName(moduleReference)) {
|
||||
const importOrExport = findAncestor(location, isImportDeclaration)?.importClause ||
|
||||
findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration));
|
||||
if (importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) {
|
||||
if (errorNode && importOrExport && !importOrExport.isTypeOnly || findAncestor(location, isImportCall)) {
|
||||
error(
|
||||
errorNode,
|
||||
Diagnostics.A_declaration_file_cannot_be_imported_without_import_type_Did_you_mean_to_import_an_implementation_file_0_instead,
|
||||
@@ -4609,19 +4609,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
else if (resolvedModule.resolvedUsingTsExtension && !shouldAllowImportingTsExtension(compilerOptions, currentSourceFile.fileName)) {
|
||||
const importOrExport = findAncestor(location, isImportDeclaration)?.importClause ||
|
||||
findAncestor(location, or(isImportEqualsDeclaration, isExportDeclaration));
|
||||
if (!(importOrExport?.isTypeOnly || findAncestor(location, isImportTypeNode))) {
|
||||
if (errorNode && !(importOrExport?.isTypeOnly || findAncestor(location, isImportTypeNode))) {
|
||||
const tsExtension = Debug.checkDefined(tryExtractTSExtension(moduleReference));
|
||||
error(errorNode, Diagnostics.An_import_path_can_only_end_with_a_0_extension_when_allowImportingTsExtensions_is_enabled, tsExtension);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceFile.symbol) {
|
||||
if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
|
||||
if (errorNode && resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
|
||||
errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference);
|
||||
}
|
||||
if (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext) {
|
||||
if (errorNode && (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext)) {
|
||||
const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration);
|
||||
const overrideHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined;
|
||||
const overrideHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l) || isJSDocImportTag(l));
|
||||
// An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of
|
||||
// normal mode restrictions
|
||||
if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !hasResolutionModeOverride(overrideHost)) {
|
||||
@@ -4684,7 +4684,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// merged symbol is module declaration symbol combined with all augmentations
|
||||
return getMergedSymbol(sourceFile.symbol);
|
||||
}
|
||||
if (moduleNotFoundError) {
|
||||
if (errorNode && moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
|
||||
}
|
||||
@@ -4706,6 +4706,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
if (!errorNode) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// May be an untyped module. If so, ignore resolutionDiagnostic.
|
||||
if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
|
||||
if (isForAugmentation) {
|
||||
@@ -8322,11 +8326,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const typePredicate = getTypePredicateOfSignature(signature);
|
||||
const type = getReturnTypeOfSignature(signature);
|
||||
if (context.enclosingDeclaration && (!isErrorType(type) || (context.flags & NodeBuilderFlags.AllowUnresolvedNames)) && signature.declaration && !nodeIsSynthesized(signature.declaration)) {
|
||||
const annotation = signature.declaration && getNonlocalEffectiveReturnTypeAnnotationNode(signature.declaration);
|
||||
// Default constructor signatures inherited from base classes return the derived class but have the base class declaration
|
||||
// To ensure we don't serialize the wrong type we check that that return type of the signature corresponds to the declaration return type signature
|
||||
if (annotation && getTypeFromTypeNode(context, annotation) === type) {
|
||||
const result = tryReuseExistingTypeNodeHelper(context, annotation);
|
||||
const annotation = getNonlocalEffectiveReturnTypeAnnotationNode(signature.declaration);
|
||||
if (annotation) {
|
||||
const result = tryReuseExistingTypeNode(context, annotation, type, context.enclosingDeclaration);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -8836,7 +8838,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
);
|
||||
}
|
||||
if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.ComputedPropertyName && !isLateBindableName(node.name)) {
|
||||
if (!(context.flags & NodeBuilderFlags.AllowUnresolvedNames && hasDynamicName(node) && isEntityNameExpression(node.name.expression) && checkComputedPropertyName(node.name).flags & TypeFlags.Any)) {
|
||||
if (!hasDynamicName(node)) {
|
||||
return visitEachChild(node, visitExistingNodeTreeSymbols);
|
||||
}
|
||||
if (!(context.flags & NodeBuilderFlags.AllowUnresolvedNames && isEntityNameExpression(node.name.expression) && checkComputedPropertyName(node.name).flags & TypeFlags.Any)) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -13416,7 +13421,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
links[resolutionKind] = resolved || emptySymbols;
|
||||
}
|
||||
|
||||
return links[resolutionKind]!;
|
||||
return links[resolutionKind];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -15958,7 +15963,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper {
|
||||
return createTypeMapper(signature.typeParameters!, typeArguments);
|
||||
return createTypeMapper(sameMap(signature.typeParameters!, tp => tp.mapper ? instantiateType(tp, tp.mapper) : tp), typeArguments);
|
||||
}
|
||||
|
||||
function getErasedSignature(signature: Signature): Signature {
|
||||
@@ -17835,10 +17840,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
// Check that the given type has a match in every union. A given type is matched by
|
||||
// an identical type, and a literal type is additionally matched by its corresponding
|
||||
// primitive type.
|
||||
// primitive type, and missingType is matched by undefinedType (and vice versa).
|
||||
function eachUnionContains(unionTypes: UnionType[], type: Type) {
|
||||
for (const u of unionTypes) {
|
||||
if (!containsType(u.types, type)) {
|
||||
if (type === missingType) {
|
||||
return containsType(u.types, undefinedType);
|
||||
}
|
||||
if (type === undefinedType) {
|
||||
return containsType(u.types, missingType);
|
||||
}
|
||||
const primitive = type.flags & TypeFlags.StringLiteral ? stringType :
|
||||
type.flags & (TypeFlags.Enum | TypeFlags.NumberLiteral) ? numberType :
|
||||
type.flags & TypeFlags.BigIntLiteral ? bigintType :
|
||||
@@ -17918,6 +17929,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (const t of u.types) {
|
||||
if (insertType(checked, t)) {
|
||||
if (eachUnionContains(unionTypes, t)) {
|
||||
// undefinedType/missingType should always come sorted first so we leverage that here
|
||||
if (t === undefinedType && result.length && result[0] === missingType) {
|
||||
continue;
|
||||
}
|
||||
if (t === missingType && result.length && result[0] === undefinedType) {
|
||||
result[0] = missingType;
|
||||
continue;
|
||||
}
|
||||
insertType(result, t);
|
||||
}
|
||||
}
|
||||
@@ -18831,7 +18850,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean): Type {
|
||||
const cache = writing ? "simplifiedForWriting" : "simplifiedForReading";
|
||||
if (type[cache]) {
|
||||
return type[cache] === circularConstraintType ? type : type[cache]!;
|
||||
return type[cache] === circularConstraintType ? type : type[cache];
|
||||
}
|
||||
type[cache] = circularConstraintType;
|
||||
// We recursively simplify the object type as it may in turn be an indexed access type. For example, with
|
||||
@@ -24181,7 +24200,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (include[i]) {
|
||||
const targetType = getTypeOfPropertyOrIndexSignatureOfType(types[i], propertyName);
|
||||
if (targetType && related(getDiscriminatingType(), targetType)) {
|
||||
if (targetType && someType(getDiscriminatingType(), t => !!related(t, targetType))) {
|
||||
matched = true;
|
||||
}
|
||||
else {
|
||||
@@ -33199,7 +33218,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option
|
||||
: Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations;
|
||||
const specifier = getJSXRuntimeImportSpecifier(file, runtimeImportSpecifier);
|
||||
const mod = resolveExternalModule(specifier || location!, runtimeImportSpecifier, errorMessage, location!);
|
||||
const mod = resolveExternalModule(specifier || location!, runtimeImportSpecifier, errorMessage, location);
|
||||
const result = mod && mod !== unknownSymbol ? getMergedSymbol(resolveSymbol(mod)) : undefined;
|
||||
if (links) {
|
||||
links.jsxImplicitImportContainer = result || false;
|
||||
@@ -51247,6 +51266,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// fallthrough
|
||||
case ModuleKind.ES2022:
|
||||
case ModuleKind.ESNext:
|
||||
case ModuleKind.Preserve:
|
||||
case ModuleKind.System:
|
||||
if (languageVersion >= ScriptTarget.ES2017) {
|
||||
break;
|
||||
@@ -52064,13 +52084,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
const nodeArguments = node.arguments;
|
||||
if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16) {
|
||||
if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16 && moduleKind !== ModuleKind.Preserve) {
|
||||
// We are allowed trailing comma after proposal-import-assertions.
|
||||
checkGrammarForDisallowedTrailingComma(nodeArguments);
|
||||
|
||||
if (nodeArguments.length > 1) {
|
||||
const importAttributesArgument = nodeArguments[1];
|
||||
return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext);
|
||||
return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_nodenext_or_preserve);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52280,8 +52300,7 @@ export function signatureHasRestParameter(s: Signature) {
|
||||
return !!(s.flags & SignatureFlags.HasRestParameter);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function signatureHasLiteralTypes(s: Signature) {
|
||||
function signatureHasLiteralTypes(s: Signature) {
|
||||
return !!(s.flags & SignatureFlags.HasLiteralTypes);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,8 +123,7 @@ import {
|
||||
WatchOptions,
|
||||
} from "./_namespaces/ts.js";
|
||||
|
||||
/** @internal */
|
||||
export const compileOnSaveCommandLineOption: CommandLineOption = {
|
||||
const compileOnSaveCommandLineOption: CommandLineOption = {
|
||||
name: "compileOnSave",
|
||||
type: "boolean",
|
||||
defaultValueDescription: false,
|
||||
@@ -1626,12 +1625,11 @@ export const optionsAffectingProgramStructure: readonly CommandLineOption[] = op
|
||||
/** @internal */
|
||||
export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => hasProperty(option, "transpileOptionValue"));
|
||||
|
||||
/** @internal */
|
||||
export const configDirTemplateSubstitutionOptions: readonly CommandLineOption[] = optionDeclarations.filter(
|
||||
const configDirTemplateSubstitutionOptions: readonly CommandLineOption[] = optionDeclarations.filter(
|
||||
option => option.allowConfigDirTemplateSubstitution || (!option.isCommandLineOnly && option.isFilePath),
|
||||
);
|
||||
/** @internal */
|
||||
export const configDirTemplateSubstitutionWatchOptions: readonly CommandLineOption[] = optionsForWatch.filter(
|
||||
|
||||
const configDirTemplateSubstitutionWatchOptions: readonly CommandLineOption[] = optionsForWatch.filter(
|
||||
option => option.allowConfigDirTemplateSubstitution || (!option.isCommandLineOnly && option.isFilePath),
|
||||
);
|
||||
|
||||
@@ -1745,8 +1743,7 @@ const compilerOptionsAlternateMode: AlternateModeDiagnostics = {
|
||||
getOptionsNameMap: getBuildOptionsNameMap,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const defaultInitCompilerOptions: CompilerOptions = {
|
||||
const defaultInitCompilerOptions: CompilerOptions = {
|
||||
module: ModuleKind.CommonJS,
|
||||
target: ScriptTarget.ES2016,
|
||||
strict: true,
|
||||
@@ -2903,8 +2900,7 @@ function directoryOfCombinedPath(fileName: string, basePath: string) {
|
||||
return getDirectoryPath(getNormalizedAbsolutePath(fileName, basePath));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const defaultIncludeSpec = "**/*";
|
||||
const defaultIncludeSpec = "**/*";
|
||||
|
||||
/**
|
||||
* Parse the contents of a config file from json or json source file (tsconfig.json).
|
||||
|
||||
+2
-112
@@ -17,8 +17,6 @@ import {
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
/** @internal */
|
||||
export const emptyMap: ReadonlyMap<never, never> = new Map<never, never>();
|
||||
/** @internal */
|
||||
export const emptySet: ReadonlySet<never> = new Set<never>();
|
||||
|
||||
/** @internal */
|
||||
export function length(array: readonly any[] | undefined): number {
|
||||
@@ -218,22 +216,6 @@ export function findLastIndex<T>(array: readonly T[] | undefined, predicate: (el
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first truthy result of `callback`, or else fails.
|
||||
* This is like `forEach`, but never returns undefined.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function findMap<T, U>(array: readonly T[], callback: (element: T, index: number) => U | undefined): U {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Debug.fail();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function contains<T>(array: readonly T[] | undefined, value: T, equalityComparer: EqualityComparer<T> = equateValues): boolean {
|
||||
if (array !== undefined) {
|
||||
@@ -827,17 +809,6 @@ export function sortAndDeduplicate<T>(array: readonly T[], comparer?: Comparer<T
|
||||
return deduplicateSorted(sort(array, comparer), equalityComparer ?? comparer ?? compareStringsCaseSensitive as any as Comparer<T>);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function arrayIsSorted<T>(array: readonly T[], comparer: Comparer<T>) {
|
||||
if (array.length < 2) return true;
|
||||
for (let i = 1, len = array.length; i < len; i++) {
|
||||
if (comparer(array[i - 1], array[i]) === Comparison.GreaterThan) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function arrayIsEqualTo<T>(array1: readonly T[] | undefined, array2: readonly T[] | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean {
|
||||
if (array1 === undefined || array2 === undefined) {
|
||||
@@ -1875,10 +1846,8 @@ export function identity<T>(x: T) {
|
||||
|
||||
/**
|
||||
* Returns lower case string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function toLowerCase(x: string) {
|
||||
function toLowerCase(x: string) {
|
||||
return x.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -1963,82 +1932,6 @@ export function memoizeOne<A extends string | number | boolean | undefined, T>(c
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of `memoize` that supports a single non-primitive argument, stored as keys of a WeakMap.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function memoizeWeak<A extends object, T>(callback: (arg: A) => T): (arg: A) => T {
|
||||
const map = new WeakMap<A, T>();
|
||||
return (arg: A) => {
|
||||
let value = map.get(arg);
|
||||
if (value === undefined && !map.has(arg)) {
|
||||
value = callback(arg);
|
||||
map.set(arg, value);
|
||||
}
|
||||
return value!;
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MemoizeCache<A extends any[], T> {
|
||||
has(args: A): boolean;
|
||||
get(args: A): T | undefined;
|
||||
set(args: A, value: T): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of `memoize` that supports multiple arguments, backed by a provided cache.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function memoizeCached<A extends any[], T>(callback: (...args: A) => T, cache: MemoizeCache<A, T>): (...args: A) => T {
|
||||
return (...args: A) => {
|
||||
let value = cache.get(args);
|
||||
if (value === undefined && !cache.has(args)) {
|
||||
value = callback(...args);
|
||||
cache.set(args, value);
|
||||
}
|
||||
return value!;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* High-order function, composes functions. Note that functions are composed inside-out;
|
||||
* for example, `compose(a, b)` is the equivalent of `x => b(a(x))`.
|
||||
*
|
||||
* @param args The functions to compose.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function compose<T>(...args: ((t: T) => T)[]): (t: T) => T;
|
||||
/** @internal */
|
||||
export function compose<T>(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T {
|
||||
if (!!e) {
|
||||
const args: ((t: T) => T)[] = [];
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
return t => reduceLeft(args, (u, f) => f(u), t);
|
||||
}
|
||||
else if (d) {
|
||||
return t => d(c(b(a(t))));
|
||||
}
|
||||
else if (c) {
|
||||
return t => c(b(a(t)));
|
||||
}
|
||||
else if (b) {
|
||||
return t => b(a(t));
|
||||
}
|
||||
else if (a) {
|
||||
return t => a(t);
|
||||
}
|
||||
else {
|
||||
return t => t;
|
||||
}
|
||||
}
|
||||
/** @internal */
|
||||
export const enum AssertionLevel {
|
||||
None = 0,
|
||||
@@ -2054,8 +1947,6 @@ export const enum AssertionLevel {
|
||||
* @internal
|
||||
*/
|
||||
export type AnyFunction = (...args: never[]) => void;
|
||||
/** @internal */
|
||||
export type AnyConstructor = new (...args: unknown[]) => unknown;
|
||||
|
||||
/** @internal */
|
||||
export function equateValues<T>(a: T, b: T) {
|
||||
@@ -2467,8 +2358,7 @@ export function orderedRemoveItemAt<T>(array: T[], index: number): void {
|
||||
array.pop();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function unorderedRemoveItemAt<T>(array: T[], index: number): void {
|
||||
function unorderedRemoveItemAt<T>(array: T[], index: number): void {
|
||||
// Fill in the "hole" left at `index`.
|
||||
array[index] = array[array.length - 1];
|
||||
array.pop();
|
||||
|
||||
@@ -33,16 +33,6 @@ export interface ReadonlyCollection<K> {
|
||||
keys(): IterableIterator<K>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common write methods for ES6 Map/Set.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export interface Collection<K> extends ReadonlyCollection<K> {
|
||||
delete(key: K): boolean;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type EqualityComparer<T> = (a: T, b: T) => boolean;
|
||||
|
||||
|
||||
@@ -1032,7 +1032,7 @@
|
||||
"category": "Error",
|
||||
"code": 1323
|
||||
},
|
||||
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', or 'nodenext'.": {
|
||||
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'nodenext', or 'preserve'.": {
|
||||
"category": "Error",
|
||||
"code": 1324
|
||||
},
|
||||
|
||||
@@ -503,8 +503,7 @@ export function canEmitTsBuildInfo(options: CompilerOptions) {
|
||||
return isIncrementalCompilation(options) || !!options.tscBuild;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: boolean): EmitFileNames {
|
||||
function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: boolean): EmitFileNames {
|
||||
const outPath = options.outFile!;
|
||||
const jsFilePath = options.emitDeclarationOnly ? undefined : outPath;
|
||||
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
|
||||
@@ -2089,7 +2088,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
// SyntaxKind.TemplateMiddle
|
||||
// SyntaxKind.TemplateTail
|
||||
function emitLiteral(node: LiteralLikeNode, jsxAttributeEscape: boolean) {
|
||||
const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape, jsxAttributeEscape);
|
||||
const text = getLiteralTextOfNode(node, /*sourceFile*/ undefined, printerOptions.neverAsciiEscape, jsxAttributeEscape);
|
||||
if (
|
||||
(printerOptions.sourceMap || printerOptions.inlineSourceMap)
|
||||
&& (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))
|
||||
@@ -2642,7 +2641,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
expression = skipPartiallyEmittedExpressions(expression);
|
||||
if (isNumericLiteral(expression)) {
|
||||
// check if numeric literal is a decimal literal that was originally written with a dot
|
||||
const text = getLiteralTextOfNode(expression as LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false);
|
||||
const text = getLiteralTextOfNode(expression as LiteralExpression, /*sourceFile*/ undefined, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false);
|
||||
// If the number will be printed verbatim and it doesn't already contain a dot or an exponent indicator, add one
|
||||
// if the expression doesn't have any comments that will be emitted.
|
||||
return !(expression.numericLiteralFlags & TokenFlags.WithSpecifier)
|
||||
@@ -5170,7 +5169,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia);
|
||||
}
|
||||
|
||||
function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
|
||||
function getLiteralTextOfNode(node: LiteralLikeNode, sourceFile = currentSourceFile, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
|
||||
if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) {
|
||||
const textSourceNode = (node as StringLiteral).textSourceNode!;
|
||||
if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) {
|
||||
@@ -5180,7 +5179,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
`"${escapeNonAsciiString(text)}"`;
|
||||
}
|
||||
else {
|
||||
return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape);
|
||||
return getLiteralTextOfNode(textSourceNode, getSourceFileOfNode(textSourceNode), neverAsciiEscape, jsxAttributeEscape);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5189,7 +5188,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
| (printerOptions.terminateUnterminatedLiterals ? GetLiteralTextFlags.TerminateUnterminatedLiterals : 0)
|
||||
| (printerOptions.target && printerOptions.target >= ScriptTarget.ES2021 ? GetLiteralTextFlags.AllowNumericSeparator : 0);
|
||||
|
||||
return getLiteralText(node, currentSourceFile, flags);
|
||||
return getLiteralText(node, sourceFile, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -696,10 +696,8 @@ export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) {
|
||||
/**
|
||||
* @param input Template string input strings
|
||||
* @param args Names which need to be made file-level unique
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function helperString(input: TemplateStringsArray, ...args: string[]) {
|
||||
function helperString(input: TemplateStringsArray, ...args: string[]) {
|
||||
return (uniqueName: EmitHelperUniqueNameCallback) => {
|
||||
let result = "";
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
@@ -713,8 +711,7 @@ export function helperString(input: TemplateStringsArray, ...args: string[]) {
|
||||
|
||||
// TypeScript Helpers
|
||||
|
||||
/** @internal */
|
||||
export const decorateHelper: UnscopedEmitHelper = {
|
||||
const decorateHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:decorate",
|
||||
importName: "__decorate",
|
||||
scoped: false,
|
||||
@@ -728,8 +725,7 @@ export const decorateHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const metadataHelper: UnscopedEmitHelper = {
|
||||
const metadataHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
importName: "__metadata",
|
||||
scoped: false,
|
||||
@@ -740,8 +736,7 @@ export const metadataHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const paramHelper: UnscopedEmitHelper = {
|
||||
const paramHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:param",
|
||||
importName: "__param",
|
||||
scoped: false,
|
||||
@@ -753,8 +748,7 @@ export const paramHelper: UnscopedEmitHelper = {
|
||||
};
|
||||
|
||||
// ES Decorators Helpers
|
||||
/** @internal */
|
||||
export const esDecorateHelper: UnscopedEmitHelper = {
|
||||
const esDecorateHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:esDecorate",
|
||||
importName: "__esDecorate",
|
||||
scoped: false,
|
||||
@@ -789,8 +783,7 @@ export const esDecorateHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const runInitializersHelper: UnscopedEmitHelper = {
|
||||
const runInitializersHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:runInitializers",
|
||||
importName: "__runInitializers",
|
||||
scoped: false,
|
||||
@@ -807,8 +800,7 @@ export const runInitializersHelper: UnscopedEmitHelper = {
|
||||
|
||||
// ES2018 Helpers
|
||||
|
||||
/** @internal */
|
||||
export const assignHelper: UnscopedEmitHelper = {
|
||||
const assignHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:assign",
|
||||
importName: "__assign",
|
||||
scoped: false,
|
||||
@@ -827,8 +819,7 @@ export const assignHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const awaitHelper: UnscopedEmitHelper = {
|
||||
const awaitHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:await",
|
||||
importName: "__await",
|
||||
scoped: false,
|
||||
@@ -836,8 +827,7 @@ export const awaitHelper: UnscopedEmitHelper = {
|
||||
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const asyncGeneratorHelper: UnscopedEmitHelper = {
|
||||
const asyncGeneratorHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncGenerator",
|
||||
importName: "__asyncGenerator",
|
||||
scoped: false,
|
||||
@@ -857,8 +847,7 @@ export const asyncGeneratorHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const asyncDelegator: UnscopedEmitHelper = {
|
||||
const asyncDelegator: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncDelegator",
|
||||
importName: "__asyncDelegator",
|
||||
scoped: false,
|
||||
@@ -871,8 +860,7 @@ export const asyncDelegator: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const asyncValues: UnscopedEmitHelper = {
|
||||
const asyncValues: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncValues",
|
||||
importName: "__asyncValues",
|
||||
scoped: false,
|
||||
@@ -888,8 +876,7 @@ export const asyncValues: UnscopedEmitHelper = {
|
||||
|
||||
// ES2018 Destructuring Helpers
|
||||
|
||||
/** @internal */
|
||||
export const restHelper: UnscopedEmitHelper = {
|
||||
const restHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:rest",
|
||||
importName: "__rest",
|
||||
scoped: false,
|
||||
@@ -909,8 +896,7 @@ export const restHelper: UnscopedEmitHelper = {
|
||||
|
||||
// ES2017 Helpers
|
||||
|
||||
/** @internal */
|
||||
export const awaiterHelper: UnscopedEmitHelper = {
|
||||
const awaiterHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
importName: "__awaiter",
|
||||
scoped: false,
|
||||
@@ -929,8 +915,7 @@ export const awaiterHelper: UnscopedEmitHelper = {
|
||||
|
||||
// ES2015 Helpers
|
||||
|
||||
/** @internal */
|
||||
export const extendsHelper: UnscopedEmitHelper = {
|
||||
const extendsHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:extends",
|
||||
importName: "__extends",
|
||||
scoped: false,
|
||||
@@ -954,8 +939,7 @@ export const extendsHelper: UnscopedEmitHelper = {
|
||||
})();`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const templateObjectHelper: UnscopedEmitHelper = {
|
||||
const templateObjectHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:makeTemplateObject",
|
||||
importName: "__makeTemplateObject",
|
||||
scoped: false,
|
||||
@@ -967,8 +951,7 @@ export const templateObjectHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const readHelper: UnscopedEmitHelper = {
|
||||
const readHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:read",
|
||||
importName: "__read",
|
||||
scoped: false,
|
||||
@@ -991,8 +974,7 @@ export const readHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const spreadArrayHelper: UnscopedEmitHelper = {
|
||||
const spreadArrayHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:spreadArray",
|
||||
importName: "__spreadArray",
|
||||
scoped: false,
|
||||
@@ -1008,8 +990,7 @@ export const spreadArrayHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const propKeyHelper: UnscopedEmitHelper = {
|
||||
const propKeyHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:propKey",
|
||||
importName: "__propKey",
|
||||
scoped: false,
|
||||
@@ -1020,8 +1001,7 @@ export const propKeyHelper: UnscopedEmitHelper = {
|
||||
};
|
||||
|
||||
// https://tc39.es/ecma262/#sec-setfunctionname
|
||||
/** @internal */
|
||||
export const setFunctionNameHelper: UnscopedEmitHelper = {
|
||||
const setFunctionNameHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:setFunctionName",
|
||||
importName: "__setFunctionName",
|
||||
scoped: false,
|
||||
@@ -1034,8 +1014,7 @@ export const setFunctionNameHelper: UnscopedEmitHelper = {
|
||||
|
||||
// ES2015 Destructuring Helpers
|
||||
|
||||
/** @internal */
|
||||
export const valuesHelper: UnscopedEmitHelper = {
|
||||
const valuesHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:values",
|
||||
importName: "__values",
|
||||
scoped: false,
|
||||
@@ -1116,8 +1095,7 @@ export const valuesHelper: UnscopedEmitHelper = {
|
||||
// entering a finally block.
|
||||
//
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
/** @internal */
|
||||
export const generatorHelper: UnscopedEmitHelper = {
|
||||
const generatorHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:generator",
|
||||
importName: "__generator",
|
||||
scoped: false,
|
||||
@@ -1154,8 +1132,7 @@ export const generatorHelper: UnscopedEmitHelper = {
|
||||
|
||||
// ES Module Helpers
|
||||
|
||||
/** @internal */
|
||||
export const createBindingHelper: UnscopedEmitHelper = {
|
||||
const createBindingHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjscreatebinding",
|
||||
importName: "__createBinding",
|
||||
scoped: false,
|
||||
@@ -1174,8 +1151,7 @@ export const createBindingHelper: UnscopedEmitHelper = {
|
||||
}));`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const setModuleDefaultHelper: UnscopedEmitHelper = {
|
||||
const setModuleDefaultHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjscreatevalue",
|
||||
importName: "__setModuleDefault",
|
||||
scoped: false,
|
||||
@@ -1189,8 +1165,7 @@ export const setModuleDefaultHelper: UnscopedEmitHelper = {
|
||||
};
|
||||
|
||||
// emit helper for `import * as Name from "foo"`
|
||||
/** @internal */
|
||||
export const importStarHelper: UnscopedEmitHelper = {
|
||||
const importStarHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportstar",
|
||||
importName: "__importStar",
|
||||
scoped: false,
|
||||
@@ -1207,8 +1182,7 @@ export const importStarHelper: UnscopedEmitHelper = {
|
||||
};
|
||||
|
||||
// emit helper for `import Name from "foo"`
|
||||
/** @internal */
|
||||
export const importDefaultHelper: UnscopedEmitHelper = {
|
||||
const importDefaultHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportdefault",
|
||||
importName: "__importDefault",
|
||||
scoped: false,
|
||||
@@ -1218,8 +1192,7 @@ export const importDefaultHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export const exportStarHelper: UnscopedEmitHelper = {
|
||||
const exportStarHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:export-star",
|
||||
importName: "__exportStar",
|
||||
scoped: false,
|
||||
@@ -1278,10 +1251,8 @@ export const exportStarHelper: UnscopedEmitHelper = {
|
||||
*
|
||||
* Reading from a private static method (TS 4.3+):
|
||||
* __classPrivateFieldGet(<any>, <constructor>, "m", <function>)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
|
||||
const classPrivateFieldGetHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:classPrivateFieldGet",
|
||||
importName: "__classPrivateFieldGet",
|
||||
scoped: false,
|
||||
@@ -1343,10 +1314,8 @@ export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
|
||||
* Writing to a private static method (TS 4.3+):
|
||||
* __classPrivateFieldSet(<any>, <constructor>, <any>, "m", <function>)
|
||||
* NOTE: This always results in a runtime error.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const classPrivateFieldSetHelper: UnscopedEmitHelper = {
|
||||
const classPrivateFieldSetHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:classPrivateFieldSet",
|
||||
importName: "__classPrivateFieldSet",
|
||||
scoped: false,
|
||||
@@ -1370,10 +1339,8 @@ export const classPrivateFieldSetHelper: UnscopedEmitHelper = {
|
||||
* Usage:
|
||||
* This helper is used to transform `#field in expression` to
|
||||
* `__classPrivateFieldIn(<weakMap/weakSet/constructor>, expression)`
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const classPrivateFieldInHelper: UnscopedEmitHelper = {
|
||||
const classPrivateFieldInHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:classPrivateFieldIn",
|
||||
importName: "__classPrivateFieldIn",
|
||||
scoped: false,
|
||||
@@ -1384,10 +1351,7 @@ export const classPrivateFieldInHelper: UnscopedEmitHelper = {
|
||||
};`,
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const addDisposableResourceHelper: UnscopedEmitHelper = {
|
||||
const addDisposableResourceHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:addDisposableResource",
|
||||
importName: "__addDisposableResource",
|
||||
scoped: false,
|
||||
@@ -1417,9 +1381,11 @@ export const addDisposableResourceHelper: UnscopedEmitHelper = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* The `s` variable represents two boolean flags from the `DisposeResources` algorithm:
|
||||
* - `needsAwait` (`1`) — Indicates that an `await using` for a `null` or `undefined` resource was encountered.
|
||||
* - `hasAwaited` (`2`) — Indicates that the algorithm has performed an Await.
|
||||
*/
|
||||
export const disposeResourcesHelper: UnscopedEmitHelper = {
|
||||
const disposeResourcesHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:disposeResources",
|
||||
importName: "__disposeResources",
|
||||
scoped: false,
|
||||
@@ -1430,17 +1396,22 @@ export const disposeResourcesHelper: UnscopedEmitHelper = {
|
||||
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
||||
env.hasError = true;
|
||||
}
|
||||
var r, s = 0;
|
||||
function next() {
|
||||
while (env.stack.length) {
|
||||
var rec = env.stack.pop();
|
||||
while (r = env.stack.pop()) {
|
||||
try {
|
||||
var result = rec.dispose && rec.dispose.call(rec.value);
|
||||
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
||||
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
||||
if (r.dispose) {
|
||||
var result = r.dispose.call(r.value);
|
||||
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
||||
}
|
||||
else s |= 1;
|
||||
}
|
||||
catch (e) {
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
||||
if (env.hasError) throw env.error;
|
||||
}
|
||||
return next();
|
||||
|
||||
@@ -364,7 +364,7 @@ export function setIdentifierAutoGenerate<T extends Identifier | PrivateIdentifi
|
||||
return node;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function getIdentifierAutoGenerate(node: Identifier | PrivateIdentifier): AutoGenerateInfo | undefined {
|
||||
return node.emitNode?.autoGenerate;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,61 @@
|
||||
import {
|
||||
Debug,
|
||||
emptyArray,
|
||||
isNodeKind,
|
||||
Node,
|
||||
SourceFileLike,
|
||||
SyntaxKind,
|
||||
SyntaxList,
|
||||
} from "../_namespaces/ts.js";
|
||||
|
||||
const nodeChildren = new WeakMap<Node, readonly Node[] | undefined>();
|
||||
const sourceFileToNodeChildren = new WeakMap<SourceFileLike, WeakMap<Node, readonly Node[] | undefined>>();
|
||||
|
||||
/** @internal */
|
||||
export function getNodeChildren(node: Node): readonly Node[] | undefined {
|
||||
if (!isNodeKind(node.kind)) return emptyArray;
|
||||
export function getNodeChildren(node: Node, sourceFile: SourceFileLike): readonly Node[] | undefined {
|
||||
const kind = node.kind;
|
||||
if (!isNodeKind(kind)) {
|
||||
return emptyArray;
|
||||
}
|
||||
if (kind === SyntaxKind.SyntaxList) {
|
||||
return (node as SyntaxList)._children;
|
||||
}
|
||||
|
||||
return nodeChildren.get(node);
|
||||
return sourceFileToNodeChildren.get(sourceFile)?.get(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function setNodeChildren(node: Node, children: readonly Node[]): readonly Node[] {
|
||||
nodeChildren.set(node, children);
|
||||
export function setNodeChildren(node: Node, sourceFile: SourceFileLike, children: readonly Node[]): readonly Node[] {
|
||||
if (node.kind === SyntaxKind.SyntaxList) {
|
||||
// SyntaxList children are always eagerly created in the process of
|
||||
// creating their parent's `children` list. We shouldn't need to set them here.
|
||||
Debug.fail("Should not need to re-set the children of a SyntaxList.");
|
||||
}
|
||||
|
||||
let map = sourceFileToNodeChildren.get(sourceFile);
|
||||
if (map === undefined) {
|
||||
map = new WeakMap();
|
||||
sourceFileToNodeChildren.set(sourceFile, map);
|
||||
}
|
||||
map.set(node, children);
|
||||
return children;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function unsetNodeChildren(node: Node) {
|
||||
nodeChildren.delete(node);
|
||||
export function unsetNodeChildren(node: Node, origSourceFile: SourceFileLike) {
|
||||
if (node.kind === SyntaxKind.SyntaxList) {
|
||||
// Syntax lists are synthesized and we store their children directly on them.
|
||||
// They are a special case where we expect incremental parsing to toss them away entirely
|
||||
// if a change intersects with their containing parents.
|
||||
Debug.fail("Did not expect to unset the children of a SyntaxList.");
|
||||
}
|
||||
sourceFileToNodeChildren.get(origSourceFile)?.delete(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function transferSourceFileChildren(sourceFile: SourceFileLike, targetSourceFile: SourceFileLike) {
|
||||
const map = sourceFileToNodeChildren.get(sourceFile);
|
||||
if (map !== undefined) {
|
||||
sourceFileToNodeChildren.delete(sourceFile);
|
||||
sourceFileToNodeChildren.set(targetSourceFile, map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +389,6 @@ import {
|
||||
setEmitFlags,
|
||||
setIdentifierAutoGenerate,
|
||||
setIdentifierTypeArguments,
|
||||
setNodeChildren,
|
||||
setParent,
|
||||
setTextRange,
|
||||
ShorthandPropertyAssignment,
|
||||
@@ -477,7 +476,7 @@ export const enum NodeFactoryFlags {
|
||||
|
||||
const nodeFactoryPatchers: ((factory: NodeFactory) => void)[] = [];
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) {
|
||||
nodeFactoryPatchers.push(fn);
|
||||
}
|
||||
@@ -6221,7 +6220,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
// @api
|
||||
function createSyntaxList(children: readonly Node[]) {
|
||||
const node = createBaseNode<SyntaxList>(SyntaxKind.SyntaxList);
|
||||
setNodeChildren(node, children);
|
||||
node._children = children;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -7304,10 +7303,8 @@ function aggregateChildrenFlags(children: MutableNodeArray<Node>) {
|
||||
|
||||
/**
|
||||
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
|
||||
function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
|
||||
if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
|
||||
return TransformFlags.TypeExcludes;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ import {
|
||||
BindingOrAssignmentPattern,
|
||||
BitwiseOperator,
|
||||
BitwiseOperatorOrHigher,
|
||||
Block,
|
||||
BooleanLiteral,
|
||||
CharacterCodes,
|
||||
CommaListExpression,
|
||||
compareStringsCaseSensitive,
|
||||
@@ -78,7 +76,6 @@ import {
|
||||
isAssignmentExpression,
|
||||
isAssignmentOperator,
|
||||
isAssignmentPattern,
|
||||
isBlock,
|
||||
isCommaListExpression,
|
||||
isComputedPropertyName,
|
||||
isDeclarationBindingElement,
|
||||
@@ -91,10 +88,8 @@ import {
|
||||
isGeneratedPrivateIdentifier,
|
||||
isIdentifier,
|
||||
isInJSFile,
|
||||
isLiteralExpression,
|
||||
isMemberName,
|
||||
isMinusToken,
|
||||
isModifierKind,
|
||||
isObjectLiteralElementLike,
|
||||
isParenthesizedExpression,
|
||||
isPlusToken,
|
||||
@@ -139,7 +134,6 @@ import {
|
||||
NodeArray,
|
||||
NodeFactory,
|
||||
nodeIsSynthesized,
|
||||
NullLiteral,
|
||||
NumericLiteral,
|
||||
ObjectLiteralElementLike,
|
||||
ObjectLiteralExpression,
|
||||
@@ -333,16 +327,6 @@ export function createForOfBindingStatement(factory: NodeFactory, node: ForIniti
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement): Block {
|
||||
if (isBlock(dest)) {
|
||||
return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements));
|
||||
}
|
||||
else {
|
||||
return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression {
|
||||
if (isQualifiedName(node)) {
|
||||
@@ -679,15 +663,6 @@ export function walkUpOuterExpressions(node: Expression, kinds = OuterExpression
|
||||
return parent;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function skipAssertions(node: Expression): Expression;
|
||||
/** @internal */
|
||||
export function skipAssertions(node: Node): Node;
|
||||
/** @internal */
|
||||
export function skipAssertions(node: Node): Node {
|
||||
return skipOuterExpressions(node, OuterExpressionKinds.Assertions);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function startOnNewLine<T extends Node>(node: T): T {
|
||||
return setStartsOnNewLine(node, /*newLine*/ true);
|
||||
@@ -761,8 +736,7 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
|
||||
function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
|
||||
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(node);
|
||||
if (externalHelpersModuleName) {
|
||||
@@ -1116,7 +1090,7 @@ export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined)
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function canHaveIllegalType(node: Node): node is HasIllegalType {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Constructor
|
||||
@@ -1183,16 +1157,6 @@ export function isModuleName(node: Node): node is ModuleName {
|
||||
return isIdentifier(node) || isStringLiteral(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isLiteralTypeLikeExpression(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.NullKeyword
|
||||
|| kind === SyntaxKind.TrueKeyword
|
||||
|| kind === SyntaxKind.FalseKeyword
|
||||
|| isLiteralExpression(node)
|
||||
|| isPrefixUnaryExpression(node);
|
||||
}
|
||||
|
||||
function isExponentiationOperator(kind: SyntaxKind): kind is ExponentiationOperator {
|
||||
return kind === SyntaxKind.AsteriskAsteriskToken;
|
||||
}
|
||||
@@ -1521,12 +1485,6 @@ export function isExportOrDefaultModifier(node: Node): node is ExportKeyword | D
|
||||
return isExportOrDefaultKeywordKind(kind);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNonExportDefaultModifier(node: Node): node is Exclude<Modifier, ExportKeyword | DefaultKeyword> {
|
||||
const kind = node.kind;
|
||||
return isModifierKind(kind) && !isExportOrDefaultKeywordKind(kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `nodes` is not undefined, creates an empty `NodeArray` that preserves the `pos` and `end` of `nodes`.
|
||||
* @internal
|
||||
|
||||
@@ -967,8 +967,7 @@ export interface CacheWithRedirects<K, V> {
|
||||
/** @internal */
|
||||
export type RedirectsCacheKey = string & { __compilerOptionsKey: any; };
|
||||
|
||||
/** @internal */
|
||||
export function createCacheWithRedirects<K, V>(ownOptions: CompilerOptions | undefined, optionsToRedirectsKey: Map<CompilerOptions, RedirectsCacheKey>): CacheWithRedirects<K, V> {
|
||||
function createCacheWithRedirects<K, V>(ownOptions: CompilerOptions | undefined, optionsToRedirectsKey: Map<CompilerOptions, RedirectsCacheKey>): CacheWithRedirects<K, V> {
|
||||
const redirectsMap = new Map<CompilerOptions, Map<K, V>>();
|
||||
const redirectsKeyToMap = new Map<RedirectsCacheKey, Map<K, V>>();
|
||||
let ownMap = new Map<K, V>();
|
||||
@@ -1752,8 +1751,10 @@ function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host:
|
||||
/*conditions*/ undefined,
|
||||
);
|
||||
}
|
||||
|
||||
// knip applies the internal marker to _all_ declarations, not just the one overload.
|
||||
export function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, conditions?: string[]): ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures
|
||||
export function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, conditions?: string[]): ResolvedModuleWithFailedLookupLocations {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
@@ -2432,8 +2433,7 @@ function readPackageJsonPeerDependencies(packageJsonInfo: PackageJsonInfo, state
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined {
|
||||
function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined {
|
||||
const { host, traceEnabled } = state;
|
||||
const packageJsonPath = combinePaths(packageDirectory, "package.json");
|
||||
if (onlyRecordFailures) {
|
||||
|
||||
+10
-7
@@ -369,6 +369,7 @@ import {
|
||||
tokenIsIdentifierOrKeywordOrGreaterThan,
|
||||
tokenToString,
|
||||
tracing,
|
||||
transferSourceFileChildren,
|
||||
TransformFlags,
|
||||
TryStatement,
|
||||
TupleTypeNode,
|
||||
@@ -424,6 +425,7 @@ let SourceFileConstructor: new (kind: SyntaxKind.SourceFile, pos: number, end: n
|
||||
* NOTE: You should not use this, it is only exported to support `createNode` in `~/src/deprecatedCompat/deprecations.ts`.
|
||||
*
|
||||
* @internal
|
||||
* @knipignore
|
||||
*/
|
||||
export const parseBaseNodeFactory: BaseNodeFactory = {
|
||||
createBaseSourceFileNode: kind => new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, -1, -1),
|
||||
@@ -9972,6 +9974,7 @@ namespace IncrementalParser {
|
||||
aggressiveChecks,
|
||||
);
|
||||
result.impliedNodeFormat = sourceFile.impliedNodeFormat;
|
||||
transferSourceFileChildren(sourceFile, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -10024,9 +10027,9 @@ namespace IncrementalParser {
|
||||
}
|
||||
}
|
||||
|
||||
function moveElementEntirelyPastChangeRange(element: Node, isArray: false, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void;
|
||||
function moveElementEntirelyPastChangeRange(element: NodeArray<Node>, isArray: true, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void;
|
||||
function moveElementEntirelyPastChangeRange(element: Node | NodeArray<Node>, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
|
||||
function moveElementEntirelyPastChangeRange(element: Node, origSourceFile: SourceFile, isArray: false, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void;
|
||||
function moveElementEntirelyPastChangeRange(element: NodeArray<Node>, origSourceFile: SourceFile, isArray: true, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void;
|
||||
function moveElementEntirelyPastChangeRange(element: Node | NodeArray<Node>, origSourceFile: SourceFile, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
|
||||
if (isArray) {
|
||||
visitArray(element as NodeArray<Node>);
|
||||
}
|
||||
@@ -10043,7 +10046,7 @@ namespace IncrementalParser {
|
||||
|
||||
// Ditch any existing LS children we may have created. This way we can avoid
|
||||
// moving them forward.
|
||||
unsetNodeChildren(node);
|
||||
unsetNodeChildren(node, origSourceFile);
|
||||
|
||||
setTextRangePosEnd(node, node.pos + delta, node.end + delta);
|
||||
|
||||
@@ -10190,7 +10193,7 @@ namespace IncrementalParser {
|
||||
if (child.pos > changeRangeOldEnd) {
|
||||
// Node is entirely past the change range. We need to move both its pos and
|
||||
// end, forward or backward appropriately.
|
||||
moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks);
|
||||
moveElementEntirelyPastChangeRange(child, sourceFile, /*isArray*/ false, delta, oldText, newText, aggressiveChecks);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10200,7 +10203,7 @@ namespace IncrementalParser {
|
||||
const fullEnd = child.end;
|
||||
if (fullEnd >= changeStart) {
|
||||
markAsIntersectingIncrementalChange(child);
|
||||
unsetNodeChildren(child);
|
||||
unsetNodeChildren(child, sourceFile);
|
||||
|
||||
// Adjust the pos or end (or both) of the intersecting element accordingly.
|
||||
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
|
||||
@@ -10223,7 +10226,7 @@ namespace IncrementalParser {
|
||||
if (array.pos > changeRangeOldEnd) {
|
||||
// Array is entirely after the change range. We need to move it, and move any of
|
||||
// its children.
|
||||
moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks);
|
||||
moveElementEntirelyPastChangeRange(array, sourceFile, /*isArray*/ true, delta, oldText, newText, aggressiveChecks);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -907,8 +907,7 @@ export function startsWithDirectory(fileName: string, directoryName: string, get
|
||||
|
||||
//// Relative Paths
|
||||
|
||||
/** @internal */
|
||||
export function getPathComponentsRelativeTo(from: string, to: string, stringEqualityComparer: (a: string, b: string) => boolean, getCanonicalFileName: GetCanonicalFileName) {
|
||||
function getPathComponentsRelativeTo(from: string, to: string, stringEqualityComparer: (a: string, b: string) => boolean, getCanonicalFileName: GetCanonicalFileName) {
|
||||
const fromComponents = reducePathComponents(getPathComponents(from));
|
||||
const toComponents = reducePathComponents(getPathComponents(to));
|
||||
|
||||
|
||||
+214
-241
@@ -140,6 +140,8 @@ import {
|
||||
getPathFromPathComponents,
|
||||
getPositionOfLineAndCharacter,
|
||||
getPropertyArrayElementValue,
|
||||
getResolvedModuleFromResolution,
|
||||
getResolvedTypeReferenceDirectiveFromResolution,
|
||||
getResolveJsonModule,
|
||||
getRootLength,
|
||||
getSetExternalModuleIndicator,
|
||||
@@ -902,7 +904,7 @@ export function getModeForUsageLocation(file: { impliedNodeFormat?: ResolutionMo
|
||||
}
|
||||
|
||||
function getModeForUsageLocationWorker(file: { impliedNodeFormat?: ResolutionMode; }, usage: StringLiteralLike, compilerOptions?: CompilerOptions) {
|
||||
if ((isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent))) {
|
||||
if (isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent) || isJSDocImportTag(usage.parent)) {
|
||||
const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage.parent);
|
||||
if (isTypeOnly) {
|
||||
const override = getResolutionModeOverride(usage.parent.attributes);
|
||||
@@ -969,6 +971,12 @@ const emptyResolution: ResolvedModuleWithFailedLookupLocations & ResolvedTypeRef
|
||||
resolvedTypeReferenceDirective: undefined,
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export interface ResolutionWithResolvedFileName {
|
||||
resolvedFileName: string | undefined;
|
||||
packageId?: PackageId;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ResolutionNameAndModeGetter<Entry, SourceFile> {
|
||||
getName(entry: Entry): string;
|
||||
@@ -1157,11 +1165,6 @@ function getLibFileNameFromLibReference(libReference: FileReference) {
|
||||
return libMap.get(libName);
|
||||
}
|
||||
|
||||
interface DiagnosticCache<T extends Diagnostic> {
|
||||
perFile?: Map<Path, readonly T[]>;
|
||||
allDiagnostics?: readonly T[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isReferencedFile(reason: FileIncludeReason | undefined): reason is ReferencedFile {
|
||||
switch (reason?.kind) {
|
||||
@@ -1366,8 +1369,7 @@ export function getImpliedNodeFormatForFileWorker(
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const plainJSErrors = new Set<number>([
|
||||
const plainJSErrors = new Set<number>([
|
||||
// binder errors
|
||||
Diagnostics.Cannot_redeclare_block_scoped_variable_0.code,
|
||||
Diagnostics.A_module_cannot_have_multiple_default_exports.code,
|
||||
@@ -1548,8 +1550,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
let filesWithReferencesProcessed: Set<Path> | undefined;
|
||||
let fileReasonsToChain: Map<Path, FileReasonToChainCache> | undefined;
|
||||
let reasonToRelatedInfo: Map<FileIncludeReason, DiagnosticWithLocation | false> | undefined;
|
||||
const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
|
||||
let cachedBindAndCheckDiagnosticsForFile: Map<Path, readonly Diagnostic[]> | undefined;
|
||||
let cachedDeclarationDiagnosticsForFile: Map<Path, readonly DiagnosticWithLocation[]> | undefined;
|
||||
|
||||
let fileProcessingDiagnostics: FilePreprocessingDiagnostics[] | undefined;
|
||||
let automaticTypeDirectiveNames: string[] | undefined;
|
||||
@@ -1858,13 +1860,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
// old file wasn't redirect but new file is
|
||||
(oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path)
|
||||
) {
|
||||
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path));
|
||||
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path), newFile);
|
||||
}
|
||||
}
|
||||
if (!host.getParsedCommandLine) {
|
||||
oldProgram.forEachResolvedProjectReference(resolvedProjectReference => {
|
||||
if (!getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) {
|
||||
host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false);
|
||||
host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false, /*newSourceFileByResolvedPath*/ undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2111,27 +2113,47 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (fromCache) addResolutionDiagnostics(fromCache);
|
||||
}
|
||||
|
||||
function resolveModuleNamesWorker(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile, reusedNames: readonly StringLiteralLike[] | undefined): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
if (!moduleNames.length) return emptyArray;
|
||||
function resolveModuleNamesWorker(
|
||||
moduleNames: readonly StringLiteralLike[],
|
||||
containingFile: SourceFile,
|
||||
reusedNames: readonly StringLiteralLike[] | undefined,
|
||||
): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory);
|
||||
const redirectedReference = getRedirectReferenceForResolution(containingFile);
|
||||
tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName });
|
||||
performance.mark("beforeResolveModule");
|
||||
const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, redirectedReference, options, containingFile, reusedNames);
|
||||
const result = actualResolveModuleNamesWorker(
|
||||
moduleNames,
|
||||
containingFileName,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingFile,
|
||||
reusedNames,
|
||||
);
|
||||
performance.mark("afterResolveModule");
|
||||
performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule");
|
||||
tracing?.pop();
|
||||
return result;
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirectiveNamesWorker<T extends FileReference | string>(typeDirectiveNames: readonly T[], containingFile: string | SourceFile, reusedNames: readonly T[] | undefined): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
|
||||
if (!typeDirectiveNames.length) return [];
|
||||
function resolveTypeReferenceDirectiveNamesWorker<T extends FileReference | string>(
|
||||
typeDirectiveNames: readonly T[],
|
||||
containingFile: string | SourceFile,
|
||||
reusedNames: readonly T[] | undefined,
|
||||
): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
|
||||
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
|
||||
const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile;
|
||||
const redirectedReference = containingSourceFile && getRedirectReferenceForResolution(containingSourceFile);
|
||||
tracing?.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName });
|
||||
performance.mark("beforeResolveTypeReference");
|
||||
const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, options, containingSourceFile, reusedNames);
|
||||
const result = actualResolveTypeReferenceDirectiveNamesWorker(
|
||||
typeDirectiveNames,
|
||||
containingFileName,
|
||||
redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
reusedNames,
|
||||
);
|
||||
performance.mark("afterResolveTypeReference");
|
||||
performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference");
|
||||
tracing?.pop();
|
||||
@@ -2215,201 +2237,177 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return classifiableNames;
|
||||
}
|
||||
|
||||
function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], file: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
if (structureIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) {
|
||||
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
|
||||
// the best we can do is fallback to the default logic.
|
||||
return resolveModuleNamesWorker(moduleNames, file, /*reusedNames*/ undefined);
|
||||
}
|
||||
|
||||
// At this point, we know at least one of the following hold:
|
||||
// - file has local declarations for ambient modules
|
||||
// - old program state is available
|
||||
// With this information, we can infer some module resolutions without performing resolution.
|
||||
|
||||
/** An ordered list of module names for which we cannot recover the resolution. */
|
||||
let unknownModuleNames: StringLiteralLike[] | undefined;
|
||||
/**
|
||||
* The indexing of elements in this list matches that of `moduleNames`.
|
||||
*
|
||||
* Before combining results, result[i] is in one of the following states:
|
||||
* * undefined: needs to be recomputed,
|
||||
* * predictedToResolveToAmbientModuleMarker: known to be an ambient module.
|
||||
* Needs to be reset to undefined before returning,
|
||||
* * ResolvedModuleFull instance: can be reused.
|
||||
*/
|
||||
let result: ResolvedModuleWithFailedLookupLocations[] | undefined;
|
||||
let reusedNames: StringLiteralLike[] | undefined;
|
||||
/** A transient placeholder used to mark predicted resolution in the result list. */
|
||||
const predictedToResolveToAmbientModuleMarker: ResolvedModuleWithFailedLookupLocations = emptyResolution;
|
||||
const oldSourceFile = oldProgram && oldProgram.getSourceFile(file.fileName);
|
||||
|
||||
for (let i = 0; i < moduleNames.length; i++) {
|
||||
const moduleName = moduleNames[i];
|
||||
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
|
||||
if (file === oldSourceFile && !hasInvalidatedResolutions(file.path)) {
|
||||
const oldResolution = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName));
|
||||
if (oldResolution?.resolvedModule) {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(
|
||||
host,
|
||||
oldResolution.resolvedModule.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2,
|
||||
moduleName.text,
|
||||
getNormalizedAbsolutePath(file.originalFileName, currentDirectory),
|
||||
oldResolution.resolvedModule.resolvedFileName,
|
||||
oldResolution.resolvedModule.packageId && packageIdToString(oldResolution.resolvedModule.packageId),
|
||||
);
|
||||
}
|
||||
(result ??= new Array(moduleNames.length))[i] = oldResolution;
|
||||
(reusedNames ??= []).push(moduleName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// We know moduleName resolves to an ambient module provided that moduleName:
|
||||
// - is in the list of ambient modules locally declared in the current source file.
|
||||
// - resolved to an ambient module in the old program whose declaration is in an unmodified file
|
||||
// (so the same module declaration will land in the new program)
|
||||
let resolvesToAmbientModuleInNonModifiedFile = false;
|
||||
if (contains(file.ambientModuleNames, moduleName.text)) {
|
||||
resolvesToAmbientModuleInNonModifiedFile = true;
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory));
|
||||
}
|
||||
}
|
||||
else {
|
||||
resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName);
|
||||
}
|
||||
|
||||
if (resolvesToAmbientModuleInNonModifiedFile) {
|
||||
(result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker;
|
||||
}
|
||||
else {
|
||||
// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
|
||||
(unknownModuleNames ??= []).push(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
const resolutions = unknownModuleNames && unknownModuleNames.length
|
||||
? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames)
|
||||
: emptyArray;
|
||||
|
||||
// Combine results of resolutions and predicted results
|
||||
if (!result) {
|
||||
// There were no unresolved/ambient resolutions.
|
||||
Debug.assert(resolutions.length === moduleNames.length);
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
let j = 0;
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (!result[i]) {
|
||||
result[i] = resolutions[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
Debug.assert(j === resolutions.length);
|
||||
|
||||
return result;
|
||||
|
||||
// If we change our policy of rechecking failed lookups on each program create,
|
||||
// we should adjust the value returned here.
|
||||
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike): boolean {
|
||||
const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule;
|
||||
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
|
||||
if (resolutionToFile && resolvedFile) {
|
||||
// In the old program, we resolved to an ambient module that was in the same
|
||||
// place as we expected to find an actual module file.
|
||||
// We actually need to return 'false' here even though this seems like a 'true' case
|
||||
// because the normal module resolution algorithm will find this anyway.
|
||||
return false;
|
||||
}
|
||||
|
||||
// at least one of declarations should come from non-modified source file
|
||||
const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text);
|
||||
|
||||
if (!unmodifiedFile) {
|
||||
return false;
|
||||
}
|
||||
function resolveModuleNamesReusingOldState(moduleNames: readonly StringLiteralLike[], containingFile: SourceFile): readonly ResolvedModuleWithFailedLookupLocations[] {
|
||||
return resolveNamesReusingOldState({
|
||||
entries: moduleNames,
|
||||
containingFile,
|
||||
containingSourceFile: containingFile,
|
||||
redirectedReference: getRedirectReferenceForResolution(containingFile),
|
||||
nameAndModeGetter: moduleResolutionNameAndModeGetter,
|
||||
resolutionWorker: resolveModuleNamesWorker,
|
||||
getResolutionFromOldProgram: (name, mode) => oldProgram?.getResolvedModule(containingFile, name, mode),
|
||||
getResolved: getResolvedModuleFromResolution,
|
||||
canReuseResolutionsInFile: () =>
|
||||
containingFile === oldProgram?.getSourceFile(containingFile.fileName) &&
|
||||
!hasInvalidatedResolutions(containingFile.path),
|
||||
isEntryResolvingToAmbientModule: moduleNameResolvesToAmbientModule,
|
||||
});
|
||||
}
|
||||
|
||||
function moduleNameResolvesToAmbientModule(moduleName: StringLiteralLike, file: SourceFile) {
|
||||
// We know moduleName resolves to an ambient module provided that moduleName:
|
||||
// - is in the list of ambient modules locally declared in the current source file.
|
||||
// - resolved to an ambient module in the old program whose declaration is in an unmodified file
|
||||
// (so the same module declaration will land in the new program)
|
||||
if (contains(file.ambientModuleNames, moduleName.text)) {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile);
|
||||
trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName.text, getNormalizedAbsolutePath(file.originalFileName, currentDirectory));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, file);
|
||||
}
|
||||
}
|
||||
|
||||
// If we change our policy of rechecking failed lookups on each program create,
|
||||
// we should adjust the value returned here.
|
||||
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: StringLiteralLike, file: SourceFile): boolean {
|
||||
const resolutionToFile = oldProgram?.getResolvedModule(file, moduleName.text, getModeForUsageLocation(file, moduleName))?.resolvedModule;
|
||||
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
|
||||
if (resolutionToFile && resolvedFile) {
|
||||
// In the old program, we resolved to an ambient module that was in the same
|
||||
// place as we expected to find an actual module file.
|
||||
// We actually need to return 'false' here even though this seems like a 'true' case
|
||||
// because the normal module resolution algorithm will find this anyway.
|
||||
return false;
|
||||
}
|
||||
|
||||
// at least one of declarations should come from non-modified source file
|
||||
const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName.text);
|
||||
|
||||
if (!unmodifiedFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName.text, unmodifiedFile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly FileReference[], containingFile: SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState(typeDirectiveNames: readonly string[], containingFile: string): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[];
|
||||
function resolveTypeReferenceDirectiveNamesReusingOldState<T extends string | FileReference>(typeDirectiveNames: readonly T[], containingFile: string | SourceFile): readonly ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] {
|
||||
if (structureIsReused === StructureIsReused.Not) {
|
||||
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
|
||||
return resolveNamesReusingOldState({
|
||||
entries: typeDirectiveNames,
|
||||
containingFile,
|
||||
containingSourceFile,
|
||||
redirectedReference: containingSourceFile && getRedirectReferenceForResolution(containingSourceFile),
|
||||
nameAndModeGetter: typeReferenceResolutionNameAndModeGetter,
|
||||
resolutionWorker: resolveTypeReferenceDirectiveNamesWorker,
|
||||
getResolutionFromOldProgram: (name, mode) =>
|
||||
containingSourceFile ?
|
||||
oldProgram?.getResolvedTypeReferenceDirective(containingSourceFile, name, mode) :
|
||||
oldProgram?.getAutomaticTypeDirectiveResolutions()?.get(name, mode),
|
||||
getResolved: getResolvedTypeReferenceDirectiveFromResolution,
|
||||
canReuseResolutionsInFile: () =>
|
||||
containingSourceFile ?
|
||||
containingSourceFile === oldProgram?.getSourceFile(containingSourceFile.fileName) && !hasInvalidatedResolutions(containingSourceFile.path) :
|
||||
!hasInvalidatedResolutions(toPath(containingFile as string)),
|
||||
});
|
||||
}
|
||||
|
||||
interface ResolveNamesReusingOldStateInput<Entry, SourceFileOrString, SourceFileOrUndefined extends SourceFile | undefined, Resolution> {
|
||||
entries: readonly Entry[];
|
||||
containingFile: SourceFileOrString;
|
||||
containingSourceFile: SourceFileOrUndefined;
|
||||
redirectedReference: ResolvedProjectReference | undefined;
|
||||
nameAndModeGetter: ResolutionNameAndModeGetter<Entry, SourceFileOrUndefined>;
|
||||
resolutionWorker: (
|
||||
entries: readonly Entry[],
|
||||
containingFile: SourceFileOrString,
|
||||
reusedNames: readonly Entry[] | undefined,
|
||||
) => readonly Resolution[];
|
||||
getResolutionFromOldProgram: (name: string, mode: ResolutionMode) => Resolution | undefined;
|
||||
getResolved: (oldResolution: Resolution) => ResolutionWithResolvedFileName | undefined;
|
||||
canReuseResolutionsInFile: () => boolean;
|
||||
isEntryResolvingToAmbientModule?: (entry: Entry, containingFile: SourceFileOrString) => boolean;
|
||||
}
|
||||
|
||||
function resolveNamesReusingOldState<Entry, SourceFileOrString, SourceFileOrUndefined extends SourceFile | undefined, Resolution>({
|
||||
entries,
|
||||
containingFile,
|
||||
containingSourceFile,
|
||||
redirectedReference,
|
||||
nameAndModeGetter,
|
||||
resolutionWorker,
|
||||
getResolutionFromOldProgram,
|
||||
getResolved,
|
||||
canReuseResolutionsInFile,
|
||||
isEntryResolvingToAmbientModule,
|
||||
}: ResolveNamesReusingOldStateInput<Entry, SourceFileOrString, SourceFileOrUndefined, Resolution>): readonly Resolution[] {
|
||||
if (!entries.length) return emptyArray;
|
||||
if (structureIsReused === StructureIsReused.Not && (!isEntryResolvingToAmbientModule || !containingSourceFile!.ambientModuleNames.length)) {
|
||||
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
|
||||
// the best we can do is fallback to the default logic.
|
||||
return resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, /*reusedNames*/ undefined);
|
||||
return resolutionWorker(
|
||||
entries,
|
||||
containingFile,
|
||||
/*reusedNames*/ undefined,
|
||||
);
|
||||
}
|
||||
|
||||
/** An ordered list of module names for which we cannot recover the resolution. */
|
||||
let unknownTypeReferenceDirectiveNames: T[] | undefined;
|
||||
let result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations[] | undefined;
|
||||
let reusedNames: T[] | undefined;
|
||||
const containingSourceFile = !isString(containingFile) ? containingFile : undefined;
|
||||
const oldSourceFile = !isString(containingFile) ? oldProgram && oldProgram.getSourceFile(containingFile.fileName) : undefined;
|
||||
const canReuseResolutions = !isString(containingFile) ?
|
||||
containingFile === oldSourceFile && !hasInvalidatedResolutions(containingFile.path) :
|
||||
!hasInvalidatedResolutions(toPath(containingFile));
|
||||
for (let i = 0; i < typeDirectiveNames.length; i++) {
|
||||
const entry = typeDirectiveNames[i];
|
||||
if (canReuseResolutions) {
|
||||
const typeDirectiveName = getTypeReferenceResolutionName(entry);
|
||||
const mode = getModeForFileReference(entry, containingSourceFile?.impliedNodeFormat);
|
||||
const oldResolution = !isString(containingFile) ?
|
||||
oldProgram?.getResolvedTypeReferenceDirective(containingFile, typeDirectiveName, mode) :
|
||||
oldProgram?.getAutomaticTypeDirectiveResolutions()?.get(typeDirectiveName, mode);
|
||||
if (oldResolution?.resolvedTypeReferenceDirective) {
|
||||
let unknownEntries: Entry[] | undefined;
|
||||
let unknownEntryIndices: number[] | undefined;
|
||||
let result: Resolution[] | undefined;
|
||||
let reusedNames: Entry[] | undefined;
|
||||
const reuseResolutions = canReuseResolutionsInFile();
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i];
|
||||
if (reuseResolutions) {
|
||||
const name = nameAndModeGetter.getName(entry);
|
||||
const mode = nameAndModeGetter.getMode(entry, containingSourceFile, redirectedReference?.commandLine.options ?? options);
|
||||
const oldResolution = getResolutionFromOldProgram(name, mode);
|
||||
const oldResolved = oldResolution && getResolved(oldResolution);
|
||||
if (oldResolved) {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
trace(
|
||||
host,
|
||||
oldResolution.resolvedTypeReferenceDirective.packageId ?
|
||||
resolutionWorker === resolveModuleNamesWorker as unknown ?
|
||||
oldResolved.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 :
|
||||
oldResolved.packageId ?
|
||||
Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 :
|
||||
Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2,
|
||||
typeDirectiveName,
|
||||
!isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile,
|
||||
oldResolution.resolvedTypeReferenceDirective.resolvedFileName,
|
||||
oldResolution.resolvedTypeReferenceDirective.packageId && packageIdToString(oldResolution.resolvedTypeReferenceDirective.packageId),
|
||||
name,
|
||||
containingSourceFile ? getNormalizedAbsolutePath(containingSourceFile.originalFileName, currentDirectory) : containingFile,
|
||||
oldResolved.resolvedFileName,
|
||||
oldResolved.packageId && packageIdToString(oldResolved.packageId),
|
||||
);
|
||||
}
|
||||
(result ??= new Array(typeDirectiveNames.length))[i] = oldResolution;
|
||||
(result ??= new Array(entries.length))[i] = oldResolution;
|
||||
(reusedNames ??= []).push(entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
|
||||
(unknownTypeReferenceDirectiveNames ??= []).push(entry);
|
||||
}
|
||||
|
||||
if (!unknownTypeReferenceDirectiveNames) return result || emptyArray;
|
||||
const resolutions = resolveTypeReferenceDirectiveNamesWorker(
|
||||
unknownTypeReferenceDirectiveNames,
|
||||
containingFile,
|
||||
reusedNames,
|
||||
);
|
||||
|
||||
// Combine results of resolutions
|
||||
if (!result) {
|
||||
// There were no unresolved resolutions.
|
||||
Debug.assert(resolutions.length === typeDirectiveNames.length);
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
let j = 0;
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (!result[i]) {
|
||||
result[i] = resolutions[j];
|
||||
j++;
|
||||
if (isEntryResolvingToAmbientModule?.(entry, containingFile)) {
|
||||
(result ??= new Array(entries.length))[i] = emptyResolution;
|
||||
}
|
||||
else {
|
||||
// Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result.
|
||||
(unknownEntries ??= []).push(entry);
|
||||
(unknownEntryIndices ??= []).push(i);
|
||||
}
|
||||
}
|
||||
Debug.assert(j === resolutions.length);
|
||||
|
||||
if (!unknownEntries) return result!;
|
||||
const resolutions = resolutionWorker(unknownEntries, containingFile, reusedNames);
|
||||
if (!result) return resolutions;
|
||||
resolutions.forEach((resolution, index) => result[unknownEntryIndices![index]] = resolution);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2777,7 +2775,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!options.noLib) {
|
||||
if (options.noLib) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2788,7 +2786,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
return equalityComparer(file.fileName, getDefaultLibraryFileName());
|
||||
}
|
||||
else {
|
||||
return some(options.lib, libFileName => equalityComparer(file.fileName, resolvedLibReferences!.get(libFileName)!.actual));
|
||||
return some(options.lib, libFileName => {
|
||||
// We might not have resolved lib if one of the root file included contained no-default-lib = true
|
||||
const resolvedLib = resolvedLibReferences!.get(libFileName);
|
||||
return !!resolvedLib && equalityComparer(file.fileName, resolvedLib.actual);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2914,10 +2916,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
);
|
||||
}
|
||||
|
||||
function getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined {
|
||||
return sourceFile
|
||||
? cachedBindAndCheckDiagnosticsForFile.perFile?.get(sourceFile.path)
|
||||
: cachedBindAndCheckDiagnosticsForFile.allDiagnostics;
|
||||
function getCachedSemanticDiagnostics(sourceFile: SourceFile): readonly Diagnostic[] | undefined {
|
||||
return cachedBindAndCheckDiagnosticsForFile?.get(sourceFile.path);
|
||||
}
|
||||
|
||||
function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
|
||||
@@ -2938,14 +2938,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
}
|
||||
|
||||
function getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[] {
|
||||
const options = program.getCompilerOptions();
|
||||
// collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit)
|
||||
if (!sourceFile || options.outFile) {
|
||||
return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
|
||||
}
|
||||
else {
|
||||
return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken);
|
||||
}
|
||||
return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken);
|
||||
}
|
||||
|
||||
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): readonly DiagnosticWithLocation[] {
|
||||
@@ -2994,7 +2987,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (nodesToCheck) {
|
||||
return getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken, nodesToCheck);
|
||||
}
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedBindAndCheckDiagnosticsForFile, getBindAndCheckDiagnosticsForFileNoCache);
|
||||
let result = cachedBindAndCheckDiagnosticsForFile?.get(sourceFile.path);
|
||||
if (!result) {
|
||||
(cachedBindAndCheckDiagnosticsForFile ??= new Map()).set(
|
||||
sourceFile.path,
|
||||
result = getBindAndCheckDiagnosticsForFileNoCache(sourceFile, cancellationToken),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getBindAndCheckDiagnosticsForFileNoCache(
|
||||
@@ -3355,11 +3355,18 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
});
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] {
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache);
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] {
|
||||
let result = cachedDeclarationDiagnosticsForFile?.get(sourceFile.path);
|
||||
if (!result) {
|
||||
(cachedDeclarationDiagnosticsForFile ??= new Map()).set(
|
||||
sourceFile.path,
|
||||
result = getDeclarationDiagnosticsForFileNoCache(sourceFile, cancellationToken),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] {
|
||||
function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] {
|
||||
return runWithCancellationToken(() => {
|
||||
const resolver = getTypeChecker().getEmitResolver(sourceFile, cancellationToken);
|
||||
// Don't actually write any files since we're just getting diagnostics.
|
||||
@@ -3367,31 +3374,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
});
|
||||
}
|
||||
|
||||
function getAndCacheDiagnostics<T extends SourceFile | undefined, U extends Diagnostic>(
|
||||
sourceFile: T,
|
||||
cancellationToken: CancellationToken | undefined,
|
||||
cache: DiagnosticCache<U>,
|
||||
getDiagnostics: (sourceFile: T, cancellationToken: CancellationToken | undefined) => readonly U[],
|
||||
): readonly U[] {
|
||||
const cachedResult = sourceFile
|
||||
? cache.perFile?.get(sourceFile.path)
|
||||
: cache.allDiagnostics;
|
||||
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
const result = getDiagnostics(sourceFile, cancellationToken);
|
||||
if (sourceFile) {
|
||||
(cache.perFile || (cache.perFile = new Map())).set(sourceFile.path, result);
|
||||
}
|
||||
else {
|
||||
cache.allDiagnostics = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] {
|
||||
return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
|
||||
return sourceFile.isDeclarationFile ? emptyArray : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
|
||||
}
|
||||
|
||||
function getOptionsDiagnostics(): SortedReadonlyArray<Diagnostic> {
|
||||
@@ -4435,7 +4419,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
options.outDir || // there is --outDir specified
|
||||
options.rootDir || // there is --rootDir specified
|
||||
options.sourceRoot || // there is --sourceRoot specified
|
||||
options.mapRoot // there is --mapRoot specified
|
||||
options.mapRoot || // there is --mapRoot specified
|
||||
(getEmitDeclarations(options) && options.declarationDir) // there is --declarationDir specified
|
||||
) {
|
||||
// Precalculate and cache the common source directory
|
||||
const dir = getCommonSourceDirectory();
|
||||
@@ -4454,16 +4439,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
if (!getEmitDeclarations(options)) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite");
|
||||
}
|
||||
|
||||
if (options.noEmit) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit");
|
||||
}
|
||||
}
|
||||
|
||||
if (options.noCheck) {
|
||||
if (options.noEmit) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noCheck", "noEmit");
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -5354,8 +5329,6 @@ export function handleNoEmitOptions<T extends BuilderProgram>(
|
||||
): EmitResult | undefined {
|
||||
const options = program.getCompilerOptions();
|
||||
if (options.noEmit) {
|
||||
// Cache the semantic diagnostics
|
||||
program.getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
return sourceFile ?
|
||||
emitSkippedWithNoDiagnostics :
|
||||
program.emitBuildInfo(writeFile, cancellationToken);
|
||||
|
||||
@@ -30,9 +30,10 @@ import {
|
||||
getOptionsForLibraryResolution,
|
||||
getPathComponents,
|
||||
getPathFromPathComponents,
|
||||
getResolvedModuleFromResolution,
|
||||
getResolvedTypeReferenceDirectiveFromResolution,
|
||||
HasInvalidatedLibResolutions,
|
||||
HasInvalidatedResolutions,
|
||||
hasTrailingDirectorySeparator,
|
||||
ignoredPaths,
|
||||
inferredTypesContainingFile,
|
||||
isDiskPathRoot,
|
||||
@@ -51,7 +52,6 @@ import {
|
||||
mutateMap,
|
||||
noopFileWatcher,
|
||||
normalizePath,
|
||||
PackageId,
|
||||
packageIdToString,
|
||||
PackageJsonInfoCacheEntry,
|
||||
parseNodeModuleFromPath,
|
||||
@@ -63,6 +63,7 @@ import {
|
||||
resolutionExtensionIsTSOrJson,
|
||||
ResolutionLoader,
|
||||
ResolutionMode,
|
||||
ResolutionWithResolvedFileName,
|
||||
ResolvedModuleWithFailedLookupLocations,
|
||||
ResolvedProjectReference,
|
||||
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
|
||||
@@ -140,7 +141,7 @@ export interface ResolutionCache {
|
||||
|
||||
invalidateResolutionsOfFailedLookupLocations(): boolean;
|
||||
invalidateResolutionOfFile(filePath: Path): void;
|
||||
removeResolutionsOfFile(filePath: Path, syncDirWatcherRemove?: boolean): void;
|
||||
removeResolutionsOfFile(filePath: Path): void;
|
||||
removeResolutionsFromProjectReferenceRedirects(filePath: Path): void;
|
||||
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<Path, readonly string[]>): void;
|
||||
createHasInvalidatedResolutions(
|
||||
@@ -167,18 +168,11 @@ export interface ResolutionWithFailedLookupLocations {
|
||||
failedLookupLocations?: string[];
|
||||
affectingLocations?: string[];
|
||||
isInvalidated?: boolean;
|
||||
refCount?: number;
|
||||
// Files that have this resolution using
|
||||
files?: Set<Path>;
|
||||
alternateResult?: string;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ResolutionWithResolvedFileName {
|
||||
resolvedFileName: string | undefined;
|
||||
packageId?: PackageId;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface CachedResolvedModuleWithFailedLookupLocations extends ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations {
|
||||
}
|
||||
@@ -192,6 +186,7 @@ export interface ResolutionCacheHost extends MinimalResolutionCacheHost {
|
||||
toPath(fileName: string): Path;
|
||||
getCanonicalFileName: GetCanonicalFileName;
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
preferNonRecursiveWatch: boolean | undefined;
|
||||
watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher;
|
||||
watchAffectingFileLocation(file: string, cb: FileWatcherCallback): FileWatcher;
|
||||
onInvalidatedResolution(): void;
|
||||
@@ -351,6 +346,7 @@ export function getDirectoryToWatchFailedLookupLocation(
|
||||
rootPath: Path,
|
||||
rootPathComponents: Readonly<PathPathComponents>,
|
||||
getCurrentDirectory: () => string | undefined,
|
||||
preferNonRecursiveWatch: boolean | undefined,
|
||||
): DirectoryOfFailedLookupWatch | undefined {
|
||||
const failedLookupPathComponents: Readonly<PathPathComponents> = getPathComponents(failedLookupLocationPath);
|
||||
// Ensure failed look up is normalized path
|
||||
@@ -390,6 +386,7 @@ export function getDirectoryToWatchFailedLookupLocation(
|
||||
nodeModulesIndex,
|
||||
rootPathComponents,
|
||||
lastNodeModulesIndex,
|
||||
preferNonRecursiveWatch,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -401,6 +398,7 @@ function getDirectoryToWatchFromFailedLookupLocationDirectory(
|
||||
nodeModulesIndex: number,
|
||||
rootPathComponents: Readonly<PathPathComponents>,
|
||||
lastNodeModulesIndex: number,
|
||||
preferNonRecursiveWatch: boolean | undefined,
|
||||
): DirectoryOfFailedLookupWatch | undefined {
|
||||
// If directory path contains node module, get the most parent node_modules directory for watching
|
||||
if (nodeModulesIndex !== -1) {
|
||||
@@ -412,14 +410,17 @@ function getDirectoryToWatchFromFailedLookupLocationDirectory(
|
||||
lastNodeModulesIndex,
|
||||
);
|
||||
}
|
||||
|
||||
// Use some ancestor of the root directory
|
||||
let nonRecursive = true;
|
||||
let length = dirPathComponentsLength;
|
||||
for (let i = 0; i < dirPathComponentsLength; i++) {
|
||||
if (dirPathComponents[i] !== rootPathComponents[i]) {
|
||||
nonRecursive = false;
|
||||
length = Math.max(i + 1, perceivedOsRootLength + 1);
|
||||
break;
|
||||
if (!preferNonRecursiveWatch) {
|
||||
for (let i = 0; i < dirPathComponentsLength; i++) {
|
||||
if (dirPathComponents[i] !== rootPathComponents[i]) {
|
||||
nonRecursive = false;
|
||||
length = Math.max(i + 1, perceivedOsRootLength + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return getDirectoryOfFailedLookupWatch(
|
||||
@@ -463,6 +464,7 @@ export function getDirectoryToWatchFailedLookupLocationFromTypeRoot(
|
||||
rootPath: Path,
|
||||
rootPathComponents: Readonly<PathPathComponents>,
|
||||
getCurrentDirectory: () => string | undefined,
|
||||
preferNonRecursiveWatch: boolean | undefined,
|
||||
filterCustomPath: (path: Path) => boolean, // Return true if this path can be used
|
||||
): Path | undefined {
|
||||
const typeRootPathComponents = getPathComponents(typeRootPath);
|
||||
@@ -479,6 +481,7 @@ export function getDirectoryToWatchFailedLookupLocationFromTypeRoot(
|
||||
typeRootPathComponents.indexOf("node_modules" as Path),
|
||||
rootPathComponents,
|
||||
typeRootPathComponents.lastIndexOf("node_modules" as Path),
|
||||
preferNonRecursiveWatch,
|
||||
);
|
||||
return toWatch && filterCustomPath(toWatch.dirPath) ? toWatch.dirPath : undefined;
|
||||
}
|
||||
@@ -491,11 +494,6 @@ export function getRootDirectoryOfResolutionCache(rootDirForResolution: string,
|
||||
normalized;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getRootPathSplitLength(rootPath: Path) {
|
||||
return rootPath.split(directorySeparator).length - (hasTrailingDirectorySeparator(rootPath) ? 1 : 0);
|
||||
}
|
||||
|
||||
function getModuleResolutionHost(resolutionHost: ResolutionCacheHost) {
|
||||
return resolutionHost.getCompilerHost?.() || resolutionHost;
|
||||
}
|
||||
@@ -670,14 +668,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
onChangesAffectModuleResolution,
|
||||
};
|
||||
|
||||
function getResolvedModule(resolution: CachedResolvedModuleWithFailedLookupLocations) {
|
||||
return resolution.resolvedModule;
|
||||
}
|
||||
|
||||
function getResolvedTypeReferenceDirective(resolution: CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations) {
|
||||
return resolution.resolvedTypeReferenceDirective;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf);
|
||||
clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf);
|
||||
@@ -776,7 +766,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
stopWatchFailedLookupLocationOfResolution(
|
||||
resolution,
|
||||
resolutionHost.toPath(getInferredLibraryNameResolveFrom(resolutionHost.getCompilationSettings(), getCurrentDirectory(), libFileName)),
|
||||
getResolvedModule,
|
||||
getResolvedModuleFromResolution,
|
||||
);
|
||||
resolvedLibraries.delete(libFileName);
|
||||
}
|
||||
@@ -1003,7 +993,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
getModuleResolutionHost(resolutionHost),
|
||||
typeReferenceDirectiveResolutionCache,
|
||||
),
|
||||
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirective,
|
||||
getResolutionWithResolvedFileName: getResolvedTypeReferenceDirectiveFromResolution,
|
||||
shouldRetryResolution: resolution => resolution.resolvedTypeReferenceDirective === undefined,
|
||||
deferWatchingNonRelativeResolution: false,
|
||||
});
|
||||
@@ -1032,7 +1022,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
resolutionHost,
|
||||
moduleResolutionCache,
|
||||
),
|
||||
getResolutionWithResolvedFileName: getResolvedModule,
|
||||
getResolutionWithResolvedFileName: getResolvedModuleFromResolution,
|
||||
shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
|
||||
logChanges: logChangesWhenResolvingModule,
|
||||
deferWatchingNonRelativeResolution: true, // Defer non relative resolution watch because we could be using ambient modules
|
||||
@@ -1051,15 +1041,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
const existingResolution = resolution;
|
||||
resolution = ts_resolveLibrary(libraryName, resolveFrom, options, host, libraryResolutionCache);
|
||||
const path = resolutionHost.toPath(resolveFrom);
|
||||
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModule, /*deferWatchingNonRelativeResolution*/ false);
|
||||
watchFailedLookupLocationsOfExternalModuleResolutions(libraryName, resolution, path, getResolvedModuleFromResolution, /*deferWatchingNonRelativeResolution*/ false);
|
||||
resolvedLibraries.set(libFileName, resolution);
|
||||
if (existingResolution) {
|
||||
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModule);
|
||||
stopWatchFailedLookupLocationOfResolution(existingResolution, path, getResolvedModuleFromResolution);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isTraceEnabled(options, host)) {
|
||||
const resolved = getResolvedModule(resolution);
|
||||
const resolved = getResolvedModuleFromResolution(resolution);
|
||||
trace(
|
||||
host,
|
||||
resolved?.resolvedFileName ?
|
||||
@@ -1107,28 +1097,21 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
|
||||
deferWatchingNonRelativeResolution: boolean,
|
||||
) {
|
||||
if (resolution.refCount) {
|
||||
resolution.refCount++;
|
||||
Debug.assertIsDefined(resolution.files);
|
||||
(resolution.files ??= new Set()).add(filePath);
|
||||
if (resolution.files.size !== 1) return;
|
||||
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
|
||||
watchFailedLookupLocationOfResolution(resolution);
|
||||
}
|
||||
else {
|
||||
resolution.refCount = 1;
|
||||
Debug.assert(!resolution.files?.size); // This resolution shouldnt be referenced by any file yet
|
||||
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
|
||||
watchFailedLookupLocationOfResolution(resolution);
|
||||
}
|
||||
else {
|
||||
nonRelativeExternalModuleResolutions.add(name, resolution);
|
||||
}
|
||||
const resolved = getResolutionWithResolvedFileName(resolution);
|
||||
if (resolved && resolved.resolvedFileName) {
|
||||
const key = resolutionHost.toPath(resolved.resolvedFileName);
|
||||
let resolutions = resolvedFileToResolution.get(key);
|
||||
if (!resolutions) resolvedFileToResolution.set(key, resolutions = new Set());
|
||||
resolutions.add(resolution);
|
||||
}
|
||||
nonRelativeExternalModuleResolutions.add(name, resolution);
|
||||
}
|
||||
const resolved = getResolutionWithResolvedFileName(resolution);
|
||||
if (resolved && resolved.resolvedFileName) {
|
||||
const key = resolutionHost.toPath(resolved.resolvedFileName);
|
||||
let resolutions = resolvedFileToResolution.get(key);
|
||||
if (!resolutions) resolvedFileToResolution.set(key, resolutions = new Set());
|
||||
resolutions.add(resolution);
|
||||
}
|
||||
(resolution.files ??= new Set()).add(filePath);
|
||||
}
|
||||
|
||||
function watchFailedLookupLocation(failedLookupLocation: string, setAtRoot: boolean) {
|
||||
@@ -1140,6 +1123,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
rootPath,
|
||||
rootPathComponents,
|
||||
getCurrentDirectory,
|
||||
resolutionHost.preferNonRecursiveWatch,
|
||||
);
|
||||
if (toWatch) {
|
||||
const { dir, dirPath, nonRecursive, packageDir, packageDirPath } = toWatch;
|
||||
@@ -1156,7 +1140,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
|
||||
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
|
||||
Debug.assert(!!resolution.refCount);
|
||||
Debug.assert(!!resolution.files?.size);
|
||||
|
||||
const { failedLookupLocations, affectingLocations, alternateResult } = resolution;
|
||||
if (!failedLookupLocations?.length && !affectingLocations?.length && !alternateResult) return;
|
||||
@@ -1177,7 +1161,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
}
|
||||
|
||||
function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) {
|
||||
Debug.assert(!!resolution.refCount);
|
||||
Debug.assert(!!resolution.files?.size);
|
||||
const { affectingLocations } = resolution;
|
||||
if (!affectingLocations?.length) return;
|
||||
if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.add(resolution);
|
||||
@@ -1289,7 +1273,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
else if (packageDirWatcher.isSymlink !== isSymlink) {
|
||||
// Handle the change
|
||||
packageDirWatcher.dirPathToWatcher.forEach(watcher => {
|
||||
removeDirectoryWatcher(packageDirWatcher!.isSymlink ? packageDirPath : dirPath, /*syncDirWatcherRemove*/ false);
|
||||
removeDirectoryWatcher(packageDirWatcher!.isSymlink ? packageDirPath : dirPath);
|
||||
watcher.watcher = createDirPathToWatcher();
|
||||
});
|
||||
packageDirWatcher.isSymlink = isSymlink;
|
||||
@@ -1345,7 +1329,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
return dirWatcher;
|
||||
}
|
||||
|
||||
function stopWatchFailedLookupLocation(failedLookupLocation: string, removeAtRoot: boolean, syncDirWatcherRemove: boolean | undefined) {
|
||||
function stopWatchFailedLookupLocation(failedLookupLocation: string, removeAtRoot: boolean) {
|
||||
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
|
||||
const toWatch = getDirectoryToWatchFailedLookupLocation(
|
||||
failedLookupLocation,
|
||||
@@ -1354,6 +1338,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
rootPath,
|
||||
rootPathComponents,
|
||||
getCurrentDirectory,
|
||||
resolutionHost.preferNonRecursiveWatch,
|
||||
);
|
||||
if (toWatch) {
|
||||
const { dirPath, packageDirPath } = toWatch;
|
||||
@@ -1365,7 +1350,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
const forDirPath = packageDirWatcher.dirPathToWatcher.get(dirPath)!;
|
||||
forDirPath.refCount--;
|
||||
if (forDirPath.refCount === 0) {
|
||||
removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath, syncDirWatcherRemove);
|
||||
removeDirectoryWatcher(packageDirWatcher.isSymlink ? packageDirPath : dirPath);
|
||||
packageDirWatcher.dirPathToWatcher.delete(dirPath);
|
||||
if (packageDirWatcher.isSymlink) {
|
||||
const refCount = dirPathToSymlinkPackageRefCount.get(dirPath)! - 1;
|
||||
@@ -1376,11 +1361,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
dirPathToSymlinkPackageRefCount.set(dirPath, refCount);
|
||||
}
|
||||
}
|
||||
if (syncDirWatcherRemove) closePackageDirWatcher(packageDirWatcher, packageDirPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeDirectoryWatcher(dirPath, syncDirWatcherRemove);
|
||||
removeDirectoryWatcher(dirPath);
|
||||
}
|
||||
}
|
||||
return removeAtRoot;
|
||||
@@ -1390,13 +1374,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
resolution: T,
|
||||
filePath: Path,
|
||||
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
|
||||
syncDirWatcherRemove?: boolean,
|
||||
) {
|
||||
Debug.checkDefined(resolution.files).delete(filePath);
|
||||
resolution.refCount!--;
|
||||
if (resolution.refCount) {
|
||||
return;
|
||||
}
|
||||
if (resolution.files!.size) return;
|
||||
resolution.files = undefined;
|
||||
const resolved = getResolutionWithResolvedFileName(resolution);
|
||||
if (resolved && resolved.resolvedFileName) {
|
||||
const key = resolutionHost.toPath(resolved.resolvedFileName);
|
||||
@@ -1409,11 +1390,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
let removeAtRoot = false;
|
||||
if (failedLookupLocations) {
|
||||
for (const failedLookupLocation of failedLookupLocations) {
|
||||
removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot, syncDirWatcherRemove);
|
||||
removeAtRoot = stopWatchFailedLookupLocation(failedLookupLocation, removeAtRoot);
|
||||
}
|
||||
}
|
||||
if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot, syncDirWatcherRemove);
|
||||
if (removeAtRoot) removeDirectoryWatcher(rootPath, syncDirWatcherRemove);
|
||||
if (alternateResult) removeAtRoot = stopWatchFailedLookupLocation(alternateResult, removeAtRoot);
|
||||
if (removeAtRoot) removeDirectoryWatcher(rootPath);
|
||||
}
|
||||
else if (affectingLocations?.length) {
|
||||
resolutionsWithOnlyAffectingLocations.delete(resolution);
|
||||
@@ -1423,16 +1404,14 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
for (const affectingLocation of affectingLocations) {
|
||||
const watcher = fileWatchesOfAffectingLocations.get(affectingLocation)!;
|
||||
watcher.resolutions--;
|
||||
if (syncDirWatcherRemove) closeFileWatcherOfAffectingLocation(watcher, affectingLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeDirectoryWatcher(dirPath: Path, syncDirWatcherRemove: boolean | undefined) {
|
||||
function removeDirectoryWatcher(dirPath: Path) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath)!;
|
||||
// Do not close the watcher yet since it might be needed by other failed lookup locations.
|
||||
dirWatcher.refCount--;
|
||||
if (syncDirWatcherRemove) closeDirectoryWatchesOfFailedLookup(dirWatcher, dirPath);
|
||||
}
|
||||
|
||||
function createDirectoryWatcher(directory: string, dirPath: Path, nonRecursive: boolean | undefined) {
|
||||
@@ -1451,7 +1430,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
cache: Map<string, ModeAwareCache<T>>,
|
||||
filePath: Path,
|
||||
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
|
||||
syncDirWatcherRemove: boolean | undefined,
|
||||
) {
|
||||
// Deleted file, stop watching failed lookups for all the resolutions in the file
|
||||
const resolutions = cache.get(filePath);
|
||||
@@ -1461,7 +1439,6 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
resolution,
|
||||
filePath,
|
||||
getResolutionWithResolvedFileName,
|
||||
syncDirWatcherRemove,
|
||||
)
|
||||
);
|
||||
cache.delete(filePath);
|
||||
@@ -1482,9 +1459,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
resolvedProjectReference.commandLine.fileNames.forEach(f => removeResolutionsOfFile(resolutionHost.toPath(f)));
|
||||
}
|
||||
|
||||
function removeResolutionsOfFile(filePath: Path, syncDirWatcherRemove?: boolean) {
|
||||
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModule, syncDirWatcherRemove);
|
||||
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective, syncDirWatcherRemove);
|
||||
function removeResolutionsOfFile(filePath: Path) {
|
||||
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModuleFromResolution);
|
||||
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirectiveFromResolution);
|
||||
}
|
||||
|
||||
function invalidateResolutions(resolutions: Set<ResolutionWithFailedLookupLocations> | Map<string, ResolutionWithFailedLookupLocations> | undefined, canInvalidate: (resolution: ResolutionWithFailedLookupLocations) => boolean | undefined) {
|
||||
@@ -1662,6 +1639,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD
|
||||
rootPath,
|
||||
rootPathComponents,
|
||||
getCurrentDirectory,
|
||||
resolutionHost.preferNonRecursiveWatch,
|
||||
dirPath => directoryWatchesOfFailedLookups.has(dirPath) || dirPathToSymlinkPackageRefCount.has(dirPath),
|
||||
);
|
||||
if (dirPath) {
|
||||
|
||||
@@ -419,12 +419,12 @@ export function stringToToken(s: string): SyntaxKind | undefined {
|
||||
|
||||
const regExpFlagCharCodes = makeReverseMap(charCodeToRegExpFlag);
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function regularExpressionFlagToCharacterCode(f: RegularExpressionFlags): CharacterCodes | undefined {
|
||||
return regExpFlagCharCodes[f];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function characterCodeToRegularExpressionFlag(ch: CharacterCodes): RegularExpressionFlags | undefined {
|
||||
return charCodeToRegExpFlag.get(ch);
|
||||
}
|
||||
@@ -603,8 +603,7 @@ function isWordCharacter(ch: number): boolean {
|
||||
return isASCIILetter(ch) || isDigit(ch) || ch === CharacterCodes._;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isOctalDigit(ch: number): boolean {
|
||||
function isOctalDigit(ch: number): boolean {
|
||||
return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
|
||||
}
|
||||
|
||||
@@ -789,15 +788,13 @@ function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: Diag
|
||||
|
||||
const shebangTriviaRegex = /^#!.*/;
|
||||
|
||||
/** @internal */
|
||||
export function isShebangTrivia(text: string, pos: number) {
|
||||
function isShebangTrivia(text: string, pos: number) {
|
||||
// Shebangs check must only be done at the start of the file
|
||||
Debug.assert(pos === 0);
|
||||
return shebangTriviaRegex.test(text);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function scanShebangTrivia(text: string, pos: number) {
|
||||
function scanShebangTrivia(text: string, pos: number) {
|
||||
const shebang = shebangTriviaRegex.exec(text)![0];
|
||||
pos = pos + shebang.length;
|
||||
return pos;
|
||||
|
||||
@@ -405,8 +405,7 @@ function isStringOrNull(x: any) {
|
||||
return typeof x === "string" || x === null;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isRawSourceMap(x: any): x is RawSourceMap {
|
||||
function isRawSourceMap(x: any): x is RawSourceMap {
|
||||
return x !== null
|
||||
&& typeof x === "object"
|
||||
&& x.version === 3
|
||||
|
||||
+3
-1
@@ -1409,6 +1409,7 @@ export interface System {
|
||||
*/
|
||||
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher;
|
||||
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher;
|
||||
/**@internal */ preferNonRecursiveWatch?: boolean;
|
||||
resolvePath(path: string): string;
|
||||
fileExists(path: string): boolean;
|
||||
directoryExists(path: string): boolean;
|
||||
@@ -1534,6 +1535,7 @@ export let sys: System = (() => {
|
||||
writeFile,
|
||||
watchFile,
|
||||
watchDirectory,
|
||||
preferNonRecursiveWatch: !fsSupportsRecursiveFsWatch,
|
||||
resolvePath: path => _path.resolve(path),
|
||||
fileExists,
|
||||
directoryExists,
|
||||
@@ -1994,7 +1996,7 @@ export let sys: System = (() => {
|
||||
return sys!;
|
||||
})();
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function setSys(s: System) {
|
||||
sys = s;
|
||||
}
|
||||
|
||||
@@ -464,8 +464,6 @@ export function transformClassFields(context: TransformationContext): (x: Source
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AccessorKeyword:
|
||||
return Debug.fail("Use `modifierVisitor` instead.");
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return visitClassDeclaration(node as ClassDeclaration);
|
||||
case SyntaxKind.ClassExpression:
|
||||
|
||||
@@ -29,9 +29,8 @@ import {
|
||||
* @param classThis The identifier to use for the captured static `this` reference, usually with the name `_classThis`.
|
||||
* @param thisExpression Overrides the expression to use for the actual `this` reference. This can be used to provide an
|
||||
* expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution.
|
||||
* @internal
|
||||
*/
|
||||
export function createClassThisAssignmentBlock(factory: NodeFactory, classThis: Identifier, thisExpression = factory.createThis()): ClassThisAssignmentBlock {
|
||||
function createClassThisAssignmentBlock(factory: NodeFactory, classThis: Identifier, thisExpression = factory.createThis()): ClassThisAssignmentBlock {
|
||||
// produces:
|
||||
//
|
||||
// static { _classThis = this; }
|
||||
|
||||
@@ -214,19 +214,24 @@ import {
|
||||
} from "../_namespaces/ts.js";
|
||||
|
||||
/** @internal */
|
||||
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
|
||||
export function getDeclarationDiagnostics(
|
||||
host: EmitHost,
|
||||
resolver: EmitResolver,
|
||||
file: SourceFile,
|
||||
): DiagnosticWithLocation[] | undefined {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const files = filter(getSourceFilesToEmit(host, file), isSourceFileNotJson);
|
||||
const result = transformNodes(
|
||||
resolver,
|
||||
host,
|
||||
factory,
|
||||
compilerOptions,
|
||||
file ? contains(files, file) ? [file] : emptyArray : files,
|
||||
[transformDeclarations],
|
||||
/*allowDtsFiles*/ false,
|
||||
);
|
||||
return result.diagnostics;
|
||||
return contains(files, file) ?
|
||||
transformNodes(
|
||||
resolver,
|
||||
host,
|
||||
factory,
|
||||
compilerOptions,
|
||||
[file],
|
||||
[transformDeclarations],
|
||||
/*allowDtsFiles*/ false,
|
||||
).diagnostics :
|
||||
undefined;
|
||||
}
|
||||
|
||||
const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals |
|
||||
@@ -303,6 +308,7 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
}
|
||||
function reportInferenceFallback(node: Node) {
|
||||
if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return;
|
||||
if (getSourceFileOfNode(node) !== currentSourceFile) return; // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set
|
||||
if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) {
|
||||
reportExpandoFunctionErrors(node);
|
||||
}
|
||||
|
||||
@@ -52,9 +52,8 @@ import {
|
||||
|
||||
/**
|
||||
* Gets a string literal to use as the assigned name of an anonymous class or function declaration.
|
||||
* @internal
|
||||
*/
|
||||
export function getAssignedNameOfIdentifier(factory: NodeFactory, name: Identifier, expression: WrappedExpression<AnonymousFunctionDefinition>): StringLiteral {
|
||||
function getAssignedNameOfIdentifier(factory: NodeFactory, name: Identifier, expression: WrappedExpression<AnonymousFunctionDefinition>): StringLiteral {
|
||||
const original = getOriginalNode(skipOuterExpressions(expression));
|
||||
if (
|
||||
(isClassDeclaration(original) || isFunctionDeclaration(original)) &&
|
||||
@@ -98,9 +97,8 @@ function getAssignedNameOfPropertyName(context: TransformationContext, name: Pro
|
||||
* side effects.
|
||||
* @param thisExpression Overrides the expression to use for the actual `this` reference. This can be used to provide an
|
||||
* expression that has already had its `EmitFlags` set or may have been tracked to prevent substitution.
|
||||
* @internal
|
||||
*/
|
||||
export function createClassNamedEvaluationHelperBlock(context: TransformationContext, assignedName: Expression, thisExpression: Expression = context.factory.createThis()): ClassNamedEvaluationHelperBlock {
|
||||
function createClassNamedEvaluationHelperBlock(context: TransformationContext, assignedName: Expression, thisExpression: Expression = context.factory.createThis()): ClassNamedEvaluationHelperBlock {
|
||||
// produces:
|
||||
//
|
||||
// static { __setFunctionName(this, "C"); }
|
||||
|
||||
@@ -429,8 +429,7 @@ export class IdentifierNameMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class IdentifierNameMultiMap<V> extends IdentifierNameMap<V[]> {
|
||||
class IdentifierNameMultiMap<V> extends IdentifierNameMap<V[]> {
|
||||
add(key: Identifier, value: V): V[] {
|
||||
let values = this.get(key);
|
||||
if (values) {
|
||||
@@ -801,8 +800,7 @@ export interface LexicalEnvironment<in out TEnvData, TPrivateEnvData, TPrivateEn
|
||||
readonly previous: LexicalEnvironment<TEnvData, TPrivateEnvData, TPrivateEntry> | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function walkUpLexicalEnvironments<TEnvData, TPrivateEnvData, TPrivateEntry, U>(
|
||||
function walkUpLexicalEnvironments<TEnvData, TPrivateEnvData, TPrivateEntry, U>(
|
||||
env: LexicalEnvironment<TEnvData, TPrivateEnvData, TPrivateEntry> | undefined,
|
||||
cb: (env: LexicalEnvironment<TEnvData, TPrivateEnvData, TPrivateEntry>) => U,
|
||||
): U | undefined {
|
||||
@@ -856,8 +854,7 @@ export function accessPrivateIdentifier<
|
||||
return walkUpLexicalEnvironments(env, env => getPrivateIdentifier(env.privateEnv, name));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isSimpleParameter(node: ParameterDeclaration) {
|
||||
function isSimpleParameter(node: ParameterDeclaration) {
|
||||
return !node.initializer && isIdentifier(node.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ import {
|
||||
getNonIncrementalBuildInfoRoots,
|
||||
getNormalizedAbsolutePath,
|
||||
getParsedCommandLineOfConfigFile,
|
||||
getPendingEmitKind,
|
||||
getPendingEmitKindWithSeen,
|
||||
getSourceFileVersionAsHashFromText,
|
||||
getTsBuildInfoEmitOutputFilePath,
|
||||
getWatchErrorSummaryDiagnosticMessage,
|
||||
@@ -198,10 +198,8 @@ function getOrCreateValueMapFromConfigFileMap<K extends string, V>(configFileMap
|
||||
|
||||
/**
|
||||
* Helper to use now method instead of current date for testing purposes to get consistent baselines
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function getCurrentTime(host: { now?(): Date; }) {
|
||||
function getCurrentTime(host: { now?(): Date; }) {
|
||||
return host.now ? host.now() : new Date();
|
||||
}
|
||||
|
||||
@@ -1513,8 +1511,14 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
|
||||
// If there are errors, we need to build project again to report it
|
||||
if (
|
||||
!project.options.noCheck &&
|
||||
(incrementalBuildInfo.semanticDiagnosticsPerFile?.length ||
|
||||
(!project.options.noEmit && getEmitDeclarations(project.options) && incrementalBuildInfo.emitDiagnosticsPerFile?.length))
|
||||
(
|
||||
incrementalBuildInfo.changeFileSet?.length ||
|
||||
incrementalBuildInfo.semanticDiagnosticsPerFile?.length ||
|
||||
(
|
||||
getEmitDeclarations(project.options) &&
|
||||
incrementalBuildInfo.emitDiagnosticsPerFile?.length
|
||||
)
|
||||
)
|
||||
) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateBuildInfoWithErrors,
|
||||
@@ -1525,8 +1529,11 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
|
||||
// If there are pending changes that are not emitted, project is out of date
|
||||
if (
|
||||
!project.options.noEmit &&
|
||||
((incrementalBuildInfo as IncrementalMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length ||
|
||||
(incrementalBuildInfo as IncrementalBundleEmitBuildInfo).pendingEmit !== undefined)
|
||||
(
|
||||
incrementalBuildInfo.changeFileSet?.length ||
|
||||
(incrementalBuildInfo as IncrementalMultiFileEmitBuildInfo).affectedFilesPendingEmit?.length ||
|
||||
(incrementalBuildInfo as IncrementalBundleEmitBuildInfo).pendingEmit !== undefined
|
||||
)
|
||||
) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateBuildInfoWithPendingEmit,
|
||||
@@ -1535,7 +1542,18 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
|
||||
}
|
||||
|
||||
// Has not emitted some of the files, project is out of date
|
||||
if (!project.options.noEmit && getPendingEmitKind(project.options, incrementalBuildInfo.options || {})) {
|
||||
if (
|
||||
(
|
||||
!project.options.noEmit ||
|
||||
(project.options.noEmit && getEmitDeclarations(project.options))
|
||||
) &&
|
||||
getPendingEmitKindWithSeen(
|
||||
project.options,
|
||||
incrementalBuildInfo.options || {},
|
||||
/*emitOnlyDtsFiles*/ undefined,
|
||||
!!project.options.noEmit,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateOptions,
|
||||
buildInfoFile: buildInfoPath,
|
||||
|
||||
+12
-21
@@ -1308,7 +1308,7 @@ export type HasExpressionInitializer =
|
||||
| PropertyAssignment
|
||||
| EnumMember;
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export type HasIllegalExpressionInitializer = PropertySignature;
|
||||
|
||||
// NOTE: Changing the following list requires changes to:
|
||||
@@ -2316,7 +2316,7 @@ export interface TypeOperatorNode extends TypeNode {
|
||||
readonly type: TypeNode;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export interface UniqueTypeOperatorNode extends TypeOperatorNode {
|
||||
readonly operator: SyntaxKind.UniqueKeyword;
|
||||
}
|
||||
@@ -2668,7 +2668,7 @@ export type ObjectBindingOrAssignmentElement =
|
||||
| SpreadAssignment // AssignmentRestProperty
|
||||
;
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export type ObjectAssignmentElement = Exclude<ObjectBindingOrAssignmentElement, BindingElement>;
|
||||
|
||||
export type ArrayBindingOrAssignmentElement =
|
||||
@@ -2699,7 +2699,7 @@ export type BindingOrAssignmentElementTarget =
|
||||
| ElementAccessExpression
|
||||
| OmittedExpression;
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export type AssignmentElementTarget = Exclude<BindingOrAssignmentElementTarget, BindingPattern>;
|
||||
|
||||
export type ObjectBindingOrAssignmentPattern =
|
||||
@@ -4746,7 +4746,7 @@ export interface Program extends ScriptReferenceHost {
|
||||
|
||||
/** @internal */ getCommonSourceDirectory(): string;
|
||||
|
||||
/** @internal */ getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined;
|
||||
/** @internal */ getCachedSemanticDiagnostics(sourceFile: SourceFile): readonly Diagnostic[] | undefined;
|
||||
|
||||
/** @internal */ getClassifiableNames(): Set<__String>;
|
||||
|
||||
@@ -5506,12 +5506,6 @@ export const enum SymbolAccessibility {
|
||||
NotResolved,
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const enum SyntheticSymbolKind {
|
||||
UnionOrIntersection,
|
||||
Spread,
|
||||
}
|
||||
|
||||
export const enum TypePredicateKind {
|
||||
This,
|
||||
Identifier,
|
||||
@@ -7982,7 +7976,7 @@ export interface CompilerHost extends ModuleResolutionHost {
|
||||
*/
|
||||
hasInvalidatedLibResolutions?(libFileName: string): boolean;
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void;
|
||||
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined): void;
|
||||
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
|
||||
/** If provided along with custom resolveModuleNames or resolveTypeReferenceDirectives, used to determine if unchanged file path needs to re-resolve modules/type reference directives */
|
||||
hasInvalidatedResolutions?(filePath: Path): boolean;
|
||||
@@ -8007,12 +8001,6 @@ export interface CompilerHost extends ModuleResolutionHost {
|
||||
*/
|
||||
export type SourceOfProjectReferenceRedirect = string | true;
|
||||
|
||||
/** @internal */
|
||||
export interface ResolvedProjectReferenceCallbacks {
|
||||
getSourceOfProjectReferenceRedirect(fileName: string): SourceOfProjectReferenceRedirect | undefined;
|
||||
forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const enum TransformFlags {
|
||||
None = 0,
|
||||
@@ -8230,9 +8218,6 @@ export interface UnscopedEmitHelper extends EmitHelperBase {
|
||||
|
||||
export type EmitHelper = ScopedEmitHelper | UnscopedEmitHelper;
|
||||
|
||||
/** @internal */
|
||||
export type UniqueNameHandler = (baseName: string, checkFn?: (name: string) => boolean, optimistic?: boolean) => string;
|
||||
|
||||
export type EmitHelperUniqueNameCallback = (name: string) => string;
|
||||
|
||||
/**
|
||||
@@ -9846,6 +9831,12 @@ export interface DiagnosticCollection {
|
||||
// SyntaxKind.SyntaxList
|
||||
export interface SyntaxList extends Node {
|
||||
kind: SyntaxKind.SyntaxList;
|
||||
|
||||
// Unlike other nodes which may or may not have their child nodes calculated,
|
||||
// the entire purpose of a SyntaxList is to hold child nodes.
|
||||
// Instead of using the WeakMap machinery in `nodeChildren.ts`,
|
||||
// we just store the children directly on the SyntaxList.
|
||||
/** @internal */ _children: readonly Node[];
|
||||
}
|
||||
|
||||
// dprint-ignore
|
||||
|
||||
+99
-200
@@ -11,7 +11,7 @@ import {
|
||||
AmpersandAmpersandEqualsToken,
|
||||
AnyImportOrBareOrAccessedRequire,
|
||||
AnyImportOrReExport,
|
||||
AnyImportOrRequireStatement,
|
||||
type AnyImportOrRequireStatement,
|
||||
AnyImportSyntax,
|
||||
AnyValidImportOrReExport,
|
||||
append,
|
||||
@@ -150,7 +150,6 @@ import {
|
||||
flatMapToMutable,
|
||||
flatten,
|
||||
forEach,
|
||||
forEachAncestorDirectory,
|
||||
forEachChild,
|
||||
forEachChildRecursively,
|
||||
ForInOrOfStatement,
|
||||
@@ -524,7 +523,6 @@ import {
|
||||
StringLiteralType,
|
||||
stringToToken,
|
||||
SuperCall,
|
||||
SuperExpression,
|
||||
SuperProperty,
|
||||
SwitchStatement,
|
||||
Symbol,
|
||||
@@ -690,8 +688,7 @@ export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOp
|
||||
optionsHaveModuleResolutionChanges(oldOptions, newOptions);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function optionsHaveModuleResolutionChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions) {
|
||||
function optionsHaveModuleResolutionChanges(oldOptions: CompilerOptions, newOptions: CompilerOptions) {
|
||||
return optionsHaveChanges(oldOptions, newOptions, moduleResolutionOptionDeclarations);
|
||||
}
|
||||
|
||||
@@ -799,6 +796,16 @@ export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleWithFaile
|
||||
oldResolution.alternateResult === newResolution.alternateResult;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getResolvedModuleFromResolution(resolution: ResolvedModuleWithFailedLookupLocations) {
|
||||
return resolution.resolvedModule;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getResolvedTypeReferenceDirectiveFromResolution(resolution: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) {
|
||||
return resolution.resolvedTypeReferenceDirective;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createModuleNotFoundChain(sourceFile: SourceFile, host: TypeCheckerHost, moduleReference: string, mode: ResolutionMode, packageName: string) {
|
||||
const alternateResult = host.getResolvedModule(sourceFile, moduleReference, mode)?.alternateResult;
|
||||
@@ -955,7 +962,7 @@ export function getStartPositionOfLine(line: number, sourceFile: SourceFileLike)
|
||||
}
|
||||
|
||||
// This is a useful function for debugging purposes.
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function nodePosToString(node: Node): string {
|
||||
const file = getSourceFileOfNode(node);
|
||||
const loc = getLineAndCharacterOfPosition(file, node.pos);
|
||||
@@ -1098,6 +1105,7 @@ export function insertStatementsAfterCustomPrologue<T extends Statement>(to: T[]
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*
|
||||
* @internal
|
||||
* @knipignore
|
||||
*/
|
||||
export function insertStatementAfterStandardPrologue<T extends Statement>(to: T[], statement: T | undefined): T[] {
|
||||
return insertStatementAfterPrologue(to, statement, isPrologueDirective);
|
||||
@@ -1180,7 +1188,7 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu
|
||||
|
||||
if (isJSDocNode(node) || node.kind === SyntaxKind.JsxText) {
|
||||
// JsxText cannot actually contain comments, even though the scanner will think it sees comments
|
||||
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
return skipTrivia((sourceFile ?? getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
}
|
||||
|
||||
if (includeJsDoc && hasJSDocNodes(node)) {
|
||||
@@ -1192,14 +1200,15 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu
|
||||
// trivia for the list, we may have skipped the JSDocComment as well. So we should process its
|
||||
// first child to determine the actual position of its first token.
|
||||
if (node.kind === SyntaxKind.SyntaxList) {
|
||||
const first = firstOrUndefined(getNodeChildren(node));
|
||||
sourceFile ??= getSourceFileOfNode(node);
|
||||
const first = firstOrUndefined(getNodeChildren(node, sourceFile));
|
||||
if (first) {
|
||||
return getTokenPosOfNode(first, sourceFile, includeJsDoc);
|
||||
}
|
||||
}
|
||||
|
||||
return skipTrivia(
|
||||
(sourceFile || getSourceFileOfNode(node)).text,
|
||||
(sourceFile ?? getSourceFileOfNode(node)).text,
|
||||
node.pos,
|
||||
/*stopAfterLineBreak*/ false,
|
||||
/*stopAtComments*/ false,
|
||||
@@ -1337,6 +1346,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Iterator: new Map(Object.entries({
|
||||
@@ -1614,6 +1627,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Uint8Array: new Map(Object.entries({
|
||||
@@ -1623,6 +1640,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Uint8ClampedArray: new Map(Object.entries({
|
||||
@@ -1632,6 +1653,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Int16Array: new Map(Object.entries({
|
||||
@@ -1641,6 +1666,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Uint16Array: new Map(Object.entries({
|
||||
@@ -1650,6 +1679,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Int32Array: new Map(Object.entries({
|
||||
@@ -1659,6 +1692,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Uint32Array: new Map(Object.entries({
|
||||
@@ -1668,6 +1705,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Float32Array: new Map(Object.entries({
|
||||
@@ -1677,6 +1718,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Float64Array: new Map(Object.entries({
|
||||
@@ -1686,6 +1731,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
BigInt64Array: new Map(Object.entries({
|
||||
@@ -1696,6 +1745,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
BigUint64Array: new Map(Object.entries({
|
||||
@@ -1706,6 +1759,10 @@ export const getScriptTargetFeatures = /* @__PURE__ */ memoize((): ScriptTargetF
|
||||
es2023: [
|
||||
"findLastIndex",
|
||||
"findLast",
|
||||
"toReversed",
|
||||
"toSorted",
|
||||
"toSpliced",
|
||||
"with",
|
||||
],
|
||||
})),
|
||||
Error: new Map(Object.entries({
|
||||
@@ -1843,10 +1900,8 @@ export function isNonGlobalAmbientModule(node: Node): node is ModuleDeclaration
|
||||
* 1. An actual declaration: namespace X { ... }
|
||||
* 2. A Javascript declaration, which is:
|
||||
* An identifier in a nested property access expression: Y in `X.Y.Z = { ... }`
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isEffectiveModuleDeclaration(node: Node) {
|
||||
function isEffectiveModuleDeclaration(node: Node) {
|
||||
return isModuleDeclaration(node) || isIdentifier(node);
|
||||
}
|
||||
|
||||
@@ -2522,12 +2577,10 @@ export function getJSDocCommentRanges(node: Node, text: string) {
|
||||
text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*<reference\s+types\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashLibReferenceRegEx = /^(\/\/\/\s*<reference\s+lib\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
/** @internal */
|
||||
export const fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*<amd-module\s+.*?\/>/;
|
||||
const defaultLibReferenceRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)(('[^']*')|("[^"]*"))\s*\/>/;
|
||||
|
||||
@@ -2633,17 +2686,6 @@ function isPartOfTypeExpressionWithTypeArguments(node: Node) {
|
||||
|| isHeritageClause(node.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isChildOfNodeWithKind(node: Node, kind: SyntaxKind): boolean {
|
||||
while (node) {
|
||||
if (node.kind === kind) {
|
||||
return true;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Warning: This has the same semantics as the forEach family of functions,
|
||||
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
|
||||
/** @internal */
|
||||
@@ -3160,12 +3202,6 @@ export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpress
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isSuperOrSuperProperty(node: Node): node is SuperExpression | SuperProperty {
|
||||
return node.kind === SyntaxKind.SuperKeyword
|
||||
|| isSuperProperty(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for `super`.
|
||||
*
|
||||
@@ -3567,11 +3603,6 @@ export function isSourceFileJS(file: SourceFile): boolean {
|
||||
return isInJSFile(file);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isSourceFileNotJS(file: SourceFile): boolean {
|
||||
return !isInJSFile(file);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isInJSFile(node: Node | undefined): boolean {
|
||||
return !!node && !!(node.flags & NodeFlags.JavaScriptFile);
|
||||
@@ -3886,19 +3917,15 @@ export function isBindableObjectDefinePropertyCall(expr: CallExpression): expr i
|
||||
|
||||
/**
|
||||
* x.y OR x[0]
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpression | PropertyAccessExpression {
|
||||
function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpression | PropertyAccessExpression {
|
||||
return isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* x[0] OR x['a'] OR x[Symbol.y]
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
|
||||
function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
|
||||
return isElementAccessExpression(node) && isStringOrNumericLiteralLike(node.argumentExpression);
|
||||
}
|
||||
|
||||
@@ -4245,8 +4272,7 @@ function getSourceOfDefaultedAssignment(node: Node): Node | undefined {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
|
||||
function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
const v = getSingleVariableOfVariableStatement(node);
|
||||
@@ -4573,7 +4599,7 @@ export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { par
|
||||
return typeParameters && find(typeParameters, p => p.name.escapedText === name);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function hasTypeArguments(node: Node): node is HasTypeArguments {
|
||||
return !!(node as HasTypeArguments).typeArguments;
|
||||
}
|
||||
@@ -4889,46 +4915,6 @@ export function isIdentifierName(node: Identifier): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
// An alias symbol is created by one of the following declarations:
|
||||
// import <symbol> = ...
|
||||
// import <symbol> from ...
|
||||
// import * as <symbol> from ...
|
||||
// import { x as <symbol> } from ...
|
||||
// export { x as <symbol> } from ...
|
||||
// export * as ns <symbol> from ...
|
||||
// export = <EntityNameExpression>
|
||||
// export default <EntityNameExpression>
|
||||
// module.exports = <EntityNameExpression>
|
||||
// module.exports.x = <EntityNameExpression>
|
||||
// const x = require("...")
|
||||
// const { x } = require("...")
|
||||
// const x = require("...").y
|
||||
// const { x } = require("...").y
|
||||
/** @internal */
|
||||
export function isAliasSymbolDeclaration(node: Node): boolean {
|
||||
if (
|
||||
node.kind === SyntaxKind.ImportEqualsDeclaration ||
|
||||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
|
||||
node.kind === SyntaxKind.ImportClause && !!(node as ImportClause).name ||
|
||||
node.kind === SyntaxKind.NamespaceImport ||
|
||||
node.kind === SyntaxKind.NamespaceExport ||
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isInJSFile(node) && (
|
||||
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) ||
|
||||
isPropertyAccessExpression(node)
|
||||
&& isBinaryExpression(node.parent)
|
||||
&& node.parent.left === node
|
||||
&& node.parent.operatorToken.kind === SyntaxKind.EqualsToken
|
||||
&& isAliasableExpression(node.parent.right)
|
||||
);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getAliasDeclarationFromName(node: EntityName): Declaration | undefined {
|
||||
switch (node.parent.kind) {
|
||||
@@ -5067,23 +5053,12 @@ export function isNonContextualKeyword(token: SyntaxKind): boolean {
|
||||
return isKeyword(token) && !isContextualKeyword(token);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isFutureReservedKeyword(token: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstFutureReservedWord <= token && token <= SyntaxKind.LastFutureReservedWord;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isStringANonContextualKeyword(name: string) {
|
||||
const token = stringToToken(name);
|
||||
return token !== undefined && isNonContextualKeyword(token);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isStringAKeyword(name: string) {
|
||||
const token = stringToToken(name);
|
||||
return token !== undefined && isKeyword(token);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isIdentifierANonContextualKeyword(node: Identifier): boolean {
|
||||
const originalKeywordKind = identifierToKeywordKind(node);
|
||||
@@ -5235,11 +5210,6 @@ export function getEscapedTextOfIdentifierOrLiteral(node: PropertyNameLiteral):
|
||||
return isMemberName(node) ? node.escapedText : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPropertyNameForUniqueESSymbol(symbol: Symbol): __String {
|
||||
return `__@${getSymbolId(symbol)}@${symbol.escapedName}` as __String;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getSymbolNameForPrivateIdentifier(containingClassSymbol: Symbol, description: __String): __String {
|
||||
return `__#${getSymbolId(containingClassSymbol)}@${description}` as __String;
|
||||
@@ -5255,24 +5225,13 @@ export function isPrivateIdentifierSymbol(symbol: Symbol): boolean {
|
||||
return startsWith(symbol.escapedName as string, "__#");
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the word "Symbol" with unicode escapes
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isESSymbolIdentifier(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.Identifier && (node as Identifier).escapedText === "Symbol";
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a property name is the special `__proto__` property.
|
||||
* Per the ECMA-262 spec, this only matters for property assignments whose name is
|
||||
* the Identifier `__proto__`, or the string literal `"__proto__"`, but not for
|
||||
* computed property names.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isProtoSetter(node: PropertyName) {
|
||||
function isProtoSetter(node: PropertyName) {
|
||||
return isIdentifier(node) ? idText(node) === "__proto__" :
|
||||
isStringLiteral(node) && node.text === "__proto__";
|
||||
}
|
||||
@@ -5287,9 +5246,8 @@ export type AnonymousFunctionDefinition =
|
||||
* Indicates whether an expression is an anonymous function definition.
|
||||
*
|
||||
* @see https://tc39.es/ecma262/#sec-isanonymousfunctiondefinition
|
||||
* @internal
|
||||
*/
|
||||
export function isAnonymousFunctionDefinition(node: Expression, cb?: (node: AnonymousFunctionDefinition) => boolean): node is WrappedExpression<AnonymousFunctionDefinition> {
|
||||
function isAnonymousFunctionDefinition(node: Expression, cb?: (node: AnonymousFunctionDefinition) => boolean): node is WrappedExpression<AnonymousFunctionDefinition> {
|
||||
node = skipOuterExpressions(node);
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
@@ -5434,11 +5392,6 @@ export function nodeIsSynthesized(range: TextRange): boolean {
|
||||
|| positionIsSynthesized(range.end);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getOriginalSourceFile(sourceFile: SourceFile) {
|
||||
return getParseTreeNode(sourceFile, isSourceFile) || sourceFile;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const enum Associativity {
|
||||
Left,
|
||||
@@ -5499,8 +5452,7 @@ export function getExpressionPrecedence(expression: Expression) {
|
||||
return getOperatorPrecedence(expression.kind, operator, hasArguments);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getOperator(expression: Expression): SyntaxKind {
|
||||
function getOperator(expression: Expression): SyntaxKind {
|
||||
if (expression.kind === SyntaxKind.BinaryExpression) {
|
||||
return (expression as BinaryExpression).operatorToken.kind;
|
||||
}
|
||||
@@ -6103,8 +6055,7 @@ export function getIndentString(level: number) {
|
||||
return indentStrings[level];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getIndentSize() {
|
||||
function getIndentSize() {
|
||||
return indentStrings[1].length;
|
||||
}
|
||||
|
||||
@@ -6366,15 +6317,15 @@ export function getOwnEmitOutputFilePath(fileName: string, host: EmitHost, exten
|
||||
|
||||
/** @internal */
|
||||
export function getDeclarationEmitOutputFilePath(fileName: string, host: EmitHost) {
|
||||
return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host.getCurrentDirectory(), host.getCommonSourceDirectory(), f => host.getCanonicalFileName(f));
|
||||
return getDeclarationEmitOutputFilePathWorker(fileName, host.getCompilerOptions(), host);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getDeclarationEmitOutputFilePathWorker(fileName: string, options: CompilerOptions, currentDirectory: string, commonSourceDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
|
||||
export function getDeclarationEmitOutputFilePathWorker(fileName: string, options: CompilerOptions, host: Pick<EmitHost, "getCommonSourceDirectory" | "getCurrentDirectory" | "getCanonicalFileName">): string {
|
||||
const outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified
|
||||
|
||||
const path = outputDir
|
||||
? getSourceFilePathInNewDirWorker(fileName, outputDir, currentDirectory, commonSourceDirectory, getCanonicalFileName)
|
||||
? getSourceFilePathInNewDirWorker(fileName, outputDir, host.getCurrentDirectory(), host.getCommonSourceDirectory(), f => host.getCanonicalFileName(f))
|
||||
: fileName;
|
||||
const declarationExtension = getDeclarationEmitExtensionForPath(path);
|
||||
return removeFileExtension(path) + declarationExtension;
|
||||
@@ -6491,8 +6442,7 @@ export function getSourceFilePathInNewDir(fileName: string, host: EmitHost, newD
|
||||
return getSourceFilePathInNewDirWorker(fileName, newDirPath, host.getCurrentDirectory(), host.getCommonSourceDirectory(), f => host.getCanonicalFileName(f));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getSourceFilePathInNewDirWorker(fileName: string, newDirPath: string, currentDirectory: string, commonSourceDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
|
||||
function getSourceFilePathInNewDirWorker(fileName: string, newDirPath: string, currentDirectory: string, commonSourceDirectory: string, getCanonicalFileName: GetCanonicalFileName): string {
|
||||
let sourceFilePath = getNormalizedAbsolutePath(fileName, currentDirectory);
|
||||
const isSourceFileInCommonSourceDirectory = getCanonicalFileName(sourceFilePath).indexOf(getCanonicalFileName(commonSourceDirectory)) === 0;
|
||||
sourceFilePath = isSourceFileInCommonSourceDirectory ? sourceFilePath.substring(commonSourceDirectory.length) : sourceFilePath;
|
||||
@@ -6551,8 +6501,7 @@ export function getLineOfLocalPosition(sourceFile: SourceFile, pos: number) {
|
||||
return computeLineOfPosition(lineStarts, pos);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getLineOfLocalPositionFromLineMap(lineMap: readonly number[], pos: number) {
|
||||
function getLineOfLocalPositionFromLineMap(lineMap: readonly number[], pos: number) {
|
||||
return computeLineOfPosition(lineMap, pos);
|
||||
}
|
||||
|
||||
@@ -6736,13 +6685,11 @@ export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDecla
|
||||
return parameter && getEffectiveTypeAnnotationNode(parameter);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function emitNewLineBeforeLeadingComments(lineMap: readonly number[], writer: EmitTextWriter, node: TextRange, leadingComments: readonly CommentRange[] | undefined) {
|
||||
function emitNewLineBeforeLeadingComments(lineMap: readonly number[], writer: EmitTextWriter, node: TextRange, leadingComments: readonly CommentRange[] | undefined) {
|
||||
emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: readonly number[], writer: EmitTextWriter, pos: number, leadingComments: readonly CommentRange[] | undefined) {
|
||||
function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: readonly number[], writer: EmitTextWriter, pos: number, leadingComments: readonly CommentRange[] | undefined) {
|
||||
// If the leading comments start on different line than the start of node, write new line
|
||||
if (
|
||||
leadingComments && leadingComments.length && pos !== leadingComments[0].pos &&
|
||||
@@ -6763,8 +6710,7 @@ export function emitNewLineBeforeLeadingCommentOfPosition(lineMap: readonly numb
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function emitComments(
|
||||
function emitComments(
|
||||
text: string,
|
||||
lineMap: readonly number[],
|
||||
writer: EmitTextWriter,
|
||||
@@ -7032,7 +6978,7 @@ export function getSelectedEffectiveModifierFlags(node: Node, flags: ModifierFla
|
||||
return getEffectiveModifierFlags(node) & flags;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function getSelectedSyntacticModifierFlags(node: Node, flags: ModifierFlags): ModifierFlags {
|
||||
return getSyntacticModifierFlags(node) & flags;
|
||||
}
|
||||
@@ -7132,6 +7078,7 @@ export function getEffectiveModifierFlagsNoCache(node: Node): ModifierFlags {
|
||||
* NOTE: This function does not use `parent` pointers and will not include modifiers from JSDoc.
|
||||
*
|
||||
* @internal
|
||||
* @knipignore
|
||||
*/
|
||||
export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags {
|
||||
let flags = canHaveModifiers(node) ? modifiersToFlags(node.modifiers) : ModifierFlags.None;
|
||||
@@ -7273,10 +7220,6 @@ export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: b
|
||||
&& isLeftHandSideExpression(node.left);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isLeftHandSideOfAssignment(node: Node) {
|
||||
return isAssignmentExpression(node.parent) && node.parent.left === node;
|
||||
}
|
||||
/** @internal */
|
||||
export function isDestructuringAssignment(node: Node): node is DestructuringAssignment {
|
||||
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
|
||||
@@ -7687,17 +7630,6 @@ export function moveRangePastModifiers(node: Node): TextRange {
|
||||
: moveRangePastDecorators(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a TextRange has the same start and end positions.
|
||||
*
|
||||
* @param range A TextRange.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function isCollapsedRange(range: TextRange) {
|
||||
return range.pos === range.end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TextRange for a token at the provides start position.
|
||||
*
|
||||
@@ -7729,7 +7661,7 @@ export function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRa
|
||||
return positionsAreOnSameLine(range1.end, range2.end, sourceFile);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
|
||||
return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile, /*includeComments*/ false), range2.end, sourceFile);
|
||||
}
|
||||
@@ -7745,7 +7677,7 @@ export function getLinesBetweenRangeEndAndRangeStart(range1: TextRange, range2:
|
||||
return getLinesBetweenPositions(sourceFile, range1.end, range2Start);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function getLinesBetweenRangeEndPositions(range1: TextRange, range2: TextRange, sourceFile: SourceFile) {
|
||||
return getLinesBetweenPositions(sourceFile, range1.end, range2.end);
|
||||
}
|
||||
@@ -7760,7 +7692,7 @@ export function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: S
|
||||
return getLinesBetweenPositions(sourceFile, pos1, pos2) === 0;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile, includeComments: boolean) {
|
||||
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos, /*stopAfterLineBreak*/ false, includeComments);
|
||||
}
|
||||
@@ -8067,11 +7999,6 @@ export function getObjectFlags(type: Type): ObjectFlags {
|
||||
return type.flags & TypeFlags.ObjectFlagsType ? (type as ObjectFlagsType).objectFlags : 0;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function forSomeAncestorDirectory(directory: string, callback: (directory: string) => boolean): boolean {
|
||||
return !!forEachAncestorDirectory(directory, d => callback(d) ? true : undefined);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isUMDExportSymbol(symbol: Symbol | undefined): boolean {
|
||||
return !!symbol && !!symbol.declarations && !!symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
|
||||
@@ -8361,6 +8288,7 @@ const objectAllocatorPatchers: ((objectAllocator: ObjectAllocator) => void)[] =
|
||||
/**
|
||||
* Used by `deprecatedCompat` to patch the object allocator to apply deprecations.
|
||||
* @internal
|
||||
* @knipignore
|
||||
*/
|
||||
export function addObjectAllocatorPatcher(fn: (objectAllocator: ObjectAllocator) => void) {
|
||||
objectAllocatorPatchers.push(fn);
|
||||
@@ -8578,8 +8506,7 @@ export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison {
|
||||
Comparison.EqualTo;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function compareDiagnosticsSkipRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison {
|
||||
function compareDiagnosticsSkipRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison {
|
||||
const code1 = getDiagnosticCode(d1);
|
||||
const code2 = getDiagnosticCode(d2);
|
||||
return compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) ||
|
||||
@@ -9040,7 +8967,7 @@ export const getEmitScriptTarget = computedOptions.target.computeValue;
|
||||
export const getEmitModuleKind = computedOptions.module.computeValue;
|
||||
/** @internal */
|
||||
export const getEmitModuleResolutionKind = computedOptions.moduleResolution.computeValue;
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export const getEmitModuleDetectionKind = computedOptions.moduleDetection.computeValue;
|
||||
/** @internal */
|
||||
export const getIsolatedModules = computedOptions.isolatedModules.computeValue;
|
||||
@@ -9343,8 +9270,7 @@ function escapeRegExpCharacter(match: string) {
|
||||
|
||||
const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question];
|
||||
|
||||
/** @internal */
|
||||
export const commonPackageFolders: readonly string[] = ["node_modules", "bower_components", "jspm_packages"];
|
||||
const commonPackageFolders: readonly string[] = ["node_modules", "bower_components", "jspm_packages"];
|
||||
|
||||
const implicitExcludePathRegexPattern = `(?!(${commonPackageFolders.join("|")})(/|$))`;
|
||||
|
||||
@@ -9706,17 +9632,14 @@ export function getScriptKindFromFileName(fileName: string): ScriptKind {
|
||||
|
||||
/**
|
||||
* Groups of supported extensions in order of file resolution precedence. (eg, TS > TSX > DTS and seperately, CTS > DCTS)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const supportedTSExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts], [Extension.Cts, Extension.Dcts], [Extension.Mts, Extension.Dmts]];
|
||||
const supportedTSExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts], [Extension.Cts, Extension.Dcts], [Extension.Mts, Extension.Dmts]];
|
||||
/** @internal */
|
||||
export const supportedTSExtensionsFlat: readonly Extension[] = flatten(supportedTSExtensions);
|
||||
const supportedTSExtensionsWithJson: readonly Extension[][] = [...supportedTSExtensions, [Extension.Json]];
|
||||
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
|
||||
const supportedTSExtensionsForExtractExtension: readonly Extension[] = [Extension.Dts, Extension.Dcts, Extension.Dmts, Extension.Cts, Extension.Mts, Extension.Ts, Extension.Tsx];
|
||||
/** @internal */
|
||||
export const supportedJSExtensions: readonly Extension[][] = [[Extension.Js, Extension.Jsx], [Extension.Mjs], [Extension.Cjs]];
|
||||
const supportedJSExtensions: readonly Extension[][] = [[Extension.Js, Extension.Jsx], [Extension.Mjs], [Extension.Cjs]];
|
||||
/** @internal */
|
||||
export const supportedJSExtensionsFlat: readonly Extension[] = flatten(supportedJSExtensions);
|
||||
const allSupportedExtensions: readonly Extension[][] = [[Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Js, Extension.Jsx], [Extension.Cts, Extension.Dcts, Extension.Cjs], [Extension.Mts, Extension.Dmts, Extension.Mjs]];
|
||||
@@ -9787,8 +9710,7 @@ export const enum ModuleSpecifierEnding {
|
||||
TsExtension,
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function usesExtensionsOnImports({ imports }: SourceFile, hasExtension: (text: string) => boolean = or(hasJSFileExtension, hasTSFileExtension)): boolean {
|
||||
function usesExtensionsOnImports({ imports }: SourceFile, hasExtension: (text: string) => boolean = or(hasJSFileExtension, hasTSFileExtension)): boolean {
|
||||
return firstDefined(imports, ({ text }) =>
|
||||
pathIsRelative(text) && !fileExtensionIsOneOf(text, extensionsNotSupportingExtensionlessResolution)
|
||||
? hasExtension(text)
|
||||
@@ -9917,7 +9839,7 @@ export function removeFileExtension(path: string): string {
|
||||
return path;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function tryRemoveExtension(path: string, extension: string): string | undefined {
|
||||
return fileExtensionIs(path, extension) ? removeExtension(path, extension) : undefined;
|
||||
}
|
||||
@@ -10402,24 +10324,6 @@ export function setParent<T extends Node>(child: T | undefined, parent: T["paren
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bypasses immutability and directly sets the `parent` property of each `Node` in an array of nodes, if is not already set.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function setEachParent<T extends readonly Node[]>(children: T, parent: T[number]["parent"]): T;
|
||||
/** @internal */
|
||||
export function setEachParent<T extends readonly Node[]>(children: T | undefined, parent: T[number]["parent"]): T | undefined;
|
||||
/** @internal */
|
||||
export function setEachParent<T extends readonly Node[]>(children: T | undefined, parent: T[number]["parent"]): T | undefined {
|
||||
if (children) {
|
||||
for (const child of children) {
|
||||
setParent(child, parent);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bypasses immutability and directly sets the `parent` property of each `Node` recursively.
|
||||
* @param rootNode The root node from which to start the recursion.
|
||||
@@ -10734,11 +10638,6 @@ export function getNodeModulePathParts(fullPath: string): NodeModulePathParts |
|
||||
return state > States.NodeModules ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getParameterTypeNode(parameter: ParameterDeclaration | JSDocParameterTag) {
|
||||
return parameter.kind === SyntaxKind.JSDocParameterTag ? parameter.typeExpression?.type : parameter.type;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | EnumDeclaration | ImportClause | ImportSpecifier | ExportSpecifier {
|
||||
switch (node.kind) {
|
||||
@@ -10900,7 +10799,7 @@ export function isExpandoPropertyDeclaration(declaration: Declaration | undefine
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function hasResolutionModeOverride(node: ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined) {
|
||||
export function hasResolutionModeOverride(node: ImportTypeNode | ImportDeclaration | ExportDeclaration | JSDocImportTag | undefined) {
|
||||
if (node === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -160,10 +160,8 @@ import {
|
||||
isKeyword,
|
||||
isModuleBlock,
|
||||
isNonNullExpression,
|
||||
isNotEmittedStatement,
|
||||
isOmittedExpression,
|
||||
isParameter,
|
||||
isPartiallyEmittedExpression,
|
||||
isPrivateIdentifier,
|
||||
isPropertyAccessExpression,
|
||||
isPropertyAssignment,
|
||||
@@ -241,7 +239,6 @@ import {
|
||||
NodeFlags,
|
||||
NonNullChain,
|
||||
normalizePath,
|
||||
NotEmittedStatement,
|
||||
NullLiteral,
|
||||
ObjectBindingOrAssignmentElement,
|
||||
ObjectBindingOrAssignmentPattern,
|
||||
@@ -251,7 +248,6 @@ import {
|
||||
OptionalChainRoot,
|
||||
OuterExpressionKinds,
|
||||
ParameterDeclaration,
|
||||
PartiallyEmittedExpression,
|
||||
pathIsRelative,
|
||||
PostfixUnaryExpression,
|
||||
PrefixUnaryExpression,
|
||||
@@ -260,7 +256,6 @@ import {
|
||||
PrivateIdentifierPropertyAccessExpression,
|
||||
PropertyAccessChain,
|
||||
PropertyAccessExpression,
|
||||
PropertyDeclaration,
|
||||
PropertyName,
|
||||
QualifiedName,
|
||||
ScriptTarget,
|
||||
@@ -1277,11 +1272,6 @@ export function getJSDocTags(node: Node): readonly JSDocTag[] {
|
||||
return getJSDocTagsWorker(node, /*noCache*/ false);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getJSDocTagsNoCache(node: Node): readonly JSDocTag[] {
|
||||
return getJSDocTagsWorker(node, /*noCache*/ true);
|
||||
}
|
||||
|
||||
/** Get the first JSDoc tag of a specified kind, or undefined if not present. */
|
||||
function getFirstJSDocTag<T extends JSDocTag>(node: Node, predicate: (tag: JSDocTag) => tag is T, noCache?: boolean): T | undefined {
|
||||
return find(getJSDocTagsWorker(node, noCache), predicate);
|
||||
@@ -1464,10 +1454,6 @@ export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag
|
||||
//
|
||||
// All node tests in the following list should *not* reference parent pointers so that
|
||||
// they may be used with transformations.
|
||||
/** @internal */
|
||||
export function isNode(node: Node) {
|
||||
return isNodeKind(node.kind);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNodeKind(kind: SyntaxKind) {
|
||||
@@ -1780,19 +1766,6 @@ export function isMethodOrAccessor(node: Node): node is MethodDeclaration | Acce
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNamedClassElement(node: Node): node is MethodDeclaration | AccessorDeclaration | PropertyDeclaration {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Type members
|
||||
|
||||
export function isModifierLike(node: Node): node is ModifierLike {
|
||||
@@ -2127,12 +2100,6 @@ export function isAssertionExpression(node: Node): node is AssertionExpression {
|
||||
|| kind === SyntaxKind.AsExpression;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression {
|
||||
return isNotEmittedStatement(node)
|
||||
|| isPartiallyEmittedExpression(node);
|
||||
}
|
||||
|
||||
// Statement
|
||||
|
||||
export function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement;
|
||||
@@ -2152,8 +2119,7 @@ export function isIterationStatement(node: Node, lookInLabeledStatements: boolea
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isScopeMarker(node: Node) {
|
||||
function isScopeMarker(node: Node) {
|
||||
return isExportAssignment(node) || isExportDeclaration(node);
|
||||
}
|
||||
|
||||
@@ -2202,14 +2168,14 @@ export function isModuleBody(node: Node): node is ModuleBody {
|
||||
|| kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function isNamespaceBody(node: Node): node is NamespaceBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ModuleBlock
|
||||
|| kind === SyntaxKind.ModuleDeclaration;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Identifier
|
||||
|
||||
+17
-8
@@ -55,6 +55,7 @@ import {
|
||||
generateDjb2Hash,
|
||||
getDefaultLibFileName,
|
||||
getDirectoryPath,
|
||||
getEmitDeclarations,
|
||||
getEmitScriptTarget,
|
||||
getLineAndCharacterOfPosition,
|
||||
getNameOfScriptTarget,
|
||||
@@ -155,8 +156,7 @@ function clearScreenIfNotWatchingForFileChanges(system: System, diagnostic: Diag
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const screenStartingMessageCodes: number[] = [
|
||||
const screenStartingMessageCodes: number[] = [
|
||||
Diagnostics.Starting_compilation_in_watch_mode.code,
|
||||
Diagnostics.File_change_detected_Starting_incremental_compilation.code,
|
||||
];
|
||||
@@ -279,18 +279,18 @@ export function getErrorSummaryText(
|
||||
) {
|
||||
if (errorCount === 0) return "";
|
||||
const nonNilFiles = filesInError.filter(fileInError => fileInError !== undefined);
|
||||
const distinctFileNamesWithLines = nonNilFiles.map(fileInError => `${fileInError!.fileName}:${fileInError!.line}`)
|
||||
const distinctFileNamesWithLines = nonNilFiles.map(fileInError => `${fileInError.fileName}:${fileInError.line}`)
|
||||
.filter((value, index, self) => self.indexOf(value) === index);
|
||||
|
||||
const firstFileReference = nonNilFiles[0] && prettyPathForFileError(nonNilFiles[0], host.getCurrentDirectory());
|
||||
|
||||
let messageAndArgs: DiagnosticAndArguments;
|
||||
if (errorCount === 1) {
|
||||
messageAndArgs = filesInError[0] !== undefined ? [Diagnostics.Found_1_error_in_0, firstFileReference!] : [Diagnostics.Found_1_error];
|
||||
messageAndArgs = filesInError[0] !== undefined ? [Diagnostics.Found_1_error_in_0, firstFileReference] : [Diagnostics.Found_1_error];
|
||||
}
|
||||
else {
|
||||
messageAndArgs = distinctFileNamesWithLines.length === 0 ? [Diagnostics.Found_0_errors, errorCount] :
|
||||
distinctFileNamesWithLines.length === 1 ? [Diagnostics.Found_0_errors_in_the_same_file_starting_at_Colon_1, errorCount, firstFileReference!] :
|
||||
distinctFileNamesWithLines.length === 1 ? [Diagnostics.Found_0_errors_in_the_same_file_starting_at_Colon_1, errorCount, firstFileReference] :
|
||||
[Diagnostics.Found_0_errors_in_1_files, errorCount, distinctFileNamesWithLines.length];
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ export function emitFilesAndReportErrors<T extends BuilderProgram>(
|
||||
emitResult: EmitResult;
|
||||
diagnostics: SortedReadonlyArray<Diagnostic>;
|
||||
} {
|
||||
const isListFilesOnly = !!program.getCompilerOptions().listFilesOnly;
|
||||
const options = program.getCompilerOptions();
|
||||
|
||||
// First get and report any syntactic errors.
|
||||
const allDiagnostics = program.getConfigFileParsingDiagnostics().slice();
|
||||
@@ -583,17 +583,25 @@ export function emitFilesAndReportErrors<T extends BuilderProgram>(
|
||||
if (allDiagnostics.length === configFileParsingDiagnosticsLength) {
|
||||
addRange(allDiagnostics, program.getOptionsDiagnostics(cancellationToken));
|
||||
|
||||
if (!isListFilesOnly) {
|
||||
if (!options.listFilesOnly) {
|
||||
addRange(allDiagnostics, program.getGlobalDiagnostics(cancellationToken));
|
||||
|
||||
if (allDiagnostics.length === configFileParsingDiagnosticsLength) {
|
||||
addRange(allDiagnostics, program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken));
|
||||
}
|
||||
|
||||
if (
|
||||
options.noEmit &&
|
||||
getEmitDeclarations(options) &&
|
||||
allDiagnostics.length === configFileParsingDiagnosticsLength
|
||||
) {
|
||||
addRange(allDiagnostics, program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit and report any errors we ran into.
|
||||
const emitResult = isListFilesOnly
|
||||
const emitResult = options.listFilesOnly
|
||||
? { emitSkipped: true, diagnostics: emptyArray }
|
||||
: program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
|
||||
addRange(allDiagnostics, emitResult.diagnostics);
|
||||
@@ -667,6 +675,7 @@ export function createWatchHost(system = sys, reportWatchStatus?: WatchStatusRep
|
||||
watchDirectory: maybeBind(system, system.watchDirectory) || returnNoopFileWatcher,
|
||||
setTimeout: maybeBind(system, system.setTimeout) || noop,
|
||||
clearTimeout: maybeBind(system, system.clearTimeout) || noop,
|
||||
preferNonRecursiveWatch: system.preferNonRecursiveWatch,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,7 @@ export interface WatchHost {
|
||||
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
preferNonRecursiveWatch?: boolean;
|
||||
}
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
@@ -498,6 +499,7 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
compilerHost.toPath = toPath;
|
||||
compilerHost.getCompilationSettings = () => compilerOptions!;
|
||||
compilerHost.useSourceOfProjectReferenceRedirect = maybeBind(host, host.useSourceOfProjectReferenceRedirect);
|
||||
compilerHost.preferNonRecursiveWatch = host.preferNonRecursiveWatch;
|
||||
compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.FailedLookupLocations);
|
||||
compilerHost.watchAffectingFileLocation = (file, cb) => watchFile(file, cb, PollingInterval.High, watchOptions, WatchType.AffectingFileLocation);
|
||||
compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(dir, cb, flags, watchOptions, WatchType.TypeRoots);
|
||||
|
||||
@@ -77,7 +77,7 @@ export type OverloadBinders<T extends OverloadDefinitions> = { [P in OverloadKey
|
||||
*/
|
||||
export type OverloadDeprecations<T extends OverloadDefinitions> = { [P in OverloadKeys<T>]?: DeprecationOptions; };
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function createOverload<T extends OverloadDefinitions>(name: string, overloads: T, binder: OverloadBinders<T>, deprecations?: OverloadDeprecations<T>) {
|
||||
Object.defineProperty(call, "name", { ...Object.getOwnPropertyDescriptor(call, "name"), value: name });
|
||||
|
||||
@@ -137,7 +137,7 @@ export interface BoundOverloadBuilder<T extends OverloadDefinitions> extends Fin
|
||||
// NOTE: We only use this "builder" because we don't infer correctly when calling `createOverload` directly in < TS 4.7,
|
||||
// but lib is currently at TS 4.4. We can switch to directly calling `createOverload` when we update LKG in main.
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export function buildOverload(name: string): OverloadBuilder {
|
||||
return {
|
||||
overload: overloads => ({
|
||||
|
||||
@@ -94,8 +94,7 @@ interface RenameEntry {
|
||||
readonly locations: RenameLocation[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function extractMessage(message: string): string {
|
||||
function extractMessage(message: string): string {
|
||||
// Read the content length
|
||||
const contentLengthPrefix = "Content-Length: ";
|
||||
const lines = message.split(/\r?\n/);
|
||||
@@ -227,12 +226,14 @@ export class SessionClient implements LanguageService {
|
||||
|
||||
openFile(file: string, fileContent?: string, scriptKindName?: "TS" | "JS" | "TSX" | "JSX"): void {
|
||||
const args: protocol.OpenRequestArgs = { file, fileContent, scriptKindName };
|
||||
this.processRequest(protocol.CommandTypes.Open, args);
|
||||
const request = this.processRequest(protocol.CommandTypes.Open, args);
|
||||
this.processResponse(request, /*expectEmptyBody*/ true);
|
||||
}
|
||||
|
||||
closeFile(file: string): void {
|
||||
const args: protocol.FileRequestArgs = { file };
|
||||
this.processRequest(protocol.CommandTypes.Close, args);
|
||||
const request = this.processRequest(protocol.CommandTypes.Close, args);
|
||||
this.processResponse(request, /*expectEmptyBody*/ true);
|
||||
}
|
||||
|
||||
createChangeFileRequestArgs(fileName: string, start: number, end: number, insertString: string): protocol.ChangeRequestArgs {
|
||||
@@ -242,7 +243,8 @@ export class SessionClient implements LanguageService {
|
||||
changeFile(fileName: string, args: protocol.ChangeRequestArgs): void {
|
||||
// clear the line map after an edit
|
||||
this.lineMaps.set(fileName, undefined!); // TODO: GH#18217
|
||||
this.processRequest(protocol.CommandTypes.Change, args);
|
||||
const request = this.processRequest(protocol.CommandTypes.Change, args);
|
||||
this.processResponse(request, /*expectEmptyBody*/ true);
|
||||
}
|
||||
|
||||
toLineColumnOffset(fileName: string, position: number) {
|
||||
@@ -1027,7 +1029,7 @@ export class SessionClient implements LanguageService {
|
||||
};
|
||||
const request = this.processRequest<protocol.GetPasteEditsRequest>(protocol.CommandTypes.GetPasteEdits, args);
|
||||
const response = this.processResponse<protocol.GetPasteEditsResponse>(request);
|
||||
if (!response.body) {
|
||||
if (response.body.edits.length === 0) {
|
||||
return { edits: [] };
|
||||
}
|
||||
const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import sourceMapSupport from "source-map-support";
|
||||
import * as fakes from "./_namespaces/fakes.js";
|
||||
import * as FourSlashInterface from "./_namespaces/FourSlashInterface.js";
|
||||
import * as Harness from "./_namespaces/Harness.js";
|
||||
@@ -4659,22 +4660,9 @@ function runCode(code: string, state: TestState, fileName: string): void {
|
||||
const generatedFile = ts.changeExtension(fileName, ".js");
|
||||
const wrappedCode = `(function(ts, test, goTo, config, verify, edit, debug, format, cancellation, classification, completion, verifyOperationIsCancelled, ignoreInterpolations) {${code}\n//# sourceURL=${ts.getBaseFileName(generatedFile)}\n})`;
|
||||
|
||||
type SourceMapSupportModule = typeof import("source-map-support") & {
|
||||
// TODO(rbuckton): This is missing from the DT definitions and needs to be added.
|
||||
resetRetrieveHandlers(): void;
|
||||
};
|
||||
|
||||
// Provide the content of the current test to 'source-map-support' so that it can give us the correct source positions
|
||||
// for test failures.
|
||||
let sourceMapSupportModule: SourceMapSupportModule | undefined;
|
||||
try {
|
||||
sourceMapSupportModule = require("source-map-support");
|
||||
}
|
||||
catch {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
sourceMapSupportModule?.install({
|
||||
sourceMapSupport.install({
|
||||
retrieveFile: path => {
|
||||
return path === generatedFile ? wrappedCode :
|
||||
undefined!;
|
||||
@@ -4700,7 +4688,7 @@ function runCode(code: string, state: TestState, fileName: string): void {
|
||||
throw err;
|
||||
}
|
||||
finally {
|
||||
sourceMapSupportModule?.resetRetrieveHandlers();
|
||||
sourceMapSupport.resetRetrieveHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import * as Diff from "diff";
|
||||
import fs from "fs";
|
||||
import pathModule from "path";
|
||||
import * as compiler from "./_namespaces/compiler.js";
|
||||
import * as documents from "./_namespaces/documents.js";
|
||||
import * as fakes from "./_namespaces/fakes.js";
|
||||
@@ -54,14 +57,6 @@ export const virtualFileSystemRoot = "/";
|
||||
|
||||
function createNodeIO(): IO {
|
||||
const workspaceRoot = Utils.findUpRoot();
|
||||
let fs: any, pathModule: any;
|
||||
if (require) {
|
||||
fs = require("fs");
|
||||
pathModule = require("path");
|
||||
}
|
||||
else {
|
||||
fs = pathModule = {};
|
||||
}
|
||||
|
||||
function deleteFile(path: string) {
|
||||
try {
|
||||
@@ -458,7 +453,7 @@ export namespace Compiler {
|
||||
): DeclarationCompilationContext | undefined {
|
||||
if (options.declaration && result.diagnostics.length === 0) {
|
||||
if (options.emitDeclarationOnly) {
|
||||
if (result.js.size > 0 || result.dts.size === 0) {
|
||||
if (result.js.size > 0 || (result.dts.size === 0 && !options.noEmit)) {
|
||||
throw new Error("Only declaration files should be generated when emitDeclarationOnly:true");
|
||||
}
|
||||
}
|
||||
@@ -1022,7 +1017,6 @@ export namespace Compiler {
|
||||
}
|
||||
else if (original.text !== doc.text) {
|
||||
jsCode += `\r\n\r\n!!!! File ${Utils.removeTestPathPrefixes(doc.file)} differs from original emit in noCheck emit\r\n`;
|
||||
const Diff = require("diff");
|
||||
const expected = original.text;
|
||||
const actual = doc.text;
|
||||
const patch = Diff.createTwoFilesPatch("Expected", "Actual", expected, actual, "The full check baseline", "with noCheck set");
|
||||
@@ -1518,8 +1512,7 @@ export namespace Baseline {
|
||||
IO.writeFile(actualFileName, encodedActual);
|
||||
}
|
||||
const errorMessage = getBaselineFileChangedErrorMessage(relativeFileName);
|
||||
if (!!require && opts && opts.PrintDiff) {
|
||||
const Diff = require("diff");
|
||||
if (opts && opts.PrintDiff) {
|
||||
const patch = Diff.createTwoFilesPatch("Expected", "Actual", expected, actual, "The current baseline", "The new version");
|
||||
throw new Error(`${errorMessage}${ts.ForegroundColorEscapeSequences.Grey}\n\n${patch}`);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import vm from "vm";
|
||||
import * as Harness from "./_namespaces/Harness.js";
|
||||
import * as ts from "./_namespaces/ts.js";
|
||||
|
||||
@@ -6,7 +7,6 @@ export function encodeString(s: string): string {
|
||||
}
|
||||
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
const vm = require("vm");
|
||||
if (nodeContext) {
|
||||
vm.runInNewContext(fileContents, nodeContext, fileName);
|
||||
}
|
||||
|
||||
@@ -254,15 +254,11 @@ export function verifyResolutionCache(
|
||||
// Verify ref count
|
||||
resolutionToRefs.forEach((info, resolution) => {
|
||||
ts.Debug.assert(
|
||||
resolution.refCount === info.length,
|
||||
`${projectName}:: Expected Resolution ref count ${info.length} but got ${resolution.refCount}`,
|
||||
resolution.files?.size === info.length,
|
||||
`${projectName}:: Expected Resolution ref count ${info.length} but got ${resolution.files?.size}`,
|
||||
() =>
|
||||
`Expected from:: ${JSON.stringify(info, undefined, " ")}` +
|
||||
`Actual from: ${resolution.refCount}`,
|
||||
);
|
||||
ts.Debug.assert(
|
||||
resolutionToExpected.get(resolution)!.refCount === resolution.refCount,
|
||||
`${projectName}:: Expected Resolution ref count ${resolutionToExpected.get(resolution)!.refCount} but got ${resolution.refCount}`,
|
||||
`Actual from: ${resolution.files?.size}`,
|
||||
);
|
||||
verifySet(resolutionToExpected.get(resolution)!.files, resolution.files, `${projectName}:: Resolution files`);
|
||||
});
|
||||
@@ -280,10 +276,9 @@ export function verifyResolutionCache(
|
||||
actual.resolvedTypeReferenceDirectives.forEach((_resolutions, path) => expected.removeResolutionsOfFile(path));
|
||||
expected.finishCachingPerDirectoryResolution(/*newProgram*/ undefined, actualProgram);
|
||||
|
||||
resolutionToExpected.forEach(expected => {
|
||||
ts.Debug.assert(!expected.refCount, `${projectName}:: All the resolution should be released`);
|
||||
ts.Debug.assert(!expected.files?.size, `${projectName}:: Shouldnt ref to any files`);
|
||||
});
|
||||
resolutionToExpected.forEach(
|
||||
expected => ts.Debug.assert(!expected.files?.size, `${projectName}:: Shouldnt ref to any files`),
|
||||
);
|
||||
ts.Debug.assert(expected.resolvedFileToResolution.size === 0, `${projectName}:: resolvedFileToResolution should be released`);
|
||||
ts.Debug.assert(expected.resolutionsWithFailedLookups.size === 0, `${projectName}:: resolutionsWithFailedLookups should be released`);
|
||||
ts.Debug.assert(expected.resolutionsWithOnlyAffectingLocations.size === 0, `${projectName}:: resolutionsWithOnlyAffectingLocations should be released`);
|
||||
@@ -516,6 +511,7 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
|
||||
fileIsOpen: project.fileIsOpen.bind(project),
|
||||
getCurrentProgram: () => project.getCurrentProgram(),
|
||||
|
||||
preferNonRecursiveWatch: project.preferNonRecursiveWatch,
|
||||
watchDirectoryOfFailedLookupLocation: ts.returnNoopFileWatcher,
|
||||
watchAffectingFileLocation: ts.returnNoopFileWatcher,
|
||||
onInvalidatedResolution: ts.noop,
|
||||
|
||||
@@ -127,7 +127,10 @@ export function sanitizeLog(s: string): string {
|
||||
s = s.replace(/"exportMapKey":\s*"\d+ \d+ /g, match => match.replace(/ \d+ /, ` * `));
|
||||
s = s.replace(/getIndentationAtPosition: getCurrentSourceFile: \d+(?:\.\d+)?/, `getIndentationAtPosition: getCurrentSourceFile: *`);
|
||||
s = s.replace(/getIndentationAtPosition: computeIndentation\s*: \d+(?:\.\d+)?/, `getIndentationAtPosition: computeIndentation: *`);
|
||||
s = s.replace(/"duration":\s*\d+(?:.\d+)?/g, `"duration": *`);
|
||||
s = s.replace(/"syntaxDiag":\s*\d+(?:.\d+)?/g, `"syntaxDiag": *`);
|
||||
s = s.replace(/"semanticDiag":\s*\d+(?:.\d+)?/g, `"semanticDiag": *`);
|
||||
s = s.replace(/"suggestionDiag":\s*\d+(?:.\d+)?/g, `"suggestionDiag": *`);
|
||||
s = s.replace(/"regionSemanticDiag":\s*\d+(?:.\d+)?/g, `"regionSemanticDiag": *`);
|
||||
s = replaceAll(s, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
|
||||
s = sanitizeHarnessLSException(s);
|
||||
return s;
|
||||
|
||||
@@ -111,8 +111,7 @@ const unprefixedNodeCoreModuleList = [
|
||||
"zlib",
|
||||
];
|
||||
|
||||
/** @internal */
|
||||
export const prefixedNodeCoreModuleList = unprefixedNodeCoreModuleList.map(name => `node:${name}`);
|
||||
const prefixedNodeCoreModuleList = unprefixedNodeCoreModuleList.map(name => `node:${name}`);
|
||||
|
||||
/** @internal */
|
||||
export const nodeCoreModuleList: readonly string[] = [...unprefixedNodeCoreModuleList, ...prefixedNodeCoreModuleList];
|
||||
|
||||
Vendored
+4
-4
@@ -1,24 +1,24 @@
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Returns an array of values of the enumerable properties of an object
|
||||
* Returns an array of values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
values<T>(o: { [s: string]: T; } | ArrayLike<T>): T[];
|
||||
|
||||
/**
|
||||
* Returns an array of values of the enumerable properties of an object
|
||||
* Returns an array of values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
values(o: {}): any[];
|
||||
|
||||
/**
|
||||
* Returns an array of key/values of the enumerable properties of an object
|
||||
* Returns an array of key/values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
entries<T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][];
|
||||
|
||||
/**
|
||||
* Returns an array of key/values of the enumerable properties of an object
|
||||
* Returns an array of key/values of the enumerable own properties of an object
|
||||
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
|
||||
*/
|
||||
entries(o: {}): [string, any][];
|
||||
|
||||
@@ -8,7 +8,6 @@ export * from "../utilities.js";
|
||||
import * as protocol from "./ts.server.protocol.js";
|
||||
export { protocol };
|
||||
export * from "../scriptInfo.js";
|
||||
export * from "../typingsCache.js";
|
||||
export * from "../project.js";
|
||||
export * from "../editorServices.js";
|
||||
export * from "../moduleSpecifierCache.js";
|
||||
|
||||
@@ -83,6 +83,7 @@ import {
|
||||
noop,
|
||||
normalizePath,
|
||||
normalizeSlashes,
|
||||
notImplemented,
|
||||
optionDeclarations,
|
||||
optionsForWatch,
|
||||
orderedRemoveItem,
|
||||
@@ -170,7 +171,6 @@ import {
|
||||
Msg,
|
||||
NormalizedPath,
|
||||
normalizedPathToPath,
|
||||
nullTypingsInstaller,
|
||||
PackageInstalledResponse,
|
||||
PackageJsonCache,
|
||||
Project,
|
||||
@@ -183,7 +183,6 @@ import {
|
||||
SetTypings,
|
||||
ThrottledOperations,
|
||||
toNormalizedPath,
|
||||
TypingsCache,
|
||||
WatchTypingLocations,
|
||||
} from "./_namespaces/ts.server.js";
|
||||
import * as protocol from "./protocol.js";
|
||||
@@ -569,6 +568,16 @@ function findProjectByName<T extends Project>(projectName: string, projects: T[]
|
||||
}
|
||||
}
|
||||
|
||||
export const nullTypingsInstaller: ITypingsInstaller = {
|
||||
isKnownTypesPackageName: returnFalse,
|
||||
// Should never be called because we never provide a types registry.
|
||||
installPackage: notImplemented,
|
||||
enqueueInstallTypingsRequest: noop,
|
||||
attach: noop,
|
||||
onProjectClosed: noop,
|
||||
globalTypingsCacheLocation: undefined!, // TODO: GH#18217
|
||||
};
|
||||
|
||||
const noopConfigFileWatcher: FileWatcher = { close: noop };
|
||||
|
||||
/** @internal */
|
||||
@@ -787,9 +796,8 @@ function forEachAncestorProject<T>(
|
||||
* Goes through project's resolved project references and finds, creates or reloads project per kind
|
||||
* If project for this resolved reference exists its used immediately otherwise,
|
||||
* follows all references in order, deciding if references of the visited project can be loaded or not
|
||||
* @internal
|
||||
*/
|
||||
export function forEachResolvedProjectReferenceProject<T>(
|
||||
function forEachResolvedProjectReferenceProject<T>(
|
||||
project: ConfiguredProject,
|
||||
fileName: string | undefined,
|
||||
cb: (child: ConfiguredProject, sentConfigFileDiag: boolean) => T | undefined,
|
||||
@@ -1074,13 +1082,17 @@ function getHostWatcherMap<T>(): HostWatcherMap<T> {
|
||||
return { idToCallbacks: new Map(), pathToId: new Map() };
|
||||
}
|
||||
|
||||
function getCanUseWatchEvents(service: ProjectService, canUseWatchEvents: boolean | undefined) {
|
||||
return !!canUseWatchEvents && !!service.eventHandler && !!service.session;
|
||||
}
|
||||
|
||||
function createWatchFactoryHostUsingWatchEvents(service: ProjectService, canUseWatchEvents: boolean | undefined): WatchFactoryHost | undefined {
|
||||
if (!canUseWatchEvents || !service.eventHandler || !service.session) return undefined;
|
||||
if (!getCanUseWatchEvents(service, canUseWatchEvents)) return undefined;
|
||||
const watchedFiles = getHostWatcherMap<FileWatcherCallback>();
|
||||
const watchedDirectories = getHostWatcherMap<DirectoryWatcherCallback>();
|
||||
const watchedDirectoriesRecursive = getHostWatcherMap<DirectoryWatcherCallback>();
|
||||
let ids = 1;
|
||||
service.session.addProtocolHandler(protocol.CommandTypes.WatchChange, req => {
|
||||
service.session!.addProtocolHandler(protocol.CommandTypes.WatchChange, req => {
|
||||
onWatchChange((req as protocol.WatchChangeRequest).arguments);
|
||||
return { responseRequired: false };
|
||||
});
|
||||
@@ -1173,9 +1185,6 @@ function createWatchFactoryHostUsingWatchEvents(service: ProjectService, canUseW
|
||||
}
|
||||
|
||||
export class ProjectService {
|
||||
/** @internal */
|
||||
readonly typingsCache: TypingsCache;
|
||||
|
||||
/** @internal */
|
||||
readonly documentRegistry: DocumentRegistry;
|
||||
|
||||
@@ -1321,6 +1330,7 @@ export class ProjectService {
|
||||
/** @internal */ verifyDocumentRegistry = noop;
|
||||
/** @internal */ verifyProgram: (project: Project) => void = noop;
|
||||
/** @internal */ onProjectCreation: (project: Project) => void = noop;
|
||||
/** @internal */ canUseWatchEvents: boolean;
|
||||
|
||||
readonly jsDocParsingMode: JSDocParsingMode | undefined;
|
||||
|
||||
@@ -1367,8 +1377,6 @@ export class ProjectService {
|
||||
|
||||
this.typingsInstaller.attach(this);
|
||||
|
||||
this.typingsCache = new TypingsCache(this.typingsInstaller);
|
||||
|
||||
this.hostConfiguration = {
|
||||
formatCodeOptions: getDefaultFormatCodeSettings(this.host.newLine),
|
||||
preferences: emptyOptions,
|
||||
@@ -1392,6 +1400,7 @@ export class ProjectService {
|
||||
log,
|
||||
getDetailWatchInfo,
|
||||
);
|
||||
this.canUseWatchEvents = getCanUseWatchEvents(this, opts.canUseWatchEvents);
|
||||
opts.incrementalVerifier?.(this);
|
||||
}
|
||||
|
||||
@@ -1481,11 +1490,16 @@ export class ProjectService {
|
||||
switch (response.kind) {
|
||||
case ActionSet:
|
||||
// Update the typing files and update the project
|
||||
project.updateTypingFiles(this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings));
|
||||
project.updateTypingFiles(
|
||||
response.compilerOptions,
|
||||
response.typeAcquisition,
|
||||
response.unresolvedImports,
|
||||
response.typings,
|
||||
);
|
||||
return;
|
||||
case ActionInvalidate:
|
||||
// Do not clear resolution cache, there was changes detected in typings, so enque typing request and let it get us correct results
|
||||
this.typingsCache.enqueueInstallTypingsForProject(project, project.lastCachedUnresolvedImportsList, /*forceRefresh*/ true);
|
||||
project.enqueueInstallTypingsForProject(/*forceRefresh*/ true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+120
-29
@@ -4,6 +4,7 @@ import {
|
||||
append,
|
||||
ApplyCodeActionCommandResult,
|
||||
arrayFrom,
|
||||
arrayIsEqualTo,
|
||||
arrayToMap,
|
||||
BuilderState,
|
||||
CachedDirectoryStructureHost,
|
||||
@@ -143,6 +144,7 @@ import {
|
||||
ModuleImportResult,
|
||||
Msg,
|
||||
NormalizedPath,
|
||||
nullTypingsInstaller,
|
||||
PackageJsonWatcher,
|
||||
ProjectOptions,
|
||||
ProjectService,
|
||||
@@ -150,7 +152,6 @@ import {
|
||||
ServerHost,
|
||||
Session,
|
||||
toNormalizedPath,
|
||||
TypingsCache,
|
||||
updateProjectIfDirty,
|
||||
} from "./_namespaces/ts.server.js";
|
||||
import * as protocol from "./protocol.js";
|
||||
@@ -306,6 +307,59 @@ const enum TypingWatcherType {
|
||||
|
||||
type TypingWatchers = Map<Path, FileWatcher> & { isInvoked?: boolean; };
|
||||
|
||||
interface TypingsCacheEntry {
|
||||
readonly typeAcquisition: TypeAcquisition;
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
readonly unresolvedImports: SortedReadonlyArray<string> | undefined;
|
||||
}
|
||||
|
||||
function setIsEqualTo(arr1: string[] | undefined, arr2: string[] | undefined): boolean {
|
||||
if (arr1 === arr2) {
|
||||
return true;
|
||||
}
|
||||
if ((arr1 || emptyArray).length === 0 && (arr2 || emptyArray).length === 0) {
|
||||
return true;
|
||||
}
|
||||
const set = new Map<string, boolean>();
|
||||
let unique = 0;
|
||||
|
||||
for (const v of arr1!) {
|
||||
if (set.get(v) !== true) {
|
||||
set.set(v, true);
|
||||
unique++;
|
||||
}
|
||||
}
|
||||
for (const v of arr2!) {
|
||||
const isSet = set.get(v);
|
||||
if (isSet === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (isSet === true) {
|
||||
set.set(v, false);
|
||||
unique--;
|
||||
}
|
||||
}
|
||||
return unique === 0;
|
||||
}
|
||||
|
||||
function typeAcquisitionChanged(opt1: TypeAcquisition, opt2: TypeAcquisition): boolean {
|
||||
return opt1.enable !== opt2.enable ||
|
||||
!setIsEqualTo(opt1.include, opt2.include) ||
|
||||
!setIsEqualTo(opt1.exclude, opt2.exclude);
|
||||
}
|
||||
|
||||
function compilerOptionsChanged(opt1: CompilerOptions, opt2: CompilerOptions): boolean {
|
||||
// TODO: add more relevant properties
|
||||
return getAllowJSCompilerOption(opt1) !== getAllowJSCompilerOption(opt2);
|
||||
}
|
||||
|
||||
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string> | undefined, imports2: SortedReadonlyArray<string> | undefined): boolean {
|
||||
if (imports1 === imports2) {
|
||||
return false;
|
||||
}
|
||||
return !arrayIsEqualTo(imports1, imports2);
|
||||
}
|
||||
|
||||
export abstract class Project implements LanguageServiceHost, ModuleResolutionHost {
|
||||
private rootFilesMap = new Map<Path, ProjectRootFile>();
|
||||
private program: Program | undefined;
|
||||
@@ -388,6 +442,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
/** @internal */
|
||||
typingFiles: SortedReadonlyArray<string> = emptyArray;
|
||||
|
||||
private typingsCache: TypingsCacheEntry | undefined;
|
||||
|
||||
private typingWatchers: TypingWatchers | undefined;
|
||||
|
||||
/** @internal */
|
||||
@@ -499,6 +555,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
protected typeAcquisition: TypeAcquisition | undefined;
|
||||
/** @internal */
|
||||
createHash = maybeBind(this.projectService.host, this.projectService.host.createHash);
|
||||
/** @internal*/ preferNonRecursiveWatch: boolean | undefined;
|
||||
|
||||
readonly jsDocParsingMode: JSDocParsingMode | undefined;
|
||||
|
||||
@@ -559,6 +616,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.trace = s => host.trace!(s);
|
||||
}
|
||||
this.realpath = maybeBind(host, host.realpath);
|
||||
this.preferNonRecursiveWatch = this.projectService.canUseWatchEvents || host.preferNonRecursiveWatch;
|
||||
|
||||
// Use the current directory as resolution root only if the project created using current directory string
|
||||
this.resolutionCache = createResolutionCache(
|
||||
@@ -578,10 +636,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
}
|
||||
|
||||
isKnownTypesPackageName(name: string): boolean {
|
||||
return this.typingsCache.isKnownTypesPackageName(name);
|
||||
return this.projectService.typingsInstaller.isKnownTypesPackageName(name);
|
||||
}
|
||||
installPackage(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult> {
|
||||
return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) });
|
||||
return this.projectService.typingsInstaller.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) });
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -589,10 +647,6 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
return this.getGlobalCache();
|
||||
}
|
||||
|
||||
private get typingsCache(): TypingsCache {
|
||||
return this.projectService.typingsCache;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getSymlinkCache(): SymlinkCache {
|
||||
if (!this.symlinks) {
|
||||
@@ -1059,7 +1113,8 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
}
|
||||
|
||||
close() {
|
||||
this.projectService.typingsCache.onProjectClosed(this);
|
||||
if (this.typingsCache) this.projectService.typingsInstaller.onProjectClosed(this);
|
||||
this.typingsCache = undefined;
|
||||
this.closeWatchingTypingLocations();
|
||||
// if we have a program - release all files that are enlisted in program but arent root
|
||||
// The releasing of the roots happens later
|
||||
@@ -1338,6 +1393,24 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.hasAddedOrRemovedSymlinks = true;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
onReleaseOldSourceFile(
|
||||
oldSourceFile: SourceFile,
|
||||
_oldOptions: CompilerOptions,
|
||||
hasSourceFileByPath: boolean,
|
||||
newSourceFileByResolvedPath: SourceFile | undefined,
|
||||
) {
|
||||
if (
|
||||
!newSourceFileByResolvedPath ||
|
||||
(oldSourceFile.resolvedPath === oldSourceFile.path && newSourceFileByResolvedPath.resolvedPath !== oldSourceFile.path)
|
||||
) {
|
||||
// new program does not contain this file - detach it from the project
|
||||
// - remove resolutions only if the new program doesnt contain source file by the path
|
||||
// (not resolvedPath since path is used for resolution)
|
||||
this.detachScriptInfoFromProject(oldSourceFile.fileName, hasSourceFileByPath);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
updateFromProjectInProgress = false;
|
||||
|
||||
@@ -1379,7 +1452,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program!, this.cachedUnresolvedImportsPerFile);
|
||||
}
|
||||
|
||||
this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles);
|
||||
this.enqueueInstallTypingsForProject(hasAddedorRemovedFiles);
|
||||
}
|
||||
else {
|
||||
this.lastCachedUnresolvedImportsList = undefined;
|
||||
@@ -1401,7 +1474,41 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
updateTypingFiles(typingFiles: SortedReadonlyArray<string>) {
|
||||
enqueueInstallTypingsForProject(forceRefresh: boolean) {
|
||||
const typeAcquisition = this.getTypeAcquisition();
|
||||
|
||||
if (!typeAcquisition || !typeAcquisition.enable || this.projectService.typingsInstaller === nullTypingsInstaller) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entry = this.typingsCache;
|
||||
if (
|
||||
forceRefresh ||
|
||||
!entry ||
|
||||
typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) ||
|
||||
compilerOptionsChanged(this.getCompilationSettings(), entry.compilerOptions) ||
|
||||
unresolvedImportsChanged(this.lastCachedUnresolvedImportsList, entry.unresolvedImports)
|
||||
) {
|
||||
// Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
|
||||
// instead it acts as a placeholder to prevent issuing multiple requests
|
||||
this.typingsCache = {
|
||||
compilerOptions: this.getCompilationSettings(),
|
||||
typeAcquisition,
|
||||
unresolvedImports: this.lastCachedUnresolvedImportsList,
|
||||
};
|
||||
// something has been changed, issue a request to update typings
|
||||
this.projectService.typingsInstaller.enqueueInstallTypingsRequest(this, typeAcquisition, this.lastCachedUnresolvedImportsList);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
updateTypingFiles(compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>, newTypings: string[]) {
|
||||
this.typingsCache = {
|
||||
compilerOptions,
|
||||
typeAcquisition,
|
||||
unresolvedImports,
|
||||
};
|
||||
const typingFiles = !typeAcquisition || !typeAcquisition.enable ? emptyArray : sort(newTypings);
|
||||
if (enumerateInsertsAndDeletes<string, string>(typingFiles, this.typingFiles, getStringComparer(!this.useCaseSensitiveFileNames()), /*inserted*/ noop, removed => this.detachScriptInfoFromProject(removed))) {
|
||||
// If typing files changed, then only schedule project update
|
||||
this.typingFiles = typingFiles;
|
||||
@@ -1550,22 +1657,6 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
let hasNewProgram = false;
|
||||
if (this.program && (!oldProgram || (this.program !== oldProgram && this.program.structureIsReused !== StructureIsReused.Completely))) {
|
||||
hasNewProgram = true;
|
||||
if (oldProgram) {
|
||||
for (const f of oldProgram.getSourceFiles()) {
|
||||
const newFile = this.program.getSourceFileByPath(f.resolvedPath);
|
||||
if (!newFile || (f.resolvedPath === f.path && newFile.resolvedPath !== f.path)) {
|
||||
// new program does not contain this file - detach it from the project
|
||||
// - remove resolutions only if the new program doesnt contain source file by the path (not resolvedPath since path is used for resolution)
|
||||
this.detachScriptInfoFromProject(f.fileName, !!this.program.getSourceFileByPath(f.path), /*syncDirWatcherRemove*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
oldProgram.forEachResolvedProjectReference(resolvedProjectReference => {
|
||||
if (!this.program!.getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) {
|
||||
this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName, /*noRemoveResolution*/ undefined, /*syncDirWatcherRemove*/ true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update roots
|
||||
this.rootFilesMap.forEach((value, path) => {
|
||||
@@ -1610,7 +1701,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
!sourceFile ||
|
||||
sourceFile.resolvedPath !== source ||
|
||||
!this.isValidGeneratedFileWatcher(
|
||||
getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.currentDirectory, this.program!.getCommonSourceDirectory(), this.getCanonicalFileName),
|
||||
getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, this.compilerOptions, this.program!),
|
||||
watcher,
|
||||
)
|
||||
) {
|
||||
@@ -1702,12 +1793,12 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
this.projectService.sendPerformanceEvent(kind, durationMs);
|
||||
}
|
||||
|
||||
private detachScriptInfoFromProject(uncheckedFileName: string, noRemoveResolution?: boolean, syncDirWatcherRemove?: boolean) {
|
||||
private detachScriptInfoFromProject(uncheckedFileName: string, noRemoveResolution?: boolean) {
|
||||
const scriptInfoToDetach = this.projectService.getScriptInfo(uncheckedFileName);
|
||||
if (scriptInfoToDetach) {
|
||||
scriptInfoToDetach.detachFromProject(this);
|
||||
if (!noRemoveResolution) {
|
||||
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path, syncDirWatcherRemove);
|
||||
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-8
@@ -311,6 +311,22 @@ export interface PerformanceData {
|
||||
* The time spent creating or updating the auto-import program, in milliseconds.
|
||||
*/
|
||||
createAutoImportProviderProgramDurationMs?: number;
|
||||
/**
|
||||
* The time spent computing diagnostics, in milliseconds.
|
||||
*/
|
||||
diagnosticsDuration?: FileDiagnosticPerformanceData[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Time spent computing each kind of diagnostics, in milliseconds.
|
||||
*/
|
||||
export type DiagnosticPerformanceData = { [Kind in DiagnosticEventKind]?: number; };
|
||||
|
||||
export interface FileDiagnosticPerformanceData extends DiagnosticPerformanceData {
|
||||
/**
|
||||
* The file for which the performance data is reported.
|
||||
*/
|
||||
file: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,7 +444,7 @@ export interface OutliningSpansRequestFull extends FileRequest {
|
||||
/**
|
||||
* Response to OutliningSpansRequest request.
|
||||
*
|
||||
* @internal
|
||||
* @internal @knipignore
|
||||
*/
|
||||
export interface OutliningSpansResponseFull extends Response {
|
||||
body?: ts.OutliningSpan[];
|
||||
@@ -1257,7 +1273,7 @@ export interface RenameFullRequest extends FileLocationRequest {
|
||||
readonly arguments: RenameRequestArgs;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export interface RenameFullResponse extends Response {
|
||||
readonly body: readonly RenameLocation[];
|
||||
}
|
||||
@@ -2497,6 +2513,7 @@ export interface RequestCompletedEvent extends Event {
|
||||
|
||||
export interface RequestCompletedEventBody {
|
||||
request_seq: number;
|
||||
performanceData?: PerformanceData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2587,11 +2604,6 @@ export interface DiagnosticEventBody {
|
||||
* Spans where the region diagnostic was requested, if this is a region semantic diagnostic event.
|
||||
*/
|
||||
spans?: TextSpan[];
|
||||
|
||||
/**
|
||||
* Time spent computing the diagnostics, in milliseconds.
|
||||
*/
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag" | "regionSemanticDiag";
|
||||
@@ -2756,7 +2768,7 @@ export interface CloseFileWatcherEventBody {
|
||||
readonly id: number;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export type AnyEvent =
|
||||
| RequestCompletedEvent
|
||||
| DiagnosticEvent
|
||||
|
||||
+113
-52
@@ -130,6 +130,7 @@ import {
|
||||
TextRange,
|
||||
TextSpan,
|
||||
textSpanEnd,
|
||||
timestamp,
|
||||
toArray,
|
||||
toFileNameLowerCase,
|
||||
tracing,
|
||||
@@ -337,15 +338,21 @@ interface NextStep {
|
||||
delay(actionType: string, ms: number, action: () => void): void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type PerformanceData =
|
||||
& Omit<protocol.PerformanceData, "diagnosticsDuration">
|
||||
& { diagnosticsDuration?: Map<NormalizedPath, protocol.DiagnosticPerformanceData>; };
|
||||
|
||||
/**
|
||||
* External capabilities used by multistep operation
|
||||
*/
|
||||
interface MultistepOperationHost {
|
||||
getCurrentRequestId(): number;
|
||||
sendRequestCompletedEvent(requestId: number): void;
|
||||
getPerformanceData(): PerformanceData | undefined;
|
||||
sendRequestCompletedEvent(requestId: number, performanceData: PerformanceData | undefined): void;
|
||||
getServerHost(): ServerHost;
|
||||
isCancellationRequested(): boolean;
|
||||
executeWithRequestId(requestId: number, action: () => void): void;
|
||||
executeWithRequestId(requestId: number, action: () => void, performanceData: PerformanceData | undefined): void;
|
||||
logError(error: Error, message: string): void;
|
||||
}
|
||||
|
||||
@@ -355,6 +362,7 @@ interface MultistepOperationHost {
|
||||
*/
|
||||
class MultistepOperation implements NextStep {
|
||||
private requestId: number | undefined;
|
||||
private performanceData: PerformanceData | undefined;
|
||||
private timerHandle: any;
|
||||
private immediateId: number | undefined;
|
||||
|
||||
@@ -368,11 +376,12 @@ class MultistepOperation implements NextStep {
|
||||
|
||||
private complete() {
|
||||
if (this.requestId !== undefined) {
|
||||
this.operationHost.sendRequestCompletedEvent(this.requestId);
|
||||
this.operationHost.sendRequestCompletedEvent(this.requestId, this.performanceData);
|
||||
this.requestId = undefined;
|
||||
}
|
||||
this.setTimerHandle(undefined);
|
||||
this.setImmediateId(undefined);
|
||||
this.performanceData = undefined;
|
||||
}
|
||||
|
||||
public immediate(actionType: string, action: () => void) {
|
||||
@@ -381,7 +390,7 @@ class MultistepOperation implements NextStep {
|
||||
this.setImmediateId(
|
||||
this.operationHost.getServerHost().setImmediate(() => {
|
||||
this.immediateId = undefined;
|
||||
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action));
|
||||
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action), this.performanceData);
|
||||
}, actionType),
|
||||
);
|
||||
}
|
||||
@@ -393,7 +402,7 @@ class MultistepOperation implements NextStep {
|
||||
this.operationHost.getServerHost().setTimeout(
|
||||
() => {
|
||||
this.timerHandle = undefined;
|
||||
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action));
|
||||
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action), this.performanceData);
|
||||
},
|
||||
ms,
|
||||
actionType,
|
||||
@@ -428,6 +437,7 @@ class MultistepOperation implements NextStep {
|
||||
this.operationHost.logError(e, `delayed processing of request ${this.requestId}`);
|
||||
}
|
||||
}
|
||||
this.performanceData = this.operationHost.getPerformanceData();
|
||||
if (stop || !this.hasPendingWork()) {
|
||||
this.complete();
|
||||
}
|
||||
@@ -975,7 +985,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
protected projectService: ProjectService;
|
||||
private changeSeq = 0;
|
||||
|
||||
private performanceData: protocol.PerformanceData | undefined;
|
||||
private performanceData: PerformanceData | undefined;
|
||||
|
||||
private currentRequestId!: number;
|
||||
private errorCheck: MultistepOperation;
|
||||
@@ -1013,11 +1023,12 @@ export class Session<TMessage = string> implements EventSender {
|
||||
? opts.eventHandler || (event => this.defaultEventHandler(event))
|
||||
: undefined;
|
||||
const multistepOperationHost: MultistepOperationHost = {
|
||||
executeWithRequestId: (requestId, action) => this.executeWithRequestId(requestId, action),
|
||||
executeWithRequestId: (requestId, action, performanceData) => this.executeWithRequestId(requestId, action, performanceData),
|
||||
getCurrentRequestId: () => this.currentRequestId,
|
||||
getPerformanceData: () => this.performanceData,
|
||||
getServerHost: () => this.host,
|
||||
logError: (err, cmd) => this.logError(err, cmd),
|
||||
sendRequestCompletedEvent: requestId => this.sendRequestCompletedEvent(requestId),
|
||||
sendRequestCompletedEvent: (requestId, performanceData) => this.sendRequestCompletedEvent(requestId, performanceData),
|
||||
isCancellationRequested: () => this.cancellationToken.isCancellationRequested(),
|
||||
};
|
||||
this.errorCheck = new MultistepOperation(multistepOperationHost);
|
||||
@@ -1067,17 +1078,36 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
}
|
||||
|
||||
private sendRequestCompletedEvent(requestId: number): void {
|
||||
this.event<protocol.RequestCompletedEventBody>({ request_seq: requestId }, "requestCompleted");
|
||||
private sendRequestCompletedEvent(requestId: number, performanceData: PerformanceData | undefined): void {
|
||||
this.event<protocol.RequestCompletedEventBody>(
|
||||
{
|
||||
request_seq: requestId,
|
||||
performanceData: performanceData && toProtocolPerformanceData(performanceData),
|
||||
},
|
||||
"requestCompleted",
|
||||
);
|
||||
}
|
||||
|
||||
private addPerformanceData(key: keyof protocol.PerformanceData, value: number) {
|
||||
private addPerformanceData(key: Exclude<keyof PerformanceData, "diagnosticsDuration">, value: number) {
|
||||
if (!this.performanceData) {
|
||||
this.performanceData = {};
|
||||
}
|
||||
this.performanceData[key] = (this.performanceData[key] ?? 0) + value;
|
||||
}
|
||||
|
||||
private addDiagnosticsPerformanceData(
|
||||
file: NormalizedPath,
|
||||
kind: protocol.DiagnosticEventKind,
|
||||
duration: number,
|
||||
): void {
|
||||
if (!this.performanceData) {
|
||||
this.performanceData = {};
|
||||
}
|
||||
let fileDiagnosticDuration = this.performanceData.diagnosticsDuration?.get(file);
|
||||
if (!fileDiagnosticDuration) (this.performanceData.diagnosticsDuration ??= new Map()).set(file, fileDiagnosticDuration = {});
|
||||
fileDiagnosticDuration[kind] = duration;
|
||||
}
|
||||
|
||||
private performanceEventHandler(event: PerformanceEvent) {
|
||||
switch (event.kind) {
|
||||
case "UpdateGraph":
|
||||
@@ -1217,14 +1247,21 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
doOutput(info: {} | undefined, cmdName: string, reqSeq: number, success: boolean, message?: string): void {
|
||||
doOutput(
|
||||
info: {} | undefined,
|
||||
cmdName: string,
|
||||
reqSeq: number,
|
||||
success: boolean,
|
||||
performanceData: PerformanceData | undefined,
|
||||
message?: string,
|
||||
): void {
|
||||
const res: protocol.Response = {
|
||||
seq: 0,
|
||||
type: "response",
|
||||
command: cmdName,
|
||||
request_seq: reqSeq,
|
||||
success,
|
||||
performanceData: this.performanceData,
|
||||
performanceData: performanceData && toProtocolPerformanceData(performanceData),
|
||||
};
|
||||
|
||||
if (success) {
|
||||
@@ -1259,7 +1296,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
|
||||
private semanticCheck(file: NormalizedPath, project: Project) {
|
||||
const diagnosticsStartTime = this.hrtime();
|
||||
const diagnosticsStartTime = timestamp();
|
||||
tracing?.push(tracing.Phase.Session, "semanticCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails
|
||||
const diags = isDeclarationFileInJSOnlyNonConfiguredProject(project, file)
|
||||
? emptyArray
|
||||
@@ -1269,21 +1306,21 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
|
||||
private syntacticCheck(file: NormalizedPath, project: Project) {
|
||||
const diagnosticsStartTime = this.hrtime();
|
||||
const diagnosticsStartTime = timestamp();
|
||||
tracing?.push(tracing.Phase.Session, "syntacticCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails
|
||||
this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag", diagnosticsStartTime);
|
||||
tracing?.pop();
|
||||
}
|
||||
|
||||
private suggestionCheck(file: NormalizedPath, project: Project) {
|
||||
const diagnosticsStartTime = this.hrtime();
|
||||
const diagnosticsStartTime = timestamp();
|
||||
tracing?.push(tracing.Phase.Session, "suggestionCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails
|
||||
this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag", diagnosticsStartTime);
|
||||
tracing?.pop();
|
||||
}
|
||||
|
||||
private regionSemanticCheck(file: NormalizedPath, project: Project, ranges: TextRange[]): void {
|
||||
const diagnosticsStartTime = this.hrtime();
|
||||
const diagnosticsStartTime = timestamp();
|
||||
tracing?.push(tracing.Phase.Session, "regionSemanticCheck", { file, configFilePath: (project as ConfiguredProject).canonicalConfigFilePath }); // undefined is fine if the cast fails
|
||||
let diagnosticsResult;
|
||||
if (!this.shouldDoRegionCheck(file) || !(diagnosticsResult = project.getLanguageService().getRegionSemanticDiagnostics(file, ranges))) {
|
||||
@@ -1308,23 +1345,22 @@ export class Session<TMessage = string> implements EventSender {
|
||||
project: Project,
|
||||
diagnostics: readonly Diagnostic[],
|
||||
kind: protocol.DiagnosticEventKind,
|
||||
diagnosticsStartTime: [number, number],
|
||||
diagnosticsStartTime: number,
|
||||
spans?: TextSpan[],
|
||||
): void {
|
||||
try {
|
||||
const scriptInfo = Debug.checkDefined(project.getScriptInfo(file));
|
||||
const duration = hrTimeToMilliseconds(this.hrtime(diagnosticsStartTime));
|
||||
|
||||
const duration = timestamp() - diagnosticsStartTime;
|
||||
const body: protocol.DiagnosticEventBody = {
|
||||
file,
|
||||
diagnostics: diagnostics.map(diag => formatDiag(file, project, diag)),
|
||||
spans: spans?.map(span => toProtocolTextSpan(span, scriptInfo)),
|
||||
duration,
|
||||
};
|
||||
this.event<protocol.DiagnosticEventBody>(
|
||||
body,
|
||||
kind,
|
||||
);
|
||||
this.addDiagnosticsPerformanceData(file, kind, duration);
|
||||
}
|
||||
catch (err) {
|
||||
this.logError(err, kind);
|
||||
@@ -2606,16 +2642,14 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
}
|
||||
|
||||
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
|
||||
private reload(args: protocol.ReloadRequestArgs) {
|
||||
const file = toNormalizedPath(args.file);
|
||||
const tempFileName = args.tmpfile === undefined ? undefined : toNormalizedPath(args.tmpfile);
|
||||
const info = this.projectService.getScriptInfoForNormalizedPath(file);
|
||||
if (info) {
|
||||
this.changeSeq++;
|
||||
// make sure no changes happen before this one is finished
|
||||
if (info.reloadFromFile(tempFileName)) {
|
||||
this.doOutput(/*info*/ undefined, protocol.CommandTypes.Reload, reqSeq, /*success*/ true);
|
||||
}
|
||||
info.reloadFromFile(tempFileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3292,12 +3326,13 @@ export class Session<TMessage = string> implements EventSender {
|
||||
|
||||
exit() {/*overridden*/}
|
||||
|
||||
private notRequired(): HandlerResponse {
|
||||
return { responseRequired: false };
|
||||
private notRequired(request: protocol.Request | undefined): HandlerResponse {
|
||||
if (request) this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ true, this.performanceData);
|
||||
return { responseRequired: false, performanceData: this.performanceData };
|
||||
}
|
||||
|
||||
private requiredResponse(response: {} | undefined): HandlerResponse {
|
||||
return { response, responseRequired: true };
|
||||
return { response, responseRequired: true, performanceData: this.performanceData };
|
||||
}
|
||||
|
||||
private handlers = new Map(Object.entries<(request: any) => HandlerResponse>({ // TODO(jakebailey): correctly type the handlers
|
||||
@@ -3376,7 +3411,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
},
|
||||
[protocol.CommandTypes.Exit]: () => {
|
||||
this.exit();
|
||||
return this.notRequired();
|
||||
return this.notRequired(/*request*/ undefined);
|
||||
},
|
||||
[protocol.CommandTypes.Definition]: (request: protocol.DefinitionRequest) => {
|
||||
return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ true));
|
||||
@@ -3427,7 +3462,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
convertScriptKindName(request.arguments.scriptKindName!), // TODO: GH#18217
|
||||
request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : undefined,
|
||||
);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.Quickinfo]: (request: protocol.QuickInfoRequest) => {
|
||||
return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true));
|
||||
@@ -3534,34 +3569,33 @@ export class Session<TMessage = string> implements EventSender {
|
||||
},
|
||||
[protocol.CommandTypes.Geterr]: (request: protocol.GeterrRequest) => {
|
||||
this.errorCheck.startNew(next => this.getDiagnostics(next, request.arguments.delay, request.arguments.files));
|
||||
return this.notRequired();
|
||||
return this.notRequired(/*request*/ undefined);
|
||||
},
|
||||
[protocol.CommandTypes.GeterrForProject]: (request: protocol.GeterrForProjectRequest) => {
|
||||
this.errorCheck.startNew(next => this.getDiagnosticsForProject(next, request.arguments.delay, request.arguments.file));
|
||||
return this.notRequired();
|
||||
return this.notRequired(/*request*/ undefined);
|
||||
},
|
||||
[protocol.CommandTypes.Change]: (request: protocol.ChangeRequest) => {
|
||||
this.change(request.arguments);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.Configure]: (request: protocol.ConfigureRequest) => {
|
||||
this.projectService.setHostConfiguration(request.arguments);
|
||||
this.doOutput(/*info*/ undefined, protocol.CommandTypes.Configure, request.seq, /*success*/ true);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.Reload]: (request: protocol.ReloadRequest) => {
|
||||
this.reload(request.arguments, request.seq);
|
||||
this.reload(request.arguments);
|
||||
return this.requiredResponse({ reloadFinished: true });
|
||||
},
|
||||
[protocol.CommandTypes.Saveto]: (request: protocol.Request) => {
|
||||
const savetoArgs = request.arguments as protocol.SavetoRequestArgs;
|
||||
this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.Close]: (request: protocol.Request) => {
|
||||
const closeArgs = request.arguments as protocol.FileRequestArgs;
|
||||
this.closeClientFile(closeArgs.file);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.Navto]: (request: protocol.NavtoRequest) => {
|
||||
return this.requiredResponse(this.getNavigateToItems(request.arguments, /*simplifiedResult*/ true));
|
||||
@@ -3600,9 +3634,9 @@ export class Session<TMessage = string> implements EventSender {
|
||||
[protocol.CommandTypes.ProjectInfo]: (request: protocol.ProjectInfoRequest) => {
|
||||
return this.requiredResponse(this.getProjectInfo(request.arguments));
|
||||
},
|
||||
[protocol.CommandTypes.ReloadProjects]: () => {
|
||||
[protocol.CommandTypes.ReloadProjects]: request => {
|
||||
this.projectService.reloadProjects();
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.JsxClosingTag]: (request: protocol.JsxClosingTagRequest) => {
|
||||
return this.requiredResponse(this.getJsxClosingTag(request.arguments));
|
||||
@@ -3657,8 +3691,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
},
|
||||
[protocol.CommandTypes.ConfigurePlugin]: (request: protocol.ConfigurePluginRequest) => {
|
||||
this.configurePlugin(request.arguments);
|
||||
this.doOutput(/*info*/ undefined, protocol.CommandTypes.ConfigurePlugin, request.seq, /*success*/ true);
|
||||
return this.notRequired();
|
||||
return this.notRequired(request);
|
||||
},
|
||||
[protocol.CommandTypes.SelectionRange]: (request: protocol.SelectionRangeRequest) => {
|
||||
return this.requiredResponse(this.getSmartSelectionRange(request.arguments, /*simplifiedResult*/ true));
|
||||
@@ -3726,36 +3759,40 @@ export class Session<TMessage = string> implements EventSender {
|
||||
this.cancellationToken.resetRequest(requestId);
|
||||
}
|
||||
|
||||
public executeWithRequestId<T>(requestId: number, f: () => T) {
|
||||
public executeWithRequestId<T>(requestId: number, f: () => T): T;
|
||||
/** @internal */
|
||||
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData: PerformanceData | undefined): T; // eslint-disable-line @typescript-eslint/unified-signatures
|
||||
public executeWithRequestId<T>(requestId: number, f: () => T, perfomanceData?: PerformanceData) {
|
||||
const currentPerformanceData = this.performanceData;
|
||||
try {
|
||||
this.performanceData = perfomanceData;
|
||||
this.setCurrentRequest(requestId);
|
||||
return f();
|
||||
}
|
||||
finally {
|
||||
this.resetCurrentRequest(requestId);
|
||||
this.performanceData = currentPerformanceData;
|
||||
}
|
||||
}
|
||||
|
||||
public executeCommand(request: protocol.Request): HandlerResponse {
|
||||
const handler = this.handlers.get(request.command);
|
||||
if (handler) {
|
||||
const response = this.executeWithRequestId(request.seq, () => handler(request));
|
||||
const response = this.executeWithRequestId(request.seq, () => handler(request), /*perfomanceData*/ undefined);
|
||||
this.projectService.enableRequestedPlugins();
|
||||
return response;
|
||||
}
|
||||
else {
|
||||
this.logger.msg(`Unrecognized JSON command:${stringifyIndented(request)}`, Msg.Err);
|
||||
this.doOutput(/*info*/ undefined, protocol.CommandTypes.Unknown, request.seq, /*success*/ false, `Unrecognized JSON command: ${request.command}`);
|
||||
this.doOutput(/*info*/ undefined, protocol.CommandTypes.Unknown, request.seq, /*success*/ false, /*performanceData*/ undefined, `Unrecognized JSON command: ${request.command}`);
|
||||
return { responseRequired: false };
|
||||
}
|
||||
}
|
||||
|
||||
public onMessage(message: TMessage) {
|
||||
this.gcTimer.scheduleCollect();
|
||||
|
||||
this.performanceData = undefined;
|
||||
|
||||
let start: [number, number] | undefined;
|
||||
const currentPerformanceData = this.performanceData;
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
start = this.hrtime();
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
@@ -3772,7 +3809,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
tracing?.instant(tracing.Phase.Session, "request", { seq: request.seq, command: request.command });
|
||||
|
||||
tracing?.push(tracing.Phase.Session, "executeCommand", { seq: request.seq, command: request.command }, /*separateBeginAndEnd*/ true);
|
||||
const { response, responseRequired } = this.executeCommand(request);
|
||||
const { response, responseRequired, performanceData } = this.executeCommand(request);
|
||||
tracing?.pop();
|
||||
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
@@ -3788,10 +3825,23 @@ export class Session<TMessage = string> implements EventSender {
|
||||
// Note: Log before writing the response, else the editor can complete its activity before the server does
|
||||
tracing?.instant(tracing.Phase.Session, "response", { seq: request.seq, command: request.command, success: !!response });
|
||||
if (response) {
|
||||
this.doOutput(response, request.command, request.seq, /*success*/ true);
|
||||
this.doOutput(
|
||||
response,
|
||||
request.command,
|
||||
request.seq,
|
||||
/*success*/ true,
|
||||
performanceData,
|
||||
);
|
||||
}
|
||||
else if (responseRequired) {
|
||||
this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ false, "No content available.");
|
||||
this.doOutput(
|
||||
/*info*/ undefined,
|
||||
request.command,
|
||||
request.seq,
|
||||
/*success*/ false,
|
||||
performanceData,
|
||||
"No content available.",
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
@@ -3801,7 +3851,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
if (err instanceof OperationCanceledException) {
|
||||
// Handle cancellation exceptions
|
||||
tracing?.instant(tracing.Phase.Session, "commandCanceled", { seq: request?.seq, command: request?.command });
|
||||
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
|
||||
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true, this.performanceData);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3813,9 +3863,13 @@ export class Session<TMessage = string> implements EventSender {
|
||||
request ? request.command : protocol.CommandTypes.Unknown,
|
||||
request ? request.seq : 0,
|
||||
/*success*/ false,
|
||||
this.performanceData,
|
||||
"Error processing request. " + (err as StackTraceError).message + "\n" + (err as StackTraceError).stack,
|
||||
);
|
||||
}
|
||||
finally {
|
||||
this.performanceData = currentPerformanceData;
|
||||
}
|
||||
}
|
||||
|
||||
protected parseMessage(message: TMessage): protocol.Request {
|
||||
@@ -3848,6 +3902,12 @@ interface FileAndProject {
|
||||
readonly project: Project;
|
||||
}
|
||||
|
||||
function toProtocolPerformanceData(performanceData: PerformanceData): protocol.PerformanceData {
|
||||
const diagnosticsDuration = performanceData.diagnosticsDuration &&
|
||||
arrayFrom(performanceData.diagnosticsDuration, ([file, data]) => ({ ...data, file }));
|
||||
return { ...performanceData, diagnosticsDuration };
|
||||
}
|
||||
|
||||
function toProtocolTextSpan(textSpan: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan {
|
||||
return {
|
||||
start: scriptInfo.positionToLineOffset(textSpan.start),
|
||||
@@ -3898,6 +3958,7 @@ function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): proto
|
||||
export interface HandlerResponse {
|
||||
response?: {};
|
||||
responseRequired?: boolean;
|
||||
/** @internal */ performanceData?: PerformanceData;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import {
|
||||
ApplyCodeActionCommandResult,
|
||||
DirectoryWatcherCallback,
|
||||
FileWatcher,
|
||||
FileWatcherCallback,
|
||||
InstallPackageOptions,
|
||||
Path,
|
||||
SortedReadonlyArray,
|
||||
System,
|
||||
TypeAcquisition,
|
||||
WatchOptions,
|
||||
} from "./_namespaces/ts.js";
|
||||
import {
|
||||
Project,
|
||||
ProjectService,
|
||||
} from "./_namespaces/ts.server.js";
|
||||
|
||||
export interface CompressedData {
|
||||
length: number;
|
||||
@@ -20,6 +29,7 @@ export type RequireResult = ModuleImportResult;
|
||||
export interface ServerHost extends System {
|
||||
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher;
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher;
|
||||
preferNonRecursiveWatch?: boolean;
|
||||
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
|
||||
clearTimeout(timeoutId: any): void;
|
||||
setImmediate(callback: (...args: any[]) => void, ...args: any[]): any;
|
||||
@@ -30,3 +40,19 @@ export interface ServerHost extends System {
|
||||
/** @internal */
|
||||
importPlugin?(root: string, moduleName: string): Promise<ModuleImportResult>;
|
||||
}
|
||||
|
||||
export interface InstallPackageOptionsWithProject extends InstallPackageOptions {
|
||||
projectName: string;
|
||||
projectRootPath: Path;
|
||||
}
|
||||
|
||||
// for backwards-compatibility
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export interface ITypingsInstaller {
|
||||
isKnownTypesPackageName(name: string): boolean;
|
||||
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult>;
|
||||
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string> | undefined): void;
|
||||
attach(projectService: ProjectService): void;
|
||||
onProjectClosed(p: Project): void;
|
||||
readonly globalTypingsCacheLocation: string | undefined;
|
||||
}
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
import {
|
||||
ApplyCodeActionCommandResult,
|
||||
arrayIsEqualTo,
|
||||
CompilerOptions,
|
||||
getAllowJSCompilerOption,
|
||||
InstallPackageOptions,
|
||||
noop,
|
||||
notImplemented,
|
||||
Path,
|
||||
returnFalse,
|
||||
sort,
|
||||
SortedReadonlyArray,
|
||||
TypeAcquisition,
|
||||
} from "./_namespaces/ts.js";
|
||||
import {
|
||||
emptyArray,
|
||||
Project,
|
||||
ProjectService,
|
||||
} from "./_namespaces/ts.server.js";
|
||||
|
||||
export interface InstallPackageOptionsWithProject extends InstallPackageOptions {
|
||||
projectName: string;
|
||||
projectRootPath: Path;
|
||||
}
|
||||
|
||||
// for backwards-compatibility
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export interface ITypingsInstaller {
|
||||
isKnownTypesPackageName(name: string): boolean;
|
||||
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult>;
|
||||
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string> | undefined): void;
|
||||
attach(projectService: ProjectService): void;
|
||||
onProjectClosed(p: Project): void;
|
||||
readonly globalTypingsCacheLocation: string | undefined;
|
||||
}
|
||||
|
||||
export const nullTypingsInstaller: ITypingsInstaller = {
|
||||
isKnownTypesPackageName: returnFalse,
|
||||
// Should never be called because we never provide a types registry.
|
||||
installPackage: notImplemented,
|
||||
enqueueInstallTypingsRequest: noop,
|
||||
attach: noop,
|
||||
onProjectClosed: noop,
|
||||
globalTypingsCacheLocation: undefined!, // TODO: GH#18217
|
||||
};
|
||||
|
||||
interface TypingsCacheEntry {
|
||||
readonly typeAcquisition: TypeAcquisition;
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
readonly typings: SortedReadonlyArray<string>;
|
||||
readonly unresolvedImports: SortedReadonlyArray<string> | undefined;
|
||||
/* mainly useful for debugging */
|
||||
poisoned: boolean;
|
||||
}
|
||||
|
||||
function setIsEqualTo(arr1: string[] | undefined, arr2: string[] | undefined): boolean {
|
||||
if (arr1 === arr2) {
|
||||
return true;
|
||||
}
|
||||
if ((arr1 || emptyArray).length === 0 && (arr2 || emptyArray).length === 0) {
|
||||
return true;
|
||||
}
|
||||
const set = new Map<string, boolean>();
|
||||
let unique = 0;
|
||||
|
||||
for (const v of arr1!) {
|
||||
if (set.get(v) !== true) {
|
||||
set.set(v, true);
|
||||
unique++;
|
||||
}
|
||||
}
|
||||
for (const v of arr2!) {
|
||||
const isSet = set.get(v);
|
||||
if (isSet === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (isSet === true) {
|
||||
set.set(v, false);
|
||||
unique--;
|
||||
}
|
||||
}
|
||||
return unique === 0;
|
||||
}
|
||||
|
||||
function typeAcquisitionChanged(opt1: TypeAcquisition, opt2: TypeAcquisition): boolean {
|
||||
return opt1.enable !== opt2.enable ||
|
||||
!setIsEqualTo(opt1.include, opt2.include) ||
|
||||
!setIsEqualTo(opt1.exclude, opt2.exclude);
|
||||
}
|
||||
|
||||
function compilerOptionsChanged(opt1: CompilerOptions, opt2: CompilerOptions): boolean {
|
||||
// TODO: add more relevant properties
|
||||
return getAllowJSCompilerOption(opt1) !== getAllowJSCompilerOption(opt2);
|
||||
}
|
||||
|
||||
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string> | undefined, imports2: SortedReadonlyArray<string> | undefined): boolean {
|
||||
if (imports1 === imports2) {
|
||||
return false;
|
||||
}
|
||||
return !arrayIsEqualTo(imports1, imports2);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class TypingsCache {
|
||||
private readonly perProjectCache = new Map<string, TypingsCacheEntry>();
|
||||
|
||||
constructor(private readonly installer: ITypingsInstaller) {
|
||||
}
|
||||
|
||||
isKnownTypesPackageName(name: string): boolean {
|
||||
return this.installer.isKnownTypesPackageName(name);
|
||||
}
|
||||
|
||||
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult> {
|
||||
return this.installer.installPackage(options);
|
||||
}
|
||||
|
||||
enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string> | undefined, forceRefresh: boolean) {
|
||||
const typeAcquisition = project.getTypeAcquisition();
|
||||
|
||||
if (!typeAcquisition || !typeAcquisition.enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const entry = this.perProjectCache.get(project.getProjectName());
|
||||
if (
|
||||
forceRefresh ||
|
||||
!entry ||
|
||||
typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) ||
|
||||
compilerOptionsChanged(project.getCompilationSettings(), entry.compilerOptions) ||
|
||||
unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports)
|
||||
) {
|
||||
// Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
|
||||
// instead it acts as a placeholder to prevent issuing multiple requests
|
||||
this.perProjectCache.set(project.getProjectName(), {
|
||||
compilerOptions: project.getCompilationSettings(),
|
||||
typeAcquisition,
|
||||
typings: entry ? entry.typings : emptyArray,
|
||||
unresolvedImports,
|
||||
poisoned: true,
|
||||
});
|
||||
// something has been changed, issue a request to update typings
|
||||
this.installer.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
|
||||
}
|
||||
}
|
||||
|
||||
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>, newTypings: string[]) {
|
||||
const typings = sort(newTypings);
|
||||
this.perProjectCache.set(projectName, {
|
||||
compilerOptions,
|
||||
typeAcquisition,
|
||||
typings,
|
||||
unresolvedImports,
|
||||
poisoned: false,
|
||||
});
|
||||
return !typeAcquisition || !typeAcquisition.enable ? emptyArray : typings;
|
||||
}
|
||||
|
||||
onProjectClosed(project: Project) {
|
||||
if (this.perProjectCache.delete(project.getProjectName())) {
|
||||
this.installer.onProjectClosed(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-24
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
binarySearch,
|
||||
Comparer,
|
||||
getBaseFileName,
|
||||
identity,
|
||||
SortedArray,
|
||||
} from "./_namespaces/ts.js";
|
||||
import { getBaseFileName } from "./_namespaces/ts.js";
|
||||
import {
|
||||
Logger,
|
||||
LogLevel,
|
||||
@@ -88,20 +82,3 @@ export function getBaseConfigFileName(configFilePath: NormalizedPath): "tsconfig
|
||||
const base = getBaseFileName(configFilePath);
|
||||
return base === "tsconfig.json" || base === "jsconfig.json" ? base : undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function removeSorted<T>(array: SortedArray<T>, remove: T, compare: Comparer<T>): void {
|
||||
if (!array || array.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array[0] === remove) {
|
||||
array.splice(0, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
const removeIndex = binarySearch(array, remove, identity, compare);
|
||||
if (removeIndex >= 0) {
|
||||
array.splice(removeIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch
|
||||
if (!classDeclaration && isPrivateIdentifier(token)) return undefined;
|
||||
|
||||
// Prefer to change the class instead of the interface if they are merged
|
||||
const declaration = classDeclaration || find(symbol.declarations, d => isInterfaceDeclaration(d) || isTypeLiteralNode(d)) as InterfaceDeclaration | TypeLiteralNode | undefined;
|
||||
const declaration = classDeclaration || find(symbol.declarations, d => isInterfaceDeclaration(d) || isTypeLiteralNode(d));
|
||||
if (declaration && !isSourceFileFromLibrary(program, declaration.getSourceFile())) {
|
||||
const makeStatic = !isTypeLiteralNode(declaration) && ((leftExpressionType as TypeReference).target || leftExpressionType) !== checker.getDeclaredTypeOfSymbol(symbol);
|
||||
if (makeStatic && (isPrivateIdentifier(token) || isInterfaceDeclaration(declaration))) return undefined;
|
||||
|
||||
@@ -610,8 +610,7 @@ function typeContainsTypeParameter(type: Type) {
|
||||
return type.flags & TypeFlags.TypeParameter;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAdder: ImportAdder, instanceTypes: Type[], contextNode: Node | undefined, scriptTarget: ScriptTarget, flags?: NodeBuilderFlags, tracker?: SymbolTracker) {
|
||||
function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAdder: ImportAdder, instanceTypes: Type[], contextNode: Node | undefined, scriptTarget: ScriptTarget, flags?: NodeBuilderFlags, tracker?: SymbolTracker) {
|
||||
// Types to be used as the types of the parameters in the new function
|
||||
// E.g. from this source:
|
||||
// added("", 0)
|
||||
@@ -874,13 +873,11 @@ export function setJsonCompilerOptionValue(
|
||||
setJsonCompilerOptionValues(changeTracker, configFile, [[optionName, optionValue]]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createJsonPropertyAssignment(name: string, initializer: Expression) {
|
||||
function createJsonPropertyAssignment(name: string, initializer: Expression) {
|
||||
return factory.createPropertyAssignment(factory.createStringLiteral(name), initializer);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined {
|
||||
function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined {
|
||||
return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name);
|
||||
}
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ import {
|
||||
// Exported only for tests
|
||||
/** @internal */
|
||||
export const moduleSpecifierResolutionLimit = 100;
|
||||
/** @internal */
|
||||
/** @internal @knipignore */
|
||||
export const moduleSpecifierResolutionCacheAttemptLimit = 1000;
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -201,7 +201,6 @@ import {
|
||||
isVoidExpression,
|
||||
isWriteAccess,
|
||||
JSDocPropertyLikeTag,
|
||||
JSDocTag,
|
||||
length,
|
||||
map,
|
||||
mapDefined,
|
||||
@@ -242,7 +241,6 @@ import {
|
||||
skipAlias,
|
||||
some,
|
||||
SourceFile,
|
||||
Statement,
|
||||
StringLiteral,
|
||||
StringLiteralLike,
|
||||
stripQuotes,
|
||||
@@ -324,8 +322,7 @@ export interface SpanEntry {
|
||||
readonly fileName: string;
|
||||
readonly textSpan: TextSpan;
|
||||
}
|
||||
/** @internal */
|
||||
export function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry {
|
||||
function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry {
|
||||
return {
|
||||
kind,
|
||||
node: (node as NamedDeclaration).name || node,
|
||||
@@ -377,7 +374,7 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined {
|
||||
const declOrStatement = findAncestor(validImport, node =>
|
||||
isDeclaration(node) ||
|
||||
isStatement(node) ||
|
||||
isJSDocTag(node))! as NamedDeclaration | Statement | JSDocTag;
|
||||
isJSDocTag(node))!;
|
||||
return isDeclaration(declOrStatement) ?
|
||||
getContextNode(declOrStatement) :
|
||||
declOrStatement;
|
||||
@@ -886,8 +883,7 @@ function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSp
|
||||
return createTextSpanFromBounds(start, end);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getTextSpanOfEntry(entry: Entry) {
|
||||
function getTextSpanOfEntry(entry: Entry) {
|
||||
return entry.kind === EntryKind.Span ? entry.textSpan :
|
||||
getTextSpan(entry.node, entry.node.getSourceFile());
|
||||
}
|
||||
|
||||
@@ -159,13 +159,13 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.AwaitKeyword) {
|
||||
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
|
||||
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
|
||||
const isAsyncFunction = functionDeclaration && some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword);
|
||||
return isAsyncFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.YieldKeyword) {
|
||||
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
|
||||
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
|
||||
const isGeneratorFunction = functionDeclaration && functionDeclaration.asteriskToken;
|
||||
return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
|
||||
}
|
||||
@@ -716,8 +716,7 @@ function createDefinitionFromSignatureDeclaration(typeChecker: TypeChecker, decl
|
||||
return createDefinitionInfo(decl, typeChecker, decl.symbol, decl, /*unverified*/ false, failedAliasResolution);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function findReferenceInPosition(refs: readonly FileReference[], pos: number): FileReference | undefined {
|
||||
function findReferenceInPosition(refs: readonly FileReference[], pos: number): FileReference | undefined {
|
||||
return find(refs, ref => textRangeContainsPositionInclusive(ref, pos));
|
||||
}
|
||||
|
||||
|
||||
@@ -787,10 +787,9 @@ function getContainingModuleSymbol(importer: Importer, checker: TypeChecker): Sy
|
||||
}
|
||||
|
||||
function getSourceFileLikeForImportDeclaration(node: ImporterOrCallExpression): SourceFileLike {
|
||||
if (node.kind === SyntaxKind.CallExpression) {
|
||||
if (node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.JSDocImportTag) {
|
||||
return node.getSourceFile();
|
||||
}
|
||||
|
||||
const { parent } = node;
|
||||
if (parent.kind === SyntaxKind.SourceFile) {
|
||||
return parent as SourceFile;
|
||||
|
||||
@@ -212,8 +212,7 @@ export function organizeImports(
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getDetectionLists(preferences: UserPreferences): { comparersToTest: Comparer<string>[]; typeOrdersToTest: OrganizeImportsTypeOrder[]; } {
|
||||
function getDetectionLists(preferences: UserPreferences): { comparersToTest: Comparer<string>[]; typeOrdersToTest: OrganizeImportsTypeOrder[]; } {
|
||||
// Returns the possible detection outcomes, given the user's preferences. The earlier in the list, the higher the priority.
|
||||
return {
|
||||
comparersToTest: typeof preferences.organizeImportsIgnoreCase === "boolean"
|
||||
|
||||
@@ -71,8 +71,9 @@ function pasteEdits(
|
||||
newText = actualPastedText ? newText.slice(0, pos) + actualPastedText[0] + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end);
|
||||
}
|
||||
|
||||
let importAdder: codefix.ImportAdder;
|
||||
Debug.checkDefined(host.runWithTemporaryFileUpdate).call(host, targetFile.fileName, newText, (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => {
|
||||
const importAdder = codefix.createImportAdder(updatedFile, updatedProgram, preferences, host);
|
||||
importAdder = codefix.createImportAdder(updatedFile, updatedProgram, preferences, host);
|
||||
if (copiedFrom?.range) {
|
||||
Debug.assert(copiedFrom.range.length === pastedText.length);
|
||||
copiedFrom.range.forEach(copy => {
|
||||
@@ -90,7 +91,7 @@ function pasteEdits(
|
||||
}
|
||||
statements.push(...statementsInSourceFile.slice(startNodeIndex, endNodeIndex === -1 ? statementsInSourceFile.length : endNodeIndex + 1));
|
||||
});
|
||||
const usage = getUsageInfo(copiedFrom.file, statements, originalProgram!.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram!.getTypeChecker()));
|
||||
const usage = getUsageInfo(copiedFrom.file, statements, originalProgram!.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram!.getTypeChecker()), { pos: copiedFrom.range[0].pos, end: copiedFrom.range[copiedFrom.range.length - 1].end });
|
||||
Debug.assertIsDefined(originalProgram);
|
||||
const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFile.fileName, originalProgram, host, !!copiedFrom.file.commonJsModuleIndicator);
|
||||
addExportsInOldFile(copiedFrom.file, usage.targetFileImportsFromOldFile, changes, useEsModuleSyntax);
|
||||
@@ -115,6 +116,13 @@ function pasteEdits(
|
||||
}
|
||||
importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences));
|
||||
});
|
||||
|
||||
/**
|
||||
* If there are no import fixes, getPasteEdits should return without making any changes to the file.
|
||||
*/
|
||||
if (!importAdder!.hasFixes()) {
|
||||
return;
|
||||
}
|
||||
pasteLocations.forEach((paste, i) => {
|
||||
changes.replaceRangeWithText(
|
||||
targetFile,
|
||||
|
||||
@@ -129,6 +129,7 @@ import {
|
||||
PropertyAccessExpression,
|
||||
PropertyAssignment,
|
||||
QuotePreference,
|
||||
rangeContainsRange,
|
||||
RefactorContext,
|
||||
RefactorEditInfo,
|
||||
RequireOrImportCall,
|
||||
@@ -145,6 +146,7 @@ import {
|
||||
SyntaxKind,
|
||||
takeWhile,
|
||||
textChanges,
|
||||
TextRange,
|
||||
TransformFlags,
|
||||
tryCast,
|
||||
TypeAliasDeclaration,
|
||||
@@ -287,15 +289,13 @@ export function addNewFileToTsconfig(program: Program, changes: textChanges.Chan
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function deleteMovedStatements(sourceFile: SourceFile, moved: readonly StatementRange[], changes: textChanges.ChangeTracker) {
|
||||
function deleteMovedStatements(sourceFile: SourceFile, moved: readonly StatementRange[], changes: textChanges.ChangeTracker) {
|
||||
for (const { first, afterLast } of moved) {
|
||||
changes.deleteNodeRangeExcludingEnd(sourceFile, first, afterLast);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[], toDelete: Set<Symbol>, importAdder: codefix.ImportAdder) {
|
||||
function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[], toDelete: Set<Symbol>, importAdder: codefix.ImportAdder) {
|
||||
for (const statement of oldFile.statements) {
|
||||
if (contains(toMove, statement)) continue;
|
||||
forEachImportInStatement(statement, i => {
|
||||
@@ -328,8 +328,7 @@ export function addExportsInOldFile(oldFile: SourceFile, targetFileImportsFromOl
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function updateImportsInOtherFiles(
|
||||
function updateImportsInOtherFiles(
|
||||
changes: textChanges.ChangeTracker,
|
||||
program: Program,
|
||||
host: LanguageServiceHost,
|
||||
@@ -438,15 +437,13 @@ function createRequireCall(moduleSpecifier: StringLiteralLike): CallExpression {
|
||||
return factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function moduleSpecifierFromImport(i: SupportedImport): StringLiteralLike {
|
||||
function moduleSpecifierFromImport(i: SupportedImport): StringLiteralLike {
|
||||
return (i.kind === SyntaxKind.ImportDeclaration ? i.moduleSpecifier
|
||||
: i.kind === SyntaxKind.ImportEqualsDeclaration ? i.moduleReference.expression
|
||||
: i.initializer.arguments[0]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function forEachImportInStatement(statement: Statement, cb: (importNode: SupportedImport) => void): void {
|
||||
function forEachImportInStatement(statement: Statement, cb: (importNode: SupportedImport) => void): void {
|
||||
if (isImportDeclaration(statement)) {
|
||||
if (isStringLiteral(statement.moduleSpecifier)) cb(statement as SupportedImport);
|
||||
}
|
||||
@@ -547,8 +544,7 @@ function isExported(sourceFile: SourceFile, decl: TopLevelDeclarationStatement,
|
||||
getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name)));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function deleteUnusedImports(sourceFile: SourceFile, importDecl: SupportedImport, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void {
|
||||
function deleteUnusedImports(sourceFile: SourceFile, importDecl: SupportedImport, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void {
|
||||
if (importDecl.kind === SyntaxKind.ImportDeclaration && importDecl.importClause) {
|
||||
const { name, namedBindings } = importDecl.importClause;
|
||||
if ((!name || isUnused(name)) && (!namedBindings || namedBindings.kind === SyntaxKind.NamedImports && namedBindings.elements.length !== 0 && namedBindings.elements.every(e => isUnused(e.name)))) {
|
||||
@@ -638,8 +634,7 @@ function getNamesToExportInCommonJS(decl: TopLevelDeclarationStatement): readonl
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined {
|
||||
function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined {
|
||||
switch (i.kind) {
|
||||
case SyntaxKind.ImportDeclaration: {
|
||||
const clause = i.importClause;
|
||||
@@ -685,13 +680,11 @@ function filterBindingName(name: BindingName, keep: (name: Identifier) => boolea
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined {
|
||||
function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined {
|
||||
return isExpressionStatement(d) ? tryCast(d.expression.left.name, isIdentifier) : tryCast(d.name, isIdentifier);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement {
|
||||
function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement {
|
||||
switch (d.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return d.parent.parent;
|
||||
@@ -704,8 +697,7 @@ export function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLeve
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function addExportToChanges(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, name: Identifier, changes: textChanges.ChangeTracker, useEs6Exports: boolean): void {
|
||||
function addExportToChanges(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, name: Identifier, changes: textChanges.ChangeTracker, useEs6Exports: boolean): void {
|
||||
if (isExported(sourceFile, decl, useEs6Exports, name)) return;
|
||||
if (useEs6Exports) {
|
||||
if (!isExpressionStatement(decl)) changes.insertExportModifier(sourceFile, decl);
|
||||
@@ -871,7 +863,7 @@ function isPureImport(node: Node): boolean {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet<Symbol> = new Set()): UsageInfo {
|
||||
export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet<Symbol> = new Set(), enclosingRange?: TextRange): UsageInfo {
|
||||
const movedSymbols = new Set<Symbol>();
|
||||
const oldImportsNeededByTargetFile = new Map<Symbol, [/*isValidTypeOnlyUseSite*/ boolean, codefix.ImportOrRequireAliasDeclaration | undefined]>();
|
||||
const targetFileImportsFromOldFile = new Map<Symbol, /*isValidTypeOnlyUseSite*/ boolean>();
|
||||
@@ -890,7 +882,7 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[],
|
||||
|
||||
const unusedImportsFromOldFile = new Set<Symbol>();
|
||||
for (const statement of toMove) {
|
||||
forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => {
|
||||
forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => {
|
||||
if (!symbol.declarations || isGlobalType(checker, symbol)) {
|
||||
return;
|
||||
}
|
||||
@@ -926,7 +918,7 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[],
|
||||
unusedImportsFromOldFile.delete(jsxNamespaceSymbol);
|
||||
}
|
||||
|
||||
forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => {
|
||||
forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => {
|
||||
if (movedSymbols.has(symbol)) oldFileImportsFromTargetFile.set(symbol, isValidTypeOnlyUseSite);
|
||||
unusedImportsFromOldFile.delete(symbol);
|
||||
});
|
||||
@@ -969,9 +961,12 @@ function inferNewFileName(importsFromNewFile: Map<Symbol, unknown>, movedSymbols
|
||||
return forEachKey(importsFromNewFile, symbolNameNoDefault) || forEachKey(movedSymbols, symbolNameNoDefault) || "newFile";
|
||||
}
|
||||
|
||||
function forEachReference(node: Node, checker: TypeChecker, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) {
|
||||
function forEachReference(node: Node, checker: TypeChecker, enclosingRange: TextRange | undefined, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) {
|
||||
node.forEachChild(function cb(node) {
|
||||
if (isIdentifier(node) && !isDeclarationName(node)) {
|
||||
if (enclosingRange && !rangeContainsRange(enclosingRange, node)) {
|
||||
return;
|
||||
}
|
||||
const sym = checker.getSymbolAtLocation(node);
|
||||
if (sym) onReference(sym, isValidTypeOnlyAliasUseSite(node));
|
||||
}
|
||||
@@ -1025,8 +1020,7 @@ function isVariableDeclarationInImport(decl: VariableDeclaration) {
|
||||
!!decl.initializer && isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isTopLevelDeclaration(node: Node): node is TopLevelDeclaration {
|
||||
function isTopLevelDeclaration(node: Node): node is TopLevelDeclaration {
|
||||
return isNonVariableTopLevelDeclaration(node) && isSourceFile(node.parent) || isVariableDeclaration(node) && isSourceFile(node.parent.parent.parent);
|
||||
}
|
||||
function sourceFileOfTopLevelDeclaration(node: TopLevelDeclaration): Node {
|
||||
@@ -1151,7 +1145,7 @@ export function getExistingLocals(sourceFile: SourceFile, statements: readonly S
|
||||
}
|
||||
|
||||
for (const statement of statements) {
|
||||
forEachReference(statement, checker, s => {
|
||||
forEachReference(statement, checker, /*enclosingRange*/ undefined, s => {
|
||||
const symbol = skipAlias(s, checker);
|
||||
if (symbol.valueDeclaration && getSourceFileOfNode(symbol.valueDeclaration).path === sourceFile.path) {
|
||||
existingLocals.add(symbol);
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
getTextOfIdentifierOrLiteral,
|
||||
getTextOfNode,
|
||||
getTouchingPropertyName,
|
||||
ImportSpecifier,
|
||||
isExternalModuleNameRelative,
|
||||
isIdentifier,
|
||||
isImportOrExportSpecifierName,
|
||||
@@ -136,7 +135,7 @@ function wouldRenameInOtherNodeModules(
|
||||
): DiagnosticMessage | undefined {
|
||||
if (!preferences.providePrefixAndSuffixTextForRename && symbol.flags & SymbolFlags.Alias) {
|
||||
const importSpecifier = symbol.declarations && find(symbol.declarations, decl => isImportSpecifier(decl));
|
||||
if (importSpecifier && !(importSpecifier as ImportSpecifier).propertyName) {
|
||||
if (importSpecifier && !importSpecifier.propertyName) {
|
||||
symbol = checker.getAliasedSymbol(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,9 +457,9 @@ class NodeObject<TKind extends SyntaxKind> implements Node {
|
||||
return this.getChildren(sourceFile)[index];
|
||||
}
|
||||
|
||||
public getChildren(sourceFile?: SourceFileLike): readonly Node[] {
|
||||
public getChildren(sourceFile: SourceFileLike = getSourceFileOfNode(this)): readonly Node[] {
|
||||
this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine");
|
||||
return getNodeChildren(this) ?? setNodeChildren(this, createChildren(this, sourceFile));
|
||||
return getNodeChildren(this, sourceFile) ?? setNodeChildren(this, sourceFile, createChildren(this, sourceFile));
|
||||
}
|
||||
|
||||
public getFirstToken(sourceFile?: SourceFileLike): Node | undefined {
|
||||
@@ -558,7 +558,7 @@ function createSyntaxList(nodes: NodeArray<Node>, parent: Node): Node {
|
||||
pos = node.end;
|
||||
}
|
||||
addSyntheticNodes(children, pos, nodes.end, parent);
|
||||
setNodeChildren(list, children);
|
||||
list._children = children;
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -1866,17 +1866,22 @@ export function createLanguageService(
|
||||
host.onReleaseParsedCommandLine?.(configFileName, oldResolvedRef, oldOptions);
|
||||
}
|
||||
else if (oldResolvedRef) {
|
||||
onReleaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions);
|
||||
releaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions);
|
||||
}
|
||||
}
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
// not part of the new program.
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
|
||||
function releaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
|
||||
const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions);
|
||||
documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat);
|
||||
}
|
||||
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined) {
|
||||
releaseOldSourceFile(oldSourceFile, oldOptions);
|
||||
host.onReleaseOldSourceFile?.(oldSourceFile, oldOptions, hasSourceFileByPath, newSourceFileByResolvedPath);
|
||||
}
|
||||
|
||||
function getOrCreateSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper {
|
||||
|
||||
const declarationPath = outPath ?
|
||||
removeFileExtension(outPath) + Extension.Dts :
|
||||
getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName);
|
||||
getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), program);
|
||||
if (declarationPath === undefined) return undefined;
|
||||
|
||||
const newLoc = getDocumentPositionMapper(declarationPath, info.fileName).getGeneratedPosition(info);
|
||||
|
||||
@@ -430,6 +430,7 @@ export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalR
|
||||
/** @internal */ sendPerformanceEvent?(kind: PerformanceEvent["kind"], durationMs: number): void;
|
||||
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
|
||||
/** @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void;
|
||||
/** @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean, newSourceFileByResolvedPath: SourceFile | undefined): void;
|
||||
/** @internal */ getIncompleteCompletionsCache?(): IncompleteCompletionsCache;
|
||||
/** @internal */ runWithTemporaryFileUpdate?(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedPastedText: SourceFile) => void): void;
|
||||
jsDocParsingMode?: JSDocParsingMode | undefined;
|
||||
|
||||
+15
-57
@@ -30,7 +30,6 @@ import {
|
||||
ConditionalExpression,
|
||||
contains,
|
||||
ContextFlags,
|
||||
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
|
||||
createRange,
|
||||
createScanner,
|
||||
createTextSpan,
|
||||
@@ -53,7 +52,6 @@ import {
|
||||
DoStatement,
|
||||
ElementAccessExpression,
|
||||
EmitFlags,
|
||||
EmitHint,
|
||||
emitModuleKindIsNonNodeESM,
|
||||
emptyArray,
|
||||
EndOfFileToken,
|
||||
@@ -177,7 +175,6 @@ import {
|
||||
isFunctionExpression,
|
||||
isFunctionLike,
|
||||
isGetAccessorDeclaration,
|
||||
isGlobalScopeAugmentation,
|
||||
isHeritageClause,
|
||||
isIdentifier,
|
||||
isIdentifierPart,
|
||||
@@ -649,8 +646,7 @@ export function climbPastPropertyAccess(node: Node) {
|
||||
return isRightSideOfPropertyAccess(node) ? node.parent : node;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function climbPastPropertyOrElementAccess(node: Node) {
|
||||
function climbPastPropertyOrElementAccess(node: Node) {
|
||||
return isRightSideOfPropertyAccess(node) || isArgumentExpressionOfElementAccess(node) ? node.parent : node;
|
||||
}
|
||||
|
||||
@@ -1149,8 +1145,7 @@ export function findListItemInfo(node: Node): ListItemInfo | undefined {
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile: SourceFile): boolean {
|
||||
function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile: SourceFile): boolean {
|
||||
return !!findChildOfKind(n, kind, sourceFile);
|
||||
}
|
||||
|
||||
@@ -2008,8 +2003,7 @@ export function findPrecedingMatchingToken(token: Node, matchingTokenKind: Synta
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function removeOptionality(type: Type, isOptionalExpression: boolean, isOptionalChain: boolean) {
|
||||
function removeOptionality(type: Type, isOptionalExpression: boolean, isOptionalChain: boolean) {
|
||||
return isOptionalExpression ? type.getNonNullableType() :
|
||||
isOptionalChain ? type.getNonOptionalType() :
|
||||
type;
|
||||
@@ -2398,8 +2392,7 @@ export function isTypeKeyword(kind: SyntaxKind): boolean {
|
||||
return contains(typeKeywords, kind);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isTypeKeywordToken(node: Node): node is Token<SyntaxKind.TypeKeyword> {
|
||||
function isTypeKeywordToken(node: Node): node is Token<SyntaxKind.TypeKeyword> {
|
||||
return node.kind === SyntaxKind.TypeKeyword;
|
||||
}
|
||||
|
||||
@@ -2872,8 +2865,7 @@ function getDisplayPartWriter(): DisplayPartsSymbolWriter {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function symbolPart(text: string, symbol: Symbol) {
|
||||
function symbolPart(text: string, symbol: Symbol) {
|
||||
return displayPart(text, displayPartKind(symbol));
|
||||
|
||||
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
|
||||
@@ -2958,13 +2950,11 @@ export function typeParameterNamePart(text: string) {
|
||||
return displayPart(text, SymbolDisplayPartKind.typeParameterName);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function linkTextPart(text: string) {
|
||||
function linkTextPart(text: string) {
|
||||
return displayPart(text, SymbolDisplayPartKind.linkText);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function linkNamePart(text: string, target: Declaration): JSDocLinkDisplayPart {
|
||||
function linkNamePart(text: string, target: Declaration): JSDocLinkDisplayPart {
|
||||
return {
|
||||
text,
|
||||
kind: SymbolDisplayPartKind[SymbolDisplayPartKind.linkName],
|
||||
@@ -2975,8 +2965,7 @@ export function linkNamePart(text: string, target: Declaration): JSDocLinkDispla
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function linkPart(text: string) {
|
||||
function linkPart(text: string) {
|
||||
return displayPart(text, SymbolDisplayPartKind.link);
|
||||
}
|
||||
|
||||
@@ -3090,15 +3079,6 @@ export function signatureToDisplayParts(typechecker: TypeChecker, signature: Sig
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function nodeToDisplayParts(node: Node, enclosingDeclaration: Node): SymbolDisplayPart[] {
|
||||
const file = enclosingDeclaration.getSourceFile();
|
||||
return mapToDisplayParts(writer => {
|
||||
const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon();
|
||||
printer.writeNode(EmitHint.Unspecified, node, file, writer);
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isImportOrExportSpecifierName(location: Node): location is Identifier {
|
||||
return !!location.parent && isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location;
|
||||
@@ -3251,7 +3231,7 @@ export function suppressLeadingTrivia(node: Node) {
|
||||
/**
|
||||
* Sets EmitFlags to suppress trailing trivia on the node.
|
||||
*
|
||||
* @internal
|
||||
* @internal @knipignore
|
||||
*/
|
||||
export function suppressTrailingTrivia(node: Node) {
|
||||
addEmitFlagsRecursively(node, EmitFlags.NoTrailingComments, getLastChild);
|
||||
@@ -3490,8 +3470,7 @@ function syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.ModuleDeclaration;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function syntaxRequiresTrailingSemicolonOrASI(kind: SyntaxKind) {
|
||||
function syntaxRequiresTrailingSemicolonOrASI(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.VariableStatement
|
||||
|| kind === SyntaxKind.ExpressionStatement
|
||||
|| kind === SyntaxKind.DoStatement
|
||||
@@ -3509,8 +3488,7 @@ export function syntaxRequiresTrailingSemicolonOrASI(kind: SyntaxKind) {
|
||||
|| kind === SyntaxKind.ExportAssignment;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const syntaxMayBeASICandidate = or(
|
||||
const syntaxMayBeASICandidate = or(
|
||||
syntaxRequiresTrailingCommaOrSemicolonOrASI,
|
||||
syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI,
|
||||
syntaxRequiresTrailingModuleBlockOrSemicolonOrASI,
|
||||
@@ -3650,8 +3628,7 @@ export function tryAndIgnoreErrors<T>(cb: () => T): T | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function tryIOAndConsumeErrors<T>(host: unknown, toApply: ((...a: any[]) => T) | undefined, ...args: any[]) {
|
||||
function tryIOAndConsumeErrors<T>(host: unknown, toApply: ((...a: any[]) => T) | undefined, ...args: any[]) {
|
||||
return tryAndIgnoreErrors(() => toApply && toApply.apply(host, args));
|
||||
}
|
||||
|
||||
@@ -3683,8 +3660,7 @@ export function findPackageJson(directory: string, host: LanguageServiceHost): s
|
||||
return packageJson;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPackageJsonsVisibleToFile(fileName: string, host: LanguageServiceHost): readonly ProjectPackageJsonInfo[] {
|
||||
function getPackageJsonsVisibleToFile(fileName: string, host: LanguageServiceHost): readonly ProjectPackageJsonInfo[] {
|
||||
if (!host.fileExists) {
|
||||
return [];
|
||||
}
|
||||
@@ -3922,8 +3898,7 @@ export function isInsideNodeModules(fileOrDirectory: string): boolean {
|
||||
return contains(getPathComponents(fileOrDirectory), "node_modules");
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isDiagnosticWithLocation(diagnostic: Diagnostic): diagnostic is DiagnosticWithLocation {
|
||||
function isDiagnosticWithLocation(diagnostic: Diagnostic): diagnostic is DiagnosticWithLocation {
|
||||
return diagnostic.file !== undefined && diagnostic.start !== undefined && diagnostic.length !== undefined;
|
||||
}
|
||||
|
||||
@@ -4058,8 +4033,7 @@ export function getDefaultLikeExportNameFromDeclaration(symbol: Symbol): string
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getSymbolParentOrFail(symbol: Symbol) {
|
||||
function getSymbolParentOrFail(symbol: Symbol) {
|
||||
return Debug.checkDefined(
|
||||
symbol.parent,
|
||||
`Symbol parent was undefined. Flags: ${Debug.formatSymbolFlags(symbol.flags)}. ` +
|
||||
@@ -4146,22 +4120,6 @@ export function startsWithUnderscore(name: string): boolean {
|
||||
return name.charCodeAt(0) === CharacterCodes._;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isGlobalDeclaration(declaration: Declaration) {
|
||||
return !isNonGlobalDeclaration(declaration);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNonGlobalDeclaration(declaration: Declaration) {
|
||||
const sourceFile = declaration.getSourceFile();
|
||||
// If the file is not a module, the declaration is global
|
||||
if (!sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) {
|
||||
return false;
|
||||
}
|
||||
// If the file is a module written in TypeScript, it still might be in a `declare global` augmentation
|
||||
return isInJSFile(declaration) || !findAncestor(declaration, d => isModuleDeclaration(d) && isGlobalScopeAugmentation(d));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isDeprecatedDeclaration(decl: Declaration) {
|
||||
return !!(getCombinedNodeFlagsAlwaysIncludeJSDoc(decl) & ModifierFlags.Deprecated);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
/* Generated file to emulate the compiler namespace. */
|
||||
|
||||
export * from "../../harness/_namespaces/compiler.js";
|
||||
@@ -1,3 +1,11 @@
|
||||
import { fork } from "child_process";
|
||||
import { statSync } from "fs";
|
||||
import Mocha from "mocha";
|
||||
import ms from "ms";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import readline from "readline";
|
||||
import tty from "tty";
|
||||
import {
|
||||
configOption,
|
||||
globalTimeout,
|
||||
@@ -26,20 +34,12 @@ import * as ts from "../_namespaces/ts.js";
|
||||
import * as Utils from "../_namespaces/Utils.js";
|
||||
|
||||
export function start(importTests: () => Promise<unknown>) {
|
||||
const Mocha = require("mocha") as typeof import("mocha");
|
||||
const Base = Mocha.reporters.Base;
|
||||
const color = Base.color;
|
||||
const cursor = Base.cursor;
|
||||
const ms = require("ms") as typeof import("ms");
|
||||
const readline = require("readline") as typeof import("readline");
|
||||
const os = require("os") as typeof import("os");
|
||||
const tty = require("tty") as typeof import("tty");
|
||||
const isatty = tty.isatty(1) && tty.isatty(2);
|
||||
const path = require("path") as typeof import("path");
|
||||
const { fork } = require("child_process") as typeof import("child_process");
|
||||
const { statSync } = require("fs") as typeof import("fs");
|
||||
|
||||
// NOTE: paths for module and types for FailedTestReporter _do not_ line up due to our use of --outFile for run.js
|
||||
// NOTE: paths for module and types for FailedTestReporter _do not_ line up when bundled
|
||||
const FailedTestReporter = require(Utils.findUpFile("scripts/failed-tests.cjs")) as typeof import("../../../scripts/failed-tests.cjs");
|
||||
|
||||
const perfdataFileNameFragment = ".parallelperf";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Mocha from "mocha";
|
||||
import {
|
||||
createRunner,
|
||||
globalTimeout,
|
||||
@@ -39,9 +40,6 @@ export function start(importTests: () => Promise<unknown>) {
|
||||
let exceptionsHooked = false;
|
||||
hookUncaughtExceptions();
|
||||
|
||||
// Capitalization is aligned with the global `Mocha` namespace for typespace/namespace references.
|
||||
const Mocha = require("mocha") as typeof import("mocha");
|
||||
|
||||
/**
|
||||
* Mixin helper.
|
||||
* @param base The base class constructor.
|
||||
|
||||
@@ -88,6 +88,7 @@ const testConfigContent = customConfig && IO.fileExists(customConfig)
|
||||
export let taskConfigsFolder: string;
|
||||
export let workerCount: number;
|
||||
export let runUnitTests: boolean | undefined;
|
||||
export let skipSysTests: boolean | undefined;
|
||||
export let stackTraceLimit: number | "full" | undefined;
|
||||
export let noColors = false;
|
||||
export let keepFailed = false;
|
||||
@@ -101,6 +102,7 @@ export interface TestConfig {
|
||||
test?: string[];
|
||||
runners?: string[];
|
||||
runUnitTests?: boolean;
|
||||
skipSysTests?: boolean;
|
||||
noColors?: boolean;
|
||||
timeout?: number;
|
||||
keepFailed?: boolean;
|
||||
@@ -143,6 +145,9 @@ function handleTestConfig() {
|
||||
if (testConfig.shards) {
|
||||
setShards(testConfig.shards);
|
||||
}
|
||||
if (testConfig.skipSysTests) {
|
||||
skipSysTests = true;
|
||||
}
|
||||
|
||||
if (testConfig.stackTraceLimit === "full") {
|
||||
(Error as any).stackTraceLimit = Infinity;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user