Merge branch 'master' into sourceMapGenerator

This commit is contained in:
Ron Buckton
2018-11-09 10:31:54 -08:00
1703 changed files with 92680 additions and 54984 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
language: node_js
node_js:
- 'stable'
- '8'
- 'node'
- '10'
- '6'
sudo: false
+4 -4
View File
@@ -137,10 +137,10 @@ You can specify which browser to use for debugging. Currently Chrome and IE are
jake runtests-browser tests=2dArrays browser=chrome
```
You can debug with VS Code or Node instead with `jake runtests debug=true`:
You can debug with VS Code or Node instead with `jake runtests inspect=true`:
```Shell
jake runtests tests=2dArrays debug=true
jake runtests tests=2dArrays inspect=true
```
## Adding a Test
@@ -153,7 +153,7 @@ The supported names and values are the same as those supported in the compiler i
They are useful for tests relating to modules.
See below for examples.
**Note** that if you have a test corresponding to a specific spec compliance item, you can place it in `tests\cases\conformance` in an appropriately-named subfolder.
**Note** that if you have a test corresponding to a specific spec compliance item, you can place it in `tests\cases\conformance` in an appropriately-named subfolder.
**Note** that filenames here must be distinct from all other compiler testcase names, so you may have to work a bit to find a unique name if it's something common.
### Tests for multiple files
@@ -194,6 +194,6 @@ to establish the new baselines as the desired behavior. This will change the fil
## Localization
All strings the user may see are stored in [`diagnosticMessages.json`](./src/compiler/diagnosticMessages.json).
If you make changes to it, run `jake generate-diagnostics` to push them to the `Diagnostic` interface in [`diagnosticInformationMap.generated.ts`](./src/compiler/diagnosticInformationMap.generated.ts).
If you make changes to it, run `jake generate-diagnostics` to push them to the `Diagnostic` interface in `diagnosticInformationMap.generated.ts`.
See [coding guidelines on diagnostic messages](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#diagnostic-messages).
+1 -1
View File
@@ -26,7 +26,7 @@ const exec = require("./scripts/build/exec");
const browserify = require("./scripts/build/browserify");
const prepend = require("./scripts/build/prepend");
const { removeSourceMaps } = require("./scripts/build/sourcemaps");
const { CancellationTokenSource, CancelError, delay, Semaphore } = require("prex");
const { CancellationTokenSource, CancelError, delay, Semaphore } = require("prex");
const { libraryTargets, generateLibs } = require("./scripts/build/lib");
const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests");
+2 -3
View File
@@ -147,14 +147,14 @@ task(TaskNames.local, [
task("default", [TaskNames.local]);
const RunTestsPrereqs = [TaskNames.lib, Paths.servicesDefinitionFile, Paths.typescriptDefinitionFile, Paths.tsserverLibraryDefinitionFile];
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... i[nspect]=true.");
task(TaskNames.runtestsParallel, RunTestsPrereqs, function () {
tsbuild([ConfigFileFor.runjs], true, () => {
runConsoleTests("min", /*parallel*/ true);
});
}, { async: true });
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... i[nspect]=true.");
task(TaskNames.runtests, RunTestsPrereqs, function () {
tsbuild([ConfigFileFor.runjs], true, () => {
runConsoleTests('mocha-fivemat-progress-reporter', /*runInParallel*/ false);
@@ -520,7 +520,6 @@ function runConsoleTests(defaultReporter, runInParallel) {
}
let testTimeout = process.env.timeout || defaultTestTimeout;
const debug = process.env.debug || process.env["debug-brk"] || process.env.d;
const inspect = process.env.inspect || process.env["inspect-brk"] || process.env.i;
const runners = process.env.runners || process.env.runner || process.env.ru;
const tests = process.env.test || process.env.tests || process.env.t;
+1 -1
View File
@@ -938,7 +938,7 @@
"Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_con_1322": "Der Typ iterierter Elemente eines \"yield*\"-Operanden muss entweder eine gültige Zusage sein oder darf keinen aufrufbaren \"then\"-Member enthalten.",
"Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_cal_1321": "Der Typ eines \"yield\"-Operanden in einem asynchronen Generator muss entweder eine gültige Zusage sein oder darf keinen aufrufbaren \"then\"-Member enthalten.",
"Type_parameter_0_has_a_circular_constraint_2313": "Der Typparameter \"{0}\" weist eine zirkuläre Einschränkung auf.",
"Type_parameter_0_has_a_circular_default_2716": "Der Typparameter \"{0}\" weist einen zirkulären Standard auf.",
"Type_parameter_0_has_a_circular_default_2716": "Der Typparameter \"{0}\" besitzt einen zirkulären Standardwert.",
"Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1_4008": "Der Typparameter \"{0}\" der Aufrufsignatur aus der exportierten Schnittstelle besitzt oder verwendet den privaten Namen \"{1}\".",
"Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1_4006": "Der Typparameter \"{0}\" der Konstruktorsignatur aus der exportierten Schnittstelle besitzt oder verwendet den privaten Namen \"{1}\".",
"Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002": "Der Typparameter \"{0}\" der exportierten Klasse besitzt oder verwendet den privaten Namen \"{1}\".",
+174 -18
View File
@@ -135,9 +135,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_refere_1254" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A 'const' initializer in an ambient context must be a string or numeric literal.]]></Val>
<Val><![CDATA[A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -861,6 +861,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_argument_for_0_was_not_provided_6210" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An argument for '{0}' was not provided.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_argument_matching_this_binding_pattern_was_not_provided_6211" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An argument matching this binding pattern was not provided.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type_2356" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An arithmetic operand must be of type 'any', 'number' or an enum type.]]></Val>
@@ -1233,6 +1245,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Build_option_0_requires_a_value_of_type_1_5073" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Build option '{0}' requires a value of type {1}.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Building_project_0_6358" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Building project '{0}'...]]></Val>
@@ -1401,6 +1419,36 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2583" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find name '{0}'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2584" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find name '{0}'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_types_Slashje_2582" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_types_Slashjquery_2581" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_types_Slashnode_2580" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node`.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_find_namespace_0_2503" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot find namespace '{0}'.]]></Val>
@@ -2001,6 +2049,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Did_you_mean_to_call_this_expression_6212" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Did you mean to call this expression?]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Did_you_mean_to_use_new_with_this_expression_6213" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Did you mean to use 'new' with this expression?]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Digit_expected_1124" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Digit expected.]]></Val>
@@ -2259,6 +2319,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enable_strict_bind_call_and_apply_methods_on_functions_6214" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enable strict 'bind', 'call', and 'apply' methods on functions.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enable_strict_checking_of_function_types_6186" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enable strict checking of function types.]]></Val>
@@ -2349,6 +2415,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_type_0_circularly_references_itself_2586" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum type '{0}' circularly references itself.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_type_0_has_members_with_initializers_that_are_not_literals_2535" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum type '{0}' has members with initializers that are not literals.]]></Val>
@@ -2421,9 +2493,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Expected_type_of_0_field_in_package_json_to_be_string_got_1_6105" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Expected_type_of_0_field_in_package_json_to_be_1_got_2_6105" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Expected type of '{0}' field in 'package.json' to be 'string', got '{1}'.]]></Val>
<Val><![CDATA[Expected type of '{0}' field in 'package.json' to be '{1}', got '{2}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -2781,6 +2853,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Generate_types_for_0_95067" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Generate types for '{0}']]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Generate_types_for_all_packages_without_types_95068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Generate types for all packages without types]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Generates a sourcemap for each corresponding '.d.ts' file.]]></Val>
@@ -2829,12 +2913,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Generic_type_instantiation_is_excessively_deep_and_possibly_infinite_2550" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Generic type instantiation is excessively deep and possibly infinite.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Getter_and_setter_accessors_do_not_agree_in_visibility_2379" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Getter and setter accessors do not agree in visibility.]]></Val>
@@ -3225,6 +3303,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";It_is_highly_likely_that_you_are_missing_a_semicolon_2734" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[It is highly likely that you are missing a semicolon.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";JSDoc_0_1_does_not_match_the_extends_2_clause_8023" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[JSDoc '@{0} {1}' does not match the 'extends {2}' clause.]]></Val>
@@ -3255,6 +3339,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";JSDoc_type_0_circularly_references_itself_2587" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[JSDoc type '{0}' circularly references itself.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags_8021" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.]]></Val>
@@ -3705,6 +3795,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Non_simple_parameter_declared_here_1348" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Non-simple parameter declared here.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Not_all_code_paths_return_a_value_7030" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Not all code paths return a value.]]></Val>
@@ -3909,9 +4005,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_5071" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_5071" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.]]></Val>
<Val><![CDATA[Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs', 'amd', 'es2015' or 'esNext'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5025,12 +5121,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Skipping_clean_because_not_all_projects_could_be_located_6371" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Skipping clean because not all projects could be located]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Source_Map_Options_6175" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Source Map Options]]></Val>
@@ -5313,6 +5403,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_expected_type_comes_from_the_return_type_of_this_signature_6502" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The expected type comes from the return type of this signature.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_expected_type_comes_from_this_index_signature_6501" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The expected type comes from this index signature.]]></Val>
@@ -5589,6 +5685,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_parameter_is_not_allowed_with_use_strict_directive_1346" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This parameter is not allowed with 'use strict' directive.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found_2354" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[This syntax requires an imported helper but module '{0}' cannot be found.]]></Val>
@@ -6051,6 +6153,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Unknown_build_option_0_5072" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Unknown build option '{0}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Unknown_compiler_option_0_5023" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Unknown compiler option '{0}'.]]></Val>
@@ -6207,6 +6315,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";You_cannot_rename_a_module_via_a_global_import_8031" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[You cannot rename a module via a global import.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library_8001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[You cannot rename elements that are defined in the standard TypeScript library.]]></Val>
@@ -6393,6 +6507,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_2585" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['{0}' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";_0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead_2686" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['{0}' refers to a UMD global, but the current file is a module. Consider adding an import instead.]]></Val>
@@ -6657,12 +6777,36 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";package_json_does_not_have_a_typesVersions_entry_that_matches_version_0_6207" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['package.json' does not have a 'typesVersions' entry that matches version '{0}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";package_json_has_0_field_1_that_references_2_6101" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['package.json' has '{0}' field '{1}' that references '{2}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range_6209" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['package.json' has a 'typesVersions' entry '{0}' that is not a valid semver range.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_ma_6208" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['package.json' has a 'typesVersions' entry '{0}' that matches compiler version '{1}', looking for a pattern to match module name '{2}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";package_json_has_a_typesVersions_field_with_version_specific_path_mappings_6206" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['package.json' has a 'typesVersions' field with version-specific path mappings.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";parameter_modifiers_can_only_be_used_in_a_ts_file_8012" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['parameter modifiers' can only be used in a .ts file.]]></Val>
@@ -6831,6 +6975,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";use_strict_directive_cannot_be_used_with_non_simple_parameter_list_1347" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['use strict' directive cannot be used with non-simple parameter list.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";use_strict_directive_used_here_1349" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['use strict' directive used here.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";with_statements_are_not_allowed_in_an_async_function_block_1300" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['with' statements are not allowed in an async function block.]]></Val>
+4 -4
View File
@@ -328,7 +328,7 @@
"Do_not_emit_outputs_if_any_errors_were_reported_6008": "No emitir salidas si se informa de algún error.",
"Do_not_emit_use_strict_directives_in_module_output_6112": "No emitir directivas 'use strict' en la salida del módulo.",
"Do_not_erase_const_enum_declarations_in_generated_code_6007": "No borrar las declaraciones de enumeración const en el código generado.",
"Do_not_generate_custom_helper_functions_like_extends_in_compiled_output_6157": "No generar funciones auxiliares personalizadas como \"__extends\" en la salida compilada.",
"Do_not_generate_custom_helper_functions_like_extends_in_compiled_output_6157": "No generar funciones del asistente personalizadas como \"__extends\" en la salida compilada.",
"Do_not_include_the_default_library_file_lib_d_ts_6158": "No incluir el archivo de biblioteca predeterminado (lib.d.ts).",
"Do_not_report_errors_on_unreachable_code_6077": "No notificar los errores del código inaccesible.",
"Do_not_report_errors_on_unused_labels_6074": "No notificar los errores de las etiquetas no usadas.",
@@ -477,7 +477,7 @@
"Import_declaration_0_is_using_private_name_1_4000": "La declaración de importación '{0}' usa el nombre privado '{1}'.",
"Import_declaration_conflicts_with_local_declaration_of_0_2440": "La declaración de importación está en conflicto con la declaración local de \"{0}\".",
"Import_declarations_in_a_namespace_cannot_reference_a_module_1147": "Las declaraciones de importación de un espacio de nombres no pueden hacer referencia a un módulo.",
"Import_emit_helpers_from_tslib_6139": "Importe elementos auxiliares de emisión de \"tslib\".",
"Import_emit_helpers_from_tslib_6139": "Importe asistentes de emisión de \"tslib\".",
"Import_may_be_converted_to_a_default_import_80003": "La importación puede convertirse a una importación predeterminada.",
"Import_name_cannot_be_0_2438": "El nombre de importación no puede ser \"{0}\".",
"Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relati_2439": "La declaración de importación o exportación de una declaración de módulo de ambiente no puede hacer referencia al módulo a través de su nombre relativo.",
@@ -892,8 +892,8 @@
"The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer_1190": "La declaración de variable de una instrucción \"for...of\" no puede tener un inicializador.",
"The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any_2410": "No se admite la instrucción 'with'. Todos los símbolos de un bloque 'with' tendrán el tipo 'any'.",
"This_constructor_function_may_be_converted_to_a_class_declaration_80002": "Esta función de constructor puede convertirse en una declaración de clase.",
"This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found_2354": "Esta sintaxis requiere una aplicación auxiliar importada, pero no se puede encontrar el módulo \"{0}\".",
"This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1_2343": "Esta sintaxis requiere una aplicación auxiliar importada denominada \"{1}\", pero el módulo \"{0}\" no tiene el miembro exportado \"{1}\".",
"This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found_2354": "Esta sintaxis requiere un asistente importado, pero no se puede encontrar el módulo \"{0}\".",
"This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1_2343": "Esta sintaxis requiere un asistente importado denominado \"{1}\", pero el módulo \"{0}\" no tiene el miembro exportado \"{1}\".",
"Trailing_comma_not_allowed_1009": "No se permite la coma final.",
"Transpile_each_file_as_a_separate_module_similar_to_ts_transpileModule_6153": "Transpilar cada archivo como un módulo aparte (parecido a \"ts.transpileModule\").",
"Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_mod_7035": "Pruebe \"npm install @types/{0}\" si existe o agregue un nuevo archivo de declaración (.d.ts) que incluya \"declare module '{0}';\"",
+8 -8
View File
@@ -68,7 +68,7 @@
"A_rest_parameter_cannot_have_an_initializer_1048": "rest 매개 변수에는 이니셜라이저를 사용할 수 없습니다.",
"A_rest_parameter_must_be_last_in_a_parameter_list_1014": "rest 매개 변수는 매개 변수 목록 마지막에 있어야 합니다.",
"A_rest_parameter_must_be_of_an_array_type_2370": "rest 매개 변수는 배열 형식이어야 합니다.",
"A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma_1013": "rest 매개 변수 또는 바인딩 패턴에 후행 쉼표를 사용할습니다.",
"A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma_1013": "rest 매개 변수 또는 바인딩 패턴에 후행 쉼표가 없을습니다.",
"A_return_statement_can_only_be_used_within_a_function_body_1108": "'return' 문은 함수 본문 내에서만 사용할 수 있습니다.",
"A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl_6167": "가져오기를 'baseUrl'에 상대적인 조회 위치로 다시 매핑하는 일련의 항목입니다.",
"A_set_accessor_cannot_have_a_return_type_annotation_1095": "'set' 접근자에는 반환 형식 주석을 사용할 수 없습니다.",
@@ -232,7 +232,7 @@
"Cannot_invoke_an_object_which_is_possibly_null_2721": "'null'일 수 있는 개체를 호출할 수 없습니다.",
"Cannot_invoke_an_object_which_is_possibly_null_or_undefined_2723": "'null'이거나 '정의되지 않음'일 수 있는 개체를 호출할 수 없습니다.",
"Cannot_invoke_an_object_which_is_possibly_undefined_2722": "'정의되지 않음'일 수 있는 개체를 호출할 수 없습니다.",
"Cannot_prepend_project_0_because_it_does_not_have_outFile_set_6308": "'outFile' 집합이 없기 때문에 '{0}' 프로젝트를 추가할 수 없습니다.",
"Cannot_prepend_project_0_because_it_does_not_have_outFile_set_6308": "'{0}' 프로젝트는 'outFile'이 설정되어 있지 않기 때문에 앞에 추가할 수 없습니다.",
"Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided_1205": "'--isolatedModules' 플래그가 제공된 경우 형식을 다시 내보낼 수 없습니다.",
"Cannot_read_file_0_Colon_1_5012": "파일 '{0}'을(를) 읽을 수 없습니다. {1}.",
"Cannot_redeclare_block_scoped_variable_0_2451": "블록 범위 변수 '{0}'을(를) 다시 선언할 수 없습니다.",
@@ -274,7 +274,7 @@
"Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json_6020": "구성 파일에 대한 경로 또는 'tsconfig.json'이 포함된 폴더에 대한 경로를 고려하여 프로젝트를 컴파일합니다.",
"Compiler_option_0_expects_an_argument_6044": "컴파일러 옵션 '{0}'에는 인수가 필요합니다.",
"Compiler_option_0_requires_a_value_of_type_1_5024": "컴파일러 옵션 '{0}'에 {1} 형식의 값이 필요합니다.",
"Composite_projects_may_not_disable_declaration_emit_6304": "복합 프로젝트는 선언 내보내기를 사용하지 않도록 설정할 수 없습니다.",
"Composite_projects_may_not_disable_declaration_emit_6304": "복합 프로젝트는 선언 내보내기를 비활성화할 수 없습니다.",
"Computed_property_names_are_not_allowed_in_enums_1164": "컴퓨팅된 속성 이름은 열거형에 사용할 수 없습니다.",
"Computed_values_are_not_permitted_in_an_enum_with_string_valued_members_2553": "계산된 값은 문자열 값 멤버가 포함된 열거형에서 허용되지 않습니다.",
"Concatenate_and_emit_output_to_single_file_6001": "출력을 연결하고 단일 파일로 내보냅니다.",
@@ -445,7 +445,7 @@
"Function_overload_must_be_static_2387": "함수 오버로드는 정적이어야 합니다.",
"Function_overload_must_not_be_static_2388": "함수 오버로드는 정적이 아니어야 합니다.",
"Generate_get_and_set_accessors_95046": "'get' 및 'set' 접근자 생성",
"Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": "해당하는 각 '.d.ts' 파일 sourcemap을 생성합니다.",
"Generates_a_sourcemap_for_each_corresponding_d_ts_file_6000": "해당하는 각 '.d.ts' 파일 sourcemap을 생성합니다.",
"Generates_corresponding_d_ts_file_6002": "해당 '.d.ts' 파일을 생성합니다.",
"Generates_corresponding_map_file_6043": "해당 '.map' 파일을 생성합니다.",
"Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_typ_7025": "생성기는 값을 생성하지 않으므로 암시적으로 '{0}' 형식입니다. 반환 형식을 제공하세요.",
@@ -677,13 +677,13 @@
"Print_names_of_generated_files_part_of_the_compilation_6154": "컴파일의 일부인 생성된 파일의 이름을 인쇄합니다.",
"Print_the_compiler_s_version_6019": "컴파일러 버전을 인쇄합니다.",
"Print_this_message_6017": "이 메시지를 출력합니다.",
"Project_0_can_t_be_built_because_its_dependency_1_has_errors_6363": "'{1}' 종속성에 오류가 있기 때문에 '{0}' 프로젝트를 빌드할 수 없습니다.",
"Project_0_can_t_be_built_because_its_dependency_1_has_errors_6363": "'{0}' 프로젝트는 '{1}' 종속성에 오류가 있기 때문에 빌드할 수 없습니다.",
"Project_0_is_out_of_date_because_its_dependency_1_is_out_of_date_6353": "'{1}' 종속성이 최신 상태가 아니기 때문에 '{0}' 프로젝트가 최신 상태가 아닙니다.",
"Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2_6350": "가장 오래된 출력 '{1}'이(가) 최신 입력 '{2}'보다 오래되었기 때문에 '{0}' 프로젝트가 최신 상태가 아닙니다.",
"Project_0_is_out_of_date_because_output_file_1_does_not_exist_6352": "'{1}' 출력 파일이 존재하지 않기 때문에 '{0}' 프로젝트가 최신 상태가 아닙니다.",
"Project_0_is_up_to_date_6361": "'{0}' 프로젝트가 최신 상태입니다.",
"Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2_6351": "최신 입력 '{1}'이(가) 가장 오래된 출력 '{2}'보다 오래되었기 때문에 '{0}' 프로젝트가 최신 상태입니다.",
"Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies_6354": "종속성 .d.ts 파일이 있기 때문에 '{0}' 프로젝트가 최신 상태입니다.",
"Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies_6354": "'{0}' 프로젝트는 종속성 .d.ts 파일이 있 최신 상태입니다.",
"Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202": "프로젝트 참조는 순환 그래프를 형성할 수 없습니다. 순환이 발견되었습니다. {0}",
"Projects_in_this_build_Colon_0_6355": "이 빌드의 프로젝트: {0}",
"Projects_to_reference_6300": "참조할 프로젝트",
@@ -803,7 +803,7 @@
"Show_what_would_be_built_or_deleted_if_specified_with_clean_6367": "빌드될 항목 표시(또는 '--clean'으로 지정된 경우 삭제될 항목 표시)",
"Signature_0_must_be_a_type_predicate_1224": "'{0}' 시그니처는 형식 조건자여야 합니다.",
"Skip_type_checking_of_declaration_files_6012": "선언 파일 형식 검사를 건너뜁니다.",
"Skipping_build_of_project_0_because_its_dependency_1_has_errors_6362": "'{1}' 종속성에 오류가 있기 때문에 '{0}' 프로젝트 빌드를 건너뜁니다.",
"Skipping_build_of_project_0_because_its_dependency_1_has_errors_6362": "'{0}' 프로젝트의 빌드는 '{1}' 종속성에 오류가 있기 때문에 건너뜁니다.",
"Skipping_clean_because_not_all_projects_could_be_located_6371": "일부 프로젝트를 찾을 수 없으므로 정리를 건너뛰는 중입니다.",
"Source_Map_Options_6175": "소스 맵 옵션",
"Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature_2382": "특수화된 오버로드 시그니처는 특수화되지 않은 서명에 할당할 수 없습니다.",
@@ -1039,7 +1039,7 @@
"const_declarations_must_be_initialized_1155": "'const' 선언은 초기화해야 합니다.",
"const_enum_member_initializer_was_evaluated_to_a_non_finite_value_2477": "'const' 열거형 멤버 이니셜라이저가 무한 값에 대해 평가되었습니다.",
"const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN_2478": "'const' 열거형 멤버 이니셜라이저가 허용되지 않은 'NaN' 값에 대해 평가되었습니다.",
"const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_im_2475": "'const' 열거형은 속성 또는 인덱스 액세스 식 또는 내보내기 할당 또는 가져오기 선언의 오른쪽 또는 형식 쿼리에서만 사용할 수 있습니다.",
"const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_im_2475": "'const' 열거형은 속성이나 인덱스 액세스 식, 또는 내보내기 할당이나 가져오기 선언의 오른쪽, 또는 형식 쿼리에서만 사용할 수 있습니다.",
"delete_cannot_be_called_on_an_identifier_in_strict_mode_1102": "strict 모드에서는 식별자에 대해 'delete'를 호출할 수 없습니다.",
"delete_this_Project_0_is_up_to_date_because_it_was_previously_built_6360": "이 항목 삭제 - '{0}' 프로젝트는 이전에 빌드되었기 때문에 최신 상태입니다.",
"enum_declarations_can_only_be_used_in_a_ts_file_8015": "'enum 선언'은 .ts 파일에서만 사용할 수 있습니다.",
+2 -2
View File
@@ -27,7 +27,7 @@ interface PromiseConstructor {
/**
* Creates a new Promise.
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
* a resolve callback used resolve the promise with a value or the result of another promise,
* a resolve callback used to resolve the promise with a value or the result of another promise,
* and a reject callback used to reject the promise with a provided reason or error.
*/
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
@@ -213,4 +213,4 @@ interface PromiseConstructor {
resolve(): Promise<void>;
}
declare var Promise: PromiseConstructor;
declare var Promise: PromiseConstructor;
+71 -1
View File
@@ -315,6 +315,66 @@ interface FunctionConstructor {
declare const Function: FunctionConstructor;
interface CallableFunction extends Function {
/**
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
* @param thisArg The object to be used as the this object.
* @param args An array of argument values to be passed to the function.
*/
apply<T, R>(this: (this: T) => R, thisArg: T): R;
apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R;
/**
* Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
* @param thisArg The object to be used as the this object.
* @param args Argument values to be passed to the function.
*/
call<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, ...args: A): R;
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg The object to be used as the this object.
* @param args Arguments to bind to the parameters of the function.
*/
bind<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T): (...args: A) => R;
bind<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R;
bind<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R;
bind<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
bind<T, A0, A1, A2, A3, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R;
bind<T, AX, R>(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R;
}
interface NewableFunction extends Function {
/**
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
* @param thisArg The object to be used as the this object.
* @param args An array of argument values to be passed to the function.
*/
apply<T>(this: new () => T, thisArg: T): void;
apply<T, A extends any[]>(this: new (...args: A) => T, thisArg: T, args: A): void;
/**
* Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
* @param thisArg The object to be used as the this object.
* @param args Argument values to be passed to the function.
*/
call<T, A extends any[]>(this: new (...args: A) => T, thisArg: T, ...args: A): void;
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg The object to be used as the this object.
* @param args Arguments to bind to the parameters of the function.
*/
bind<A extends any[], R>(this: new (...args: A) => R, thisArg: any): new (...args: A) => R;
bind<A0, A extends any[], R>(this: new (arg0: A0, ...args: A) => R, thisArg: any, arg0: A0): new (...args: A) => R;
bind<A0, A1, A extends any[], R>(this: new (arg0: A0, arg1: A1, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1): new (...args: A) => R;
bind<A0, A1, A2, A extends any[], R>(this: new (arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1, arg2: A2): new (...args: A) => R;
bind<A0, A1, A2, A3, A extends any[], R>(this: new (arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: any, arg0: A0, arg1: A1, arg2: A2, arg3: A3): new (...args: A) => R;
bind<AX, R>(this: new (...args: AX[]) => R, thisArg: any, ...args: AX[]): new (...args: AX[]) => R;
}
interface IArguments {
[index: number]: any;
length: number;
@@ -1370,7 +1430,7 @@ type Readonly<T> = {
};
/**
* From T pick a set of properties K
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
@@ -1398,6 +1458,16 @@ type Extract<T, U> = T extends U ? T : never;
*/
type NonNullable<T> = T extends null | undefined ? never : T;
/**
* Obtain the parameters of a function type in a tuple
*/
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer P) => any ? P : never;
/**
* Obtain the parameters of a constructor function type in a tuple
*/
type ConstructorParameters<T extends new (...args: any[]) => any> = T extends new (...args: infer P) => any ? P : never;
/**
* Obtain the return type of a function type
*/
+2 -2
View File
@@ -31,7 +31,7 @@ interface ReadonlyArray<T> {
* thisArg is omitted, undefined is used as the this value.
*/
flatMap<U, This = undefined> (
callback: (this: This, value: T, index: number, array: T[]) => U|U[],
callback: (this: This, value: T, index: number, array: T[]) => U|ReadonlyArray<U>,
thisArg?: This
): U[]
@@ -145,7 +145,7 @@ interface Array<T> {
* thisArg is omitted, undefined is used as the this value.
*/
flatMap<U, This = undefined> (
callback: (this: This, value: T, index: number, array: T[]) => U|U[],
callback: (this: This, value: T, index: number, array: T[]) => U|ReadonlyArray<U>,
thisArg?: This
): U[]
+51 -6
View File
@@ -827,15 +827,17 @@ declare namespace ts.server.protocol {
/**
* Information about the item to be renamed.
*/
interface RenameInfo {
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
/**
* True if item can be renamed.
*/
canRename: boolean;
canRename: true;
/**
* Error message if item can not be renamed.
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
localizedErrorMessage?: string;
fileToRename?: string;
/**
* Display name of the item to be renamed.
*/
@@ -852,6 +854,15 @@ declare namespace ts.server.protocol {
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
/** Span of text to rename. */
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage: string;
}
/**
* A group of text spans, all in 'file'.
@@ -860,7 +871,11 @@ declare namespace ts.server.protocol {
/** The file to which the spans apply */
file: string;
/** The text spans in this group */
locs: TextSpan[];
locs: RenameTextSpan[];
}
interface RenameTextSpan extends TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface RenameResponseBody {
/**
@@ -1373,7 +1388,7 @@ declare namespace ts.server.protocol {
* begin with prefix.
*/
interface CompletionsRequest extends FileLocationRequest {
command: CommandTypes.Completions;
command: CommandTypes.Completions | CommandTypes.CompletionInfo;
arguments: CompletionsRequestArgs;
}
/**
@@ -1885,6 +1900,35 @@ declare namespace ts.server.protocol {
*/
openFiles: string[];
}
type ProjectLoadingStartEventName = "projectLoadingStart";
interface ProjectLoadingStartEvent extends Event {
event: ProjectLoadingStartEventName;
body: ProjectLoadingStartEventBody;
}
interface ProjectLoadingStartEventBody {
/** name of the project */
projectName: string;
/** reason for loading */
reason: string;
}
type ProjectLoadingFinishEventName = "projectLoadingFinish";
interface ProjectLoadingFinishEvent extends Event {
event: ProjectLoadingFinishEventName;
body: ProjectLoadingFinishEventBody;
}
interface ProjectLoadingFinishEventBody {
/** name of the project */
projectName: string;
}
type SurveyReadyEventName = "surveyReady";
interface SurveyReadyEvent extends Event {
event: SurveyReadyEventName;
body: SurveyReadyEventBody;
}
interface SurveyReadyEventBody {
/** Name of the survey. This is an internal machine- and programmer-friendly name */
surveyId: string;
}
type LargeFileReferencedEventName = "largeFileReferenced";
interface LargeFileReferencedEvent extends Event {
event: LargeFileReferencedEventName;
@@ -2220,6 +2264,7 @@ declare namespace ts.server.protocol {
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
}
interface CompilerOptions {
allowJs?: boolean;
+12 -12
View File
@@ -61,7 +61,7 @@
"A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly_1330": "Uma propriedade de uma interface ou tipo literal cujo tipo é um tipo de 'unique symbol' deve ser 'readonly'.",
"A_required_parameter_cannot_follow_an_optional_parameter_1016": "Um parâmetro obrigatório não pode seguir um parâmetro opcional.",
"A_rest_element_cannot_contain_a_binding_pattern_2501": "Um elemento rest não pode conter um padrão de associação.",
"A_rest_element_cannot_have_a_property_name_2566": "Um elemento restante não pode ter um nome de propriedade.",
"A_rest_element_cannot_have_a_property_name_2566": "Um elemento rest não pode ter um nome de propriedade.",
"A_rest_element_cannot_have_an_initializer_1186": "Um elemento rest não pode ter um inicializador.",
"A_rest_element_must_be_last_in_a_destructuring_pattern_2462": "Um elemento rest deve ser o último em um padrão de desestruturação.",
"A_rest_parameter_cannot_be_optional_1047": "Um parâmetro rest não pode ser opcional.",
@@ -174,7 +174,7 @@
"An_object_member_cannot_be_declared_optional_1162": "Um membro de objeto não pode ser declarado como opcional.",
"An_overload_signature_cannot_be_declared_as_a_generator_1222": "A assinatura de sobrecarga não pode ser declarada como geradora.",
"An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_ex_17006": "Uma expressão unária com o operador '{0}' não é permitida no lado esquerdo de uma expressão de exponenciação. Considere delimitar a expressão em parênteses.",
"Annotate_everything_with_types_from_JSDoc_95043": "Anotar tudo com tipos de JSDoc",
"Annotate_everything_with_types_from_JSDoc_95043": "Anotar tudo com tipos do JSDoc",
"Annotate_with_type_from_JSDoc_95009": "Anotar com o tipo do JSDoc",
"Annotate_with_types_from_JSDoc_95010": "Anotar com os tipos do JSDoc",
"Argument_expression_expected_1135": "Expressão de argumento esperada.",
@@ -368,7 +368,7 @@
"Enables_experimental_support_for_ES7_decorators_6065": "Habilita o suporte experimental para decoradores ES7.",
"Enables_experimental_support_for_emitting_type_metadata_for_decorators_6066": "Habilita o suporte experimental para a emissão de tipo de metadados para decoradores.",
"Enum_0_used_before_its_declaration_2450": "A enumeração '{0}' usada antes de sua declaração.",
"Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567": "As declarações de enum apenas podem se mescladas com namespaces ou com outras declarações de enum.",
"Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567": "As declarações enum só podem ser mescladas com namespaces ou com outras declarações enum.",
"Enum_declarations_must_all_be_const_or_non_const_2473": "Declarações de enumeração devem ser const ou não const.",
"Enum_member_expected_1132": "Membro de enumeração esperado.",
"Enum_member_must_have_initializer_1061": "O membro de enumeração deve ter um inicializador.",
@@ -571,7 +571,7 @@
"Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambig_2308": "O módulo {0} já exportou um membro denominado '{1}'. Considere reexportar explicitamente para resolver a ambiguidade.",
"Module_0_has_no_default_export_1192": "O módulo '{0}' não tem padrão de exportação.",
"Module_0_has_no_exported_member_1_2305": "O módulo '{0}' não tem nenhum membro exportado '{1}'.",
"Module_0_has_no_exported_member_1_Did_you_mean_2_2724": "O módulo '{0}' não tem nenhum membro exportado '{1}'. Você quis dizer '{2}'?",
"Module_0_has_no_exported_member_1_Did_you_mean_2_2724": "O módulo '{0}' não tem nenhum membro '{1}' exportado. Você quis dizer '{2}'?",
"Module_0_is_hidden_by_a_local_declaration_with_the_same_name_2437": "O módulo '{0}' está oculto por uma declaração de local com o mesmo nome.",
"Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct_2497": "O módulo '{0}' resolve para uma entidade sem módulo e não pode ser importado usando este constructo.",
"Module_0_uses_export_and_cannot_be_used_with_export_Asterisk_2498": "O módulo '{0}' usa 'export =' e não pode ser usado com 'export *'.",
@@ -622,7 +622,7 @@
"Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided_5051": "A opção '{0} só pode ser usada quando qualquer uma das opções '--inlineSourceMap' ou '--sourceMap' é fornecida.",
"Option_0_cannot_be_specified_with_option_1_5053": "A opção '{0}' não pode ser especificada com a opção '{1}'.",
"Option_0_cannot_be_specified_without_specifying_option_1_5052": "A opção '{0}' não pode ser especificada sem especificar a opção '{1}'.",
"Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069": "A opção '{0}' não pode ser especificada sem especificar a opção '{1}' ou a opção '{2}'.",
"Option_0_cannot_be_specified_without_specifying_option_1_or_option_2_5069": "A opção '{0}' não pode ser especificada sem a especificação da opção '{1}' ou '{2}'.",
"Option_0_should_have_array_of_strings_as_a_value_6103": "A opção '{0}' deve ter matriz de cadeias de um valor.",
"Option_build_must_be_the_first_command_line_argument_6369": "A opção '--build' precisa ser o primeiro argumento da linha de comando.",
"Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES_5047": "A opção 'isolatedModules' só pode ser usada quando nenhuma opção de '--module' for fornecida ou a opção 'target' for 'ES2015' ou superior.",
@@ -686,7 +686,7 @@
"Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies_6354": "O projeto '{0}' está atualizado com os arquivos .d.ts de suas dependências",
"Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202": "Referências de projeto não podem formar um gráfico circular. Ciclo detectado: {0}",
"Projects_in_this_build_Colon_0_6355": "Projetos neste build: {0}",
"Projects_to_reference_6300": "Projetos para referência",
"Projects_to_reference_6300": "Projetos a serem referenciados",
"Property_0_does_not_exist_on_const_enum_1_2479": "A propriedade '{0}' não existe na enumeração 'const' '{1}'.",
"Property_0_does_not_exist_on_type_1_2339": "A propriedade '{0}' não existe no tipo '{1}'.",
"Property_0_does_not_exist_on_type_1_Did_you_forget_to_use_await_2570": "A propriedade '{0}' não existe no tipo '{1}'. Você esqueceu de usar 'await'?",
@@ -740,7 +740,7 @@
"Remove_braces_from_arrow_function_95060": "Remover chaves da função de seta",
"Remove_declaration_for_Colon_0_90004": "Remover declaração para: '{0}'",
"Remove_destructuring_90009": "Remover desestruturação",
"Remove_import_from_0_90005": "Remover importação do '{0}'",
"Remove_import_from_0_90005": "Remover importação de '{0}'",
"Remove_unreachable_code_95050": "Remover código inacessível",
"Remove_unused_label_95053": "Remover rótulo não utilizado",
"Remove_variable_statement_90010": "Remover instrução de variável",
@@ -752,7 +752,7 @@
"Report_errors_on_unused_parameters_6135": "Relatar erros nos parâmetros não utilizados.",
"Required_type_parameters_may_not_follow_optional_type_parameters_2706": "Os parâmetros de tipo necessários podem não seguir os parâmetros de tipo opcionais.",
"Resolution_for_module_0_was_found_in_cache_from_location_1_6147": "A resolução para o módulo '{0}' foi encontrada no cache do local '{1}'.",
"Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols_6195": "Resolva 'keyof' para nomes de propriedades com valores de cadeia de caracteres somente (sem números ou símbolos).",
"Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols_6195": "Resolva 'keyof' somente para nomes de propriedades com valores de cadeia de caracteres (sem números nem símbolos).",
"Resolving_from_node_modules_folder_6118": "Resolvendo na pasta node_modules...",
"Resolving_module_0_from_1_6086": "======== Resolvendo módulo '{0}' de '{1}'. ========",
"Resolving_module_name_0_relative_to_base_url_1_2_6094": "Resolvendo nome de módulo '{0}' relativo à URL base '{1}' - '{2}'.",
@@ -803,8 +803,8 @@
"Show_what_would_be_built_or_deleted_if_specified_with_clean_6367": "Mostrar o que seria compilado (ou excluído, se especificado com '--clean')",
"Signature_0_must_be_a_type_predicate_1224": "A assinatura '{0}' deve ser um predicado de tipo.",
"Skip_type_checking_of_declaration_files_6012": "Ignorar a verificação de tipo dos arquivos de declaração.",
"Skipping_build_of_project_0_because_its_dependency_1_has_errors_6362": "Ignorando build do projeto '{0}' porque sua dependência '{1}' tem erros",
"Skipping_clean_because_not_all_projects_could_be_located_6371": "Ignorando a limpeza porque nem todos os projetos foram localizados",
"Skipping_build_of_project_0_because_its_dependency_1_has_errors_6362": "Ignorando o build do projeto '{0}' porque a dependência '{1}' tem erros",
"Skipping_clean_because_not_all_projects_could_be_located_6371": "Ignorando a limpeza porque não foram localizados todos os projetos",
"Source_Map_Options_6175": "Opções do Sourcemap",
"Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature_2382": "A assinatura de sobrecarga especializada não pode ser atribuída a qualquer assinatura não especializada.",
"Specifier_of_dynamic_import_cannot_be_spread_element_1325": "O especificador de importação dinâmica não pode ser o elemento de difusão.",
@@ -966,7 +966,7 @@
"Unexpected_end_of_text_1126": "Fim inesperado do texto.",
"Unexpected_token_1012": "Token inesperado.",
"Unexpected_token_A_constructor_method_accessor_or_property_was_expected_1068": "Token inesperado. Um construtor, método, acessador ou propriedade era esperado.",
"Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069": "Token inesperado. Um nome de parâmetro de tipo era esperado sem chaves.",
"Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces_1069": "Token inesperado. Era esperado um nome de parâmetro de tipo sem chaves.",
"Unexpected_token_expected_1179": "Token inesperado. '{' esperado.",
"Unknown_compiler_option_0_5023": "Opção do compilador '{0}' desconhecida.",
"Unknown_option_excludes_Did_you_mean_exclude_6114": "Opção desconhecida 'excludes'. Você quis dizer 'exclude'?",
@@ -993,7 +993,7 @@
"Variable_declaration_list_cannot_be_empty_1123": "A lista de declaração de variável não pode estar vazia.",
"Version_0_6029": "Versão {0}",
"Watch_input_files_6005": "Observe os arquivos de entrada.",
"Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen_6191": "Se se deve manter a saída de console desatualizada no modo de inspeção, em vez de limpar a tela.",
"Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen_6191": "Se é necessário manter a saída de console desatualizada no modo de inspeção, em vez de limpar a tela.",
"You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library_8001": "Não é possível renomear elementos que são definidos na biblioteca TypeScript padrão.",
"You_cannot_rename_this_element_8000": "Você não pode renomear este elemento.",
"_0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write__1329": "'{0}' aceita muito poucos argumentos para serem usados como um decorador aqui. Você quis dizer para chamá-lo primeiro e gravar '@{0}()'?",
+10 -10
View File
@@ -49,8 +49,8 @@
"A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged_2434": "Bir ad alanı bildirimi, birleştirildiği sınıf veya işlevden önce gelemez.",
"A_namespace_declaration_is_only_allowed_in_a_namespace_or_module_1235": "Ad alanı bildirimine yalnızca bir ad alanında veya modülde izin verilir.",
"A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_7038": "Bir ad alanı stili içeri aktarma işlemi çağrılamadığından veya oluşturulamadığından çalışma zamanında hataya yol açacak.",
"A_non_dry_build_would_build_project_0_6357": "non-dry bir derleme '{0}' projesini derler",
"A_non_dry_build_would_delete_the_following_files_Colon_0_6356": "non-dry bir derleme şu dosyaları siler: {0}",
"A_non_dry_build_would_build_project_0_6357": "-dry bayrağı kullanılmayan bir derleme '{0}' projesini derler",
"A_non_dry_build_would_delete_the_following_files_Colon_0_6356": "-dry bayrağı kullanılmayan bir derleme şu dosyaları siler: {0}",
"A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation_2371": "Parametre başlatıcısına yalnızca bir işlevde veya oluşturucu uygulamasında izin verilir.",
"A_parameter_property_cannot_be_declared_using_a_rest_parameter_1317": "Parametre özelliği, rest parametresi kullanılarak bildirilemez.",
"A_parameter_property_is_only_allowed_in_a_constructor_implementation_2369": "Parametre özelliğine yalnızca bir oluşturucu uygulamasında izin verilir.",
@@ -110,7 +110,7 @@
"Add_initializers_to_all_uninitialized_properties_95027": "Tüm başlatılmamış özelliklere başlatıcılar ekle",
"Add_missing_super_call_90001": "Eksik 'super()' çağrısını ekle",
"Add_missing_typeof_95052": "Eksik 'typeof' öğesini ekle",
"Add_or_remove_braces_in_an_arrow_function_95058": "Ok işlevine küme ayracı ekleyin veya kaldırın",
"Add_or_remove_braces_in_an_arrow_function_95058": "Ok işlevine küme ayracı ekle veya kaldır",
"Add_qualifier_to_all_unresolved_variables_matching_a_member_name_95037": "Bir üye adıyla eşleşen tüm çözülmemiş değişkenlere niteleyici ekle",
"Add_to_all_uncalled_decorators_95044": "Çağrılmayan tüm dekoratörlere '()' ekle",
"Add_ts_ignore_to_all_error_messages_95042": "Tüm hata iletilerine '@ts-ignore' ekle",
@@ -122,7 +122,7 @@
"All_declarations_of_0_must_have_identical_modifiers_2687": "Tüm '{0}' bildirimleri aynı değiştiricilere sahip olmalıdır.",
"All_declarations_of_0_must_have_identical_type_parameters_2428": "Tüm '{0}' bildirimleri özdeş tür parametrelerine sahip olmalıdır.",
"All_declarations_of_an_abstract_method_must_be_consecutive_2516": "Soyut metoda ait tüm bildirimler ardışık olmalıdır.",
"All_destructured_elements_are_unused_6198": "Yok edilen öğelerin hiçbiri kullanılmamış.",
"All_destructured_elements_are_unused_6198": "Yapısı bozulan öğelerin hiçbiri kullanılmıyor.",
"All_imports_in_import_declaration_are_unused_6192": "İçeri aktarma bildirimindeki hiçbir içeri aktarma kullanılmadı.",
"All_variables_are_unused_6199": "Hiçbir değişken kullanılmıyor.",
"Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typech_6011": "Varsayılan dışarı aktarmaya sahip olmayan modüllerde varsayılan içeri aktarmalara izin verin. Bu işlem kod üretimini etkilemez, yalnızca tür denetimini etkiler.",
@@ -232,7 +232,7 @@
"Cannot_invoke_an_object_which_is_possibly_null_2721": "Muhtemelen 'null' olan bir nesne çağrılamıyor.",
"Cannot_invoke_an_object_which_is_possibly_null_or_undefined_2723": "Muhtemelen 'null' veya 'undefined' olan bir nesne çağrılamıyor.",
"Cannot_invoke_an_object_which_is_possibly_undefined_2722": "Muhtemelen 'undefined' olan bir nesne çağrılamıyor.",
"Cannot_prepend_project_0_because_it_does_not_have_outFile_set_6308": "'{0}' projesi, 'outFile' kümesi içermediğinden başa eklenemiyor",
"Cannot_prepend_project_0_because_it_does_not_have_outFile_set_6308": "{0}' projesi için 'outFile' ayarlanmadığından başa eklenemiyor",
"Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided_1205": "'--isolatedModules' bayrağı sağlandığında bir tür yeniden dışarı aktarılamaz.",
"Cannot_read_file_0_Colon_1_5012": "'{0}' dosyası okunamıyor: {1}.",
"Cannot_redeclare_block_scoped_variable_0_2451": "Blok kapsamlı değişken '{0}', yeniden bildirilemiyor.",
@@ -311,7 +311,7 @@
"Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name_1207": "Dekoratörler aynı ada sahip birden fazla get/set erişimcisine uygulanamaz.",
"Default_export_of_the_module_has_or_is_using_private_name_0_4082": "Modülün varsayılan dışarı aktarımı '{0}' özel adına sahip veya bu adı kullanıyor.",
"Delete_all_unused_declarations_95024": "Kullanılmayan tüm bildirimleri sil",
"Delete_the_outputs_of_all_projects_6365": "Tüm projelerin çıkışlarını silin",
"Delete_the_outputs_of_all_projects_6365": "Tüm projelerin çıkışlarını sil",
"Deprecated_Use_jsxFactory_instead_Specify_the_object_invoked_for_createElement_when_targeting_react__6084": "[Kullanım Dışı] Bunun yerine '--jsxFactory' kullanın. 'react' JSX gösterimi hedefleniyorsa, createElement için çağrılan nesneyi belirtin",
"Deprecated_Use_outFile_instead_Concatenate_and_emit_output_to_single_file_6170": "[Kullanım Dışı] Bunun yerine '--outFile' kullanın. Çıkışı tek bir dosya olarak birleştirin ve gösterin",
"Deprecated_Use_skipLibCheck_instead_Skip_type_checking_of_default_library_declaration_files_6160": "[Kullanım Dışı] Bunun yerine '--skipLibCheck' kullanın. Varsayılan kitaplık bildirim dosyalarının tür denetimini atlayın.",
@@ -362,13 +362,13 @@
"Enable_strict_checking_of_property_initialization_in_classes_6187": "Sınıflarda sıkı özellik başlatma denetimini etkinleştirin.",
"Enable_strict_null_checks_6113": "Katı null denetimlerini etkinleştir.",
"Enable_tracing_of_the_name_resolution_process_6085": "Ad çözümleme işlemini izlemeyi etkinleştir.",
"Enable_verbose_logging_6366": "Ayrıntılı günlüğe yazmayı etkinleştirin",
"Enable_verbose_logging_6366": "Ayrıntılı günlüğe yazmayı etkinleştir",
"Enables_emit_interoperability_between_CommonJS_and_ES_Modules_via_creation_of_namespace_objects_for__7037": "Tüm içeri aktarma işlemleri için ad alanı nesnelerinin oluşturulması aracılığıyla CommonJS ile ES Modülleri arasında yayımlama birlikte çalışabilirliğine imkan tanır. Şu anlama gelir: 'allowSyntheticDefaultImports'.",
"Enables_experimental_support_for_ES7_async_functions_6068": "Zaman uyumsuz ES7 işlevleri için deneysel desteği etkinleştirir.",
"Enables_experimental_support_for_ES7_decorators_6065": "ES7 dekoratörleri için deneysel desteği etkinleştirir.",
"Enables_experimental_support_for_emitting_type_metadata_for_decorators_6066": "Dekoratörlere tür meta verisi gönderme için deneysel desteği etkinleştirir.",
"Enum_0_used_before_its_declaration_2450": "'{0}' sabit listesi, bildiriminden önce kullanıldı.",
"Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567": "Enum bildirimleri yalnızca ad alanı veya diğer enum bildirimleri ile birleştirilebilir.",
"Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567": "Sabit listesi bildirimleri yalnızca ad alanı veya diğer sabit listesi bildirimleri ile birleştirilebilir.",
"Enum_declarations_must_all_be_const_or_non_const_2473": "Sabit listesi bildirimlerinin tümü const veya const olmayan değerler olmalıdır.",
"Enum_member_expected_1132": "Sabit listesi üyesi bekleniyor.",
"Enum_member_must_have_initializer_1061": "Sabit listesi üyesi bir başlatıcıya sahip olmalıdır.",
@@ -571,7 +571,7 @@
"Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambig_2308": "{0} modülü, '{1}' adlı bir üyeyi zaten dışarı aktardı. Belirsizliği çözmek için açık olarak yeniden dışarı aktarmayı göz önünde bulundurun.",
"Module_0_has_no_default_export_1192": "'{0}' modülü için varsayılan dışarı aktarma yok.",
"Module_0_has_no_exported_member_1_2305": "'{0}' modülü, dışarı aktarılan '{1}' üyesine sahip değil.",
"Module_0_has_no_exported_member_1_Did_you_mean_2_2724": "'{0}' modülünün dışa aktarılan '{1}' adlı bir üyesi yok. Şunu mu demek istediniz: '{2}'?",
"Module_0_has_no_exported_member_1_Did_you_mean_2_2724": "{0}' modülünün dışarı aktarılan '{1}' adlı bir üyesi yok. Şunu mu demek istediniz: '{2}'?",
"Module_0_is_hidden_by_a_local_declaration_with_the_same_name_2437": "'{0}' modülü, aynı ada sahip bir yerel bildirim tarafından gizleniyor.",
"Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct_2497": "'{0}' modülü, modül olmayan bir varlığa çözümleniyor ve bu oluşturma ile içeri aktarılamaz.",
"Module_0_uses_export_and_cannot_be_used_with_export_Asterisk_2498": "'{0}' modülü 'export =' kullanıyor ve 'export *' ile birlikte kullanılamaz.",
@@ -737,7 +737,7 @@
"Referenced_project_0_must_have_setting_composite_Colon_true_6306": "Başvurulan proje '{0}' \"composite\": true ayarına sahip olmalıdır.",
"Remove_all_unreachable_code_95051": "Tüm erişilemeyen kodları kaldır",
"Remove_all_unused_labels_95054": "Kullanılmayan tüm etiketleri kaldır",
"Remove_braces_from_arrow_function_95060": "Ok işlevinden köşeli ayraçları kaldırın",
"Remove_braces_from_arrow_function_95060": "Ok işlevinden küme ayraçlarını kaldır",
"Remove_declaration_for_Colon_0_90004": "'{0}' bildirimini kaldır",
"Remove_destructuring_90009": "Yıkmayı kaldır",
"Remove_import_from_0_90005": "'{0}' öğesinden içeri aktarmayı kaldır",
+5115 -3374
View File
File diff suppressed because it is too large Load Diff
+7548 -4532
View File
File diff suppressed because it is too large Load Diff
+197 -280
View File
@@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.1";
const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
const version: string;
}
@@ -69,7 +69,8 @@ declare namespace ts {
pos: number;
end: number;
}
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown;
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown | KeywordSyntaxKind;
type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
enum SyntaxKind {
Unknown = 0,
@@ -536,6 +537,7 @@ declare namespace ts {
name?: Identifier | StringLiteral | NumericLiteral;
}
interface ComputedPropertyName extends Node {
parent: Declaration;
kind: SyntaxKind.ComputedPropertyName;
expression: Expression;
}
@@ -632,6 +634,7 @@ declare namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
@@ -668,6 +671,7 @@ declare namespace ts {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction;
@@ -1079,7 +1083,7 @@ declare namespace ts {
}
interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
interface NewExpression extends PrimaryExpression, Declaration {
@@ -1808,7 +1812,8 @@ declare namespace ts {
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
isSourceFileDefaultLibrary(file: SourceFile): boolean;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
@@ -2056,32 +2061,32 @@ declare namespace ts {
ExportStar = 8388608,
Optional = 16777216,
Transient = 33554432,
JSContainer = 67108864,
Assignment = 67108864,
ModuleExports = 134217728,
Enum = 384,
Variable = 3,
Value = 67216319,
Type = 67901928,
Value = 67220415,
Type = 67897832,
Namespace = 1920,
Module = 1536,
Accessor = 98304,
FunctionScopedVariableExcludes = 67216318,
BlockScopedVariableExcludes = 67216319,
ParameterExcludes = 67216319,
FunctionScopedVariableExcludes = 67220414,
BlockScopedVariableExcludes = 67220415,
ParameterExcludes = 67220415,
PropertyExcludes = 0,
EnumMemberExcludes = 68008959,
FunctionExcludes = 67215791,
FunctionExcludes = 67219887,
ClassExcludes = 68008383,
InterfaceExcludes = 67901832,
InterfaceExcludes = 67897736,
RegularEnumExcludes = 68008191,
ConstEnumExcludes = 68008831,
ValueModuleExcludes = 67215503,
ValueModuleExcludes = 110735,
NamespaceModuleExcludes = 0,
MethodExcludes = 67208127,
GetAccessorExcludes = 67150783,
SetAccessorExcludes = 67183551,
TypeParameterExcludes = 67639784,
TypeAliasExcludes = 67901928,
MethodExcludes = 67212223,
GetAccessorExcludes = 67154879,
SetAccessorExcludes = 67187647,
TypeParameterExcludes = 67635688,
TypeAliasExcludes = 67897832,
AliasExcludes = 2097152,
ModuleMember = 2623475,
ExportHasLocal = 944,
@@ -2490,6 +2495,7 @@ declare namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
@@ -2581,7 +2587,6 @@ declare namespace ts {
}
interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
interface CreateProgramOptions {
@@ -2592,14 +2597,6 @@ declare namespace ts {
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
interface UpToDateHost {
fileExists(fileName: string): boolean;
getModifiedTime(fileName: string): Date | undefined;
getUnchangedTime?(fileName: string): Date | undefined;
getLastStatus?(fileName: string): UpToDateStatus | undefined;
setLastStatus?(fileName: string, status: UpToDateStatus): void;
parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined;
}
interface ModuleResolutionHost {
fileExists(fileName: string): boolean;
readFile(fileName: string): string | undefined;
@@ -2698,9 +2695,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
getModifiedTime?(fileName: string): Date | undefined;
setModifiedTime?(fileName: string, date: Date): void;
deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -3001,6 +2995,16 @@ declare namespace ts {
Parameters = 1296,
IndexSignatureParameters = 4432
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
}
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -3209,17 +3213,27 @@ declare namespace ts {
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* @remarks Returns any JSDoc param tag whose name matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
* For binding patterns, parameter tags are matched by position.
*/
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag>;
/**
* Gets the JSDoc type parameter tags for the node if present.
*
* @remarks Returns any JSDoc template tag whose names match the provided
* parameter, whether a template tag on a containing function
* expression, or a template tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the template
* tag on the containing function expression would be first.
*/
function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray<JSDocTemplateTag>;
/**
* Return true if the node has JSDoc parameter tags.
*
@@ -4171,14 +4185,15 @@ declare namespace ts {
* @returns A 'Program' object.
*/
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
interface ResolveProjectReferencePathHost {
/** @deprecated */ interface ResolveProjectReferencePathHost {
fileExists(fileName: string): boolean;
}
/**
* Returns the target config filename of a project reference.
* Note: The file might not exist.
*/
function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName;
/** @deprecated */ function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
}
declare namespace ts {
interface EmitOutput {
@@ -4303,32 +4318,43 @@ declare namespace ts {
* Create the builder to manage semantic diagnostics and cache them
*/
function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): SemanticDiagnosticsBuilderProgram;
/**
* Create the builder that can handle the changes in program and iterate through changed files
* to emit the those files and manage semantic diagnostics cache as well
*/
function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): EmitAndSemanticDiagnosticsBuilderProgram;
/**
* Creates a builder thats just abstraction over program and can be used with watch
*/
function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): BuilderProgram;
}
declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
interface WatchCompilerHost<T extends BuilderProgram> {
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference> | undefined) => T;
/** Host that has watch functionality used in --watch mode */
interface WatchHost {
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram<T>;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4361,14 +4387,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
@@ -4378,6 +4396,8 @@ declare namespace ts {
rootFiles: string[];
/** Compiler options */
options: CompilerOptions;
/** Project References */
projectReferences?: ReadonlyArray<ProjectReference>;
}
/**
* Host to create watch with config file
@@ -4412,8 +4432,8 @@ declare namespace ts {
/**
* Create the watch compiler host for either configFile or fileNames and its options
*/
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions<T>;
function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray<ProjectReference>): WatchCompilerHostOfFilesAndCompilerOptions<T>;
/**
* Creates the watch from the host for root files and compiler options
*/
@@ -4423,184 +4443,11 @@ declare namespace ts {
*/
function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
}
declare namespace ts {
interface BuildHost {
verbose(diag: DiagnosticMessage, ...args: string[]): void;
error(diag: DiagnosticMessage, ...args: string[]): void;
errorDiagnostic(diag: Diagnostic): void;
message(diag: DiagnosticMessage, ...args: string[]): void;
}
/**
* A BuildContext tracks what's going on during the course of a build.
*
* Callers may invoke any number of build requests within the same context;
* until the context is reset, each project will only be built at most once.
*
* Example: In a standard setup where project B depends on project A, and both are out of date,
* a failed build of A will result in A remaining out of date. When we try to build
* B, we should immediately bail instead of recomputing A's up-to-date status again.
*
* This also matters for performing fast (i.e. fake) downstream builds of projects
* when their upstream .d.ts files haven't changed content (but have newer timestamps)
*/
interface BuildContext {
options: BuildOptions;
/**
* Map from output file name to its pre-build timestamp
*/
unchangedOutputs: FileMap<Date>;
/**
* Map from config file name to up-to-date status
*/
projectStatus: FileMap<UpToDateStatus>;
invalidatedProjects: FileMap<true>;
queuedProjects: FileMap<true>;
missingRoots: Map<true>;
}
type Mapper = ReturnType<typeof createDependencyMapper>;
interface DependencyGraph {
buildQueue: ResolvedConfigFileName[];
dependencyMap: Mapper;
}
interface BuildOptions {
dry: boolean;
force: boolean;
verbose: boolean;
}
enum UpToDateStatusType {
Unbuildable = 0,
UpToDate = 1,
/**
* The project appears out of date because its upstream inputs are newer than its outputs,
* but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs.
* This means we can Pseudo-build (just touch timestamps), as if we had actually built this project.
*/
UpToDateWithUpstreamTypes = 2,
OutputMissing = 3,
OutOfDateWithSelf = 4,
OutOfDateWithUpstream = 5,
UpstreamOutOfDate = 6,
UpstreamBlocked = 7,
/**
* Projects with no outputs (i.e. "solution" files)
*/
ContainerOnly = 8
}
type UpToDateStatus = Status.Unbuildable | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ContainerOnly;
namespace Status {
/**
* The project can't be built at all in its current state. For example,
* its config file cannot be parsed, or it has a syntax error or missing file
*/
interface Unbuildable {
type: UpToDateStatusType.Unbuildable;
reason: string;
}
/**
* This project doesn't have any outputs, so "is it up to date" is a meaningless question.
*/
interface ContainerOnly {
type: UpToDateStatusType.ContainerOnly;
}
/**
* The project is up to date with respect to its inputs.
* We track what the newest input file is.
*/
interface UpToDate {
type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
newestInputFileTime?: Date;
newestInputFileName?: string;
newestDeclarationFileContentChangedTime?: Date;
newestOutputFileTime?: Date;
newestOutputFileName?: string;
oldestOutputFileName?: string;
}
/**
* One or more of the outputs of the project does not exist.
*/
interface OutputMissing {
type: UpToDateStatusType.OutputMissing;
/**
* The name of the first output file that didn't exist
*/
missingOutputFileName: string;
}
/**
* One or more of the project's outputs is older than its newest input.
*/
interface OutOfDateWithSelf {
type: UpToDateStatusType.OutOfDateWithSelf;
outOfDateOutputFileName: string;
newerInputFileName: string;
}
/**
* This project depends on an out-of-date project, so shouldn't be built yet
*/
interface UpstreamOutOfDate {
type: UpToDateStatusType.UpstreamOutOfDate;
upstreamProjectName: string;
}
/**
* This project depends an upstream project with build errors
*/
interface UpstreamBlocked {
type: UpToDateStatusType.UpstreamBlocked;
upstreamProjectName: string;
}
/**
* One or more of the project's outputs is older than the newest output of
* an upstream project.
*/
interface OutOfDateWithUpstream {
type: UpToDateStatusType.OutOfDateWithUpstream;
outOfDateOutputFileName: string;
newerProjectName: string;
}
}
interface FileMap<T> {
setValue(fileName: string, value: T): void;
getValue(fileName: string): T | never;
getValueOrUndefined(fileName: string): T | undefined;
hasKey(fileName: string): boolean;
removeKey(fileName: string): void;
getKeys(): string[];
}
function createDependencyMapper(): {
addReference: (childConfigFileName: ResolvedConfigFileName, parentConfigFileName: ResolvedConfigFileName) => void;
getReferencesTo: (parentConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getReferencesOf: (childConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getKeys: () => ReadonlyArray<ResolvedConfigFileName>;
};
function createBuildContext(options: BuildOptions): BuildContext;
function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
*/
function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions, system?: System): {
buildAllProjects: () => ExitStatus;
getUpToDateStatus: (project: ParsedCommandLine | undefined) => UpToDateStatus;
getUpToDateStatusOfFile: (configFileName: ResolvedConfigFileName) => UpToDateStatus;
cleanAllProjects: () => ExitStatus.Success | ExitStatus.DiagnosticsPresent_OutputsSkipped;
resetBuildContext: (opts?: BuildOptions) => void;
getBuildGraph: (configFileNames: ReadonlyArray<string>) => DependencyGraph | undefined;
invalidateProject: (configFileName: string) => void;
buildInvalidatedProjects: () => void;
buildDependentInvalidatedProjects: () => void;
resolveProjectName: (name: string) => ResolvedConfigFileName | undefined;
startWatching: () => void;
};
/**
* Gets the UpToDateStatus for a project
*/
function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus;
function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string>;
function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined;
}
declare namespace ts.server {
type ActionSet = "action::set";
type ActionInvalidate = "action::invalidate";
type ActionPackageInstalled = "action::packageInstalled";
type ActionValueInspected = "action::valueInspected";
type EventTypesRegistry = "event::typesRegistry";
type EventBeginInstallTypes = "event::beginInstallTypes";
type EventEndInstallTypes = "event::endInstallTypes";
@@ -4609,7 +4456,7 @@ declare namespace ts.server {
" __sortedArrayBrand": any;
}
interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
interface TypingInstallerRequestWithProjectName {
readonly projectName: string;
@@ -4817,14 +4664,7 @@ declare namespace ts {
getCustomTransformers?(): CustomTransformers | undefined;
isKnownTypesPackageName?(name: string): boolean;
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
writeFile?(fileName: string, content: string): void;
}
interface LanguageService {
cleanupSemanticCache(): void;
@@ -4882,9 +4722,9 @@ declare namespace ts {
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
/** @deprecated `fileName` will be ignored */
@@ -5046,9 +4886,16 @@ declare namespace ts {
changes: ReadonlyArray<FileTextChanges>;
commands?: ReadonlyArray<CodeActionCommand>;
}
type CodeActionCommand = InstallPackageAction;
type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
interface InstallPackageAction {
}
interface GenerateTypesAction extends GenerateTypesOptions {
}
interface GenerateTypesOptions {
readonly file: string;
readonly fileToGenerateTypesFor: string;
readonly outputFileName: string;
}
/**
* A set of one or more available refactoring actions, grouped under a parent refactoring.
*/
@@ -5114,6 +4961,8 @@ declare namespace ts {
originalFileName?: string;
}
interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
@@ -5266,15 +5115,24 @@ declare namespace ts {
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
interface RenameInfo {
canRename: boolean;
localizedErrorMessage?: string;
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
@@ -5751,24 +5609,6 @@ declare namespace ts.server {
remove(path: NormalizedPath): void;
}
function createNormalizedPathMap<T>(): NormalizedPathMap<T>;
interface ProjectOptions {
configHasExtendsProperty: boolean;
/**
* true if config file explicitly listed files
*/
configHasFilesProperty: boolean;
configHasIncludeProperty: boolean;
configHasExcludeProperty: boolean;
projectReferences: ReadonlyArray<ProjectReference> | undefined;
/**
* these fields can be present in the project file
*/
files?: string[];
wildcardDirectories?: Map<WatchDirectoryFlags>;
compilerOptions?: CompilerOptions;
typeAcquisition?: TypeAcquisition;
compileOnSave?: boolean;
}
function isInferredProjectName(name: string): boolean;
function makeInferredProjectName(counter: number): string;
function createSortedArray<T>(): SortedArray<T>;
@@ -6602,15 +6442,17 @@ declare namespace ts.server.protocol {
/**
* Information about the item to be renamed.
*/
interface RenameInfo {
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
/**
* True if item can be renamed.
*/
canRename: boolean;
canRename: true;
/**
* Error message if item can not be renamed.
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
localizedErrorMessage?: string;
fileToRename?: string;
/**
* Display name of the item to be renamed.
*/
@@ -6627,6 +6469,15 @@ declare namespace ts.server.protocol {
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
/** Span of text to rename. */
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage: string;
}
/**
* A group of text spans, all in 'file'.
@@ -6635,7 +6486,11 @@ declare namespace ts.server.protocol {
/** The file to which the spans apply */
file: string;
/** The text spans in this group */
locs: TextSpan[];
locs: RenameTextSpan[];
}
interface RenameTextSpan extends TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface RenameResponseBody {
/**
@@ -7148,7 +7003,7 @@ declare namespace ts.server.protocol {
* begin with prefix.
*/
interface CompletionsRequest extends FileLocationRequest {
command: CommandTypes.Completions;
command: CommandTypes.Completions | CommandTypes.CompletionInfo;
arguments: CompletionsRequestArgs;
}
/**
@@ -7660,6 +7515,35 @@ declare namespace ts.server.protocol {
*/
openFiles: string[];
}
type ProjectLoadingStartEventName = "projectLoadingStart";
interface ProjectLoadingStartEvent extends Event {
event: ProjectLoadingStartEventName;
body: ProjectLoadingStartEventBody;
}
interface ProjectLoadingStartEventBody {
/** name of the project */
projectName: string;
/** reason for loading */
reason: string;
}
type ProjectLoadingFinishEventName = "projectLoadingFinish";
interface ProjectLoadingFinishEvent extends Event {
event: ProjectLoadingFinishEventName;
body: ProjectLoadingFinishEventBody;
}
interface ProjectLoadingFinishEventBody {
/** name of the project */
projectName: string;
}
type SurveyReadyEventName = "surveyReady";
interface SurveyReadyEvent extends Event {
event: SurveyReadyEventName;
body: SurveyReadyEventBody;
}
interface SurveyReadyEventBody {
/** Name of the survey. This is an internal machine- and programmer-friendly name */
surveyId: string;
}
type LargeFileReferencedEventName = "largeFileReferenced";
interface LargeFileReferencedEvent extends Event {
event: LargeFileReferencedEventName;
@@ -7995,6 +7879,7 @@ declare namespace ts.server.protocol {
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
}
interface CompilerOptions {
allowJs?: boolean;
@@ -8126,14 +8011,14 @@ declare namespace ts.server {
getSnapshot(): IScriptSnapshot;
private ensureRealPath;
getFormatCodeSettings(): FormatCodeSettings | undefined;
getPreferences(): UserPreferences | undefined;
getPreferences(): protocol.UserPreferences | undefined;
attachToProject(project: Project): boolean;
isAttached(project: Project): boolean;
detachFromProject(project: Project): void;
detachAllProjects(): void;
getDefaultProject(): Project;
registerFileUpdate(): void;
setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void;
setOptions(formatSettings: FormatCodeSettings, preferences: protocol.UserPreferences | undefined): void;
getLatestVersion(): string;
saveTo(fileName: string): void;
reloadFromFile(tempFileName?: NormalizedPath): boolean;
@@ -8238,6 +8123,7 @@ declare namespace ts.server {
* This property is different from projectStructureVersion since in most cases edits don't affect set of files in the project
*/
private projectStateVersion;
protected isInitialLoadPending: () => boolean;
private readonly cancellationToken;
isNonTsProject(): boolean;
isJsOnlyProject(): boolean;
@@ -8261,6 +8147,7 @@ declare namespace ts.server {
useCaseSensitiveFileNames(): boolean;
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
readFile(fileName: string): string | undefined;
writeFile(fileName: string, content: string): void;
fileExists(file: string): boolean;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[];
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
@@ -8322,7 +8209,7 @@ declare namespace ts.server {
filesToString(writeProjectFileNames: boolean): string;
setCompilerOptions(compilerOptions: CompilerOptions): void;
protected removeRoot(info: ScriptInfo): void;
protected enableGlobalPlugins(): void;
protected enableGlobalPlugins(options: CompilerOptions): void;
protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]): void;
/** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */
refreshDiagnostics(): void;
@@ -8351,14 +8238,14 @@ declare namespace ts.server {
* Otherwise it will create an InferredProject.
*/
class ConfiguredProject extends Project {
compileOnSaveEnabled: boolean;
private projectReferences;
private typeAcquisition;
private directoriesWatchedForWildcards;
readonly canonicalConfigFilePath: NormalizedPath;
/** Ref count to the project when opened from external project */
private externalProjectRefCount;
private projectErrors;
private projectReferences;
protected isInitialLoadPending: () => boolean;
/**
* If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph
* @returns: true if set of files in the project stays the same and false - otherwise.
@@ -8391,6 +8278,7 @@ declare namespace ts.server {
compileOnSaveEnabled: boolean;
excludedFiles: ReadonlyArray<NormalizedPath>;
private typeAcquisition;
updateGraph(): boolean;
getExcludedFiles(): ReadonlyArray<NormalizedPath>;
getTypeAcquisition(): TypeAcquisition;
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void;
@@ -8399,6 +8287,9 @@ declare namespace ts.server {
declare namespace ts.server {
const maxProgramSizeForNonTsFiles: number;
const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
const ProjectLoadingStartEvent = "projectLoadingStart";
const ProjectLoadingFinishEvent = "projectLoadingFinish";
const SurveyReady = "surveyReady";
const LargeFileReferencedEvent = "largeFileReferenced";
const ConfigFileDiagEvent = "configFileDiag";
const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
@@ -8410,6 +8301,25 @@ declare namespace ts.server {
openFiles: string[];
};
}
interface ProjectLoadingStartEvent {
eventName: typeof ProjectLoadingStartEvent;
data: {
project: Project;
reason: string;
};
}
interface ProjectLoadingFinishEvent {
eventName: typeof ProjectLoadingFinishEvent;
data: {
project: Project;
};
}
interface SurveyReady {
eventName: typeof SurveyReady;
data: {
surveyId: string;
};
}
interface LargeFileReferencedEvent {
eventName: typeof LargeFileReferencedEvent;
data: {
@@ -8488,7 +8398,7 @@ declare namespace ts.server {
interface OpenFileInfo {
readonly checkJs: boolean;
}
type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ProjectLoadingStartEvent | ProjectLoadingFinishEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
interface SafeList {
[name: string]: {
@@ -8509,7 +8419,7 @@ declare namespace ts.server {
function convertScriptKindName(scriptKindName: protocol.ScriptKindName): ScriptKind.Unknown | ScriptKind.JS | ScriptKind.JSX | ScriptKind.TS | ScriptKind.TSX;
interface HostConfiguration {
formatCodeOptions: FormatCodeSettings;
preferences: UserPreferences;
preferences: protocol.UserPreferences;
hostInfo: string;
extraFileExtensions?: FileExtensionInfo[];
}
@@ -8538,6 +8448,7 @@ declare namespace ts.server {
* Container of all known scripts
*/
private readonly filenameToScriptInfo;
private readonly scriptInfoInNodeModulesWatchers;
/**
* Contains all the deleted script info's version information so that
* it does not reset when creating script info again
@@ -8586,7 +8497,7 @@ declare namespace ts.server {
private readonly throttledOperations;
private readonly hostConfiguration;
private safelist;
private legacySafelist;
private readonly legacySafelist;
private pendingProjectUpdates;
readonly currentDirectory: NormalizedPath;
readonly toCanonicalFileName: (f: string) => string;
@@ -8607,6 +8518,8 @@ declare namespace ts.server {
readonly syntaxOnly?: boolean;
/** Tracks projects that we have already sent telemetry for. */
private readonly seenProjects;
/** Tracks projects that we have already sent survey events for. */
private readonly seenSurveyProjects;
constructor(opts: ProjectServiceOptions);
toPath(fileName: string): Path;
private loadTypesMap;
@@ -8628,9 +8541,9 @@ declare namespace ts.server {
*/
private ensureProjectStructuresUptoDate;
getFormatCodeOptions(file: NormalizedPath): FormatCodeSettings;
getPreferences(file: NormalizedPath): UserPreferences;
getPreferences(file: NormalizedPath): protocol.UserPreferences;
getHostFormatCodeOptions(): FormatCodeSettings;
getHostPreferences(): UserPreferences;
getHostPreferences(): protocol.UserPreferences;
private onSourceFileChanged;
private handleDeletedFile;
private onConfigChangedForConfiguredProject;
@@ -8692,15 +8605,13 @@ declare namespace ts.server {
private findConfiguredProjectByProjectName;
private getConfiguredProjectByCanonicalConfigFilePath;
private findExternalProjectByProjectName;
private convertConfigFileContentToProjectOptions;
/** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */
private getFilenameForExceededTotalSizeLimitForNonTsFiles;
private createExternalProject;
private sendProjectTelemetry;
private addFilesToNonInferredProjectAndUpdateGraph;
private addFilesToNonInferredProject;
private createConfiguredProject;
private updateNonInferredProjectFiles;
private updateNonInferredProject;
private updateRootAndOptionsOfNonInferredProject;
private sendConfigFileDiagEvent;
private getOrCreateInferredProjectForProjectRootPathIfEnabled;
private getOrCreateSingleInferredProjectIfEnabled;
@@ -8708,6 +8619,10 @@ declare namespace ts.server {
private createInferredProject;
getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined;
private watchClosedScriptInfo;
private watchClosedScriptInfoInNodeModules;
private getModifiedTime;
private refreshScriptInfo;
private refreshScriptInfosInDirectory;
private stopWatchingScriptInfo;
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath;
private getOrCreateScriptInfoOpenedByClientForNormalizedPath;
@@ -8815,6 +8730,7 @@ declare namespace ts.server {
globalPlugins?: ReadonlyArray<string>;
pluginProbeLocations?: ReadonlyArray<string>;
allowLocalPluginLoads?: boolean;
typesMapLocation?: string;
}
class Session implements EventSender {
private readonly gcTimer;
@@ -8837,6 +8753,7 @@ declare namespace ts.server {
private defaultEventHandler;
private projectsUpdatedInBackgroundEvent;
logError(err: Error, cmd: string): void;
private logErrorWorker;
send(msg: protocol.Message): void;
event<T extends object>(body: T, eventName: string): void;
/** @deprecated */
@@ -8881,7 +8798,7 @@ declare namespace ts.server {
private getProjects;
private getDefaultProject;
private getRenameLocations;
private static mapRenameInfo;
private mapRenameInfo;
private toSpanGroups;
private getReferences;
/**
+7655 -4622
View File
File diff suppressed because it is too large Load Diff
+99 -241
View File
@@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.1";
const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
const version: string;
}
@@ -69,7 +69,8 @@ declare namespace ts {
pos: number;
end: number;
}
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown;
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown | KeywordSyntaxKind;
type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
enum SyntaxKind {
Unknown = 0,
@@ -536,6 +537,7 @@ declare namespace ts {
name?: Identifier | StringLiteral | NumericLiteral;
}
interface ComputedPropertyName extends Node {
parent: Declaration;
kind: SyntaxKind.ComputedPropertyName;
expression: Expression;
}
@@ -632,6 +634,7 @@ declare namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
@@ -668,6 +671,7 @@ declare namespace ts {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction;
@@ -1079,7 +1083,7 @@ declare namespace ts {
}
interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
interface NewExpression extends PrimaryExpression, Declaration {
@@ -1808,7 +1812,8 @@ declare namespace ts {
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
isSourceFileDefaultLibrary(file: SourceFile): boolean;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
@@ -2056,32 +2061,32 @@ declare namespace ts {
ExportStar = 8388608,
Optional = 16777216,
Transient = 33554432,
JSContainer = 67108864,
Assignment = 67108864,
ModuleExports = 134217728,
Enum = 384,
Variable = 3,
Value = 67216319,
Type = 67901928,
Value = 67220415,
Type = 67897832,
Namespace = 1920,
Module = 1536,
Accessor = 98304,
FunctionScopedVariableExcludes = 67216318,
BlockScopedVariableExcludes = 67216319,
ParameterExcludes = 67216319,
FunctionScopedVariableExcludes = 67220414,
BlockScopedVariableExcludes = 67220415,
ParameterExcludes = 67220415,
PropertyExcludes = 0,
EnumMemberExcludes = 68008959,
FunctionExcludes = 67215791,
FunctionExcludes = 67219887,
ClassExcludes = 68008383,
InterfaceExcludes = 67901832,
InterfaceExcludes = 67897736,
RegularEnumExcludes = 68008191,
ConstEnumExcludes = 68008831,
ValueModuleExcludes = 67215503,
ValueModuleExcludes = 110735,
NamespaceModuleExcludes = 0,
MethodExcludes = 67208127,
GetAccessorExcludes = 67150783,
SetAccessorExcludes = 67183551,
TypeParameterExcludes = 67639784,
TypeAliasExcludes = 67901928,
MethodExcludes = 67212223,
GetAccessorExcludes = 67154879,
SetAccessorExcludes = 67187647,
TypeParameterExcludes = 67635688,
TypeAliasExcludes = 67897832,
AliasExcludes = 2097152,
ModuleMember = 2623475,
ExportHasLocal = 944,
@@ -2490,6 +2495,7 @@ declare namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
@@ -2581,7 +2587,6 @@ declare namespace ts {
}
interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
interface CreateProgramOptions {
@@ -2592,14 +2597,6 @@ declare namespace ts {
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
interface UpToDateHost {
fileExists(fileName: string): boolean;
getModifiedTime(fileName: string): Date | undefined;
getUnchangedTime?(fileName: string): Date | undefined;
getLastStatus?(fileName: string): UpToDateStatus | undefined;
setLastStatus?(fileName: string, status: UpToDateStatus): void;
parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined;
}
interface ModuleResolutionHost {
fileExists(fileName: string): boolean;
readFile(fileName: string): string | undefined;
@@ -2698,9 +2695,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
getModifiedTime?(fileName: string): Date | undefined;
setModifiedTime?(fileName: string, date: Date): void;
deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -3001,6 +2995,16 @@ declare namespace ts {
Parameters = 1296,
IndexSignatureParameters = 4432
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
}
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -3209,17 +3213,27 @@ declare namespace ts {
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* @remarks Returns any JSDoc param tag whose name matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
* For binding patterns, parameter tags are matched by position.
*/
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag>;
/**
* Gets the JSDoc type parameter tags for the node if present.
*
* @remarks Returns any JSDoc template tag whose names match the provided
* parameter, whether a template tag on a containing function
* expression, or a template tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the template
* tag on the containing function expression would be first.
*/
function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray<JSDocTemplateTag>;
/**
* Return true if the node has JSDoc parameter tags.
*
@@ -4171,14 +4185,15 @@ declare namespace ts {
* @returns A 'Program' object.
*/
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
interface ResolveProjectReferencePathHost {
/** @deprecated */ interface ResolveProjectReferencePathHost {
fileExists(fileName: string): boolean;
}
/**
* Returns the target config filename of a project reference.
* Note: The file might not exist.
*/
function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName;
/** @deprecated */ function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
}
declare namespace ts {
interface EmitOutput {
@@ -4303,32 +4318,43 @@ declare namespace ts {
* Create the builder to manage semantic diagnostics and cache them
*/
function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): SemanticDiagnosticsBuilderProgram;
/**
* Create the builder that can handle the changes in program and iterate through changed files
* to emit the those files and manage semantic diagnostics cache as well
*/
function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): EmitAndSemanticDiagnosticsBuilderProgram;
/**
* Creates a builder thats just abstraction over program and can be used with watch
*/
function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): BuilderProgram;
}
declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
interface WatchCompilerHost<T extends BuilderProgram> {
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference> | undefined) => T;
/** Host that has watch functionality used in --watch mode */
interface WatchHost {
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram<T>;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4361,14 +4387,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
@@ -4378,6 +4396,8 @@ declare namespace ts {
rootFiles: string[];
/** Compiler options */
options: CompilerOptions;
/** Project References */
projectReferences?: ReadonlyArray<ProjectReference>;
}
/**
* Host to create watch with config file
@@ -4412,8 +4432,8 @@ declare namespace ts {
/**
* Create the watch compiler host for either configFile or fileNames and its options
*/
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions<T>;
function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray<ProjectReference>): WatchCompilerHostOfFilesAndCompilerOptions<T>;
/**
* Creates the watch from the host for root files and compiler options
*/
@@ -4423,184 +4443,11 @@ declare namespace ts {
*/
function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
}
declare namespace ts {
interface BuildHost {
verbose(diag: DiagnosticMessage, ...args: string[]): void;
error(diag: DiagnosticMessage, ...args: string[]): void;
errorDiagnostic(diag: Diagnostic): void;
message(diag: DiagnosticMessage, ...args: string[]): void;
}
/**
* A BuildContext tracks what's going on during the course of a build.
*
* Callers may invoke any number of build requests within the same context;
* until the context is reset, each project will only be built at most once.
*
* Example: In a standard setup where project B depends on project A, and both are out of date,
* a failed build of A will result in A remaining out of date. When we try to build
* B, we should immediately bail instead of recomputing A's up-to-date status again.
*
* This also matters for performing fast (i.e. fake) downstream builds of projects
* when their upstream .d.ts files haven't changed content (but have newer timestamps)
*/
interface BuildContext {
options: BuildOptions;
/**
* Map from output file name to its pre-build timestamp
*/
unchangedOutputs: FileMap<Date>;
/**
* Map from config file name to up-to-date status
*/
projectStatus: FileMap<UpToDateStatus>;
invalidatedProjects: FileMap<true>;
queuedProjects: FileMap<true>;
missingRoots: Map<true>;
}
type Mapper = ReturnType<typeof createDependencyMapper>;
interface DependencyGraph {
buildQueue: ResolvedConfigFileName[];
dependencyMap: Mapper;
}
interface BuildOptions {
dry: boolean;
force: boolean;
verbose: boolean;
}
enum UpToDateStatusType {
Unbuildable = 0,
UpToDate = 1,
/**
* The project appears out of date because its upstream inputs are newer than its outputs,
* but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs.
* This means we can Pseudo-build (just touch timestamps), as if we had actually built this project.
*/
UpToDateWithUpstreamTypes = 2,
OutputMissing = 3,
OutOfDateWithSelf = 4,
OutOfDateWithUpstream = 5,
UpstreamOutOfDate = 6,
UpstreamBlocked = 7,
/**
* Projects with no outputs (i.e. "solution" files)
*/
ContainerOnly = 8
}
type UpToDateStatus = Status.Unbuildable | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ContainerOnly;
namespace Status {
/**
* The project can't be built at all in its current state. For example,
* its config file cannot be parsed, or it has a syntax error or missing file
*/
interface Unbuildable {
type: UpToDateStatusType.Unbuildable;
reason: string;
}
/**
* This project doesn't have any outputs, so "is it up to date" is a meaningless question.
*/
interface ContainerOnly {
type: UpToDateStatusType.ContainerOnly;
}
/**
* The project is up to date with respect to its inputs.
* We track what the newest input file is.
*/
interface UpToDate {
type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
newestInputFileTime?: Date;
newestInputFileName?: string;
newestDeclarationFileContentChangedTime?: Date;
newestOutputFileTime?: Date;
newestOutputFileName?: string;
oldestOutputFileName?: string;
}
/**
* One or more of the outputs of the project does not exist.
*/
interface OutputMissing {
type: UpToDateStatusType.OutputMissing;
/**
* The name of the first output file that didn't exist
*/
missingOutputFileName: string;
}
/**
* One or more of the project's outputs is older than its newest input.
*/
interface OutOfDateWithSelf {
type: UpToDateStatusType.OutOfDateWithSelf;
outOfDateOutputFileName: string;
newerInputFileName: string;
}
/**
* This project depends on an out-of-date project, so shouldn't be built yet
*/
interface UpstreamOutOfDate {
type: UpToDateStatusType.UpstreamOutOfDate;
upstreamProjectName: string;
}
/**
* This project depends an upstream project with build errors
*/
interface UpstreamBlocked {
type: UpToDateStatusType.UpstreamBlocked;
upstreamProjectName: string;
}
/**
* One or more of the project's outputs is older than the newest output of
* an upstream project.
*/
interface OutOfDateWithUpstream {
type: UpToDateStatusType.OutOfDateWithUpstream;
outOfDateOutputFileName: string;
newerProjectName: string;
}
}
interface FileMap<T> {
setValue(fileName: string, value: T): void;
getValue(fileName: string): T | never;
getValueOrUndefined(fileName: string): T | undefined;
hasKey(fileName: string): boolean;
removeKey(fileName: string): void;
getKeys(): string[];
}
function createDependencyMapper(): {
addReference: (childConfigFileName: ResolvedConfigFileName, parentConfigFileName: ResolvedConfigFileName) => void;
getReferencesTo: (parentConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getReferencesOf: (childConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getKeys: () => ReadonlyArray<ResolvedConfigFileName>;
};
function createBuildContext(options: BuildOptions): BuildContext;
function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
*/
function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions, system?: System): {
buildAllProjects: () => ExitStatus;
getUpToDateStatus: (project: ParsedCommandLine | undefined) => UpToDateStatus;
getUpToDateStatusOfFile: (configFileName: ResolvedConfigFileName) => UpToDateStatus;
cleanAllProjects: () => ExitStatus.Success | ExitStatus.DiagnosticsPresent_OutputsSkipped;
resetBuildContext: (opts?: BuildOptions) => void;
getBuildGraph: (configFileNames: ReadonlyArray<string>) => DependencyGraph | undefined;
invalidateProject: (configFileName: string) => void;
buildInvalidatedProjects: () => void;
buildDependentInvalidatedProjects: () => void;
resolveProjectName: (name: string) => ResolvedConfigFileName | undefined;
startWatching: () => void;
};
/**
* Gets the UpToDateStatus for a project
*/
function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus;
function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string>;
function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined;
}
declare namespace ts.server {
type ActionSet = "action::set";
type ActionInvalidate = "action::invalidate";
type ActionPackageInstalled = "action::packageInstalled";
type ActionValueInspected = "action::valueInspected";
type EventTypesRegistry = "event::typesRegistry";
type EventBeginInstallTypes = "event::beginInstallTypes";
type EventEndInstallTypes = "event::endInstallTypes";
@@ -4609,7 +4456,7 @@ declare namespace ts.server {
" __sortedArrayBrand": any;
}
interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
interface TypingInstallerRequestWithProjectName {
readonly projectName: string;
@@ -4817,14 +4664,7 @@ declare namespace ts {
getCustomTransformers?(): CustomTransformers | undefined;
isKnownTypesPackageName?(name: string): boolean;
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
writeFile?(fileName: string, content: string): void;
}
interface LanguageService {
cleanupSemanticCache(): void;
@@ -4882,9 +4722,9 @@ declare namespace ts {
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
/** @deprecated `fileName` will be ignored */
@@ -5046,9 +4886,16 @@ declare namespace ts {
changes: ReadonlyArray<FileTextChanges>;
commands?: ReadonlyArray<CodeActionCommand>;
}
type CodeActionCommand = InstallPackageAction;
type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
interface InstallPackageAction {
}
interface GenerateTypesAction extends GenerateTypesOptions {
}
interface GenerateTypesOptions {
readonly file: string;
readonly fileToGenerateTypesFor: string;
readonly outputFileName: string;
}
/**
* A set of one or more available refactoring actions, grouped under a parent refactoring.
*/
@@ -5114,6 +4961,8 @@ declare namespace ts {
originalFileName?: string;
}
interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
@@ -5266,15 +5115,24 @@ declare namespace ts {
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
interface RenameInfo {
canRename: boolean;
localizedErrorMessage?: string;
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
+7225 -4442
View File
File diff suppressed because it is too large Load Diff
+99 -241
View File
@@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.1";
const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
const version: string;
}
@@ -69,7 +69,8 @@ declare namespace ts {
pos: number;
end: number;
}
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown;
type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.NoSubstitutionTemplateLiteral | SyntaxKind.Unknown | KeywordSyntaxKind;
type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
enum SyntaxKind {
Unknown = 0,
@@ -536,6 +537,7 @@ declare namespace ts {
name?: Identifier | StringLiteral | NumericLiteral;
}
interface ComputedPropertyName extends Node {
parent: Declaration;
kind: SyntaxKind.ComputedPropertyName;
expression: Expression;
}
@@ -632,6 +634,7 @@ declare namespace ts {
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
equalsToken?: Token<SyntaxKind.EqualsToken>;
objectAssignmentInitializer?: Expression;
}
@@ -668,6 +671,7 @@ declare namespace ts {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
}
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction;
@@ -1079,7 +1083,7 @@ declare namespace ts {
}
interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
interface NewExpression extends PrimaryExpression, Declaration {
@@ -1808,7 +1812,8 @@ declare namespace ts {
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
isSourceFileDefaultLibrary(file: SourceFile): boolean;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
@@ -2056,32 +2061,32 @@ declare namespace ts {
ExportStar = 8388608,
Optional = 16777216,
Transient = 33554432,
JSContainer = 67108864,
Assignment = 67108864,
ModuleExports = 134217728,
Enum = 384,
Variable = 3,
Value = 67216319,
Type = 67901928,
Value = 67220415,
Type = 67897832,
Namespace = 1920,
Module = 1536,
Accessor = 98304,
FunctionScopedVariableExcludes = 67216318,
BlockScopedVariableExcludes = 67216319,
ParameterExcludes = 67216319,
FunctionScopedVariableExcludes = 67220414,
BlockScopedVariableExcludes = 67220415,
ParameterExcludes = 67220415,
PropertyExcludes = 0,
EnumMemberExcludes = 68008959,
FunctionExcludes = 67215791,
FunctionExcludes = 67219887,
ClassExcludes = 68008383,
InterfaceExcludes = 67901832,
InterfaceExcludes = 67897736,
RegularEnumExcludes = 68008191,
ConstEnumExcludes = 68008831,
ValueModuleExcludes = 67215503,
ValueModuleExcludes = 110735,
NamespaceModuleExcludes = 0,
MethodExcludes = 67208127,
GetAccessorExcludes = 67150783,
SetAccessorExcludes = 67183551,
TypeParameterExcludes = 67639784,
TypeAliasExcludes = 67901928,
MethodExcludes = 67212223,
GetAccessorExcludes = 67154879,
SetAccessorExcludes = 67187647,
TypeParameterExcludes = 67635688,
TypeAliasExcludes = 67897832,
AliasExcludes = 2097152,
ModuleMember = 2623475,
ExportHasLocal = 944,
@@ -2490,6 +2495,7 @@ declare namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean;
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
stripInternal?: boolean;
@@ -2581,7 +2587,6 @@ declare namespace ts {
}
interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
interface CreateProgramOptions {
@@ -2592,14 +2597,6 @@ declare namespace ts {
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
interface UpToDateHost {
fileExists(fileName: string): boolean;
getModifiedTime(fileName: string): Date | undefined;
getUnchangedTime?(fileName: string): Date | undefined;
getLastStatus?(fileName: string): UpToDateStatus | undefined;
setLastStatus?(fileName: string, status: UpToDateStatus): void;
parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined;
}
interface ModuleResolutionHost {
fileExists(fileName: string): boolean;
readFile(fileName: string): string | undefined;
@@ -2698,9 +2695,6 @@ declare namespace ts {
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
getEnvironmentVariable?(name: string): string | undefined;
createHash?(data: string): string;
getModifiedTime?(fileName: string): Date | undefined;
setModifiedTime?(fileName: string, date: Date): void;
deleteFile?(fileName: string): void;
}
interface SourceMapRange extends TextRange {
source?: SourceMapSource;
@@ -3001,6 +2995,16 @@ declare namespace ts {
Parameters = 1296,
IndexSignatureParameters = 4432
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
}
}
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -3209,17 +3213,27 @@ declare namespace ts {
/**
* Gets the JSDoc parameter tags for the node if present.
*
* @remarks Returns any JSDoc param tag that matches the provided
* @remarks Returns any JSDoc param tag whose name matches the provided
* parameter, whether a param tag on a containing function
* expression, or a param tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the param
* tag on the containing function expression would be first.
*
* Does not return tags for binding patterns, because JSDoc matches
* parameters by name and binding patterns do not have a name.
* For binding patterns, parameter tags are matched by position.
*/
function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag>;
/**
* Gets the JSDoc type parameter tags for the node if present.
*
* @remarks Returns any JSDoc template tag whose names match the provided
* parameter, whether a template tag on a containing function
* expression, or a template tag on a variable declaration whose
* initializer is the containing function. The tags closest to the
* node are returned first, so in the previous example, the template
* tag on the containing function expression would be first.
*/
function getJSDocTypeParameterTags(param: TypeParameterDeclaration): ReadonlyArray<JSDocTemplateTag>;
/**
* Return true if the node has JSDoc parameter tags.
*
@@ -4171,14 +4185,15 @@ declare namespace ts {
* @returns A 'Program' object.
*/
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
interface ResolveProjectReferencePathHost {
/** @deprecated */ interface ResolveProjectReferencePathHost {
fileExists(fileName: string): boolean;
}
/**
* Returns the target config filename of a project reference.
* Note: The file might not exist.
*/
function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName;
/** @deprecated */ function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
}
declare namespace ts {
interface EmitOutput {
@@ -4303,32 +4318,43 @@ declare namespace ts {
* Create the builder to manage semantic diagnostics and cache them
*/
function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): SemanticDiagnosticsBuilderProgram;
function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): SemanticDiagnosticsBuilderProgram;
/**
* Create the builder that can handle the changes in program and iterate through changed files
* to emit the those files and manage semantic diagnostics cache as well
*/
function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): EmitAndSemanticDiagnosticsBuilderProgram;
function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): EmitAndSemanticDiagnosticsBuilderProgram;
/**
* Creates a builder thats just abstraction over program and can be used with watch
*/
function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): BuilderProgram;
}
declare namespace ts {
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
interface WatchCompilerHost<T extends BuilderProgram> {
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference> | undefined) => T;
/** Host that has watch functionality used in --watch mode */
interface WatchHost {
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
/**
* Used to create the program when need for program creation or recreation detected
*/
createProgram: CreateProgram<T>;
/** If provided, callback to invoke after every new program creation */
afterProgramCreate?(program: T): void;
/** If provided, called with Diagnostic message that informs about change in watch status */
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
getCurrentDirectory(): string;
@@ -4361,14 +4387,6 @@ declare namespace ts {
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
/** If provided, will be used to reset existing delayed compilation */
clearTimeout?(timeoutId: any): void;
}
/**
* Host to create watch with root files and options
@@ -4378,6 +4396,8 @@ declare namespace ts {
rootFiles: string[];
/** Compiler options */
options: CompilerOptions;
/** Project References */
projectReferences?: ReadonlyArray<ProjectReference>;
}
/**
* Host to create watch with config file
@@ -4412,8 +4432,8 @@ declare namespace ts {
/**
* Create the watch compiler host for either configFile or fileNames and its options
*/
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions<T>;
function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray<ProjectReference>): WatchCompilerHostOfFilesAndCompilerOptions<T>;
/**
* Creates the watch from the host for root files and compiler options
*/
@@ -4423,184 +4443,11 @@ declare namespace ts {
*/
function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
}
declare namespace ts {
interface BuildHost {
verbose(diag: DiagnosticMessage, ...args: string[]): void;
error(diag: DiagnosticMessage, ...args: string[]): void;
errorDiagnostic(diag: Diagnostic): void;
message(diag: DiagnosticMessage, ...args: string[]): void;
}
/**
* A BuildContext tracks what's going on during the course of a build.
*
* Callers may invoke any number of build requests within the same context;
* until the context is reset, each project will only be built at most once.
*
* Example: In a standard setup where project B depends on project A, and both are out of date,
* a failed build of A will result in A remaining out of date. When we try to build
* B, we should immediately bail instead of recomputing A's up-to-date status again.
*
* This also matters for performing fast (i.e. fake) downstream builds of projects
* when their upstream .d.ts files haven't changed content (but have newer timestamps)
*/
interface BuildContext {
options: BuildOptions;
/**
* Map from output file name to its pre-build timestamp
*/
unchangedOutputs: FileMap<Date>;
/**
* Map from config file name to up-to-date status
*/
projectStatus: FileMap<UpToDateStatus>;
invalidatedProjects: FileMap<true>;
queuedProjects: FileMap<true>;
missingRoots: Map<true>;
}
type Mapper = ReturnType<typeof createDependencyMapper>;
interface DependencyGraph {
buildQueue: ResolvedConfigFileName[];
dependencyMap: Mapper;
}
interface BuildOptions {
dry: boolean;
force: boolean;
verbose: boolean;
}
enum UpToDateStatusType {
Unbuildable = 0,
UpToDate = 1,
/**
* The project appears out of date because its upstream inputs are newer than its outputs,
* but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs.
* This means we can Pseudo-build (just touch timestamps), as if we had actually built this project.
*/
UpToDateWithUpstreamTypes = 2,
OutputMissing = 3,
OutOfDateWithSelf = 4,
OutOfDateWithUpstream = 5,
UpstreamOutOfDate = 6,
UpstreamBlocked = 7,
/**
* Projects with no outputs (i.e. "solution" files)
*/
ContainerOnly = 8
}
type UpToDateStatus = Status.Unbuildable | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ContainerOnly;
namespace Status {
/**
* The project can't be built at all in its current state. For example,
* its config file cannot be parsed, or it has a syntax error or missing file
*/
interface Unbuildable {
type: UpToDateStatusType.Unbuildable;
reason: string;
}
/**
* This project doesn't have any outputs, so "is it up to date" is a meaningless question.
*/
interface ContainerOnly {
type: UpToDateStatusType.ContainerOnly;
}
/**
* The project is up to date with respect to its inputs.
* We track what the newest input file is.
*/
interface UpToDate {
type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes;
newestInputFileTime?: Date;
newestInputFileName?: string;
newestDeclarationFileContentChangedTime?: Date;
newestOutputFileTime?: Date;
newestOutputFileName?: string;
oldestOutputFileName?: string;
}
/**
* One or more of the outputs of the project does not exist.
*/
interface OutputMissing {
type: UpToDateStatusType.OutputMissing;
/**
* The name of the first output file that didn't exist
*/
missingOutputFileName: string;
}
/**
* One or more of the project's outputs is older than its newest input.
*/
interface OutOfDateWithSelf {
type: UpToDateStatusType.OutOfDateWithSelf;
outOfDateOutputFileName: string;
newerInputFileName: string;
}
/**
* This project depends on an out-of-date project, so shouldn't be built yet
*/
interface UpstreamOutOfDate {
type: UpToDateStatusType.UpstreamOutOfDate;
upstreamProjectName: string;
}
/**
* This project depends an upstream project with build errors
*/
interface UpstreamBlocked {
type: UpToDateStatusType.UpstreamBlocked;
upstreamProjectName: string;
}
/**
* One or more of the project's outputs is older than the newest output of
* an upstream project.
*/
interface OutOfDateWithUpstream {
type: UpToDateStatusType.OutOfDateWithUpstream;
outOfDateOutputFileName: string;
newerProjectName: string;
}
}
interface FileMap<T> {
setValue(fileName: string, value: T): void;
getValue(fileName: string): T | never;
getValueOrUndefined(fileName: string): T | undefined;
hasKey(fileName: string): boolean;
removeKey(fileName: string): void;
getKeys(): string[];
}
function createDependencyMapper(): {
addReference: (childConfigFileName: ResolvedConfigFileName, parentConfigFileName: ResolvedConfigFileName) => void;
getReferencesTo: (parentConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getReferencesOf: (childConfigFileName: ResolvedConfigFileName) => ResolvedConfigFileName[];
getKeys: () => ReadonlyArray<ResolvedConfigFileName>;
};
function createBuildContext(options: BuildOptions): BuildContext;
function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined;
/**
* A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but
* can dynamically add/remove other projects based on changes on the rootNames' references
*/
function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions, system?: System): {
buildAllProjects: () => ExitStatus;
getUpToDateStatus: (project: ParsedCommandLine | undefined) => UpToDateStatus;
getUpToDateStatusOfFile: (configFileName: ResolvedConfigFileName) => UpToDateStatus;
cleanAllProjects: () => ExitStatus.Success | ExitStatus.DiagnosticsPresent_OutputsSkipped;
resetBuildContext: (opts?: BuildOptions) => void;
getBuildGraph: (configFileNames: ReadonlyArray<string>) => DependencyGraph | undefined;
invalidateProject: (configFileName: string) => void;
buildInvalidatedProjects: () => void;
buildDependentInvalidatedProjects: () => void;
resolveProjectName: (name: string) => ResolvedConfigFileName | undefined;
startWatching: () => void;
};
/**
* Gets the UpToDateStatus for a project
*/
function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus;
function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string>;
function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined;
}
declare namespace ts.server {
type ActionSet = "action::set";
type ActionInvalidate = "action::invalidate";
type ActionPackageInstalled = "action::packageInstalled";
type ActionValueInspected = "action::valueInspected";
type EventTypesRegistry = "event::typesRegistry";
type EventBeginInstallTypes = "event::beginInstallTypes";
type EventEndInstallTypes = "event::endInstallTypes";
@@ -4609,7 +4456,7 @@ declare namespace ts.server {
" __sortedArrayBrand": any;
}
interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
interface TypingInstallerRequestWithProjectName {
readonly projectName: string;
@@ -4817,14 +4664,7 @@ declare namespace ts {
getCustomTransformers?(): CustomTransformers | undefined;
isKnownTypesPackageName?(name: string): boolean;
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
writeFile?(fileName: string, content: string): void;
}
interface LanguageService {
cleanupSemanticCache(): void;
@@ -4882,9 +4722,9 @@ declare namespace ts {
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
/** @deprecated `fileName` will be ignored */
applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
/** @deprecated `fileName` will be ignored */
@@ -5046,9 +4886,16 @@ declare namespace ts {
changes: ReadonlyArray<FileTextChanges>;
commands?: ReadonlyArray<CodeActionCommand>;
}
type CodeActionCommand = InstallPackageAction;
type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
interface InstallPackageAction {
}
interface GenerateTypesAction extends GenerateTypesOptions {
}
interface GenerateTypesOptions {
readonly file: string;
readonly fileToGenerateTypesFor: string;
readonly outputFileName: string;
}
/**
* A set of one or more available refactoring actions, grouped under a parent refactoring.
*/
@@ -5114,6 +4961,8 @@ declare namespace ts {
originalFileName?: string;
}
interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
interface ReferenceEntry extends DocumentSpan {
isWriteAccess: boolean;
@@ -5266,15 +5115,24 @@ declare namespace ts {
documentation?: SymbolDisplayPart[];
tags?: JSDocTagInfo[];
}
interface RenameInfo {
canRename: boolean;
localizedErrorMessage?: string;
type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
+7225 -4442
View File
File diff suppressed because it is too large Load Diff
+5814 -3853
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -68,7 +68,7 @@
"A_rest_parameter_cannot_have_an_initializer_1048": "rest 参数不能具有初始化表达式。",
"A_rest_parameter_must_be_last_in_a_parameter_list_1014": "rest 参数必须是参数列表中的最后一个参数。",
"A_rest_parameter_must_be_of_an_array_type_2370": "rest 参数必须是数组类型。",
"A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma_1013": "Rest 参数或绑定模式可能不具有尾随逗号。",
"A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma_1013": "Rest 参数或绑定模式不可带尾随逗号。",
"A_return_statement_can_only_be_used_within_a_function_body_1108": "\"return\" 语句只能在函数体中使用。",
"A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl_6167": "一系列条目,这些条目将重新映射导入内容,以查找与 \"baseUrl\" 有关的位置。",
"A_set_accessor_cannot_have_a_return_type_annotation_1095": "\"set\" 访问器不能具有返回类型批注。",
@@ -161,7 +161,7 @@
"An_index_signature_parameter_cannot_have_an_accessibility_modifier_1018": "索引签名参数不能具有可访问性修饰符。",
"An_index_signature_parameter_cannot_have_an_initializer_1020": "索引签名参数不能具有初始化表达式。",
"An_index_signature_parameter_must_have_a_type_annotation_1022": "索引签名参数必须具有类型批注。",
"An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead_1336": "索引签名参数类型不能为类型别名。请考虑改编写“[{0}: {1}]:{2}”。",
"An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead_1336": "索引签名参数类型不能为类型别名。请考虑改编写“[{0}: {1}]:{2}”。",
"An_index_signature_parameter_type_cannot_be_a_union_type_Consider_using_a_mapped_object_type_instead_1337": "索引签名参数类型不能为联合类型。请考虑改用映射的对象类型。",
"An_index_signature_parameter_type_must_be_string_or_number_1023": "索引签名参数类型必须为 \"string\" 或 \"number\"。",
"An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments_2499": "接口只能扩展具有可选类型参数的标识符/限定名称。",
@@ -628,7 +628,7 @@
"Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES_5047": "选项 \"isolatedModules\" 只可在提供了选项 \"--module\" 或者选项 \"target\" 是 \"ES2015\" 或更高版本时使用。",
"Option_paths_cannot_be_used_without_specifying_baseUrl_option_5060": "在未指定 \"--baseUrl\" 选项的情况下,无法使用选项 \"paths\"。",
"Option_project_cannot_be_mixed_with_source_files_on_a_command_line_5042": "选项 \"project\" 在命令行上不能与源文件混合使用。",
"Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070": "没有 \"node\" 模块解析策略的情况下,无法指定选项 \"-resolveJsonModule\"。",
"Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy_5070": "没有 \"node\" 模块解析策略的情况下,无法指定选项 \"-resolveJsonModule\"。",
"Options_0_and_1_cannot_be_combined_6370": "选项“{0}”与“{1}”不能组合在一起。",
"Options_Colon_6027": "选项:",
"Output_directory_for_generated_declaration_files_6166": "已生成声明文件的输出目录。",
+68 -12
View File
@@ -2112,7 +2112,7 @@ namespace ts {
// Nothing to do
break;
default:
Debug.fail("Unknown special property assignment kind");
Debug.fail("Unknown binary expression special property assignment kind");
}
return checkStrictModeBinaryExpression(<BinaryExpression>node);
case SyntaxKind.CatchClause:
@@ -2188,6 +2188,19 @@ namespace ts {
return bindFunctionExpression(<FunctionExpression>node);
case SyntaxKind.CallExpression:
const assignmentKind = getAssignmentDeclarationKind(node as CallExpression);
switch (assignmentKind) {
case AssignmentDeclarationKind.ObjectDefinePropertyValue:
return bindObjectDefinePropertyAssignment(node as BindableObjectDefinePropertyCall);
case AssignmentDeclarationKind.ObjectDefinePropertyExports:
return bindObjectDefinePropertyExport(node as BindableObjectDefinePropertyCall);
case AssignmentDeclarationKind.ObjectDefinePrototypeProperty:
return bindObjectDefinePrototypeProperty(node as BindableObjectDefinePropertyCall);
case AssignmentDeclarationKind.None:
break; // Nothing to do
default:
return Debug.fail("Unknown call expression assignment declaration kind");
}
if (isInJSFile(node)) {
bindCallExpression(<CallExpression>node);
}
@@ -2351,6 +2364,22 @@ namespace ts {
return true;
}
function bindObjectDefinePropertyExport(node: BindableObjectDefinePropertyCall) {
if (!setCommonJsModuleIndicator(node)) {
return;
}
const symbol = forEachIdentifierInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => {
if (symbol) {
addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment);
}
return symbol;
});
if (symbol) {
const flags = SymbolFlags.Property | SymbolFlags.ExportValue;
declareSymbol(symbol.exports!, symbol, node, flags, SymbolFlags.None);
}
}
function bindExportsPropertyAssignment(node: BinaryExpression) {
// When we create a property via 'exports.foo = bar', the 'exports.foo' property access
// expression is the declaration
@@ -2389,7 +2418,7 @@ namespace ts {
const flags = exportAssignmentIsAlias(node)
? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class
: SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule;
declareSymbol(file.symbol.exports!, file.symbol, node, flags, SymbolFlags.None);
declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None);
}
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
@@ -2458,6 +2487,11 @@ namespace ts {
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false);
}
function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) {
const namespaceSymbol = lookupSymbolForPropertyAccess((node.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression);
bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ true);
}
/**
* For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared.
* Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration.
@@ -2476,6 +2510,12 @@ namespace ts {
bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true);
}
function bindObjectDefinePropertyAssignment(node: BindableObjectDefinePropertyCall) {
let namespaceSymbol = lookupSymbolForPropertyAccess(node.arguments[0]);
const isToplevel = node.parent.parent.kind === SyntaxKind.SourceFile;
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, node.arguments[0], isToplevel, /*isPrototypeProperty*/ false);
bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ false);
}
function bindSpecialPropertyAssignment(node: BinaryExpression) {
const lhs = node.left as PropertyAccessEntityNameExpression;
@@ -2507,16 +2547,12 @@ namespace ts {
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false);
}
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
const isToplevel = isBinaryExpression(propertyAccess.parent)
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: EntityNameExpression, isToplevel: boolean, isPrototypeProperty: boolean) {
if (isToplevel && !isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace))) {
// make symbols or add declarations for intermediate containers
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment;
namespaceSymbol = forEachIdentifierInEntityName(propertyAccess.expression, namespaceSymbol, (id, symbol, parent) => {
namespaceSymbol = forEachIdentifierInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => {
if (symbol) {
addDeclarationToSymbol(symbol, id, flags);
return symbol;
@@ -2528,6 +2564,10 @@ namespace ts {
}
});
}
return namespaceSymbol;
}
function bindPotentiallyNewExpandoMemberToNamespace(declaration: PropertyAccessEntityNameExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) {
if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) {
return;
}
@@ -2537,10 +2577,19 @@ namespace ts {
(namespaceSymbol.members || (namespaceSymbol.members = createSymbolTable())) :
(namespaceSymbol.exports || (namespaceSymbol.exports = createSymbolTable()));
const isMethod = isFunctionLikeDeclaration(getAssignedExpandoInitializer(propertyAccess)!);
const isMethod = isFunctionLikeDeclaration(getAssignedExpandoInitializer(declaration)!);
const includes = isMethod ? SymbolFlags.Method : SymbolFlags.Property;
const excludes = isMethod ? SymbolFlags.MethodExcludes : SymbolFlags.PropertyExcludes;
declareSymbol(symbolTable, namespaceSymbol, propertyAccess, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment);
declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment);
}
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
const isToplevel = isBinaryExpression(propertyAccess.parent)
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty);
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);
}
/**
@@ -2558,6 +2607,9 @@ namespace ts {
return true;
}
const node = symbol.valueDeclaration;
if (isCallExpression(node)) {
return !!getAssignedExpandoInitializer(node);
}
let init = !node ? undefined :
isVariableDeclaration(node) ? node.initializer :
isBinaryExpression(node) ? node.right :
@@ -2869,7 +2921,6 @@ namespace ts {
}
}
/* @internal */
export function isExportsOrModuleExportsOrAlias(sourceFile: SourceFile, node: Expression): boolean {
return isExportsIdentifier(node) ||
isModuleExportsPropertyAccessExpression(node) ||
@@ -3650,6 +3701,10 @@ namespace ts {
}
break;
case SyntaxKind.BigIntLiteral:
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.ForOfStatement:
// This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of).
if ((<ForOfStatement>node).awaitModifier) {
@@ -3666,6 +3721,7 @@ namespace ts {
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.StringKeyword:
@@ -3841,7 +3897,6 @@ namespace ts {
* For performance reasons, `computeTransformFlagsForNode` uses local constant values rather
* than calling this function.
*/
/* @internal */
export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
return TransformFlags.TypeExcludes;
@@ -3874,6 +3929,7 @@ namespace ts {
return TransformFlags.MethodOrAccessorExcludes;
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.ObjectKeyword:
+37 -4
View File
@@ -201,12 +201,13 @@ namespace ts {
}
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
const seenFileAndExportsOfFile = createMap<true>();
// Go through exported modules from cache first
// If exported modules has path, all files referencing file exported from are affected
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
exportedModules &&
exportedModules.has(affectedFile.path) &&
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path)
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile)
)) {
return;
}
@@ -215,7 +216,7 @@ namespace ts {
forEachEntry(state.exportedModulesMap, (exportedModules, exportedFromPath) =>
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
exportedModules.has(affectedFile.path) &&
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path)
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile)
);
}
@@ -223,9 +224,41 @@ namespace ts {
* removes the semantic diagnostics of files referencing referencedPath and
* returns true if there are no more semantic diagnostics from old state
*/
function removeSemanticDiagnosticsOfFilesReferencingPath(state: BuilderProgramState, referencedPath: Path) {
function removeSemanticDiagnosticsOfFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Map<true>) {
return forEachEntry(state.referencedMap!, (referencesInFile, filePath) =>
referencesInFile.has(referencedPath) && removeSemanticDiagnosticsOf(state, filePath as Path)
referencesInFile.has(referencedPath) && removeSemanticDiagnosticsOfFileAndExportsOfFile(state, filePath as Path, seenFileAndExportsOfFile)
);
}
/**
* Removes semantic diagnostics of file and anything that exports this file
*/
function removeSemanticDiagnosticsOfFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Map<true>): boolean {
if (!addToSeen(seenFileAndExportsOfFile, filePath)) {
return false;
}
if (removeSemanticDiagnosticsOf(state, filePath)) {
// If there are no more diagnostics from old cache, done
return true;
}
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
// Go through exported modules from cache first
// If exported modules has path, all files referencing file exported from are affected
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
exportedModules &&
exportedModules.has(filePath) &&
removeSemanticDiagnosticsOfFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile)
)) {
return true;
}
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
return !!forEachEntry(state.exportedModulesMap!, (exportedModules, exportedFromPath) =>
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
exportedModules.has(filePath) &&
removeSemanticDiagnosticsOfFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile)
);
}
+36
View File
@@ -148,8 +148,39 @@ namespace ts.BuilderState {
});
}
// Add module augmentation as references
if (sourceFile.moduleAugmentations.length) {
const checker = program.getTypeChecker();
for (const moduleName of sourceFile.moduleAugmentations) {
if (!isStringLiteral(moduleName)) { continue; }
const symbol = checker.getSymbolAtLocation(moduleName);
if (!symbol) { continue; }
// Add any file other than our own as reference
addReferenceFromAmbientModule(symbol);
}
}
// From ambient modules
for (const ambientModule of program.getTypeChecker().getAmbientModules()) {
if (ambientModule.declarations.length > 1) {
addReferenceFromAmbientModule(ambientModule);
}
}
return referencedFiles;
function addReferenceFromAmbientModule(symbol: Symbol) {
// Add any file other than our own as reference
for (const declaration of symbol.declarations) {
const declarationSourceFile = getSourceFileOfNode(declaration);
if (declarationSourceFile &&
declarationSourceFile !== sourceFile) {
addReferencedFile(declarationSourceFile.resolvedPath);
}
}
}
function addReferencedFile(referencedPath: Path) {
if (!referencedFiles) {
referencedFiles = createMap<true>();
@@ -261,6 +292,11 @@ namespace ts.BuilderState {
let latestSignature: string;
if (sourceFile.isDeclarationFile) {
latestSignature = sourceFile.version;
if (exportedModulesMapCache && latestSignature !== prevSignature) {
// All the references in this file are exported
const references = state.referencedMap ? state.referencedMap.get(sourceFile.path) : undefined;
exportedModulesMapCache.set(sourceFile.path, references || false);
}
}
else {
const emitOutput = getFileEmitOutput(programOfThisState, sourceFile, /*emitOnlyDtsFiles*/ true, cancellationToken);
+1239 -1088
View File
File diff suppressed because it is too large Load Diff
+197 -80
View File
@@ -44,7 +44,8 @@ namespace ts {
["esnext.array", "lib.esnext.array.d.ts"],
["esnext.symbol", "lib.esnext.symbol.d.ts"],
["esnext.asynciterable", "lib.esnext.asynciterable.d.ts"],
["esnext.intl", "lib.esnext.intl.d.ts"]
["esnext.intl", "lib.esnext.intl.d.ts"],
["esnext.bigint", "lib.esnext.bigint.d.ts"]
];
/**
@@ -104,6 +105,13 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation
},
{
name: "pretty",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental
},
{
name: "traceResolution",
@@ -158,11 +166,11 @@ namespace ts {
description: Diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date
},
{
name: "pretty",
name: "showConfig",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental
isCommandLineOnly: true,
description: Diagnostics.Print_the_final_configuration_instead_of_building
},
// Basic
@@ -576,6 +584,12 @@ namespace ts {
category: Diagnostics.Experimental_Options,
description: Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators
},
{
name: "experimentalBigInt",
type: "boolean",
category: Diagnostics.Experimental_Options,
description: Diagnostics.Enables_experimental_support_for_ESNext_BigInt_literals
},
// Advanced
{
@@ -1013,7 +1027,7 @@ namespace ts {
i++;
break;
case "list":
const result = parseListTypeOption(<CommandLineOptionOfListType>opt, args[i], errors);
const result = parseListTypeOption(opt, args[i], errors);
options[opt.name] = result || [];
if (result) {
i++;
@@ -1146,7 +1160,7 @@ namespace ts {
}
/* @internal */
export function printHelp(optionsList: CommandLineOption[], syntaxPrefix = "") {
export function printHelp(optionsList: ReadonlyArray<CommandLineOption>, syntaxPrefix = "") {
const output: string[] = [];
// We want to align our "syntax" and "examples" commands to a certain margin.
@@ -1293,6 +1307,9 @@ namespace ts {
const result = parseJsonText(configFileName, configFileText);
const cwd = host.getCurrentDirectory();
result.path = toPath(configFileName, cwd, createGetCanonicalFileName(host.useCaseSensitiveFileNames));
result.resolvedPath = result.path;
result.originalFileName = result.fileName;
return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd));
}
@@ -1650,6 +1667,137 @@ namespace ts {
return false;
}
/**
* Generate an uncommented, complete tsconfig for use with "--showConfig"
* @param configParseResult options to be generated into tsconfig.json
* @param configFileName name of the parsed config file - output paths will be generated relative to this
* @param host provides current directory and case sensitivity services
*/
/** @internal */
export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: { getCurrentDirectory(): string, useCaseSensitiveFileNames: boolean }): object {
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
const files = map(
filter(
configParseResult.fileNames,
!configParseResult.configFileSpecs ? _ => false : matchesSpecs(
configFileName,
configParseResult.configFileSpecs.validatedIncludeSpecs,
configParseResult.configFileSpecs.validatedExcludeSpecs
)
),
f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), f, getCanonicalFileName)
);
const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames });
const config = {
compilerOptions: {
...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}),
showConfig: undefined,
configFile: undefined,
configFilePath: undefined,
help: undefined,
init: undefined,
listFiles: undefined,
listEmittedFiles: undefined,
project: undefined,
},
references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath, originalPath: undefined })),
files: length(files) ? files : undefined,
...(configParseResult.configFileSpecs ? {
include: filterSameAsDefaultInclude(configParseResult.configFileSpecs.validatedIncludeSpecs),
exclude: configParseResult.configFileSpecs.validatedExcludeSpecs
} : {}),
compilerOnSave: !!configParseResult.compileOnSave ? true : undefined
};
return config;
}
function filterSameAsDefaultInclude(specs: ReadonlyArray<string> | undefined) {
if (!length(specs)) return undefined;
if (length(specs) !== 1) return specs;
if (specs![0] === "**/*") return undefined;
return specs;
}
function matchesSpecs(path: string, includeSpecs: ReadonlyArray<string> | undefined, excludeSpecs: ReadonlyArray<string> | undefined): (path: string) => boolean {
if (!includeSpecs) return _ => false;
const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, sys.useCaseSensitiveFileNames, sys.getCurrentDirectory());
const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, sys.useCaseSensitiveFileNames);
const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, sys.useCaseSensitiveFileNames);
if (includeRe) {
if (excludeRe) {
return path => includeRe.test(path) && !excludeRe.test(path);
}
return path => includeRe.test(path);
}
if (excludeRe) {
return path => !excludeRe.test(path);
}
return _ => false;
}
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
// this is of a type CommandLineOptionOfPrimitiveType
return undefined;
}
else if (optionDefinition.type === "list") {
return getCustomTypeMapOfCommandLineOption(optionDefinition.element);
}
else {
return (<CommandLineOptionOfCustomType>optionDefinition).type;
}
}
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: Map<string | number>): string | undefined {
// There is a typeMap associated with this command-line option so use it to map value back to its name
return forEachEntry(customTypeMap, (mapValue, key) => {
if (mapValue === value) {
return key;
}
});
}
function serializeCompilerOptions(options: CompilerOptions, pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean }): Map<CompilerOptionsValue> {
const result = createMap<CompilerOptionsValue>();
const optionsNameMap = getOptionNameMap().optionNameMap;
const getCanonicalFileName = pathOptions && createGetCanonicalFileName(pathOptions.useCaseSensitiveFileNames);
for (const name in options) {
if (hasProperty(options, name)) {
// tsconfig only options cannot be specified via command line,
// so we can assume that only types that can appear here string | number | boolean
if (optionsNameMap.has(name) && optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options) {
continue;
}
const value = <CompilerOptionsValue>options[name];
const optionDefinition = optionsNameMap.get(name.toLowerCase());
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
if (!customTypeMap) {
// There is no map associated with this compiler option then use the value as-is
// This is the case if the value is expect to be string, number, boolean or list of string
if (pathOptions && optionDefinition.isFilePath) {
result.set(name, getRelativePathFromFile(pathOptions.configFilePath, getNormalizedAbsolutePath(value as string, getDirectoryPath(pathOptions.configFilePath)), getCanonicalFileName!));
}
else {
result.set(name, value);
}
}
else {
if (optionDefinition.type === "list") {
result.set(name, (value as ReadonlyArray<string | number>).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217
}
else {
// There is a typeMap associated with this command-line option so use it to map value back to its name
result.set(name, getNameOfCompilerOptionValue(value, customTypeMap));
}
}
}
}
}
return result;
}
/**
* Generate tsconfig configuration when running command line "--init"
* @param options commandlineOptions to be generated into tsconfig.json
@@ -1661,63 +1809,6 @@ namespace ts {
const compilerOptionsMap = serializeCompilerOptions(compilerOptions);
return writeConfigurations();
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
// this is of a type CommandLineOptionOfPrimitiveType
return undefined;
}
else if (optionDefinition.type === "list") {
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
}
else {
return (<CommandLineOptionOfCustomType>optionDefinition).type;
}
}
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: Map<string | number>): string | undefined {
// There is a typeMap associated with this command-line option so use it to map value back to its name
return forEachEntry(customTypeMap, (mapValue, key) => {
if (mapValue === value) {
return key;
}
});
}
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
const result = createMap<CompilerOptionsValue>();
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(options, name)) {
// tsconfig only options cannot be specified via command line,
// so we can assume that only types that can appear here string | number | boolean
if (optionsNameMap.has(name) && optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options) {
continue;
}
const value = <CompilerOptionsValue>options[name];
const optionDefinition = optionsNameMap.get(name.toLowerCase());
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
if (!customTypeMap) {
// There is no map associated with this compiler option then use the value as-is
// This is the case if the value is expect to be string, number, boolean or list of string
result.set(name, value);
}
else {
if (optionDefinition.type === "list") {
result.set(name, (value as ReadonlyArray<string | number>).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217
}
else {
// There is a typeMap associated with this command-line option so use it to map value back to its name
result.set(name, getNameOfCompilerOptionValue(value, customTypeMap));
}
}
}
}
}
return result;
}
function getDefaultValueForOption(option: CommandLineOption) {
switch (option.type) {
case "number":
@@ -1731,7 +1822,7 @@ namespace ts {
case "object":
return {};
default:
return (option as CommandLineOptionOfCustomType).type.keys().next().value;
return option.type.keys().next().value;
}
}
@@ -2188,20 +2279,24 @@ namespace ts {
errors: Push<Diagnostic>,
createDiagnostic: (message: DiagnosticMessage, arg1?: string) => Diagnostic) {
extendedConfig = normalizeSlashes(extendedConfig);
// If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future)
if (!(isRootedDiskPath(extendedConfig) || startsWith(extendedConfig, "./") || startsWith(extendedConfig, "../"))) {
errors.push(createDiagnostic(Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extendedConfig));
return undefined;
}
let extendedConfigPath = getNormalizedAbsolutePath(extendedConfig, basePath);
if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, Extension.Json)) {
extendedConfigPath = `${extendedConfigPath}.json`;
if (!host.fileExists(extendedConfigPath)) {
errors.push(createDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig));
return undefined;
if (isRootedDiskPath(extendedConfig) || startsWith(extendedConfig, "./") || startsWith(extendedConfig, "../")) {
let extendedConfigPath = getNormalizedAbsolutePath(extendedConfig, basePath);
if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, Extension.Json)) {
extendedConfigPath = `${extendedConfigPath}.json`;
if (!host.fileExists(extendedConfigPath)) {
errors.push(createDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig));
return undefined;
}
}
return extendedConfigPath;
}
return extendedConfigPath;
// If the path isn't a rooted or relative path, resolve like a module
const resolved = nodeModuleNameResolver(extendedConfig, combinePaths(basePath, "tsconfig.json"), { moduleResolution: ModuleResolutionKind.NodeJs }, host, /*cache*/ undefined, /*projectRefs*/ undefined, /*lookupConfig*/ true);
if (resolved.resolvedModule) {
return resolved.resolvedModule.resolvedFileName;
}
errors.push(createDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig));
return undefined;
}
function getExtendedConfig(
@@ -2338,7 +2433,7 @@ namespace ts {
function normalizeOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
if (isNullOrUndefined(value)) return undefined;
if (option.type === "list") {
const listOption = <CommandLineOptionOfListType>option;
const listOption = option;
if (listOption.element.isFilePath || !isString(listOption.element.type)) {
return <CompilerOptionsValue>filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => !!v);
}
@@ -2509,11 +2604,16 @@ namespace ts {
// via wildcard, and to handle extension priority.
const wildcardFileMap = createMap<string>();
// Wildcard paths of json files (provided via the "includes" array in tsconfig.json) are stored in a
// file map with a possibly case insensitive key. We use this map to store paths matched
// via wildcard of *.json kind
const wildCardJsonFileMap = createMap<string>();
const { filesSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories } = spec;
// Rather than requery this for each file and filespec, we query the supported extensions
// once and store it on the expansion context.
const supportedExtensions = getSupportedExtensions(options, extraFileExtensions);
const supportedExtensionsWithJsonIfResolveJsonModule = getSuppoertedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions);
// Literal files are always included verbatim. An "include" or "exclude" specification cannot
// remove a literal file.
@@ -2524,8 +2624,25 @@ namespace ts {
}
}
let jsonOnlyIncludeRegexes: ReadonlyArray<RegExp> | undefined;
if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) {
for (const file of host.readDirectory(basePath, supportedExtensions, validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) {
for (const file of host.readDirectory(basePath, supportedExtensionsWithJsonIfResolveJsonModule, validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) {
if (fileExtensionIs(file, Extension.Json)) {
// Valid only if *.json specified
if (!jsonOnlyIncludeRegexes) {
const includes = validatedIncludeSpecs.filter(s => endsWith(s, Extension.Json));
const includeFilePatterns = map(getRegularExpressionsForWildcards(includes, basePath, "files"), pattern => `^${pattern}$`);
jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => getRegexFromPattern(pattern, host.useCaseSensitiveFileNames)) : emptyArray;
}
const includeIndex = findIndex(jsonOnlyIncludeRegexes, re => re.test(file));
if (includeIndex !== -1) {
const key = keyMapper(file);
if (!literalFileMap.has(key) && !wildCardJsonFileMap.has(key)) {
wildCardJsonFileMap.set(key, file);
}
}
continue;
}
// If we have already included a literal or wildcard path with a
// higher priority extension, we should skip this file.
//
@@ -2553,7 +2670,7 @@ namespace ts {
const wildcardFiles = arrayFrom(wildcardFileMap.values());
return {
fileNames: literalFiles.concat(wildcardFiles),
fileNames: literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values())),
wildcardDirectories,
spec
};
@@ -2723,7 +2840,7 @@ namespace ts {
case "boolean":
return typeof value === "boolean" ? value : "";
case "list":
const elementType = (option as CommandLineOptionOfListType).element;
const elementType = option.element;
return isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : "";
default:
return forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
+37 -16
View File
@@ -16,6 +16,10 @@ namespace ts {
[index: string]: T;
}
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
" __sortedArrayBrand": any;
}
export interface SortedArray<T> extends Array<T> {
" __sortedArrayBrand": any;
}
@@ -511,12 +515,27 @@ namespace ts {
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export function flatMap<T, U>(array: ReadonlyArray<T>, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[];
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined;
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined {
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): ReadonlyArray<U> {
let result: U[] | undefined;
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
const v = mapfn(array[i], i);
if (v) {
if (isArray(v)) {
result = addRange(result, v);
}
else {
result = append(result, v);
}
}
}
}
return result || emptyArray;
}
export function flatMapToMutable<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] {
const result: U[] = [];
if (array) {
for (let i = 0; i < array.length; i++) {
const v = mapfn(array[i], i);
if (v) {
@@ -800,8 +819,8 @@ namespace ts {
/**
* Deduplicates an array that has already been sorted.
*/
function deduplicateSorted<T>(array: ReadonlyArray<T>, comparer: EqualityComparer<T> | Comparer<T>): T[] {
if (array.length === 0) return [];
function deduplicateSorted<T>(array: SortedReadonlyArray<T>, comparer: EqualityComparer<T> | Comparer<T>): SortedReadonlyArray<T> {
if (array.length === 0) return emptyArray as any as SortedReadonlyArray<T>;
let last = array[0];
const deduplicated: T[] = [last];
@@ -823,7 +842,7 @@ namespace ts {
deduplicated.push(last = next);
}
return deduplicated;
return deduplicated as any as SortedReadonlyArray<T>;
}
export function insertSorted<T>(array: SortedArray<T>, insert: T, compare: Comparer<T>): void {
@@ -838,8 +857,10 @@ namespace ts {
}
}
export function sortAndDeduplicate<T>(array: ReadonlyArray<T>, comparer: Comparer<T>, equalityComparer?: EqualityComparer<T>) {
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer);
export function sortAndDeduplicate<T>(array: ReadonlyArray<string>): SortedReadonlyArray<string>;
export function sortAndDeduplicate<T>(array: ReadonlyArray<T>, comparer: Comparer<T>, equalityComparer?: EqualityComparer<T>): SortedReadonlyArray<T>;
export function sortAndDeduplicate<T>(array: ReadonlyArray<T>, comparer?: Comparer<T>, equalityComparer?: EqualityComparer<T>): SortedReadonlyArray<T> {
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive as any as Comparer<T>);
}
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean {
@@ -1020,8 +1041,8 @@ namespace ts {
/**
* Returns a new sorted array.
*/
export function sort<T>(array: ReadonlyArray<T>, comparer: Comparer<T>): T[] {
return array.slice().sort(comparer);
export function sort<T>(array: ReadonlyArray<T>, comparer?: Comparer<T>): SortedReadonlyArray<T> {
return (array.length === 0 ? array : array.slice().sort(comparer)) as SortedReadonlyArray<T>;
}
export function arrayIterator<T>(array: ReadonlyArray<T>): Iterator<T> {
@@ -1615,8 +1636,9 @@ namespace ts {
return value;
}
export function assertNever(member: never, message?: string, stackCrawlMark?: AnyFunction): never {
return fail(message || `Illegal value: ${member}`, stackCrawlMark || assertNever);
export function assertNever(member: never, message = "Illegal value:", stackCrawlMark?: AnyFunction): never {
const detail = "kind" in member && "pos" in member ? "SyntaxKind: " + showSyntaxKind(member as Node) : JSON.stringify(member);
return fail(`${message} ${detail}`, stackCrawlMark || assertNever);
}
export function getFunctionName(func: AnyFunction) {
@@ -2043,7 +2065,6 @@ namespace ts {
}
/** Represents a "prefix*suffix" pattern. */
/* @internal */
export interface Pattern {
prefix: string;
suffix: string;
@@ -2198,7 +2219,7 @@ namespace ts {
}
private unsafeAdd(value: T, sortedAndUnique: boolean) {
if (this.copyOnWrite) {
if (this.copyOnWrite || this.unsafeArray === emptyArray) {
this.unsafeArray = this.unsafeArray.slice();
this.copyOnWrite = false;
}
@@ -2210,7 +2231,7 @@ namespace ts {
private ensureSortedAndUnique() {
if (!this.sortedAndUnique) {
this.unsafeArray = deduplicateSorted(stableSort(this.unsafeArray, this.relationalComparer), this.equalityComparer);
this.unsafeArray = deduplicateSorted(stableSort(this.unsafeArray, this.relationalComparer) as any as SortedReadonlyArray<T>, this.equalityComparer) as any as T[];
this.unsafeLast = undefined;
this.sortedAndUnique = true;
}
+79 -10
View File
@@ -1007,6 +1007,14 @@
"category": "Error",
"code": 1349
},
"Print the final configuration instead of building.": {
"category": "Message",
"code": 1350
},
"Experimental support for BigInt is a feature that is subject to change in a future release. Set the 'experimentalBigInt' option to remove this warning.": {
"category": "Error",
"code": 1351
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -1232,7 +1240,7 @@
"category": "Error",
"code": 2355
},
"An arithmetic operand must be of type 'any', 'number' or an enum type.": {
"An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.": {
"category": "Error",
"code": 2356
},
@@ -1256,11 +1264,11 @@
"category": "Error",
"code": 2361
},
"The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": {
"The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.": {
"category": "Error",
"code": 2362
},
"The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": {
"The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.": {
"category": "Error",
"code": 2363
},
@@ -2088,15 +2096,15 @@
"category": "Error",
"code": 2577
},
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node`.": {
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.": {
"category": "Error",
"code": 2580
},
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`.": {
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.": {
"category": "Error",
"code": 2581
},
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.": {
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig.": {
"category": "Error",
"code": 2582
},
@@ -2485,14 +2493,26 @@
"category": "Error",
"code": 2732
},
"Index '{0}' is out-of-bounds in tuple of length {1}.": {
"category": "Error",
"code": 2733
},
"It is highly likely that you are missing a semicolon.": {
"category": "Error",
"code": 2734
},
"Did you mean for '{0}' to be constrained to type 'new (...args: any[]) => {1}'?": {
"category": "Error",
"code": 2735
},
"Operator '{0}' cannot be applied to type '{1}'.": {
"category": "Error",
"code": 2736
},
"BigInt literals are not available when targetting lower than ESNext.": {
"category": "Error",
"code": 2737
},
"An outer value of 'this' is shadowed by this container.": {
"category": "Message",
"code": 2738
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -3767,6 +3787,18 @@
"category": "Message",
"code": 6214
},
"Using compiler options of project reference redirect '{0}'.": {
"category": "Message",
"code": 6215
},
"Found 1 error.": {
"category": "Message",
"code": 6216
},
"Found {0} errors.": {
"category": "Message",
"code": 6217
},
"Projects to reference": {
"category": "Message",
@@ -3889,6 +3921,10 @@
"category": "Error",
"code": 6370
},
"Enables experimental support for ESNext BigInt literals.": {
"category": "Message",
"code": 6371
},
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",
@@ -4041,6 +4077,39 @@
"category": "Error",
"code": 7042
},
"Variable '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7043
},
"Parameter '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7044
},
"Member '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7045
},
"Variable '{0}' implicitly has type '{1}' in some locations, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7046
},
"Rest parameter '{0}' implicitly has an 'any[]' type, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7047
},
"Property '{0}' implicitly has type 'any', but a better type for its get accessor may be inferred from usage.": {
"category": "Suggestion",
"code": 7048
},
"Property '{0}' implicitly has type 'any', but a better type for its set accessor may be inferred from usage.": {
"category": "Suggestion",
"code": 7049
},
"'{0}' implicitly has an '{1}' return type, but a better type may be inferred from usage.": {
"category": "Suggestion",
"code": 7050
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+220 -22
View File
@@ -42,20 +42,25 @@ namespace ts {
export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames {
const options = host.getCompilerOptions();
if (sourceFile.kind === SyntaxKind.Bundle) {
const jsFilePath = options.outFile || options.out!;
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined;
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const outPath = options.outFile || options.out!;
const jsFilePath = options.emitDeclarationOnly ? undefined : outPath;
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
}
else {
const jsFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile, options));
const sourceMapFilePath = isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile, options));
// If json file emits to the same location skip writing it, if emitDeclarationOnly skip writing it
const isJsonEmittedToSameLocation = isJsonSourceFile(sourceFile) &&
comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo;
const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath;
const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
// For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error
const isJs = isSourceFileJS(sourceFile);
const declarationFilePath = ((forceDtsPaths || getEmitDeclarations(options)) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath: undefined };
}
}
@@ -128,27 +133,33 @@ namespace ts {
if (!emitSkipped && emittedFilesList) {
if (!emitOnlyDtsFiles) {
emittedFilesList.push(jsFilePath);
}
if (sourceMapFilePath) {
emittedFilesList.push(sourceMapFilePath);
if (jsFilePath) {
emittedFilesList.push(jsFilePath);
}
if (sourceMapFilePath) {
emittedFilesList.push(sourceMapFilePath);
}
if (bundleInfoPath) {
emittedFilesList.push(bundleInfoPath);
}
}
if (declarationFilePath) {
emittedFilesList.push(declarationFilePath);
}
if (bundleInfoPath) {
emittedFilesList.push(bundleInfoPath);
if (declarationMapPath) {
emittedFilesList.push(declarationMapPath);
}
}
}
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string | undefined, bundleInfoPath: string | undefined) {
// Make sure not to write js file and source map file if any of them cannot be written
if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) {
emitSkipped = true;
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string | undefined, sourceMapFilePath: string | undefined, bundleInfoPath: string | undefined) {
if (emitOnlyDtsFiles || !jsFilePath) {
return;
}
if (emitOnlyDtsFiles) {
// Make sure not to write js file and source map file if any of them cannot be written
if ((jsFilePath && host.isEmitBlocked(jsFilePath)) || compilerOptions.noEmit) {
emitSkipped = true;
return;
}
// Transform the source files
@@ -955,7 +966,34 @@ namespace ts {
case SyntaxKind.EnumMember:
return emitEnumMember(<EnumMember>node);
// JSDoc nodes (ignored)
// JSDoc nodes (only used in codefixes currently)
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.JSDocPropertyTag:
return emitJSDocPropertyLikeTag(node as JSDocPropertyLikeTag);
case SyntaxKind.JSDocReturnTag:
case SyntaxKind.JSDocTypeTag:
case SyntaxKind.JSDocThisTag:
case SyntaxKind.JSDocEnumTag:
return emitJSDocSimpleTypedTag(node as JSDocTypeTag);
case SyntaxKind.JSDocAugmentsTag:
return emitJSDocAugmentsTag(node as JSDocAugmentsTag);
case SyntaxKind.JSDocTemplateTag:
return emitJSDocTemplateTag(node as JSDocTemplateTag);
case SyntaxKind.JSDocTypedefTag:
return emitJSDocTypedefTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocCallbackTag:
return emitJSDocCallbackTag(node as JSDocCallbackTag);
case SyntaxKind.JSDocSignature:
return emitJSDocSignature(node as JSDocSignature);
case SyntaxKind.JSDocTypeLiteral:
return emitJSDocTypeLiteral(node as JSDocTypeLiteral);
case SyntaxKind.JSDocClassTag:
case SyntaxKind.JSDocTag:
return emitJSDocSimpleTag(node as JSDocTag);
case SyntaxKind.JSDocComment:
return emitJSDoc(node as JSDoc);
// Transformation nodes (ignored)
}
@@ -973,7 +1011,8 @@ namespace ts {
switch (node.kind) {
// Literals
case SyntaxKind.NumericLiteral:
return emitNumericLiteral(<NumericLiteral>node);
case SyntaxKind.BigIntLiteral:
return emitNumericOrBigIntLiteral(<NumericLiteral | BigIntLiteral>node);
case SyntaxKind.StringLiteral:
case SyntaxKind.RegularExpressionLiteral:
@@ -1137,7 +1176,8 @@ namespace ts {
//
// SyntaxKind.NumericLiteral
function emitNumericLiteral(node: NumericLiteral) {
// SyntaxKind.BigIntLiteral
function emitNumericOrBigIntLiteral(node: NumericLiteral | BigIntLiteral) {
emitLiteral(node);
}
@@ -2687,6 +2727,154 @@ namespace ts {
emitInitializer(node.initializer, node.name.end, node);
}
//
// JSDoc
//
function emitJSDoc(node: JSDoc) {
write("/**");
if (node.comment) {
const lines = node.comment.split(/\r\n?|\n/g);
for (const line of lines) {
writeLine();
writeSpace();
writePunctuation("*");
writeSpace();
write(line);
}
}
if (node.tags) {
if (node.tags.length === 1 && node.tags[0].kind === SyntaxKind.JSDocTypeTag && !node.comment) {
writeSpace();
emit(node.tags[0]);
}
else {
emitList(node, node.tags, ListFormat.JSDocComment);
}
}
writeSpace();
write("*/");
}
function emitJSDocSimpleTypedTag(tag: JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocReturnTag) {
emitJSDocTagName(tag.tagName);
emitJSDocTypeExpression(tag.typeExpression);
emitJSDocComment(tag.comment);
}
function emitJSDocAugmentsTag(tag: JSDocAugmentsTag) {
emitJSDocTagName(tag.tagName);
writeSpace();
writePunctuation("{");
emit(tag.class);
writePunctuation("}");
emitJSDocComment(tag.comment);
}
function emitJSDocTemplateTag(tag: JSDocTemplateTag) {
emitJSDocTagName(tag.tagName);
emitJSDocTypeExpression(tag.constraint);
writeSpace();
emitList(tag, tag.typeParameters, ListFormat.CommaListElements);
emitJSDocComment(tag.comment);
}
function emitJSDocTypedefTag(tag: JSDocTypedefTag) {
emitJSDocTagName(tag.tagName);
if (tag.typeExpression) {
if (tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) {
emitJSDocTypeExpression(tag.typeExpression);
}
else {
writeSpace();
writePunctuation("{");
write("Object");
if (tag.typeExpression.isArrayType) {
writePunctuation("[");
writePunctuation("]");
}
writePunctuation("}");
}
}
if (tag.fullName) {
writeSpace();
emit(tag.fullName);
}
emitJSDocComment(tag.comment);
if (tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeLiteral) {
emitJSDocTypeLiteral(tag.typeExpression);
}
}
function emitJSDocCallbackTag(tag: JSDocCallbackTag) {
emitJSDocTagName(tag.tagName);
if (tag.name) {
writeSpace();
emit(tag.name);
}
emitJSDocComment(tag.comment);
emitJSDocSignature(tag.typeExpression);
}
function emitJSDocSimpleTag(tag: JSDocTag) {
emitJSDocTagName(tag.tagName);
emitJSDocComment(tag.comment);
}
function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) {
emitList(lit, createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment);
}
function emitJSDocSignature(sig: JSDocSignature) {
if (sig.typeParameters) {
emitList(sig, createNodeArray(sig.typeParameters), ListFormat.JSDocComment);
}
if (sig.parameters) {
emitList(sig, createNodeArray(sig.parameters), ListFormat.JSDocComment);
}
if (sig.type) {
writeLine();
writeSpace();
writePunctuation("*");
writeSpace();
emit(sig.type);
}
}
function emitJSDocPropertyLikeTag(param: JSDocPropertyLikeTag) {
emitJSDocTagName(param.tagName);
emitJSDocTypeExpression(param.typeExpression);
writeSpace();
if (param.isBracketed) {
writePunctuation("[");
}
emit(param.name);
if (param.isBracketed) {
writePunctuation("]");
}
emitJSDocComment(param.comment);
}
function emitJSDocTagName(tagName: Identifier) {
writePunctuation("@");
emit(tagName);
}
function emitJSDocComment(comment: string | undefined) {
if (comment) {
writeSpace();
write(comment);
}
}
function emitJSDocTypeExpression(typeExpression: JSDocTypeExpression | undefined) {
if (typeExpression) {
writeSpace();
writePunctuation("{");
emit(typeExpression.type);
writePunctuation("}");
}
}
//
// Top-level nodes
//
@@ -2984,6 +3172,11 @@ namespace ts {
writeSpace();
writePunctuation("|");
break;
case ListFormat.AsteriskDelimited:
writeSpace();
writePunctuation("*");
writeSpace();
break;
case ListFormat.AmpersandDelimited:
writeSpace();
writePunctuation("&");
@@ -3053,7 +3246,12 @@ namespace ts {
const child = children![start + i];
// Write the delimiter if this is not the first node.
if (previousSibling) {
if (format & ListFormat.AsteriskDelimited) {
// always write JSDoc in the format "\n *"
writeLine();
writeDelimiter(format);
}
else if (previousSibling) {
// i.e
// function commentedParameters(
// /* Parameter a */
+63 -3
View File
@@ -68,13 +68,16 @@ namespace ts {
/* @internal */ export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote: boolean): StringLiteral; // tslint:disable-line unified-signatures
/** If a node is passed, creates a string literal whose source text is read from a source node during emit. */
export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral;
export function createLiteral(value: number): NumericLiteral;
export function createLiteral(value: number | PseudoBigInt): NumericLiteral;
export function createLiteral(value: boolean): BooleanLiteral;
export function createLiteral(value: string | number | boolean): PrimaryExpression;
export function createLiteral(value: string | number | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote?: boolean): PrimaryExpression {
export function createLiteral(value: string | number | PseudoBigInt | boolean): PrimaryExpression;
export function createLiteral(value: string | number | PseudoBigInt | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote?: boolean): PrimaryExpression {
if (typeof value === "number") {
return createNumericLiteral(value + "");
}
if (typeof value === "object" && "base10Value" in value) { // PseudoBigInt
return createBigIntLiteral(pseudoBigIntToString(value) + "n");
}
if (typeof value === "boolean") {
return value ? createTrue() : createFalse();
}
@@ -93,6 +96,12 @@ namespace ts {
return node;
}
export function createBigIntLiteral(value: string): BigIntLiteral {
const node = <BigIntLiteral>createSynthesizedNode(SyntaxKind.BigIntLiteral);
node.text = value;
return node;
}
export function createStringLiteral(text: string): StringLiteral {
const node = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
node.text = text;
@@ -2170,6 +2179,56 @@ namespace ts {
: node;
}
// JSDoc
/* @internal */
export function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression {
const node = createSynthesizedNode(SyntaxKind.JSDocTypeExpression) as JSDocTypeExpression;
node.type = type;
return node;
}
/* @internal */
export function createJSDocTypeTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocTypeTag {
const tag = createJSDocTag<JSDocTypeTag>(SyntaxKind.JSDocTypeTag, "type");
tag.typeExpression = typeExpression;
tag.comment = comment;
return tag;
}
/* @internal */
export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag {
const tag = createJSDocTag<JSDocReturnTag>(SyntaxKind.JSDocReturnTag, "returns");
tag.typeExpression = typeExpression;
tag.comment = comment;
return tag;
}
/* @internal */
export function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag {
const tag = createJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, "param");
tag.typeExpression = typeExpression;
tag.name = name;
tag.isBracketed = isBracketed;
tag.comment = comment;
return tag;
}
/* @internal */
export function createJSDocComment(comment?: string | undefined, tags?: NodeArray<JSDocTag> | undefined) {
const node = createSynthesizedNode(SyntaxKind.JSDocComment) as JSDoc;
node.comment = comment;
node.tags = tags;
return node;
}
/* @internal */
function createJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: string): T {
const node = createSynthesizedNode(kind) as T;
node.tagName = createIdentifier(tagName);
return node;
}
// JSX
export function createJsxElement(openingElement: JsxOpeningElement, children: ReadonlyArray<JsxChild>, closingElement: JsxClosingElement) {
@@ -3416,6 +3475,7 @@ namespace ts {
return cacheIdentifiers;
case SyntaxKind.ThisKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
return false;
case SyntaxKind.ArrayLiteralExpression:
+158 -74
View File
@@ -62,6 +62,7 @@ namespace ts {
TypeScript, /** '.ts', '.tsx', or '.d.ts' */
JavaScript, /** '.js' or '.jsx' */
Json, /** '.json' */
TSConfig, /** '.json' with `tsconfig` used instead of `index` */
DtsOnly /** Only '.d.ts' */
}
@@ -98,6 +99,7 @@ namespace ts {
types?: string;
typesVersions?: MapLike<MapLike<string[]>>;
main?: string;
tsconfig?: string;
}
interface PackageJson extends PackageJsonPathFields {
@@ -126,7 +128,7 @@ namespace ts {
return value;
}
function readPackageJsonPathField<K extends "typings" | "types" | "main">(jsonContent: PackageJson, fieldName: K, baseDirectory: string, state: ModuleResolutionState): PackageJson[K] | undefined {
function readPackageJsonPathField<K extends "typings" | "types" | "main" | "tsconfig">(jsonContent: PackageJson, fieldName: K, baseDirectory: string, state: ModuleResolutionState): PackageJson[K] | undefined {
const fileName = readPackageJsonField(jsonContent, fieldName, "string", state);
if (fileName === undefined) return;
const path = normalizePath(combinePaths(baseDirectory, fileName));
@@ -141,6 +143,10 @@ namespace ts {
|| readPackageJsonPathField(jsonContent, "types", baseDirectory, state);
}
function readPackageJsonTSConfigField(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState) {
return readPackageJsonPathField(jsonContent, "tsconfig", baseDirectory, state);
}
function readPackageJsonMainField(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState) {
return readPackageJsonPathField(jsonContent, "main", baseDirectory, state);
}
@@ -258,8 +264,11 @@ namespace ts {
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
* is assumed to be the same as root directory of the project.
*/
export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(options, host);
if (redirectedReference) {
options = redirectedReference.commandLine.options;
}
const failedLookupLocations: string[] = [];
const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations };
@@ -281,6 +290,9 @@ namespace ts {
trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots);
}
}
if (redirectedReference) {
trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName);
}
}
let resolved = primaryLookup();
@@ -292,14 +304,12 @@ namespace ts {
let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
if (resolved) {
if (!options.preserveSymlinks) {
resolved = { ...resolved, fileName: realPath(resolved.fileName, host, traceEnabled) };
}
const { fileName, packageId } = resolved;
const resolvedFileName = options.preserveSymlinks ? fileName : realPath(fileName, host, traceEnabled);
if (traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved.fileName, primary);
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFileName, primary);
}
resolvedTypeReferenceDirective = { primary, resolvedFileName: resolved.fileName, packageId: resolved.packageId };
resolvedTypeReferenceDirective = { primary, resolvedFileName, packageId, isExternalLibraryImport: pathContainsNodeModules(fileName) };
}
return { resolvedTypeReferenceDirective, failedLookupLocations };
@@ -310,7 +320,7 @@ namespace ts {
if (traceEnabled) {
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
}
return forEach(typeRoots, typeRoot => {
return firstDefined(typeRoots, typeRoot => {
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName);
const candidateDirectory = getDirectoryPath(candidate);
const directoryExists = directoryProbablyExists(candidateDirectory, host);
@@ -337,15 +347,16 @@ namespace ts {
if (traceEnabled) {
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
}
let result: SearchResult<Resolved> | undefined;
let result: Resolved | undefined;
if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) {
result = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined);
const searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined);
result = searchResult && searchResult.value;
}
else {
const { path: candidate } = normalizePathAndParts(combinePaths(initialLocationForSecondaryLookup, typeReferenceDirectiveName));
result = toSearchResult(nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true));
result = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true);
}
const resolvedFile = resolvedTypeScriptOnly(result && result.value);
const resolvedFile = resolvedTypeScriptOnly(result);
if (!resolvedFile && traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
}
@@ -409,7 +420,7 @@ namespace ts {
* This assumes that any module id will have the same resolution for sibling files located in the same folder.
*/
export interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache {
getOrCreateCacheForDirectory(directoryName: string): Map<ResolvedModuleWithFailedLookupLocations>;
getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): Map<ResolvedModuleWithFailedLookupLocations>;
}
/**
@@ -417,7 +428,7 @@ namespace ts {
* We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive.
*/
export interface NonRelativeModuleNameResolutionCache {
getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache;
getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache;
}
export interface PerModuleNameCache {
@@ -427,40 +438,78 @@ namespace ts {
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache {
return createModuleResolutionCacheWithMaps(
createMap<Map<ResolvedModuleWithFailedLookupLocations>>(),
createMap<PerModuleNameCache>(),
createCacheWithRedirects(),
createCacheWithRedirects(),
currentDirectory,
getCanonicalFileName
);
}
/*@internal*/
export interface CacheWithRedirects<T> {
ownMap: Map<T>;
redirectsMap: Map<Map<T>>;
getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): Map<T>;
clear(): void;
}
/*@internal*/
export function createCacheWithRedirects<T>(): CacheWithRedirects<T> {
const ownMap: Map<T> = createMap();
const redirectsMap: Map<Map<T>> = createMap();
return {
ownMap,
redirectsMap,
getOrCreateMapOfCacheRedirects,
clear
};
function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined) {
if (!redirectedReference) {
return ownMap;
}
const path = redirectedReference.sourceFile.path;
let redirects = redirectsMap.get(path);
if (!redirects) {
redirects = createMap();
redirectsMap.set(path, redirects);
}
return redirects;
}
function clear() {
ownMap.clear();
redirectsMap.clear();
}
}
/*@internal*/
export function createModuleResolutionCacheWithMaps(
directoryToModuleNameMap: Map<Map<ResolvedModuleWithFailedLookupLocations>>,
moduleNameToDirectoryMap: Map<PerModuleNameCache>,
directoryToModuleNameMap: CacheWithRedirects<Map<ResolvedModuleWithFailedLookupLocations>>,
moduleNameToDirectoryMap: CacheWithRedirects<PerModuleNameCache>,
currentDirectory: string,
getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache {
return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName };
function getOrCreateCacheForDirectory(directoryName: string) {
function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference) {
const path = toPath(directoryName, currentDirectory, getCanonicalFileName);
let perFolderCache = directoryToModuleNameMap.get(path);
if (!perFolderCache) {
perFolderCache = createMap<ResolvedModuleWithFailedLookupLocations>();
directoryToModuleNameMap.set(path, perFolderCache);
}
return perFolderCache;
return getOrCreateCache<Map<ResolvedModuleWithFailedLookupLocations>>(directoryToModuleNameMap, redirectedReference, path, createMap);
}
function getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache {
function getOrCreateCacheForModuleName(nonRelativeModuleName: string, redirectedReference?: ResolvedProjectReference): PerModuleNameCache {
Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName));
let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName);
if (!perModuleNameCache) {
perModuleNameCache = createPerModuleNameCache();
moduleNameToDirectoryMap.set(nonRelativeModuleName, perModuleNameCache);
return getOrCreateCache(moduleNameToDirectoryMap, redirectedReference, nonRelativeModuleName, createPerModuleNameCache);
}
function getOrCreateCache<T>(cacheWithRedirects: CacheWithRedirects<T>, redirectedReference: ResolvedProjectReference | undefined, key: string, create: () => T): T {
const cache = cacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference);
let result = cache.get(key);
if (!result) {
result = create();
cache.set(key, result);
}
return perModuleNameCache;
return result;
}
function createPerModuleNameCache(): PerModuleNameCache {
@@ -542,13 +591,19 @@ namespace ts {
return perFolderCache && perFolderCache.get(moduleName);
}
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(compilerOptions, host);
if (redirectedReference) {
compilerOptions = redirectedReference.commandLine.options;
}
if (traceEnabled) {
trace(host, Diagnostics.Resolving_module_0_from_1, moduleName, containingFile);
if (redirectedReference) {
trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName);
}
}
const containingDirectory = getDirectoryPath(containingFile);
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference);
let result = perFolderCache && perFolderCache.get(moduleName);
if (result) {
@@ -572,10 +627,10 @@ namespace ts {
switch (moduleResolution) {
case ModuleResolutionKind.NodeJs:
result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache);
result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
break;
case ModuleResolutionKind.Classic:
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache);
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
break;
default:
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
@@ -585,7 +640,7 @@ namespace ts {
perFolderCache.set(moduleName, result);
if (!isExternalModuleNameRelative(moduleName)) {
// put result in per-module name cache
cache!.getOrCreateCacheForModuleName(moduleName).set(containingDirectory, result);
cache!.getOrCreateCacheForModuleName(moduleName, redirectedReference).set(containingDirectory, result);
}
}
}
@@ -675,6 +730,9 @@ namespace ts {
function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
state: ModuleResolutionState): Resolved | undefined {
const resolved = tryLoadModuleUsingPathsIfEligible(extensions, moduleName, loader, state);
if (resolved) return resolved.value;
if (!isExternalModuleNameRelative(moduleName)) {
return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, state);
}
@@ -683,6 +741,17 @@ namespace ts {
}
}
function tryLoadModuleUsingPathsIfEligible(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState) {
const { baseUrl, paths } = state.compilerOptions;
if (baseUrl && paths && !pathIsRelative(moduleName)) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName);
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
return tryLoadModuleUsingPaths(extensions, moduleName, baseUrl, paths, loader, /*onlyRecordFailures*/ false, state);
}
}
function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
state: ModuleResolutionState): Resolved | undefined {
@@ -761,22 +830,13 @@ namespace ts {
}
function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined {
const { baseUrl, paths } = state.compilerOptions;
const { baseUrl } = state.compilerOptions;
if (!baseUrl) {
return undefined;
}
if (state.traceEnabled) {
trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName);
}
if (paths) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
const resolved = tryLoadModuleUsingPaths(extensions, moduleName, baseUrl, paths, loader, /*onlyRecordFailures*/ false, state);
if (resolved) {
return resolved.value;
}
}
const candidate = normalizePath(combinePaths(baseUrl, moduleName));
if (state.traceEnabled) {
trace(state.host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, baseUrl, candidate);
@@ -804,25 +864,27 @@ namespace ts {
return resolvedModule && resolvedModule.resolvedFileName;
}
const jsOnlyExtensions = [Extensions.JavaScript];
const tsExtensions = [Extensions.TypeScript, Extensions.JavaScript];
const tsPlusJsonExtensions = [...tsExtensions, Extensions.Json];
const tsconfigExtensions = [Extensions.TSConfig];
function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
return nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, jsOnlyExtensions, /*redirectedReferences*/ undefined);
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false);
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
/* @internal */ export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations; // tslint:disable-line unified-signatures
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, lookupConfig ? tsconfigExtensions : (compilerOptions.resolveJsonModule ? tsPlusJsonExtensions : tsExtensions), redirectedReference);
}
function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, jsOnly: boolean): ResolvedModuleWithFailedLookupLocations {
function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, extensions: Extensions[], redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(compilerOptions, host);
const failedLookupLocations: string[] = [];
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations };
const result = jsOnly ?
tryResolve(Extensions.JavaScript) :
(tryResolve(Extensions.TypeScript) ||
tryResolve(Extensions.JavaScript) ||
(compilerOptions.resolveJsonModule ? tryResolve(Extensions.Json) : undefined));
const result = forEach(extensions, ext => tryResolve(ext));
if (result && result.value) {
const { resolved, isExternalLibraryImport } = result.value;
return createResolvedModuleWithFailedLookupLocations(resolved, isExternalLibraryImport, failedLookupLocations);
@@ -833,14 +895,14 @@ namespace ts {
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ true);
const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, state);
if (resolved) {
return toSearchResult({ resolved, isExternalLibraryImport: stringContains(resolved.path, nodeModulesPathPart) });
return toSearchResult({ resolved, isExternalLibraryImport: pathContainsNodeModules(resolved.path) });
}
if (!isExternalModuleNameRelative(moduleName)) {
if (traceEnabled) {
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]);
}
const resolved = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache);
const resolved = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference);
if (!resolved) return undefined;
let resolvedValue = resolved.value;
@@ -910,6 +972,10 @@ namespace ts {
/*@internal*/
export const nodeModulesPathPart = "/node_modules/";
/*@internal*/
export function pathContainsNodeModules(path: string): boolean {
return stringContains(path, nodeModulesPathPart);
}
/**
* This will be called on the successfully resolved path from `loadModuleFromFile`.
@@ -966,9 +1032,9 @@ namespace ts {
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
*/
function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
if (extensions === Extensions.Json) {
if (extensions === Extensions.Json || extensions === Extensions.TSConfig) {
const extensionLess = tryRemoveExtension(candidate, Extension.Json);
return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, onlyRecordFailures, state);
return (extensionLess === undefined && extensions === Extensions.Json) ? undefined : tryAddingExtensions(extensionLess || candidate, extensions, onlyRecordFailures, state);
}
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
@@ -1006,6 +1072,7 @@ namespace ts {
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts);
case Extensions.JavaScript:
return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
case Extensions.TSConfig:
case Extensions.Json:
return tryExtension(Extension.Json);
}
@@ -1103,11 +1170,27 @@ namespace ts {
}
function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, jsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined {
const packageFile = jsonContent && (extensions !== Extensions.JavaScript && extensions !== Extensions.Json
? readPackageJsonTypesFields(jsonContent, candidate, state) ||
// When resolving typescript modules, try resolving using main field as well
(extensions === Extensions.TypeScript ? readPackageJsonMainField(jsonContent, candidate, state) : undefined)
: readPackageJsonMainField(jsonContent, candidate, state));
let packageFile: string | undefined;
if (jsonContent) {
switch (extensions) {
case Extensions.JavaScript:
case Extensions.Json:
packageFile = readPackageJsonMainField(jsonContent, candidate, state);
break;
case Extensions.TypeScript:
// When resolving typescript modules, try resolving using main field as well
packageFile = readPackageJsonTypesFields(jsonContent, candidate, state) || readPackageJsonMainField(jsonContent, candidate, state);
break;
case Extensions.DtsOnly:
packageFile = readPackageJsonTypesFields(jsonContent, candidate, state);
break;
case Extensions.TSConfig:
packageFile = readPackageJsonTSConfigField(jsonContent, candidate, state);
break;
default:
return Debug.assertNever(extensions);
}
}
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => {
const fromFile = tryFile(candidate, onlyRecordFailures, state);
@@ -1129,7 +1212,7 @@ namespace ts {
const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined;
const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host);
const indexPath = combinePaths(candidate, "index");
const indexPath = combinePaths(candidate, extensions === Extensions.TSConfig ? "tsconfig" : "index");
if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) {
const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false);
@@ -1160,6 +1243,7 @@ namespace ts {
switch (extensions) {
case Extensions.JavaScript:
return extension === Extension.Js || extension === Extension.Jsx;
case Extensions.TSConfig:
case Extensions.Json:
return extension === Extension.Json;
case Extensions.TypeScript:
@@ -1178,17 +1262,17 @@ namespace ts {
return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) };
}
function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult<Resolved> {
return loadModuleFromNearestNodeModulesDirectoryWorker(extensions, moduleName, directory, state, /*typesScopeOnly*/ false, cache);
function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
return loadModuleFromNearestNodeModulesDirectoryWorker(extensions, moduleName, directory, state, /*typesScopeOnly*/ false, cache, redirectedReference);
}
function loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName: string, directory: string, state: ModuleResolutionState): SearchResult<Resolved> {
// Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly.
return loadModuleFromNearestNodeModulesDirectoryWorker(Extensions.DtsOnly, moduleName, directory, state, /*typesScopeOnly*/ true, /*cache*/ undefined);
return loadModuleFromNearestNodeModulesDirectoryWorker(Extensions.DtsOnly, moduleName, directory, state, /*typesScopeOnly*/ true, /*cache*/ undefined, /*redirectedReference*/ undefined);
}
function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult<Resolved> {
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName);
function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, redirectedReference);
return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => {
if (getBaseFileName(ancestorDirectory) !== "node_modules") {
const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, ancestorDirectory, state);
@@ -1211,7 +1295,7 @@ namespace ts {
if (packageResult) {
return packageResult;
}
if (extensions !== Extensions.JavaScript && extensions !== Extensions.Json) {
if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) {
const nodeModulesAtTypes = combinePaths(nodeModulesFolder, "@types");
let nodeModulesAtTypesExists = nodeModulesFolderExists;
if (nodeModulesFolderExists && !directoryProbablyExists(nodeModulesAtTypes, state.host)) {
@@ -1356,7 +1440,7 @@ namespace ts {
}
}
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache): ResolvedModuleWithFailedLookupLocations {
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(compilerOptions, host);
const failedLookupLocations: string[] = [];
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations };
@@ -1373,7 +1457,7 @@ namespace ts {
}
if (!isExternalModuleNameRelative(moduleName)) {
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName);
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, redirectedReference);
// Climb up parent directories looking for a module.
const resolved = forEachAncestorDirectory(containingDirectory, directory => {
const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, state);
+7 -3
View File
@@ -260,6 +260,9 @@ namespace ts.moduleSpecifiers {
}
function tryGetModuleNameAsNodeModule(moduleFileName: string, { getCanonicalFileName, sourceDirectory }: Info, host: ModuleSpecifierResolutionHost, options: CompilerOptions): string | undefined {
if (!host.fileExists || !host.readFile) {
return undefined;
}
const parts: NodeModulePathParts = getNodeModulePathParts(moduleFileName)!;
if (!parts) {
return undefined;
@@ -267,8 +270,8 @@ namespace ts.moduleSpecifiers {
const packageRootPath = moduleFileName.substring(0, parts.packageRootIndex);
const packageJsonPath = combinePaths(packageRootPath, "package.json");
const packageJsonContent = host.fileExists!(packageJsonPath)
? JSON.parse(host.readFile!(packageJsonPath)!)
const packageJsonContent = host.fileExists(packageJsonPath)
? JSON.parse(host.readFile(packageJsonPath)!)
: undefined;
const versionPaths = packageJsonContent && packageJsonContent.typesVersions
? getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions)
@@ -325,11 +328,12 @@ namespace ts.moduleSpecifiers {
}
function tryGetAnyFileFromPath(host: ModuleSpecifierResolutionHost, path: string) {
if (!host.fileExists) return;
// We check all js, `node` and `json` extensions in addition to TS, since node module resolution would also choose those over the directory
const extensions = getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: ScriptKind.JSON }]);
for (const e of extensions) {
const fullPath = path + e;
if (host.fileExists!(fullPath)) { // TODO: GH#18217
if (host.fileExists(fullPath)) {
return fullPath;
}
}
+76 -77
View File
@@ -1482,7 +1482,15 @@ namespace ts {
// which would be a candidate for improved error reporting.
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
case ParsingContext.ObjectLiteralMembers:
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
switch (token()) {
case SyntaxKind.OpenBracketToken:
case SyntaxKind.AsteriskToken:
case SyntaxKind.DotDotDotToken:
case SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`)
return true;
default:
return isLiteralPropertyName();
}
case ParsingContext.RestProperties:
return isLiteralPropertyName();
case ParsingContext.ObjectBindingElements:
@@ -1510,8 +1518,10 @@ namespace ts {
case ParsingContext.TypeParameters:
return isIdentifier();
case ParsingContext.ArrayLiteralMembers:
if (token() === SyntaxKind.CommaToken) {
return true;
switch (token()) {
case SyntaxKind.CommaToken:
case SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`)
return true;
}
// falls through
case ParsingContext.ArgumentExpressions:
@@ -2237,8 +2247,7 @@ namespace ts {
function parseLiteralLikeNode(kind: SyntaxKind): LiteralExpression | LiteralLikeNode {
const node = <LiteralExpression>createNode(kind);
const text = scanner.getTokenValue();
node.text = text;
node.text = scanner.getTokenValue();
if (scanner.hasExtendedUnicodeEscape()) {
node.hasExtendedUnicodeEscape = true;
@@ -2882,8 +2891,9 @@ namespace ts {
return finishNode(node);
}
function nextTokenIsNumericLiteral() {
return nextToken() === SyntaxKind.NumericLiteral;
function nextTokenIsNumericOrBigIntLiteral() {
nextToken();
return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral;
}
function parseNonArrayType(): TypeNode {
@@ -2892,6 +2902,7 @@ namespace ts {
case SyntaxKind.UnknownKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.UndefinedKeyword:
@@ -2912,11 +2923,12 @@ namespace ts {
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return parseLiteralTypeNode();
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();
@@ -2950,6 +2962,7 @@ namespace ts {
case SyntaxKind.UnknownKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.UniqueKeyword:
@@ -2967,6 +2980,7 @@ namespace ts {
case SyntaxKind.NewKeyword:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.ObjectKeyword:
@@ -2980,7 +2994,7 @@ namespace ts {
case SyntaxKind.FunctionKeyword:
return !inStartOfParameter;
case SyntaxKind.MinusToken:
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral);
case SyntaxKind.OpenParenToken:
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
// or something that starts a type. We don't want to consider things like '(1)' a type.
@@ -3205,6 +3219,7 @@ namespace ts {
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
@@ -4614,6 +4629,7 @@ namespace ts {
function parsePrimaryExpression(): PrimaryExpression {
switch (token()) {
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return parseLiteralNode();
@@ -4728,8 +4744,7 @@ namespace ts {
// CoverInitializedName[Yield] :
// IdentifierReference[?Yield] Initializer[In, ?Yield]
// this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern
const isShorthandPropertyAssignment =
tokenIsIdentifier && (token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EqualsToken);
const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken);
if (isShorthandPropertyAssignment) {
node.kind = SyntaxKind.ShorthandPropertyAssignment;
const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
@@ -5130,7 +5145,7 @@ namespace ts {
function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
nextToken();
return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
}
function isDeclaration(): boolean {
@@ -6308,7 +6323,7 @@ namespace ts {
// Parses out a JSDoc type expression.
export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression {
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression);
const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
result.type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
@@ -6512,7 +6527,7 @@ namespace ts {
}
}
function skipWhitespaceOrAsterisk(next: () => void): void {
function skipWhitespaceOrAsterisk(): void {
if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range
@@ -6527,58 +6542,56 @@ namespace ts {
else if (token() === SyntaxKind.AsteriskToken) {
precedingLineBreak = false;
}
next();
nextJSDocToken();
}
}
function parseTag(indent: number) {
Debug.assert(token() === SyntaxKind.AtToken);
const atToken = <AtToken>createNode(SyntaxKind.AtToken, scanner.getTokenPos());
atToken.end = scanner.getTextPos();
const start = scanner.getTokenPos();
nextJSDocToken();
// Use 'nextToken' instead of 'nextJsDocToken' so we can parse a type like 'number' in `@enum number`
const tagName = parseJSDocIdentifierName(/*message*/ undefined, nextToken);
skipWhitespaceOrAsterisk(nextToken);
const tagName = parseJSDocIdentifierName(/*message*/ undefined);
skipWhitespaceOrAsterisk();
let tag: JSDocTag | undefined;
switch (tagName.escapedText) {
case "augments":
case "extends":
tag = parseAugmentsTag(atToken, tagName);
tag = parseAugmentsTag(start, tagName);
break;
case "class":
case "constructor":
tag = parseClassTag(atToken, tagName);
tag = parseClassTag(start, tagName);
break;
case "this":
tag = parseThisTag(atToken, tagName);
tag = parseThisTag(start, tagName);
break;
case "enum":
tag = parseEnumTag(atToken, tagName);
tag = parseEnumTag(start, tagName);
break;
case "arg":
case "argument":
case "param":
return parseParameterOrPropertyTag(atToken, tagName, PropertyLikeParse.Parameter, indent);
return parseParameterOrPropertyTag(start, tagName, PropertyLikeParse.Parameter, indent);
case "return":
case "returns":
tag = parseReturnTag(atToken, tagName);
tag = parseReturnTag(start, tagName);
break;
case "template":
tag = parseTemplateTag(atToken, tagName);
tag = parseTemplateTag(start, tagName);
break;
case "type":
tag = parseTypeTag(atToken, tagName);
tag = parseTypeTag(start, tagName);
break;
case "typedef":
tag = parseTypedefTag(atToken, tagName, indent);
tag = parseTypedefTag(start, tagName, indent);
break;
case "callback":
tag = parseCallbackTag(atToken, tagName, indent);
tag = parseCallbackTag(start, tagName, indent);
break;
default:
tag = parseUnknownTag(atToken, tagName);
tag = parseUnknownTag(start, tagName);
break;
}
@@ -6661,9 +6674,8 @@ namespace ts {
return comments.length === 0 ? undefined : comments.join("");
}
function parseUnknownTag(atToken: AtToken, tagName: Identifier) {
const result = <JSDocTag>createNode(SyntaxKind.JSDocTag, atToken.pos);
result.atToken = atToken;
function parseUnknownTag(start: number, tagName: Identifier) {
const result = <JSDocTag>createNode(SyntaxKind.JSDocTag, start);
result.tagName = tagName;
return finishNode(result);
}
@@ -6683,7 +6695,7 @@ namespace ts {
}
function tryParseTypeExpression(): JSDocTypeExpression | undefined {
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
}
@@ -6720,10 +6732,10 @@ namespace ts {
}
}
function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag {
function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag {
let typeExpression = tryParseTypeExpression();
let isNameFirst = !typeExpression;
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
skipWhitespace();
@@ -6733,15 +6745,14 @@ namespace ts {
}
const result = target === PropertyLikeParse.Property ?
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos) :
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, atToken.pos);
const comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos);
<JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, start) :
<JSDocParameterTag>createNode(SyntaxKind.JSDocParameterTag, start);
const comment = parseTagComments(indent + scanner.getStartPos() - start);
const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target, indent);
if (nestedTypeLiteral) {
typeExpression = nestedTypeLiteral;
isNameFirst = true;
}
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = typeExpression;
result.name = name;
@@ -6775,33 +6786,30 @@ namespace ts {
}
}
function parseReturnTag(atToken: AtToken, tagName: Identifier): JSDocReturnTag {
function parseReturnTag(start: number, tagName: Identifier): JSDocReturnTag {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocReturnTag)) {
parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
}
const result = <JSDocReturnTag>createNode(SyntaxKind.JSDocReturnTag, atToken.pos);
result.atToken = atToken;
const result = <JSDocReturnTag>createNode(SyntaxKind.JSDocReturnTag, start);
result.tagName = tagName;
result.typeExpression = tryParseTypeExpression();
return finishNode(result);
}
function parseTypeTag(atToken: AtToken, tagName: Identifier): JSDocTypeTag {
function parseTypeTag(start: number, tagName: Identifier): JSDocTypeTag {
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTypeTag)) {
parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
}
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
result.atToken = atToken;
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, start);
result.tagName = tagName;
result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
return finishNode(result);
}
function parseAugmentsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsTag {
const result = <JSDocAugmentsTag>createNode(SyntaxKind.JSDocAugmentsTag, atToken.pos);
result.atToken = atToken;
function parseAugmentsTag(start: number, tagName: Identifier): JSDocAugmentsTag {
const result = <JSDocAugmentsTag>createNode(SyntaxKind.JSDocAugmentsTag, start);
result.tagName = tagName;
result.class = parseExpressionWithTypeArgumentsForAugments();
return finishNode(result);
@@ -6830,37 +6838,33 @@ namespace ts {
return node;
}
function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
tag.atToken = atToken;
function parseClassTag(start: number, tagName: Identifier): JSDocClassTag {
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, start);
tag.tagName = tagName;
return finishNode(tag);
}
function parseThisTag(atToken: AtToken, tagName: Identifier): JSDocThisTag {
const tag = <JSDocThisTag>createNode(SyntaxKind.JSDocThisTag, atToken.pos);
tag.atToken = atToken;
function parseThisTag(start: number, tagName: Identifier): JSDocThisTag {
const tag = <JSDocThisTag>createNode(SyntaxKind.JSDocThisTag, start);
tag.tagName = tagName;
tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
skipWhitespace();
return finishNode(tag);
}
function parseEnumTag(atToken: AtToken, tagName: Identifier): JSDocEnumTag {
const tag = <JSDocEnumTag>createNode(SyntaxKind.JSDocEnumTag, atToken.pos);
tag.atToken = atToken;
function parseEnumTag(start: number, tagName: Identifier): JSDocEnumTag {
const tag = <JSDocEnumTag>createNode(SyntaxKind.JSDocEnumTag, start);
tag.tagName = tagName;
tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
skipWhitespace();
return finishNode(tag);
}
function parseTypedefTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocTypedefTag {
function parseTypedefTag(start: number, tagName: Identifier, indent: number): JSDocTypedefTag {
const typeExpression = tryParseTypeExpression();
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
typedefTag.atToken = atToken;
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, start);
typedefTag.tagName = tagName;
typedefTag.fullName = parseJSDocTypeNameWithNamespace();
typedefTag.name = getJSDocTypeAliasName(typedefTag.fullName);
@@ -6873,7 +6877,6 @@ namespace ts {
let child: JSDocTypeTag | JSDocPropertyTag | false;
let jsdocTypeLiteral: JSDocTypeLiteral | undefined;
let childTypeTag: JSDocTypeTag | undefined;
const start = atToken.pos;
while (child = tryParse(() => parseChildPropertyTag(indent))) {
if (!jsdocTypeLiteral) {
jsdocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, start);
@@ -6927,9 +6930,8 @@ namespace ts {
return typeNameOrNamespaceName;
}
function parseCallbackTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocCallbackTag {
const callbackTag = createNode(SyntaxKind.JSDocCallbackTag, atToken.pos) as JSDocCallbackTag;
callbackTag.atToken = atToken;
function parseCallbackTag(start: number, tagName: Identifier, indent: number): JSDocCallbackTag {
const callbackTag = createNode(SyntaxKind.JSDocCallbackTag, start) as JSDocCallbackTag;
callbackTag.tagName = tagName;
callbackTag.fullName = parseJSDocTypeNameWithNamespace();
callbackTag.name = getJSDocTypeAliasName(callbackTag.fullName);
@@ -6937,7 +6939,6 @@ namespace ts {
callbackTag.comment = parseTagComments(indent);
let child: JSDocParameterTag | false;
const start = scanner.getStartPos();
const jsdocSignature = createNode(SyntaxKind.JSDocSignature, start) as JSDocSignature;
jsdocSignature.parameters = [];
while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) {
@@ -7025,8 +7026,7 @@ namespace ts {
function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
Debug.assert(token() === SyntaxKind.AtToken);
const atToken = <AtToken>createNode(SyntaxKind.AtToken);
atToken.end = scanner.getTextPos();
const start = scanner.getStartPos();
nextJSDocToken();
const tagName = parseJSDocIdentifierName();
@@ -7034,7 +7034,7 @@ namespace ts {
let t: PropertyLikeParse;
switch (tagName.escapedText) {
case "type":
return target === PropertyLikeParse.Property && parseTypeTag(atToken, tagName);
return target === PropertyLikeParse.Property && parseTypeTag(start, tagName);
case "prop":
case "property":
t = PropertyLikeParse.Property;
@@ -7050,10 +7050,10 @@ namespace ts {
if (!(target & t)) {
return false;
}
return parseParameterOrPropertyTag(atToken, tagName, target, indent);
return parseParameterOrPropertyTag(start, tagName, target, indent);
}
function parseTemplateTag(atToken: AtToken, tagName: Identifier): JSDocTemplateTag {
function parseTemplateTag(start: number, tagName: Identifier): JSDocTemplateTag {
// the template tag looks like '@template {Constraint} T,U,V'
let constraint: JSDocTypeExpression | undefined;
if (token() === SyntaxKind.OpenBraceToken) {
@@ -7071,8 +7071,7 @@ namespace ts {
typeParameters.push(typeParameter);
} while (parseOptionalJsdoc(SyntaxKind.CommaToken));
const result = <JSDocTemplateTag>createNode(SyntaxKind.JSDocTemplateTag, atToken.pos);
result.atToken = atToken;
const result = <JSDocTemplateTag>createNode(SyntaxKind.JSDocTemplateTag, start);
result.tagName = tagName;
result.constraint = constraint;
result.typeParameters = createNodeArray(typeParameters, typeParametersPos);
@@ -7110,7 +7109,7 @@ namespace ts {
return entity;
}
function parseJSDocIdentifierName(message?: DiagnosticMessage, next: () => void = nextJSDocToken): Identifier {
function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier {
if (!tokenIsIdentifierOrKeyword(token())) {
return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected);
}
@@ -7121,7 +7120,7 @@ namespace ts {
result.escapedText = escapeLeadingUnderscores(scanner.getTokenText());
finishNode(result, end);
next();
nextJSDocToken();
return result;
}
}
+326 -201
View File
@@ -198,7 +198,7 @@ namespace ts {
};
}
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
const diagnostics = [
...program.getConfigFileParsingDiagnostics(),
...program.getOptionsDiagnostics(cancellationToken),
@@ -406,7 +406,7 @@ namespace ts {
}
}
function loadWithLocalCache<T>(names: string[], containingFile: string, loader: (name: string, containingFile: string) => T): T[] {
function loadWithLocalCache<T>(names: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] {
if (names.length === 0) {
return [];
}
@@ -418,7 +418,7 @@ namespace ts {
result = cache.get(name)!;
}
else {
cache.set(name, result = loader(name, containingFile));
cache.set(name, result = loader(name, containingFile, redirectedReference));
}
resolutions.push(result);
}
@@ -454,6 +454,8 @@ namespace ts {
return false;
}
let seenResolvedRefs: ResolvedProjectReference[] | undefined;
// If project references dont match
if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) {
return false;
@@ -485,7 +487,7 @@ namespace ts {
function sourceFileNotUptoDate(sourceFile: SourceFile) {
return !sourceFileVersionUptoDate(sourceFile) ||
hasInvalidatedResolution(sourceFile.resolvedPath);
hasInvalidatedResolution(sourceFile.path);
}
function sourceFileVersionUptoDate(sourceFile: SourceFile) {
@@ -496,11 +498,29 @@ namespace ts {
if (!projectReferenceIsEqualTo(oldRef, newRef)) {
return false;
}
const oldResolvedRef = program!.getResolvedProjectReferences()![index];
return resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef);
}
function resolvedProjectReferenceUptoDate(oldResolvedRef: ResolvedProjectReference | undefined, oldRef: ProjectReference): boolean {
if (oldResolvedRef) {
if (contains(seenResolvedRefs, oldResolvedRef)) {
// Assume true
return true;
}
// If sourceFile for the oldResolvedRef existed, check the version for uptodate
return sourceFileVersionUptoDate(oldResolvedRef.sourceFile);
if (!sourceFileVersionUptoDate(oldResolvedRef.sourceFile)) {
return false;
}
// Add to seen before checking the referenced paths of this config file
(seenResolvedRefs || (seenResolvedRefs = [])).push(oldResolvedRef);
// If child project references are upto date, this project reference is uptodate
return !forEach(oldResolvedRef.references, (childResolvedRef, index) =>
!resolvedProjectReferenceUptoDate(childResolvedRef, oldResolvedRef.commandLine.projectReferences![index]));
}
// In old program, not able to resolve project reference path,
// so if config file doesnt exist, it is uptodate.
return !fileExists(resolveProjectReferencePath(oldRef));
@@ -574,12 +594,12 @@ namespace ts {
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: UnderscoreEscapedMap<true>;
let modifiedFilePaths: Path[] | undefined;
const ambientModuleNameToUnmodifiedFileName = createMap<string>();
const cachedSemanticDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective | undefined>();
let fileProcessingDiagnostics = createDiagnosticCollection();
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
@@ -610,18 +630,17 @@ namespace ts {
const programDiagnostics = createDiagnosticCollection();
const currentDirectory = host.getCurrentDirectory();
const supportedExtensions = getSupportedExtensions(options);
const supportedExtensionsWithJsonIfResolveJsonModule = options.resolveJsonModule ? [...supportedExtensions, Extension.Json] : undefined;
const supportedExtensionsWithJsonIfResolveJsonModule = getSuppoertedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions);
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createMap<boolean>();
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | null | undefined;
let _referencesArrayLiteralSyntax: ArrayLiteralExpression | null | undefined;
let moduleResolutionCache: ModuleResolutionCache | undefined;
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[]) => ResolvedModuleFull[];
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) => ResolvedModuleFull[];
const hasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
if (host.resolveModuleNames) {
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(resolved => {
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames, redirectedReference).map(resolved => {
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
return resolved as ResolvedModuleFull;
@@ -633,17 +652,17 @@ namespace ts {
}
else {
moduleResolutionCache = createModuleResolutionCache(currentDirectory, x => host.getCanonicalFileName(x));
const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule!; // TODO: GH#18217
resolveModuleNamesWorker = (moduleNames, containingFile) => loadWithLocalCache<ResolvedModuleFull>(Debug.assertEachDefined(moduleNames), containingFile, loader);
const loader = (moduleName: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache, redirectedReference).resolvedModule!; // TODO: GH#18217
resolveModuleNamesWorker = (moduleNames, containingFile, _reusedNames, redirectedReference) => loadWithLocalCache<ResolvedModuleFull>(Debug.assertEachDefined(moduleNames), containingFile, redirectedReference, loader);
}
let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference) => (ResolvedTypeReferenceDirective | undefined)[];
if (host.resolveTypeReferenceDirectives) {
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile);
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile, redirectedReference);
}
else {
const loader = (typesRef: string, containingFile: string) => resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective!; // TODO: GH#18217
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile) => loadWithLocalCache<ResolvedTypeReferenceDirective>(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader);
const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective(typesRef, containingFile, options, host, redirectedReference).resolvedTypeReferenceDirective!; // TODO: GH#18217
resolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference) => loadWithLocalCache<ResolvedTypeReferenceDirective>(Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, loader);
}
// Map from a stringified PackageId to the source file with that id.
@@ -662,8 +681,8 @@ namespace ts {
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap<SourceFile>() : undefined;
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
let resolvedProjectReferences: (ResolvedProjectReference | undefined)[] | undefined = projectReferences ? [] : undefined;
let projectReferenceRedirects: ParsedCommandLine[] | undefined;
let resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined;
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
@@ -672,16 +691,18 @@ namespace ts {
processingOtherFiles = [];
if (projectReferences) {
for (const ref of projectReferences) {
const parsedRef = parseProjectReferenceConfigFile(ref);
resolvedProjectReferences!.push(parsedRef);
if (parsedRef) {
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
if (out) {
const dtsOutfile = changeExtension(out, ".d.ts");
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
if (!resolvedProjectReferences) {
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
}
if (rootNames.length) {
for (const parsedRef of resolvedProjectReferences) {
if (parsedRef) {
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
if (out) {
const dtsOutfile = changeExtension(out, ".d.ts");
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
}
}
addProjectReferenceRedirects(parsedRef.commandLine);
}
}
}
@@ -689,7 +710,7 @@ namespace ts {
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false));
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
const typeReferences: string[] = rootNames.length ? getAutomaticTypeDirectiveNames(options, host) : emptyArray;
if (typeReferences.length) {
// This containingFilename needs to match with the one used in managed-side
@@ -705,7 +726,7 @@ namespace ts {
// - The '--noLib' flag is used.
// - A 'no-default-lib' reference comment is encountered in
// processing the root files.
if (!skipDefaultLib) {
if (rootNames.length && !skipDefaultLib) {
// If '--lib' is not specified, include default library file according to '--target'
// otherwise, using options specified in '--lib' instead of '--target' default library file
const defaultLibraryFileName = getDefaultLibraryFileName();
@@ -732,10 +753,18 @@ namespace ts {
if (oldProgram && host.onReleaseOldSourceFile) {
const oldSourceFiles = oldProgram.getSourceFiles();
for (const oldSourceFile of oldSourceFiles) {
if (!getSourceFile(oldSourceFile.path) || shouldCreateNewSourceFile) {
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions());
const newFile = getSourceFileByPath(oldSourceFile.resolvedPath);
if (shouldCreateNewSourceFile || !newFile ||
// old file wasnt redirect but new file is
(oldSourceFile.resolvedPath === oldSourceFile.path && newFile.resolvedPath !== oldSourceFile.path)) {
host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path));
}
}
oldProgram.forEachResolvedProjectReference((resolvedProjectReference, resolvedProjectReferencePath) => {
if (resolvedProjectReference && !getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) {
host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false);
}
});
}
// unconditionally set oldProgram to undefined to prevent it from being captured in closure
@@ -778,7 +807,10 @@ namespace ts {
getResolvedModuleWithFailedLookupLocationsFromCache,
getProjectReferences,
getResolvedProjectReferences,
getProjectReferenceRedirect
getProjectReferenceRedirect,
getResolvedProjectReferenceToRedirect,
getResolvedProjectReferenceByPath,
forEachResolvedProjectReference
};
verifyCompilerOptions();
@@ -850,21 +882,14 @@ namespace ts {
return classifiableNames;
}
interface OldProgramState {
program: Program | undefined;
oldSourceFile: SourceFile | undefined;
/** The collection of paths modified *since* the old program. */
modifiedFilePaths: Path[] | undefined;
}
function resolveModuleNamesReusingOldState(moduleNames: string[], containingFile: string, file: SourceFile, oldProgramState: OldProgramState) {
function resolveModuleNamesReusingOldState(moduleNames: string[], containingFile: string, file: SourceFile) {
if (structuralIsReused === 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, containingFile);
return resolveModuleNamesWorker(moduleNames, containingFile, /*reusedNames*/ undefined, getResolvedProjectReferenceToRedirect(file.originalFileName));
}
const oldSourceFile = oldProgramState.program && oldProgramState.program.getSourceFile(containingFile);
const oldSourceFile = oldProgram && oldProgram.getSourceFile(containingFile);
if (oldSourceFile !== file && file.resolvedModules) {
// `file` was created for the new program.
//
@@ -928,7 +953,7 @@ namespace ts {
}
}
else {
resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, oldProgramState);
resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName);
}
if (resolvesToAmbientModuleInNonModifiedFile) {
@@ -941,7 +966,7 @@ namespace ts {
}
const resolutions = unknownModuleNames && unknownModuleNames.length
? resolveModuleNamesWorker(unknownModuleNames, containingFile, reusedNames)
? resolveModuleNamesWorker(unknownModuleNames, containingFile, reusedNames, getResolvedProjectReferenceToRedirect(file.originalFileName))
: emptyArray;
// Combine results of resolutions and predicted results
@@ -971,12 +996,9 @@ namespace ts {
// If we change our policy of rechecking failed lookups on each program create,
// we should adjust the value returned here.
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, oldProgramState: OldProgramState): boolean {
if (!oldProgramState.program) {
return false;
}
const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile!, moduleName); // TODO: GH#18217
const resolvedFile = resolutionToFile && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName);
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string): boolean {
const resolutionToFile = getResolvedModule(oldSourceFile!, moduleName);
const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) {
// 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.
@@ -986,21 +1008,43 @@ namespace ts {
}
// at least one of declarations should come from non-modified source file
const firstUnmodifiedFile = oldProgramState.program.getSourceFiles().find(
f => !contains(oldProgramState.modifiedFilePaths, f.path) && contains(f.ambientModuleNames, moduleName)
);
const unmodifiedFile = ambientModuleNameToUnmodifiedFileName.get(moduleName);
if (!firstUnmodifiedFile) {
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, firstUnmodifiedFile.fileName);
trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, unmodifiedFile);
}
return true;
}
}
function canReuseProjectReferences(): boolean {
return !forEachProjectReference(
oldProgram!.getProjectReferences(),
oldProgram!.getResolvedProjectReferences(),
(oldResolvedRef, index, parent) => {
const newRef = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
const newResolvedRef = parseProjectReferenceConfigFile(newRef);
if (oldResolvedRef) {
// Resolved project reference has gone missing or changed
return !newResolvedRef || newResolvedRef.sourceFile !== oldResolvedRef.sourceFile;
}
else {
// A previously-unresolved reference may be resolved now
return newResolvedRef !== undefined;
}
},
(oldProjectReferences, parent) => {
// If array of references is changed, we cant resue old program
const newReferences = parent ? getResolvedProjectReferenceByPath(parent.sourceFile.path)!.commandLine.projectReferences : projectReferences;
return !arrayIsEqualTo(oldProjectReferences, newReferences, projectReferenceIsEqualTo);
}
);
}
function tryReuseStructureFromOldProgram(): StructureIsReused {
if (!oldProgram) {
return StructureIsReused.Not;
@@ -1026,43 +1070,15 @@ namespace ts {
}
// Check if any referenced project tsconfig files are different
// If array of references is changed, we cant resue old program
const oldProjectReferences = oldProgram.getProjectReferences();
if (!arrayIsEqualTo(oldProjectReferences!, projectReferences, projectReferenceIsEqualTo)) {
if (!canReuseProjectReferences()) {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
// Check the json files for the project references
const oldRefs = oldProgram.getResolvedProjectReferences();
if (projectReferences) {
// Resolved project referenced should be array if projectReferences provided are array
Debug.assert(!!oldRefs);
for (let i = 0; i < projectReferences.length; i++) {
const oldRef = oldRefs![i];
const newRef = parseProjectReferenceConfigFile(projectReferences[i]);
if (oldRef) {
if (!newRef || newRef.sourceFile !== oldRef.sourceFile) {
// Resolved project reference has gone missing or changed
return oldProgram.structureIsReused = StructureIsReused.Not;
}
}
else {
// A previously-unresolved reference may be resolved now
if (newRef !== undefined) {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
}
}
}
else {
// Resolved project referenced should be undefined if projectReferences is undefined
Debug.assert(!oldRefs);
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
}
// check if program source files has changed in the way that can affect structure of the program
const newSourceFiles: SourceFile[] = [];
const filePaths: Path[] = [];
const modifiedSourceFiles: { oldFile: SourceFile, newFile: SourceFile }[] = [];
oldProgram.structureIsReused = StructureIsReused.Completely;
@@ -1115,7 +1131,6 @@ namespace ts {
newSourceFile.originalFileName = oldSourceFile.originalFileName;
newSourceFile.resolvedPath = oldSourceFile.resolvedPath;
newSourceFile.fileName = oldSourceFile.fileName;
filePaths.push(newSourceFile.path);
const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
if (packageName !== undefined) {
@@ -1188,14 +1203,20 @@ namespace ts {
return oldProgram.structureIsReused;
}
modifiedFilePaths = modifiedSourceFiles.map(f => f.newFile.path);
const modifiedFiles = modifiedSourceFiles.map(f => f.oldFile);
for (const oldFile of oldSourceFiles) {
if (!contains(modifiedFiles, oldFile)) {
for (const moduleName of oldFile.ambientModuleNames) {
ambientModuleNameToUnmodifiedFileName.set(moduleName, oldFile.fileName);
}
}
}
// try to verify results of module resolution
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.originalFileName, currentDirectory);
if (resolveModuleNamesWorker) {
const moduleNames = getModuleNames(newSourceFile);
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState);
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile);
// ensure that module resolution results are still correct
const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo);
if (resolutionsChanged) {
@@ -1209,7 +1230,7 @@ namespace ts {
if (resolveTypeReferenceDirectiveNamesWorker) {
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
const typesReferenceDirectives = map(newSourceFile.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase());
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath);
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath, getResolvedProjectReferenceToRedirect(newSourceFile.originalFileName));
// ensure that types resolutions are still correct
const resolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo);
if (resolutionsChanged) {
@@ -1233,11 +1254,12 @@ namespace ts {
missingFilePaths = oldProgram.getMissingFilePaths();
// update fileName -> file mapping
for (let i = 0; i < newSourceFiles.length; i++) {
filesByName.set(filePaths[i], newSourceFiles[i]);
for (const newSourceFile of newSourceFiles) {
const filePath = newSourceFile.path;
addFileToFilesByName(newSourceFile, filePath, newSourceFile.resolvedPath);
// Set the file as found during node modules search if it was found that way in old progra,
if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i])!)) {
sourceFilesFoundSearchingNodeModules.set(filePaths[i], true);
if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePath)!)) {
sourceFilesFoundSearchingNodeModules.set(filePath, true);
}
}
@@ -1248,14 +1270,6 @@ namespace ts {
fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile.newFile);
}
resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives();
resolvedProjectReferences = oldProgram.getResolvedProjectReferences();
if (resolvedProjectReferences) {
resolvedProjectReferences.forEach(ref => {
if (ref) {
addProjectReferenceRedirects(ref.commandLine);
}
});
}
sourceFileToPackageName = oldProgram.sourceFileToPackageName;
redirectTargetsMap = oldProgram.redirectTargetsMap;
@@ -1805,18 +1819,29 @@ namespace ts {
return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
}
function getOptionsDiagnostics(): Diagnostic[] {
function getOptionsDiagnostics(): SortedReadonlyArray<Diagnostic> {
return sortAndDeduplicateDiagnostics(concatenate(
fileProcessingDiagnostics.getGlobalDiagnostics(),
concatenate(
programDiagnostics.getGlobalDiagnostics(),
options.configFile ? programDiagnostics.getDiagnostics(options.configFile.fileName) : []
getOptionsDiagnosticsOfConfigFile()
)
));
}
function getGlobalDiagnostics(): Diagnostic[] {
return sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice());
function getOptionsDiagnosticsOfConfigFile() {
if (!options.configFile) { return emptyArray; }
let diagnostics = programDiagnostics.getDiagnostics(options.configFile.fileName);
forEachResolvedProjectReference(resolvedRef => {
if (resolvedRef) {
diagnostics = concatenate(diagnostics, programDiagnostics.getDiagnostics(resolvedRef.sourceFile.fileName));
}
});
return diagnostics;
}
function getGlobalDiagnostics(): SortedReadonlyArray<Diagnostic> {
return rootNames.length ? sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray<Diagnostic>;
}
function getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic> {
@@ -1866,12 +1891,9 @@ namespace ts {
for (const node of file.statements) {
collectModuleReferences(node, /*inAmbientModule*/ false);
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
collectDynamicImportOrRequireCalls(node);
}
}
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
collectDynamicImportOrRequireCalls(file.endOfFileToken);
collectDynamicImportOrRequireCalls(file);
}
file.imports = imports || emptyArray;
@@ -1923,25 +1945,38 @@ namespace ts {
}
}
function collectDynamicImportOrRequireCalls(node: Node): void {
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
imports = append(imports, node.arguments[0]);
}
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
imports = append(imports, node.arguments[0] as StringLiteralLike);
}
else if (isLiteralImportTypeNode(node)) {
imports = append(imports, node.argument.literal);
}
collectDynamicImportOrRequireCallsForEachChild(node);
if (hasJSDocNodes(node)) {
forEach(node.jsDoc, collectDynamicImportOrRequireCallsForEachChild);
function collectDynamicImportOrRequireCalls(file: SourceFile) {
const r = /import|require/g;
while (r.exec(file.text) !== null) {
const node = getNodeAtPosition(file, r.lastIndex);
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
imports = append(imports, node.arguments[0]);
}
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
imports = append(imports, node.arguments[0] as StringLiteralLike);
}
else if (isLiteralImportTypeNode(node)) {
imports = append(imports, node.argument.literal);
}
}
}
function collectDynamicImportOrRequireCallsForEachChild(node: Node) {
forEachChild(node, collectDynamicImportOrRequireCalls);
/** Returns a token if position is in [start-of-leading-trivia, end), includes JSDoc only in JS files */
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
let current: Node = sourceFile;
const getContainingChild = (child: Node) => {
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
return child;
}
};
while (true) {
const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
if (!child) {
return current;
}
current = child;
}
}
}
@@ -1965,7 +2000,7 @@ namespace ts {
refFile?: SourceFile): SourceFile | undefined {
if (hasExtension(fileName)) {
if (!options.allowNonTsExtensions && !forEach(supportedExtensionsWithJsonIfResolveJsonModule || supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) {
if (!options.allowNonTsExtensions && !forEach(supportedExtensionsWithJsonIfResolveJsonModule, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) {
if (fail) fail(Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + supportedExtensions.join("', '") + "'");
return undefined;
}
@@ -2031,6 +2066,7 @@ namespace ts {
redirect.resolvedPath = resolvedPath;
redirect.originalFileName = originalFileName;
redirect.redirectInfo = { redirectTarget, unredirected };
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
Object.defineProperties(redirect, {
id: {
get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; },
@@ -2088,7 +2124,7 @@ namespace ts {
return file;
}
let redirectedPath: string | undefined;
let redirectedPath: Path | undefined;
if (refFile) {
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
@@ -2122,7 +2158,7 @@ namespace ts {
// Instead of creating a duplicate, just redirect to the existing one.
const dupFile = createRedirectSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName); // TODO: GH#18217
redirectTargetsMap.add(fileFromPackageId.path, fileName);
filesByName.set(path, dupFile);
addFileToFilesByName(dupFile, path, redirectedPath);
sourceFileToPackageName.set(path, packageId.name);
processingOtherFiles!.push(dupFile);
return dupFile;
@@ -2133,11 +2169,7 @@ namespace ts {
sourceFileToPackageName.set(path, packageId.name);
}
}
filesByName.set(path, file);
if (redirectedPath) {
filesByName.set(redirectedPath, file);
}
addFileToFilesByName(file, path, redirectedPath);
if (file) {
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
@@ -2180,27 +2212,109 @@ namespace ts {
return file;
}
function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
filesByName.set(path, file);
if (redirectedPath) {
filesByName.set(redirectedPath, file);
}
}
function getProjectReferenceRedirect(fileName: string): string | undefined {
// Ignore dts or any of the non ts files
if (!projectReferenceRedirects || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
return undefined;
}
// If this file is produced by a referenced project, we need to rewrite it to
// look in the output folder of the referenced project rather than the input
return forEach(projectReferenceRedirects, referencedProject => {
const referencedProject = getResolvedProjectReferenceToRedirect(fileName);
if (!referencedProject) {
return undefined;
}
const out = referencedProject.commandLine.options.outFile || referencedProject.commandLine.options.out;
return out ?
changeExtension(out, Extension.Dts) :
getOutputDeclarationFileName(fileName, referencedProject.commandLine);
}
/**
* Get the referenced project if the file is input file from that reference project
*/
function getResolvedProjectReferenceToRedirect(fileName: string) {
return forEachResolvedProjectReference((referencedProject, referenceProjectPath) => {
// not input file from the referenced project, ignore
if (!contains(referencedProject.fileNames, fileName, isSameFile)) {
if (!referencedProject ||
toPath(options.configFilePath!) === referenceProjectPath ||
!contains(referencedProject.commandLine.fileNames, fileName, isSameFile)) {
return undefined;
}
const out = referencedProject.options.outFile || referencedProject.options.out;
return out ?
changeExtension(out, Extension.Dts) :
getOutputDeclarationFileName(fileName, referencedProject);
return referencedProject;
});
}
function forEachResolvedProjectReference<T>(
cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined
): T | undefined {
return forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
const resolvedRefPath = toPath(resolveProjectReferencePath(ref));
return cb(resolvedRef, resolvedRefPath);
});
}
function forEachProjectReference<T>(
projectReferences: ReadonlyArray<ProjectReference> | undefined,
resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined,
cbResolvedRef: (resolvedRef: ResolvedProjectReference | undefined, index: number, parent: ResolvedProjectReference | undefined) => T | undefined,
cbRef?: (projectReferences: ReadonlyArray<ProjectReference> | undefined, parent: ResolvedProjectReference | undefined) => T | undefined
): T | undefined {
let seenResolvedRefs: ResolvedProjectReference[] | undefined;
return worker(projectReferences, resolvedProjectReferences, /*parent*/ undefined, cbResolvedRef, cbRef);
function worker(
projectReferences: ReadonlyArray<ProjectReference> | undefined,
resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined,
parent: ResolvedProjectReference | undefined,
cbResolvedRef: (resolvedRef: ResolvedProjectReference | undefined, index: number, parent: ResolvedProjectReference | undefined) => T | undefined,
cbRef?: (projectReferences: ReadonlyArray<ProjectReference> | undefined, parent: ResolvedProjectReference | undefined) => T | undefined,
): T | undefined {
// Visit project references first
if (cbRef) {
const result = cbRef(projectReferences, parent);
if (result) { return result; }
}
return forEach(resolvedProjectReferences, (resolvedRef, index) => {
if (contains(seenResolvedRefs, resolvedRef)) {
// ignore recursives
return undefined;
}
const result = cbResolvedRef(resolvedRef, index, parent);
if (result) {
return result;
}
if (!resolvedRef) return undefined;
(seenResolvedRefs || (seenResolvedRefs = [])).push(resolvedRef);
return worker(resolvedRef.commandLine.projectReferences, resolvedRef.references, resolvedRef, cbResolvedRef, cbRef);
});
}
}
function getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined {
if (!projectReferenceRedirects) {
return undefined;
}
return projectReferenceRedirects.get(projectReferencePath) || undefined;
}
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
@@ -2215,7 +2329,7 @@ namespace ts {
return;
}
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName);
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName, getResolvedProjectReferenceToRedirect(file.originalFileName));
for (let i = 0; i < typeDirectives.length; i++) {
const ref = file.typeReferenceDirectives[i];
@@ -2227,7 +2341,7 @@ namespace ts {
}
}
function processTypeReferenceDirective(typeReferenceDirective: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective,
function processTypeReferenceDirective(typeReferenceDirective: string, resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective,
refFile?: SourceFile, refPos?: number, refEnd?: number): void {
// If we already found this library as a primary reference - nothing to do
@@ -2237,6 +2351,8 @@ namespace ts {
}
let saveResolution = true;
if (resolvedTypeReferenceDirective) {
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth++;
if (resolvedTypeReferenceDirective.primary) {
// resolved from the primary path
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
@@ -2265,6 +2381,8 @@ namespace ts {
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
}
}
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth--;
}
else {
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217
@@ -2310,8 +2428,7 @@ namespace ts {
if (file.imports.length || file.moduleAugmentations.length) {
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
const moduleNames = getModuleNames(file);
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file, oldProgramState);
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file);
Debug.assert(resolutions.length === moduleNames.length);
for (let i = 0; i < moduleNames.length; i++) {
const resolution = resolutions[i];
@@ -2388,22 +2505,37 @@ namespace ts {
return allFilesBelongToPath;
}
function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined {
function parseProjectReferenceConfigFile(ref: ProjectReference): ResolvedProjectReference | undefined {
if (!projectReferenceRedirects) {
projectReferenceRedirects = createMap<ResolvedProjectReference | false>();
}
// The actual filename (i.e. add "/tsconfig.json" if necessary)
const refPath = resolveProjectReferencePath(ref);
const sourceFilePath = toPath(refPath);
const fromCache = projectReferenceRedirects.get(sourceFilePath);
if (fromCache !== undefined) {
return fromCache || undefined;
}
// An absolute path pointing to the containing directory of the config file
const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory());
const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined;
addFileToFilesByName(sourceFile, sourceFilePath, /*redirectedPath*/ undefined);
if (sourceFile === undefined) {
projectReferenceRedirects.set(sourceFilePath, false);
return undefined;
}
sourceFile.path = toPath(refPath);
sourceFile.path = sourceFilePath;
sourceFile.resolvedPath = sourceFilePath;
sourceFile.originalFileName = refPath;
const commandLine = parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath);
return { commandLine, sourceFile };
}
function addProjectReferenceRedirects(referencedProject: ParsedCommandLine) {
(projectReferenceRedirects || (projectReferenceRedirects = [])).push(referencedProject);
const resolvedRef: ResolvedProjectReference = { commandLine, sourceFile };
projectReferenceRedirects.set(sourceFilePath, resolvedRef);
if (commandLine.projectReferences) {
resolvedRef.references = commandLine.projectReferences.map(parseProjectReferenceConfigFile);
}
return resolvedRef;
}
function verifyCompilerOptions() {
@@ -2448,30 +2580,7 @@ namespace ts {
}
}
if (projectReferences) {
for (let i = 0; i < projectReferences.length; i++) {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences![i] && resolvedProjectReferences![i]!.commandLine.options;
if (resolvedRefOpts === undefined) {
createDiagnosticForReference(i, Diagnostics.File_0_does_not_exist, ref.path);
continue;
}
if (!resolvedRefOpts.composite) {
createDiagnosticForReference(i, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
}
if (ref.prepend) {
const out = resolvedRefOpts.outFile || resolvedRefOpts.out;
if (out) {
if (!host.fileExists(out)) {
createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path);
}
}
else {
createDiagnosticForReference(i, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path);
}
}
}
}
verifyProjectReferences();
// List of collected files is complete; validate exhautiveness if this is a project with a file list
if (options.composite) {
@@ -2560,13 +2669,13 @@ namespace ts {
const languageVersion = options.target || ScriptTarget.ES3;
const outFile = options.outFile || options.out;
const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !f.isDeclarationFile ? f : undefined);
const firstNonAmbientExternalModuleSourceFile = find(files, f => isExternalModule(f) && !f.isDeclarationFile);
if (options.isolatedModules) {
if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) {
createDiagnosticForOptionName(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target");
}
const firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !f.isDeclarationFile ? f : undefined);
const firstNonExternalModuleSourceFile = find(files, f => !isExternalModule(f) && !f.isDeclarationFile && f.scriptKind !== ScriptKind.JSON);
if (firstNonExternalModuleSourceFile) {
const span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile);
programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided));
@@ -2609,7 +2718,7 @@ namespace ts {
const dir = getCommonSourceDirectory();
// If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure
if (options.outDir && dir === "" && forEach(files, file => getRootLength(file.fileName) > 1)) {
if (options.outDir && dir === "" && files.some(file => getRootLength(file.fileName) > 1)) {
createDiagnosticForOptionName(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir");
}
}
@@ -2689,6 +2798,36 @@ namespace ts {
}
}
function verifyProjectReferences() {
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
const parentFile = parent && parent.sourceFile as JsonSourceFile;
if (!resolvedRef) {
createDiagnosticForReference(parentFile, index, Diagnostics.File_0_not_found, ref.path);
return;
}
const options = resolvedRef.commandLine.options;
if (!options.composite) {
// ok to not have composite if the current program is container only
const inputs = parent ? parent.commandLine.fileNames : rootNames;
if (inputs.length) {
createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
}
}
if (ref.prepend) {
const out = options.outFile || options.out;
if (out) {
if (!host.fileExists(out)) {
createDiagnosticForReference(parentFile, index, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path);
}
}
else {
createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path);
}
}
});
}
function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, arg0: string | number, arg1: string | number, arg2?: string | number) {
let needCompilerDiagnostic = true;
const pathsSyntax = getOptionPathsSyntax();
@@ -2745,10 +2884,11 @@ namespace ts {
createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0);
}
function createDiagnosticForReference(index: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number) {
const referencesSyntax = getProjectReferencesSyntax();
function createDiagnosticForReference(sourceFile: JsonSourceFile | undefined, index: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number) {
const referencesSyntax = firstDefined(getTsConfigPropArray(sourceFile || options.configFile, "references"),
property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined);
if (referencesSyntax && referencesSyntax.elements.length > index) {
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, referencesSyntax.elements[index], message, arg0, arg1));
programDiagnostics.add(createDiagnosticForNodeInSourceFile(sourceFile || options.configFile!, referencesSyntax.elements[index], message, arg0, arg1));
}
else {
programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1));
@@ -2765,22 +2905,6 @@ namespace ts {
}
}
function getProjectReferencesSyntax(): ArrayLiteralExpression | null {
if (_referencesArrayLiteralSyntax === undefined) {
_referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword
if (options.configFile) {
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile)!; // TODO: GH#18217
for (const prop of getPropertyAssignment(jsonObjectLiteral, "references")) {
if (isArrayLiteralExpression(prop.initializer)) {
_referencesArrayLiteralSyntax = prop.initializer;
break;
}
}
}
}
return _referencesArrayLiteralSyntax;
}
function getCompilerOptionsObjectLiteralSyntax() {
if (_compilerOptionsObjectLiteralSyntax === undefined) {
_compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword
@@ -2862,7 +2986,8 @@ namespace ts {
readFile: f => host.readFile(f),
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
getCurrentDirectory: () => host.getCurrentDirectory(),
onUnRecoverableConfigFileDiagnostic: () => undefined
onUnRecoverableConfigFileDiagnostic: () => undefined,
trace: host.trace ? (s) => host.trace!(s) : undefined
};
}
+74 -44
View File
@@ -5,12 +5,13 @@ namespace ts {
startRecordingFilesWithChangedResolutions(): void;
finishRecordingFilesWithChangedResolutions(): Path[] | undefined;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[];
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference): (ResolvedModuleFull | undefined)[];
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): CachedResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
invalidateResolutionOfFile(filePath: Path): void;
removeResolutionsOfFile(filePath: Path): void;
removeResolutionsFromProjectReferenceRedirects(filePath: Path): void;
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<ReadonlyArray<string>>): void;
createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution;
@@ -68,7 +69,10 @@ namespace ts {
dir: string;
dirPath: Path;
nonRecursive?: boolean;
ignore?: true;
}
export function isPathInNodeModulesStartingWithDot(path: Path) {
return stringContains(path, "/node_modules/.");
}
export const maxNumberOfFilesToIterateForInvalidation = 256;
@@ -79,7 +83,7 @@ namespace ts {
export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootDirForResolution: string | undefined, logChangesWhenResolvingModule: boolean): ResolutionCache {
let filesWithChangedSetOfUnresolvedImports: Path[] | undefined;
let filesWithInvalidatedResolutions: Map<true> | undefined;
let filesWithInvalidatedNonRelativeUnresolvedImports: Map<ReadonlyArray<string>> | undefined;
let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyMap<ReadonlyArray<string>> | undefined;
let allFilesHaveInvalidatedResolution = false;
const nonRelativeExternalModuleResolutions = createMultiMap<ResolutionWithFailedLookupLocations>();
@@ -90,17 +94,17 @@ namespace ts {
// The key in the map is source file's path.
// The values are Map of resolutions with key being name lookedup.
const resolvedModuleNames = createMap<Map<CachedResolvedModuleWithFailedLookupLocations>>();
const perDirectoryResolvedModuleNames = createMap<Map<CachedResolvedModuleWithFailedLookupLocations>>();
const nonRelaticeModuleNameCache = createMap<PerModuleNameCache>();
const perDirectoryResolvedModuleNames: CacheWithRedirects<Map<CachedResolvedModuleWithFailedLookupLocations>> = createCacheWithRedirects();
const nonRelativeModuleNameCache: CacheWithRedirects<PerModuleNameCache> = createCacheWithRedirects();
const moduleResolutionCache = createModuleResolutionCacheWithMaps(
perDirectoryResolvedModuleNames,
nonRelaticeModuleNameCache,
nonRelativeModuleNameCache,
getCurrentDirectory(),
resolutionHost.getCanonicalFileName
);
const resolvedTypeReferenceDirectives = createMap<Map<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
const perDirectoryResolvedTypeReferenceDirectives = createMap<Map<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
const perDirectoryResolvedTypeReferenceDirectives: CacheWithRedirects<Map<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations>> = createCacheWithRedirects();
/**
* These are the extensions that failed lookup files will have by default,
@@ -128,6 +132,7 @@ namespace ts {
resolveModuleNames,
getResolvedModuleWithFailedLookupLocationsFromCache,
resolveTypeReferenceDirectives,
removeResolutionsFromProjectReferenceRedirects,
removeResolutionsOfFile,
invalidateResolutionOfFile,
setFilesWithInvalidatedNonRelativeUnresolvedImports,
@@ -199,7 +204,7 @@ namespace ts {
function clearPerDirectoryResolutions() {
perDirectoryResolvedModuleNames.clear();
nonRelaticeModuleNameCache.clear();
nonRelativeModuleNameCache.clear();
perDirectoryResolvedTypeReferenceDirectives.clear();
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions);
nonRelativeExternalModuleResolutions.clear();
@@ -217,8 +222,8 @@ namespace ts {
});
}
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): CachedResolvedModuleWithFailedLookupLocations {
const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache);
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): CachedResolvedModuleWithFailedLookupLocations {
const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference);
// return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
if (!resolutionHost.getGlobalCache) {
return primaryResult;
@@ -240,41 +245,52 @@ namespace ts {
}
function resolveNamesWithLocalCache<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
names: string[],
names: ReadonlyArray<string>,
containingFile: string,
redirectedReference: ResolvedProjectReference | undefined,
cache: Map<Map<T>>,
perDirectoryCache: Map<Map<T>>,
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => T,
perDirectoryCacheWithRedirects: CacheWithRedirects<Map<T>>,
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference) => T,
getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName<T, R>,
reusedNames: string[] | undefined,
logChanges: boolean): R[] {
shouldRetryResolution: (t: T) => boolean,
reusedNames: ReadonlyArray<string> | undefined,
logChanges: boolean): (R | undefined)[] {
const path = resolutionHost.toPath(containingFile);
const resolutionsInFile = cache.get(path) || cache.set(path, createMap()).get(path)!;
const dirPath = getDirectoryPath(path);
const perDirectoryCache = perDirectoryCacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference);
let perDirectoryResolution = perDirectoryCache.get(dirPath);
if (!perDirectoryResolution) {
perDirectoryResolution = createMap();
perDirectoryCache.set(dirPath, perDirectoryResolution);
}
const resolvedModules: R[] = [];
const resolvedModules: (R | undefined)[] = [];
const compilerOptions = resolutionHost.getCompilationSettings();
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
// All the resolutions in this file are invalidated if this file wasnt resolved using same redirect
const program = resolutionHost.getCurrentProgram();
const oldRedirect = program && program.getResolvedProjectReferenceToRedirect(containingFile);
const unmatchedRedirects = oldRedirect ?
!redirectedReference || redirectedReference.sourceFile.path !== oldRedirect.sourceFile.path :
!!redirectedReference;
const seenNamesInFile = createMap<true>();
for (const name of names) {
let resolution = resolutionsInFile.get(name);
// Resolution is valid if it is present and not invalidated
if (!seenNamesInFile.has(name) &&
allFilesHaveInvalidatedResolution || !resolution || resolution.isInvalidated ||
allFilesHaveInvalidatedResolution || unmatchedRedirects || !resolution || resolution.isInvalidated ||
// If the name is unresolved import that was invalidated, recalculate
(hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && !getResolutionWithResolvedFileName(resolution))) {
(hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && shouldRetryResolution(resolution))) {
const existingResolution = resolution;
const resolutionInDirectory = perDirectoryResolution.get(name);
if (resolutionInDirectory) {
resolution = resolutionInDirectory;
}
else {
resolution = loader(name, containingFile, compilerOptions, resolutionHost);
resolution = loader(name, containingFile, compilerOptions, resolutionHost, redirectedReference);
perDirectoryResolution.set(name, resolution);
}
resolutionsInFile.set(name, resolution);
@@ -291,7 +307,7 @@ namespace ts {
}
Debug.assert(resolution !== undefined && !resolution.isInvalidated);
seenNamesInFile.set(name, true);
resolvedModules.push(getResolutionWithResolvedFileName(resolution)!); // TODO: GH#18217
resolvedModules.push(getResolutionWithResolvedFileName(resolution));
}
// Stop watching and remove the unused name
@@ -323,20 +339,22 @@ namespace ts {
}
}
function resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
function resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[] {
return resolveNamesWithLocalCache<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolvedTypeReferenceDirective>(
typeDirectiveNames, containingFile,
typeDirectiveNames, containingFile, redirectedReference,
resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives,
resolveTypeReferenceDirective, getResolvedTypeReferenceDirective,
/*shouldRetryResolution*/ resolution => resolution.resolvedTypeReferenceDirective === undefined,
/*reusedNames*/ undefined, /*logChanges*/ false
);
}
function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined): ResolvedModuleFull[] {
function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference): (ResolvedModuleFull | undefined)[] {
return resolveNamesWithLocalCache<CachedResolvedModuleWithFailedLookupLocations, ResolvedModuleFull>(
moduleNames, containingFile,
moduleNames, containingFile, redirectedReference,
resolvedModuleNames, perDirectoryResolvedModuleNames,
resolveModuleName, getResolvedModule,
/*shouldRetryResolution*/ resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension),
reusedNames, logChangesWhenResolvingModule
);
}
@@ -389,14 +407,7 @@ namespace ts {
return true;
}
function filterFSRootDirectoriesToWatch(watchPath: DirectoryOfFailedLookupWatch, dirPath: Path): DirectoryOfFailedLookupWatch {
if (!canWatchDirectory(dirPath)) {
watchPath.ignore = true;
}
return watchPath;
}
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch {
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch | undefined {
if (isInDirectoryPath(rootPath, failedLookupLocationPath)) {
// Ensure failed look up is normalized path
failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory());
@@ -418,16 +429,16 @@ namespace ts {
);
}
function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: Path) {
function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: Path): DirectoryOfFailedLookupWatch | undefined {
// If directory path contains node module, get the most parent node_modules directory for watching
while (stringContains(dirPath, nodeModulesPathPart)) {
while (pathContainsNodeModules(dirPath)) {
dir = getDirectoryPath(dir);
dirPath = getDirectoryPath(dirPath);
}
// If the directory is node_modules use it to watch, always watch it recursively
if (isNodeModulesDirectory(dirPath)) {
return filterFSRootDirectoriesToWatch({ dir, dirPath }, getDirectoryPath(dirPath));
return canWatchDirectory(getDirectoryPath(dirPath)) ? { dir, dirPath } : undefined;
}
let nonRecursive = true;
@@ -447,7 +458,7 @@ namespace ts {
}
}
return filterFSRootDirectoriesToWatch({ dir: subDirectory || dir, dirPath: subDirectoryPath || dirPath, nonRecursive }, dirPath);
return canWatchDirectory(dirPath) ? { dir: subDirectory || dir, dirPath: subDirectoryPath || dirPath, nonRecursive } : undefined;
}
function isPathWithDefaultFailedLookupExtension(path: Path) {
@@ -479,8 +490,9 @@ namespace ts {
let setAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const { dir, dirPath, nonRecursive, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
const toWatch = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (toWatch) {
const { dir, dirPath, nonRecursive } = toWatch;
// If the failed lookup location path is not one of the supported extensions,
// store it in the custom path
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
@@ -539,8 +551,9 @@ namespace ts {
let removeAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
const toWatch = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (toWatch) {
const { dirPath } = toWatch;
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
if (refCount) {
if (refCount === 1) {
@@ -594,6 +607,20 @@ namespace ts {
}
}
function removeResolutionsFromProjectReferenceRedirects(filePath: Path) {
if (!fileExtensionIs(filePath, Extension.Json)) { return; }
const program = resolutionHost.getCurrentProgram();
if (!program) { return; }
// If this file is input file for the referenced project, get it
const resolvedProjectReference = program.getResolvedProjectReferenceByPath(filePath);
if (!resolvedProjectReference) { return; }
// filePath is for the projectReference and the containing file is from this project reference, invalidate the resolution
resolvedProjectReference.commandLine.fileNames.forEach(f => removeResolutionsOfFile(resolutionHost.toPath(f)));
}
function removeResolutionsOfFile(filePath: Path) {
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath);
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath);
@@ -655,7 +682,7 @@ namespace ts {
);
}
function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: Map<ReadonlyArray<string>>) {
function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: ReadonlyMap<ReadonlyArray<string>>) {
Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined);
filesWithInvalidatedNonRelativeUnresolvedImports = filesMap;
}
@@ -668,6 +695,9 @@ namespace ts {
isChangedFailedLookupLocation = location => isInDirectoryPath(fileOrDirectoryPath, resolutionHost.toPath(location));
}
else {
// If something to do with folder/file starting with "." in node_modules folder, skip it
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return false;
// Some file or directory in the watching directory is created
// Return early if it does not have any of the watching extension or not the custom failed lookup path
const dirOfFileOrDirectory = getDirectoryPath(fileOrDirectoryPath);
@@ -712,8 +742,8 @@ namespace ts {
if (isInDirectoryPath(rootPath, typeRootPath)) {
return rootPath;
}
const { dirPath, ignore } = getDirectoryToWatchFromFailedLookupLocationDirectory(typeRoot, typeRootPath);
return !ignore && directoryWatchesOfFailedLookups.has(dirPath) ? dirPath : undefined;
const toWatch = getDirectoryToWatchFromFailedLookupLocationDirectory(typeRoot, typeRootPath);
return toWatch && directoryWatchesOfFailedLookups.has(toWatch.dirPath) ? toWatch.dirPath : undefined;
}
function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher {
+165 -138
View File
@@ -60,81 +60,88 @@ namespace ts {
tryScan<T>(callback: () => T): T;
}
const textToToken = createMapFromTemplate({
"abstract": SyntaxKind.AbstractKeyword,
"any": SyntaxKind.AnyKeyword,
"as": SyntaxKind.AsKeyword,
"boolean": SyntaxKind.BooleanKeyword,
"break": SyntaxKind.BreakKeyword,
"case": SyntaxKind.CaseKeyword,
"catch": SyntaxKind.CatchKeyword,
"class": SyntaxKind.ClassKeyword,
"continue": SyntaxKind.ContinueKeyword,
"const": SyntaxKind.ConstKeyword,
"constructor": SyntaxKind.ConstructorKeyword,
"debugger": SyntaxKind.DebuggerKeyword,
"declare": SyntaxKind.DeclareKeyword,
"default": SyntaxKind.DefaultKeyword,
"delete": SyntaxKind.DeleteKeyword,
"do": SyntaxKind.DoKeyword,
"else": SyntaxKind.ElseKeyword,
"enum": SyntaxKind.EnumKeyword,
"export": SyntaxKind.ExportKeyword,
"extends": SyntaxKind.ExtendsKeyword,
"false": SyntaxKind.FalseKeyword,
"finally": SyntaxKind.FinallyKeyword,
"for": SyntaxKind.ForKeyword,
"from": SyntaxKind.FromKeyword,
"function": SyntaxKind.FunctionKeyword,
"get": SyntaxKind.GetKeyword,
"if": SyntaxKind.IfKeyword,
"implements": SyntaxKind.ImplementsKeyword,
"import": SyntaxKind.ImportKeyword,
"in": SyntaxKind.InKeyword,
"infer": SyntaxKind.InferKeyword,
"instanceof": SyntaxKind.InstanceOfKeyword,
"interface": SyntaxKind.InterfaceKeyword,
"is": SyntaxKind.IsKeyword,
"keyof": SyntaxKind.KeyOfKeyword,
"let": SyntaxKind.LetKeyword,
"module": SyntaxKind.ModuleKeyword,
"namespace": SyntaxKind.NamespaceKeyword,
"never": SyntaxKind.NeverKeyword,
"new": SyntaxKind.NewKeyword,
"null": SyntaxKind.NullKeyword,
"number": SyntaxKind.NumberKeyword,
"object": SyntaxKind.ObjectKeyword,
"package": SyntaxKind.PackageKeyword,
"private": SyntaxKind.PrivateKeyword,
"protected": SyntaxKind.ProtectedKeyword,
"public": SyntaxKind.PublicKeyword,
"readonly": SyntaxKind.ReadonlyKeyword,
"require": SyntaxKind.RequireKeyword,
"global": SyntaxKind.GlobalKeyword,
"return": SyntaxKind.ReturnKeyword,
"set": SyntaxKind.SetKeyword,
"static": SyntaxKind.StaticKeyword,
"string": SyntaxKind.StringKeyword,
"super": SyntaxKind.SuperKeyword,
"switch": SyntaxKind.SwitchKeyword,
"symbol": SyntaxKind.SymbolKeyword,
"this": SyntaxKind.ThisKeyword,
"throw": SyntaxKind.ThrowKeyword,
"true": SyntaxKind.TrueKeyword,
"try": SyntaxKind.TryKeyword,
"type": SyntaxKind.TypeKeyword,
"typeof": SyntaxKind.TypeOfKeyword,
"undefined": SyntaxKind.UndefinedKeyword,
"unique": SyntaxKind.UniqueKeyword,
"unknown": SyntaxKind.UnknownKeyword,
"var": SyntaxKind.VarKeyword,
"void": SyntaxKind.VoidKeyword,
"while": SyntaxKind.WhileKeyword,
"with": SyntaxKind.WithKeyword,
"yield": SyntaxKind.YieldKeyword,
"async": SyntaxKind.AsyncKeyword,
"await": SyntaxKind.AwaitKeyword,
"of": SyntaxKind.OfKeyword,
const textToKeywordObj: MapLike<KeywordSyntaxKind> = {
abstract: SyntaxKind.AbstractKeyword,
any: SyntaxKind.AnyKeyword,
as: SyntaxKind.AsKeyword,
bigint: SyntaxKind.BigIntKeyword,
boolean: SyntaxKind.BooleanKeyword,
break: SyntaxKind.BreakKeyword,
case: SyntaxKind.CaseKeyword,
catch: SyntaxKind.CatchKeyword,
class: SyntaxKind.ClassKeyword,
continue: SyntaxKind.ContinueKeyword,
const: SyntaxKind.ConstKeyword,
["" + "constructor"]: SyntaxKind.ConstructorKeyword,
debugger: SyntaxKind.DebuggerKeyword,
declare: SyntaxKind.DeclareKeyword,
default: SyntaxKind.DefaultKeyword,
delete: SyntaxKind.DeleteKeyword,
do: SyntaxKind.DoKeyword,
else: SyntaxKind.ElseKeyword,
enum: SyntaxKind.EnumKeyword,
export: SyntaxKind.ExportKeyword,
extends: SyntaxKind.ExtendsKeyword,
false: SyntaxKind.FalseKeyword,
finally: SyntaxKind.FinallyKeyword,
for: SyntaxKind.ForKeyword,
from: SyntaxKind.FromKeyword,
function: SyntaxKind.FunctionKeyword,
get: SyntaxKind.GetKeyword,
if: SyntaxKind.IfKeyword,
implements: SyntaxKind.ImplementsKeyword,
import: SyntaxKind.ImportKeyword,
in: SyntaxKind.InKeyword,
infer: SyntaxKind.InferKeyword,
instanceof: SyntaxKind.InstanceOfKeyword,
interface: SyntaxKind.InterfaceKeyword,
is: SyntaxKind.IsKeyword,
keyof: SyntaxKind.KeyOfKeyword,
let: SyntaxKind.LetKeyword,
module: SyntaxKind.ModuleKeyword,
namespace: SyntaxKind.NamespaceKeyword,
never: SyntaxKind.NeverKeyword,
new: SyntaxKind.NewKeyword,
null: SyntaxKind.NullKeyword,
number: SyntaxKind.NumberKeyword,
object: SyntaxKind.ObjectKeyword,
package: SyntaxKind.PackageKeyword,
private: SyntaxKind.PrivateKeyword,
protected: SyntaxKind.ProtectedKeyword,
public: SyntaxKind.PublicKeyword,
readonly: SyntaxKind.ReadonlyKeyword,
require: SyntaxKind.RequireKeyword,
global: SyntaxKind.GlobalKeyword,
return: SyntaxKind.ReturnKeyword,
set: SyntaxKind.SetKeyword,
static: SyntaxKind.StaticKeyword,
string: SyntaxKind.StringKeyword,
super: SyntaxKind.SuperKeyword,
switch: SyntaxKind.SwitchKeyword,
symbol: SyntaxKind.SymbolKeyword,
this: SyntaxKind.ThisKeyword,
throw: SyntaxKind.ThrowKeyword,
true: SyntaxKind.TrueKeyword,
try: SyntaxKind.TryKeyword,
type: SyntaxKind.TypeKeyword,
typeof: SyntaxKind.TypeOfKeyword,
undefined: SyntaxKind.UndefinedKeyword,
unique: SyntaxKind.UniqueKeyword,
unknown: SyntaxKind.UnknownKeyword,
var: SyntaxKind.VarKeyword,
void: SyntaxKind.VoidKeyword,
while: SyntaxKind.WhileKeyword,
with: SyntaxKind.WithKeyword,
yield: SyntaxKind.YieldKeyword,
async: SyntaxKind.AsyncKeyword,
await: SyntaxKind.AwaitKeyword,
of: SyntaxKind.OfKeyword,
};
const textToKeyword = createMapFromTemplate(textToKeywordObj);
const textToToken = createMapFromTemplate<SyntaxKind>({
...textToKeywordObj,
"{": SyntaxKind.OpenBraceToken,
"}": SyntaxKind.CloseBraceToken,
"(": SyntaxKind.OpenParenToken,
@@ -913,7 +920,7 @@ namespace ts {
return result + text.substring(start, pos);
}
function scanNumber(): string {
function scanNumber(): {type: SyntaxKind, value: string} {
const start = pos;
const mainFragment = scanNumberFragment();
let decimalFragment: string | undefined;
@@ -937,18 +944,29 @@ namespace ts {
end = pos;
}
}
let result: string;
if (tokenFlags & TokenFlags.ContainsSeparator) {
let result = mainFragment;
result = mainFragment;
if (decimalFragment) {
result += "." + decimalFragment;
}
if (scientificFragment) {
result += scientificFragment;
}
return "" + +result;
}
else {
return "" + +(text.substring(start, end)); // No need to use all the fragments; no _ removal needed
result = text.substring(start, end); // No need to use all the fragments; no _ removal needed
}
if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) {
return {
type: SyntaxKind.NumericLiteral,
value: "" + +result // if value is not an integer, it can be safely coerced to a number
};
}
else {
tokenValue = result;
const type = checkBigIntSuffix(); // if value is an integer, check whether it is a bigint
return { type, value: tokenValue };
}
}
@@ -965,24 +983,24 @@ namespace ts {
* returning -1 if the given number is unavailable.
*/
function scanExactNumberOfHexDigits(count: number, canHaveSeparators: boolean): number {
return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators);
const valueString = scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators);
return valueString ? parseInt(valueString, 16) : -1;
}
/**
* Scans as many hexadecimal digits as are available in the text,
* returning -1 if the given number of digits was unavailable.
* returning "" if the given number of digits was unavailable.
*/
function scanMinimumNumberOfHexDigits(count: number, canHaveSeparators: boolean): number {
function scanMinimumNumberOfHexDigits(count: number, canHaveSeparators: boolean): string {
return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true, canHaveSeparators);
}
function scanHexDigits(minCount: number, scanAsManyAsPossible: boolean, canHaveSeparators: boolean): number {
let digits = 0;
let value = 0;
function scanHexDigits(minCount: number, scanAsManyAsPossible: boolean, canHaveSeparators: boolean): string {
let valueChars: number[] = [];
let allowSeparator = false;
let isPreviousTokenSeparator = false;
while (digits < minCount || scanAsManyAsPossible) {
const ch = text.charCodeAt(pos);
while (valueChars.length < minCount || scanAsManyAsPossible) {
let ch = text.charCodeAt(pos);
if (canHaveSeparators && ch === CharacterCodes._) {
tokenFlags |= TokenFlags.ContainsSeparator;
if (allowSeparator) {
@@ -999,29 +1017,25 @@ namespace ts {
continue;
}
allowSeparator = canHaveSeparators;
if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
value = value * 16 + ch - CharacterCodes._0;
if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {
ch += CharacterCodes.a - CharacterCodes.A; // standardize hex literals to lowercase
}
else if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {
value = value * 16 + ch - CharacterCodes.A + 10;
}
else if (ch >= CharacterCodes.a && ch <= CharacterCodes.f) {
value = value * 16 + ch - CharacterCodes.a + 10;
}
else {
else if (!((ch >= CharacterCodes._0 && ch <= CharacterCodes._9) ||
(ch >= CharacterCodes.a && ch <= CharacterCodes.f)
)) {
break;
}
valueChars.push(ch);
pos++;
digits++;
isPreviousTokenSeparator = false;
}
if (digits < minCount) {
value = -1;
if (valueChars.length < minCount) {
valueChars = [];
}
if (text.charCodeAt(pos - 1) === CharacterCodes._) {
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
}
return value;
return String.fromCharCode(...valueChars);
}
function scanString(jsxAttributeString = false): string {
@@ -1201,7 +1215,8 @@ namespace ts {
}
function scanExtendedUnicodeEscape(): string {
const escapedValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1;
let isInvalidExtendedEscape = false;
// Validate the value of the digit
@@ -1288,28 +1303,25 @@ namespace ts {
return result;
}
function getIdentifierToken(): SyntaxKind {
function getIdentifierToken(): SyntaxKind.Identifier | KeywordSyntaxKind {
// Reserved words are between 2 and 11 characters long and start with a lowercase letter
const len = tokenValue.length;
if (len >= 2 && len <= 11) {
const ch = tokenValue.charCodeAt(0);
if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) {
token = textToToken.get(tokenValue)!;
if (token !== undefined) {
return token;
const keyword = textToKeyword.get(tokenValue);
if (keyword !== undefined) {
return token = keyword;
}
}
}
return token = SyntaxKind.Identifier;
}
function scanBinaryOrOctalDigits(base: number): number {
Debug.assert(base === 2 || base === 8, "Expected either base 2 or base 8");
let value = 0;
function scanBinaryOrOctalDigits(base: 2 | 8): string {
let value = "";
// For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b.
// Similarly valid octalIntegerLiteral must have at least one octal digit following o or O.
let numberOfDigits = 0;
let separatorAllowed = false;
let isPreviousTokenSeparator = false;
while (true) {
@@ -1331,27 +1343,42 @@ namespace ts {
continue;
}
separatorAllowed = true;
const valueOfCh = ch - CharacterCodes._0;
if (!isDigit(ch) || valueOfCh >= base) {
if (!isDigit(ch) || ch - CharacterCodes._0 >= base) {
break;
}
value = value * base + valueOfCh;
value += text[pos];
pos++;
numberOfDigits++;
isPreviousTokenSeparator = false;
}
// Invalid binaryIntegerLiteral or octalIntegerLiteral
if (numberOfDigits === 0) {
return -1;
}
if (text.charCodeAt(pos - 1) === CharacterCodes._) {
// Literal ends with underscore - not allowed
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
return value;
}
return value;
}
function checkBigIntSuffix(): SyntaxKind {
if (text.charCodeAt(pos) === CharacterCodes.n) {
tokenValue += "n";
// Use base 10 instead of base 2 or base 8 for shorter literals
if (tokenFlags & TokenFlags.BinaryOrOctalSpecifier) {
tokenValue = parsePseudoBigInt(tokenValue) + "n";
}
pos++;
return SyntaxKind.BigIntLiteral;
}
else { // not a bigint, so can convert to number in simplified form
// Number() may not support 0b or 0o, so use parseInt() instead
const numericValue = tokenFlags & TokenFlags.BinarySpecifier
? parseInt(tokenValue.slice(2), 2) // skip "0b"
: tokenFlags & TokenFlags.OctalSpecifier
? parseInt(tokenValue.slice(2), 8) // skip "0o"
: +tokenValue;
tokenValue = "" + numericValue;
return SyntaxKind.NumericLiteral;
}
}
function scan(): SyntaxKind {
startPos = pos;
tokenFlags = 0;
@@ -1500,7 +1527,7 @@ namespace ts {
return token = SyntaxKind.MinusToken;
case CharacterCodes.dot:
if (isDigit(text.charCodeAt(pos + 1))) {
tokenValue = scanNumber();
tokenValue = scanNumber().value;
return token = SyntaxKind.NumericLiteral;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
@@ -1576,36 +1603,36 @@ namespace ts {
case CharacterCodes._0:
if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) {
pos += 2;
let value = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true);
if (value < 0) {
tokenValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true);
if (!tokenValue) {
error(Diagnostics.Hexadecimal_digit_expected);
value = 0;
tokenValue = "0";
}
tokenValue = "" + value;
tokenValue = "0x" + tokenValue;
tokenFlags |= TokenFlags.HexSpecifier;
return token = SyntaxKind.NumericLiteral;
return token = checkBigIntSuffix();
}
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) {
pos += 2;
let value = scanBinaryOrOctalDigits(/* base */ 2);
if (value < 0) {
tokenValue = scanBinaryOrOctalDigits(/* base */ 2);
if (!tokenValue) {
error(Diagnostics.Binary_digit_expected);
value = 0;
tokenValue = "0";
}
tokenValue = "" + value;
tokenValue = "0b" + tokenValue;
tokenFlags |= TokenFlags.BinarySpecifier;
return token = SyntaxKind.NumericLiteral;
return token = checkBigIntSuffix();
}
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) {
pos += 2;
let value = scanBinaryOrOctalDigits(/* base */ 8);
if (value < 0) {
tokenValue = scanBinaryOrOctalDigits(/* base */ 8);
if (!tokenValue) {
error(Diagnostics.Octal_digit_expected);
value = 0;
tokenValue = "0";
}
tokenValue = "" + value;
tokenValue = "0o" + tokenValue;
tokenFlags |= TokenFlags.OctalSpecifier;
return token = SyntaxKind.NumericLiteral;
return token = checkBigIntSuffix();
}
// Try to parse as an octal
if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
@@ -1626,8 +1653,8 @@ namespace ts {
case CharacterCodes._7:
case CharacterCodes._8:
case CharacterCodes._9:
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
({ type: token, value: tokenValue } = scanNumber());
return token;
case CharacterCodes.colon:
pos++;
return token = SyntaxKind.ColonToken;
@@ -2016,7 +2043,7 @@ namespace ts {
pos++;
}
tokenValue = text.substring(tokenPos, pos);
return token = SyntaxKind.Identifier;
return token = getIdentifierToken();
}
else {
return token = SyntaxKind.Unknown;
+12 -10
View File
@@ -591,10 +591,12 @@ namespace ts {
export function createDocumentPositionMapper(host: DocumentPositionMapperHost, map: RawSourceMap, mapPath: string): DocumentPositionMapper {
const mapDirectory = getDirectoryPath(mapPath);
const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory;
const generatedFilePath = toPath(map.file, mapDirectory, host.getCanonicalFileName);
const generatedFile = host.getSourceFileLike(generatedFilePath);
const sourceFilePaths = map.sources.map(source => toPath(source, sourceRoot, host.getCanonicalFileName));
const sourceToSourceIndexMap = createMapFromEntries(sourceFilePaths.map((source, i) => [source, i] as [string, number]));
const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory);
const generatedCanonicalFilePath = host.getCanonicalFileName(generatedAbsoluteFilePath) as Path;
const generatedFile = host.getSourceFileLike(generatedCanonicalFilePath);
const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot));
const sourceFileCanonicalPaths = sourceFileAbsolutePaths.map(source => host.getCanonicalFileName(source) as Path);
const sourceToSourceIndexMap = createMapFromEntries(sourceFileCanonicalPaths.map((source, i) => [source, i] as [string, number]));
let decodedMappings: ReadonlyArray<MappedPosition> | undefined;
let generatedMappings: ReadonlyArray<MappedPosition> | undefined;
let sourceMappings: ReadonlyArray<ReadonlyArray<SourceMappedPosition>> | undefined;
@@ -611,7 +613,7 @@ namespace ts {
let source: string | undefined;
let sourcePosition: number | undefined;
if (isSourceMapping(mapping)) {
const sourceFilePath = sourceFilePaths[mapping.sourceIndex];
const sourceFilePath = sourceFileCanonicalPaths[mapping.sourceIndex];
const sourceFile = host.getSourceFileLike(sourceFilePath);
source = map.sources[mapping.sourceIndex];
sourcePosition = sourceFile !== undefined
@@ -670,7 +672,7 @@ namespace ts {
}
function getGeneratedPosition(loc: DocumentPosition): DocumentPosition {
const sourceIndex = sourceToSourceIndexMap.get(loc.fileName);
const sourceIndex = sourceToSourceIndexMap.get(host.getCanonicalFileName(loc.fileName));
if (sourceIndex === undefined) return loc;
const sourceMappings = getSourceMappings(sourceIndex);
@@ -678,7 +680,7 @@ namespace ts {
let targetIndex = binarySearchKey(sourceMappings, loc.pos, getSourcePositionOfMapping, compareValues);
if (targetIndex < 0) {
// if no exact match, closest is 2's compliment of result
// if no exact match, closest is 2's complement of result
targetIndex = ~targetIndex;
}
@@ -687,7 +689,7 @@ namespace ts {
return loc;
}
return { fileName: generatedFilePath, pos: mapping.generatedPosition }; // Closest pos
return { fileName: generatedAbsoluteFilePath, pos: mapping.generatedPosition }; // Closest pos
}
function getSourcePosition(loc: DocumentPosition): DocumentPosition {
@@ -696,7 +698,7 @@ namespace ts {
let targetIndex = binarySearchKey(generatedMappings, loc.pos, getGeneratedPositionOfMapping, compareValues);
if (targetIndex < 0) {
// if no exact match, closest is 2's compliment of result
// if no exact match, closest is 2's complement of result
targetIndex = ~targetIndex;
}
@@ -705,7 +707,7 @@ namespace ts {
return loc;
}
return { fileName: sourceFilePaths[mapping.sourceIndex], pos: mapping.sourcePosition }; // Closest pos
return { fileName: sourceFileAbsolutePaths[mapping.sourceIndex], pos: mapping.sourcePosition }; // Closest pos
}
}
+4 -22
View File
@@ -36,23 +36,6 @@ namespace ts {
Low = 250
}
function getPriorityValues(highPriorityValue: number): [number, number, number] {
const mediumPriorityValue = highPriorityValue * 2;
const lowPriorityValue = mediumPriorityValue * 4;
return [highPriorityValue, mediumPriorityValue, lowPriorityValue];
}
function pollingInterval(watchPriority: PollingInterval): number {
return pollingIntervalsForPriority[watchPriority];
}
const pollingIntervalsForPriority = getPriorityValues(250);
/* @internal */
export function watchFileUsingPriorityPollingInterval(host: System, fileName: string, callback: FileWatcherCallback, watchPriority: PollingInterval): FileWatcher {
return host.watchFile!(fileName, callback, pollingInterval(watchPriority));
}
/* @internal */
export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval | undefined) => FileWatcher;
/* @internal */
@@ -796,11 +779,10 @@ namespace ts {
dirName,
(_eventName: string, relativeFileName) => {
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
const fileName = !isString(relativeFileName)
? undefined! // TODO: GH#18217
: getNormalizedAbsolutePath(relativeFileName, dirName);
if (!isString(relativeFileName)) { return; }
const fileName = getNormalizedAbsolutePath(relativeFileName, dirName);
// Some applications save a working file via rename operations
const callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName));
const callbacks = fileName && fileWatcherCallbacks.get(toCanonicalName(fileName));
if (callbacks) {
for (const fileCallback of callbacks) {
fileCallback(fileName, FileWatcherEventKind.Changed);
@@ -847,7 +829,7 @@ namespace ts {
}
}
type FsWatchCallback = (eventName: "rename" | "change", relativeFileName: string) => void;
type FsWatchCallback = (eventName: "rename" | "change", relativeFileName: string | undefined) => void;
function createFileWatcherCallback(callback: FsWatchCallback): FileWatcherCallback {
return (_fileName, eventKind) => callback(eventKind === FileWatcherEventKind.Changed ? "change" : "rename", "");
+3 -3
View File
@@ -275,7 +275,7 @@ namespace ts {
else {
if (isBundledEmit && contains((node as Bundle).sourceFiles, file)) return; // Omit references to files which are being merged
const paths = getOutputPathsFor(file, host, /*forceDtsPaths*/ true);
declFileName = paths.declarationFilePath || paths.jsFilePath;
declFileName = paths.declarationFilePath || paths.jsFilePath || file.fileName;
}
if (declFileName) {
@@ -373,7 +373,7 @@ namespace ts {
function ensureNoInitializer(node: CanHaveLiteralInitializer) {
if (shouldPrintWithInitializer(node)) {
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe
}
return undefined;
}
@@ -1043,7 +1043,7 @@ namespace ts {
const modifiers = createNodeArray(ensureModifiers(input, isPrivate));
const typeParameters = ensureTypeParams(input, input.typeParameters);
const ctor = getFirstConstructorWithBody(input);
let parameterProperties: PropertyDeclaration[] | undefined;
let parameterProperties: ReadonlyArray<PropertyDeclaration> | undefined;
if (ctor) {
const oldDiag = getSymbolAccessibilityDiagnostic;
parameterProperties = compact(flatMap(ctor.parameters, param => {
@@ -466,4 +466,4 @@ namespace ts {
};
}
}
}
}
+23
View File
@@ -1901,6 +1901,9 @@ namespace ts {
case SyntaxKind.NumericLiteral:
return createIdentifier("Number");
case SyntaxKind.BigIntLiteral:
return getGlobalBigIntNameWithFallback();
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return createIdentifier("Boolean");
@@ -1912,6 +1915,9 @@ namespace ts {
case SyntaxKind.NumberKeyword:
return createIdentifier("Number");
case SyntaxKind.BigIntKeyword:
return getGlobalBigIntNameWithFallback();
case SyntaxKind.SymbolKeyword:
return languageVersion < ScriptTarget.ES2015
? getGlobalSymbolNameWithFallback()
@@ -2006,6 +2012,9 @@ namespace ts {
case TypeReferenceSerializationKind.VoidNullableOrNeverType:
return createVoidZero();
case TypeReferenceSerializationKind.BigIntLikeType:
return getGlobalBigIntNameWithFallback();
case TypeReferenceSerializationKind.BooleanType:
return createIdentifier("Boolean");
@@ -2115,6 +2124,20 @@ namespace ts {
);
}
/**
* Gets an expression that points to the global "BigInt" constructor at runtime if it is
* available.
*/
function getGlobalBigIntNameWithFallback(): SerializedTypeNode {
return languageVersion < ScriptTarget.ESNext
? createConditional(
createTypeCheck(createIdentifier("BigInt"), "function"),
createIdentifier("BigInt"),
createIdentifier("Object")
)
: createIdentifier("BigInt");
}
/**
* A simple inlinable expression is an expression which can be copied into multiple locations
* without risk of repeating any sideeffects and whose value could not possibly change between
+37 -17
View File
@@ -29,6 +29,9 @@ namespace ts {
preserveWatchOutput?: boolean;
listEmittedFiles?: boolean;
listFiles?: boolean;
pretty?: boolean;
traceResolution?: boolean;
}
enum BuildResultFlags {
@@ -316,7 +319,7 @@ namespace ts {
return fileExtensionIs(fileName, Extension.Dts);
}
export interface SolutionBuilderHost extends CompilerHost {
export interface SolutionBuilderHostBase extends CompilerHost {
getModifiedTime(fileName: string): Date | undefined;
setModifiedTime(fileName: string, date: Date): void;
deleteFile(fileName: string): void;
@@ -325,13 +328,18 @@ namespace ts {
reportSolutionBuilderStatus: DiagnosticReporter;
}
export interface SolutionBuilderWithWatchHost extends SolutionBuilderHost, WatchHost {
export interface SolutionBuilderHost extends SolutionBuilderHostBase {
reportErrorSummary?: ReportEmitErrorSummary;
}
export interface SolutionBuilderWithWatchHost extends SolutionBuilderHostBase, WatchHost {
}
export interface SolutionBuilder {
buildAllProjects(): ExitStatus;
cleanAllProjects(): ExitStatus;
// TODO:: All the below ones should technically only be in watch mode. but thats for later time
/*@internal*/ resolveProjectName(name: string): ResolvedConfigFileName;
/*@internal*/ getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus;
/*@internal*/ getBuildGraph(configFileNames: ReadonlyArray<string>): DependencyGraph;
@@ -340,7 +348,9 @@ namespace ts {
/*@internal*/ buildInvalidatedProject(): void;
/*@internal*/ resetBuildContext(opts?: BuildOptions): void;
}
export interface SolutionBuilderWithWatch extends SolutionBuilder {
/*@internal*/ startWatching(): void;
}
@@ -355,8 +365,8 @@ namespace ts {
};
}
export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
const host = createCompilerHostWorker({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHost;
function createSolutionBuilderHostBase(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
const host = createCompilerHostWorker({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHostBase;
host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined;
host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop;
host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop;
@@ -365,8 +375,14 @@ namespace ts {
return host;
}
export function createSolutionBuilderWithWatchHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
const host = createSolutionBuilderHost(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost;
export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) {
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost;
host.reportErrorSummary = reportErrorSummary;
return host;
}
export function createSolutionBuilderWithWatchHost(system?: System, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost;
const watchHost = createWatchHost(system, reportWatchStatus);
host.onWatchStatusChange = watchHost.onWatchStatusChange;
host.watchFile = watchHost.watchFile;
@@ -390,7 +406,9 @@ namespace ts {
* TODO: use SolutionBuilderWithWatchHost => watchedSolution
* use SolutionBuilderHost => Solution
*/
export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder {
export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder;
export function createSolutionBuilder(host: SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch;
export function createSolutionBuilder(host: SolutionBuilderHost | SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch {
const hostWithWatch = host as SolutionBuilderWithWatchHost;
const currentDirectory = host.getCurrentDirectory();
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
@@ -803,9 +821,7 @@ namespace ts {
globalDependencyGraph = undefined;
}
projectStatus.removeKey(resolved);
if (options.watch) {
diagnostics.removeKey(resolved);
}
diagnostics.removeKey(resolved);
addProjToQueue(resolved, reloadLevel);
}
@@ -874,7 +890,7 @@ namespace ts {
}
function reportErrorSummary() {
if (options.watch) {
if (options.watch || (host as SolutionBuilderHost).reportErrorSummary) {
// Report errors from the other projects
getGlobalDependencyGraph().buildQueue.forEach(project => {
if (!projectErrorsReported.hasKey(project)) {
@@ -882,8 +898,13 @@ namespace ts {
}
});
let totalErrors = 0;
diagnostics.forEach(singleProjectErrors => totalErrors += singleProjectErrors.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length);
reportWatchStatus(totalErrors === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, totalErrors);
diagnostics.forEach(singleProjectErrors => totalErrors += getErrorCountForSummary(singleProjectErrors));
if (options.watch) {
reportWatchStatus(getWatchErrorSummaryDiagnosticMessage(totalErrors), totalErrors);
}
else {
(host as SolutionBuilderHost).reportErrorSummary!(totalErrors);
}
}
}
@@ -1066,6 +1087,7 @@ namespace ts {
type: UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime
};
diagnostics.removeKey(proj);
projectStatus.setValue(proj, status);
return resultFlags;
@@ -1204,10 +1226,8 @@ namespace ts {
function reportAndStoreErrors(proj: ResolvedConfigFileName, errors: ReadonlyArray<Diagnostic>) {
reportErrors(errors);
if (options.watch) {
projectErrorsReported.setValue(proj, true);
diagnostics.setValue(proj, errors);
}
projectErrorsReported.setValue(proj, true);
diagnostics.setValue(proj, errors);
}
function reportErrors(errors: ReadonlyArray<Diagnostic>) {
+209 -73
View File
@@ -24,7 +24,85 @@ namespace ts {
| SyntaxKind.DotToken
| SyntaxKind.Identifier
| SyntaxKind.NoSubstitutionTemplateLiteral
| SyntaxKind.Unknown;
| SyntaxKind.Unknown
| KeywordSyntaxKind;
export type KeywordSyntaxKind =
| SyntaxKind.AbstractKeyword
| SyntaxKind.AnyKeyword
| SyntaxKind.AsKeyword
| SyntaxKind.BigIntKeyword
| SyntaxKind.BooleanKeyword
| SyntaxKind.BreakKeyword
| SyntaxKind.CaseKeyword
| SyntaxKind.CatchKeyword
| SyntaxKind.ClassKeyword
| SyntaxKind.ContinueKeyword
| SyntaxKind.ConstKeyword
| SyntaxKind.ConstructorKeyword
| SyntaxKind.DebuggerKeyword
| SyntaxKind.DeclareKeyword
| SyntaxKind.DefaultKeyword
| SyntaxKind.DeleteKeyword
| SyntaxKind.DoKeyword
| SyntaxKind.ElseKeyword
| SyntaxKind.EnumKeyword
| SyntaxKind.ExportKeyword
| SyntaxKind.ExtendsKeyword
| SyntaxKind.FalseKeyword
| SyntaxKind.FinallyKeyword
| SyntaxKind.ForKeyword
| SyntaxKind.FromKeyword
| SyntaxKind.FunctionKeyword
| SyntaxKind.GetKeyword
| SyntaxKind.IfKeyword
| SyntaxKind.ImplementsKeyword
| SyntaxKind.ImportKeyword
| SyntaxKind.InKeyword
| SyntaxKind.InferKeyword
| SyntaxKind.InstanceOfKeyword
| SyntaxKind.InterfaceKeyword
| SyntaxKind.IsKeyword
| SyntaxKind.KeyOfKeyword
| SyntaxKind.LetKeyword
| SyntaxKind.ModuleKeyword
| SyntaxKind.NamespaceKeyword
| SyntaxKind.NeverKeyword
| SyntaxKind.NewKeyword
| SyntaxKind.NullKeyword
| SyntaxKind.NumberKeyword
| SyntaxKind.ObjectKeyword
| SyntaxKind.PackageKeyword
| SyntaxKind.PrivateKeyword
| SyntaxKind.ProtectedKeyword
| SyntaxKind.PublicKeyword
| SyntaxKind.ReadonlyKeyword
| SyntaxKind.RequireKeyword
| SyntaxKind.GlobalKeyword
| SyntaxKind.ReturnKeyword
| SyntaxKind.SetKeyword
| SyntaxKind.StaticKeyword
| SyntaxKind.StringKeyword
| SyntaxKind.SuperKeyword
| SyntaxKind.SwitchKeyword
| SyntaxKind.SymbolKeyword
| SyntaxKind.ThisKeyword
| SyntaxKind.ThrowKeyword
| SyntaxKind.TrueKeyword
| SyntaxKind.TryKeyword
| SyntaxKind.TypeKeyword
| SyntaxKind.TypeOfKeyword
| SyntaxKind.UndefinedKeyword
| SyntaxKind.UniqueKeyword
| SyntaxKind.UnknownKeyword
| SyntaxKind.VarKeyword
| SyntaxKind.VoidKeyword
| SyntaxKind.WhileKeyword
| SyntaxKind.WithKeyword
| SyntaxKind.YieldKeyword
| SyntaxKind.AsyncKeyword
| SyntaxKind.AwaitKeyword
| SyntaxKind.OfKeyword;
export type JsxTokenSyntaxKind =
| SyntaxKind.LessThanSlashToken
@@ -51,6 +129,7 @@ namespace ts {
ConflictMarkerTrivia,
// Literals
NumericLiteral,
BigIntLiteral,
StringLiteral,
JsxText,
JsxTextAllWhiteSpaces,
@@ -194,6 +273,7 @@ namespace ts {
UnknownKeyword,
FromKeyword,
GlobalKeyword,
BigIntKeyword,
OfKeyword, // LastKeyword and LastToken and LastContextualKeyword
// Parse tree nodes
@@ -639,7 +719,6 @@ namespace ts {
export type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
export type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
export type EndOfFileToken = Token<SyntaxKind.EndOfFileToken> & JSDocContainer;
export type AtToken = Token<SyntaxKind.AtToken>;
export type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
export type PlusToken = Token<SyntaxKind.PlusToken>;
@@ -713,7 +792,7 @@ namespace ts {
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern;
export interface Declaration extends Node {
_declarationBrand: any;
@@ -1032,6 +1111,7 @@ namespace ts {
kind: SyntaxKind.AnyKeyword
| SyntaxKind.UnknownKeyword
| SyntaxKind.NumberKeyword
| SyntaxKind.BigIntKeyword
| SyntaxKind.ObjectKeyword
| SyntaxKind.BooleanKeyword
| SyntaxKind.StringKeyword
@@ -1582,7 +1662,7 @@ namespace ts {
OctalSpecifier = 1 << 8, // e.g. `0o777`
ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinarySpecifier | OctalSpecifier | ContainsSeparator
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
}
export interface NumericLiteral extends LiteralExpression {
@@ -1591,6 +1671,10 @@ namespace ts {
numericLiteralFlags: TokenFlags;
}
export interface BigIntLiteral extends LiteralExpression {
kind: SyntaxKind.BigIntLiteral;
}
export interface TemplateHead extends LiteralLikeNode {
kind: SyntaxKind.TemplateHead;
parent: TemplateExpression;
@@ -1697,6 +1781,9 @@ namespace ts {
arguments: NodeArray<Expression>;
}
/** @internal */
export type BindableObjectDefinePropertyCall = CallExpression & { arguments: { 0: EntityNameExpression, 1: StringLiteralLike | NumericLiteral, 2: ObjectLiteralExpression } };
// see: https://tc39.github.io/ecma262/#prod-SuperCall
export interface SuperCall extends CallExpression {
expression: SuperExpression;
@@ -2333,7 +2420,6 @@ namespace ts {
export interface JSDocTag extends Node {
parent: JSDoc | JSDocTypeLiteral;
atToken: AtToken;
tagName: Identifier;
comment?: string;
}
@@ -2367,7 +2453,7 @@ namespace ts {
export interface JSDocTemplateTag extends JSDocTag {
kind: SyntaxKind.JSDocTemplateTag;
constraint: TypeNode | undefined;
constraint: JSDocTypeExpression | undefined;
typeParameters: NodeArray<TypeParameterDeclaration>;
}
@@ -2634,7 +2720,7 @@ namespace ts {
// It is used to resolve module names in the checker.
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
/* @internal */ resolvedModules?: Map<ResolvedModuleFull | undefined>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective | undefined>;
/* @internal */ imports: ReadonlyArray<StringLiteralLike>;
/**
* When a file's references are redirected due to project reference directives,
@@ -2713,7 +2799,7 @@ namespace ts {
export interface ParseConfigHost {
useCaseSensitiveFileNames: boolean;
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): ReadonlyArray<string>;
/**
* Gets a value indicating whether the specified path exists and is a file.
@@ -2722,6 +2808,7 @@ namespace ts {
fileExists(path: string): boolean;
readFile(path: string): string | undefined;
trace?(s: string): void;
}
/**
@@ -2809,7 +2896,7 @@ namespace ts {
/* @internal */ getTypeCount(): number;
/* @internal */ getFileProcessingDiagnostics(): DiagnosticCollection;
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective | undefined>;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
isSourceFileDefaultLibrary(file: SourceFile): boolean;
@@ -2829,8 +2916,11 @@ namespace ts {
/* @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
getResolvedProjectReferences(): ReadonlyArray<ResolvedProjectReference | undefined> | undefined;
/*@internal*/ getProjectReferenceRedirect(fileName: string): string | undefined;
/*@internal*/ getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
/*@internal*/ forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined): T | undefined;
/*@internal*/ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined;
}
/* @internal */
@@ -2839,6 +2929,7 @@ namespace ts {
export interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
sourceFile: SourceFile;
references?: ReadonlyArray<ResolvedProjectReference | undefined>;
}
/* @internal */
@@ -2902,12 +2993,12 @@ namespace ts {
}
/* @internal */
export interface TypeCheckerHost {
export interface TypeCheckerHost extends ModuleSpecifierResolutionHost {
getCompilerOptions(): CompilerOptions;
getSourceFiles(): ReadonlyArray<SourceFile>;
getSourceFile(fileName: string): SourceFile | undefined;
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective>;
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective | undefined>;
readonly redirectTargetsMap: RedirectTargetsMap;
}
@@ -2988,7 +3079,7 @@ namespace ts {
getFullyQualifiedName(symbol: Symbol): string;
getAugmentedPropertiesOfType(type: Type): Symbol[];
getRootSymbols(symbol: Symbol): Symbol[];
getRootSymbols(symbol: Symbol): ReadonlyArray<Symbol>;
getContextualType(node: Expression): Type | undefined;
/* @internal */ getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined;
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined;
@@ -3020,8 +3111,6 @@ namespace ts {
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
@@ -3084,11 +3173,13 @@ namespace ts {
/* @internal */ getTypeCount(): number;
/* @internal */ isArrayLikeType(type: Type): boolean;
/* @internal */ getObjectFlags(type: Type): ObjectFlags;
/**
* True if `contextualType` should not be considered for completions because
* e.g. it specifies `kind: "a"` and obj has `kind: "b"`.
*/
/* @internal */ isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression): boolean;
/* @internal */ isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean;
/**
* For a union, will include a property if it's defined in *any* of the member types.
* So for `{ a } | { b }`, this will include both `a` and `b`.
@@ -3177,6 +3268,8 @@ namespace ts {
InTypeAlias = 1 << 23, // Writing type in type alias declaration
InInitialEntityName = 1 << 24, // Set when writing the LHS of an entity name or entity name expression
InReverseMappedType = 1 << 25,
/* @internal */ DoNotIncludeSymbolChain = 1 << 26, // Skip looking up and printing an accessible symbol chain
}
// Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment
@@ -3239,6 +3332,9 @@ namespace ts {
// Prefer aliases which are not directly visible
UseAliasDefinedOutsideCurrentScope = 0x00000008,
// Skip building an accessible symbol chain
/* @internal */ DoNotIncludeSymbolChain = 0x00000010,
}
/* @internal */
@@ -3365,6 +3461,7 @@ namespace ts {
// of a type, such as the global `Promise` type in lib.d.ts).
VoidNullableOrNeverType, // The TypeReferenceNode resolves to a Void-like, Nullable, or Never type.
NumberLikeType, // The TypeReferenceNode resolves to a Number-like type.
BigIntLikeType, // The TypeReferenceNode resolves to a BigInt-like type.
StringLikeType, // The TypeReferenceNode resolves to a String-like type.
BooleanType, // The TypeReferenceNode resolves to a Boolean-like type.
ArrayLikeType, // The TypeReferenceNode resolves to an Array-like type.
@@ -3397,7 +3494,7 @@ namespace ts {
createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined;
createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined;
createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): Expression;
createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
@@ -3553,6 +3650,7 @@ namespace ts {
originatingImport?: ImportDeclaration | ImportCall; // Import declaration which produced the symbol, present if the symbol is marked as uncallable but had call signatures in `resolveESModuleSymbol`
lateSymbol?: Symbol; // Late-bound symbol for a computed property
specifierCache?: Map<string>; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings
variances?: Variance[]; // Alias symbol type argument variance cache
}
/* @internal */
@@ -3589,6 +3687,7 @@ namespace ts {
export interface ReverseMappedSymbol extends TransientSymbol {
propertyType: Type;
mappedType: MappedType;
constraintType: IndexType;
}
export const enum InternalSymbolName {
@@ -3681,7 +3780,6 @@ namespace ts {
resolvedType?: Type; // Cached type of type node
resolvedEnumType?: Type; // Cached constraint type from enum jsdoc tag
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSignatures?: Map<Signature[]>; // Cached signatures of jsx node
resolvedSymbol?: Symbol; // Cached name resolution result
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
@@ -3708,29 +3806,27 @@ namespace ts {
Number = 1 << 3,
Boolean = 1 << 4,
Enum = 1 << 5,
StringLiteral = 1 << 6,
NumberLiteral = 1 << 7,
BooleanLiteral = 1 << 8,
EnumLiteral = 1 << 9, // Always combined with StringLiteral, NumberLiteral, or Union
ESSymbol = 1 << 10, // Type of symbol primitive introduced in ES6
UniqueESSymbol = 1 << 11, // unique symbol
Void = 1 << 12,
Undefined = 1 << 13,
Null = 1 << 14,
Never = 1 << 15, // Never type
TypeParameter = 1 << 16, // Type parameter
Object = 1 << 17, // Object type
Union = 1 << 18, // Union (T | U)
Intersection = 1 << 19, // Intersection (T & U)
Index = 1 << 20, // keyof T
IndexedAccess = 1 << 21, // T[K]
Conditional = 1 << 22, // T extends U ? X : Y
Substitution = 1 << 23, // Type parameter substitution
NonPrimitive = 1 << 24, // intrinsic object type
/* @internal */
FreshLiteral = 1 << 25, // Fresh literal or unique type
/* @internal */
UnionOfPrimitiveTypes = 1 << 26, // Type is union of primitive types
BigInt = 1 << 6,
StringLiteral = 1 << 7,
NumberLiteral = 1 << 8,
BooleanLiteral = 1 << 9,
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
BigIntLiteral = 1 << 11,
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
UniqueESSymbol = 1 << 13, // unique symbol
Void = 1 << 14,
Undefined = 1 << 15,
Null = 1 << 16,
Never = 1 << 17, // Never type
TypeParameter = 1 << 18, // Type parameter
Object = 1 << 19, // Object type
Union = 1 << 20, // Union (T | U)
Intersection = 1 << 21, // Intersection (T & U)
Index = 1 << 22, // keyof T
IndexedAccess = 1 << 23, // T[K]
Conditional = 1 << 24, // T extends U ? X : Y
Substitution = 1 << 25, // Type parameter substitution
NonPrimitive = 1 << 26, // intrinsic object type
/* @internal */
ContainsWideningType = 1 << 27, // Type is or contains undefined or null widening type
/* @internal */
@@ -3742,26 +3838,27 @@ namespace ts {
AnyOrUnknown = Any | Unknown,
/* @internal */
Nullable = Undefined | Null,
Literal = StringLiteral | NumberLiteral | BooleanLiteral,
Literal = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral,
Unit = Literal | UniqueESSymbol | Nullable,
StringOrNumberLiteral = StringLiteral | NumberLiteral,
/* @internal */
StringOrNumberLiteralOrUnique = StringLiteral | NumberLiteral | UniqueESSymbol,
/* @internal */
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,
PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean,
DefinitelyFalsy = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral | Void | Undefined | Null,
PossiblyFalsy = DefinitelyFalsy | String | Number | BigInt | Boolean,
/* @internal */
Intrinsic = Any | Unknown | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
Intrinsic = Any | Unknown | String | Number | BigInt | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
/* @internal */
Primitive = String | Number | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol,
Primitive = String | Number | BigInt | Boolean | Enum | EnumLiteral | ESSymbol | Void | Undefined | Null | Literal | UniqueESSymbol,
StringLike = String | StringLiteral,
NumberLike = Number | NumberLiteral | Enum,
BigIntLike = BigInt | BigIntLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
ESSymbolLike = ESSymbol | UniqueESSymbol,
VoidLike = Void | Undefined,
/* @internal */
DisjointDomains = NonPrimitive | StringLike | NumberLike | BooleanLike | ESSymbolLike | VoidLike | Null,
DisjointDomains = NonPrimitive | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbolLike | VoidLike | Null,
UnionOrIntersection = Union | Intersection,
StructuredType = Object | Union | Intersection,
TypeVariable = TypeParameter | IndexedAccess,
@@ -3772,7 +3869,7 @@ namespace ts {
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
NotUnionOrUnit = Any | Unknown | ESSymbol | Object | NonPrimitive,
/* @internal */
NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable,
@@ -3805,6 +3902,7 @@ namespace ts {
pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any)
aliasSymbol?: Symbol; // Alias associated with type
aliasTypeArguments?: ReadonlyArray<Type>; // Alias type arguments (if any)
/* @internal */ aliasTypeArgumentsContainsMarker?: boolean; // Alias type arguments (if any)
/* @internal */
wildcardInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type
/* @internal */
@@ -3828,10 +3926,11 @@ namespace ts {
// String literal types (TypeFlags.StringLiteral)
// Numeric literal types (TypeFlags.NumberLiteral)
// BigInt literal types (TypeFlags.BigIntLiteral)
export interface LiteralType extends Type {
value: string | number; // Value of literal
freshType: LiteralType; // Fresh version of type
regularType: LiteralType; // Regular version of type
value: string | number | PseudoBigInt; // Value of literal
freshType: LiteralType; // Fresh version of type
regularType: LiteralType; // Regular version of type
}
// Unique symbol types (TypeFlags.UniqueESSymbol)
@@ -3847,6 +3946,10 @@ namespace ts {
value: number;
}
export interface BigIntLiteralType extends LiteralType {
value: PseudoBigInt;
}
// Enum types (TypeFlags.Enum)
export interface EnumType extends Type {
}
@@ -3867,6 +3970,7 @@ namespace ts {
JsxAttributes = 1 << 12, // Jsx attributes type
MarkerType = 1 << 13, // Marker type used for variance probing
JSLiteral = 1 << 14, // Object type declared in JS - disables errors on read/write of nonexisting members
FreshLiteral = 1 << 15, // Fresh object literal
ClassOrInterface = Class | Interface
}
@@ -3962,7 +4066,10 @@ namespace ts {
couldContainTypeVariables: boolean;
}
export interface UnionType extends UnionOrIntersectionType { }
export interface UnionType extends UnionOrIntersectionType {
/* @internal */
primitiveTypesOnly: boolean;
}
export interface IntersectionType extends UnionOrIntersectionType {
/* @internal */
@@ -3986,6 +4093,7 @@ namespace ts {
templateType?: Type;
modifiersType?: Type;
resolvedApparentType?: Type;
instantiating?: boolean;
}
export interface EvolvingArrayType extends ObjectType {
@@ -3997,6 +4105,7 @@ namespace ts {
export interface ReverseMappedType extends ObjectType {
source: Type;
mappedType: MappedType;
constraintType: IndexType;
}
/* @internal */
@@ -4121,6 +4230,13 @@ namespace ts {
substitute: Type; // Type to substitute for type parameter
}
/* @internal */
export const enum JsxReferenceKind {
Component,
Function,
Mixed
}
export const enum SignatureKind {
Call,
Construct,
@@ -4257,6 +4373,15 @@ namespace ts {
Property,
// F.prototype = { ... }
Prototype,
// Object.defineProperty(x, 'name', { value: any, writable?: boolean (false by default) });
// Object.defineProperty(x, 'name', { get: Function, set: Function });
// Object.defineProperty(x, 'name', { get: Function });
// Object.defineProperty(x, 'name', { set: Function });
ObjectDefinePropertyValue,
// Object.defineProperty(exports || module.exports, 'name', ...);
ObjectDefinePropertyExports,
// Object.defineProperty(Foo.prototype, 'name', ...);
ObjectDefinePrototypeProperty,
}
/** @deprecated Use FileExtensionInfo instead. */
@@ -4370,6 +4495,7 @@ namespace ts {
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalBigInt?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
/*@internal*/help?: boolean;
@@ -4442,6 +4568,7 @@ namespace ts {
/*@internal*/ version?: boolean;
/*@internal*/ watch?: boolean;
esModuleInterop?: boolean;
/* @internal */ showConfig?: boolean;
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
}
@@ -4840,6 +4967,8 @@ namespace ts {
// The location of the .d.ts file we located, or undefined if resolution failed
resolvedFileName: string | undefined;
packageId?: PackageId;
/** True if `resolvedFileName` comes from `node_modules`. */
isExternalLibraryImport?: boolean;
}
export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
@@ -4871,13 +5000,13 @@ namespace ts {
* If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just
* 'throw new Error("NotImplemented")'
*/
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[];
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModule | undefined)[];
/**
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
*/
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
getEnvironmentVariable?(name: string): string | undefined;
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void;
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void;
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
createHash?(data: string): string;
@@ -5091,7 +5220,6 @@ namespace ts {
useCaseSensitiveFileNames(): boolean;
getCurrentDirectory(): string;
/* @internal */
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
@@ -5449,7 +5577,7 @@ namespace ts {
reportInaccessibleThisError?(): void;
reportPrivateInBaseOfClassExpression?(propertyName: string): void;
reportInaccessibleUniqueSymbolError?(): void;
moduleResolverHost?: EmitHost;
moduleResolverHost?: ModuleSpecifierResolutionHost & { getSourceFiles(): ReadonlyArray<SourceFile>, getCommonSourceDirectory(): string };
trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void;
trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void;
}
@@ -5502,33 +5630,34 @@ namespace ts {
BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited.
AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited.
CommaDelimited = 1 << 4, // Each list item is comma (",") delimited.
DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited,
AsteriskDelimited = 1 << 5, // Each list item is asterisk ("\n *") delimited, used with JSDoc.
DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited | AsteriskDelimited,
AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present.
AllowTrailingComma = 1 << 6, // Write a trailing comma (",") if present.
// Whitespace
Indented = 1 << 6, // The list should be indented.
SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace.
SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node.
Indented = 1 << 7, // The list should be indented.
SpaceBetweenBraces = 1 << 8, // Inserts a space after the opening brace and before the closing brace.
SpaceBetweenSiblings = 1 << 9, // Inserts a space between each sibling node.
// Brackets/Braces
Braces = 1 << 9, // The list is surrounded by "{" and "}".
Parenthesis = 1 << 10, // The list is surrounded by "(" and ")".
AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">".
SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]".
Braces = 1 << 10, // The list is surrounded by "{" and "}".
Parenthesis = 1 << 11, // The list is surrounded by "(" and ")".
AngleBrackets = 1 << 12, // The list is surrounded by "<" and ">".
SquareBrackets = 1 << 13, // The list is surrounded by "[" and "]".
BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets,
OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined.
OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty.
OptionalIfUndefined = 1 << 14, // Do not emit brackets if the list is undefined.
OptionalIfEmpty = 1 << 15, // Do not emit brackets if the list is empty.
Optional = OptionalIfUndefined | OptionalIfEmpty,
// Other
PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes.
NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list.
NoInterveningComments = 1 << 17, // Do not emit comments between each node
PreferNewLine = 1 << 16, // Prefer adding a LineTerminator between synthesized nodes.
NoTrailingNewLine = 1 << 17, // Do not emit a trailing NewLine for a MultiLine list.
NoInterveningComments = 1 << 18, // Do not emit comments between each node
NoSpaceIfEmpty = 1 << 18, // If the literal is empty, do not add spaces between braces.
SingleElement = 1 << 19,
NoSpaceIfEmpty = 1 << 19, // If the literal is empty, do not add spaces between braces.
SingleElement = 1 << 20,
// Precomputed Formats
Modifiers = SingleLine | SpaceBetweenSiblings | NoInterveningComments,
@@ -5568,6 +5697,7 @@ namespace ts {
TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | AngleBrackets | Optional,
Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,
IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets,
JSDocComment = MultiLine | AsteriskDelimited,
}
/* @internal */
@@ -5716,4 +5846,10 @@ namespace ts {
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */
export interface PseudoBigInt {
negative: boolean;
base10Value: string;
}
}
+164 -31
View File
@@ -7,7 +7,7 @@ namespace ts {
return pathIsRelative(moduleName) || isRootedDiskPath(moduleName);
}
export function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: ReadonlyArray<T>): T[] {
export function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: ReadonlyArray<T>): SortedReadonlyArray<T> {
return sortAndDeduplicate<T>(diagnostics, compareDiagnostics);
}
}
@@ -228,9 +228,9 @@ namespace ts {
sourceFile.resolvedModules.set(moduleNameText, resolvedModule);
}
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective): void {
if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective | undefined>();
}
sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, resolvedTypeReferenceDirective);
@@ -528,7 +528,10 @@ namespace ts {
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, neverAsciiEscape: boolean | undefined) {
// If we don't need to downlevel and we can reach the original source text using
// the node's parent reference, then simply get the text as it was originally written.
if (!nodeIsSynthesized(node) && node.parent && !(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator)) {
if (!nodeIsSynthesized(node) && node.parent && !(
(isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator) ||
isBigIntLiteral(node)
)) {
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
}
@@ -555,6 +558,7 @@ namespace ts {
case SyntaxKind.TemplateTail:
return "}" + escapeText(node.text, CharacterCodes.backtick) + "`";
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.RegularExpressionLiteral:
return node.text;
}
@@ -766,12 +770,13 @@ namespace ts {
return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined;
}
export function getTextOfPropertyName(name: PropertyName): __String {
export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String {
switch (name.kind) {
case SyntaxKind.Identifier:
return name.escapedText;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteralLike(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
@@ -976,6 +981,7 @@ namespace ts {
case SyntaxKind.AnyKeyword:
case SyntaxKind.UnknownKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BigIntKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
@@ -1599,6 +1605,7 @@ namespace ts {
}
// falls through
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.ThisKeyword:
return isInExpressionContext(node);
@@ -1771,7 +1778,7 @@ namespace ts {
}
export function isAssignmentDeclaration(decl: Declaration) {
return isBinaryExpression(decl) || isPropertyAccessExpression(decl) || isIdentifier(decl);
return isBinaryExpression(decl) || isPropertyAccessExpression(decl) || isIdentifier(decl) || isCallExpression(decl);
}
/** Get the initializer, taking into account defaulted Javascript initializers */
@@ -1790,16 +1797,26 @@ namespace ts {
return init && getExpandoInitializer(init, isPrototypeAccess(node.name));
}
function hasExpandoValueProperty(node: ObjectLiteralExpression, isPrototypeAssignment: boolean) {
return forEach(node.properties, p => isPropertyAssignment(p) && isIdentifier(p.name) && p.name.escapedText === "value" && p.initializer && getExpandoInitializer(p.initializer, isPrototypeAssignment));
}
/**
* Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getExpandoInitializer).
* We treat the right hand side of assignments with container-like initalizers as declarations.
*/
export function getAssignedExpandoInitializer(node: Node) {
export function getAssignedExpandoInitializer(node: Node | undefined) {
if (node && node.parent && isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) {
const isPrototypeAssignment = isPrototypeAccess(node.parent.left);
return getExpandoInitializer(node.parent.right, isPrototypeAssignment) ||
getDefaultedExpandoInitializer(node.parent.left as EntityNameExpression, node.parent.right, isPrototypeAssignment);
}
if (node && isCallExpression(node) && isBindableObjectDefinePropertyCall(node)) {
const result = hasExpandoValueProperty(node.arguments[2], node.arguments[1].text === "prototype");
if (result) {
return result;
}
}
}
/**
@@ -1906,12 +1923,35 @@ namespace ts {
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
/// assignments we treat as special in the binder
export function getAssignmentDeclarationKind(expr: BinaryExpression): AssignmentDeclarationKind {
export function getAssignmentDeclarationKind(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind {
const special = getAssignmentDeclarationKindWorker(expr);
return special === AssignmentDeclarationKind.Property || isInJSFile(expr) ? special : AssignmentDeclarationKind.None;
}
function getAssignmentDeclarationKindWorker(expr: BinaryExpression): AssignmentDeclarationKind {
export function isBindableObjectDefinePropertyCall(expr: CallExpression): expr is BindableObjectDefinePropertyCall {
return length(expr.arguments) === 3 &&
isPropertyAccessExpression(expr.expression) &&
isIdentifier(expr.expression.expression) &&
idText(expr.expression.expression) === "Object" &&
idText(expr.expression.name) === "defineProperty" &&
isStringOrNumericLiteralLike(expr.arguments[1]) &&
isEntityNameExpression(expr.arguments[0]);
}
function getAssignmentDeclarationKindWorker(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind {
if (isCallExpression(expr)) {
if (!isBindableObjectDefinePropertyCall(expr)) {
return AssignmentDeclarationKind.None;
}
const entityName = expr.arguments[0];
if (isExportsIdentifier(entityName) || isModuleExportsPropertyAccessExpression(entityName)) {
return AssignmentDeclarationKind.ObjectDefinePropertyExports;
}
if (isPropertyAccessExpression(entityName) && entityName.name.escapedText === "prototype" && isEntityNameExpression(entityName.expression)) {
return AssignmentDeclarationKind.ObjectDefinePrototypeProperty;
}
return AssignmentDeclarationKind.ObjectDefinePropertyValue;
}
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken ||
!isPropertyAccessExpression(expr.left)) {
return AssignmentDeclarationKind.None;
@@ -1928,7 +1968,7 @@ namespace ts {
if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
return AssignmentDeclarationKind.ThisProperty;
}
else if (isIdentifier(lhs.expression) && lhs.expression.escapedText === "module" && lhs.name.escapedText === "exports") {
else if (isModuleExportsPropertyAccessExpression(lhs)) {
// module.exports = expr
return AssignmentDeclarationKind.ModuleExports;
}
@@ -1993,7 +2033,7 @@ namespace ts {
case SyntaxKind.ExternalModuleReference:
return (node.parent as ExternalModuleReference).parent as AnyValidImportOrReExport;
case SyntaxKind.CallExpression:
return node.parent as AnyValidImportOrReExport;
return isImportCall(node.parent) || isRequireCall(node.parent, /*checkArg*/ false) ? node.parent as RequireOrImportCall : undefined;
case SyntaxKind.LiteralType:
Debug.assert(isStringLiteral(node));
return tryCast(node.parent.parent, isImportTypeNode) as ValidImportTypeNode | undefined;
@@ -2457,6 +2497,7 @@ namespace ts {
// export { x as <symbol> } from ...
// export = <EntityNameExpression>
// export default <EntityNameExpression>
// module.exports = <EntityNameExpression>
export function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
@@ -2465,7 +2506,7 @@ namespace ts {
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier ||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node) ||
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports;
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node);
}
export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean {
@@ -2552,6 +2593,10 @@ namespace ts {
return token !== undefined && isNonContextualKeyword(token);
}
export function isIdentifierANonContextualKeyword({ originalKeywordKind }: Identifier): boolean {
return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind);
}
export type TriviaKind = SyntaxKind.SingleLineCommentTrivia
| SyntaxKind.MultiLineCommentTrivia
| SyntaxKind.NewLineTrivia
@@ -2867,6 +2912,7 @@ namespace ts {
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
@@ -2888,7 +2934,6 @@ namespace ts {
}
}
/* @internal */
export function getBinaryOperatorPrecedence(kind: SyntaxKind): number {
switch (kind) {
case SyntaxKind.BarBarToken:
@@ -3005,7 +3050,7 @@ namespace ts {
return fileDiagnostics.get(fileName) || [];
}
const fileDiags: Diagnostic[] = flatMap(filesWithDiagnostics, f => fileDiagnostics.get(f));
const fileDiags: Diagnostic[] = flatMapToMutable(filesWithDiagnostics, f => fileDiagnostics.get(f));
if (!nonFileDiagnostics.length) {
return fileDiags;
}
@@ -3066,7 +3111,7 @@ namespace ts {
export function isIntrinsicJsxName(name: __String | string) {
const ch = (name as string).charCodeAt(0);
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || (name as string).indexOf("-") > -1;
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || stringContains((name as string), "-");
}
function get16BitUnicodeEscapeSequence(charCode: number): string {
@@ -3311,7 +3356,7 @@ namespace ts {
}
export interface EmitFileNames {
jsFilePath: string;
jsFilePath: string | undefined;
sourceMapFilePath: string | undefined;
declarationFilePath: string | undefined;
declarationMapPath: string | undefined;
@@ -5043,14 +5088,19 @@ namespace ts {
}
break;
}
case SyntaxKind.CallExpression:
case SyntaxKind.BinaryExpression: {
const expr = declaration as BinaryExpression;
const expr = declaration as BinaryExpression | CallExpression;
switch (getAssignmentDeclarationKind(expr)) {
case AssignmentDeclarationKind.ExportsProperty:
case AssignmentDeclarationKind.ThisProperty:
case AssignmentDeclarationKind.Property:
case AssignmentDeclarationKind.PrototypeProperty:
return (expr.left as PropertyAccessExpression).name;
return ((expr as BinaryExpression).left as PropertyAccessExpression).name;
case AssignmentDeclarationKind.ObjectDefinePropertyValue:
case AssignmentDeclarationKind.ObjectDefinePropertyExports:
case AssignmentDeclarationKind.ObjectDefinePrototypeProperty:
return (expr as BindableObjectDefinePropertyCall).arguments[1];
default:
return undefined;
}
@@ -5261,7 +5311,7 @@ namespace ts {
}
if (isJSDocTypeAlias(node)) {
Debug.assert(node.parent.kind === SyntaxKind.JSDocComment);
return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined) as ReadonlyArray<TypeParameterDeclaration>;
return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined);
}
if (node.typeParameters) {
return node.typeParameters;
@@ -5294,6 +5344,10 @@ namespace ts {
return node.kind === SyntaxKind.NumericLiteral;
}
export function isBigIntLiteral(node: Node): node is BigIntLiteral {
return node.kind === SyntaxKind.BigIntLiteral;
}
export function isStringLiteral(node: Node): node is StringLiteral {
return node.kind === SyntaxKind.StringLiteral;
}
@@ -6237,6 +6291,7 @@ namespace ts {
|| kind === SyntaxKind.AnyKeyword
|| kind === SyntaxKind.UnknownKeyword
|| kind === SyntaxKind.NumberKeyword
|| kind === SyntaxKind.BigIntKeyword
|| kind === SyntaxKind.ObjectKeyword
|| kind === SyntaxKind.BooleanKeyword
|| kind === SyntaxKind.StringKeyword
@@ -6419,6 +6474,7 @@ namespace ts {
case SyntaxKind.Identifier:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
@@ -6861,7 +6917,6 @@ namespace ts {
/* @internal */
namespace ts {
/** @internal */
export function isNamedImportsOrExports(node: Node): node is NamedImportsOrExports {
return node.kind === SyntaxKind.NamedImports || node.kind === SyntaxKind.NamedExports;
}
@@ -6925,7 +6980,6 @@ namespace ts {
getSourceMapSourceConstructor: () => <any>SourceMapSource,
};
/* @internal */
export function formatStringFromArgs(text: string, args: ArrayLike<string>, baseIndex = 0): string {
return text.replace(/{(\d+)}/g, (_match, index: string) => Debug.assertDefined(args[+index + baseIndex]));
}
@@ -6936,7 +6990,6 @@ namespace ts {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}
/* @internal */
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation {
Debug.assertGreaterThanOrEqual(start, 0);
@@ -6965,7 +7018,6 @@ namespace ts {
};
}
/* @internal */
export function formatMessage(_dummy: any, message: DiagnosticMessage): string {
let text = getLocaleSpecificMessage(message);
@@ -6976,7 +7028,6 @@ namespace ts {
return text;
}
/* @internal */
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number | undefined)[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
let text = getLocaleSpecificMessage(message);
@@ -6997,7 +7048,6 @@ namespace ts {
};
}
/* @internal */
export function createCompilerDiagnosticFromMessageChain(chain: DiagnosticMessageChain): Diagnostic {
return {
file: undefined,
@@ -7010,7 +7060,6 @@ namespace ts {
};
}
/* @internal */
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage, ...args: (string | undefined)[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage): DiagnosticMessageChain {
let text = getLocaleSpecificMessage(message);
@@ -7042,14 +7091,12 @@ namespace ts {
return diagnostic.file ? diagnostic.file.path : undefined;
}
/* @internal */
export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison {
return compareDiagnosticsSkipRelatedInformation(d1, d2) ||
compareRelatedInformation(d1, d2) ||
Comparison.EqualTo;
}
/* @internal */
export function compareDiagnosticsSkipRelatedInformation(d1: Diagnostic, d2: Diagnostic): Comparison {
return compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) ||
compareValues(d1.start, d2.start) ||
@@ -7387,7 +7434,6 @@ namespace ts {
return rootLength > 0 && rootLength === path.length;
}
/* @internal */
export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string {
return !isRootedDiskPath(absoluteOrRelativePath)
? absoluteOrRelativePath
@@ -7804,7 +7850,7 @@ namespace ts {
return `^(${pattern})${terminator}`;
}
function getRegularExpressionsForWildcards(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
export function getRegularExpressionsForWildcards(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): ReadonlyArray<string> | undefined {
if (specs === undefined || specs.length === 0) {
return undefined;
}
@@ -8069,12 +8115,16 @@ namespace ts {
* List of supported extensions in order of file resolution precedence.
*/
export const supportedTSExtensions: ReadonlyArray<Extension> = [Extension.Ts, Extension.Tsx, Extension.Dts];
export const supportedTSExtensionsWithJson: ReadonlyArray<Extension> = [Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Json];
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
export const supportedTSExtensionsForExtractExtension: ReadonlyArray<Extension> = [Extension.Dts, Extension.Ts, Extension.Tsx];
export const supportedJSExtensions: ReadonlyArray<Extension> = [Extension.Js, Extension.Jsx];
export const supportedJSAndJsonExtensions: ReadonlyArray<Extension> = [Extension.Js, Extension.Jsx, Extension.Json];
const allSupportedExtensions: ReadonlyArray<Extension> = [...supportedTSExtensions, ...supportedJSExtensions];
const allSupportedExtensionsWithJson: ReadonlyArray<Extension> = [...supportedTSExtensions, ...supportedJSExtensions, Extension.Json];
export function getSupportedExtensions(options?: CompilerOptions): ReadonlyArray<Extension>;
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: ReadonlyArray<FileExtensionInfo>): ReadonlyArray<string>;
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: ReadonlyArray<FileExtensionInfo>): ReadonlyArray<string> {
const needJsExtensions = options && options.allowJs;
@@ -8090,6 +8140,13 @@ namespace ts {
return deduplicate<string>(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive);
}
export function getSuppoertedExtensionsWithJsonIfResolveJsonModule(options: CompilerOptions | undefined, supportedExtensions: ReadonlyArray<string>): ReadonlyArray<string> {
if (!options || !options.resolveJsonModule) { return supportedExtensions; }
if (supportedExtensions === allSupportedExtensions) { return allSupportedExtensionsWithJson; }
if (supportedExtensions === supportedTSExtensions) { return supportedTSExtensionsWithJson; }
return [...supportedExtensions, Extension.Json];
}
function isJSLike(scriptKind: ScriptKind | undefined): boolean {
return scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX;
}
@@ -8109,7 +8166,8 @@ namespace ts {
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: ReadonlyArray<FileExtensionInfo>) {
if (!fileName) { return false; }
for (const extension of getSupportedExtensions(compilerOptions, extraFileExtensions)) {
const supportedExtensions = getSupportedExtensions(compilerOptions, extraFileExtensions);
for (const extension of getSuppoertedExtensionsWithJsonIfResolveJsonModule(compilerOptions, supportedExtensions)) {
if (fileExtensionIs(fileName, extension)) {
return true;
}
@@ -8448,4 +8506,79 @@ namespace ts {
return got;
}
}
/**
* Converts a bigint literal string, e.g. `0x1234n`,
* to its decimal string representation, e.g. `4660`.
*/
export function parsePseudoBigInt(stringValue: string): string {
let log2Base: number;
switch (stringValue.charCodeAt(1)) { // "x" in "0x123"
case CharacterCodes.b:
case CharacterCodes.B: // 0b or 0B
log2Base = 1;
break;
case CharacterCodes.o:
case CharacterCodes.O: // 0o or 0O
log2Base = 3;
break;
case CharacterCodes.x:
case CharacterCodes.X: // 0x or 0X
log2Base = 4;
break;
default: // already in decimal; omit trailing "n"
const nIndex = stringValue.length - 1;
// Skip leading 0s
let nonZeroStart = 0;
while (stringValue.charCodeAt(nonZeroStart) === CharacterCodes._0) {
nonZeroStart++;
}
return stringValue.slice(nonZeroStart, nIndex) || "0";
}
// Omit leading "0b", "0o", or "0x", and trailing "n"
const startIndex = 2, endIndex = stringValue.length - 1;
const bitsNeeded = (endIndex - startIndex) * log2Base;
// Stores the value specified by the string as a LE array of 16-bit integers
// using Uint16 instead of Uint32 so combining steps can use bitwise operators
const segments = new Uint16Array((bitsNeeded >>> 4) + (bitsNeeded & 15 ? 1 : 0));
// Add the digits, one at a time
for (let i = endIndex - 1, bitOffset = 0; i >= startIndex; i--, bitOffset += log2Base) {
const segment = bitOffset >>> 4;
const digitChar = stringValue.charCodeAt(i);
// Find character range: 0-9 < A-F < a-f
const digit = digitChar <= CharacterCodes._9
? digitChar - CharacterCodes._0
: 10 + digitChar -
(digitChar <= CharacterCodes.F ? CharacterCodes.A : CharacterCodes.a);
const shiftedDigit = digit << (bitOffset & 15);
segments[segment] |= shiftedDigit;
const residual = shiftedDigit >>> 16;
if (residual) segments[segment + 1] |= residual; // overflows segment
}
// Repeatedly divide segments by 10 and add remainder to base10Value
let base10Value = "";
let firstNonzeroSegment = segments.length - 1;
let segmentsRemaining = true;
while (segmentsRemaining) {
let mod10 = 0;
segmentsRemaining = false;
for (let segment = firstNonzeroSegment; segment >= 0; segment--) {
const newSegment = mod10 << 16 | segments[segment];
const segmentValue = (newSegment / 10) | 0;
segments[segment] = segmentValue;
mod10 = newSegment - segmentValue * 10;
if (segmentValue && !segmentsRemaining) {
firstNonzeroSegment = segment;
segmentsRemaining = true;
}
}
base10Value = mod10 + base10Value;
}
return base10Value;
}
export function pseudoBigIntToString({negative, base10Value}: PseudoBigInt): string {
return (negative && base10Value !== "0" ? "-" : "") + base10Value;
}
}
+2
View File
@@ -1111,6 +1111,7 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
result = reduceNode((<TaggedTemplateExpression>node).tag, cbNode, result);
result = reduceNodes((<TaggedTemplateExpression>node).typeArguments, cbNodes, result);
result = reduceNode((<TaggedTemplateExpression>node).template, cbNode, result);
break;
@@ -1377,6 +1378,7 @@ namespace ts {
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).typeArguments, cbNode, result);
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNode, result);
break;
+44 -23
View File
@@ -43,7 +43,6 @@ namespace ts {
return false;
}
/** @internal */
export const screenStartingMessageCodes: number[] = [
Diagnostics.Starting_compilation_in_watch_mode.code,
Diagnostics.File_change_detected_Starting_incremental_compilation.code,
@@ -106,6 +105,22 @@ namespace ts {
export type ReportEmitErrorSummary = (errorCount: number) => void;
export function getErrorCountForSummary(diagnostics: ReadonlyArray<Diagnostic>) {
return countWhere(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
}
export function getWatchErrorSummaryDiagnosticMessage(errorCount: number) {
return errorCount === 1 ?
Diagnostics.Found_1_error_Watching_for_file_changes :
Diagnostics.Found_0_errors_Watching_for_file_changes;
}
export function getErrorSummaryText(errorCount: number, newLine: string) {
if (errorCount === 0) return "";
const d = createCompilerDiagnostic(errorCount === 1 ? Diagnostics.Found_1_error : Diagnostics.Found_0_errors, errorCount);
return `${newLine}${flattenDiagnosticMessageText(d.messageText, newLine)}${newLine}${newLine}`;
}
/**
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
*/
@@ -151,7 +166,7 @@ namespace ts {
}
if (reportSummary) {
reportSummary(diagnostics.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length);
reportSummary(getErrorCountForSummary(diagnostics));
}
if (emitSkipped && diagnostics.length > 0) {
@@ -227,16 +242,16 @@ namespace ts {
const compilerOptions = builderProgram.getCompilerOptions();
const newLine = getNewLineCharacter(compilerOptions, () => system.newLine);
const reportSummary = (errorCount: number) => {
if (errorCount === 1) {
onWatchStatusChange!(createCompilerDiagnostic(Diagnostics.Found_1_error_Watching_for_file_changes, errorCount), newLine, compilerOptions);
}
else {
onWatchStatusChange!(createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount, errorCount), newLine, compilerOptions);
}
};
emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName, reportSummary);
emitFilesAndReportErrors(
builderProgram,
reportDiagnostic,
writeFileName,
errorCount => onWatchStatusChange!(
createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(errorCount), errorCount),
newLine,
compilerOptions
)
);
}
}
@@ -338,9 +353,9 @@ namespace ts {
getEnvironmentVariable?(name: string): string | undefined;
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModule | undefined)[];
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
}
/** Internal interface used to wire emit through same host */
@@ -484,7 +499,8 @@ namespace ts {
fileExists: path => host.fileExists(path),
readFile,
getCurrentDirectory,
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic,
trace: host.trace ? s => host.trace!(s) : undefined
};
// From tsc we want to get already parsed result and hence check for rootFileNames
@@ -558,11 +574,11 @@ namespace ts {
);
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
compilerHost.resolveModuleNames = host.resolveModuleNames ?
((moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames)) :
((moduleNames, containingFile, reusedNames) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames));
((moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames, redirectedReference)) :
((moduleNames, containingFile, reusedNames, redirectedReference) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference));
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
((typeDirectiveNames, containingFile) => host.resolveTypeReferenceDirectives!(typeDirectiveNames, containingFile)) :
((typeDirectiveNames, containingFile) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile));
((typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(typeDirectiveNames, containingFile, redirectedReference)) :
((typeDirectiveNames, containingFile, redirectedReference) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference));
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
synchronizeProgram();
@@ -764,8 +780,8 @@ namespace ts {
return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString();
}
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions) {
const hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.path);
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
const hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.resolvedPath);
// If this is the source file thats in the cache and new program doesnt need it,
// remove the cached entry.
// Note we arent deleting entry if file became missing in new program or
@@ -779,8 +795,10 @@ namespace ts {
if ((hostSourceFileInfo as FilePresentOnHost).fileWatcher) {
(hostSourceFileInfo as FilePresentOnHost).fileWatcher.close();
}
sourceFilesCache.delete(oldSourceFile.path);
resolutionCache.removeResolutionsOfFile(oldSourceFile.path);
sourceFilesCache.delete(oldSourceFile.resolvedPath);
if (!hasSourceFileByPath) {
resolutionCache.removeResolutionsOfFile(oldSourceFile.path);
}
}
}
}
@@ -875,6 +893,7 @@ namespace ts {
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) {
resolutionCache.invalidateResolutionOfFile(path);
}
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);
nextSourceFileVersion(path);
// Update the program
@@ -934,6 +953,8 @@ namespace ts {
}
nextSourceFileVersion(fileOrDirectoryPath);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
// If the the added or created file or directory is not supported file name, ignore the file
// But when watched directory is added/removed, we need to reload the file list
if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) {
+4
View File
@@ -694,6 +694,10 @@ namespace ts.server {
return response.body!.map(entry => this.decodeSpan(entry, fileName)); // TODO: GH#18217
}
configurePlugin(pluginName: string, configuration: any): void {
this.processRequest<protocol.ConfigurePluginRequest>("configurePlugin", { pluginName, configuration });
}
getIndentationAtPosition(_fileName: string, _position: number, _options: EditorOptions): number {
return notImplemented();
}
+1 -1
View File
@@ -58,7 +58,7 @@ namespace compiler {
private _inputs: documents.TextDocument[] = [];
private _inputsAndOutputs: collections.SortedMap<string, CompilationOutput>;
constructor(host: fakes.CompilerHost, options: ts.CompilerOptions, program: ts.Program | undefined, result: ts.EmitResult | undefined, diagnostics: ts.Diagnostic[]) {
constructor(host: fakes.CompilerHost, options: ts.CompilerOptions, program: ts.Program | undefined, result: ts.EmitResult | undefined, diagnostics: ReadonlyArray<ts.Diagnostic>) {
this.host = host;
this.program = program;
this.result = result;
+610 -486
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -490,7 +490,7 @@ namespace Harness {
getExecutingFilePath(): string;
getWorkspaceRoot(): string;
exit(exitCode?: number): void;
readDirectory(path: string, extension?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
readDirectory(path: string, extension?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): ReadonlyArray<string>;
getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries;
tryEnableSourceMapsForHost?(): void;
getEnvironmentVariable?(name: string): string;
@@ -1159,7 +1159,7 @@ namespace Harness {
}
// If not a primitive, the possible types are specified in what is effectively a map of options.
case "list":
return ts.parseListTypeOption(<ts.CommandLineOptionOfListType>option, value, errors);
return ts.parseListTypeOption(option, value, errors);
default:
return ts.parseCustomTypeOption(<ts.CommandLineOptionOfCustomType>option, value, errors);
}
@@ -1325,6 +1325,9 @@ namespace Harness {
const [, content] = value;
outputLines += content;
}
if (pretty) {
outputLines += ts.getErrorSummaryText(ts.getErrorCountForSummary(diagnostics), IO.newLine());
}
return outputLines;
}
+44 -13
View File
@@ -1,4 +1,18 @@
namespace Harness.LanguageService {
export function makeDefaultProxy(info: ts.server.PluginCreateInfo): ts.LanguageService {
// tslint:disable-next-line:no-null-keyword
const proxy = Object.create(/*prototype*/ null);
const langSvc: any = info.languageService;
for (const k of Object.keys(langSvc)) {
// tslint:disable-next-line only-arrow-functions
proxy[k] = function () {
return langSvc[k].apply(langSvc, arguments);
};
}
return proxy;
}
export class ScriptInfo {
public version = 1;
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
@@ -833,25 +847,42 @@ namespace Harness.LanguageService {
error: undefined
};
// Accepts configurations
case "configurable-diagnostic-adder":
let customMessage = "default message";
return {
module: () => ({
create(info: ts.server.PluginCreateInfo) {
customMessage = info.config.message;
const proxy = makeDefaultProxy(info);
proxy.getSemanticDiagnostics = filename => {
const prev = info.languageService.getSemanticDiagnostics(filename);
const sourceFile: ts.SourceFile = info.project.getSourceFile(ts.toPath(filename, /*basePath*/ undefined, ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!;
prev.push({
category: ts.DiagnosticCategory.Error,
file: sourceFile,
code: 9999,
length: 3,
messageText: customMessage,
start: 0
});
return prev;
};
return proxy;
},
onConfigurationChanged(config: any) {
customMessage = config.message;
}
}),
error: undefined
};
default:
return {
module: undefined,
error: new Error("Could not resolve module")
};
}
function makeDefaultProxy(info: ts.server.PluginCreateInfo): ts.LanguageService {
// tslint:disable-next-line:no-null-keyword
const proxy = Object.create(/*prototype*/ null);
const langSvc: any = info.languageService;
for (const k of Object.keys(langSvc)) {
// tslint:disable-next-line only-arrow-functions
proxy[k] = function () {
return langSvc[k].apply(langSvc, arguments);
};
}
return proxy;
}
}
}
+19 -6
View File
@@ -128,7 +128,7 @@ interface Array<T> {}`
return s && isString((<FsSymLink>s).symLink);
}
function invokeWatcherCallbacks<T>(callbacks: T[], invokeCallback: (cb: T) => void): void {
function invokeWatcherCallbacks<T>(callbacks: ReadonlyArray<T> | undefined, invokeCallback: (cb: T) => void): void {
if (callbacks) {
// The array copy is made to ensure that even if one of the callback removes the callbacks,
// we dont miss any callbacks following it
@@ -341,6 +341,7 @@ interface Array<T> {}`
private readonly currentDirectory: string;
private readonly dynamicPriorityWatchFile: HostWatchFile | undefined;
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
public require: (initialPath: string, moduleName: string) => server.RequireResult;
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
@@ -587,8 +588,8 @@ interface Array<T> {}`
}
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Created);
if (isFsFolder(fileOrDirectory)) {
this.invokeDirectoryWatcher(fileOrDirectory.fullPath, "");
this.invokeWatchedDirectoriesRecursiveCallback(fileOrDirectory.fullPath, "");
this.invokeDirectoryWatcher(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
this.invokeWatchedDirectoriesRecursiveCallback(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
}
this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath);
}
@@ -650,15 +651,15 @@ interface Array<T> {}`
// For overriding the methods
invokeWatchedDirectoriesCallback(folderFullPath: string, relativePath: string) {
invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath));
invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath));
}
invokeWatchedDirectoriesRecursiveCallback(folderFullPath: string, relativePath: string) {
invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath))!, cb => this.directoryCallback(cb, relativePath));
invokeWatcherCallbacks(this.watchedDirectoriesRecursive.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath));
}
private invokeFileWatcher(fileFullPath: string, eventKind: FileWatcherEventKind, useFileNameInCallback?: boolean) {
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath))!, ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind));
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(fileFullPath)), ({ cb, fileName }) => cb(useFileNameInCallback ? fileName : fileFullPath, eventKind));
}
private getRelativePathToDirectory(directoryFullPath: string, fileFullPath: string) {
@@ -988,4 +989,16 @@ interface Array<T> {}`
return this.environmentVariables && this.environmentVariables.get(name) || "";
}
}
export const tsbuildProjectsLocation = "/user/username/projects";
export function getTsBuildProjectFilePath(project: string, file: string) {
return `${tsbuildProjectsLocation}/${project}/${file}`;
}
export function getTsBuildProjectFile(project: string, file: string): File {
return {
path: getTsBuildProjectFilePath(project, file),
content: Harness.IO.readFile(`${Harness.IO.getWorkspaceRoot()}/tests/projects/${project}/${file}`)!
};
}
}
-3
View File
@@ -24,13 +24,11 @@ namespace ts.JsTyping {
version: Version;
}
/* @internal */
export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike<string>) {
const availableVersion = new Version(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!);
return availableVersion.compareTo(cachedTyping.version) <= 0;
}
/* @internal */
export const nodeCoreModuleList: ReadonlyArray<string> = [
"assert",
"async_hooks",
@@ -70,7 +68,6 @@ namespace ts.JsTyping {
"zlib"
];
/* @internal */
export const nodeCoreModules = arrayToSet(nodeCoreModuleList);
/**
-1
View File
@@ -34,7 +34,6 @@ namespace ts.server {
: undefined;
}
/*@internal*/
export function nowString() {
// E.g. "12:34:56.789"
const d = new Date();
-4
View File
@@ -8,10 +8,6 @@ declare namespace ts.server {
export type EventEndInstallTypes = "event::endInstallTypes";
export type EventInitializationFailed = "event::initializationFailed";
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
" __sortedArrayBrand": any;
}
export interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
+24 -18
View File
@@ -142,6 +142,7 @@ interface BiquadFilterOptions extends AudioNodeOptions {
}
interface BlobPropertyBag {
endings?: EndingType;
type?: string;
}
@@ -200,11 +201,12 @@ interface ComputedEffectTiming extends EffectTiming {
progress?: number | null;
}
interface ComputedKeyframe extends Record<keyof CSSStyleDeclaration, string> {
composite?: CompositeOperation | null;
computedOffset?: number;
easing?: string;
offset?: number | null;
interface ComputedKeyframe {
composite: CompositeOperationOrAuto;
computedOffset: number;
easing: string;
offset: number | null;
[property: string]: string | number | null | undefined;
}
interface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation {
@@ -566,10 +568,11 @@ interface KeyboardEventInit extends EventModifierInit {
repeat?: boolean;
}
interface Keyframe extends Record<keyof CSSStyleDeclaration, string> {
composite?: CompositeOperation | null;
interface Keyframe {
composite?: CompositeOperationOrAuto;
easing?: string;
offset?: number | null;
[property: string]: string | number | null | undefined;
}
interface KeyframeAnimationOptions extends KeyframeEffectOptions {
@@ -921,10 +924,11 @@ interface PromiseRejectionEventInit extends EventInit {
reason?: any;
}
interface PropertyIndexedKeyframes extends Record<keyof CSSStyleDeclaration, string | string[]> {
composite?: CompositeOperation | (CompositeOperation | null)[];
interface PropertyIndexedKeyframes {
composite?: CompositeOperationOrAuto | CompositeOperationOrAuto[];
easing?: string | string[];
offset?: number | (number | null)[];
[property: string]: string | string[] | number | null | (number | null)[] | undefined;
}
interface PushSubscriptionJSON {
@@ -3984,7 +3988,7 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par
/**
* Gets a reference to the root node of the document.
*/
readonly documentElement: HTMLElement | null;
readonly documentElement: HTMLElement;
/**
* Returns document's URL.
*/
@@ -4016,7 +4020,7 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par
/**
* Returns the head element.
*/
readonly head: HTMLHeadElement | null;
readonly head: HTMLHeadElement;
readonly hidden: boolean;
/**
* Retrieves a collection, in source order, of img objects in the document.
@@ -4046,7 +4050,7 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par
/**
* Contains information about the current URL.
*/
location: Location | null;
location: Location;
onfullscreenchange: ((this: Document, ev: Event) => any) | null;
onfullscreenerror: ((this: Document, ev: Event) => any) | null;
/**
@@ -4329,7 +4333,7 @@ interface Document extends Node, NonElementParentNode, DocumentOrShadowRoot, Par
*/
elementFromPoint(x: number, y: number): Element | null;
elementsFromPoint(x: number, y: number): Element[];
evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;
evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | ((prefix: string) => string | null) | null, type: number, result: XPathResult | null): XPathResult;
/**
* Executes a command on the current document, current selection, or the given range.
* @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script.
@@ -5013,7 +5017,7 @@ interface FileReader extends EventTarget {
readAsArrayBuffer(blob: Blob): void;
readAsBinaryString(blob: Blob): void;
readAsDataURL(blob: Blob): void;
readAsText(blob: Blob, label?: string): void;
readAsText(blob: Blob, encoding?: string): void;
readonly DONE: number;
readonly EMPTY: number;
readonly LOADING: number;
@@ -7135,7 +7139,7 @@ interface HTMLMediaElement extends HTMLElement {
*/
readonly seekable: TimeRanges;
/**
* Gets a flag that indicates whether the the client is currently moving to a new playback position in the media resource.
* Gets a flag that indicates whether the client is currently moving to a new playback position in the media resource.
*/
readonly seeking: boolean;
/**
@@ -11799,7 +11803,7 @@ declare var ReadableStreamReader: {
interface Request extends Body {
/**
* Returns the cache mode associated with request, which is a string indicating
* how the the request will interact with the browser's cache when fetching.
* how the request will interact with the browser's cache when fetching.
*/
readonly cache: RequestCache;
/**
@@ -16752,7 +16756,7 @@ declare var XMLSerializer: {
interface XPathEvaluator {
createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;
createNSResolver(nodeResolver?: Node): XPathNSResolver;
evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;
evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | ((prefix: string) => string | null) | null, type: number, result: XPathResult | null): XPathResult;
}
declare var XPathEvaluator: {
@@ -16770,7 +16774,7 @@ declare var XPathExpression: {
};
interface XPathNSResolver {
lookupNamespaceURI(prefix: string): string;
lookupNamespaceURI(prefix: string): string | null;
}
declare var XPathNSResolver: {
@@ -17648,11 +17652,13 @@ type ChannelCountMode = "max" | "clamped-max" | "explicit";
type ChannelInterpretation = "speakers" | "discrete";
type ClientTypes = "window" | "worker" | "sharedworker" | "all";
type CompositeOperation = "replace" | "add" | "accumulate";
type CompositeOperationOrAuto = "replace" | "add" | "accumulate" | "auto";
type DirectionSetting = "" | "rl" | "lr";
type DisplayCaptureSurfaceType = "monitor" | "window" | "application" | "browser";
type DistanceModelType = "linear" | "inverse" | "exponential";
type DocumentReadyState = "loading" | "interactive" | "complete";
type EndOfStreamError = "network" | "decode";
type EndingType = "transparent" | "native";
type FillMode = "none" | "forwards" | "backwards" | "both" | "auto";
type GamepadHand = "" | "left" | "right";
type GamepadHapticActuatorType = "vibration";
+2 -1
View File
@@ -9,7 +9,8 @@ interface Map<K, V> {
}
interface MapConstructor {
new <K = any, V = any>(entries?: ReadonlyArray<[K, V]> | null): Map<K, V>;
new(): Map<any, any>;
new<K, V>(entries?: ReadonlyArray<[K, V]> | null): Map<K, V>;
readonly prototype: Map<any, any>;
}
declare var Map: MapConstructor;
+1 -1
View File
@@ -135,7 +135,7 @@ interface MapConstructor {
interface WeakMap<K extends object, V> { }
interface WeakMapConstructor {
new <K extends object = object, V = any>(iterable: Iterable<[K, V]>): WeakMap<K, V>;
new <K extends object, V>(iterable: Iterable<[K, V]>): WeakMap<K, V>;
}
interface Set<T> {
+609
View File
@@ -0,0 +1,609 @@
interface BigInt {
/**
* Returns a string representation of an object.
* @param radix Specifies a radix for converting numeric values to strings.
*/
toString(radix?: number): string;
/** Returns a string representation appropriate to the host environment's current locale. */
toLocaleString(): string;
/** Returns the primitive value of the specified object. */
valueOf(): bigint;
readonly [Symbol.toStringTag]: "BigInt";
}
interface BigIntConstructor {
(value?: any): bigint;
readonly prototype: BigInt;
/**
* Interprets the low bits of a BigInt as a 2's-complement signed integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asIntN(bits: number, int: bigint): bigint;
/**
* Interprets the low bits of a BigInt as an unsigned integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asUintN(bits: number, int: bigint): bigint;
}
declare const BigInt: BigIntConstructor;
/**
* A typed array of 64-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated, an exception is raised.
*/
interface BigInt64Array {
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/** The ArrayBuffer instance referenced by the array. */
readonly buffer: ArrayBufferLike;
/** The length in bytes of the array. */
readonly byteLength: number;
/** The offset in bytes of the array. */
readonly byteOffset: number;
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this;
/** Yields index, value pairs for every entry in the array. */
entries(): IterableIterator<[number, bigint]>;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns false,
* or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: bigint, start?: number, end?: number): this;
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls
* the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: bigint, index: number, array: BigInt64Array) => any, thisArg?: any): BigInt64Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): bigint | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: bigint, index: number, array: BigInt64Array) => void, thisArg?: any): void;
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: bigint, fromIndex?: number): boolean;
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
indexOf(searchElement: bigint, fromIndex?: number): number;
/**
* Adds all the elements of an array separated by the specified separator string.
* @param separator A string used to separate one element of an array from the next in the
* resulting String. If omitted, the array elements are separated with a comma.
*/
join(separator?: string): string;
/** Yields each index in the array. */
keys(): IterableIterator<number>;
/**
* Returns the index of the last occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
lastIndexOf(searchElement: bigint, fromIndex?: number): number;
/** The length of the array. */
readonly length: number;
/**
* Calls a defined callback function on each element of an array, and returns an array that
* contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: bigint, index: number, array: BigInt64Array) => bigint, thisArg?: any): BigInt64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an
* argument instead of an array value.
*/
reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduceRight<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U;
/** Reverses the elements in the array. */
reverse(): this;
/**
* Sets a value or an array of values.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: ArrayLike<bigint>, offset?: number): void;
/**
* Returns a section of an array.
* @param start The beginning of the specified portion of the array.
* @param end The end of the specified portion of the array.
*/
slice(start?: number, end?: number): BigInt64Array;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the
* callbackfn function for each element in the array until the callbackfn returns true, or until
* the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): boolean;
/**
* Sorts the array.
* @param compareFn The function used to determine the order of the elements. If omitted, the elements are sorted in ascending order.
*/
sort(compareFn?: (a: bigint, b: bigint) => number | bigint): this;
/**
* Gets a new BigInt64Array view of the ArrayBuffer store for this array, referencing the elements
* at begin, inclusive, up to end, exclusive.
* @param begin The index of the beginning of the array.
* @param end The index of the end of the array.
*/
subarray(begin: number, end?: number): BigInt64Array;
/** Converts the array to a string by using the current locale. */
toLocaleString(): string;
/** Returns a string representation of the array. */
toString(): string;
/** Yields each value in the array. */
values(): IterableIterator<bigint>;
[Symbol.iterator](): IterableIterator<bigint>;
readonly [Symbol.toStringTag]: "BigInt64Array";
[index: number]: bigint;
}
interface BigInt64ArrayConstructor {
readonly prototype: BigInt64Array;
new(length?: number): BigInt64Array;
new(array: Iterable<bigint>): BigInt64Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigInt64Array;
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of(...items: bigint[]): BigInt64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<bigint>): BigInt64Array;
from<U>(arrayLike: ArrayLike<U>, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigInt64Array;
}
declare const BigInt64Array: BigInt64ArrayConstructor;
/**
* A typed array of 64-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated, an exception is raised.
*/
interface BigUint64Array {
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/** The ArrayBuffer instance referenced by the array. */
readonly buffer: ArrayBufferLike;
/** The length in bytes of the array. */
readonly byteLength: number;
/** The offset in bytes of the array. */
readonly byteOffset: number;
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this;
/** Yields index, value pairs for every entry in the array. */
entries(): IterableIterator<[number, bigint]>;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns false,
* or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: bigint, start?: number, end?: number): this;
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls
* the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: bigint, index: number, array: BigUint64Array) => any, thisArg?: any): BigUint64Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): bigint | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: bigint, index: number, array: BigUint64Array) => void, thisArg?: any): void;
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: bigint, fromIndex?: number): boolean;
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
indexOf(searchElement: bigint, fromIndex?: number): number;
/**
* Adds all the elements of an array separated by the specified separator string.
* @param separator A string used to separate one element of an array from the next in the
* resulting String. If omitted, the array elements are separated with a comma.
*/
join(separator?: string): string;
/** Yields each index in the array. */
keys(): IterableIterator<number>;
/**
* Returns the index of the last occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
lastIndexOf(searchElement: bigint, fromIndex?: number): number;
/** The length of the array. */
readonly length: number;
/**
* Calls a defined callback function on each element of an array, and returns an array that
* contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: bigint, index: number, array: BigUint64Array) => bigint, thisArg?: any): BigUint64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an
* argument instead of an array value.
*/
reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduceRight<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U;
/** Reverses the elements in the array. */
reverse(): this;
/**
* Sets a value or an array of values.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: ArrayLike<bigint>, offset?: number): void;
/**
* Returns a section of an array.
* @param start The beginning of the specified portion of the array.
* @param end The end of the specified portion of the array.
*/
slice(start?: number, end?: number): BigUint64Array;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the
* callbackfn function for each element in the array until the callbackfn returns true, or until
* the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): boolean;
/**
* Sorts the array.
* @param compareFn The function used to determine the order of the elements. If omitted, the elements are sorted in ascending order.
*/
sort(compareFn?: (a: bigint, b: bigint) => number | bigint): this;
/**
* Gets a new BigUint64Array view of the ArrayBuffer store for this array, referencing the elements
* at begin, inclusive, up to end, exclusive.
* @param begin The index of the beginning of the array.
* @param end The index of the end of the array.
*/
subarray(begin: number, end?: number): BigUint64Array;
/** Converts the array to a string by using the current locale. */
toLocaleString(): string;
/** Returns a string representation of the array. */
toString(): string;
/** Yields each value in the array. */
values(): IterableIterator<bigint>;
[Symbol.iterator](): IterableIterator<bigint>;
readonly [Symbol.toStringTag]: "BigUint64Array";
[index: number]: bigint;
}
interface BigUint64ArrayConstructor {
readonly prototype: BigUint64Array;
new(length?: number): BigUint64Array;
new(array: Iterable<bigint>): BigUint64Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigUint64Array;
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of(...items: bigint[]): BigUint64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<bigint>): BigUint64Array;
from<U>(arrayLike: ArrayLike<U>, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigUint64Array;
}
declare const BigUint64Array: BigUint64ArrayConstructor;
interface DataView {
/**
* Gets the BigInt64 value at the specified byte offset from the start of the view. There is
* no alignment constraint; multi-byte values may be fetched from any offset.
* @param byteOffset The place in the buffer at which the value should be retrieved.
*/
getBigInt64(byteOffset: number, littleEndian?: boolean): bigint;
/**
* Gets the BigUint64 value at the specified byte offset from the start of the view. There is
* no alignment constraint; multi-byte values may be fetched from any offset.
* @param byteOffset The place in the buffer at which the value should be retrieved.
*/
getBigUint64(byteOffset: number, littleEndian?: boolean): bigint;
/**
* Stores a BigInt64 value at the specified byte offset from the start of the view.
* @param byteOffset The place in the buffer at which the value should be set.
* @param value The value to set.
* @param littleEndian If false or undefined, a big-endian value should be written,
* otherwise a little-endian value should be written.
*/
setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void;
/**
* Stores a BigUint64 value at the specified byte offset from the start of the view.
* @param byteOffset The place in the buffer at which the value should be set.
* @param value The value to set.
* @param littleEndian If false or undefined, a big-endian value should be written,
* otherwise a little-endian value should be written.
*/
setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void;
}
+1
View File
@@ -1,5 +1,6 @@
/// <reference lib="es2018" />
/// <reference lib="esnext.asynciterable" />
/// <reference lib="esnext.array" />
/// <reference lib="esnext.bigint" />
/// <reference lib="esnext.symbol" />
/// <reference lib="esnext.intl" />
+1
View File
@@ -34,6 +34,7 @@
"es2018.intl",
"esnext.asynciterable",
"esnext.array",
"esnext.bigint",
"esnext.symbol",
"esnext.intl",
// Default libraries
+28 -3
View File
@@ -39,6 +39,7 @@ interface Algorithm {
}
interface BlobPropertyBag {
endings?: EndingType;
type?: string;
}
@@ -1197,7 +1198,7 @@ interface FileReader extends EventTarget {
readAsArrayBuffer(blob: Blob): void;
readAsBinaryString(blob: Blob): void;
readAsDataURL(blob: Blob): void;
readAsText(blob: Blob, label?: string): void;
readAsText(blob: Blob, encoding?: string): void;
readonly DONE: number;
readonly EMPTY: number;
readonly LOADING: number;
@@ -1219,7 +1220,7 @@ interface FileReaderSync {
readAsArrayBuffer(blob: Blob): ArrayBuffer;
readAsBinaryString(blob: Blob): string;
readAsDataURL(blob: Blob): string;
readAsText(blob: Blob, label?: string): string;
readAsText(blob: Blob, encoding?: string): string;
}
declare var FileReaderSync: {
@@ -2202,7 +2203,7 @@ declare var ReadableStreamReader: {
interface Request extends Body {
/**
* Returns the cache mode associated with request, which is a string indicating
* how the the request will interact with the browser's cache when fetching.
* how the request will interact with the browser's cache when fetching.
*/
readonly cache: RequestCache;
/**
@@ -2524,6 +2525,29 @@ declare var TextEncoder: {
new(): TextEncoder;
};
interface TextMetrics {
readonly actualBoundingBoxAscent: number;
readonly actualBoundingBoxDescent: number;
readonly actualBoundingBoxLeft: number;
readonly actualBoundingBoxRight: number;
readonly alphabeticBaseline: number;
readonly emHeightAscent: number;
readonly emHeightDescent: number;
readonly fontBoundingBoxAscent: number;
readonly fontBoundingBoxDescent: number;
readonly hangingBaseline: number;
/**
* Returns the measurement described below.
*/
readonly ideographicBaseline: number;
readonly width: number;
}
declare var TextMetrics: {
prototype: TextMetrics;
new(): TextMetrics;
};
interface URL {
hash: string;
host: string;
@@ -2967,6 +2991,7 @@ type IDBValidKey = number | string | Date | BufferSource | IDBArrayKey;
type Transferable = ArrayBuffer | MessagePort | ImageBitmap;
type BinaryType = "blob" | "arraybuffer";
type ClientTypes = "window" | "worker" | "sharedworker" | "all";
type EndingType = "transparent" | "native";
type IDBCursorDirection = "next" | "nextunique" | "prev" | "prevunique";
type IDBRequestReadyState = "pending" | "done";
type IDBTransactionMode = "readonly" | "readwrite" | "versionchange";
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<LCX SchemaVersion="6.0" Name="f:\ddSetup\sources\typescript\localization\compiler2.resx" PsrId="306" FileType="1" SrcCul="en-US" TgtCul="zh-TW" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
<Props>
<Str Name="CustomName1" Val="Custom 1" />
@@ -3766,7 +3766,7 @@
<Str Cat="Text">
<Val><![CDATA[Extract constant]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮常數]]></Val>
<Val><![CDATA[擷取常數]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -3775,7 +3775,7 @@
<Str Cat="Text">
<Val><![CDATA[Extract function]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮函式]]></Val>
<Val><![CDATA[擷取函式]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -3784,7 +3784,7 @@
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1}]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮至 {1} 中的 {0}]]></Val>
<Val><![CDATA[擷取至 {1} 中的 {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -3793,7 +3793,7 @@
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in {1} scope]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮至 {1} 範圍中的 {0}]]></Val>
<Val><![CDATA[擷取至 {1} 範圍中的 {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -3802,7 +3802,7 @@
<Str Cat="Text">
<Val><![CDATA[Extract to {0} in enclosing scope]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[解壓縮至封閉式範圍中的 {0}]]></Val>
<Val><![CDATA[擷取至封閉式範圍中的 {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
@@ -5437,7 +5437,7 @@
<Str Cat="Text">
<Val><![CDATA[Move to a new file]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[移至新]]></Val>
<Val><![CDATA[移至新]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
File diff suppressed because it is too large Load Diff
+82 -47
View File
@@ -486,7 +486,7 @@ namespace ts.server {
private readonly hostConfiguration: HostConfiguration;
private safelist: SafeList = defaultTypeSafeList;
private legacySafelist: { [key: string]: string } = {};
private readonly legacySafelist = createMap<string>();
private pendingProjectUpdates = createMap<Project>();
/* @internal */
@@ -509,6 +509,8 @@ namespace ts.server {
public readonly globalPlugins: ReadonlyArray<string>;
public readonly pluginProbeLocations: ReadonlyArray<string>;
public readonly allowLocalPluginLoads: boolean;
private currentPluginConfigOverrides: Map<any> | undefined;
public readonly typesMapLocation: string | undefined;
public readonly syntaxOnly?: boolean;
@@ -561,7 +563,7 @@ namespace ts.server {
this.typingsCache = new TypingsCache(this.typingsInstaller);
this.hostConfiguration = {
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
formatCodeOptions: getDefaultFormatCodeSettings(this.host.newLine),
preferences: emptyOptions,
hostInfo: "Unknown host",
extraFileExtensions: []
@@ -638,14 +640,14 @@ namespace ts.server {
this.safelist = raw.typesMap;
for (const key in raw.simpleMap) {
if (raw.simpleMap.hasOwnProperty(key)) {
this.legacySafelist[key] = raw.simpleMap[key].toLowerCase();
this.legacySafelist.set(key, raw.simpleMap[key].toLowerCase());
}
}
}
catch (e) {
this.logger.info(`Error loading types map: ${e}`);
this.safelist = defaultTypeSafeList;
this.legacySafelist = {};
this.legacySafelist.clear();
}
}
@@ -833,9 +835,9 @@ namespace ts.server {
/* @internal */
private forEachProject(cb: (project: Project) => void) {
this.inferredProjects.forEach(cb);
this.configuredProjects.forEach(cb);
this.externalProjects.forEach(cb);
this.configuredProjects.forEach(cb);
this.inferredProjects.forEach(cb);
}
/* @internal */
@@ -865,7 +867,7 @@ namespace ts.server {
private doEnsureDefaultProjectForFile(fileName: NormalizedPath): Project {
this.ensureProjectStructuresUptoDate();
const scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
return scriptInfo ? scriptInfo.getDefaultProject() : Errors.ThrowNoProject();
return scriptInfo ? scriptInfo.getDefaultProject() : (this.logErrorForScriptInfoNotFound(fileName), Errors.ThrowNoProject());
}
getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) {
@@ -918,15 +920,20 @@ namespace ts.server {
if (!info) {
this.logger.msg(`Error: got watch notification for unknown file: ${fileName}`);
}
else if (eventKind === FileWatcherEventKind.Deleted) {
// File was deleted
this.handleDeletedFile(info);
}
else if (!info.isScriptOpen()) {
// file has been changed which might affect the set of referenced files in projects that include
// this file and set of inferred projects
info.delayReloadNonMixedContentFile();
this.delayUpdateProjectGraphs(info.containingProjects);
else {
if (info.containingProjects) {
info.containingProjects.forEach(project => project.resolutionCache.removeResolutionsFromProjectReferenceRedirects(info.path));
}
if (eventKind === FileWatcherEventKind.Deleted) {
// File was deleted
this.handleDeletedFile(info);
}
else if (!info.isScriptOpen()) {
// file has been changed which might affect the set of referenced files in projects that include
// this file and set of inferred projects
info.delayReloadNonMixedContentFile();
this.delayUpdateProjectGraphs(info.containingProjects);
}
}
}
@@ -957,6 +964,7 @@ namespace ts.server {
fileOrDirectory => {
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
const configFilename = project.getConfigFilePath();
// If the the added or created file or directory is not supported file name, ignore the file
@@ -1029,11 +1037,12 @@ namespace ts.server {
}
private removeProject(project: Project) {
this.logger.info(`remove project: ${project.getRootFiles().toString()}`);
this.logger.info("`remove Project::");
project.print();
project.close();
if (Debug.shouldAssert(AssertionLevel.Normal)) {
this.filenameToScriptInfo.forEach(info => Debug.assert(!info.isAttached(project)));
this.filenameToScriptInfo.forEach(info => Debug.assert(!info.isAttached(project), "Found script Info still attached to project", () => `${project.projectName}: ScriptInfos still attached: ${JSON.stringify(mapDefined(arrayFrom(this.filenameToScriptInfo.values()), info => info.isAttached(project) ? info : undefined))}`));
}
// Remove the project from pending project updates
this.pendingProjectUpdates.delete(project.getProjectName());
@@ -1469,19 +1478,9 @@ namespace ts.server {
const writeProjectFileNames = this.logger.hasLevel(LogLevel.verbose);
this.logger.startGroup();
let counter = 0;
const printProjects = (projects: Project[], counter: number): number => {
for (const project of projects) {
this.logger.info(`Project '${project.getProjectName()}' (${ProjectKind[project.projectKind]}) ${counter}`);
this.logger.info(project.filesToString(writeProjectFileNames));
this.logger.info("-----------------------------------------------");
counter++;
}
return counter;
};
counter = printProjects(this.externalProjects, counter);
counter = printProjects(arrayFrom(this.configuredProjects.values()), counter);
printProjects(this.inferredProjects, counter);
let counter = printProjectsWithCounter(this.externalProjects, 0);
counter = printProjectsWithCounter(arrayFrom(this.configuredProjects.values()), counter);
printProjectsWithCounter(this.inferredProjects, counter);
this.logger.info("Open files: ");
this.openFiles.forEach((projectRootPath, path) => {
@@ -1737,7 +1736,7 @@ namespace ts.server {
project.enableLanguageService();
project.watchWildcards(createMapFromTemplate(parsedCommandLine.wildcardDirectories!)); // TODO: GH#18217
}
project.enablePluginsWithOptions(compilerOptions);
project.enablePluginsWithOptions(compilerOptions, this.currentPluginConfigOverrides);
const filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles());
this.updateRootAndOptionsOfNonInferredProject(project, filesToAdd, fileNamePropertyReader, compilerOptions, parsedCommandLine.typeAcquisition!, parsedCommandLine.compileOnSave!); // TODO: GH#18217
}
@@ -1927,7 +1926,7 @@ namespace ts.server {
private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject {
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects;
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath, currentDirectory);
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath, currentDirectory, this.currentPluginConfigOverrides);
if (isSingleInferredProject) {
this.inferredProjects.unshift(project);
}
@@ -1958,6 +1957,12 @@ namespace ts.server {
return configProject && configProject.getCompilerOptions().configFile;
}
/* @internal */
logErrorForScriptInfoNotFound(fileName: string): void {
const names = arrayFrom(this.filenameToScriptInfo.entries()).map(([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName }));
this.logger.msg(`Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, Msg.Err);
}
/**
* Returns the projects that contain script info through SymLink
* Note that this does not return projects in info.containingProjects
@@ -2035,6 +2040,8 @@ namespace ts.server {
watchDir,
(fileOrDirectory) => {
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
// Has extension
Debug.assert(result.refCount > 0);
if (watchDir === fileOrDirectoryPath) {
@@ -2102,7 +2109,20 @@ namespace ts.server {
}
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) {
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
if (isRootedDiskPath(fileName) || isDynamicFileName(fileName)) {
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
}
// This is non rooted path with different current directory than project service current directory
// Only paths recognized are open relative file paths
const info = this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName));
if (info) {
return info;
}
// This means triple slash references wont be resolved in dynamic and unsaved files
// which is intentional since we dont know what it means to be relative to non disk files
return undefined;
}
private getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) {
@@ -2119,7 +2139,7 @@ namespace ts.server {
let info = this.getScriptInfoForPath(path);
if (!info) {
const isDynamic = isDynamicFileName(fileName);
Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info`);
Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`);
Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`);
Debug.assert(!isDynamic || this.currentDirectory === currentDirectory, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always have current directory context since containing external project name will always match the script info name.`);
// If the file is not opened by client and the file doesnot exist on the disk, return
@@ -2132,7 +2152,7 @@ namespace ts.server {
if (!openedByClient) {
this.watchClosedScriptInfo(info);
}
else if (!isRootedDiskPath(fileName) && currentDirectory !== this.currentDirectory) {
else if (!isRootedDiskPath(fileName) && !isDynamic) {
// File that is opened by user but isn't rooted disk path
this.openFilesWithNonRootedDiskPath.set(this.toCanonicalFileName(fileName), info);
}
@@ -2487,17 +2507,14 @@ namespace ts.server {
}
else {
// If the configured project for project reference has more than zero references, keep it alive
const resolvedProjectReferences = project.getResolvedProjectReferences();
if (resolvedProjectReferences) {
for (const ref of resolvedProjectReferences) {
if (ref) {
const refProject = this.configuredProjects.get(ref.sourceFile.path);
if (refProject && refProject.hasOpenRef()) {
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
}
project.forEachResolvedProjectReference(ref => {
if (ref) {
const refProject = this.configuredProjects.get(ref.sourceFile.path);
if (refProject && refProject.hasOpenRef()) {
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
}
}
}
});
}
});
@@ -2721,13 +2738,13 @@ namespace ts.server {
if (fileExtensionIs(baseName, "js")) {
const inferredTypingName = removeFileExtension(baseName);
const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName);
if (this.legacySafelist[cleanedTypingName]) {
const typeName = this.legacySafelist.get(cleanedTypingName);
if (typeName !== undefined) {
this.logger.info(`Excluded '${normalizedNames[i]}' because it matched ${cleanedTypingName} from the legacy safelist`);
excludedFiles.push(normalizedNames[i]);
// *exclude* it from the project...
exclude = true;
// ... but *include* it in the list of types to acquire
const typeName = this.legacySafelist[cleanedTypingName];
// Same best-effort dedupe as above
if (typeAcqInclude.indexOf(typeName) < 0) {
typeAcqInclude.push(typeName);
@@ -2878,6 +2895,16 @@ namespace ts.server {
return false;
}
configurePlugin(args: protocol.ConfigurePluginRequestArguments) {
// For any projects that already have the plugin loaded, configure the plugin
this.forEachEnabledProject(project => project.onPluginConfigurationChanged(args.pluginName, args.configuration));
// Also save the current configuration to pass on to any projects that are yet to be loaded.
// If a plugin is configured twice, only the latest configuration will be remembered.
this.currentPluginConfigOverrides = this.currentPluginConfigOverrides || createMap();
this.currentPluginConfigOverrides.set(args.pluginName, args.configuration);
}
}
/* @internal */
@@ -2886,4 +2913,12 @@ namespace ts.server {
export function isConfigFile(config: ScriptInfoOrConfig): config is TsConfigSourceFile {
return (config as TsConfigSourceFile).kind !== undefined;
}
function printProjectsWithCounter(projects: Project[], counter: number) {
for (const project of projects) {
project.print(counter);
counter++;
}
return counter;
}
}
+104 -92
View File
@@ -72,6 +72,12 @@ namespace ts.server {
export interface PluginModule {
create(createInfo: PluginCreateInfo): LanguageService;
getExternalFiles?(proj: Project): string[];
onConfigurationChanged?(config: any): void;
}
export interface PluginModuleWithName {
name: string;
module: PluginModule;
}
export type PluginModuleFactory = (mod: { typescript: typeof ts }) => PluginModule;
@@ -92,7 +98,7 @@ namespace ts.server {
private program: Program;
private externalFiles: SortedReadonlyArray<string>;
private missingFilesMap: Map<FileWatcher>;
private plugins: PluginModule[] = [];
private plugins: PluginModuleWithName[] = [];
/*@internal*/
/**
@@ -198,7 +204,7 @@ namespace ts.server {
/*@internal*/
constructor(
/*@internal*/readonly projectName: string,
readonly projectName: string,
readonly projectKind: ProjectKind,
readonly projectService: ProjectService,
private documentRegistry: DocumentRegistry,
@@ -281,8 +287,8 @@ namespace ts.server {
return this.projectStateVersion.toString();
}
getProjectReferences(): ReadonlyArray<ProjectReference> {
return emptyArray;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return undefined;
}
getScriptFileNames() {
@@ -368,16 +374,16 @@ namespace ts.server {
return !this.isWatchedMissingFile(path) && this.directoryStructureHost.fileExists(file);
}
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModuleFull[] {
return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames);
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModuleFull | undefined)[] {
return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference);
}
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined {
return this.resolutionCache.getResolvedModuleWithFailedLookupLocationsFromCache(moduleName, containingFile);
}
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
return this.resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile);
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[] {
return this.resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference);
}
directoryExists(path: string): boolean {
@@ -548,10 +554,10 @@ namespace ts.server {
}
getExternalFiles(): SortedReadonlyArray<string> {
return toSortedArray(flatMap(this.plugins, plugin => {
if (typeof plugin.getExternalFiles !== "function") return;
return sort(flatMap(this.plugins, plugin => {
if (typeof plugin.module.getExternalFiles !== "function") return;
try {
return plugin.getExternalFiles(this);
return plugin.module.getExternalFiles(this);
}
catch (e) {
this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`);
@@ -583,14 +589,11 @@ namespace ts.server {
for (const f of this.program.getSourceFiles()) {
this.detachScriptInfoIfNotRoot(f.fileName);
}
const projectReferences = this.program.getResolvedProjectReferences();
if (projectReferences) {
for (const ref of projectReferences) {
if (ref) {
this.detachScriptInfoFromProject(ref.sourceFile.fileName);
}
this.program.forEachResolvedProjectReference(ref => {
if (ref) {
this.detachScriptInfoFromProject(ref.sourceFile.fileName);
}
}
});
}
// Release external files
forEach(this.externalFiles, externalFile => this.detachScriptInfoIfNotRoot(externalFile));
@@ -792,41 +795,6 @@ namespace ts.server {
}
}
/* @internal */
private extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: string[]): ReadonlyArray<string> {
const cached = this.cachedUnresolvedImportsPerFile.get(file.path);
if (cached) {
// found cached result, return
return cached;
}
let unresolvedImports: string[] | undefined;
if (file.resolvedModules) {
file.resolvedModules.forEach((resolvedModule, name) => {
// pick unresolved non-relative names
if (!resolvedModule && !isExternalModuleNameRelative(name) && !isAmbientlyDeclaredModule(name)) {
// for non-scoped names extract part up-to the first slash
// for scoped names - extract up to the second slash
let trimmed = name.trim();
let i = trimmed.indexOf("/");
if (i !== -1 && trimmed.charCodeAt(0) === CharacterCodes.at) {
i = trimmed.indexOf("/", i + 1);
}
if (i !== -1) {
trimmed = trimmed.substr(0, i);
}
(unresolvedImports || (unresolvedImports = [])).push(trimmed);
}
});
}
this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray);
return unresolvedImports || emptyArray;
function isAmbientlyDeclaredModule(name: string) {
return ambientModules.some(m => m === name);
}
}
/* @internal */
onFileAddedOrRemoved() {
this.hasAddedorRemovedFiles = true;
@@ -860,15 +828,7 @@ namespace ts.server {
// (can reuse cached imports for files that were not changed)
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
if (hasNewProgram || changedFiles.length) {
let result: string[] | undefined;
const ambientModules = this.program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName()));
for (const sourceFile of this.program.getSourceFiles()) {
const unResolved = this.extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules);
if (unResolved !== emptyArray) {
(result || (result = [])).push(...unResolved);
}
}
this.lastCachedUnresolvedImportsList = result ? toDeduplicatedSortedArray(result) : emptyArray;
this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program, this.cachedUnresolvedImportsPerFile);
}
this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles);
@@ -885,7 +845,7 @@ namespace ts.server {
/*@internal*/
updateTypingFiles(typingFiles: SortedReadonlyArray<string>) {
enumerateInsertsAndDeletes(typingFiles, this.typingFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
enumerateInsertsAndDeletes<string, string>(typingFiles, this.typingFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
/*inserted*/ noop,
removed => this.detachScriptInfoFromProject(removed)
);
@@ -925,12 +885,19 @@ namespace ts.server {
if (hasNewProgram) {
if (oldProgram) {
for (const f of oldProgram.getSourceFiles()) {
if (this.program.getSourceFileByPath(f.path)) {
continue;
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));
}
// new program does not contain this file - detach it from the project
this.detachScriptInfoFromProject(f.fileName);
}
oldProgram.forEachResolvedProjectReference((resolvedProjectReference, resolvedProjectReferencePath) => {
if (resolvedProjectReference && !this.program.getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) {
this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName);
}
});
}
// Update the missing file paths watcher
@@ -949,7 +916,7 @@ namespace ts.server {
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
this.externalFiles = this.getExternalFiles();
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
enumerateInsertsAndDeletes<string, string>(this.externalFiles, oldExternalFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
// by the LSHost for files in the program when the program is retrieved above but
// the program doesn't contain external files so this must be done explicitly.
@@ -964,11 +931,13 @@ namespace ts.server {
return hasNewProgram;
}
private detachScriptInfoFromProject(uncheckedFileName: string) {
private detachScriptInfoFromProject(uncheckedFileName: string, noRemoveResolution?: boolean) {
const scriptInfoToDetach = this.projectService.getScriptInfo(uncheckedFileName);
if (scriptInfoToDetach) {
scriptInfoToDetach.detachFromProject(this);
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path);
if (!noRemoveResolution) {
this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path);
}
}
}
@@ -1026,6 +995,13 @@ namespace ts.server {
return strBuilder;
}
/*@internal*/
print(counter?: number) {
this.writeLog(`Project '${this.projectName}' (${ProjectKind[this.projectKind]}) ${counter === undefined ? "" : counter}`);
this.writeLog(this.filesToString(this.projectService.logger.hasLevel(LogLevel.verbose)));
this.writeLog("-----------------------------------------------");
}
setCompilerOptions(compilerOptions: CompilerOptions) {
if (compilerOptions) {
compilerOptions.allowNonTsExtensions = true;
@@ -1105,7 +1081,7 @@ namespace ts.server {
this.rootFilesMap.delete(info.path);
}
protected enableGlobalPlugins(options: CompilerOptions) {
protected enableGlobalPlugins(options: CompilerOptions, pluginConfigOverrides: Map<any> | undefined) {
const host = this.projectService.host;
if (!host.require) {
@@ -1128,12 +1104,13 @@ namespace ts.server {
// Provide global: true so plugins can detect why they can't find their config
this.projectService.logger.info(`Loading global plugin ${globalPluginName}`);
this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths);
this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths, pluginConfigOverrides);
}
}
}
protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]) {
protected enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[], pluginConfigOverrides: Map<any> | undefined) {
this.projectService.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`);
const log = (message: string) => {
@@ -1143,6 +1120,14 @@ namespace ts.server {
const resolvedModule = firstDefined(searchPaths, searchPath =>
<PluginModuleFactory | undefined>Project.resolveModule(pluginConfigEntry.name, searchPath, this.projectService.host, log));
if (resolvedModule) {
const configurationOverride = pluginConfigOverrides && pluginConfigOverrides.get(pluginConfigEntry.name);
if (configurationOverride) {
// Preserve the name property since it's immutable
const pluginName = pluginConfigEntry.name;
pluginConfigEntry = configurationOverride;
pluginConfigEntry.name = pluginName;
}
this.enableProxy(resolvedModule, pluginConfigEntry);
}
else {
@@ -1150,11 +1135,6 @@ namespace ts.server {
}
}
/** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */
refreshDiagnostics() {
this.projectService.sendProjectsUpdatedInBackgroundEvent();
}
private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) {
try {
if (typeof pluginModuleFactory !== "function") {
@@ -1180,12 +1160,47 @@ namespace ts.server {
}
this.projectService.logger.info(`Plugin validation succeded`);
this.languageService = newLS;
this.plugins.push(pluginModule);
this.plugins.push({ name: configEntry.name, module: pluginModule });
}
catch (e) {
this.projectService.logger.info(`Plugin activation failed: ${e}`);
}
}
/*@internal*/
onPluginConfigurationChanged(pluginName: string, configuration: any) {
this.plugins.filter(plugin => plugin.name === pluginName).forEach(plugin => {
if (plugin.module.onConfigurationChanged) {
plugin.module.onConfigurationChanged(configuration);
}
});
}
/** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */
refreshDiagnostics() {
this.projectService.sendProjectsUpdatedInBackgroundEvent();
}
}
function getUnresolvedImports(program: Program, cachedUnresolvedImportsPerFile: Map<ReadonlyArray<string>>): SortedReadonlyArray<string> {
const ambientModules = program.getTypeChecker().getAmbientModules().map(mod => stripQuotes(mod.getName()));
return sortAndDeduplicate(flatMap(program.getSourceFiles(), sourceFile =>
extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile)));
}
function extractUnresolvedImportsFromSourceFile(file: SourceFile, ambientModules: ReadonlyArray<string>, cachedUnresolvedImportsPerFile: Map<ReadonlyArray<string>>): ReadonlyArray<string> {
return getOrUpdate(cachedUnresolvedImportsPerFile, file.path, () => {
if (!file.resolvedModules) return emptyArray;
let unresolvedImports: string[] | undefined;
file.resolvedModules.forEach((resolvedModule, name) => {
// pick unresolved non-relative names
if ((!resolvedModule || !resolutionExtensionIsTSOrJson(resolvedModule.extension)) &&
!isExternalModuleNameRelative(name) &&
!ambientModules.some(m => m === name)) {
unresolvedImports = append(unresolvedImports, parsePackageName(name).packageName);
}
});
return unresolvedImports || emptyArray;
});
}
/**
@@ -1241,7 +1256,8 @@ namespace ts.server {
documentRegistry: DocumentRegistry,
compilerOptions: CompilerOptions,
projectRootPath: NormalizedPath | undefined,
currentDirectory: string | undefined) {
currentDirectory: string | undefined,
pluginConfigOverrides: Map<any> | undefined) {
super(InferredProject.newName(),
ProjectKind.Inferred,
projectService,
@@ -1257,7 +1273,7 @@ namespace ts.server {
if (!projectRootPath && !projectService.useSingleInferredProject) {
this.canonicalCurrentDirectory = projectService.toCanonicalFileName(this.currentDirectory);
}
this.enableGlobalPlugins(this.getCompilerOptions());
this.enableGlobalPlugins(this.getCompilerOptions(), pluginConfigOverrides);
}
addRoot(info: ScriptInfo) {
@@ -1399,8 +1415,8 @@ namespace ts.server {
return asNormalizedPath(this.getProjectName());
}
getProjectReferences(): ReadonlyArray<ProjectReference> {
return this.projectReferences || emptyArray;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return this.projectReferences;
}
updateReferences(refs: ReadonlyArray<ProjectReference> | undefined) {
@@ -1408,17 +1424,13 @@ namespace ts.server {
}
/*@internal*/
getResolvedProjectReferences() {
forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined): T | undefined {
const program = this.getCurrentProgram();
return program && program.getResolvedProjectReferences();
}
enablePlugins() {
this.enablePluginsWithOptions(this.getCompilerOptions());
return program && program.forEachResolvedProjectReference(cb);
}
/*@internal*/
enablePluginsWithOptions(options: CompilerOptions) {
enablePluginsWithOptions(options: CompilerOptions, pluginConfigOverrides: Map<any> | undefined) {
const host = this.projectService.host;
if (!host.require) {
@@ -1439,11 +1451,11 @@ namespace ts.server {
// Enable tsconfig-specified plugins
if (options.plugins) {
for (const pluginConfigEntry of options.plugins) {
this.enablePlugin(pluginConfigEntry, searchPaths);
this.enablePlugin(pluginConfigEntry, searchPaths, pluginConfigOverrides);
}
}
this.enableGlobalPlugins(options);
this.enableGlobalPlugins(options, pluginConfigOverrides);
}
/**
+22 -1
View File
@@ -129,6 +129,7 @@ namespace ts.server.protocol {
GetEditsForFileRename = "getEditsForFileRename",
/* @internal */
GetEditsForFileRenameFull = "getEditsForFileRename-full",
ConfigurePlugin = "configurePlugin"
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
}
@@ -220,6 +221,11 @@ namespace ts.server.protocol {
* Contains message body if success === true.
*/
body?: any;
/**
* Contains extra information that plugin can include to be passed on
*/
metadata?: unknown;
}
/**
@@ -1023,7 +1029,7 @@ namespace ts.server.protocol {
/**
* The file locations referencing the symbol.
*/
refs: ReferencesResponseItem[];
refs: ReadonlyArray<ReferencesResponseItem>;
/**
* The name of the symbol.
@@ -1375,6 +1381,16 @@ namespace ts.server.protocol {
export interface ConfigureResponse extends Response {
}
export interface ConfigurePluginRequestArguments {
pluginName: string;
configuration: any;
}
export interface ConfigurePluginRequest extends Request {
command: CommandTypes.ConfigurePlugin;
arguments: ConfigurePluginRequestArguments;
}
/**
* Information found in an "open" request.
*/
@@ -2390,6 +2406,7 @@ namespace ts.server.protocol {
*/
export interface DiagnosticEvent extends Event {
body?: DiagnosticEventBody;
event: DiagnosticEventKind;
}
export interface ConfigFileDiagnosticEventBody {
@@ -2509,6 +2526,10 @@ namespace ts.server.protocol {
maxFileSize: number;
}
/*@internal*/
export type AnyEvent = RequestCompletedEvent | DiagnosticEvent | ConfigFileDiagnosticEvent | ProjectLanguageServiceStateEvent | TelemetryEvent |
ProjectsUpdatedInBackgroundEvent | ProjectLoadingStartEvent | ProjectLoadingFinishEvent | SurveyReadyEvent | LargeFileReferencedEvent;
/**
* Arguments for reload request.
*/
+1 -2
View File
@@ -6,7 +6,6 @@ namespace ts.server {
/* @internal */
export class TextStorage {
/*@internal*/
version: ScriptInfoVersion;
/**
@@ -438,7 +437,7 @@ namespace ts.server {
setOptions(formatSettings: FormatCodeSettings, preferences: protocol.UserPreferences | undefined): void {
if (formatSettings) {
if (!this.formatSettings) {
this.formatSettings = getDefaultFormatCodeSettings(this.host);
this.formatSettings = getDefaultFormatCodeSettings(this.host.newLine);
assign(this.formatSettings, formatSettings);
}
else {
-1
View File
@@ -382,7 +382,6 @@ namespace ts.server {
}
}
/* @internal */
export class LineIndex {
root: LineNode;
// set this to true to check each edit for accuracy
+109 -47
View File
@@ -267,7 +267,7 @@ namespace ts.server {
projects: Projects,
action: (project: Project, value: T) => ReadonlyArray<U> | U | undefined,
): U[] {
const outputs = flatMap(isArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
const outputs = flatMapToMutable(isArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
if (!isArray(projects) && projects.symLinkedProjects) {
projects.symLinkedProjects.forEach((projects, path) => {
const value = getValue(path as Path);
@@ -289,7 +289,6 @@ namespace ts.server {
function combineProjectOutputWhileOpeningReferencedProjects<T>(
projects: Projects,
defaultProject: Project,
projectService: ProjectService,
action: (project: Project) => ReadonlyArray<T>,
getLocation: (t: T) => DocumentPosition,
resultsEqual: (a: T, b: T) => boolean,
@@ -299,7 +298,6 @@ namespace ts.server {
projects,
defaultProject,
/*initialLocation*/ undefined,
projectService,
({ project }, tryAddToTodo) => {
for (const output of action(project)) {
if (!contains(outputs, output, resultsEqual) && !tryAddToTodo(project, getLocation(output))) {
@@ -312,17 +310,27 @@ namespace ts.server {
}
function combineProjectOutputForRenameLocations(
projects: Projects, defaultProject: Project, initialLocation: DocumentPosition, projectService: ProjectService, findInStrings: boolean, findInComments: boolean
projects: Projects,
defaultProject: Project,
initialLocation: DocumentPosition,
findInStrings: boolean,
findInComments: boolean
): ReadonlyArray<RenameLocation> {
const outputs: RenameLocation[] = [];
combineProjectOutputWorker<DocumentPosition>(projects, defaultProject, initialLocation, projectService, ({ project, location }, tryAddToTodo) => {
combineProjectOutputWorker<DocumentPosition>(
projects,
defaultProject,
initialLocation,
({ project, location }, tryAddToTodo) => {
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments) || emptyArray) {
if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) {
outputs.push(output);
if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) {
outputs.push(output);
}
}
}
}, () => getDefinitionLocation(defaultProject, initialLocation));
},
() => getDefinitionLocation(defaultProject, initialLocation)
);
return outputs;
}
@@ -333,31 +341,41 @@ namespace ts.server {
return info && { fileName: info.fileName, pos: info.textSpan.start };
}
function combineProjectOutputForReferences(projects: Projects, defaultProject: Project, initialLocation: DocumentPosition, projectService: ProjectService): ReadonlyArray<ReferencedSymbol> {
function combineProjectOutputForReferences(
projects: Projects,
defaultProject: Project,
initialLocation: DocumentPosition
): ReadonlyArray<ReferencedSymbol> {
const outputs: ReferencedSymbol[] = [];
combineProjectOutputWorker<DocumentPosition>(projects, defaultProject, initialLocation, projectService, ({ project, location }, getMappedLocation) => {
combineProjectOutputWorker<DocumentPosition>(
projects,
defaultProject,
initialLocation,
({ project, location }, getMappedLocation) => {
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) {
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
...outputReferencedSymbol.definition,
textSpan: createTextSpan(mappedDefinitionFile.pos, outputReferencedSymbol.definition.textSpan.length),
fileName: mappedDefinitionFile.fileName,
};
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
if (!symbolToAddTo) {
symbolToAddTo = { definition, references: [] };
outputs.push(symbolToAddTo);
}
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
...outputReferencedSymbol.definition,
textSpan: createTextSpan(mappedDefinitionFile.pos, outputReferencedSymbol.definition.textSpan.length),
fileName: mappedDefinitionFile.fileName,
};
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
if (!symbolToAddTo) {
symbolToAddTo = { definition, references: [] };
outputs.push(symbolToAddTo);
}
for (const ref of outputReferencedSymbol.references) {
// If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
symbolToAddTo.references.push(ref);
for (const ref of outputReferencedSymbol.references) {
// If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
symbolToAddTo.references.push(ref);
}
}
}
}
}, () => getDefinitionLocation(defaultProject, initialLocation));
},
() => getDefinitionLocation(defaultProject, initialLocation)
);
return outputs.filter(o => o.references.length !== 0);
}
@@ -389,10 +407,10 @@ namespace ts.server {
projects: Projects,
defaultProject: Project,
initialLocation: TLocation,
projectService: ProjectService,
cb: CombineProjectOutputCallback<TLocation>,
getDefinition: (() => DocumentPosition | undefined) | undefined,
): void {
const projectService = defaultProject.projectService;
let toDo: ProjectAndLocation<TLocation>[] | undefined;
const seenProjects = createMap<true>();
forEachProjectInProjects(projects, initialLocation && initialLocation.fileName, (project, path) => {
@@ -576,7 +594,7 @@ namespace ts.server {
break;
case ProjectLoadingFinishEvent:
const { project: finishProject } = event.data;
this.event<protocol.ProjectLoadingFinishEventBody>({ projectName: finishProject.getProjectName() }, ProjectLoadingStartEvent);
this.event<protocol.ProjectLoadingFinishEventBody>({ projectName: finishProject.getProjectName() }, ProjectLoadingFinishEvent);
break;
case LargeFileReferencedEvent:
const { file, fileSize, maxFileSize } = event.data;
@@ -688,7 +706,26 @@ namespace ts.server {
success,
};
if (success) {
res.body = info;
let metadata: unknown;
if (isArray(info)) {
res.body = info;
metadata = (info as WithMetadata<ReadonlyArray<any>>).metadata;
delete (info as WithMetadata<ReadonlyArray<any>>).metadata;
}
else if (typeof info === "object") {
if ((info as WithMetadata<{}>).metadata) {
const { metadata: infoMetadata, ...body } = (info as WithMetadata<{}>);
res.body = body;
metadata = infoMetadata;
}
else {
res.body = info;
}
}
else {
res.body = info;
}
if (metadata) res.metadata = metadata;
}
else {
Debug.assert(info === undefined);
@@ -1157,7 +1194,9 @@ namespace ts.server {
this.projectService.getScriptInfoEnsuringProjectsUptoDate(args.file) :
this.projectService.getScriptInfo(args.file);
if (!scriptInfo) {
return ignoreNoProjectError ? emptyArray : Errors.ThrowNoProject();
if (ignoreNoProjectError) return emptyArray;
this.projectService.logErrorForScriptInfoNotFound(args.file);
return Errors.ThrowNoProject();
}
projects = scriptInfo.containingProjects;
symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
@@ -1165,6 +1204,7 @@ namespace ts.server {
// filter handles case when 'projects' is undefined
projects = filter(projects, p => p.languageServiceEnabled && !p.isOrphan());
if (!ignoreNoProjectError && (!projects || !projects.length) && !symLinkedProjects) {
this.projectService.logErrorForScriptInfoNotFound(args.file);
return Errors.ThrowNoProject();
}
return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217
@@ -1186,7 +1226,13 @@ namespace ts.server {
const position = this.getPositionInFile(args, file);
const projects = this.getProjects(args);
const locations = combineProjectOutputForRenameLocations(projects, this.getDefaultProject(args), { fileName: args.file, pos: position }, this.projectService, !!args.findInStrings, !!args.findInComments);
const locations = combineProjectOutputForRenameLocations(
projects,
this.getDefaultProject(args),
{ fileName: args.file, pos: position },
!!args.findInStrings,
!!args.findInComments
);
if (!simplifiedResult) return locations;
const defaultProject = this.getDefaultProject(args);
@@ -1220,7 +1266,11 @@ namespace ts.server {
const file = toNormalizedPath(args.file);
const projects = this.getProjects(args);
const position = this.getPositionInFile(args, file);
const references = combineProjectOutputForReferences(projects, this.getDefaultProject(args), { fileName: args.file, pos: position }, this.projectService);
const references = combineProjectOutputForReferences(
projects,
this.getDefaultProject(args),
{ fileName: args.file, pos: position },
);
if (simplifiedResult) {
const defaultProject = this.getDefaultProject(args);
@@ -1230,7 +1280,7 @@ namespace ts.server {
const nameSpan = nameInfo && nameInfo.textSpan;
const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
const refs: protocol.ReferencesResponseItem[] = flatMap(references, referencedSymbol =>
const refs: ReadonlyArray<protocol.ReferencesResponseItem> = flatMap(references, referencedSymbol =>
referencedSymbol.references.map(({ fileName, textSpan, isWriteAccess, isDefinition }): protocol.ReferencesResponseItem => {
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
const start = scriptInfo.positionToLineOffset(textSpan.start);
@@ -1464,7 +1514,7 @@ namespace ts.server {
});
}
private getCompletions(args: protocol.CompletionsRequestArgs, kind: protocol.CommandTypes.CompletionInfo | protocol.CommandTypes.Completions | protocol.CommandTypes.CompletionsFull): ReadonlyArray<protocol.CompletionEntry> | protocol.CompletionInfo | CompletionInfo | undefined {
private getCompletions(args: protocol.CompletionsRequestArgs, kind: protocol.CommandTypes.CompletionInfo | protocol.CommandTypes.Completions | protocol.CommandTypes.CompletionsFull): WithMetadata<ReadonlyArray<protocol.CompletionEntry>> | protocol.CompletionInfo | CompletionInfo | undefined {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const position = this.getPosition(args, scriptInfo);
@@ -1489,7 +1539,10 @@ namespace ts.server {
}
}).sort((a, b) => compareStringsCaseSensitiveUI(a.name, b.name));
if (kind === protocol.CommandTypes.Completions) return entries;
if (kind === protocol.CommandTypes.Completions) {
if (completions.metadata) (entries as WithMetadata<ReadonlyArray<protocol.CompletionEntry>>).metadata = completions.metadata;
return entries;
}
const res: protocol.CompletionInfo = {
...completions,
@@ -1724,7 +1777,6 @@ namespace ts.server {
return combineProjectOutputWhileOpeningReferencedProjects<NavigateToItem>(
this.getProjects(args),
this.getDefaultProject(args),
this.projectService,
project =>
project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject()),
documentSpanLocation,
@@ -1908,8 +1960,17 @@ namespace ts.server {
return textChanges.map(change => this.mapTextChangeToCodeEdit(change));
}
private mapTextChangeToCodeEdit(change: FileTextChanges): protocol.FileCodeEdits {
return mapTextChangesToCodeEdits(change, this.projectService.getScriptInfoOrConfig(change.fileName));
private mapTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
const scriptInfo = this.projectService.getScriptInfoOrConfig(textChanges.fileName);
if (!!textChanges.isNewFile === !!scriptInfo) {
if (!scriptInfo) { // and !isNewFile
this.projectService.logErrorForScriptInfoNotFound(textChanges.fileName);
}
Debug.fail("Expected isNewFile for (only) new files. " + JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }));
}
return scriptInfo
? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, scriptInfo)) }
: convertNewFileTextChangeToCodeEdit(textChanges);
}
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
@@ -1983,6 +2044,10 @@ namespace ts.server {
this.updateErrorCheck(next, checkList, delay, /*requireOpen*/ false);
}
private configurePlugin(args: protocol.ConfigurePluginRequestArguments) {
this.projectService.configurePlugin(args);
}
getCanonicalFileName(fileName: string) {
const name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
return normalizePath(name);
@@ -2304,6 +2369,10 @@ namespace ts.server {
[CommandNames.GetEditsForFileRenameFull]: (request: protocol.GetEditsForFileRenameRequest) => {
return this.requiredResponse(this.getEditsForFileRename(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.ConfigurePlugin]: (request: protocol.ConfigurePluginRequest) => {
this.configurePlugin(request.arguments);
return this.notRequired();
}
});
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
@@ -2423,13 +2492,6 @@ namespace ts.server {
return { file: fileName, start: scriptInfo.positionToLineOffset(textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) };
}
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, scriptInfo: ScriptInfoOrConfig | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !scriptInfo, "Expected isNewFile for (only) new files", () => JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }));
return scriptInfo
? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, scriptInfo)) }
: convertNewFileTextChangeToCodeEdit(textChanges);
}
function convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfoOrConfig): protocol.CodeEdit {
return { start: positionToLineOffset(scriptInfo, change.span.start), end: positionToLineOffset(scriptInfo, textSpanEnd(change.span)), newText: change.newText };
}
+1 -1
View File
@@ -130,7 +130,7 @@ namespace ts.server {
}
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>, newTypings: string[]) {
const typings = toSortedArray(newTypings);
const typings = sort(newTypings);
this.perProjectCache.set(projectName, {
compilerOptions,
typeAcquisition,
-42
View File
@@ -56,30 +56,6 @@ namespace ts.server {
}
}
export function getDefaultFormatCodeSettings(host: ServerHost): FormatCodeSettings {
return {
indentSize: 4,
tabSize: 4,
newLineCharacter: host.newLine || "\n",
convertTabsToSpaces: true,
indentStyle: IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
}
export type NormalizedPath = string & { __normalizedPathTag: any };
export function toNormalizedPath(fileName: string): NormalizedPath {
@@ -230,31 +206,13 @@ namespace ts.server {
}
}
export function toSortedArray(arr: string[]): SortedArray<string>;
export function toSortedArray<T>(arr: T[], comparer: Comparer<T>): SortedArray<T>;
export function toSortedArray<T>(arr: T[], comparer?: Comparer<T>): SortedArray<T> {
arr.sort(comparer);
return arr as SortedArray<T>;
}
export function toDeduplicatedSortedArray(arr: string[]): SortedArray<string> {
arr.sort();
filterMutate(arr, isNonDuplicateInSortedArray);
return arr as SortedArray<string>;
}
function isNonDuplicateInSortedArray<T>(value: T, index: number, array: T[]) {
return index === 0 || value !== array[index - 1];
}
const indentStr = "\n ";
/* @internal */
export function indent(str: string): string {
return indentStr + str.replace(/\n/g, indentStr);
}
/** Put stringified JSON on the next line, indented. */
/* @internal */
export function stringifyIndented(json: {}): string {
return indentStr + JSON.stringify(json);
}
+9 -1
View File
@@ -182,6 +182,7 @@ namespace ts {
SyntaxKind.Identifier,
SyntaxKind.StringLiteral,
SyntaxKind.NumericLiteral,
SyntaxKind.BigIntLiteral,
SyntaxKind.RegularExpressionLiteral,
SyntaxKind.ThisKeyword,
SyntaxKind.PlusPlusToken,
@@ -286,6 +287,7 @@ namespace ts {
case ClassificationType.comment: return TokenClass.Comment;
case ClassificationType.keyword: return TokenClass.Keyword;
case ClassificationType.numericLiteral: return TokenClass.NumberLiteral;
case ClassificationType.bigintLiteral: return TokenClass.BigIntLiteral;
case ClassificationType.operator: return TokenClass.Operator;
case ClassificationType.stringLiteral: return TokenClass.StringLiteral;
case ClassificationType.whiteSpace: return TokenClass.Whitespace;
@@ -422,6 +424,8 @@ namespace ts {
switch (token) {
case SyntaxKind.NumericLiteral:
return ClassificationType.numericLiteral;
case SyntaxKind.BigIntLiteral:
return ClassificationType.bigintLiteral;
case SyntaxKind.StringLiteral:
return ClassificationType.stringLiteral;
case SyntaxKind.RegularExpressionLiteral:
@@ -542,6 +546,7 @@ namespace ts {
case ClassificationType.identifier: return ClassificationTypeNames.identifier;
case ClassificationType.keyword: return ClassificationTypeNames.keyword;
case ClassificationType.numericLiteral: return ClassificationTypeNames.numericLiteral;
case ClassificationType.bigintLiteral: return ClassificationTypeNames.bigintLiteral;
case ClassificationType.operator: return ClassificationTypeNames.operator;
case ClassificationType.stringLiteral: return ClassificationTypeNames.stringLiteral;
case ClassificationType.whiteSpace: return ClassificationTypeNames.whiteSpace;
@@ -698,7 +703,7 @@ namespace ts {
pushCommentRange(pos, tag.pos - pos);
}
pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation); // "@"
pushClassification(tag.pos, 1, ClassificationType.punctuation); // "@"
pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); // e.g. "param"
pos = tag.tagName.end;
@@ -886,6 +891,9 @@ namespace ts {
else if (tokenKind === SyntaxKind.NumericLiteral) {
return ClassificationType.numericLiteral;
}
else if (tokenKind === SyntaxKind.BigIntLiteral) {
return ClassificationType.bigintLiteral;
}
else if (tokenKind === SyntaxKind.StringLiteral) {
// TODO: GH#18217
return token!.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
+1 -1
View File
@@ -62,7 +62,7 @@ namespace ts {
return arrayFrom(errorCodeToFixes.keys());
}
export function getFixes(context: CodeFixContext): CodeFixAction[] {
export function getFixes(context: CodeFixContext): ReadonlyArray<CodeFixAction> {
return flatMap(errorCodeToFixes.get(String(context.errorCode)) || emptyArray, f => f.getCodeActions(context));
}
@@ -58,9 +58,9 @@ namespace ts.codefix {
const allVarNames: SymbolAndIdentifier[] = [];
const isInJavascript = isInJSFile(functionToConvert);
const setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker);
const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames);
const functionToConvertRenamed = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames);
const constIdentifiers = getConstIdentifiers(synthNamesMap);
const returnStatements = getReturnStatementsWithPromiseHandlers(functionToConvertRenamed);
const returnStatements = functionToConvertRenamed.body && isBlock(functionToConvertRenamed.body) ? getReturnStatementsWithPromiseHandlers(functionToConvertRenamed.body) : emptyArray;
const transformer: Transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
if (!returnStatements.length) {
@@ -87,6 +87,14 @@ namespace ts.codefix {
}
}
function getReturnStatementsWithPromiseHandlers(body: Block): ReadonlyArray<ReturnStatement> {
const res: ReturnStatement[] = [];
forEachReturnStatement(body, ret => {
if (isReturnStatementWithFixablePromiseHandler(ret)) res.push(ret);
});
return res;
}
// Returns the identifiers that are never reassigned in the refactor
function getConstIdentifiers(synthNamesMap: ReadonlyMap<SynthIdentifier>): Identifier[] {
const constIdentifiers: Identifier[] = [];
@@ -442,7 +450,7 @@ namespace ts.codefix {
seenReturnStatement = true;
}
if (getReturnStatementsWithPromiseHandlers(statement).length) {
if (isReturnStatementWithFixablePromiseHandler(statement)) {
refactoredStmts = refactoredStmts.concat(getInnerTransformationBody(transformer, [statement], prevArgName));
}
else {
@@ -458,7 +466,7 @@ namespace ts.codefix {
seenReturnStatement);
}
else {
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody));
const innerRetStmts = isFixablePromiseHandler(funcBody) ? [createReturn(funcBody)] : emptyArray;
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
if (innerCbBody.length > 0) {
@@ -185,6 +185,10 @@ namespace ts.codefix {
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
}
else {
const contextualType = checker.getContextualType(token.parent as Expression);
typeNode = contextualType ? checker.typeToTypeNode(contextualType) : undefined;
}
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
+12 -4
View File
@@ -181,8 +181,8 @@ namespace ts.codefix {
function deleteAssignments(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Identifier, checker: TypeChecker) {
FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, (ref: Node) => {
if (ref.parent.kind === SyntaxKind.PropertyAccessExpression) ref = ref.parent;
if (ref.parent.kind === SyntaxKind.BinaryExpression && ref.parent.parent.kind === SyntaxKind.ExpressionStatement) {
if (isPropertyAccessExpression(ref.parent) && ref.parent.name === ref) ref = ref.parent;
if (isBinaryExpression(ref.parent) && isExpressionStatement(ref.parent.parent) && ref.parent.left === ref) {
changes.delete(sourceFile, ref.parent.parent);
}
});
@@ -200,8 +200,16 @@ namespace ts.codefix {
function tryDeleteParameter(changes: textChanges.ChangeTracker, sourceFile: SourceFile, p: ParameterDeclaration, checker: TypeChecker, sourceFiles: ReadonlyArray<SourceFile>, isFixAll: boolean): void {
if (mayDeleteParameter(p, checker, isFixAll)) {
changes.delete(sourceFile, p);
deleteUnusedArguments(changes, sourceFile, p, sourceFiles, checker);
if (p.modifiers && p.modifiers.length > 0
&& (!isIdentifier(p.name) || FindAllReferences.Core.isSymbolReferencedInFile(p.name, checker, sourceFile))) {
p.modifiers.forEach(modifier => {
changes.deleteModifier(sourceFile, modifier);
});
}
else {
changes.delete(sourceFile, p);
deleteUnusedArguments(changes, sourceFile, p, sourceFiles, checker);
}
}
}
+18 -7
View File
@@ -1,14 +1,22 @@
/* @internal */
namespace ts {
export function generateTypesForModule(name: string, moduleValue: unknown, formatSettings: FormatCodeSettings): string {
return valueInfoToDeclarationFileText(inspectValue(name, moduleValue), formatSettings);
return generateTypesForModuleOrGlobal(name, moduleValue, formatSettings, OutputKind.ExportEquals);
}
export function valueInfoToDeclarationFileText(valueInfo: ValueInfo, formatSettings: FormatCodeSettings): string {
return textChanges.getNewFileText(toStatements(valueInfo, OutputKind.ExportEquals), ScriptKind.TS, "\n", formatting.getFormatContext(formatSettings));
export function generateTypesForGlobal(name: string, globalValue: unknown, formatSettings: FormatCodeSettings): string {
return generateTypesForModuleOrGlobal(name, globalValue, formatSettings, OutputKind.Global);
}
const enum OutputKind { ExportEquals, NamedExport, NamespaceMember }
function generateTypesForModuleOrGlobal(name: string, globalValue: unknown, formatSettings: FormatCodeSettings, outputKind: OutputKind.ExportEquals | OutputKind.Global): string {
return valueInfoToDeclarationFileText(inspectValue(name, globalValue), formatSettings, outputKind);
}
/* @internal */
export function valueInfoToDeclarationFileText(valueInfo: ValueInfo, formatSettings: FormatCodeSettings, outputKind: OutputKind.ExportEquals | OutputKind.Global = OutputKind.ExportEquals): string {
return textChanges.getNewFileText(toStatements(valueInfo, outputKind), ScriptKind.TS, formatSettings.newLineCharacter || "\n", formatting.getFormatContext(formatSettings));
}
const enum OutputKind { ExportEquals, NamedExport, NamespaceMember, Global }
function toNamespaceMemberStatements(info: ValueInfo): ReadonlyArray<Statement> {
return toStatements(info, OutputKind.NamespaceMember);
}
@@ -18,7 +26,7 @@ namespace ts {
if (!isValidIdentifier(name) || isDefault && kind !== OutputKind.NamedExport) return emptyArray;
const modifiers = isDefault && info.kind === ValueKind.FunctionOrClass ? [createModifier(SyntaxKind.ExportKeyword), createModifier(SyntaxKind.DefaultKeyword)]
: kind === OutputKind.ExportEquals ? [createModifier(SyntaxKind.DeclareKeyword)]
: kind === OutputKind.Global || kind === OutputKind.ExportEquals ? [createModifier(SyntaxKind.DeclareKeyword)]
: kind === OutputKind.NamedExport ? [createModifier(SyntaxKind.ExportKeyword)]
: undefined;
const exportEquals = () => kind === OutputKind.ExportEquals ? [exportEqualsOrDefault(info.name, /*isExportEquals*/ true)] : emptyArray;
@@ -132,11 +140,14 @@ namespace ts {
case ValueKind.FunctionOrClass:
return createTypeReferenceNode("Function", /*typeArguments*/ undefined); // Normally we create a FunctionDeclaration, but this can happen for a function in an array.
case ValueKind.Object:
return createTypeLiteralNode(info.members.map(m => createPropertySignature(/*modifiers*/ undefined, m.name, /*questionToken*/ undefined, toType(m), /*initializer*/ undefined)));
return createTypeLiteralNode(info.members.map(m => createPropertySignature(/*modifiers*/ undefined, toPropertyName(m.name), /*questionToken*/ undefined, toType(m), /*initializer*/ undefined)));
default:
return Debug.assertNever(info);
}
}
function toPropertyName(name: string): Identifier | StringLiteral {
return isIdentifierText(name, ScriptTarget.ESNext) ? createIdentifier(name) : createStringLiteral(name);
}
// Parses assignments to "this.x" in the constructor into class property declarations
function getConstructorFunctionInstanceProperties(fnAst: FunctionOrConstructorNode): ReadonlyArray<PropertyDeclaration> {
+7 -7
View File
@@ -185,20 +185,20 @@ namespace ts.codefix {
const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions);
if (defaultInfo && defaultInfo.name === symbolName && skipAlias(defaultInfo.symbol, checker) === exportedSymbol) {
result.push({ moduleSymbol, importKind: defaultInfo.kind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(defaultInfo.symbol) });
result.push({ moduleSymbol, importKind: defaultInfo.kind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(defaultInfo.symbol, checker) });
}
for (const exported of checker.getExportsOfModule(moduleSymbol)) {
if (exported.name === symbolName && skipAlias(exported, checker) === exportedSymbol) {
result.push({ moduleSymbol, importKind: ImportKind.Named, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exported) });
result.push({ moduleSymbol, importKind: ImportKind.Named, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exported, checker) });
}
}
});
return result;
}
function isTypeOnlySymbol(s: Symbol): boolean {
return !(s.flags & SymbolFlags.Value);
function isTypeOnlySymbol(s: Symbol, checker: TypeChecker): boolean {
return !(skipAlias(s, checker).flags & SymbolFlags.Value);
}
function getFixForImport(
@@ -289,7 +289,7 @@ namespace ts.codefix {
// `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types.
exportedSymbolIsTypeOnly && isJs ? { kind: ImportFixKind.ImportType, moduleSpecifier, position: Debug.assertDefined(position) } : { kind: ImportFixKind.AddNew, moduleSpecifier, importKind }));
// Sort to keep the shortest paths first
return choicesForEachExportingModule.sort((a, b) => a.moduleSpecifier.length - b.moduleSpecifier.length);
return sort(choicesForEachExportingModule, (a, b) => a.moduleSpecifier.length - b.moduleSpecifier.length);
}
function getFixesForAddImport(
@@ -398,7 +398,7 @@ namespace ts.codefix {
// Maps symbol id to info for modules providing that symbol (original export + re-exports).
const originalSymbolToExportInfos = createMultiMap<SymbolExportInfo>();
function addSymbol(moduleSymbol: Symbol, exportedSymbol: Symbol, importKind: ImportKind): void {
originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol, importKind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exportedSymbol) });
originalSymbolToExportInfos.add(getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol, importKind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exportedSymbol, checker) });
}
forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), moduleSymbol => {
cancellationToken.throwIfCancellationRequested();
@@ -424,7 +424,7 @@ namespace ts.codefix {
if (!exported) return undefined;
const { symbol, kind } = exported;
const info = getDefaultExportInfoWorker(symbol, moduleSymbol, checker, compilerOptions);
return info && { symbol, symbolForMeaning: info.symbolForMeaning, name: info.name, kind };
return info && { symbol, kind, ...info };
}
function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined {
+300 -87
View File
@@ -21,28 +21,46 @@ namespace ts.codefix {
// Property declarations
Diagnostics.Member_0_implicitly_has_an_1_type.code,
//// Suggestions
// Variable declarations
Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code,
// Variable uses
Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
// Parameter declarations
Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code,
// Get Accessor declarations
Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code,
Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code,
// Set Accessor declarations
Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code,
// Property declarations
Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
];
registerCodeFix({
errorCodes,
getCodeActions(context) {
const { sourceFile, program, span: { start }, errorCode, cancellationToken } = context;
if (isSourceFileJS(sourceFile)) {
return undefined; // TODO: GH#20113
}
const { sourceFile, program, span: { start }, errorCode, cancellationToken, host } = context;
const token = getTokenAtPosition(sourceFile, start);
let declaration!: Declaration | undefined;
const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeenseen*/ returnTrue); });
const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeen*/ returnTrue, host); });
const name = declaration && getNameOfDeclaration(declaration);
return !name || changes.length === 0 ? undefined
: [createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), name.getText(sourceFile)], fixId, Diagnostics.Infer_all_types_from_usage)];
},
fixIds: [fixId],
getAllCodeActions(context) {
const { sourceFile, program, cancellationToken } = context;
const { sourceFile, program, cancellationToken, host } = context;
const markSeen = nodeSeenTracker();
return codeFixAll(context, errorCodes, (changes, err) => {
doChange(changes, sourceFile, getTokenAtPosition(err.file, err.start), err.code, program, cancellationToken, markSeen);
doChange(changes, sourceFile, getTokenAtPosition(err.file, err.start), err.code, program, cancellationToken, markSeen, host);
});
},
});
@@ -50,26 +68,62 @@ namespace ts.codefix {
function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage {
switch (errorCode) {
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
return isSetAccessor(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217
case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
return isSetAccessorDeclaration(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Infer_parameter_types_from_usage;
default:
return Diagnostics.Infer_type_of_0_from_usage;
}
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, markSeen: NodeSeenTracker): Declaration | undefined {
if (!isParameterPropertyModifier(token.kind) && token.kind !== SyntaxKind.Identifier && token.kind !== SyntaxKind.DotDotDotToken) {
/** Map suggestion code to error code */
function mapSuggestionDiagnostic(errorCode: number) {
switch (errorCode) {
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code;
case Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Variable_0_implicitly_has_an_1_type.code;
case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Parameter_0_implicitly_has_an_1_type.code;
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code;
case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code:
return Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code;
case Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code;
case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code:
return Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code;
case Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
return Diagnostics.Member_0_implicitly_has_an_1_type.code;
}
return errorCode;
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, markSeen: NodeSeenTracker, host: LanguageServiceHost): Declaration | undefined {
if (!isParameterPropertyModifier(token.kind) && token.kind !== SyntaxKind.Identifier && token.kind !== SyntaxKind.DotDotDotToken && token.kind !== SyntaxKind.ThisKeyword) {
return undefined;
}
const { parent } = token;
errorCode = mapSuggestionDiagnostic(errorCode);
switch (errorCode) {
// Variable and Property declarations
case Diagnostics.Member_0_implicitly_has_an_1_type.code:
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
if ((isVariableDeclaration(parent) && markSeen(parent)) || isPropertyDeclaration(parent) || isPropertySignature(parent)) { // handle bad location
annotateVariableDeclaration(changes, sourceFile, parent, program, cancellationToken);
annotateVariableDeclaration(changes, sourceFile, parent, program, host, cancellationToken);
return parent;
}
if (isPropertyAccessExpression(parent)) {
const type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken);
const typeNode = getTypeNodeIfAccessible(type, parent, program, host);
if (typeNode) {
// Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags
const typeTag = createJSDocTypeTag(createJSDocTypeExpression(typeNode), /*comment*/ "");
addJSDocTags(changes, sourceFile, cast(parent.parent.parent, isExpressionStatement), [typeTag]);
}
return parent;
}
return undefined;
@@ -77,7 +131,7 @@ namespace ts.codefix {
case Diagnostics.Variable_0_implicitly_has_an_1_type.code: {
const symbol = program.getTypeChecker().getSymbolAtLocation(token);
if (symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && markSeen(symbol.valueDeclaration)) {
annotateVariableDeclaration(changes, sourceFile, symbol.valueDeclaration, program, cancellationToken);
annotateVariableDeclaration(changes, sourceFile, symbol.valueDeclaration, program, host, cancellationToken);
return symbol.valueDeclaration;
}
return undefined;
@@ -92,15 +146,15 @@ namespace ts.codefix {
switch (errorCode) {
// Parameter declarations
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
if (isSetAccessor(containingFunction)) {
annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
if (isSetAccessorDeclaration(containingFunction)) {
annotateSetAccessor(changes, sourceFile, containingFunction, program, host, cancellationToken);
return containingFunction;
}
// falls through
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
if (markSeen(containingFunction)) {
const param = cast(parent, isParameter);
annotateParameters(changes, param, containingFunction, sourceFile, program, cancellationToken);
annotateParameters(changes, sourceFile, param, containingFunction, program, host, cancellationToken);
return param;
}
return undefined;
@@ -108,16 +162,16 @@ namespace ts.codefix {
// Get Accessor declarations
case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code:
case Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code:
if (isGetAccessor(containingFunction) && isIdentifier(containingFunction.name)) {
annotate(changes, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program);
if (isGetAccessorDeclaration(containingFunction) && isIdentifier(containingFunction.name)) {
annotate(changes, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program, host);
return containingFunction;
}
return undefined;
// Set Accessor declarations
case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code:
if (isSetAccessor(containingFunction)) {
annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
if (isSetAccessorDeclaration(containingFunction)) {
annotateSetAccessor(changes, sourceFile, containingFunction, program, host, cancellationToken);
return containingFunction;
}
return undefined;
@@ -127,9 +181,9 @@ namespace ts.codefix {
}
}
function annotateVariableDeclaration(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: VariableDeclaration | PropertyDeclaration | PropertySignature, program: Program, cancellationToken: CancellationToken): void {
function annotateVariableDeclaration(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: VariableDeclaration | PropertyDeclaration | PropertySignature, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
if (isIdentifier(declaration.name)) {
annotate(changes, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program);
annotate(changes, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program, host);
}
}
@@ -140,45 +194,119 @@ namespace ts.codefix {
case SyntaxKind.Constructor:
return true;
case SyntaxKind.FunctionExpression:
return !!declaration.name;
const parent = declaration.parent;
return isVariableDeclaration(parent) && isIdentifier(parent.name) || !!declaration.name;
}
return false;
}
function annotateParameters(changes: textChanges.ChangeTracker, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): void {
function annotateParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
if (!isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) {
return;
}
const types = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
containingFunction.parameters.map(p => isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined);
// We didn't actually find a set of type inference positions matching each parameter position
if (!types || containingFunction.parameters.length !== types.length) {
return;
}
const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
containingFunction.parameters.map<ParameterInference>(p => ({
declaration: p,
type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType()
}));
Debug.assert(containingFunction.parameters.length === parameterInferences.length);
zipWith(containingFunction.parameters, types, (parameter, type) => {
if (!parameter.type && !parameter.initializer) {
annotate(changes, sourceFile, parameter, type, program);
if (isInJSFile(containingFunction)) {
annotateJSDocParameters(changes, sourceFile, parameterInferences, program, host);
}
else {
for (const { declaration, type } of parameterInferences) {
if (declaration && !declaration.type && !declaration.initializer) {
annotate(changes, sourceFile, declaration, type, program, host);
}
}
});
}
}
function annotateSetAccessor(changes: textChanges.ChangeTracker, sourceFile: SourceFile, setAccessorDeclaration: SetAccessorDeclaration, program: Program, cancellationToken: CancellationToken): void {
function annotateSetAccessor(changes: textChanges.ChangeTracker, sourceFile: SourceFile, setAccessorDeclaration: SetAccessorDeclaration, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
const param = firstOrUndefined(setAccessorDeclaration.parameters);
if (param && isIdentifier(setAccessorDeclaration.name) && isIdentifier(param.name)) {
const type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken) ||
inferTypeForVariableFromUsage(param.name, program, cancellationToken);
annotate(changes, sourceFile, param, type, program);
let type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken);
if (type === program.getTypeChecker().getAnyType()) {
type = inferTypeForVariableFromUsage(param.name, program, cancellationToken);
}
if (isInJSFile(setAccessorDeclaration)) {
annotateJSDocParameters(changes, sourceFile, [{ declaration: param, type }], program, host);
}
else {
annotate(changes, sourceFile, param, type, program, host);
}
}
}
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type | undefined, program: Program): void {
const typeNode = type && getTypeNodeIfAccessible(type, declaration, program.getTypeChecker());
if (typeNode) changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode);
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type, program: Program, host: LanguageServiceHost): void {
const typeNode = getTypeNodeIfAccessible(type, declaration, program, host);
if (typeNode) {
if (isInJSFile(sourceFile) && declaration.kind !== SyntaxKind.PropertySignature) {
const parent = isVariableDeclaration(declaration) ? tryCast(declaration.parent.parent, isVariableStatement) : declaration;
if (!parent) {
return;
}
const typeExpression = createJSDocTypeExpression(typeNode);
const typeTag = isGetAccessorDeclaration(declaration) ? createJSDocReturnTag(typeExpression, "") : createJSDocTypeTag(typeExpression, "");
addJSDocTags(changes, sourceFile, parent, [typeTag]);
}
else {
changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode);
}
}
}
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, checker: TypeChecker): TypeNode | undefined {
function annotateJSDocParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterInferences: ReadonlyArray<ParameterInference>, program: Program, host: LanguageServiceHost): void {
const signature = parameterInferences.length && parameterInferences[0].declaration.parent;
if (!signature) {
return;
}
const paramTags = mapDefined(parameterInferences, inference => {
const param = inference.declaration;
// only infer parameters that have (1) no type and (2) an accessible inferred type
if (param.initializer || getJSDocType(param) || !isIdentifier(param.name)) return;
const typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host);
const name = getSynthesizedClone(param.name);
setEmitFlags(name, EmitFlags.NoComments | EmitFlags.NoNestedComments);
return typeNode && createJSDocParamTag(name, !!inference.isOptional, createJSDocTypeExpression(typeNode), "");
});
addJSDocTags(changes, sourceFile, signature, paramTags);
}
function addJSDocTags(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parent: HasJSDoc, newTags: ReadonlyArray<JSDocTag>): void {
const comments = mapDefined(parent.jsDoc, j => j.comment);
const oldTags = flatMapToMutable(parent.jsDoc, j => j.tags);
const unmergedNewTags = newTags.filter(newTag => !oldTags || !oldTags.some((tag, i) => {
const merged = tryMergeJsdocTags(tag, newTag);
if (merged) oldTags[i] = merged;
return !!merged;
}));
const tag = createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags]));
changes.insertJsdocCommentBefore(sourceFile, parent, tag);
}
function tryMergeJsdocTags(oldTag: JSDocTag, newTag: JSDocTag): JSDocTag | undefined {
if (oldTag.kind !== newTag.kind) {
return undefined;
}
switch (oldTag.kind) {
case SyntaxKind.JSDocParameterTag: {
const oldParam = oldTag as JSDocParameterTag;
const newParam = newTag as JSDocParameterTag;
return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText
? createJSDocParamTag(newParam.name, newParam.isBracketed, newParam.typeExpression, oldParam.comment)
: undefined;
}
case SyntaxKind.JSDocReturnTag:
return createJSDocReturnTag((newTag as JSDocReturnTag).typeExpression, oldTag.comment);
}
}
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, program: Program, host: LanguageServiceHost): TypeNode | undefined {
const checker = program.getTypeChecker();
let typeIsAccessible = true;
const notAccessible = () => { typeIsAccessible = false; };
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
@@ -189,6 +317,14 @@ namespace ts.codefix {
reportInaccessibleThisError: notAccessible,
reportPrivateInBaseOfClassExpression: notAccessible,
reportInaccessibleUniqueSymbolError: notAccessible,
moduleResolverHost: {
readFile: host.readFile,
fileExists: host.fileExists,
directoryExists: host.directoryExists,
getSourceFiles: program.getSourceFiles,
getCurrentDirectory: program.getCurrentDirectory,
getCommonSourceDirectory: program.getCommonSourceDirectory,
}
});
return typeIsAccessible ? res : undefined;
}
@@ -199,24 +335,39 @@ namespace ts.codefix {
entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined);
}
function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type | undefined {
return InferFromReference.inferTypeFromReferences(getReferences(token, program, cancellationToken), program.getTypeChecker(), cancellationToken);
function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type {
const references = getReferences(token, program, cancellationToken);
const checker = program.getTypeChecker();
const types = InferFromReference.inferTypesFromReferences(references, checker, cancellationToken);
return InferFromReference.unifyFromContext(types, checker);
}
function inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): (Type | undefined)[] | undefined {
function inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
let searchToken;
switch (containingFunction.kind) {
case SyntaxKind.Constructor:
searchToken = findChildOfKind<Token<SyntaxKind.ConstructorKeyword>>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile);
break;
case SyntaxKind.FunctionExpression:
const parent = containingFunction.parent;
searchToken = isVariableDeclaration(parent) && isIdentifier(parent.name) ?
parent.name :
containingFunction.name;
break;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
const isConstructor = containingFunction.kind === SyntaxKind.Constructor;
const searchToken = isConstructor ?
findChildOfKind<Token<SyntaxKind.ConstructorKeyword>>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile) :
containingFunction.name;
if (searchToken) {
return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken);
}
searchToken = containingFunction.name;
break;
}
if (searchToken) {
return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program, cancellationToken);
}
}
interface ParameterInference {
readonly declaration: ParameterDeclaration;
readonly type: Type;
readonly isOptional?: boolean;
}
namespace InferFromReference {
@@ -228,7 +379,9 @@ namespace ts.codefix {
interface UsageContext {
isNumber?: boolean;
isString?: boolean;
isNumberOrString?: boolean;
hasNonVacuousType?: boolean;
hasNonVacuousNonAnonymousType?: boolean;
candidateTypes?: Type[];
properties?: UnderscoreEscapedMap<UsageContext>;
callContexts?: CallContext[];
@@ -237,20 +390,20 @@ namespace ts.codefix {
stringIndexContext?: UsageContext;
}
export function inferTypeFromReferences(references: ReadonlyArray<Identifier>, checker: TypeChecker, cancellationToken: CancellationToken): Type | undefined {
export function inferTypesFromReferences(references: ReadonlyArray<Identifier>, checker: TypeChecker, cancellationToken: CancellationToken): Type[] {
const usageContext: UsageContext = {};
for (const reference of references) {
cancellationToken.throwIfCancellationRequested();
inferTypeFromContext(reference, checker, usageContext);
}
return getTypeFromUsageContext(usageContext, checker);
return inferFromContext(usageContext, checker);
}
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, checker: TypeChecker, cancellationToken: CancellationToken): (Type | undefined)[] | undefined {
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
const checker = program.getTypeChecker();
if (references.length === 0) {
return undefined;
}
if (!declaration.parameters) {
return undefined;
}
@@ -262,15 +415,16 @@ namespace ts.codefix {
}
const isConstructor = declaration.kind === SyntaxKind.Constructor;
const callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts;
return callContexts && declaration.parameters.map((parameter, parameterIndex) => {
return callContexts && declaration.parameters.map((parameter, parameterIndex): ParameterInference => {
const types: Type[] = [];
const isRest = isRestParameter(parameter);
let isOptional = false;
for (const callContext of callContexts) {
if (callContext.argumentTypes.length <= parameterIndex) {
continue;
isOptional = isInJSFile(declaration);
types.push(checker.getUndefinedType());
}
if (isRest) {
else if (isRest) {
for (let i = parameterIndex; i < callContext.argumentTypes.length; i++) {
types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i]));
}
@@ -279,11 +433,15 @@ namespace ts.codefix {
types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex]));
}
}
if (!types.length) {
return undefined;
if (isIdentifier(parameter.name)) {
types.push(...inferTypesFromReferences(getReferences(parameter.name, program, cancellationToken), checker, cancellationToken));
}
const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
return isRest ? checker.createArrayType(type) : type;
const type = unifyFromContext(types, checker);
return {
type: isRest ? checker.createArrayType(type) : type,
isOptional: isOptional && !isRest,
declaration: parameter
};
});
}
@@ -352,7 +510,8 @@ namespace ts.codefix {
break;
case SyntaxKind.PlusToken:
usageContext.isNumberOrString = true;
usageContext.isNumber = true;
usageContext.isString = true;
break;
// case SyntaxKind.ExclamationToken:
@@ -423,7 +582,8 @@ namespace ts.codefix {
usageContext.isString = true;
}
else {
usageContext.isNumberOrString = true;
usageContext.isNumber = true;
usageContext.isString = true;
}
break;
@@ -497,7 +657,8 @@ namespace ts.codefix {
function inferTypeFromPropertyElementExpressionContext(parent: ElementAccessExpression, node: Expression, checker: TypeChecker, usageContext: UsageContext): void {
if (node === parent.argumentExpression) {
usageContext.isNumberOrString = true;
usageContext.isNumber = true;
usageContext.isString = true;
return;
}
else {
@@ -513,29 +674,83 @@ namespace ts.codefix {
}
}
function getTypeFromUsageContext(usageContext: UsageContext, checker: TypeChecker): Type | undefined {
if (usageContext.isNumberOrString && !usageContext.isNumber && !usageContext.isString) {
return checker.getUnionType([checker.getNumberType(), checker.getStringType()]);
export function unifyFromContext(inferences: ReadonlyArray<Type>, checker: TypeChecker, fallback = checker.getAnyType()): Type {
if (!inferences.length) return fallback;
const hasNonVacuousType = inferences.some(i => !(i.flags & (TypeFlags.Any | TypeFlags.Void)));
const hasNonVacuousNonAnonymousType = inferences.some(
i => !(i.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(checker.getObjectFlags(i) & ObjectFlags.Anonymous));
const anons = inferences.filter(i => checker.getObjectFlags(i) & ObjectFlags.Anonymous) as AnonymousType[];
const good = [];
if (!hasNonVacuousNonAnonymousType && anons.length) {
good.push(unifyAnonymousTypes(anons, checker));
}
else if (usageContext.isNumber) {
return checker.getNumberType();
good.push(...inferences.filter(i => !(checker.getObjectFlags(i) & ObjectFlags.Anonymous) && !(hasNonVacuousType && i.flags & (TypeFlags.Any | TypeFlags.Void))));
return checker.getWidenedType(checker.getUnionType(good));
}
function unifyAnonymousTypes(anons: AnonymousType[], checker: TypeChecker) {
if (anons.length === 1) {
return anons[0];
}
else if (usageContext.isString) {
return checker.getStringType();
const calls = [];
const constructs = [];
const stringIndices = [];
const numberIndices = [];
let stringIndexReadonly = false;
let numberIndexReadonly = false;
const props = createMultiMap<Type>();
for (const anon of anons) {
for (const p of checker.getPropertiesOfType(anon)) {
props.add(p.name, checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration));
}
calls.push(...checker.getSignaturesOfType(anon, SignatureKind.Call));
constructs.push(...checker.getSignaturesOfType(anon, SignatureKind.Construct));
if (anon.stringIndexInfo) {
stringIndices.push(anon.stringIndexInfo.type);
stringIndexReadonly = stringIndexReadonly || anon.stringIndexInfo.isReadonly;
}
if (anon.numberIndexInfo) {
numberIndices.push(anon.numberIndexInfo.type);
numberIndexReadonly = numberIndexReadonly || anon.numberIndexInfo.isReadonly;
}
}
else if (usageContext.candidateTypes) {
return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(t => checker.getBaseTypeOfLiteralType(t)), UnionReduction.Subtype));
const members = mapEntries(props, (name, types) => {
const isOptional = types.length < anons.length ? SymbolFlags.Optional : 0;
const s = checker.createSymbol(SymbolFlags.Property | isOptional, name as __String);
s.type = checker.getUnionType(types);
return [name, s];
});
return checker.createAnonymousType(
anons[0].symbol,
members as UnderscoreEscapedMap<TransientSymbol>,
calls,
constructs,
stringIndices.length ? checker.createIndexInfo(checker.getUnionType(stringIndices), stringIndexReadonly) : undefined,
numberIndices.length ? checker.createIndexInfo(checker.getUnionType(numberIndices), numberIndexReadonly) : undefined);
}
function inferFromContext(usageContext: UsageContext, checker: TypeChecker) {
const types = [];
if (usageContext.isNumber) {
types.push(checker.getNumberType());
}
else if (usageContext.properties && hasCallContext(usageContext.properties.get("then" as __String))) {
if (usageContext.isString) {
types.push(checker.getStringType());
}
types.push(...(usageContext.candidateTypes || []).map(t => checker.getBaseTypeOfLiteralType(t)));
if (usageContext.properties && hasCallContext(usageContext.properties.get("then" as __String))) {
const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!; // TODO: GH#18217
const types = paramType.getCallSignatures().map(c => c.getReturnType());
return checker.createPromiseType(types.length ? checker.getUnionType(types, UnionReduction.Subtype) : checker.getAnyType());
types.push(checker.createPromiseType(types.length ? checker.getUnionType(types, UnionReduction.Subtype) : checker.getAnyType()));
}
else if (usageContext.properties && hasCallContext(usageContext.properties.get("push" as __String))) {
return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!);
types.push(checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String)!.callContexts!, /*isRestParameter*/ false, checker)!));
}
else if (usageContext.numberIndexContext) {
return checker.createArrayType(recur(usageContext.numberIndexContext));
if (usageContext.numberIndexContext) {
return [checker.createArrayType(recur(usageContext.numberIndexContext))];
}
else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.stringIndexContext) {
const members = createUnderscoreEscapedMap<Symbol>();
@@ -567,14 +782,12 @@ namespace ts.codefix {
stringIndexInfo = checker.createIndexInfo(recur(usageContext.stringIndexContext), /*isReadonly*/ false);
}
return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined); // TODO: GH#18217
}
else {
return undefined;
types.push(checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined)); // TODO: GH#18217
}
return types;
function recur(innerContext: UsageContext): Type {
return getTypeFromUsageContext(innerContext, checker) || checker.getAnyType();
return unifyFromContext(inferFromContext(innerContext, checker), checker);
}
}
@@ -607,7 +820,7 @@ namespace ts.codefix {
symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i]));
parameters.push(symbol);
}
const returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType();
const returnType = unifyFromContext(inferFromContext(callContext.returnType, checker), checker, checker.getVoidType());
// TODO: GH#18217
return checker.createSignature(/*declaration*/ undefined!, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
}
+30 -295
View File
@@ -37,18 +37,13 @@ namespace ts.Completions {
export function getCompletionsAtPosition(host: LanguageServiceHost, program: Program, log: Log, sourceFile: SourceFile, position: number, preferences: UserPreferences, triggerCharacter: CompletionsTriggerCharacter | undefined): CompletionInfo | undefined {
const typeChecker = program.getTypeChecker();
const compilerOptions = program.getCompilerOptions();
if (isInReferenceComment(sourceFile, position)) {
const entries = PathCompletions.getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host);
return entries && convertPathCompletions(entries);
}
const contextToken = findPrecedingToken(position, sourceFile);
if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) return undefined;
if (isInString(sourceFile, position, contextToken)) {
return !contextToken || !isStringLiteralLike(contextToken)
? undefined
: convertStringLiteralCompletions(getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host), sourceFile, typeChecker, log, preferences);
const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, contextToken, typeChecker, compilerOptions, host, log, preferences);
if (stringCompletions) {
return stringCompletions;
}
if (contextToken && isBreakOrContinueStatement(contextToken.parent)
@@ -77,34 +72,6 @@ namespace ts.Completions {
}
}
function convertStringLiteralCompletions(completion: StringLiteralCompletion | undefined, sourceFile: SourceFile, checker: TypeChecker, log: Log, preferences: UserPreferences): CompletionInfo | undefined {
if (completion === undefined) {
return undefined;
}
switch (completion.kind) {
case StringLiteralCompletionKind.Paths:
return convertPathCompletions(completion.paths);
case StringLiteralCompletionKind.Properties: {
const entries: CompletionEntry[] = [];
getCompletionEntriesFromSymbols(completion.symbols, entries, sourceFile, sourceFile, checker, ScriptTarget.ESNext, log, CompletionKind.String, preferences); // Target will not be used, so arbitrary
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, entries };
}
case StringLiteralCompletionKind.Types: {
const entries = completion.types.map(type => ({ name: type.value, kindModifiers: ScriptElementKindModifier.none, kind: ScriptElementKind.string, sortText: "0" }));
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, entries };
}
default:
return Debug.assertNever(completion);
}
}
function convertPathCompletions(pathCompletions: ReadonlyArray<PathCompletions.PathCompletion>): CompletionInfo {
const isGlobalCompletion = false; // We don't want the editor to offer any other completions, such as snippets, inside a comment.
const isNewIdentifierLocation = true; // The user may type in a path that doesn't yet exist, creating a "new identifier" with respect to the collection of identifiers the server is aware of.
const entries = pathCompletions.map(({ name, kind, span }) => ({ name, kind, kindModifiers: ScriptElementKindModifier.none, sortText: "0", replacementSpan: span }));
return { isGlobalCompletion, isMemberCompletion: false, isNewIdentifierLocation, entries };
}
function jsdocCompletionInfo(entries: CompletionEntry[]): CompletionInfo {
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries };
}
@@ -198,8 +165,9 @@ namespace ts.Completions {
});
}
const completionNameForLiteral = JSON.stringify;
function createCompletionEntryForLiteral(literal: string | number): CompletionEntry {
const completionNameForLiteral = (literal: string | number | PseudoBigInt) =>
typeof literal === "object" ? pseudoBigIntToString(literal) + "n" : JSON.stringify(literal);
function createCompletionEntryForLiteral(literal: string | number | PseudoBigInt): CompletionEntry {
return { name: completionNameForLiteral(literal), kind: ScriptElementKind.string, kindModifiers: ScriptElementKindModifier.none, sortText: "0" };
}
@@ -270,22 +238,6 @@ namespace ts.Completions {
};
}
function quote(text: string, preferences: UserPreferences): string {
if (/^\d+$/.test(text)) {
return text;
}
const quoted = JSON.stringify(text);
switch (preferences.quotePreference) {
case undefined:
case "double":
return quoted;
case "single":
return `'${stripQuotes(quoted).replace("'", "\\'").replace('\\"', '"')}'`;
default:
return Debug.assertNever(preferences.quotePreference);
}
}
function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol | undefined, checker: TypeChecker): boolean {
return localSymbol === recommendedCompletion ||
!!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion;
@@ -299,7 +251,7 @@ namespace ts.Completions {
return origin && originIsExport(origin) ? stripQuotes(origin.moduleSymbol.name) : undefined;
}
function getCompletionEntriesFromSymbols(
export function getCompletionEntriesFromSymbols(
symbols: ReadonlyArray<Symbol>,
entries: Push<CompletionEntry>,
location: Node | undefined,
@@ -377,145 +329,6 @@ namespace ts.Completions {
return entries;
}
const enum StringLiteralCompletionKind { Paths, Properties, Types }
interface StringLiteralCompletionsFromProperties {
readonly kind: StringLiteralCompletionKind.Properties;
readonly symbols: ReadonlyArray<Symbol>;
readonly hasIndexSignature: boolean;
}
interface StringLiteralCompletionsFromTypes {
readonly kind: StringLiteralCompletionKind.Types;
readonly types: ReadonlyArray<StringLiteralType>;
readonly isNewIdentifier: boolean;
}
type StringLiteralCompletion = { readonly kind: StringLiteralCompletionKind.Paths, readonly paths: ReadonlyArray<PathCompletions.PathCompletion> } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes;
function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost): StringLiteralCompletion | undefined {
const { parent } = node;
switch (parent.kind) {
case SyntaxKind.LiteralType:
switch (parent.parent.kind) {
case SyntaxKind.TypeReference:
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent as LiteralTypeNode)), isNewIdentifier: false };
case SyntaxKind.IndexedAccessType:
// Get all apparent property names
// i.e. interface Foo {
// foo: string;
// bar: string;
// }
// let x: Foo["/*completion position*/"]
return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((parent.parent as IndexedAccessTypeNode).objectType));
case SyntaxKind.ImportType:
return { kind: StringLiteralCompletionKind.Paths, paths: PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
case SyntaxKind.UnionType: {
if (!isTypeReferenceNode(parent.parent.parent)) return undefined;
const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion(parent.parent as UnionTypeNode, parent as LiteralTypeNode);
const types = getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent.parent as UnionTypeNode)).filter(t => !contains(alreadyUsedTypes, t.value));
return { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier: false };
}
default:
return undefined;
}
case SyntaxKind.PropertyAssignment:
if (isObjectLiteralExpression(parent.parent) && (<PropertyAssignment>parent).name === node) {
// Get quoted name of properties of the object literal expression
// i.e. interface ConfigFiles {
// 'jspm:dev': string
// }
// let files: ConfigFiles = {
// '/*completion position*/'
// }
//
// function foo(c: ConfigFiles) {}
// foo({
// '/*completion position*/'
// });
return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(parent.parent));
}
return fromContextualType();
case SyntaxKind.ElementAccessExpression: {
const { expression, argumentExpression } = parent as ElementAccessExpression;
if (node === argumentExpression) {
// Get all names of properties on the expression
// i.e. interface A {
// 'prop1': string
// }
// let a: A;
// a['/*completion position*/']
return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression));
}
return undefined;
}
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
if (!isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ false) && !isImportCall(parent)) {
const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile);
// Get string literal completions from specialized signatures of the target
// i.e. declare function f(a: 'A');
// f("/*completion position*/")
return argumentInfo ? getStringLiteralCompletionsFromSignature(argumentInfo, typeChecker) : fromContextualType();
}
// falls through (is `require("")` or `import("")`)
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExternalModuleReference:
// Get all known external module names or complete a path to a module
// i.e. import * as ns from "/*completion position*/";
// var y = import("/*completion position*/");
// import x = require("/*completion position*/");
// var y = require("/*completion position*/");
// export * from "/*completion position*/";
return { kind: StringLiteralCompletionKind.Paths, paths: PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
default:
return fromContextualType();
}
function fromContextualType(): StringLiteralCompletion {
// Get completion for string literal from string literal type
// i.e. var x: "hi" | "hello" = "/*completion position*/"
return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false };
}
}
function getAlreadyUsedTypesInStringLiteralUnion(union: UnionTypeNode, current: LiteralTypeNode): ReadonlyArray<string> {
return mapDefined(union.types, type =>
type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text : undefined);
}
function getStringLiteralCompletionsFromSignature(argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes {
let isNewIdentifier = false;
const uniques = createMap<true>();
const candidates: Signature[] = [];
checker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount);
const types = flatMap(candidates, candidate => {
if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return;
const type = checker.getParameterType(candidate, argumentInfo.argumentIndex);
isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String);
return getStringLiteralTypes(type, uniques);
});
return { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier };
}
function stringLiteralCompletionsFromProperties(type: Type | undefined): StringLiteralCompletionsFromProperties | undefined {
return type && { kind: StringLiteralCompletionKind.Properties, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) };
}
function getStringLiteralTypes(type: Type | undefined, uniques = createMap<true>()): ReadonlyArray<StringLiteralType> {
if (!type) return emptyArray;
type = skipConstraint(type);
return type.isUnion()
? flatMap(type.types, t => getStringLiteralTypes(t, uniques))
: type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value)
? [type]
: emptyArray;
}
interface SymbolCompletion {
type: "symbol";
symbol: Symbol;
@@ -525,7 +338,7 @@ namespace ts.Completions {
readonly isJsxInitializer: IsJsxInitializer;
}
function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier,
): SymbolCompletion | { type: "request", request: Request } | { type: "literal", literal: string | number } | { type: "none" } {
): SymbolCompletion | { type: "request", request: Request } | { type: "literal", literal: string | number | PseudoBigInt } | { type: "none" } {
const compilerOptions = program.getCompilerOptions();
const completionData = getCompletionData(program, log, sourceFile, isUncheckedFile(sourceFile, compilerOptions), position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId);
if (!completionData) {
@@ -583,10 +396,7 @@ namespace ts.Completions {
const contextToken = findPrecedingToken(position, sourceFile);
if (isInString(sourceFile, position, contextToken)) {
const stringLiteralCompletions = !contextToken || !isStringLiteralLike(contextToken)
? undefined
: getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host);
return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken!, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); // TODO: GH#18217
return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken);
}
// Compute all the completion symbols again.
@@ -626,7 +436,7 @@ namespace ts.Completions {
return createCompletionDetails(name, ScriptElementKindModifier.none, kind, [displayPart(name, kind2)]);
}
function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails {
export function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails {
const { displayParts, documentation, symbolKind, tags } =
checker.runWithCancellationToken(cancellationToken, checker =>
SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, SemanticMeaning.All)
@@ -634,24 +444,7 @@ namespace ts.Completions {
return createCompletionDetails(symbol.name, SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay);
}
function stringLiteralCompletionDetails(name: string, location: Node, completion: StringLiteralCompletion, sourceFile: SourceFile, checker: TypeChecker, cancellationToken: CancellationToken): CompletionEntryDetails | undefined {
switch (completion.kind) {
case StringLiteralCompletionKind.Paths: {
const match = find(completion.paths, p => p.name === name);
return match && createCompletionDetails(name, ScriptElementKindModifier.none, match.kind, [textPart(name)]);
}
case StringLiteralCompletionKind.Properties: {
const match = find(completion.symbols, s => s.name === name);
return match && createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken);
}
case StringLiteralCompletionKind.Types:
return find(completion.types, t => t.value === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.typeElement, [textPart(name)]) : undefined;
default:
return Debug.assertNever(completion);
}
}
function createCompletionDetails(name: string, kindModifiers: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], documentation?: SymbolDisplayPart[], tags?: JSDocTagInfo[], codeActions?: CodeAction[], source?: SymbolDisplayPart[]): CompletionEntryDetails {
export function createCompletionDetails(name: string, kindModifiers: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], documentation?: SymbolDisplayPart[], tags?: JSDocTagInfo[], codeActions?: CodeAction[], source?: SymbolDisplayPart[]): CompletionEntryDetails {
return { name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source };
}
@@ -710,7 +503,7 @@ namespace ts.Completions {
readonly isNewIdentifierLocation: boolean;
readonly location: Node | undefined;
readonly keywordFilters: KeywordCompletionFilters;
readonly literals: ReadonlyArray<string | number>;
readonly literals: ReadonlyArray<string | number | PseudoBigInt>;
readonly symbolToOriginInfoMap: SymbolOriginInfoMap;
readonly recommendedCompletion: Symbol | undefined;
readonly previousToken: Node | undefined;
@@ -718,7 +511,7 @@ namespace ts.Completions {
}
type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag };
const enum CompletionKind {
export const enum CompletionKind {
ObjectPropertyDeclaration,
Global,
PropertyAccess,
@@ -772,28 +565,6 @@ namespace ts.Completions {
}
}
function getContextualTypeFromParent(node: Expression, checker: TypeChecker): Type | undefined {
const { parent } = node;
switch (parent.kind) {
case SyntaxKind.NewExpression:
return checker.getContextualType(parent as NewExpression);
case SyntaxKind.BinaryExpression: {
const { left, operatorToken, right } = parent as BinaryExpression;
return isEqualityOperatorKind(operatorToken.kind)
? checker.getTypeAtLocation(node === right ? left : right)
: checker.getContextualType(node);
}
case SyntaxKind.CaseClause:
return (parent as CaseClause).expression === node ? getSwitchedType(parent as CaseClause, checker) : undefined;
default:
return checker.getContextualType(node);
}
}
function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined {
return checker.getTypeAtLocation(caseClause.parent.parent.expression);
}
function getFirstSymbolInChain(symbol: Symbol, enclosingDeclaration: Node, checker: TypeChecker): Symbol | undefined {
const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ SymbolFlags.All, /*useOnlyExternalAliasing*/ false);
if (chain) return first(chain);
@@ -1200,9 +971,9 @@ namespace ts.Completions {
function tryGetJsxCompletionSymbols(): GlobalsSearch {
const jsxContainer = tryGetContainingJsxElement(contextToken);
// Cursor is inside a JSX self-closing element or opening element
const attrsType = jsxContainer && typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
if (!attrsType) return GlobalsSearch.Continue;
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer!.attributes.properties);
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
completionKind = CompletionKind.MemberLike;
isNewIdentifierLocation = false;
return GlobalsSearch.Success;
@@ -1358,23 +1129,13 @@ namespace ts.Completions {
return false;
}
function symbolCanBeReferencedAtTypeLocation(symbol: Symbol): boolean {
symbol = symbol.exportSymbol || symbol;
// This is an alias, follow what it aliases
symbol = skipAlias(symbol, typeChecker);
if (symbol.flags & SymbolFlags.Type) {
return true;
}
if (symbol.flags & SymbolFlags.Module) {
const exportedSymbols = typeChecker.getExportsOfModule(symbol);
// If the exported symbols contains type,
// symbol can be referenced at locations where type is allowed
return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation);
}
return false;
/** True if symbol is a type or a module containing at least one type. */
function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, seenModules = createMap<true>()): boolean {
const sym = skipAlias(symbol.exportSymbol || symbol, typeChecker);
return !!(sym.flags & SymbolFlags.Type) ||
!!(sym.flags & SymbolFlags.Module) &&
addToSeen(seenModules, getSymbolId(sym)) &&
typeChecker.getExportsOfModule(sym).some(e => symbolCanBeReferencedAtTypeLocation(e, seenModules));
}
function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string, target: ScriptTarget): void {
@@ -1407,14 +1168,16 @@ namespace ts.Completions {
// The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details.
// This is just to avoid adding duplicate completion entries.
//
// If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols.
// If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
// If `symbol.parent !== ...`, this is an `export * from "foo"` re-export. Those don't create new symbols.
if (typeChecker.getMergedSymbol(symbol.parent!) !== resolvedModuleSymbol
|| some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) {
|| some(symbol.declarations, d =>
// If `!!d.name.originalKeywordKind`, this is `export { _break as break };` -- skip this and prefer the keyword completion.
// If `!!d.parent.parent.moduleSpecifier`, this is `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
isExportSpecifier(d) && (d.propertyName ? isIdentifierANonContextualKeyword(d.name) : !!d.parent.parent.moduleSpecifier))) {
continue;
}
const isDefaultExport = symbol.name === InternalSymbolName.Default;
const isDefaultExport = symbol.escapedName === InternalSymbolName.Default;
if (isDefaultExport) {
symbol = getLocalSymbolForExportDefault(symbol) || symbol;
}
@@ -2150,7 +1913,7 @@ namespace ts.Completions {
case KeywordCompletionFilters.None:
return false;
case KeywordCompletionFilters.All:
return kind === SyntaxKind.AsyncKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind) || kind === SyntaxKind.DeclareKeyword || kind === SyntaxKind.ModuleKeyword
return kind === SyntaxKind.AsyncKeyword || SyntaxKind.AwaitKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind) || kind === SyntaxKind.DeclareKeyword || kind === SyntaxKind.ModuleKeyword
|| isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword;
case KeywordCompletionFilters.ClassElementKeywords:
return isClassMemberCompletionKeyword(kind);
@@ -2193,25 +1956,13 @@ namespace ts.Completions {
return isIdentifier(node) ? node.originalKeywordKind || SyntaxKind.Unknown : node.kind;
}
function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator {
switch (kind) {
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
return true;
default:
return false;
}
}
/** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined {
const jsdoc = findAncestor(node, isJSDoc);
return jsdoc && jsdoc.tags && (rangeContainsPosition(jsdoc, position) ? findLast(jsdoc.tags, tag => tag.pos < position) : undefined);
}
function getPropertiesForObjectExpression(contextualType: Type, obj: ObjectLiteralExpression, checker: TypeChecker): Symbol[] {
function getPropertiesForObjectExpression(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] {
return contextualType.isUnion()
? checker.getAllPossiblePropertiesOfTypes(contextualType.types.filter(memberType =>
// If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.
@@ -2272,10 +2023,6 @@ namespace ts.Completions {
return node.parent && isClassOrTypeElement(node.parent) && isObjectTypeDeclaration(node.parent.parent);
}
function hasIndexSignature(type: Type): boolean {
return !!type.getStringIndexType() || !!type.getNumberIndexType();
}
function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node | undefined, position: number): boolean {
switch (triggerCharacter) {
case ".":
@@ -2301,16 +2048,4 @@ namespace ts.Completions {
function binaryExpressionMayBeOpenTag({ left }: BinaryExpression): boolean {
return nodeIsMissing(left);
}
function isStringLiteralOrTemplate(node: Node): node is StringLiteralLike | TemplateExpression | TaggedTemplateExpression {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
case SyntaxKind.TaggedTemplateExpression:
return true;
default:
return false;
}
}
}
+2 -12
View File
@@ -121,14 +121,6 @@ namespace ts {
const buckets = createMap<Map<DocumentRegistryEntry>>();
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): Map<DocumentRegistryEntry> {
let bucket = buckets.get(key);
if (!bucket && createIfMissing) {
buckets.set(key, bucket = createMap<DocumentRegistryEntry>());
}
return bucket!; // TODO: GH#18217
}
function reportStats() {
const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => {
const entries = buckets.get(name)!;
@@ -178,7 +170,7 @@ namespace ts {
acquiring: boolean,
scriptKind?: ScriptKind): SourceFile {
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
const bucket = getOrUpdate<Map<DocumentRegistryEntry>>(buckets, key, createMap);
let entry = bucket.get(path);
const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : compilationSettings.target || ScriptTarget.ES5;
if (!entry && externalCache) {
@@ -238,9 +230,7 @@ namespace ts {
}
function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void {
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false);
Debug.assert(bucket !== undefined);
const bucket = Debug.assertDefined(buckets.get(key));
const entry = bucket.get(path)!;
entry.languageServiceRefCount--;
+38 -8
View File
@@ -1,8 +1,8 @@
/* @internal */
namespace ts.FindAllReferences {
export interface SymbolAndEntries {
definition: Definition | undefined;
references: Entry[];
readonly definition: Definition | undefined;
readonly references: ReadonlyArray<Entry>;
}
export const enum DefinitionKind { Symbol, Label, Keyword, This, String }
@@ -60,7 +60,7 @@ namespace ts.FindAllReferences {
return map(referenceEntries, entry => toImplementationLocation(entry, checker));
}
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number): Entry[] | undefined {
function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number): ReadonlyArray<Entry> | undefined {
if (node.kind === SyntaxKind.SourceFile) {
return undefined;
}
@@ -94,11 +94,19 @@ namespace ts.FindAllReferences {
export type ToReferenceOrRenameEntry<T> = (entry: Entry, originalNode: Node) => T;
export function getReferenceEntriesForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlyMap<true> = arrayToSet(sourceFiles, f => f.fileName)): Entry[] | undefined {
export function getReferenceEntriesForNode(
position: number,
node: Node,
program: Program,
sourceFiles: ReadonlyArray<SourceFile>,
cancellationToken: CancellationToken,
options: Options = {},
sourceFilesSet: ReadonlyMap<true> = arrayToSet(sourceFiles, f => f.fileName),
): ReadonlyArray<Entry> | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
}
function flattenEntries(referenceSymbols: SymbolAndEntries[] | undefined): Entry[] | undefined {
function flattenEntries(referenceSymbols: SymbolAndEntries[] | undefined): ReadonlyArray<Entry> | undefined {
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
}
@@ -143,7 +151,7 @@ namespace ts.FindAllReferences {
function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } {
const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol);
const enclosingDeclaration = firstOrUndefined(symbol.declarations) || node;
const enclosingDeclaration = symbol.declarations && firstOrUndefined(symbol.declarations) || node;
const { displayParts, symbolKind } =
SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning);
return { displayParts, kind: symbolKind };
@@ -360,6 +368,10 @@ namespace ts.FindAllReferences.Core {
return !options.implementations && isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
}
if (symbol.escapedName === InternalSymbolName.ExportEquals) {
return getReferencedSymbolsForModule(program, symbol.parent!, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
}
let moduleReferences: SymbolAndEntries[] = emptyArray;
const moduleSourceFile = isModuleSymbol(symbol);
let referencedNode: Node | undefined = node;
@@ -419,6 +431,22 @@ namespace ts.FindAllReferences.Core {
}
}
const exported = symbol.exports!.get(InternalSymbolName.ExportEquals);
if (exported) {
for (const decl of exported.declarations) {
const sourceFile = decl.getSourceFile();
if (sourceFilesSet.has(sourceFile.fileName)) {
// At `module.exports = ...`, reference node is `module`
const node = isBinaryExpression(decl) && isPropertyAccessExpression(decl.left)
? decl.left.expression
: isExportAssignment(decl)
? Debug.assertDefined(findChildOfKind(decl, SyntaxKind.ExportKeyword, sourceFile))
: getNameOfDeclaration(decl) || decl;
references.push(nodeEntry(node));
}
}
}
return references.length ? [{ definition: { type: DefinitionKind.Symbol, symbol }, references }] : emptyArray;
}
@@ -831,7 +859,9 @@ namespace ts.FindAllReferences.Core {
}
export function eachSymbolReferenceInFile<T>(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, cb: (token: Identifier) => T): T | undefined {
const symbol = checker.getSymbolAtLocation(definition);
const symbol = isParameterPropertyDeclaration(definition.parent)
? first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text))
: checker.getSymbolAtLocation(definition);
if (!symbol) return undefined;
for (const token of getPossibleSymbolReferenceNodes(sourceFile, symbol.name)) {
if (!isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) continue;
@@ -920,7 +950,7 @@ namespace ts.FindAllReferences.Core {
case SyntaxKind.StringLiteral: {
const str = node as StringLiteral;
return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node)) &&
return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || (isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) &&
str.text.length === searchSymbolName.length;
}
+54 -38
View File
@@ -334,7 +334,6 @@ namespace ts.formatting {
return 0;
}
/* @internal */
export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, formatContext: FormatContext): TextChange[] {
const range = { pos: 0, end: sourceFileLike.text.length };
return getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, scanner => formatSpanWorker(
@@ -365,16 +364,21 @@ namespace ts.formatting {
function formatSpan(originalRange: TextRange, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] {
// find the smallest node that fully wraps the range and compute the initial indentation for the node
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
return getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, scanner => formatSpanWorker(
originalRange,
enclosingNode,
SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options),
getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile),
scanner,
formatContext,
requestKind,
prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange),
sourceFile));
return getFormattingScanner(
sourceFile.text,
sourceFile.languageVariant,
getScanStartPosition(enclosingNode, originalRange, sourceFile),
originalRange.end,
scanner => formatSpanWorker(
originalRange,
enclosingNode,
SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options),
getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile),
scanner,
formatContext,
requestKind,
prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange),
sourceFile));
}
function formatSpanWorker(originalRange: TextRange,
@@ -413,7 +417,8 @@ namespace ts.formatting {
if (!formattingScanner.isOnToken()) {
const leadingTrivia = formattingScanner.getCurrentLeadingTrivia();
if (leadingTrivia) {
processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!); // TODO: GH#18217
indentTriviaItems(leadingTrivia, initialIndentation, /*indentNextTokenOrTrivia*/ false,
item => processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined!));
trimTrailingWhitespacesForRemainingRange();
}
}
@@ -753,17 +758,17 @@ namespace ts.formatting {
const listEndToken = getCloseTokenForOpenToken(listStartToken);
if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken()) {
let tokenInfo = formattingScanner.readTokenInfo(parent);
let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent);
if (tokenInfo.token.kind === SyntaxKind.CommaToken && isCallLikeExpression(parent)) {
formattingScanner.advance();
tokenInfo = formattingScanner.readTokenInfo(parent);
tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined;
}
// consume the list end token only if it is still belong to the parent
// there might be the case when current token matches end token but does not considered as one
// function (x: function) <--
// without this check close paren will be interpreted as list end token for function expression which is wrong
if (tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) {
if (tokenInfo && tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) {
// consume list end token
consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
}
@@ -814,27 +819,8 @@ namespace ts.formatting {
let indentNextTokenOrTrivia = true;
if (currentTokenInfo.leadingTrivia) {
const commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container);
for (const triviaItem of currentTokenInfo.leadingTrivia) {
const triviaInRange = rangeContainsRange(originalRange, triviaItem);
switch (triviaItem.kind) {
case SyntaxKind.MultiLineCommentTrivia:
if (triviaInRange) {
indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
}
indentNextTokenOrTrivia = false;
break;
case SyntaxKind.SingleLineCommentTrivia:
if (indentNextTokenOrTrivia && triviaInRange) {
insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false);
}
indentNextTokenOrTrivia = false;
break;
case SyntaxKind.NewLineTrivia:
indentNextTokenOrTrivia = true;
break;
}
}
indentNextTokenOrTrivia = indentTriviaItems(currentTokenInfo.leadingTrivia, commentIndentation, indentNextTokenOrTrivia,
item => insertIndentation(item.pos, commentIndentation, /*lineAdded*/ false));
}
// indent token only if is it is in target range and does not overlap with any error ranges
@@ -852,6 +838,34 @@ namespace ts.formatting {
}
}
function indentTriviaItems(
trivia: TextRangeWithKind[],
commentIndentation: number,
indentNextTokenOrTrivia: boolean,
indentSingleLine: (item: TextRangeWithKind) => void) {
for (const triviaItem of trivia) {
const triviaInRange = rangeContainsRange(originalRange, triviaItem);
switch (triviaItem.kind) {
case SyntaxKind.MultiLineCommentTrivia:
if (triviaInRange) {
indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
}
indentNextTokenOrTrivia = false;
break;
case SyntaxKind.SingleLineCommentTrivia:
if (indentNextTokenOrTrivia && triviaInRange) {
indentSingleLine(triviaItem);
}
indentNextTokenOrTrivia = false;
break;
case SyntaxKind.NewLineTrivia:
indentNextTokenOrTrivia = true;
break;
}
}
return indentNextTokenOrTrivia;
}
function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): void {
for (const triviaItem of trivia) {
if (isComment(triviaItem.kind) && rangeContainsRange(originalRange, triviaItem)) {
@@ -861,7 +875,6 @@ namespace ts.formatting {
}
}
// TODO: GH#18217 use an enum instead of `boolean | undefined`
function processRange(range: TextRangeWithKind,
rangeStart: LineAndCharacter,
parent: Node,
@@ -1072,7 +1085,10 @@ namespace ts.formatting {
* Trimming will be done for lines after the previous range
*/
function trimTrailingWhitespacesForRemainingRange() {
const startPosition = previousRange ? previousRange.end : originalRange.pos;
if (!previousRange) {
return;
}
const startPosition = previousRange.end;
const startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line;
const endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line;
+2 -2
View File
@@ -22,8 +22,8 @@ namespace ts.formatting {
const binaryKeywordOperators = [SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword];
const unaryPrefixOperators = [SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken];
const unaryPrefixExpressions = [
SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken,
SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword];
SyntaxKind.NumericLiteral, SyntaxKind.BigIntLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken,
SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword];
const unaryPreincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword];
const unaryPostincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword];
const unaryPredecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword];
+3 -3
View File
@@ -79,14 +79,14 @@ namespace ts.formatting {
return findFirstNonWhitespaceColumn(getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options);
}
const startPostionOfLine = getStartPositionOfLine(previousLine, sourceFile);
const { column, character } = findFirstNonWhitespaceCharacterAndColumn(startPostionOfLine, position, sourceFile, options);
const startPositionOfLine = getStartPositionOfLine(previousLine, sourceFile);
const { column, character } = findFirstNonWhitespaceCharacterAndColumn(startPositionOfLine, position, sourceFile, options);
if (column === 0) {
return column;
}
const firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPostionOfLine + character);
const firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPositionOfLine + character);
return firstNonWhitespaceCharacterCode === CharacterCodes.asterisk ? column - 1 : column;
}
+5 -4
View File
@@ -14,7 +14,7 @@ namespace ts {
const oldToNew = getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper);
const newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper);
return textChanges.ChangeTracker.with({ host, formatContext }, changeTracker => {
updateTsconfigFiles(program, changeTracker, oldToNew, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames);
updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames);
updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName);
});
}
@@ -45,7 +45,7 @@ namespace ts {
return combinePathsSafe(getDirectoryPath(a1), rel);
}
function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldToNew: PathUpdater, newFileOrDirPath: string, currentDirectory: string, useCaseSensitiveFileNames: boolean): void {
function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldToNew: PathUpdater, oldFileOrDirPath: string, newFileOrDirPath: string, currentDirectory: string, useCaseSensitiveFileNames: boolean): void {
const { configFile } = program.getCompilerOptions();
if (!configFile) return;
const configDir = getDirectoryPath(configFile.fileName);
@@ -63,7 +63,8 @@ namespace ts {
const includes = mapDefined(property.initializer.elements, e => isStringLiteral(e) ? e.text : undefined);
const matchers = getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory);
// If there isn't some include for this, add a new one.
if (!getRegexFromPattern(Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) {
if (getRegexFromPattern(Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) &&
!getRegexFromPattern(Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) {
changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), createStringLiteral(relativePath(newFileOrDirPath)));
}
}
@@ -72,7 +73,7 @@ namespace ts {
case "compilerOptions":
forEachProperty(property.initializer, (property, propertyName) => {
const option = getOptionFromName(propertyName);
if (option && (option.isFilePath || option.type === "list" && (option as CommandLineOptionOfListType).element.isFilePath)) {
if (option && (option.isFilePath || option.type === "list" && option.element.isFilePath)) {
updatePaths(property);
}
else if (propertyName === "paths") {
+3 -3
View File
@@ -1,6 +1,6 @@
/* @internal */
namespace ts.GoToDefinition {
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined {
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): ReadonlyArray<DefinitionInfo> | undefined {
const reference = getReferenceAtPosition(sourceFile, position, program);
if (reference) {
return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
@@ -129,7 +129,7 @@ namespace ts.GoToDefinition {
}
/// Goto type
export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[] | undefined {
export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): ReadonlyArray<DefinitionInfo> | undefined {
const node = getTouchingPropertyName(sourceFile, position);
if (node === sourceFile) {
return undefined;
@@ -145,7 +145,7 @@ namespace ts.GoToDefinition {
return fromReturnType && fromReturnType.length !== 0 ? fromReturnType : definitionFromType(typeAtLocation, typeChecker, node);
}
function definitionFromType(type: Type, checker: TypeChecker, node: Node): DefinitionInfo[] {
function definitionFromType(type: Type, checker: TypeChecker, node: Node): ReadonlyArray<DefinitionInfo> {
return flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t =>
t.symbol && getDefinitionFromSymbol(checker, t.symbol, node));
}
+3
View File
@@ -281,6 +281,9 @@ namespace ts.NavigationBar {
case AssignmentDeclarationKind.ThisProperty:
case AssignmentDeclarationKind.Property:
case AssignmentDeclarationKind.None:
case AssignmentDeclarationKind.ObjectDefinePropertyValue:
case AssignmentDeclarationKind.ObjectDefinePropertyExports:
case AssignmentDeclarationKind.ObjectDefinePrototypeProperty:
break;
default:
Debug.assertNever(special);
+2 -2
View File
@@ -146,7 +146,7 @@ namespace ts.OrganizeImports {
: undefined;
}
/* @internal */ // Internal for testing
// Internal for testing
/**
* @param importGroup a list of ImportDeclarations, all with the same module name.
*/
@@ -266,7 +266,7 @@ namespace ts.OrganizeImports {
}
}
/* @internal */ // Internal for testing
// Internal for testing
/**
* @param exportGroup a list of ExportDeclarations, all with the same module name.
*/
-512
View File
@@ -1,512 +0,0 @@
/* @internal */
namespace ts.Completions.PathCompletions {
export interface NameAndKind {
readonly name: string;
readonly kind: ScriptElementKind.scriptElement | ScriptElementKind.directory | ScriptElementKind.externalModuleName;
}
export interface PathCompletion extends NameAndKind {
readonly span: TextSpan | undefined;
}
function nameAndKind(name: string, kind: NameAndKind["kind"]): NameAndKind {
return { name, kind };
}
function addReplacementSpans(text: string, textStart: number, names: ReadonlyArray<NameAndKind>): ReadonlyArray<PathCompletion> {
const span = getDirectoryFragmentTextSpan(text, textStart);
return names.map(({ name, kind }): PathCompletion => ({ name, kind, span }));
}
export function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): ReadonlyArray<PathCompletion> {
return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker));
}
function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): ReadonlyArray<NameAndKind> {
const literalValue = normalizeSlashes(node.text);
const scriptPath = sourceFile.path;
const scriptDirectory = getDirectoryPath(scriptPath);
if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) {
const extensions = getSupportedExtensionsForModuleResolution(compilerOptions);
if (compilerOptions.rootDirs) {
return getCompletionEntriesForDirectoryFragmentWithRootDirs(
compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, compilerOptions, host, scriptPath);
}
else {
return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, host, scriptPath);
}
}
else {
return getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker);
}
}
function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions) {
const extensions = getSupportedExtensions(compilerOptions);
return compilerOptions.resolveJsonModule && getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ?
extensions.concat(Extension.Json) :
extensions;
}
/**
* Takes a script path and returns paths for all potential folders that could be merged with its
* containing folder via the "rootDirs" compiler option
*/
function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptPath: string, ignoreCase: boolean): string[] {
// Make all paths absolute/normalized if they are not already
rootDirs = rootDirs.map(rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory)));
// Determine the path to the directory containing the script relative to the root directory it is contained within
const relativeDirectory = firstDefined(rootDirs, rootDirectory =>
containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217
// Now find a path for each potential directory that is to be merged with the one containing the script
return deduplicate<string>(
rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)),
equateStringsCaseSensitive,
compareStringsCaseSensitive);
}
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: ReadonlyArray<string>, includeExtensions: boolean, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): NameAndKind[] {
const basePath = compilerOptions.project || host.getCurrentDirectory();
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase);
const result: NameAndKind[] = [];
for (const baseDirectory of baseDirectories) {
getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, host, exclude, result);
}
return result;
}
/**
* Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename.
*/
function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: ReadonlyArray<string>, includeExtensions: boolean, host: LanguageServiceHost, exclude?: string, result: NameAndKind[] = []): NameAndKind[] {
if (fragment === undefined) {
fragment = "";
}
fragment = normalizeSlashes(fragment);
/**
* Remove the basename from the path. Note that we don't use the basename to filter completions;
* the client is responsible for refining completions.
*/
if (!hasTrailingDirectorySeparator(fragment)) {
fragment = getDirectoryPath(fragment);
}
if (fragment === "") {
fragment = "." + directorySeparator;
}
fragment = ensureTrailingDirectorySeparator(fragment);
// const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths
const absolutePath = resolvePath(scriptPath, fragment);
const baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath);
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
if (tryDirectoryExists(host, baseDirectory)) {
// Enumerate the available files if possible
const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]);
if (files) {
/**
* Multiple file entries might map to the same truncated name once we remove extensions
* (happens iff includeExtensions === false)so we use a set-like data structure. Eg:
*
* both foo.ts and foo.tsx become foo
*/
const foundFiles = createMap<true>();
for (let filePath of files) {
filePath = normalizePath(filePath);
if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) {
continue;
}
const foundFileName = includeExtensions || fileExtensionIs(filePath, Extension.Json) ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath));
if (!foundFiles.has(foundFileName)) {
foundFiles.set(foundFileName, true);
}
}
forEachKey(foundFiles, foundFile => {
result.push(nameAndKind(foundFile, ScriptElementKind.scriptElement));
});
}
// If possible, get folder completion as well
const directories = tryGetDirectories(host, baseDirectory);
if (directories) {
for (const directory of directories) {
const directoryName = getBaseFileName(normalizePath(directory));
if (directoryName !== "@types") {
result.push(nameAndKind(directoryName, ScriptElementKind.directory));
}
}
}
// check for a version redirect
const packageJsonPath = findPackageJson(baseDirectory, host);
if (packageJsonPath) {
const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined });
const typesVersions = (packageJson as any).typesVersions;
if (typeof typesVersions === "object") {
const versionResult = getPackageJsonTypesVersionsPaths(typesVersions);
const versionPaths = versionResult && versionResult.paths;
const rest = absolutePath.slice(ensureTrailingDirectorySeparator(baseDirectory).length);
if (versionPaths) {
addCompletionEntriesFromPaths(result, rest, baseDirectory, extensions, versionPaths, host);
}
}
}
}
return result;
}
function addCompletionEntriesFromPaths(result: NameAndKind[], fragment: string, baseDirectory: string, fileExtensions: ReadonlyArray<string>, paths: MapLike<string[]>, host: LanguageServiceHost) {
for (const path in paths) {
if (!hasProperty(paths, path)) continue;
const patterns = paths[path];
if (patterns) {
for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseDirectory, fileExtensions, host)) {
// Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
if (!result.some(entry => entry.name === name)) {
result.push(nameAndKind(name, kind));
}
}
}
}
}
/**
* Check all of the declared modules and those in node modules. Possible sources of modules:
* Modules that are found by the type checker
* Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option)
* Modules from node_modules (i.e. those listed in package.json)
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions
*/
function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): NameAndKind[] {
const { baseUrl, paths } = compilerOptions;
const result: NameAndKind[] = [];
const fileExtensions = getSupportedExtensionsForModuleResolution(compilerOptions);
if (baseUrl) {
const projectDir = compilerOptions.project || host.getCurrentDirectory();
const absolute = normalizePath(combinePaths(projectDir, baseUrl));
getCompletionEntriesForDirectoryFragment(fragment, absolute, fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result);
if (paths) {
addCompletionEntriesFromPaths(result, fragment, absolute, fileExtensions, paths, host);
}
}
const fragmentDirectory = containsSlash(fragment) ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined;
for (const ambientName of getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker)) {
result.push(nameAndKind(ambientName, ScriptElementKind.externalModuleName));
}
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, result);
if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs) {
// If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies.
// (But do if we didn't find anything, e.g. 'package.json' missing.)
let foundGlobal = false;
if (fragmentDirectory === undefined) {
for (const moduleName of enumerateNodeModulesVisibleToScript(host, scriptPath)) {
if (!result.some(entry => entry.name === moduleName)) {
foundGlobal = true;
result.push(nameAndKind(moduleName, ScriptElementKind.externalModuleName));
}
}
}
if (!foundGlobal) {
forEachAncestorDirectory(scriptPath, ancestor => {
const nodeModules = combinePaths(ancestor, "node_modules");
if (tryDirectoryExists(host, nodeModules)) {
getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result);
}
});
}
}
return result;
}
function getCompletionsForPathMapping(
path: string, patterns: ReadonlyArray<string>, fragment: string, baseUrl: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost,
): ReadonlyArray<NameAndKind> {
if (!endsWith(path, "*")) {
// For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion.
return !stringContains(path, "*") ? justPathMappingName(path) : emptyArray;
}
const pathPrefix = path.slice(0, path.length - 1);
const remainingFragment = tryRemovePrefix(fragment, pathPrefix);
return remainingFragment === undefined ? justPathMappingName(pathPrefix) : flatMap(patterns, pattern =>
getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host));
function justPathMappingName(name: string): ReadonlyArray<NameAndKind> {
return startsWith(name, fragment) ? [{ name, kind: ScriptElementKind.directory }] : emptyArray;
}
}
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: ReadonlyArray<string>, host: LanguageServiceHost): ReadonlyArray<NameAndKind> | undefined {
if (!host.readDirectory) {
return undefined;
}
const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined;
if (!parsed) {
return undefined;
}
// The prefix has two effective parts: the directory path and the base component after the filepath that is not a
// full directory component. For example: directory/path/of/prefix/base*
const normalizedPrefix = resolvePath(parsed.prefix);
const normalizedPrefixDirectory = hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : getDirectoryPath(normalizedPrefix);
const normalizedPrefixBase = hasTrailingDirectorySeparator(parsed.prefix) ? "" : getBaseFileName(normalizedPrefix);
const fragmentHasPath = containsSlash(fragment);
const fragmentDirectory = fragmentHasPath ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined;
// Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory;
const normalizedSuffix = normalizePath(parsed.suffix);
// Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b".
const baseDirectory = normalizePath(combinePaths(baseUrl, expandedPrefixDirectory));
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
// If we have a suffix, then we need to read the directory all the way down. We could create a glob
// that encodes the suffix, but we would have to escape the character "?" which readDirectory
// doesn't support. For now, this is safer but slower
const includeGlob = normalizedSuffix ? "**/*" : "./*";
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]).map<NameAndKind>(name => ({ name, kind: ScriptElementKind.scriptElement }));
const directories = tryGetDirectories(host, baseDirectory).map(d => combinePaths(baseDirectory, d)).map<NameAndKind>(name => ({ name, kind: ScriptElementKind.directory }));
// Trim away prefix and suffix
return mapDefined<NameAndKind, NameAndKind>(concatenate(matches, directories), ({ name, kind }) => {
const normalizedMatch = normalizePath(name);
const inner = withoutStartAndEnd(normalizedMatch, completePrefix, normalizedSuffix);
return inner !== undefined ? { name: removeLeadingDirectorySeparator(removeFileExtension(inner)), kind } : undefined;
});
}
function withoutStartAndEnd(s: string, start: string, end: string): string | undefined {
return startsWith(s, start) && endsWith(s, end) ? s.slice(start.length, s.length - end.length) : undefined;
}
function removeLeadingDirectorySeparator(path: string): string {
return path[0] === directorySeparator ? path.slice(1) : path;
}
function getAmbientModuleCompletions(fragment: string, fragmentDirectory: string | undefined, checker: TypeChecker): ReadonlyArray<string> {
// Get modules that the type checker picked up
const ambientModules = checker.getAmbientModules().map(sym => stripQuotes(sym.name));
const nonRelativeModuleNames = ambientModules.filter(moduleName => startsWith(moduleName, fragment));
// Nested modules of the form "module-name/sub" need to be adjusted to only return the string
// after the last '/' that appears in the fragment because that's where the replacement span
// starts
if (fragmentDirectory !== undefined) {
const moduleNameWithSeparator = ensureTrailingDirectorySeparator(fragmentDirectory);
return nonRelativeModuleNames.map(nonRelativeModuleName => removePrefix(nonRelativeModuleName, moduleNameWithSeparator));
}
return nonRelativeModuleNames;
}
export function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): ReadonlyArray<PathCompletion> | undefined {
const token = getTokenAtPosition(sourceFile, position);
const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos);
const range = commentRanges && find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end);
if (!range) {
return undefined;
}
const text = sourceFile.text.slice(range.pos, position);
const match = tripleSlashDirectiveFragmentRegex.exec(text);
if (!match) {
return undefined;
}
const [, prefix, kind, toComplete] = match;
const scriptPath = getDirectoryPath(sourceFile.path);
const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/ true, host, sourceFile.path)
: kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath)
: undefined;
return names && addReplacementSpans(toComplete, range.pos + prefix.length, names);
}
function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, result: NameAndKind[] = []): NameAndKind[] {
// Check for typings specified in compiler options
const seen = createMap<true>();
if (options.types) {
for (const typesName of options.types) {
const moduleName = unmangleScopedPackageName(typesName);
pushResult(moduleName);
}
}
else if (host.getDirectories) {
let typeRoots: ReadonlyArray<string> | undefined;
try {
typeRoots = getEffectiveTypeRoots(options, host);
}
catch { /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */ }
if (typeRoots) {
for (const root of typeRoots) {
getCompletionEntriesFromDirectories(root);
}
}
// Also get all @types typings installed in visible node_modules directories
for (const packageJson of findPackageJsons(scriptPath, host)) {
const typesDir = combinePaths(getDirectoryPath(packageJson), "node_modules/@types");
getCompletionEntriesFromDirectories(typesDir);
}
}
return result;
function getCompletionEntriesFromDirectories(directory: string) {
Debug.assert(!!host.getDirectories);
if (tryDirectoryExists(host, directory)) {
const directories = tryGetDirectories(host, directory);
if (directories) {
for (let typeDirectory of directories) {
typeDirectory = normalizePath(typeDirectory);
const directoryName = getBaseFileName(typeDirectory);
const moduleName = unmangleScopedPackageName(directoryName);
pushResult(moduleName);
}
}
}
}
function pushResult(moduleName: string) {
if (!seen.has(moduleName)) {
result.push(nameAndKind(moduleName, ScriptElementKind.externalModuleName));
seen.set(moduleName, true);
}
}
}
function findPackageJsons(directory: string, host: LanguageServiceHost): string[] {
const paths: string[] = [];
forEachAncestorDirectory(directory, ancestor => {
const currentConfigPath = findConfigFile(ancestor, (f) => tryFileExists(host, f), "package.json");
if (!currentConfigPath) {
return true; // break out
}
paths.push(currentConfigPath);
});
return paths;
}
function findPackageJson(directory: string, host: LanguageServiceHost): string | undefined {
let packageJson: string | undefined;
forEachAncestorDirectory(directory, ancestor => {
if (ancestor === "node_modules") return true;
packageJson = findConfigFile(ancestor, (f) => tryFileExists(host, f), "package.json");
if (packageJson) {
return true; // break out
}
});
return packageJson;
}
function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string): ReadonlyArray<string> {
if (!host.readFile || !host.fileExists) return emptyArray;
const result: string[] = [];
for (const packageJson of findPackageJsons(scriptPath, host)) {
const contents = readJson(packageJson, host as { readFile: (filename: string) => string | undefined }); // Cast to assert that readFile is defined
// Provide completions for all non @types dependencies
for (const key of nodeModulesDependencyKeys) {
const dependencies: object | undefined = (contents as any)[key];
if (!dependencies) continue;
for (const dep in dependencies) {
if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types/")) {
result.push(dep);
}
}
}
}
return result;
}
// Replace everything after the last directory separator that appears
function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan | undefined {
const index = Math.max(text.lastIndexOf(directorySeparator), text.lastIndexOf("\\"));
const offset = index !== -1 ? index + 1 : 0;
// If the range is an identifier, span is unnecessary.
const length = text.length - offset;
return length === 0 || isIdentifierText(text.substr(offset, length), ScriptTarget.ESNext) ? undefined : createTextSpan(textStart + offset, length);
}
// Returns true if the path is explicitly relative to the script (i.e. relative to . or ..)
function isPathRelativeToScript(path: string) {
if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) {
const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1;
const slashCharCode = path.charCodeAt(slashIndex);
return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash;
}
return false;
}
/**
* Matches a triple slash reference directive with an incomplete string literal for its path. Used
* to determine if the caret is currently within the string literal and capture the literal fragment
* for completions.
* For example, this matches
*
* /// <reference path="fragment
*
* but not
*
* /// <reference path="fragment"
*/
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^\3"]*)$/;
const nodeModulesDependencyKeys = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
function tryGetDirectories(host: LanguageServiceHost, directoryName: string): string[] {
return tryIOAndConsumeErrors(host, host.getDirectories, directoryName) || [];
}
function tryReadDirectory(host: LanguageServiceHost, path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>): ReadonlyArray<string> {
return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || emptyArray;
}
function tryFileExists(host: LanguageServiceHost, path: string): boolean {
return tryIOAndConsumeErrors(host, host.fileExists, path);
}
function tryDirectoryExists(host: LanguageServiceHost, path: string): boolean {
try {
return directoryProbablyExists(path, host);
}
catch { /*ignore*/ }
return false;
}
function tryIOAndConsumeErrors<T>(host: LanguageServiceHost, toApply: ((...a: any[]) => T) | undefined, ...args: any[]) {
try {
return toApply && toApply.apply(host, args);
}
catch { /*ignore*/ }
return undefined;
}
function containsSlash(fragment: string) {
return stringContains(fragment, directorySeparator);
}
}
+2 -2
View File
@@ -461,11 +461,11 @@ namespace ts {
};
}
/* @internal */ export function breakIntoCharacterSpans(identifier: string): TextSpan[] {
export function breakIntoCharacterSpans(identifier: string): TextSpan[] {
return breakIntoSpans(identifier, /*word:*/ false);
}
/* @internal */ export function breakIntoWordSpans(identifier: string): TextSpan[] {
export function breakIntoWordSpans(identifier: string): TextSpan[] {
return breakIntoSpans(identifier, /*word:*/ true);
}
+1 -1
View File
@@ -5,7 +5,7 @@ namespace ts {
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
/** Compute (quickly) which actions are available here */
getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined;
getAvailableActions(context: RefactorContext): ReadonlyArray<ApplicableRefactorInfo>;
}
export interface RefactorContext extends textChanges.TextChangesContext {
@@ -15,10 +15,10 @@ namespace ts.refactor.addOrRemoveBracesToArrowFunction {
addBraces: boolean;
}
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
function getAvailableActions(context: RefactorContext): ReadonlyArray<ApplicableRefactorInfo> {
const { file, startPosition } = context;
const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
if (!info) return undefined;
if (!info) return emptyArray;
return [{
name: refactorName,
+2 -2
View File
@@ -4,9 +4,9 @@ namespace ts.refactor {
const actionNameDefaultToNamed = "Convert default export to named export";
const actionNameNamedToDefault = "Convert named export to default export";
registerRefactor(refactorName, {
getAvailableActions(context): ApplicableRefactorInfo[] | undefined {
getAvailableActions(context): ReadonlyArray<ApplicableRefactorInfo> {
const info = getInfo(context);
if (!info) return undefined;
if (!info) return emptyArray;
const description = info.wasDefault ? Diagnostics.Convert_default_export_to_named_export.message : Diagnostics.Convert_named_export_to_default_export.message;
const actionName = info.wasDefault ? actionNameDefaultToNamed : actionNameNamedToDefault;
return [{ name: refactorName, description, actions: [{ name: actionName, description }] }];
+2 -2
View File
@@ -4,9 +4,9 @@ namespace ts.refactor {
const actionNameNamespaceToNamed = "Convert namespace import to named imports";
const actionNameNamedToNamespace = "Convert named imports to namespace import";
registerRefactor(refactorName, {
getAvailableActions(context): ApplicableRefactorInfo[] | undefined {
getAvailableActions(context): ReadonlyArray<ApplicableRefactorInfo> {
const i = getImportToConvert(context);
if (!i) return undefined;
if (!i) return emptyArray;
const description = i.kind === SyntaxKind.NamespaceImport ? Diagnostics.Convert_namespace_import_to_named_imports.message : Diagnostics.Convert_named_imports_to_namespace_import.message;
const actionName = i.kind === SyntaxKind.NamespaceImport ? actionNameNamespaceToNamed : actionNameNamedToNamespace;
return [{ name: refactorName, description, actions: [{ name: actionName, description }] }];
+4 -4
View File
@@ -7,18 +7,18 @@ namespace ts.refactor.extractSymbol {
* Compute the associated code actions
* Exported for tests.
*/
export function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
export function getAvailableActions(context: RefactorContext): ReadonlyArray<ApplicableRefactorInfo> {
const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context));
const targetRange = rangeToExtract.targetRange;
if (targetRange === undefined) {
return undefined;
return emptyArray;
}
const extractions = getPossibleExtractions(targetRange, context);
if (extractions === undefined) {
// No extractions possible
return undefined;
return emptyArray;
}
const functionActions: RefactorActionInfo[] = [];
@@ -82,7 +82,7 @@ namespace ts.refactor.extractSymbol {
});
}
return infos.length ? infos : undefined;
return infos.length ? infos : emptyArray;
}
/* Exported for tests */

Some files were not shown because too many files have changed in this diff Show More