Merge branch 'master' into tsconfig_canonicalpath

This commit is contained in:
Andy Hanson
2018-10-22 14:35:42 -07:00
1657 changed files with 70641 additions and 34449 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ Please fill in the *entire* template below.
-->
<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:** 3.1.0-dev.201xxxxx
**TypeScript Version:** 3.2.0-dev.201xxxxx
<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
+1
View File
@@ -20,6 +20,7 @@ branches:
- release-2.8
- release-2.9
- release-3.0
- release-3.1
install:
- npm uninstall typescript --no-save
+1
View File
@@ -0,0 +1 @@
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
+3 -3
View File
@@ -72,7 +72,7 @@ Your pull request should:
* Requests need not be a single commit, but should be a linear sequence of commits (i.e. no merge commits in your PR)
* It is desirable, but not necessary, for the tests to pass at each commit
* Have clear commit messages
* e.g. "Refactor feature", "Fix issue", "Add tests for issue"
* e.g. "Minor refactor in goToTypeDefinition", "Fix iterated type in for-await-of", "Add test for preserveWatchOutput on command line"
* Include adequate tests
* At least one test should fail in the absence of your non-test code changes. If your PR does not match this criteria, please specify why
* Tests should include reasonable permutations of the target fix/change
@@ -104,7 +104,7 @@ To run all tests, invoke the `runtests-parallel` target using jake:
jake runtests-parallel
```
This run will all tests; to run only a specific subset of tests, use:
This will run all tests; to run only a specific subset of tests, use:
```Shell
jake runtests tests=<regex>
@@ -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
@@ -61,7 +61,7 @@ Change to the TypeScript directory:
cd TypeScript
```
Install Jake tools and dev dependencies:
Install [Jake](http://jakejs.com/) tools and dev dependencies:
```bash
npm install -g jake
+1 -1
View File
@@ -286,7 +286,7 @@ function f(s) {
}
```
In the JavaScript output, all type annotations have been erased. In general, TypeScript erases all type information before emiting JavaScript.
In the JavaScript output, all type annotations have been erased. In general, TypeScript erases all type information before emitting JavaScript.
## <a name="1.1"/>1.1 Ambient Declarations
+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",
+5112 -3371
View File
File diff suppressed because it is too large Load Diff
+7546 -4530
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;
/**
+7653 -4620
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[];
+7223 -4440
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[];
+7223 -4440
View File
File diff suppressed because it is too large Load Diff
+5812 -3851
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": "已生成声明文件的输出目录。",
+3 -2
View File
@@ -1,8 +1,8 @@
{
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "http://typescriptlang.org/",
"version": "3.1.0",
"homepage": "https://www.typescriptlang.org/",
"version": "3.2.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
@@ -75,6 +75,7 @@
"gulp-typescript": "latest",
"istanbul": "latest",
"jake": "latest",
"lodash": "4.17.10",
"merge2": "latest",
"minimist": "latest",
"mkdirp": "latest",
+312 -8
View File
@@ -4,7 +4,7 @@ const fs = require("fs");
const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util)
const ts = require("../../lib/typescript");
const { Duplex } = require("stream");
const chalk = require("./chalk");
const chalk = /**@type {*} */(require("chalk"));
const Vinyl = require("vinyl");
/**
@@ -14,7 +14,7 @@ const Vinyl = require("vinyl");
* @param {UpToDateOptions} [options]
*
* @typedef UpToDateOptions
* @property {boolean} [verbose]
* @property {boolean | "minimal"} [verbose]
* @property {(configFilePath: string) => ParsedCommandLine | undefined} [parseProject]
*/
function upToDate(parsedProject, options) {
@@ -47,9 +47,9 @@ function upToDate(parsedProject, options) {
cb();
},
final(cb) {
const status = ts.getUpToDateStatus(upToDateHost, parsedProject);
const status = getUpToDateStatus(upToDateHost, parsedProject);
reportStatus(parsedProject, status, options);
if (status.type !== ts.UpToDateStatusType.UpToDate) {
if (status.type !== UpToDateStatusType.UpToDate) {
for (const input of inputs) duplex.push(input);
}
duplex.push(null);
@@ -88,11 +88,25 @@ function formatMessage(message, ...args) {
/**
* @param {ParsedCommandLine} project
* @param {UpToDateStatus} status
* @param {{verbose?: boolean}} options
* @param {{verbose?: boolean | "minimal"}} options
*/
function reportStatus(project, status, options) {
switch (options.verbose) {
case "minimal":
switch (status.type) {
case UpToDateStatusType.UpToDate:
log.info(`Project '${fileName(project.options.configFilePath)}' is up to date.`);
break;
default:
log.info(`Project '${fileName(project.options.configFilePath)}' is out of date, rebuilding...`);
break;
}
break;
case true:
/**@type {*}*/(ts).formatUpToDateStatus(project.options.configFilePath, status, fileName, formatMessage);
break;
}
if (!options.verbose) return;
ts.formatUpToDateStatus(project.options.configFilePath, status, fileName, formatMessage);
}
/**
@@ -120,12 +134,302 @@ function formatStringFromArgs(text, args, baseIndex = 0) {
return text.replace(/{(\d+)}/g, (_match, index) => args[+index + baseIndex]);
}
const minimumDate = new Date(-8640000000000000);
const maximumDate = new Date(8640000000000000);
const missingFileModifiedTime = new Date(0);
/**
* @typedef {0} UpToDateStatusType.Unbuildable
* @typedef {1} UpToDateStatusType.UpToDate
* @typedef {2} UpToDateStatusType.UpToDateWithUpstreamTypes
* @typedef {3} UpToDateStatusType.OutputMissing
* @typedef {4} UpToDateStatusType.OutOfDateWithSelf
* @typedef {5} UpToDateStatusType.OutOfDateWithUpstream
* @typedef {6} UpToDateStatusType.UpstreamOutOfDate
* @typedef {7} UpToDateStatusType.UpstreamBlocked
* @typedef {8} UpToDateStatusType.ComputingUpstream
* @typedef {9} UpToDateStatusType.ContainerOnly
* @enum {UpToDateStatusType.Unbuildable | UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes | UpToDateStatusType.OutputMissing | UpToDateStatusType.OutOfDateWithSelf | UpToDateStatusType.OutOfDateWithUpstream | UpToDateStatusType.UpstreamOutOfDate | UpToDateStatusType.UpstreamBlocked | UpToDateStatusType.ComputingUpstream | UpToDateStatusType.ContainerOnly}
*/
const UpToDateStatusType = {
Unbuildable: /** @type {0} */(0),
UpToDate: /** @type {1} */(1),
UpToDateWithUpstreamTypes: /** @type {2} */(2),
OutputMissing: /** @type {3} */(3),
OutOfDateWithSelf: /** @type {4} */(4),
OutOfDateWithUpstream: /** @type {5} */(5),
UpstreamOutOfDate: /** @type {6} */(6),
UpstreamBlocked: /** @type {7} */(7),
ComputingUpstream: /** @type {8} */(8),
ContainerOnly: /** @type {9} */(9),
};
/**
* @param {Date} date1
* @param {Date} date2
* @returns {Date}
*/
function newer(date1, date2) {
return date2 > date1 ? date2 : date1;
}
/**
* @param {UpToDateHost} host
* @param {ParsedCommandLine | undefined} project
* @returns {UpToDateStatus}
*/
function getUpToDateStatus(host, project) {
if (project === undefined) return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
const prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath) : undefined;
if (prior !== undefined) {
return prior;
}
const actual = getUpToDateStatusWorker(host, project);
if (host.setLastStatus) {
host.setLastStatus(project.options.configFilePath, actual);
}
return actual;
}
/**
* @param {UpToDateHost} host
* @param {ParsedCommandLine | undefined} project
* @returns {UpToDateStatus}
*/
function getUpToDateStatusWorker(host, project) {
/** @type {string} */
let newestInputFileName = undefined;
let newestInputFileTime = minimumDate;
// Get timestamps of input files
for (const inputFile of project.fileNames) {
if (!host.fileExists(inputFile)) {
return {
type: UpToDateStatusType.Unbuildable,
reason: `${inputFile} does not exist`
};
}
const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime;
if (inputTime > newestInputFileTime) {
newestInputFileName = inputFile;
newestInputFileTime = inputTime;
}
}
// Collect the expected outputs of this project
const outputs = /**@type {string[]}*/(/**@type {*}*/(ts).getAllProjectOutputs(project));
if (outputs.length === 0) {
return {
type: UpToDateStatusType.ContainerOnly
};
}
// Now see if all outputs are newer than the newest input
let oldestOutputFileName = "(none)";
let oldestOutputFileTime = maximumDate;
let newestOutputFileName = "(none)";
let newestOutputFileTime = minimumDate;
/** @type {string | undefined} */
let missingOutputFileName;
let newestDeclarationFileContentChangedTime = minimumDate;
let isOutOfDateWithInputs = false;
for (const output of outputs) {
// Output is missing; can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
if (!host.fileExists(output)) {
missingOutputFileName = output;
break;
}
const outputTime = host.getModifiedTime(output) || missingFileModifiedTime;
if (outputTime < oldestOutputFileTime) {
oldestOutputFileTime = outputTime;
oldestOutputFileName = output;
}
// If an output is older than the newest input, we can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
if (outputTime < newestInputFileTime) {
isOutOfDateWithInputs = true;
break;
}
if (outputTime > newestOutputFileTime) {
newestOutputFileTime = outputTime;
newestOutputFileName = output;
}
// Keep track of when the most recent time a .d.ts file was changed.
// In addition to file timestamps, we also keep track of when a .d.ts file
// had its file touched but not had its contents changed - this allows us
// to skip a downstream typecheck
if (path.extname(output) === ".d.ts") {
const unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
if (unchangedTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
}
else {
const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime;
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
}
}
}
let pseudoUpToDate = false;
let usesPrepend = false;
/** @type {string | undefined} */
let upstreamChangedProject;
if (project.projectReferences) {
if (host.setLastStatus) host.setLastStatus(project.options.configFilePath, { type: UpToDateStatusType.ComputingUpstream });
for (const ref of project.projectReferences) {
usesPrepend = usesPrepend || !!(ref.prepend);
const resolvedRef = ts.resolveProjectReferencePath(host, ref);
const parsedRef = host.parseConfigFile ? host.parseConfigFile(resolvedRef) : ts.getParsedCommandLineOfConfigFile(resolvedRef, {}, parseConfigHost);
const refStatus = getUpToDateStatus(host, parsedRef);
// Its a circular reference ignore the status of this project
if (refStatus.type === UpToDateStatusType.ComputingUpstream) {
continue;
}
// An upstream project is blocked
if (refStatus.type === UpToDateStatusType.Unbuildable) {
return {
type: UpToDateStatusType.UpstreamBlocked,
upstreamProjectName: ref.path
};
}
// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
if (refStatus.type !== UpToDateStatusType.UpToDate) {
return {
type: UpToDateStatusType.UpstreamOutOfDate,
upstreamProjectName: ref.path
};
}
// If the upstream project's newest file is older than our oldest output, we
// can't be out of date because of it
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
continue;
}
// If the upstream project has only change .d.ts files, and we've built
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
pseudoUpToDate = true;
upstreamChangedProject = ref.path;
continue;
}
// We have an output older than an upstream output - we are out of date
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: ref.path
};
}
}
if (missingOutputFileName !== undefined) {
return {
type: UpToDateStatusType.OutputMissing,
missingOutputFileName
};
}
if (isOutOfDateWithInputs) {
return {
type: UpToDateStatusType.OutOfDateWithSelf,
outOfDateOutputFileName: oldestOutputFileName,
newerInputFileName: newestInputFileName
};
}
if (usesPrepend && pseudoUpToDate) {
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: upstreamChangedProject
};
}
// Up to date
return {
type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime,
newestInputFileTime,
newestOutputFileTime,
newestInputFileName,
newestOutputFileName,
oldestOutputFileName
};
}
const parseConfigHost = {
useCaseSensitiveFileNames: true,
getCurrentDirectory: () => process.cwd(),
readDirectory: (file) => fs.readdirSync(file),
fileExists: file => fs.existsSync(file) && fs.statSync(file).isFile(),
readFile: file => fs.readFileSync(file, "utf8"),
onUnRecoverableConfigFileDiagnostic: () => undefined
};
/**
* @typedef {import("vinyl")} File
* @typedef {import("../../lib/typescript").ParsedCommandLine & { options: CompilerOptions }} ParsedCommandLine
* @typedef {import("../../lib/typescript").CompilerOptions & { configFilePath?: string }} CompilerOptions
* @typedef {import("../../lib/typescript").UpToDateHost} UpToDateHost
* @typedef {import("../../lib/typescript").UpToDateStatus} UpToDateStatus
* @typedef {import("../../lib/typescript").DiagnosticMessage} DiagnosticMessage
* @typedef UpToDateHost
* @property {(fileName: string) => boolean} fileExists
* @property {(fileName: string) => Date} getModifiedTime
* @property {(fileName: string) => Date} [getUnchangedTime]
* @property {(configFilePath: string) => ParsedCommandLine | undefined} parseConfigFile
* @property {(configFilePath: string) => UpToDateStatus} [getLastStatus]
* @property {(configFilePath: string, status: UpToDateStatus) => void} [setLastStatus]
*
* @typedef Status.Unbuildable
* @property {UpToDateStatusType.Unbuildable} type
* @property {string} reason
*
* @typedef Status.ContainerOnly
* @property {UpToDateStatusType.ContainerOnly} type
*
* @typedef Status.UpToDate
* @property {UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes} type
* @property {Date} [newestInputFileTime]
* @property {string} [newestInputFileName]
* @property {Date} [newestDeclarationFileContentChangedTime]
* @property {Date} [newestOutputFileTime]
* @property {string} [newestOutputFileName]
* @property {string} [oldestOutputFileName]
*
* @typedef Status.OutputMissing
* @property {UpToDateStatusType.OutputMissing} type
* @property {string} missingOutputFileName
*
* @typedef Status.OutOfDateWithSelf
* @property {UpToDateStatusType.OutOfDateWithSelf} type
* @property {string} outOfDateOutputFileName
* @property {string} newerInputFileName
*
* @typedef Status.UpstreamOutOfDate
* @property {UpToDateStatusType.UpstreamOutOfDate} type
* @property {string} upstreamProjectName
*
* @typedef Status.UpstreamBlocked
* @property {UpToDateStatusType.UpstreamBlocked} type
* @property {string} upstreamProjectName
*
* @typedef Status.ComputingUpstream
* @property {UpToDateStatusType.ComputingUpstream} type
*
* @typedef Status.OutOfDateWithUpstream
* @property {UpToDateStatusType.OutOfDateWithUpstream} type
* @property {string} outOfDateOutputFileName
* @property {string} newerProjectName
* @typedef {Status.Unbuildable | Status.ContainerOnly | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ComputingUpstream | Status.OutOfDateWithUpstream} UpToDateStatus
*/
void 0;
+98 -55
View File
@@ -640,6 +640,7 @@ namespace ts {
function bindChildrenWorker(node: Node): void {
if (checkUnreachable(node)) {
bindEachChild(node);
bindJSDoc(node);
return;
}
switch (node.kind) {
@@ -1180,7 +1181,6 @@ namespace ts {
}
const preCaseLabel = createBranchLabel();
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, fallthroughFlow);
currentFlow = finishFlowLabel(preCaseLabel);
const clause = clauses[i];
@@ -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);
}
@@ -2310,27 +2323,17 @@ namespace ts {
if (node.modifiers && node.modifiers.length) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Modifiers_cannot_appear_here));
}
if (node.parent.kind !== SyntaxKind.SourceFile) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Global_module_exports_may_only_appear_at_top_level));
return;
const diag = !isSourceFile(node.parent) ? Diagnostics.Global_module_exports_may_only_appear_at_top_level
: !isExternalModule(node.parent) ? Diagnostics.Global_module_exports_may_only_appear_in_module_files
: !node.parent.isDeclarationFile ? Diagnostics.Global_module_exports_may_only_appear_in_declaration_files
: undefined;
if (diag) {
file.bindDiagnostics.push(createDiagnosticForNode(node, diag));
}
else {
const parent = node.parent as SourceFile;
if (!isExternalModule(parent)) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Global_module_exports_may_only_appear_in_module_files));
return;
}
if (!parent.isDeclarationFile) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Global_module_exports_may_only_appear_in_declaration_files));
return;
}
file.symbol.globalExports = file.symbol.globalExports || createSymbolTable();
declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
}
file.symbol.globalExports = file.symbol.globalExports || createSymbolTable();
declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
}
function bindExportDeclaration(node: ExportDeclaration) {
@@ -2361,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
@@ -2465,7 +2484,12 @@ namespace ts {
node.left.parent = node;
node.right.parent = node;
const lhs = node.left as PropertyAccessEntityNameExpression;
bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false);
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);
}
/**
@@ -2486,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;
@@ -2517,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;
if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace)) && isToplevel) {
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;
@@ -2538,6 +2564,10 @@ namespace ts {
}
});
}
return namespaceSymbol;
}
function bindPotentiallyNewExpandoMemberToNamespace(declaration: PropertyAccessEntityNameExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) {
if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) {
return;
}
@@ -2547,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);
}
/**
@@ -3010,7 +3049,7 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpread
if (subtreeFlags & TransformFlags.ContainsRestOrSpread
|| (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) {
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
// node.
@@ -3041,7 +3080,7 @@ namespace ts {
if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpread) {
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
// If the this node contains a SpreadElementExpression then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
@@ -3084,18 +3123,18 @@ namespace ts {
// syntax.
if (node.questionToken
|| node.type
|| subtreeFlags & TransformFlags.ContainsDecorators
|| (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax && some(node.decorators))
|| isThisIdentifier(name)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If a parameter has an accessibility modifier, then it is TypeScript syntax.
if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) {
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsTypeScriptClassSyntax;
}
// parameters with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3148,7 +3187,7 @@ namespace ts {
// TypeScript syntax.
// An exported declaration may be TypeScript syntax, but is handled by the visitor
// for a namespace declaration.
if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask)
if ((subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax)
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@@ -3170,7 +3209,7 @@ namespace ts {
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask
if (subtreeFlags & TransformFlags.ContainsTypeScriptClassSyntax
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@@ -3247,7 +3286,7 @@ namespace ts {
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3271,7 +3310,7 @@ namespace ts {
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3302,7 +3341,7 @@ namespace ts {
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3317,7 +3356,7 @@ namespace ts {
// If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor
// so that it handle the transformation.
if (node.initializer || isComputedPropertyName(node.name)) {
transformFlags |= TransformFlags.ContainsPropertyInitializer;
transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3351,7 +3390,7 @@ namespace ts {
}
// function declarations with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3393,7 +3432,7 @@ namespace ts {
}
// function expressions with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3434,7 +3473,7 @@ namespace ts {
}
// arrow functions with object rest destructuring are ES Next syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3454,7 +3493,9 @@ namespace ts {
// ES6 syntax, and requires a lexical `this` binding.
if (transformFlags & TransformFlags.Super) {
transformFlags ^= TransformFlags.Super;
transformFlags |= TransformFlags.ContainsSuper;
// super inside of an async function requires hoisting the super access (ES2017).
// same for super inside of an async generator, which is ESNext.
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3470,7 +3511,9 @@ namespace ts {
// ES6 syntax, and requires a lexical `this` binding.
if (expressionFlags & TransformFlags.Super) {
transformFlags &= ~TransformFlags.Super;
transformFlags |= TransformFlags.ContainsSuper;
// super inside of an async function requires hoisting the super access (ES2017).
// same for super inside of an async generator, which is ESNext.
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3482,7 +3525,7 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
// A VariableDeclaration containing ObjectRest is ESNext syntax
if (subtreeFlags & TransformFlags.ContainsObjectRest) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext;
}
@@ -3731,11 +3774,11 @@ namespace ts {
break;
case SyntaxKind.SpreadElement:
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsSpread;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsRestOrSpread;
break;
case SyntaxKind.SpreadAssignment:
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectSpread;
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRestOrSpread;
break;
case SyntaxKind.SuperKeyword:
@@ -3751,8 +3794,8 @@ namespace ts {
case SyntaxKind.ObjectBindingPattern:
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
if (subtreeFlags & TransformFlags.ContainsRest) {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRest;
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRestOrSpread;
}
excludeFlags = TransformFlags.BindingPatternExcludes;
break;
@@ -3765,13 +3808,13 @@ namespace ts {
case SyntaxKind.BindingElement:
transformFlags |= TransformFlags.AssertES2015;
if ((<BindingElement>node).dotDotDotToken) {
transformFlags |= TransformFlags.ContainsRest;
transformFlags |= TransformFlags.ContainsRestOrSpread;
}
break;
case SyntaxKind.Decorator:
// This node is TypeScript syntax, and marks its container as also being TypeScript syntax.
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsDecorators;
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsTypeScriptClassSyntax;
break;
case SyntaxKind.ObjectLiteralExpression:
@@ -3788,7 +3831,7 @@ namespace ts {
transformFlags |= TransformFlags.ContainsLexicalThis;
}
if (subtreeFlags & TransformFlags.ContainsObjectSpread) {
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
// If an ObjectLiteralExpression contains a spread element, then it
// is an ES next node.
transformFlags |= TransformFlags.AssertESNext;
@@ -3799,7 +3842,7 @@ namespace ts {
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.NewExpression:
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes;
if (subtreeFlags & TransformFlags.ContainsSpread) {
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
// If the this node contains a SpreadExpression, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
+46 -3
View File
@@ -88,7 +88,7 @@ namespace ts.BuilderState {
function getReferencedFileFromImportedModuleSymbol(symbol: Symbol) {
if (symbol.declarations && symbol.declarations[0]) {
const declarationSourceFile = getSourceFileOfNode(symbol.declarations[0]);
return declarationSourceFile && declarationSourceFile.path;
return declarationSourceFile && declarationSourceFile.resolvedPath;
}
}
@@ -100,6 +100,13 @@ namespace ts.BuilderState {
return symbol && getReferencedFileFromImportedModuleSymbol(symbol);
}
/**
* Gets the path to reference file from file name, it could be resolvedPath if present otherwise path
*/
function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path {
return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName);
}
/**
* Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true
*/
@@ -123,7 +130,7 @@ namespace ts.BuilderState {
// Handle triple slash references
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
for (const referencedFile of sourceFile.referencedFiles) {
const referencedPath = toPath(referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
const referencedPath = getReferencedFileFromFileName(program, referencedFile.fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(referencedPath);
}
}
@@ -136,13 +143,44 @@ namespace ts.BuilderState {
}
const fileName = resolvedTypeReferenceDirective.resolvedFileName!; // TODO: GH#18217
const typeFilePath = toPath(fileName, sourceFileDirectory, getCanonicalFileName);
const typeFilePath = getReferencedFileFromFileName(program, fileName, sourceFileDirectory, getCanonicalFileName);
addReferencedFile(typeFilePath);
});
}
// 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>();
@@ -254,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);
+1086 -973
View File
File diff suppressed because it is too large Load Diff
+89 -30
View File
@@ -77,6 +77,14 @@ namespace ts {
shortName: "?",
type: "boolean"
},
{
name: "watch",
shortName: "w",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Watch_input_files,
},
{
name: "preserveWatchOutput",
type: "boolean",
@@ -96,13 +104,12 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation
},
{
name: "watch",
shortName: "w",
name: "traceResolution",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Watch_input_files,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Enable_tracing_of_the_name_resolution_process
},
];
@@ -366,6 +373,14 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_function_types
},
{
name: "strictBindCallApply",
type: "boolean",
strictFlag: true,
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_bind_call_and_apply_methods_on_functions
},
{
name: "strictPropertyInitialization",
type: "boolean",
@@ -581,12 +596,6 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_verbose_diagnostic_information
},
{
name: "traceResolution",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Enable_tracing_of_the_name_resolution_process
},
{
name: "resolveJsonModule",
type: "boolean",
@@ -1004,7 +1013,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++;
@@ -1284,6 +1293,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));
}
@@ -1520,7 +1532,12 @@ namespace ts {
elements: NodeArray<Expression>,
elementOption: CommandLineOption | undefined
): any[] | void {
return (returnValue ? elements.map : elements.forEach).call(elements, (element: Expression) => convertPropertyValueToJson(element, elementOption));
if (!returnValue) {
return elements.forEach(element => convertPropertyValueToJson(element, elementOption));
}
// Filter out invalid values
return filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined);
}
function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any {
@@ -1653,7 +1670,7 @@ namespace ts {
return undefined;
}
else if (optionDefinition.type === "list") {
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
return getCustomTypeMapOfCommandLineOption(optionDefinition.element);
}
else {
return (<CommandLineOptionOfCustomType>optionDefinition).type;
@@ -1717,7 +1734,7 @@ namespace ts {
case "object":
return {};
default:
return (option as CommandLineOptionOfCustomType).type.keys().next().value;
return option.type.keys().next().value;
}
}
@@ -1886,7 +1903,8 @@ namespace ts {
filesSpecs = <ReadonlyArray<string>>raw.files;
const hasReferences = hasProperty(raw, "references") && !isNullOrUndefined(raw.references);
const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0;
if (filesSpecs.length === 0 && hasZeroOrNoReferences) {
const hasExtends = hasProperty(raw, "extends");
if (filesSpecs.length === 0 && hasZeroOrNoReferences && !hasExtends) {
if (sourceFile) {
const fileName = configFileName || "tsconfig.json";
const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty;
@@ -1939,7 +1957,7 @@ namespace ts {
}
const result = matchFileNames(filesSpecs, includeSpecs, excludeSpecs, configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath, options, host, errors, extraFileExtensions, sourceFile);
if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0 && !hasProperty(raw, "references")) {
if (shouldReportNoInputFiles(result, canJsonReportNoInutFiles(raw), resolutionStack)) {
errors.push(getErrorForNoInputFiles(result.spec, configFileName));
}
@@ -1974,13 +1992,11 @@ namespace ts {
}
}
/*@internal*/
export function isErrorNoInputFiles(error: Diagnostic) {
function isErrorNoInputFiles(error: Diagnostic) {
return error.code === Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code;
}
/*@internal*/
export function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ConfigFileSpecs, configFileName: string | undefined) {
function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ConfigFileSpecs, configFileName: string | undefined) {
return createCompilerDiagnostic(
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
configFileName || "tsconfig.json",
@@ -1988,6 +2004,27 @@ namespace ts {
JSON.stringify(excludeSpecs || []));
}
function shouldReportNoInputFiles(result: ExpandResult, canJsonReportNoInutFiles: boolean, resolutionStack?: Path[]) {
return result.fileNames.length === 0 && canJsonReportNoInutFiles && (!resolutionStack || resolutionStack.length === 0);
}
/*@internal*/
export function canJsonReportNoInutFiles(raw: any) {
return !hasProperty(raw, "files") && !hasProperty(raw, "references");
}
/*@internal*/
export function updateErrorForNoInputFiles(result: ExpandResult, configFileName: string, configFileSpecs: ConfigFileSpecs, configParseDiagnostics: Diagnostic[], canJsonReportNoInutFiles: boolean) {
const existingErrors = configParseDiagnostics.length;
if (shouldReportNoInputFiles(result, canJsonReportNoInutFiles)) {
configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName));
}
else {
filterMutate(configParseDiagnostics, error => !isErrorNoInputFiles(error));
}
return existingErrors !== configParseDiagnostics.length;
}
interface ParsedTsconfig {
raw: any;
options?: CompilerOptions;
@@ -2030,7 +2067,7 @@ namespace ts {
if (ownConfig.extendedConfigPath) {
// copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
resolutionStack = resolutionStack.concat([resolvedPath]);
const extendedConfig = getExtendedConfig(sourceFile!, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors);
if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
const baseRaw = extendedConfig.raw;
const raw = ownConfig.raw;
@@ -2171,7 +2208,7 @@ namespace ts {
}
function getExtendedConfig(
sourceFile: TsConfigSourceFile,
sourceFile: TsConfigSourceFile | undefined,
extendedConfigPath: string,
host: ParseConfigHost,
basePath: string,
@@ -2180,7 +2217,7 @@ namespace ts {
): ParsedTsconfig | undefined {
const extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path));
if (sourceFile) {
(sourceFile.extendedSourceFiles || (sourceFile.extendedSourceFiles = [])).push(extendedResult.fileName);
sourceFile.extendedSourceFiles = [extendedResult.fileName];
}
if (extendedResult.parseDiagnostics.length) {
errors.push(...extendedResult.parseDiagnostics);
@@ -2190,8 +2227,8 @@ namespace ts {
const extendedDirname = getDirectoryPath(extendedConfigPath);
const extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname,
getBaseFileName(extendedConfigPath), resolutionStack, errors);
if (sourceFile) {
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles!);
if (sourceFile && extendedResult.extendedSourceFiles) {
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles);
}
if (isSuccessfulParsedTsconfig(extendedConfig)) {
@@ -2304,7 +2341,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);
}
@@ -2475,11 +2512,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.
@@ -2490,8 +2532,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.
//
@@ -2519,7 +2578,7 @@ namespace ts {
const wildcardFiles = arrayFrom(wildcardFileMap.values());
return {
fileNames: literalFiles.concat(wildcardFiles),
fileNames: literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values())),
wildcardDirectories,
spec
};
@@ -2689,7 +2748,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) => {
+2 -2
View File
@@ -220,7 +220,7 @@ namespace ts {
}
if (extendedDiagnostics) {
performance.mark("beginEmitBodyWithDetachedCommetns");
performance.mark("beginEmitBodyWithDetachedComments");
}
if (!skipTrailingComments) {
@@ -231,7 +231,7 @@ namespace ts {
}
if (extendedDiagnostics) {
performance.measure("commentTime", "beginEmitBodyWithDetachedCommetns");
performance.measure("commentTime", "beginEmitBodyWithDetachedComments");
}
}
+15 -6
View File
@@ -1,7 +1,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "3.1";
export const versionMajorMinor = "3.2";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}
@@ -842,7 +842,7 @@ namespace ts {
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer);
}
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean {
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T> | undefined, array2: ReadonlyArray<T> | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean {
if (!array1 || !array2) {
return array1 === array2;
}
@@ -852,7 +852,7 @@ namespace ts {
}
for (let i = 0; i < array1.length; i++) {
if (!equalityComparer(array1[i], array2[i])) {
if (!equalityComparer(array1[i], array2[i], i)) {
return false;
}
}
@@ -1409,9 +1409,12 @@ namespace ts {
/**
* Tests whether a value is string
*/
export function isString(text: any): text is string {
export function isString(text: unknown): text is string {
return typeof text === "string";
}
export function isNumber(x: unknown): x is number {
return typeof x === "number";
}
export function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined;
export function tryCast<T>(value: T, test: (value: T) => boolean): T | undefined;
@@ -1534,6 +1537,7 @@ namespace ts {
* Every function should be assignable to this, but this should not be assignable to every function.
*/
export type AnyFunction = (...args: never[]) => void;
export type AnyConstructor = new (...args: unknown[]) => unknown;
export namespace Debug {
export let currentAssertionLevel = AssertionLevel.None;
@@ -1598,8 +1602,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) {
@@ -2125,4 +2130,8 @@ namespace ts {
deleted(oldItems[oldIndex++]);
}
}
export function fill<T>(length: number, cb: (index: number) => T): T[] {
return new Array(length).fill(0).map((_, i) => cb(i));
}
}
+32 -4
View File
@@ -2112,6 +2112,14 @@
"category": "Error",
"code": 2585
},
"Enum type '{0}' circularly references itself.": {
"category": "Error",
"code": 2586
},
"JSDoc type '{0}' circularly references itself.": {
"category": "Error",
"code": 2587
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -2477,10 +2485,6 @@
"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
@@ -3755,6 +3759,14 @@
"category": "Message",
"code": 6213
},
"Enable strict 'bind', 'call', and 'apply' methods on functions.": {
"category": "Message",
"code": 6214
},
"Using compiler options of project reference redirect '{0}'.": {
"category": "Message",
"code": 6215
},
"Projects to reference": {
"category": "Message",
@@ -3886,6 +3898,10 @@
"category": "Message",
"code": 6501
},
"The expected type comes from the return type of this signature.": {
"category": "Message",
"code": 6502
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
@@ -4145,6 +4161,10 @@
"category": "Error",
"code": 8030
},
"You cannot rename a module via a global import.": {
"category": "Error",
"code": 8031
},
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
"category": "Error",
"code": 9002
@@ -4659,5 +4679,13 @@
"Convert all to async functions": {
"category": "Message",
"code": 95066
},
"Generate types for '{0}'": {
"category": "Message",
"code": 95067
},
"Generate types for all packages without types": {
"category": "Message",
"code": 95068
}
}
+29 -18
View File
@@ -41,20 +41,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 };
}
}
@@ -135,27 +140,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
+1 -1
View File
@@ -235,7 +235,7 @@ namespace ts {
// Modifiers
export function createModifier<T extends Modifier["kind"]>(kind: T) {
export function createModifier<T extends Modifier["kind"]>(kind: T): Token<T> {
return createToken(kind);
}
+159
View File
@@ -0,0 +1,159 @@
/* @internal */
namespace ts {
export interface InspectValueOptions {
readonly fileNameToRequire: string;
}
export const enum ValueKind { Const, Array, FunctionOrClass, Object }
export interface ValueInfoBase {
readonly name: string;
}
export type ValueInfo = ValueInfoSimple | ValueInfoArray | ValueInfoFunctionOrClass | ValueInfoObject;
export interface ValueInfoSimple extends ValueInfoBase {
readonly kind: ValueKind.Const;
readonly typeName: string;
readonly comment?: string | undefined;
}
export interface ValueInfoFunctionOrClass extends ValueInfoBase {
readonly kind: ValueKind.FunctionOrClass;
readonly source: string | number; // For a native function, this is the length.
readonly prototypeMembers: ReadonlyArray<ValueInfo>;
readonly namespaceMembers: ReadonlyArray<ValueInfo>;
}
export interface ValueInfoArray extends ValueInfoBase {
readonly kind: ValueKind.Array;
readonly inner: ValueInfo;
}
export interface ValueInfoObject extends ValueInfoBase {
readonly kind: ValueKind.Object;
readonly members: ReadonlyArray<ValueInfo>;
}
export function inspectModule(fileNameToRequire: string): ValueInfo {
return inspectValue(removeFileExtension(getBaseFileName(fileNameToRequire)), tryRequire(fileNameToRequire));
}
export function inspectValue(name: string, value: unknown): ValueInfo {
return getValueInfo(name, value, getRecurser());
}
type Recurser = <T>(obj: unknown, name: string, cbOk: () => T, cbFail: (isCircularReference: boolean, keyStack: ReadonlyArray<string>) => T) => T;
function getRecurser(): Recurser {
const seen = new Set<unknown>();
const nameStack: string[] = [];
return (obj, name, cbOk, cbFail) => {
if (seen.has(obj) || nameStack.length > 4) {
return cbFail(seen.has(obj), nameStack);
}
seen.add(obj);
nameStack.push(name);
const res = cbOk();
nameStack.pop();
seen.delete(obj);
return res;
};
}
function getValueInfo(name: string, value: unknown, recurser: Recurser): ValueInfo {
return recurser(value, name,
(): ValueInfo => {
if (typeof value === "function") return getFunctionOrClassInfo(value as AnyFunction, name, recurser);
if (typeof value === "object") {
const builtin = getBuiltinType(name, value as object, recurser);
if (builtin !== undefined) return builtin;
const entries = getEntriesOfObject(value as object);
return { kind: ValueKind.Object, name, members: flatMap(entries, ({ key, value }) => getValueInfo(key, value, recurser)) };
}
return { kind: ValueKind.Const, name, typeName: isNullOrUndefined(value) ? "any" : typeof value };
},
(isCircularReference, keyStack) => anyValue(name, ` ${isCircularReference ? "Circular reference" : "Too-deep object hierarchy"} from ${keyStack.join(".")}`));
}
function getFunctionOrClassInfo(fn: AnyFunction, name: string, recurser: Recurser): ValueInfoFunctionOrClass {
const prototypeMembers = getPrototypeMembers(fn, recurser);
const namespaceMembers = flatMap(getEntriesOfObject(fn), ({ key, value }) => getValueInfo(key, value, recurser));
const toString = cast(Function.prototype.toString.call(fn), isString);
const source = stringContains(toString, "{ [native code] }") ? getFunctionLength(fn) : toString;
return { kind: ValueKind.FunctionOrClass, name, source, namespaceMembers, prototypeMembers };
}
const builtins: () => ReadonlyMap<AnyConstructor> = memoize(() => {
const map = createMap<AnyConstructor>();
for (const { key, value } of getEntriesOfObject(global)) {
if (typeof value === "function" && typeof value.prototype === "object" && value !== Object) {
map.set(key, value as AnyConstructor);
}
}
return map;
});
function getBuiltinType(name: string, value: object, recurser: Recurser): ValueInfo | undefined {
return isArray(value)
? { name, kind: ValueKind.Array, inner: value.length && getValueInfo("element", first(value), recurser) || anyValue(name) }
: forEachEntry(builtins(), (builtin, builtinName): ValueInfo | undefined =>
value instanceof builtin ? { kind: ValueKind.Const, name, typeName: builtinName } : undefined);
}
function getPrototypeMembers(fn: AnyFunction, recurser: Recurser): ReadonlyArray<ValueInfo> {
const prototype = fn.prototype as unknown;
// tslint:disable-next-line no-unnecessary-type-assertion (TODO: update LKG and it will really be unnecessary)
return typeof prototype !== "object" || prototype === null ? emptyArray : mapDefined(getEntriesOfObject(prototype as object), ({ key, value }) =>
key === "constructor" ? undefined : getValueInfo(key, value, recurser));
}
const ignoredProperties: ReadonlySet<string> = new Set(["arguments", "caller", "constructor", "eval", "super_"]);
const reservedFunctionProperties: ReadonlySet<string> = new Set(Object.getOwnPropertyNames(noop));
interface ObjectEntry { readonly key: string; readonly value: unknown; }
function getEntriesOfObject(obj: object): ReadonlyArray<ObjectEntry> {
const seen = createMap<true>();
const entries: ObjectEntry[] = [];
let chain = obj;
while (!isNullOrUndefined(chain) && chain !== Object.prototype && chain !== Function.prototype) {
for (const key of Object.getOwnPropertyNames(chain)) {
if (!isJsPrivate(key) &&
!ignoredProperties.has(key) &&
(typeof obj !== "function" || !reservedFunctionProperties.has(key)) &&
// Don't add property from a higher prototype if it already exists in a lower one
addToSeen(seen, key)) {
const value = safeGetPropertyOfObject(chain, key);
// Don't repeat "toString" that matches signature from Object.prototype
if (!(key === "toString" && typeof value === "function" && value.length === 0)) {
entries.push({ key, value });
}
}
}
chain = Object.getPrototypeOf(chain);
}
return entries.sort((e1, e2) => compareStringsCaseSensitive(e1.key, e2.key));
}
function getFunctionLength(fn: AnyFunction): number {
return tryCast(safeGetPropertyOfObject(fn, "length"), isNumber) || 0;
}
function safeGetPropertyOfObject(obj: object, key: string): unknown {
const desc = Object.getOwnPropertyDescriptor(obj, key);
return desc && desc.value;
}
function isNullOrUndefined(value: unknown): value is null | undefined {
return value == null; // tslint:disable-line
}
function anyValue(name: string, comment?: string): ValueInfo {
return { kind: ValueKind.Const, name, typeName: "any", comment };
}
export function isJsPrivate(name: string): boolean {
return name.startsWith("_");
}
function tryRequire(fileNameToRequire: string): unknown {
try {
return require(fileNameToRequire);
}
catch {
return undefined;
}
}
}
+139 -79
View File
@@ -258,8 +258,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 +284,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 +298,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 +314,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,8 +341,16 @@ namespace ts {
if (traceEnabled) {
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
}
const result = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined);
const resolvedFile = resolvedTypeScriptOnly(result && result.value);
let result: Resolved | undefined;
if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) {
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 = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true);
}
const resolvedFile = resolvedTypeScriptOnly(result);
if (!resolvedFile && traceEnabled) {
trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName);
}
@@ -381,8 +393,13 @@ namespace ts {
// tslint:disable-next-line:no-null-keyword
const isNotNeededPackage = host.fileExists(packageJsonPath) && (readJson(packageJsonPath, host) as PackageJson).typings === null;
if (!isNotNeededPackage) {
// Return just the type directive names
result.push(getBaseFileName(normalized));
const baseFileName = getBaseFileName(normalized);
// At this stage, skip results with leading dot.
if (baseFileName.charCodeAt(0) !== CharacterCodes.dot) {
// Return just the type directive names
result.push(baseFileName);
}
}
}
}
@@ -397,7 +414,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>;
}
/**
@@ -405,7 +422,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 {
@@ -415,40 +432,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 {
@@ -530,13 +585,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) {
@@ -560,10 +621,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}`);
@@ -573,7 +634,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);
}
}
}
@@ -779,19 +840,28 @@ namespace ts {
*/
/* @internal */
export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string {
const { resolvedModule, failedLookupLocations } =
nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host);
if (!resolvedModule) {
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`);
}
return resolvedModule.resolvedFileName;
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false);
/* @internal */
export function tryResolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string | undefined {
const { resolvedModule } = tryResolveJSModuleWorker(moduleName, initialDir, host);
return resolvedModule && resolvedModule.resolvedFileName;
}
function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, jsOnly: boolean): ResolvedModuleWithFailedLookupLocations {
function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*redirectedReference*/ undefined, /*jsOnly*/ true);
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, redirectedReference, /*jsOnly*/ false);
}
function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, jsOnly: boolean): ResolvedModuleWithFailedLookupLocations {
const traceEnabled = isTraceEnabled(compilerOptions, host);
const failedLookupLocations: string[] = [];
@@ -812,14 +882,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;
@@ -889,6 +959,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`.
@@ -1022,15 +1096,6 @@ namespace ts {
return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths));
}
function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined {
const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, versionPaths, extensions, candidate, state);
if (fromPackageJson) {
return fromPackageJson;
}
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), !directoryExists, state);
}
interface PackageJsonInfo {
packageJsonContent: PackageJsonPathFields | undefined;
packageId: PackageId | undefined;
@@ -1090,22 +1155,12 @@ namespace ts {
}
}
function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, versionPaths: VersionPaths | undefined, extensions: Extensions, candidate: string, state: ModuleResolutionState): PathAndExtension | undefined {
let file = extensions !== Extensions.JavaScript && extensions !== Extensions.Json
? readPackageJsonTypesFields(jsonContent, candidate, state)
: readPackageJsonMainField(jsonContent, candidate, state);
if (!file) {
if (extensions === Extensions.TypeScript) {
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
file = readPackageJsonMainField(jsonContent, candidate, state);
if (!file) {
return undefined;
}
}
else {
return undefined;
}
}
(extensions === Extensions.TypeScript ? readPackageJsonMainField(jsonContent, candidate, state) : undefined)
: readPackageJsonMainField(jsonContent, candidate, state));
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => {
const fromFile = tryFile(candidate, onlyRecordFailures, state);
@@ -1125,21 +1180,26 @@ namespace ts {
return nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false);
};
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host);
const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined;
const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host);
const indexPath = combinePaths(candidate, "index");
if (versionPaths && containsPath(candidate, file)) {
const moduleName = getRelativePathFromDirectory(candidate, file, /*ignoreCase*/ false);
if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) {
const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false);
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, moduleName);
}
const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailures, state);
const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, state);
if (result) {
return removeIgnoredPackageId(result.value);
}
}
// It won't have a `packageId` set, because we disabled `considerPackageJson`.
return removeIgnoredPackageId(loader(extensions, file, onlyRecordFailures, state));
const packageFileResult = packageFile && removeIgnoredPackageId(loader(extensions, packageFile, onlyRecordFailuresForPackageFile!, state));
if (packageFileResult) return packageFileResult;
return loadModuleFromFile(extensions, indexPath, onlyRecordFailuresForIndex, state);
}
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
@@ -1171,17 +1231,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);
@@ -1349,7 +1409,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 };
@@ -1366,7 +1426,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;
}
}
+34 -32
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:
@@ -6308,7 +6316,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);
@@ -6441,13 +6449,6 @@ namespace ts {
indent += asterisk.length;
}
break;
case SyntaxKind.Identifier:
// Anything else is doc comment text. We just save it. Because it
// wasn't a tag, we can no longer parse a tag on this line until we hit the next
// line break.
pushComment(scanner.getTokenText());
state = JSDocState.SavingComments;
break;
case SyntaxKind.WhitespaceTrivia:
// only collect whitespace if we're already saving comments or have just crossed the comment indent margin
const whitespace = scanner.getTokenText();
@@ -6462,7 +6463,9 @@ namespace ts {
case SyntaxKind.EndOfFileToken:
break loop;
default:
// anything other than whitespace or asterisk at the beginning of the line starts the comment text
// Anything else is doc comment text. We just save it. Because it
// wasn't a tag, we can no longer parse a tag on this line until we hit the next
// line break.
state = JSDocState.SavingComments;
pushComment(scanner.getTokenText());
break;
@@ -6517,7 +6520,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
@@ -6532,7 +6535,7 @@ namespace ts {
else if (token() === SyntaxKind.AsteriskToken) {
precedingLineBreak = false;
}
next();
nextJSDocToken();
}
}
@@ -6542,9 +6545,8 @@ namespace ts {
atToken.end = scanner.getTextPos();
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) {
@@ -6688,7 +6690,7 @@ namespace ts {
}
function tryParseTypeExpression(): JSDocTypeExpression | undefined {
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
}
@@ -6728,7 +6730,7 @@ namespace ts {
function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag {
let typeExpression = tryParseTypeExpression();
let isNameFirst = !typeExpression;
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
skipWhitespace();
@@ -6862,7 +6864,7 @@ namespace ts {
function parseTypedefTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocTypedefTag {
const typeExpression = tryParseTypeExpression();
skipWhitespaceOrAsterisk(nextJSDocToken);
skipWhitespaceOrAsterisk();
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
typedefTag.atToken = atToken;
@@ -7115,7 +7117,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);
}
@@ -7126,7 +7128,7 @@ namespace ts {
result.escapedText = escapeLeadingUnderscores(scanner.getTokenText());
finishNode(result, end);
next();
nextJSDocToken();
return result;
}
}
@@ -7725,7 +7727,7 @@ namespace ts {
/*@internal*/
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const pragmas: PragmaPsuedoMapEntry[] = [];
const pragmas: PragmaPseudoMapEntry[] = [];
// Keep scanning all the leading trivia in the file until we get to something that
// isn't trivia. Any single line comment will be analyzed to see if it is a
@@ -7780,7 +7782,7 @@ namespace ts {
const referencedFiles = context.referencedFiles;
const typeReferenceDirectives = context.typeReferenceDirectives;
const libReferenceDirectives = context.libReferenceDirectives;
forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => {
forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => {
// TODO: GH#18217
if (arg!.arguments["no-default-lib"]) {
context.hasNoDefaultLib = true;
@@ -7803,7 +7805,7 @@ namespace ts {
case "amd-dependency": {
context.amdDependencies = map(
toArray(entryOrList),
(x: PragmaPsuedoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
break;
}
case "amd-module": {
@@ -7813,11 +7815,11 @@ namespace ts {
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
}
context.moduleName = (entry as PragmaPsuedoMap["amd-module"])!.arguments.name;
context.moduleName = (entry as PragmaPseudoMap["amd-module"])!.arguments.name;
}
}
else {
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"])!.arguments.name;
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"])!.arguments.name;
}
break;
}
@@ -7853,10 +7855,10 @@ namespace ts {
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
function extractPragmas(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, text: string) {
function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) {
const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
if (tripleSlash) {
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const name = tripleSlash[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) {
return;
@@ -7883,10 +7885,10 @@ namespace ts {
}
}
}
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
}
else {
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPseudoMapEntry);
}
return;
}
@@ -7905,9 +7907,9 @@ namespace ts {
}
}
function addPragmaForMatch(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
if (!match) return;
const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind! & kind)) {
return;
@@ -7915,7 +7917,7 @@ namespace ts {
const args = match[2]; // Split on spaces and match up positionally with definition
const argument = getNamedPragmaArguments(pragma, args);
if (argument === "fail") return; // Missing required argument, fail to parse it
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
return;
}
+320 -165
View File
@@ -207,7 +207,7 @@ namespace ts {
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (program.getCompilerOptions().declaration) {
if (getEmitDeclarations(program.getCompilerOptions())) {
addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, 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,8 +454,10 @@ namespace ts {
return false;
}
let seenResolvedRefs: ResolvedProjectReference[] | undefined;
// If project references dont match
if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences)) {
if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) {
return false;
}
@@ -483,10 +485,46 @@ namespace ts {
return true;
function sourceFileNotUptoDate(sourceFile: SourceFile): boolean {
return sourceFile.version !== getSourceVersion(sourceFile.path) ||
function sourceFileNotUptoDate(sourceFile: SourceFile) {
return !sourceFileVersionUptoDate(sourceFile) ||
hasInvalidatedResolution(sourceFile.path);
}
function sourceFileVersionUptoDate(sourceFile: SourceFile) {
return sourceFile.version === getSourceVersion(sourceFile.resolvedPath);
}
function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) {
if (!projectReferenceIsEqualTo(oldRef, newRef)) {
return false;
}
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
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));
}
}
export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray<Diagnostic> {
@@ -592,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;
@@ -615,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[];
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.
@@ -644,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;
const projectReferenceRedirects: Map<string> = createMap();
let resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined;
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
@@ -654,15 +691,16 @@ namespace ts {
processingOtherFiles = [];
if (projectReferences) {
for (const ref of projectReferences) {
const parsedRef = parseProjectReferenceConfigFile(ref);
resolvedProjectReferences!.push(parsedRef);
if (!resolvedProjectReferences) {
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
}
for (const parsedRef of resolvedProjectReferences) {
if (parsedRef) {
if (parsedRef.commandLine.options.outFile) {
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
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, projectReferenceRedirects);
}
}
}
@@ -713,10 +751,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
@@ -758,7 +804,11 @@ namespace ts {
getConfigFileParsingDiagnostics,
getResolvedModuleWithFailedLookupLocationsFromCache,
getProjectReferences,
getResolvedProjectReferences
getResolvedProjectReferences,
getProjectReferenceRedirect,
getResolvedProjectReferenceToRedirect,
getResolvedProjectReferenceByPath,
forEachResolvedProjectReference
};
verifyCompilerOptions();
@@ -797,9 +847,9 @@ namespace ts {
// If a rootDir is specified use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
}
else if (options.composite) {
else if (options.composite && options.configFilePath) {
// Project compilations never infer their root from the input source paths
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath!)); // TODO: GH#18217
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory);
}
else {
@@ -841,7 +891,7 @@ namespace ts {
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);
@@ -921,7 +971,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
@@ -981,6 +1031,30 @@ namespace ts {
}
}
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;
@@ -1006,43 +1080,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;
@@ -1059,7 +1105,7 @@ namespace ts {
for (const oldSourceFile of oldSourceFiles) {
let newSourceFile = host.getSourceFileByPath
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile)
: host.getSourceFile(oldSourceFile.fileName, options.target!, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217
if (!newSourceFile) {
@@ -1090,8 +1136,11 @@ namespace ts {
fileChanged = newSourceFile !== oldSourceFile;
}
// Since the project references havent changed, its right to set originalFileName and resolvedPath here
newSourceFile.path = oldSourceFile.path;
filePaths.push(newSourceFile.path);
newSourceFile.originalFileName = oldSourceFile.originalFileName;
newSourceFile.resolvedPath = oldSourceFile.resolvedPath;
newSourceFile.fileName = oldSourceFile.fileName;
const packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path);
if (packageName !== undefined) {
@@ -1167,7 +1216,7 @@ namespace ts {
modifiedFilePaths = modifiedSourceFiles.map(f => f.newFile.path);
// try to verify results of module resolution
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.originalFileName, currentDirectory);
if (resolveModuleNamesWorker) {
const moduleNames = getModuleNames(newSourceFile);
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
@@ -1185,7 +1234,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) {
@@ -1209,11 +1258,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);
}
}
@@ -1224,7 +1274,6 @@ namespace ts {
fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile.newFile);
}
resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives();
resolvedProjectReferences = oldProgram.getResolvedProjectReferences();
sourceFileToPackageName = oldProgram.sourceFileToPackageName;
redirectTargetsMap = oldProgram.redirectTargetsMap;
@@ -1280,12 +1329,13 @@ namespace ts {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine;
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
const out = resolvedRefOpts.options.outFile || resolvedRefOpts.options.out;
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
if (!resolvedRefOpts.options.outFile) continue;
if (!out) continue;
const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts");
const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`;
const jsMapPath = resolvedRefOpts.options.outFile + ".map"; // TODO: try to read sourceMappingUrl comment from the file
const dtsFilename = changeExtension(out, ".d.ts");
const js = host.readFile(out) || `/* Input file ${out} was missing */\r\n`;
const jsMapPath = out + ".map"; // TODO: try to read sourceMappingUrl comment from the file
const jsMap = host.readFile(jsMapPath);
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
const dtsMapPath = dtsFilename + ".map";
@@ -1360,7 +1410,7 @@ namespace ts {
...program.getSemanticDiagnostics(sourceFile, cancellationToken)
];
if (diagnostics.length === 0 && program.getCompilerOptions().declaration) {
if (diagnostics.length === 0 && getEmitDeclarations(program.getCompilerOptions())) {
declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken);
}
@@ -1778,11 +1828,22 @@ namespace ts {
fileProcessingDiagnostics.getGlobalDiagnostics(),
concatenate(
programDiagnostics.getGlobalDiagnostics(),
options.configFile ? programDiagnostics.getDiagnostics(options.configFile.fileName) : []
getOptionsDiagnosticsOfConfigFile()
)
));
}
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(): Diagnostic[] {
return sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice());
}
@@ -1933,7 +1994,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;
}
@@ -1992,11 +2053,14 @@ namespace ts {
}
}
function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path): SourceFile {
function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string): SourceFile {
const redirect: SourceFile = Object.create(redirectTarget);
redirect.fileName = fileName;
redirect.path = path;
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; },
@@ -2012,6 +2076,7 @@ namespace ts {
// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
const originalFileName = fileName;
if (filesByName.has(path)) {
const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
@@ -2053,7 +2118,7 @@ namespace ts {
return file;
}
let redirectedPath: string | undefined;
let redirectedPath: Path | undefined;
if (refFile) {
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
@@ -2085,9 +2150,9 @@ namespace ts {
if (fileFromPackageId) {
// Some other SourceFile already exists with this package name and version.
// Instead of creating a duplicate, just redirect to the existing one.
const dupFile = createRedirectSourceFile(fileFromPackageId, file!, fileName, path); // TODO: GH#18217
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;
@@ -2098,16 +2163,13 @@ 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);
file.path = path;
file.resolvedPath = toPath(fileName);
file.originalFileName = originalFileName;
if (host.useCaseSensitiveFileNames()) {
const pathLowerCase = path.toLowerCase();
@@ -2144,26 +2206,112 @@ 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 {
const path = toPath(fileName);
// Ignore dts or any of the non ts files
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
const normalized = getNormalizedAbsolutePath(fileName, path);
let result: string | undefined;
projectReferenceRedirects.forEach((v, k) => {
if (result !== undefined) {
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 (!referencedProject ||
toPath(options.configFilePath!) === referenceProjectPath ||
!contains(referencedProject.commandLine.fileNames, fileName, isSameFile)) {
return undefined;
}
if (normalized.indexOf(k) === 0) {
result = changeExtension(fileName.replace(k, v), ".d.ts");
}
return referencedProject;
});
return result;
}
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.fileName);
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end);
});
}
@@ -2175,7 +2323,7 @@ namespace ts {
return;
}
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName, getResolvedProjectReferenceToRedirect(file.originalFileName));
for (let i = 0; i < typeDirectives.length; i++) {
const ref = file.typeReferenceDirectives[i];
@@ -2197,6 +2345,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
@@ -2225,6 +2375,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
@@ -2271,7 +2423,7 @@ namespace ts {
// 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.fileName, currentDirectory), file, oldProgramState);
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file, oldProgramState);
Debug.assert(resolutions.length === moduleNames.length);
for (let i = 0; i < moduleNames.length; i++) {
const resolution = resolutions[i];
@@ -2348,29 +2500,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, target: Map<string>) {
const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath!)); // TODO: GH#18217
target.set(rootDir, getDeclarationOutputDirectory(referencedProject));
}
function getDeclarationOutputDirectory(proj: ParsedCommandLine) {
return proj.options.declarationDir ||
proj.options.outDir ||
getDirectoryPath(proj.options.configFilePath!); // TODO: GH#18217
const resolvedRef: ResolvedProjectReference = { commandLine, sourceFile };
projectReferenceRedirects.set(sourceFilePath, resolvedRef);
if (commandLine.projectReferences) {
resolvedRef.references = commandLine.projectReferences.map(parseProjectReferenceConfigFile);
}
return resolvedRef;
}
function verifyCompilerOptions() {
@@ -2379,8 +2539,8 @@ namespace ts {
}
if (options.isolatedModules) {
if (options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules");
if (getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, getEmitDeclarationOptionName(options), "isolatedModules");
}
if (options.noEmitOnError) {
@@ -2415,29 +2575,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) {
if (resolvedRefOpts.outFile) {
if (!host.fileExists(resolvedRefOpts.outFile)) {
createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, resolvedRefOpts.outFile, 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) {
@@ -2503,8 +2641,8 @@ namespace ts {
}
if (options.declarationDir) {
if (!options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration");
if (!getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationDir", "declaration", "composite");
}
if (options.out || options.outFile) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile");
@@ -2512,7 +2650,7 @@ namespace ts {
}
if (options.declarationMap && !getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationMap", "declaration");
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationMap", "declaration", "composite");
}
if (options.lib && options.noLib) {
@@ -2545,7 +2683,7 @@ namespace ts {
}
// Cannot specify module gen that isn't amd or system with --out
if (outFile) {
if (outFile && !options.emitDeclarationOnly) {
if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) {
createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module");
}
@@ -2580,8 +2718,8 @@ namespace ts {
}
}
if (!options.noEmit && options.allowJs && options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration");
if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", getEmitDeclarationOptionName(options));
}
if (options.checkJs && !options.allowJs) {
@@ -2589,8 +2727,8 @@ namespace ts {
}
if (options.emitDeclarationOnly) {
if (!options.declaration) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDeclarationOnly", "declaration");
if (!getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite");
}
if (options.noEmit) {
@@ -2655,6 +2793,32 @@ 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) {
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();
@@ -2711,10 +2875,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));
@@ -2731,22 +2896,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
@@ -2821,7 +2970,10 @@ namespace ts {
export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost {
return {
fileExists: f => host.fileExists(f),
readDirectory: (root, extensions, includes, depth?) => host.readDirectory ? host.readDirectory(root, extensions, includes, depth) : [],
readDirectory(root, extensions, excludes, includes, depth) {
Debug.assertDefined(host.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
return host.readDirectory!(root, extensions, excludes, includes, depth);
},
readFile: f => host.readFile(f),
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
getCurrentDirectory: () => host.getCurrentDirectory(),
@@ -2845,6 +2997,9 @@ namespace ts {
return resolveConfigFileProjectName(passedInRef.path);
}
function getEmitDeclarationOptionName(options: CompilerOptions) {
return options.declaration ? "declaration" : "composite";
}
/* @internal */
/**
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
+46 -19
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[];
getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): CachedResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirective[];
invalidateResolutionOfFile(filePath: Path): void;
removeResolutionsOfFile(filePath: Path): void;
removeResolutionsFromProjectReferenceRedirects(filePath: Path): void;
setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: Map<ReadonlyArray<string>>): void;
createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution;
@@ -90,17 +91,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 +129,7 @@ namespace ts {
resolveModuleNames,
getResolvedModuleWithFailedLookupLocationsFromCache,
resolveTypeReferenceDirectives,
removeResolutionsFromProjectReferenceRedirects,
removeResolutionsOfFile,
invalidateResolutionOfFile,
setFilesWithInvalidatedNonRelativeUnresolvedImports,
@@ -199,7 +201,7 @@ namespace ts {
function clearPerDirectoryResolutions() {
perDirectoryResolvedModuleNames.clear();
nonRelaticeModuleNameCache.clear();
nonRelativeModuleNameCache.clear();
perDirectoryResolvedTypeReferenceDirectives.clear();
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions);
nonRelativeExternalModuleResolutions.clear();
@@ -217,8 +219,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;
@@ -242,9 +244,10 @@ namespace ts {
function resolveNamesWithLocalCache<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
names: 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[] {
@@ -252,6 +255,7 @@ namespace ts {
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();
@@ -260,12 +264,20 @@ namespace ts {
const resolvedModules: R[] = [];
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))) {
const existingResolution = resolution;
@@ -274,7 +286,7 @@ namespace ts {
resolution = resolutionInDirectory;
}
else {
resolution = loader(name, containingFile, compilerOptions, resolutionHost);
resolution = loader(name, containingFile, compilerOptions, resolutionHost, redirectedReference);
perDirectoryResolution.set(name, resolution);
}
resolutionsInFile.set(name, resolution);
@@ -323,18 +335,18 @@ namespace ts {
}
}
function resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
function resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirective[] {
return resolveNamesWithLocalCache<CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolvedTypeReferenceDirective>(
typeDirectiveNames, containingFile,
typeDirectiveNames, containingFile, redirectedReference,
resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives,
resolveTypeReferenceDirective, getResolvedTypeReferenceDirective,
/*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[] {
return resolveNamesWithLocalCache<CachedResolvedModuleWithFailedLookupLocations, ResolvedModuleFull>(
moduleNames, containingFile,
moduleNames, containingFile, redirectedReference,
resolvedModuleNames, perDirectoryResolvedModuleNames,
resolveModuleName, getResolvedModule,
reusedNames, logChangesWhenResolvingModule
@@ -398,7 +410,8 @@ namespace ts {
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch {
if (isInDirectoryPath(rootPath, failedLookupLocationPath)) {
failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? failedLookupLocation : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory());
// Ensure failed look up is normalized path
failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory());
Debug.assert(failedLookupLocation.length === failedLookupLocationPath.length, `FailedLookup: ${failedLookupLocation} failedLookupLocationPath: ${failedLookupLocationPath}`); // tslint:disable-line
const subDirectoryInRoot = failedLookupLocationPath.indexOf(directorySeparator, rootPath.length + 1);
if (subDirectoryInRoot !== -1) {
@@ -419,7 +432,7 @@ namespace ts {
function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: Path) {
// 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);
}
@@ -593,6 +606,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);
+86 -80
View File
@@ -60,81 +60,87 @@ 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,
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,
@@ -1288,15 +1294,15 @@ 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;
}
}
}
@@ -2016,7 +2022,7 @@ namespace ts {
pos++;
}
tokenValue = text.substring(tokenPos, pos);
return token = SyntaxKind.Identifier;
return token = getIdentifierToken();
}
else {
return token = SyntaxKind.Unknown;
+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", "");
+1 -1
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) {
@@ -434,7 +434,7 @@ namespace ts {
// Heritage clause is written by user so it can always be named
if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
// Class or Interface implemented/extended is inaccessible
diagnosticMessage = (node as ExpressionWithTypeArguments).parent.token === SyntaxKind.ImplementsKeyword ?
diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ?
Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
}
@@ -446,7 +446,7 @@ namespace ts {
return {
diagnosticMessage,
errorNode: node,
typeName: getNameOfDeclaration((node as ExpressionWithTypeArguments).parent.parent)
typeName: getNameOfDeclaration(node.parent.parent as Declaration)
};
}
@@ -466,4 +466,4 @@ namespace ts {
};
}
}
}
}
+3 -3
View File
@@ -307,8 +307,8 @@ namespace ts {
if (!getRestIndicatorOfBindingOrAssignmentElement(element)) {
const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!;
if (flattenContext.level >= FlattenLevel.ObjectRest
&& !(element.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
&& !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRest | TransformFlags.ContainsObjectRest))
&& !(element.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread))
&& !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread))
&& !isComputedPropertyName(propertyName)) {
bindingElements = append(bindingElements, element);
}
@@ -384,7 +384,7 @@ namespace ts {
if (flattenContext.level >= FlattenLevel.ObjectRest) {
// If an array pattern contains an ObjectRest, we must cache the result so that we
// can perform the ObjectRest destructuring in a different declaration
if (element.transformFlags & TransformFlags.ContainsObjectRest) {
if (element.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
if (flattenContext.hoistTempVariables) {
flattenContext.context.hoistVariableDeclaration(temp);
+458 -161
View File
@@ -46,10 +46,16 @@ namespace ts {
* so nobody can observe this new value.
*/
interface LoopOutParameter {
flags: LoopOutParameterFlags;
originalName: Identifier;
outParamName: Identifier;
}
const enum LoopOutParameterFlags {
Body = 1 << 0, // Modified in the body of the iteration statement
Initializer = 1 << 1, // Set in the initializer of a ForStatement
}
const enum CopyDirection {
ToOriginal,
ToOutParameter
@@ -129,10 +135,14 @@ namespace ts {
*/
hoistedLocalVariables?: Identifier[];
conditionVariable?: Identifier;
loopParameters: ParameterDeclaration[];
/**
* List of loop out parameters - detailed descripion can be found in the comment to LoopOutParameter
*/
loopOutParameters?: LoopOutParameter[];
loopOutParameters: LoopOutParameter[];
}
const enum SuperCaptureResult {
@@ -347,7 +357,7 @@ namespace ts {
return (node.transformFlags & TransformFlags.ContainsES2015) !== 0
|| convertedLoopState !== undefined
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block)))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatement(node))
|| (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0;
}
@@ -646,8 +656,8 @@ namespace ts {
}
}
let returnExpression: Expression = createLiteral(labelMarker);
if (convertedLoopState.loopOutParameters!.length) {
const outParams = convertedLoopState.loopOutParameters!;
if (convertedLoopState.loopOutParameters.length) {
const outParams = convertedLoopState.loopOutParameters;
let expr: Expression | undefined;
for (let i = 0; i < outParams.length; i++) {
const copyExpr = copyOutParameter(outParams[i], CopyDirection.ToOutParameter);
@@ -2610,7 +2620,40 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
function shouldConvertIterationStatementBody(node: IterationStatement): boolean {
interface ForStatementWithConvertibleInitializer extends ForStatement {
initializer: VariableDeclarationList;
}
interface ForStatementWithConvertibleCondition extends ForStatement {
condition: Expression;
}
interface ForStatementWithConvertibleIncrementor extends ForStatement {
incrementor: Expression;
}
function shouldConvertPartOfIterationStatement(node: Node) {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsCapturedBlockScopeBinding) !== 0;
}
function shouldConvertInitializerOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleInitializer {
return isForStatement(node) && !!node.initializer && shouldConvertPartOfIterationStatement(node.initializer);
}
function shouldConvertConditionOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleCondition {
return isForStatement(node) && !!node.condition && shouldConvertPartOfIterationStatement(node.condition);
}
function shouldConvertIncrementorOfForStatement(node: IterationStatement): node is ForStatementWithConvertibleIncrementor {
return isForStatement(node) && !!node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor);
}
function shouldConvertIterationStatement(node: IterationStatement) {
return shouldConvertBodyOfIterationStatement(node)
|| shouldConvertInitializerOfForStatement(node);
}
function shouldConvertBodyOfIterationStatement(node: IterationStatement): boolean {
return (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LoopWithCapturedBlockScopedBinding) !== 0;
}
@@ -2639,7 +2682,7 @@ namespace ts {
}
function convertIterationStatementBodyIfNecessary(node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convert?: LoopConverter): VisitResult<Statement> {
if (!shouldConvertIterationStatementBody(node)) {
if (!shouldConvertIterationStatement(node)) {
let saveAllowedNonLabeledJumps: Jump | undefined;
if (convertedLoopState) {
// we get here if we are trying to emit normal loop loop inside converted loop
@@ -2658,7 +2701,102 @@ namespace ts {
return result;
}
const functionName = createUniqueName("_loop");
const currentState = createConvertedLoopState(node);
const statements: Statement[] = [];
const outerConvertedLoopState = convertedLoopState;
convertedLoopState = currentState;
const initializerFunction = shouldConvertInitializerOfForStatement(node) ? createFunctionForInitializerOfForStatement(node, currentState) : undefined;
const bodyFunction = shouldConvertBodyOfIterationStatement(node) ? createFunctionForBodyOfIterationStatement(node, currentState, outerConvertedLoopState) : undefined;
convertedLoopState = outerConvertedLoopState;
if (initializerFunction) statements.push(initializerFunction.functionDeclaration);
if (bodyFunction) statements.push(bodyFunction.functionDeclaration);
addExtraDeclarationsForConvertedLoop(statements, currentState, outerConvertedLoopState);
if (initializerFunction) {
statements.push(generateCallToConvertedLoopInitializer(initializerFunction.functionName, initializerFunction.containsYield));
}
let loop: Statement;
if (bodyFunction) {
if (convert) {
loop = convert(node, outermostLabeledStatement, bodyFunction.part);
}
else {
const clone = convertIterationStatementCore(node, initializerFunction, createBlock(bodyFunction.part, /*multiLine*/ true));
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
}
else {
const clone = convertIterationStatementCore(node, initializerFunction, visitNode(node.statement, visitor, isStatement, liftToBlock));
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
statements.push(loop);
return statements;
}
function convertIterationStatementCore(node: IterationStatement, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, convertedLoopBody: Statement) {
switch (node.kind) {
case SyntaxKind.ForStatement: return convertForStatement(node as ForStatement, initializerFunction, convertedLoopBody);
case SyntaxKind.ForInStatement: return convertForInStatement(node as ForInStatement, convertedLoopBody);
case SyntaxKind.ForOfStatement: return convertForOfStatement(node as ForOfStatement, convertedLoopBody);
case SyntaxKind.DoStatement: return convertDoStatement(node as DoStatement, convertedLoopBody);
case SyntaxKind.WhileStatement: return convertWhileStatement(node as WhileStatement, convertedLoopBody);
default: return Debug.failBadSyntaxKind(node, "IterationStatement expected");
}
}
function convertForStatement(node: ForStatement, initializerFunction: IterationStatementPartFunction<VariableDeclarationList> | undefined, convertedLoopBody: Statement) {
const shouldConvertCondition = node.condition && shouldConvertPartOfIterationStatement(node.condition);
const shouldConvertIncrementor = shouldConvertCondition || node.incrementor && shouldConvertPartOfIterationStatement(node.incrementor);
return updateFor(
node,
visitNode(initializerFunction ? initializerFunction.part : node.initializer, visitor, isForInitializer),
visitNode(shouldConvertCondition ? undefined : node.condition, visitor, isExpression),
visitNode(shouldConvertIncrementor ? undefined : node.incrementor, visitor, isExpression),
convertedLoopBody
);
}
function convertForOfStatement(node: ForOfStatement, convertedLoopBody: Statement) {
return updateForOf(
node,
/*awaitModifier*/ undefined,
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function convertForInStatement(node: ForInStatement, convertedLoopBody: Statement) {
return updateForIn(
node,
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function convertDoStatement(node: DoStatement, convertedLoopBody: Statement) {
return updateDo(
node,
convertedLoopBody,
visitNode(node.expression, visitor, isExpression));
}
function convertWhileStatement(node: WhileStatement, convertedLoopBody: Statement) {
return updateWhile(
node,
visitNode(node.expression, visitor, isExpression),
convertedLoopBody);
}
function createConvertedLoopState(node: IterationStatement) {
let loopInitializer: VariableDeclarationList | undefined;
switch (node.kind) {
case SyntaxKind.ForStatement:
@@ -2670,74 +2808,311 @@ namespace ts {
}
break;
}
// variables that will be passed to the loop as parameters
const loopParameters: ParameterDeclaration[] = [];
// variables declared in the loop initializer that will be changed inside the loop
const loopOutParameters: LoopOutParameter[] = [];
if (loopInitializer && (getCombinedNodeFlags(loopInitializer) & NodeFlags.BlockScoped)) {
const hasCapturedBindingsInForInitializer = shouldConvertInitializerOfForStatement(node);
for (const decl of loopInitializer.declarations) {
processLoopVariableDeclaration(decl, loopParameters, loopOutParameters);
processLoopVariableDeclaration(node, decl, loopParameters, loopOutParameters, hasCapturedBindingsInForInitializer);
}
}
const outerConvertedLoopState = convertedLoopState;
convertedLoopState = { loopOutParameters };
if (outerConvertedLoopState) {
const currentState: ConvertedLoopState = { loopParameters, loopOutParameters };
if (convertedLoopState) {
// convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop.
// if outer converted loop has already accumulated some state - pass it through
if (outerConvertedLoopState.argumentsName) {
if (convertedLoopState.argumentsName) {
// outer loop has already used 'arguments' so we've already have some name to alias it
// use the same name in all nested loops
convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName;
currentState.argumentsName = convertedLoopState.argumentsName;
}
if (outerConvertedLoopState.thisName) {
if (convertedLoopState.thisName) {
// outer loop has already used 'this' so we've already have some name to alias it
// use the same name in all nested loops
convertedLoopState.thisName = outerConvertedLoopState.thisName;
currentState.thisName = convertedLoopState.thisName;
}
if (outerConvertedLoopState.hoistedLocalVariables) {
if (convertedLoopState.hoistedLocalVariables) {
// we've already collected some non-block scoped variable declarations in enclosing loop
// use the same storage in nested loop
convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables;
currentState.hoistedLocalVariables = convertedLoopState.hoistedLocalVariables;
}
}
return currentState;
}
function addExtraDeclarationsForConvertedLoop(statements: Statement[], state: ConvertedLoopState, outerState: ConvertedLoopState | undefined) {
let extraVariableDeclarations: VariableDeclaration[] | undefined;
// propagate state from the inner loop to the outer loop if necessary
if (state.argumentsName) {
// if alias for arguments is set
if (outerState) {
// pass it to outer converted loop
outerState.argumentsName = state.argumentsName;
}
else {
// this is top level converted loop and we need to create an alias for 'arguments' object
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
state.argumentsName,
/*type*/ undefined,
createIdentifier("arguments")
)
);
}
}
if (state.thisName) {
// if alias for this is set
if (outerState) {
// pass it to outer converted loop
outerState.thisName = state.thisName;
}
else {
// this is top level converted loop so we need to create an alias for 'this' here
// NOTE:
// if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set.
// If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'.
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
state.thisName,
/*type*/ undefined,
createIdentifier("this")
)
);
}
}
if (state.hoistedLocalVariables) {
// if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later
if (outerState) {
// pass them to outer converted loop
outerState.hoistedLocalVariables = state.hoistedLocalVariables;
}
else {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
// hoist collected variable declarations
for (const identifier of state.hoistedLocalVariables) {
extraVariableDeclarations.push(createVariableDeclaration(identifier));
}
}
}
// add extra variables to hold out parameters if necessary
if (state.loopOutParameters.length) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
for (const outParam of state.loopOutParameters) {
extraVariableDeclarations.push(createVariableDeclaration(outParam.outParamName));
}
}
if (state.conditionVariable) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
extraVariableDeclarations.push(createVariableDeclaration(state.conditionVariable, /*type*/ undefined, createFalse()));
}
// create variable statement to hold all introduced variable declarations
if (extraVariableDeclarations) {
statements.push(createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(extraVariableDeclarations)
));
}
}
interface IterationStatementPartFunction<T> {
functionName: Identifier;
functionDeclaration: Statement;
containsYield: boolean;
part: T;
}
function createOutVariable(p: LoopOutParameter) {
return createVariableDeclaration(p.originalName, /*type*/ undefined, p.outParamName);
}
/**
* Creates a `_loop_init` function for a `ForStatement` with a block-scoped initializer
* that is captured in a closure inside of the initializer. The `_loop_init` function is
* used to preserve the per-iteration environment semantics of
* [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation).
*/
function createFunctionForInitializerOfForStatement(node: ForStatementWithConvertibleInitializer, currentState: ConvertedLoopState): IterationStatementPartFunction<VariableDeclarationList> {
const functionName = createUniqueName("_loop_init");
const containsYield = (node.initializer.transformFlags & TransformFlags.ContainsYield) !== 0;
let emitFlags = EmitFlags.None;
if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis;
if (containsYield && hierarchyFacts & HierarchyFacts.AsyncFunctionBody) emitFlags |= EmitFlags.AsyncFunctionBody;
const statements: Statement[] = [];
statements.push(createVariableStatement(/*modifiers*/ undefined, node.initializer));
copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Initializer, CopyDirection.ToOutParameter, statements);
// This transforms the following ES2015 syntax:
//
// for (let i = (setImmediate(() => console.log(i)), 0); i < 2; i++) {
// // loop body
// }
//
// Into the following ES5 syntax:
//
// var _loop_init_1 = function () {
// var i = (setImmediate(() => console.log(i)), 0);
// out_i_1 = i;
// };
// var out_i_1;
// _loop_init_1();
// for (var i = out_i_1; i < 2; i++) {
// // loop body
// }
//
// Which prevents mutations to `i` in the per-iteration environment of the body
// from affecting the initial value for `i` outside of the per-iteration environment.
const functionDeclaration = createVariableStatement(
/*modifiers*/ undefined,
setEmitFlags(
createVariableDeclarationList([
createVariableDeclaration(
functionName,
/*type*/ undefined,
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ undefined,
/*type*/ undefined,
visitNode(
createBlock(statements, /*multiLine*/ true),
visitor,
isBlock
)
),
emitFlags
)
)
]),
EmitFlags.NoHoisting
)
);
const part = createVariableDeclarationList(map(currentState.loopOutParameters, createOutVariable));
return { functionName, containsYield, functionDeclaration, part };
}
/**
* Creates a `_loop` function for an `IterationStatement` with a block-scoped initializer
* that is captured in a closure inside of the loop body. The `_loop` function is used to
* preserve the per-iteration environment semantics of
* [13.7.4.8 RS: ForBodyEvaluation](https://tc39.github.io/ecma262/#sec-forbodyevaluation).
*/
function createFunctionForBodyOfIterationStatement(node: IterationStatement, currentState: ConvertedLoopState, outerState: ConvertedLoopState | undefined): IterationStatementPartFunction<Statement[]> {
const functionName = createUniqueName("_loop");
startLexicalEnvironment();
let loopBody = visitNode(node.statement, visitor, isStatement, liftToBlock);
const statement = visitNode(node.statement, visitor, isStatement, liftToBlock);
const lexicalEnvironment = endLexicalEnvironment();
const currentState = convertedLoopState;
convertedLoopState = outerConvertedLoopState;
const statements: Statement[] = [];
if (shouldConvertConditionOfForStatement(node) || shouldConvertIncrementorOfForStatement(node)) {
// If a block-scoped variable declared in the initializer of `node` is captured in
// the condition or incrementor, we must move the condition and incrementor into
// the body of the for loop.
//
// This transforms the following ES2015 syntax:
//
// for (let i = 0; setImmediate(() => console.log(i)), i < 2; setImmediate(() => console.log(i)), i++) {
// // loop body
// }
//
// Into the following ES5 syntax:
//
// var _loop_1 = function (i) {
// if (inc_1)
// setImmediate(() => console.log(i)), i++;
// else
// inc_1 = true;
// if (!(setImmediate(() => console.log(i)), i < 2))
// return out_i_1 = i, "break";
// // loop body
// out_i_1 = i;
// }
// var out_i_1, inc_1 = false;
// for (var i = 0;;) {
// var state_1 = _loop_1(i);
// i = out_i_1;
// if (state_1 === "break")
// break;
// }
//
// Which prevents mutations to `i` in the per-iteration environment of the body
// from affecting the value of `i` in the previous per-iteration environment.
//
// Note that the incrementor of a `for` loop is evaluated in a *new* per-iteration
// environment that is carried over to the next iteration of the loop. As a result,
// we must indicate whether this is the first evaluation of the loop body so that
// we only evaluate the incrementor on subsequent evaluations.
if (loopOutParameters.length || lexicalEnvironment) {
const statements = isBlock(loopBody) ? loopBody.statements.slice() : [loopBody];
if (loopOutParameters.length) {
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
currentState.conditionVariable = createUniqueName("inc");
statements.push(createIf(
currentState.conditionVariable,
createStatement(visitNode(node.incrementor, visitor, isExpression)),
createStatement(createAssignment(currentState.conditionVariable, createTrue()))
));
if (shouldConvertConditionOfForStatement(node)) {
statements.push(createIf(
createPrefix(SyntaxKind.ExclamationToken, visitNode(node.condition, visitor, isExpression)),
visitNode(createBreak(), visitor, isStatement)
));
}
addStatementsAfterPrologue(statements, lexicalEnvironment);
loopBody = createBlock(statements, /*multiline*/ true);
}
if (isBlock(loopBody)) {
loopBody.multiLine = true;
if (isBlock(statement)) {
addRange(statements, statement.statements);
}
else {
loopBody = createBlock([loopBody], /*multiline*/ true);
statements.push(statement);
}
copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOutParameter, statements);
addStatementsAfterPrologue(statements, lexicalEnvironment);
const loopBody = createBlock(statements, /*multiLine*/ true);
if (isBlock(statement)) setOriginalNode(loopBody, statement);
const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0;
const isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0;
let loopBodyFlags: EmitFlags = 0;
if (currentState.containsLexicalThis) {
loopBodyFlags |= EmitFlags.CapturesThis;
}
let emitFlags: EmitFlags = 0;
if (currentState.containsLexicalThis) emitFlags |= EmitFlags.CapturesThis;
if (containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0) emitFlags |= EmitFlags.AsyncFunctionBody;
if (isAsyncBlockContainingAwait) {
loopBodyFlags |= EmitFlags.AsyncFunctionBody;
}
// This transforms the following ES2015 syntax (in addition to other variations):
//
// for (let i = 0; i < 2; i++) {
// setImmediate(() => console.log(i));
// }
//
// Into the following ES5 syntax:
//
// var _loop_1 = function (i) {
// setImmediate(() => console.log(i));
// };
// for (var i = 0; i < 2; i++) {
// _loop_1(i);
// }
const convertedLoopVariable =
const functionDeclaration =
createVariableStatement(
/*modifiers*/ undefined,
setEmitFlags(
@@ -2752,11 +3127,11 @@ namespace ts {
containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
loopParameters,
currentState.loopParameters,
/*type*/ undefined,
<Block>loopBody
loopBody
),
loopBodyFlags
emitFlags
)
)
]
@@ -2765,106 +3140,8 @@ namespace ts {
)
);
const statements: Statement[] = [convertedLoopVariable];
let extraVariableDeclarations: VariableDeclaration[] | undefined;
// propagate state from the inner loop to the outer loop if necessary
if (currentState.argumentsName) {
// if alias for arguments is set
if (outerConvertedLoopState) {
// pass it to outer converted loop
outerConvertedLoopState.argumentsName = currentState.argumentsName;
}
else {
// this is top level converted loop and we need to create an alias for 'arguments' object
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
currentState.argumentsName,
/*type*/ undefined,
createIdentifier("arguments")
)
);
}
}
if (currentState.thisName) {
// if alias for this is set
if (outerConvertedLoopState) {
// pass it to outer converted loop
outerConvertedLoopState.thisName = currentState.thisName;
}
else {
// this is top level converted loop so we need to create an alias for 'this' here
// NOTE:
// if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set.
// If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'.
(extraVariableDeclarations || (extraVariableDeclarations = [])).push(
createVariableDeclaration(
currentState.thisName,
/*type*/ undefined,
createIdentifier("this")
)
);
}
}
if (currentState.hoistedLocalVariables) {
// if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later
if (outerConvertedLoopState) {
// pass them to outer converted loop
outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables;
}
else {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
// hoist collected variable declarations
for (const identifier of currentState.hoistedLocalVariables) {
extraVariableDeclarations.push(createVariableDeclaration(identifier));
}
}
}
// add extra variables to hold out parameters if necessary
if (loopOutParameters.length) {
if (!extraVariableDeclarations) {
extraVariableDeclarations = [];
}
for (const outParam of loopOutParameters) {
extraVariableDeclarations.push(createVariableDeclaration(outParam.outParamName));
}
}
// create variable statement to hold all introduced variable declarations
if (extraVariableDeclarations) {
statements.push(createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(extraVariableDeclarations)
));
}
const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, containsYield);
let loop: Statement;
if (convert) {
loop = convert(node, outermostLabeledStatement, convertedLoopBodyStatements);
}
else {
let clone = getMutableClone(node);
// clean statement part
clone.statement = undefined!;
// visit childnodes to transform initializer/condition/incrementor parts
clone = visitEachChild(clone, visitor, context);
// set loop statement
clone.statement = createBlock(convertedLoopBodyStatements, /*multiline*/ true);
// reset and re-aggregate the transform flags
clone.transformFlags = 0;
aggregateTransformFlags(clone);
loop = restoreEnclosingLabel(clone, outermostLabeledStatement, convertedLoopState && resetLabel);
}
statements.push(loop);
return statements;
const part = generateCallToConvertedLoop(functionName, currentState, outerState, containsYield);
return { functionName, containsYield, functionDeclaration, part };
}
function copyOutParameter(outParam: LoopOutParameter, copyDirection: CopyDirection): BinaryExpression {
@@ -2873,14 +3150,26 @@ namespace ts {
return createBinary(target, SyntaxKind.EqualsToken, source);
}
function copyOutParameters(outParams: LoopOutParameter[], copyDirection: CopyDirection, statements: Statement[]): void {
function copyOutParameters(outParams: LoopOutParameter[], partFlags: LoopOutParameterFlags, copyDirection: CopyDirection, statements: Statement[]): void {
for (const outParam of outParams) {
statements.push(createExpressionStatement(copyOutParameter(outParam, copyDirection)));
if (outParam.flags & partFlags) {
statements.push(createExpressionStatement(copyOutParameter(outParam, copyDirection)));
}
}
}
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, parameters: ParameterDeclaration[], state: ConvertedLoopState, isAsyncBlockContainingAwait: boolean): Statement[] {
const outerConvertedLoopState = convertedLoopState;
function generateCallToConvertedLoopInitializer(initFunctionExpressionName: Identifier, containsYield: boolean): Statement {
const call = createCall(initFunctionExpressionName, /*typeArguments*/ undefined, []);
const callResult = containsYield
? createYield(
createToken(SyntaxKind.AsteriskToken),
setEmitFlags(call, EmitFlags.Iterator)
)
: call;
return createStatement(callResult);
}
function generateCallToConvertedLoop(loopFunctionExpressionName: Identifier, state: ConvertedLoopState, outerState: ConvertedLoopState | undefined, containsYield: boolean): Statement[] {
const statements: Statement[] = [];
// loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop
@@ -2891,8 +3180,8 @@ namespace ts {
!state.labeledNonLocalBreaks &&
!state.labeledNonLocalContinues;
const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(parameters, p => <Identifier>p.name));
const callResult = isAsyncBlockContainingAwait
const call = createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, map(state.loopParameters, p => <Identifier>p.name));
const callResult = containsYield
? createYield(
createToken(SyntaxKind.AsteriskToken),
setEmitFlags(call, EmitFlags.Iterator)
@@ -2900,7 +3189,7 @@ namespace ts {
: call;
if (isSimpleLoop) {
statements.push(createExpressionStatement(callResult));
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements);
}
else {
const loopResultName = createUniqueName("state");
@@ -2911,12 +3200,12 @@ namespace ts {
)
);
statements.push(stateVariable);
copyOutParameters(state.loopOutParameters!, CopyDirection.ToOriginal, statements);
copyOutParameters(state.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOriginal, statements);
if (state.nonLocalJumps! & Jump.Return) {
let returnStatement: ReturnStatement;
if (outerConvertedLoopState) {
outerConvertedLoopState.nonLocalJumps! |= Jump.Return;
if (outerState) {
outerState.nonLocalJumps! |= Jump.Return;
returnStatement = createReturn(loopResultName);
}
else {
@@ -2949,8 +3238,8 @@ namespace ts {
if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) {
const caseClauses: CaseClause[] = [];
processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses);
processLabeledJumps(state.labeledNonLocalBreaks!, /*isBreak*/ true, loopResultName, outerState, caseClauses);
processLabeledJumps(state.labeledNonLocalContinues!, /*isBreak*/ false, loopResultName, outerState, caseClauses);
statements.push(
createSwitch(
loopResultName,
@@ -2998,20 +3287,28 @@ namespace ts {
});
}
function processLoopVariableDeclaration(decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[]) {
function processLoopVariableDeclaration(container: IterationStatement, decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[], hasCapturedBindingsInForInitializer: boolean) {
const name = decl.name;
if (isBindingPattern(name)) {
for (const element of name.elements) {
if (!isOmittedExpression(element)) {
processLoopVariableDeclaration(element, loopParameters, loopOutParameters);
processLoopVariableDeclaration(container, element, loopParameters, loopOutParameters, hasCapturedBindingsInForInitializer);
}
}
}
else {
loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) {
const checkFlags = resolver.getNodeCheckFlags(decl);
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter || hasCapturedBindingsInForInitializer) {
const outParamName = createUniqueName("out_" + idText(name));
loopOutParameters.push({ originalName: name, outParamName });
let flags: LoopOutParameterFlags = 0;
if (checkFlags & NodeCheckFlags.NeedsLoopOutParameter) {
flags |= LoopOutParameterFlags.Body;
}
if (isForStatement(container) && container.initializer && resolver.isBindingCapturedByNode(container.initializer, decl)) {
flags |= LoopOutParameterFlags.Initializer;
}
loopOutParameters.push({ flags, originalName: name, outParamName });
}
}
}
@@ -3432,7 +3729,7 @@ namespace ts {
function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression {
// We are here either because SuperKeyword was used somewhere in the expression, or
// because we contain a SpreadElementExpression.
if (node.transformFlags & TransformFlags.ContainsSpread ||
if (node.transformFlags & TransformFlags.ContainsRestOrSpread ||
node.expression.kind === SyntaxKind.SuperKeyword ||
isSuperProperty(skipOuterExpressions(node.expression))) {
@@ -3442,7 +3739,7 @@ namespace ts {
}
let resultingCall: CallExpression | BinaryExpression;
if (node.transformFlags & TransformFlags.ContainsSpread) {
if (node.transformFlags & TransformFlags.ContainsRestOrSpread) {
// [source]
// f(...a, b)
// x.m(...a, b)
@@ -3505,7 +3802,7 @@ namespace ts {
* @param node A NewExpression node.
*/
function visitNewExpression(node: NewExpression): LeftHandSideExpression {
if (node.transformFlags & TransformFlags.ContainsSpread) {
if (node.transformFlags & TransformFlags.ContainsRestOrSpread) {
// We are here because we contain a SpreadElementExpression.
// [source]
// new C(...a)
@@ -4079,7 +4376,7 @@ namespace ts {
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
};
return function (d, b) {
extendStatics(d, b);
+144 -14
View File
@@ -32,6 +32,15 @@ namespace ts {
let enclosingFunctionParameterNames: UnderscoreEscapedMap<true>;
/**
* Keeps track of property names accessed on super (`super.x`) within async functions.
*/
let capturedSuperProperties: UnderscoreEscapedMap<true>;
/** Whether the async function contains an element access on super (`super[x]`). */
let hasSuperElementAccess: boolean;
/** A set of node IDs for generated super accessors (variable statements). */
const substitutedSuperAccessors: boolean[] = [];
// Save the previous transformation hooks.
const previousOnEmitNode = context.onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
@@ -56,7 +65,6 @@ namespace ts {
if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) {
return node;
}
switch (node.kind) {
case SyntaxKind.AsyncKeyword:
// ES2017 async modifier should be elided for targets < ES2017
@@ -77,6 +85,18 @@ namespace ts {
case SyntaxKind.ArrowFunction:
return visitArrowFunction(<ArrowFunction>node);
case SyntaxKind.PropertyAccessExpression:
if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) {
capturedSuperProperties.set(node.name.escapedText, true);
}
return visitEachChild(node, visitor, context);
case SyntaxKind.ElementAccessExpression:
if (capturedSuperProperties && (<ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword) {
hasSuperElementAccess = true;
}
return visitEachChild(node, visitor, context);
default:
return visitEachChild(node, visitor, context);
}
@@ -398,6 +418,11 @@ namespace ts {
recordDeclarationName(parameter, enclosingFunctionParameterNames);
}
const savedCapturedSuperProperties = capturedSuperProperties;
const savedHasSuperElementAccess = hasSuperElementAccess;
capturedSuperProperties = createUnderscoreEscapedMap<true>();
hasSuperElementAccess = false;
let result: ConciseBody;
if (!isArrowFunction) {
const statements: Statement[] = [];
@@ -415,18 +440,26 @@ namespace ts {
addStatementsAfterPrologue(statements, endLexicalEnvironment());
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuperBinding | NodeCheckFlags.AsyncMethodWithSuper);
if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
addStatementsAfterPrologue(statements, [variableStatement]);
}
const block = createBlock(statements, /*multiLine*/ true);
setTextRange(block, node.body);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
if (languageVersion >= ScriptTarget.ES2015) {
if (emitSuperHelpers && hasSuperElementAccess) {
// Emit helpers for super element access expressions (`super[x]`).
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, asyncSuperHelper);
}
}
@@ -452,6 +485,8 @@ namespace ts {
}
enclosingFunctionParameterNames = savedEnclosingFunctionParameterNames;
capturedSuperProperties = savedCapturedSuperProperties;
hasSuperElementAccess = savedHasSuperElementAccess;
return result;
}
@@ -493,6 +528,8 @@ namespace ts {
context.enableEmitNotification(SyntaxKind.GetAccessor);
context.enableEmitNotification(SyntaxKind.SetAccessor);
context.enableEmitNotification(SyntaxKind.Constructor);
// We need to be notified when entering the generated accessor arrow functions.
context.enableEmitNotification(SyntaxKind.VariableStatement);
}
}
@@ -516,6 +553,14 @@ namespace ts {
return;
}
}
// Disable substitution in the generated super accessor itself.
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = 0;
previousOnEmitNode(hint, node, emitCallback);
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
return;
}
previousOnEmitNode(hint, node, emitCallback);
}
@@ -548,8 +593,10 @@ namespace ts {
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
createLiteral(idText(node.name)),
return setTextRange(
createPropertyAccess(
createFileLevelUniqueName("_super"),
node.name),
node
);
}
@@ -558,7 +605,7 @@ namespace ts {
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
return createSuperElementAccessInAsyncMethod(
node.argumentExpression,
node
);
@@ -593,12 +640,12 @@ namespace ts {
|| kind === SyntaxKind.SetAccessor;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
createFileLevelUniqueName("_super"),
createFileLevelUniqueName("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
@@ -610,7 +657,7 @@ namespace ts {
else {
return setTextRange(
createCall(
createFileLevelUniqueName("_super"),
createFileLevelUniqueName("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
@@ -620,6 +667,89 @@ namespace ts {
}
}
/** Creates a variable named `_super` with accessor properties for the given property names. */
export function createSuperAccessVariableStatement(resolver: EmitResolver, node: FunctionLikeDeclaration, names: UnderscoreEscapedMap<true>) {
// Create a variable declaration with a getter/setter (if binding) definition for each name:
// const _super = Object.create(null, { x: { get: () => super.x, set: (v) => super.x = v }, ... });
const hasBinding = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) !== 0;
const accessors: PropertyAssignment[] = [];
names.forEach((_, key) => {
const name = unescapeLeadingUnderscores(key);
const getterAndSetter: PropertyAssignment[] = [];
getterAndSetter.push(createPropertyAssignment(
"get",
createArrowFunction(
/* modifiers */ undefined,
/* typeParameters */ undefined,
/* parameters */ [],
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
createPropertyAccess(
createSuper(),
name
)
)
));
if (hasBinding) {
getterAndSetter.push(
createPropertyAssignment(
"set",
createArrowFunction(
/* modifiers */ undefined,
/* typeParameters */ undefined,
/* parameters */ [
createParameter(
/* decorators */ undefined,
/* modifiers */ undefined,
/* dotDotDotToken */ undefined,
"v",
/* questionToken */ undefined,
/* type */ undefined,
/* initializer */ undefined
)
],
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
createAssignment(
createPropertyAccess(
createSuper(),
name),
createIdentifier("v")
)
)
)
);
}
accessors.push(
createPropertyAssignment(
name,
createObjectLiteral(getterAndSetter),
)
);
});
return createVariableStatement(
/* modifiers */ undefined,
createVariableDeclarationList(
[
createVariableDeclaration(
createFileLevelUniqueName("_super"),
/* type */ undefined,
createCall(
createPropertyAccess(
createIdentifier("Object"),
"create"
),
/* typeArguments */ undefined,
[
createNull(),
createObjectLiteral(accessors, /* multiline */ true)
]
)
)
],
NodeFlags.Const));
}
const awaiterHelper: EmitHelper = {
name: "typescript:awaiter",
scoped: false,
@@ -667,14 +797,14 @@ namespace ts {
name: "typescript:async-super",
scoped: true,
text: helperString`
const ${"_super"} = name => super[name];`
const ${"_superIndex"} = name => super[name];`
};
export const advancedAsyncSuperHelper: EmitHelper = {
name: "typescript:advanced-async-super",
scoped: true,
text: helperString`
const ${"_super"} = (function (geti, seti) {
const ${"_superIndex"} = (function (geti, seti) {
const cache = Object.create(null);
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
})(name => super[name], (name, value) => super[name] = value);`
+77 -33
View File
@@ -26,6 +26,13 @@ namespace ts {
let enclosingFunctionFlags: FunctionFlags;
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
/** Keeps track of property names accessed on super (`super.x`) within async functions. */
let capturedSuperProperties: UnderscoreEscapedMap<true>;
/** Whether the async function contains an element access on super (`super[x]`). */
let hasSuperElementAccess: boolean;
/** A set of node IDs for generated super accessors. */
const substitutedSuperAccessors: boolean[] = [];
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
@@ -57,7 +64,6 @@ namespace ts {
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
return node;
}
switch (node.kind) {
case SyntaxKind.AwaitExpression:
return visitAwaitExpression(node as AwaitExpression);
@@ -101,6 +107,16 @@ namespace ts {
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
case SyntaxKind.CatchClause:
return visitCatchClause(node as CatchClause);
case SyntaxKind.PropertyAccessExpression:
if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) {
capturedSuperProperties.set(node.name.escapedText, true);
}
return visitEachChild(node, visitor, context);
case SyntaxKind.ElementAccessExpression:
if (capturedSuperProperties && (<ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword) {
hasSuperElementAccess = true;
}
return visitEachChild(node, visitor, context);
default:
return visitEachChild(node, visitor, context);
}
@@ -210,7 +226,7 @@ namespace ts {
}
function visitObjectLiteralExpression(node: ObjectLiteralExpression): Expression {
if (node.transformFlags & TransformFlags.ContainsObjectSpread) {
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
// spread elements emit like so:
// non-spread elements are chunked together into object literals, and then all are passed to __assign:
// { a, ...o, b } => __assign({a}, o, {b});
@@ -250,7 +266,7 @@ namespace ts {
* @param node A BinaryExpression node.
*/
function visitBinaryExpression(node: BinaryExpression, noDestructuringValue: boolean): Expression {
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRest) {
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
return flattenDestructuringAssignment(
node,
visitor,
@@ -276,7 +292,7 @@ namespace ts {
*/
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
// If we are here it is because the name contains a binding pattern with a rest somewhere in it.
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRest) {
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
return flattenDestructuringBinding(
node,
visitor,
@@ -307,7 +323,7 @@ namespace ts {
* @param node A ForOfStatement.
*/
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult<Statement> {
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) {
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
node = transformForOfStatementWithObjectRest(node);
}
if (node.awaitModifier) {
@@ -499,7 +515,7 @@ namespace ts {
}
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
if (node.transformFlags & TransformFlags.ContainsObjectRest) {
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
// Binding patterns are converted into a generated name and are
// evaluated inside the function body.
return updateParameter(
@@ -655,41 +671,57 @@ namespace ts {
const statementOffset = addPrologue(statements, node.body!.statements, /*ensureUseStrict*/ false, visitor);
appendObjectRestAssignmentsIfNeeded(statements, node);
statements.push(
createReturn(
createAsyncGeneratorHelper(
context,
createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
node.name && getGeneratedNameForNode(node.name),
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
updateBlock(
node.body!,
visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset)
)
const savedCapturedSuperProperties = capturedSuperProperties;
const savedHasSuperElementAccess = hasSuperElementAccess;
capturedSuperProperties = createUnderscoreEscapedMap<true>();
hasSuperElementAccess = false;
const returnStatement = createReturn(
createAsyncGeneratorHelper(
context,
createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
node.name && getGeneratedNameForNode(node.name),
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
updateBlock(
node.body!,
visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset)
)
)
)
);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
const emitSuperHelpers = languageVersion >= ScriptTarget.ES2015 && resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuperBinding | NodeCheckFlags.AsyncMethodWithSuper);
if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
addStatementsAfterPrologue(statements, [variableStatement]);
}
statements.push(returnStatement);
addStatementsAfterPrologue(statements, endLexicalEnvironment());
const block = updateBlock(node.body!, statements);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
if (languageVersion >= ScriptTarget.ES2015) {
if (emitSuperHelpers && hasSuperElementAccess) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, asyncSuperHelper);
}
}
capturedSuperProperties = savedCapturedSuperProperties;
hasSuperElementAccess = savedHasSuperElementAccess;
return block;
}
@@ -716,7 +748,7 @@ namespace ts {
function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined {
for (const parameter of node.parameters) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRest) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
const temp = getGeneratedNameForNode(parameter);
const declarations = flattenDestructuringBinding(
parameter,
@@ -758,6 +790,8 @@ namespace ts {
context.enableEmitNotification(SyntaxKind.GetAccessor);
context.enableEmitNotification(SyntaxKind.SetAccessor);
context.enableEmitNotification(SyntaxKind.Constructor);
// We need to be notified when entering the generated accessor arrow functions.
context.enableEmitNotification(SyntaxKind.VariableStatement);
}
}
@@ -781,6 +815,14 @@ namespace ts {
return;
}
}
// Disable substitution in the generated super accessor itself.
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = 0 as NodeCheckFlags;
previousOnEmitNode(hint, node, emitCallback);
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
return;
}
previousOnEmitNode(hint, node, emitCallback);
}
@@ -813,8 +855,10 @@ namespace ts {
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
createLiteral(idText(node.name)),
return setTextRange(
createPropertyAccess(
createFileLevelUniqueName("_super"),
node.name),
node
);
}
@@ -823,7 +867,7 @@ namespace ts {
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
return createSuperElementAccessInAsyncMethod(
node.argumentExpression,
node
);
@@ -858,12 +902,12 @@ namespace ts {
|| kind === SyntaxKind.SetAccessor;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
createIdentifier("_super"),
createIdentifier("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
@@ -875,7 +919,7 @@ namespace ts {
else {
return setTextRange(
createCall(
createIdentifier("_super"),
createIdentifier("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
+4 -2
View File
@@ -973,9 +973,11 @@ namespace ts {
// Check if we have property assignment inside class declaration.
// If there is a property assignment, we need to emit constructor whether users define it or not
// If there is no property assignment, we can omit constructor if users do not define it
const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty);
const hasParameterPropertyAssignments = node.transformFlags & TransformFlags.ContainsParameterPropertyAssignments;
const constructor = getFirstConstructorWithBody(node);
const hasInstancePropertyWithInitializer = forEach(node.members, isInstanceInitializedProperty);
const hasParameterPropertyAssignments = constructor &&
constructor.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax &&
forEach(constructor.parameters, isParameterWithPropertyAssignment);
// If the class does not contain nodes that require a synthesized constructor,
// accept the current constructor if it exists.
+13 -13
View File
@@ -248,7 +248,7 @@ namespace ts {
return getOrCreateValueFromConfigFileMap<Map<T>>(configFileMap, resolved, createMap);
}
function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
return changeExtension(outputPath, Extension.Dts);
@@ -285,16 +285,17 @@ namespace ts {
}
function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
if (!project.options.outFile) {
const out = project.options.outFile || project.options.out;
if (!out) {
return Debug.fail("outFile must be set");
}
const outputs: string[] = [];
outputs.push(project.options.outFile);
outputs.push(out);
if (project.options.sourceMap) {
outputs.push(`${project.options.outFile}.map`);
outputs.push(`${out}.map`);
}
if (getEmitDeclarations(project.options)) {
const dts = changeExtension(project.options.outFile, Extension.Dts);
const dts = changeExtension(out, Extension.Dts);
outputs.push(dts);
if (project.options.declarationMap) {
outputs.push(`${dts}.map`);
@@ -862,7 +863,7 @@ namespace ts {
if (buildProject) {
buildSingleInvalidatedProject(buildProject.project, buildProject.reloadLevel);
if (hasPendingInvalidatedProjects()) {
if (!timerToBuildInvalidatedProject) {
if (options.watch && !timerToBuildInvalidatedProject) {
scheduleBuildInvalidatedProject();
}
}
@@ -901,12 +902,7 @@ namespace ts {
else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) {
// Update file names
const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(resolved), proj.options, parseConfigFileHost);
if (result.fileNames.length !== 0) {
filterMutate(proj.errors, error => !isErrorNoInputFiles(error));
}
else if (!proj.configFileSpecs!.filesSpecs && !some(proj.errors, isErrorNoInputFiles)) {
proj.errors.push(getErrorForNoInputFiles(proj.configFileSpecs!, resolved));
}
updateErrorForNoInputFiles(result, resolved, proj.configFileSpecs!, proj.errors, canJsonReportNoInutFiles(proj.raw));
proj.fileNames = result.fileNames;
watchInputFiles(resolved, proj);
}
@@ -1001,6 +997,7 @@ namespace ts {
return resultFlags;
}
if (configFile.fileNames.length === 0) {
reportAndStoreErrors(proj, configFile.errors);
// Nothing to build - must be a solution file, basically
return BuildResultFlags.None;
}
@@ -1069,6 +1066,9 @@ namespace ts {
type: UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime
};
if (options.watch) {
diagnostics.removeKey(proj);
}
projectStatus.setValue(proj, status);
return resultFlags;
@@ -1248,7 +1248,7 @@ namespace ts {
}
export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
if (project.options.outFile) {
if (project.options.outFile || project.options.out) {
return getOutFileOutputs(project);
}
else {
+2 -1
View File
@@ -52,6 +52,7 @@
"resolutionCache.ts",
"moduleSpecifiers.ts",
"watch.ts",
"tsbuild.ts"
"tsbuild.ts",
"inspectValue.ts",
]
}
+173 -61
View File
@@ -24,7 +24,84 @@ namespace ts {
| SyntaxKind.DotToken
| SyntaxKind.Identifier
| SyntaxKind.NoSubstitutionTemplateLiteral
| SyntaxKind.Unknown;
| SyntaxKind.Unknown
| KeywordSyntaxKind;
export 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;
export type JsxTokenSyntaxKind =
| SyntaxKind.LessThanSlashToken
@@ -713,7 +790,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;
@@ -1697,6 +1774,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;
@@ -1708,7 +1788,7 @@ namespace ts {
export interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent: HeritageClause;
parent: HeritageClause | JSDocAugmentsTag;
expression: LeftHandSideExpression;
}
@@ -2551,7 +2631,18 @@ namespace ts {
fileName: string;
/* @internal */ path: Path;
text: string;
/** Resolved path can be different from path property,
* when file is included through project reference is mapped to its output instead of source
* in that case resolvedPath = path to output file
* path = input file's path
*/
/* @internal */ resolvedPath: Path;
/** Original file name that can be different from fileName,
* when file is included through project reference is mapped to its output instead of source
* in that case originalFileName = name of input file
* fileName = output file's name
*/
/* @internal */ originalFileName: string;
/**
* If two source files are for the same version of the same package, one will redirect to the other.
@@ -2818,7 +2909,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 */
@@ -2827,6 +2922,7 @@ namespace ts {
export interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
sourceFile: SourceFile;
references?: ReadonlyArray<ResolvedProjectReference | undefined>;
}
/* @internal */
@@ -2896,7 +2992,7 @@ namespace ts {
}
/* @internal */
export interface TypeCheckerHost {
export interface TypeCheckerHost extends ModuleSpecifierResolutionHost {
getCompilerOptions(): CompilerOptions;
getSourceFiles(): ReadonlyArray<SourceFile>;
@@ -3014,8 +3110,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[];
@@ -3082,7 +3176,7 @@ namespace ts {
* 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`.
@@ -3171,6 +3265,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
@@ -3233,6 +3329,9 @@ namespace ts {
// Prefer aliases which are not directly visible
UseAliasDefinedOutsideCurrentScope = 0x00000008,
// Skip building an accessible symbol chain
/* @internal */ DoNotIncludeSymbolChain = 0x00000010,
}
/* @internal */
@@ -3408,6 +3507,7 @@ namespace ts {
getJsxFactoryEntity(location?: Node): EntityName | undefined;
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
}
export const enum SymbolFlags {
@@ -3523,6 +3623,7 @@ namespace ts {
type?: Type; // Type of value symbol
uniqueESSymbolType?: Type; // UniqueESSymbol type for a symbol
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
resolvedJSDocType?: Type; // Resolved type of a JSDoc type reference
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
inferredClassType?: Type; // Type of an inferred ES5 class
@@ -3656,22 +3757,23 @@ namespace ts {
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
AssignmentsMarked = 0x00400000, // Parameter assignments have been marked
ClassWithConstructorReference = 0x00800000, // Class that contains a binding to its constructor inside of the class body.
ConstructorReferenceInClass = 0x01000000, // Binding to a class constructor inside of the class's body.
ContainsCapturedBlockScopeBinding = 0x00020000, // Part of a loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00040000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00080000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00400000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
AssignmentsMarked = 0x00800000, // Parameter assignments have been marked
ClassWithConstructorReference = 0x01000000, // Class that contains a binding to its constructor inside of the class body.
ConstructorReferenceInClass = 0x02000000, // Binding to a class constructor inside of the class's body.
}
/* @internal */
export interface NodeLinks {
flags: NodeCheckFlags; // Set of flags specific to Node
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
@@ -3687,6 +3789,8 @@ namespace ts {
switchTypes?: Type[]; // Cached array of switch case expression types
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
deferredNodes?: Map<Node>; // Set of nodes whose checking has been deferred
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
}
export const enum TypeFlags {
@@ -3974,6 +4078,7 @@ namespace ts {
templateType?: Type;
modifiersType?: Type;
resolvedApparentType?: Type;
instantiating?: boolean;
}
export interface EvolvingArrayType extends ObjectType {
@@ -4245,6 +4350,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. */
@@ -4414,6 +4528,7 @@ namespace ts {
sourceRoot?: string;
strict?: boolean;
strictFunctionTypes?: boolean; // Always combine with strict property
strictBindCallApply?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
strictPropertyInitialization?: boolean; // Always combine with strict property
stripInternal?: boolean;
@@ -4827,6 +4942,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 {
@@ -4858,13 +4975,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[];
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;
@@ -4891,25 +5008,21 @@ namespace ts {
// Markers
// - Flags used to indicate that a subtree contains a specific transformation.
ContainsDecorators = 1 << 12,
ContainsPropertyInitializer = 1 << 13,
ContainsLexicalThis = 1 << 14,
ContainsCapturedLexicalThis = 1 << 15,
ContainsLexicalThisInComputedPropertyName = 1 << 16,
ContainsDefaultValueAssignments = 1 << 17,
ContainsParameterPropertyAssignments = 1 << 18,
ContainsSpread = 1 << 19,
ContainsObjectSpread = 1 << 20,
ContainsRest = ContainsSpread,
ContainsObjectRest = ContainsObjectSpread,
ContainsComputedPropertyName = 1 << 21,
ContainsBlockScopedBinding = 1 << 22,
ContainsBindingPattern = 1 << 23,
ContainsYield = 1 << 24,
ContainsHoistedDeclarationOrCompletion = 1 << 25,
ContainsDynamicImport = 1 << 26,
Super = 1 << 27,
ContainsSuper = 1 << 28,
ContainsTypeScriptClassSyntax = 1 << 12, // Decorators, Property Initializers, Parameter Property Initializers
ContainsLexicalThis = 1 << 13,
ContainsCapturedLexicalThis = 1 << 14,
ContainsLexicalThisInComputedPropertyName = 1 << 15,
ContainsDefaultValueAssignments = 1 << 16,
ContainsRestOrSpread = 1 << 17,
ContainsObjectRestOrSpread = 1 << 18,
ContainsComputedPropertyName = 1 << 19,
ContainsBlockScopedBinding = 1 << 20,
ContainsBindingPattern = 1 << 21,
ContainsYield = 1 << 22,
ContainsHoistedDeclarationOrCompletion = 1 << 23,
ContainsDynamicImport = 1 << 24,
Super = 1 << 25,
ContainsSuper = 1 << 26,
// Please leave this as 1 << 29.
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
@@ -4933,23 +5046,22 @@ namespace ts {
OuterExpressionExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
PropertyAccessExcludes = OuterExpressionExcludes | Super,
NodeExcludes = PropertyAccessExcludes | ContainsSuper,
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRest,
ClassExcludes = NodeExcludes | ContainsDecorators | ContainsPropertyInitializer | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsParameterPropertyAssignments | ContainsLexicalThisInComputedPropertyName,
ModuleExcludes = NodeExcludes | ContainsDecorators | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
TypeExcludes = ~ContainsTypeScript,
ObjectLiteralExcludes = NodeExcludes | ContainsDecorators | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectSpread,
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsSpread,
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRest,
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectRestOrSpread,
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread,
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRestOrSpread,
ParameterExcludes = NodeExcludes,
CatchClauseExcludes = NodeExcludes | ContainsObjectRest,
BindingPatternExcludes = NodeExcludes | ContainsRest,
CatchClauseExcludes = NodeExcludes | ContainsObjectRestOrSpread,
BindingPatternExcludes = NodeExcludes | ContainsRestOrSpread,
// Masks
// - Additional bitmasks
TypeScriptClassSyntaxMask = ContainsParameterPropertyAssignments | ContainsPropertyInitializer | ContainsDecorators,
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
}
@@ -5365,7 +5477,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;
}
@@ -5599,15 +5711,15 @@ namespace ts {
type ConcretePragmaSpecs = typeof commentPragmas;
/* @internal */
export type PragmaPsuedoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
/* @internal */
export type PragmaPsuedoMapEntry = {[K in keyof PragmaPsuedoMap]: {name: K, args: PragmaPsuedoMap[K]}}[keyof PragmaPsuedoMap];
export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];
/* @internal */
export interface ReadonlyPragmaMap extends ReadonlyMap<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]> {
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
export interface ReadonlyPragmaMap extends ReadonlyMap<PragmaPseudoMap[keyof PragmaPseudoMap] | PragmaPseudoMap[keyof PragmaPseudoMap][]> {
get<TKey extends keyof PragmaPseudoMap>(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPseudoMap>(value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey) => void): void;
}
/**
@@ -5616,10 +5728,10 @@ namespace ts {
* in multiple places
*/
/* @internal */
export interface PragmaMap extends Map<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]>, ReadonlyPragmaMap {
set<TKey extends keyof PragmaPsuedoMap>(key: TKey, value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]): this;
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
export interface PragmaMap extends Map<PragmaPseudoMap[keyof PragmaPseudoMap] | PragmaPseudoMap[keyof PragmaPseudoMap][]>, ReadonlyPragmaMap {
set<TKey extends keyof PragmaPseudoMap>(key: TKey, value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][]): this;
get<TKey extends keyof PragmaPseudoMap>(key: TKey): PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPseudoMap>(value: PragmaPseudoMap[TKey] | PragmaPseudoMap[TKey][], key: TKey) => void): void;
}
export interface UserPreferences {
+80 -29
View File
@@ -765,12 +765,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!
@@ -978,6 +979,7 @@ namespace ts {
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NeverKeyword:
return true;
@@ -1769,7 +1771,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 */
@@ -1904,12 +1906,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;
@@ -1926,7 +1951,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;
}
@@ -3244,7 +3269,7 @@ namespace ts {
}
export interface EmitFileNames {
jsFilePath: string;
jsFilePath: string | undefined;
sourceMapFilePath: string | undefined;
declarationFilePath: string | undefined;
declarationMapPath: string | undefined;
@@ -3265,7 +3290,7 @@ namespace ts {
const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
if (options.outFile || options.out) {
const moduleKind = getEmitModuleKind(options);
const moduleEmitEnabled = moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
const moduleEmitEnabled = options.emitDeclarationOnly || moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
return filter(host.getSourceFiles(), sourceFile =>
(moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
@@ -3734,11 +3759,20 @@ namespace ts {
/** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */
export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined {
if (isExpressionWithTypeArguments(node) &&
node.parent.token === SyntaxKind.ExtendsKeyword &&
isClassLike(node.parent.parent)) {
return node.parent.parent;
}
const cls = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node);
return cls && !cls.isImplements ? cls.class : undefined;
}
export interface ClassImplementingOrExtendingExpressionWithTypeArguments {
readonly class: ClassLikeDeclaration;
readonly isImplements: boolean;
}
export function tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node: Node): ClassImplementingOrExtendingExpressionWithTypeArguments | undefined {
return isExpressionWithTypeArguments(node)
&& isHeritageClause(node.parent)
&& isClassLike(node.parent.parent)
? { class: node.parent.parent, isImplements: node.parent.token === SyntaxKind.ImplementsKeyword }
: undefined;
}
export function isAssignmentExpression(node: Node, excludeCompoundAssignment: true): node is AssignmentExpression<EqualsToken>;
@@ -3765,15 +3799,6 @@ namespace ts {
return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined;
}
export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments
&& isEntityNameExpression((node as ExpressionWithTypeArguments).expression)
&& node.parent
&& (<HeritageClause>node.parent).token === SyntaxKind.ImplementsKeyword
&& node.parent.parent
&& isClassLike(node.parent.parent);
}
export function isEntityNameExpression(node: Node): node is EntityNameExpression {
return node.kind === SyntaxKind.Identifier || isPropertyAccessEntityNameExpression(node);
}
@@ -4976,14 +5001,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;
}
@@ -7077,16 +7107,15 @@ namespace ts {
const moduleKind = getEmitModuleKind(compilerOptions);
return compilerOptions.allowSyntheticDefaultImports !== undefined
? compilerOptions.allowSyntheticDefaultImports
: compilerOptions.esModuleInterop
? moduleKind !== ModuleKind.None && moduleKind < ModuleKind.ES2015
: moduleKind === ModuleKind.System;
: compilerOptions.esModuleInterop ||
moduleKind === ModuleKind.System;
}
export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean {
return !!(compilerOptions.declaration || compilerOptions.composite);
}
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictBindCallApply" | "strictPropertyInitialization" | "alwaysStrict";
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag];
@@ -7738,7 +7767,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"): string[] | undefined {
if (specs === undefined || specs.length === 0) {
return undefined;
}
@@ -8003,11 +8032,13 @@ 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, extraFileExtensions?: ReadonlyArray<FileExtensionInfo>): ReadonlyArray<string> {
const needJsExtensions = options && options.allowJs;
@@ -8024,6 +8055,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;
}
@@ -8043,7 +8081,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;
}
@@ -8370,4 +8409,16 @@ namespace ts {
export function isJsonEqual(a: unknown, b: unknown): boolean {
return a === b || typeof a === "object" && a !== null && typeof b === "object" && b !== null && equalOwnProperties(a as MapLike<unknown>, b as MapLike<unknown>, isJsonEqual);
}
export function getOrUpdate<T>(map: Map<T>, key: string, getDefault: () => T): T {
const got = map.get(key);
if (got === undefined) {
const value = getDefault();
map.set(key, value);
return value;
}
else {
return got;
}
}
}
+20 -19
View File
@@ -338,9 +338,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[];
/** 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[];
}
/** Internal interface used to wire emit through same host */
@@ -469,7 +469,8 @@ namespace ts {
const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host;
let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host;
let configFileSpecs: ConfigFileSpecs;
let configFileParsingDiagnostics: ReadonlyArray<Diagnostic> | undefined;
let configFileParsingDiagnostics: Diagnostic[] | undefined;
let canConfigFileJsonReportNoInputFiles = false;
let hasChangedConfigFileParsingErrors = false;
const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames);
@@ -546,7 +547,8 @@ namespace ts {
},
maxNumberOfFilesToIterateForInvalidation: host.maxNumberOfFilesToIterateForInvalidation,
getCurrentProgram,
writeLog
writeLog,
readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
};
// Cache for the module resolution
const resolutionCache = createResolutionCache(compilerHost, configFileName ?
@@ -556,11 +558,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();
@@ -762,8 +764,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
@@ -777,8 +779,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);
}
}
}
}
@@ -828,12 +832,7 @@ namespace ts {
function reloadFileNamesFromConfigFile() {
writeLog("Reloading new file names and options");
const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, parseConfigFileHost);
if (result.fileNames.length) {
configFileParsingDiagnostics = filter(configFileParsingDiagnostics, error => !isErrorNoInputFiles(error));
hasChangedConfigFileParsingErrors = true;
}
else if (!configFileSpecs.filesSpecs && !some(configFileParsingDiagnostics, isErrorNoInputFiles)) {
configFileParsingDiagnostics = configFileParsingDiagnostics!.concat(getErrorForNoInputFiles(configFileSpecs, configFileName));
if (updateErrorForNoInputFiles(result, configFileName, configFileSpecs, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) {
hasChangedConfigFileParsingErrors = true;
}
rootFileNames = result.fileNames;
@@ -866,7 +865,8 @@ namespace ts {
compilerOptions = configFileParseResult.options;
configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217
projectReferences = configFileParseResult.projectReferences;
configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult);
configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult).slice();
canConfigFileJsonReportNoInputFiles = canJsonReportNoInutFiles(configFileParseResult.raw);
hasChangedConfigFileParsingErrors = true;
}
@@ -877,6 +877,7 @@ namespace ts {
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) {
resolutionCache.invalidateResolutionOfFile(path);
}
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);
nextSourceFileVersion(path);
// Update the program
+35 -25
View File
@@ -3,12 +3,15 @@ namespace ts.server {
writeMessage(message: string): void;
}
interface RenameEntry extends RenameInfo {
fileName: string;
position: number;
locations: RenameLocation[];
findInStrings: boolean;
findInComments: boolean;
interface RenameEntry {
readonly renameInfo: RenameInfo;
readonly inputs: {
readonly fileName: string;
readonly position: number;
readonly findInStrings: boolean;
readonly findInComments: boolean;
};
readonly locations: RenameLocation[];
}
/* @internal */
@@ -390,34 +393,41 @@ namespace ts.server {
const locations: RenameLocation[] = [];
for (const entry of body.locs) {
const fileName = entry.file;
for (const loc of entry.locs) {
locations.push({ textSpan: this.decodeSpan(loc, fileName), fileName });
for (const { start, end, ...prefixSuffixText } of entry.locs) {
locations.push({ textSpan: this.decodeSpan({ start, end }, fileName), fileName, ...prefixSuffixText });
}
}
return this.lastRenameEntry = {
canRename: body.info.canRename,
fileToRename: body.info.fileToRename,
displayName: body.info.displayName,
fullDisplayName: body.info.fullDisplayName,
kind: body.info.kind,
kindModifiers: body.info.kindModifiers,
localizedErrorMessage: body.info.localizedErrorMessage,
triggerSpan: createTextSpanFromBounds(position, position),
fileName,
position,
findInStrings: !!findInStrings,
findInComments: !!findInComments,
const renameInfo = body.info.canRename
? identity<RenameInfoSuccess>({
canRename: body.info.canRename,
fileToRename: body.info.fileToRename,
displayName: body.info.displayName,
fullDisplayName: body.info.fullDisplayName,
kind: body.info.kind,
kindModifiers: body.info.kindModifiers,
triggerSpan: createTextSpanFromBounds(position, position),
})
: identity<RenameInfoFailure>({ canRename: false, localizedErrorMessage: body.info.localizedErrorMessage });
this.lastRenameEntry = {
renameInfo,
inputs: {
fileName,
position,
findInStrings: !!findInStrings,
findInComments: !!findInComments,
},
locations,
};
return renameInfo;
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
if (!this.lastRenameEntry ||
this.lastRenameEntry.fileName !== fileName ||
this.lastRenameEntry.position !== position ||
this.lastRenameEntry.findInStrings !== findInStrings ||
this.lastRenameEntry.findInComments !== findInComments) {
this.lastRenameEntry.inputs.fileName !== fileName ||
this.lastRenameEntry.inputs.position !== position ||
this.lastRenameEntry.inputs.findInStrings !== findInStrings ||
this.lastRenameEntry.inputs.findInComments !== findInComments) {
this.getRenameInfo(fileName, position, findInStrings, findInComments);
}
+64 -31
View File
@@ -1181,12 +1181,7 @@ namespace FourSlash {
}));
for (const start of toArray<string | Range>(starts)) {
if (typeof start === "string") {
this.goToMarker(start);
}
else {
this.goToRangeStart(start);
}
this.goToMarkerOrRange(start);
const fullActual = ts.map<ts.ReferencedSymbol, ReferenceGroupJson>(this.findReferencesAtCaret(), ({ definition, references }, i) => {
const text = definition.displayParts.map(d => d.text).join("");
return {
@@ -1203,15 +1198,7 @@ namespace FourSlash {
}
public verifyNoReferences(markerNameOrRange?: string | Range) {
if (markerNameOrRange) {
if (ts.isString(markerNameOrRange)) {
this.goToMarker(markerNameOrRange);
}
else {
this.goToRangeStart(markerNameOrRange);
}
}
if (markerNameOrRange) this.goToMarkerOrRange(markerNameOrRange);
const refs = this.getReferencesAtCaret();
if (refs && refs.length) {
this.raiseError(`Expected getReferences to fail, but saw references: ${stringify(refs)}`);
@@ -1328,8 +1315,10 @@ Actual: ${stringify(fullActual)}`);
})));
}
public verifyQuickInfoAt(markerName: string, expectedText: string, expectedDocumentation?: string) {
this.goToMarker(markerName);
public verifyQuickInfoAt(markerName: string | Range, expectedText: string, expectedDocumentation?: string) {
if (typeof markerName === "string") this.goToMarker(markerName);
else this.goToRangeStart(markerName);
this.verifyQuickInfoString(expectedText, expectedDocumentation);
}
@@ -1395,7 +1384,7 @@ Actual: ${stringify(fullActual)}`);
}
}
public verifyRenameLocations(startRanges: ArrayOrSingle<Range>, options: ReadonlyArray<Range> | { findInStrings?: boolean, findInComments?: boolean, ranges: ReadonlyArray<Range> }) {
public verifyRenameLocations(startRanges: ArrayOrSingle<Range>, options: FourSlashInterface.RenameLocationsOptions) {
const { findInStrings = false, findInComments = false, ranges = this.getRanges() } = ts.isArray(options) ? { findInStrings: false, findInComments: false, ranges: options } : options;
for (const startRange of toArray(startRanges)) {
@@ -1412,7 +1401,10 @@ Actual: ${stringify(fullActual)}`);
const sort = (locations: ReadonlyArray<ts.RenameLocation> | undefined) =>
locations && ts.sort(locations, (r1, r2) => ts.compareStringsCaseSensitive(r1.fileName, r2.fileName) || r1.textSpan.start - r2.textSpan.start);
assert.deepEqual(sort(references), sort(ranges.map((r): ts.RenameLocation => ({ fileName: r.fileName, textSpan: ts.createTextSpanFromRange(r) }))));
assert.deepEqual(sort(references), sort(ranges.map((rangeOrOptions): ts.RenameLocation => {
const { range, ...prefixSuffixText } = "range" in rangeOrOptions ? rangeOrOptions : { range: rangeOrOptions };
return { fileName: range.fileName, textSpan: ts.createTextSpanFromRange(range), ...prefixSuffixText };
})));
}
}
@@ -1534,7 +1526,7 @@ Actual: ${stringify(fullActual)}`);
public verifyRenameInfoSucceeded(displayName: string | undefined, fullDisplayName: string | undefined, kind: string | undefined, kindModifiers: string | undefined, fileToRename: string | undefined, expectedRange: Range | undefined): void {
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
if (!renameInfo.canRename) {
this.raiseError("Rename did not succeed");
throw this.raiseError("Rename did not succeed");
}
this.validate("displayName", displayName, renameInfo.displayName);
@@ -1560,9 +1552,8 @@ Actual: ${stringify(fullActual)}`);
public verifyRenameInfoFailed(message?: string) {
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
if (renameInfo.canRename) {
this.raiseError("Rename was expected to fail");
throw this.raiseError("Rename was expected to fail");
}
this.validate("error", message, renameInfo.localizedErrorMessage);
}
@@ -2049,6 +2040,14 @@ Actual: ${stringify(fullActual)}`);
this.goToPosition(len);
}
private goToMarkerOrRange(markerOrRange: string | Range) {
if (typeof markerOrRange === "string") {
this.goToMarker(markerOrRange);
} else {
this.goToRangeStart(markerOrRange);
}
}
public goToRangeStart({ fileName, pos }: Range) {
this.openFile(fileName);
this.goToPosition(pos);
@@ -2502,9 +2501,7 @@ Actual: ${stringify(fullActual)}`);
const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.emptyOptions);
assert.deepEqual<ReadonlyArray<{}> | undefined>(commands, expectedCommands);
assert(changes.every(c => c.fileName === this.activeFile.fileName), "TODO: support testing codefixes that touch multiple files");
this.applyChanges(changes);
this.verifyCurrentFileContent(newFileContent);
this.verifyNewContent({ newFileContent }, changes);
}
/**
@@ -2516,10 +2513,10 @@ Actual: ${stringify(fullActual)}`);
* @param expectedContents The contents of the file after the fixes are applied.
* @param fileName The file to check. If not supplied, the current open file is used.
*/
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) {
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string, index?: number) {
fileName = fileName ? fileName : this.activeFile.fileName;
this.applyCodeActions(this.getCodeFixes(fileName));
this.applyCodeActions(this.getCodeFixes(fileName), index);
const actualContents: string = this.getFileContent(fileName);
if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) {
@@ -3389,6 +3386,19 @@ Actual: ${stringify(fullActual)}`);
private getApplicableRefactorsWorker(positionOrRange: number | ts.TextRange, fileName: string, preferences = ts.emptyOptions): ReadonlyArray<ts.ApplicableRefactorInfo> {
return this.languageService.getApplicableRefactors(fileName, positionOrRange, preferences) || ts.emptyArray;
}
public generateTypes(examples: ReadonlyArray<FourSlashInterface.GenerateTypesOptions>): void {
for (const { name = "example", value, output, outputBaseline } of examples) {
const actual = ts.generateTypesForModule(name, value, this.formatCodeSettings);
if (outputBaseline) {
if (actual === undefined) throw ts.Debug.fail();
Harness.Baseline.runBaseline(ts.combinePaths("generateTypes", outputBaseline + ts.Extension.Dts), actual);
}
else {
assert.equal(actual, output, `generateTypes output for ${name} does not match`);
}
}
}
}
function updateTextRangeForTextChanges({ pos, end }: ts.TextRange, textChanges: ReadonlyArray<ts.TextChange>): ts.TextRange {
@@ -3442,7 +3452,7 @@ Actual: ${stringify(fullActual)}`);
// Parse out the files and their metadata
const testData = parseTestData(absoluteBasePath, content, absoluteFileName);
const state = new TestState(absoluteBasePath, testType, testData);
const output = ts.transpileModule(content, { reportDiagnostics: true });
const output = ts.transpileModule(content, { reportDiagnostics: true, compilerOptions: { target: ts.ScriptTarget.ES2015 } });
if (output.diagnostics!.length > 0) {
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`);
}
@@ -4208,7 +4218,7 @@ namespace FourSlashInterface {
this.state.verifyQuickInfoString(expectedText, expectedDocumentation);
}
public quickInfoAt(markerName: string, expectedText: string, expectedDocumentation?: string) {
public quickInfoAt(markerName: string | FourSlash.Range, expectedText: string, expectedDocumentation?: string) {
this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation);
}
@@ -4375,6 +4385,10 @@ namespace FourSlashInterface {
this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index);
}
public fileAfterCodeFix(expectedContents: string, fileName?: string, index?: number) {
this.state.verifyFileAfterCodeFix(expectedContents, fileName, index);
}
public codeFixAll(options: VerifyCodeFixAllOptions): void {
this.state.verifyCodeFixAll(options);
}
@@ -4473,7 +4487,7 @@ namespace FourSlashInterface {
this.state.verifyRenameInfoFailed(message);
}
public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges: FourSlash.Range[] }) {
public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: RenameLocationsOptions) {
this.state.verifyRenameLocations(startRanges, options);
}
@@ -4512,6 +4526,18 @@ namespace FourSlashInterface {
public noMoveToNewFile(): void {
this.state.noMoveToNewFile();
}
public generateTypes(...options: GenerateTypesOptions[]): void {
this.state.generateTypes(options);
}
}
export interface GenerateTypesOptions {
readonly name?: string;
readonly value: unknown;
// Exactly one of these should be set:
readonly output?: string;
readonly outputBaseline?: string;
}
export class Edit {
@@ -4901,7 +4927,7 @@ namespace FourSlashInterface {
export interface VerifyCodeFixAllOptions {
fixId: string;
fixAllDescription: string;
newFileContent: string;
newFileContent: NewFileContent;
commands: ReadonlyArray<{}>;
}
@@ -4936,4 +4962,11 @@ namespace FourSlashInterface {
readonly newFileContents: { readonly [fileName: string]: string };
readonly preferences?: ts.UserPreferences;
}
export type RenameLocationsOptions = ReadonlyArray<RenameLocationOptions> | {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
readonly ranges: ReadonlyArray<RenameLocationOptions>;
};
export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string };
}
+1 -1
View File
@@ -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);
}
+10 -2
View File
@@ -4,6 +4,8 @@ namespace ts.TestFSWithWatch {
content: `/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
@@ -187,9 +189,10 @@ interface Array<T> {}`
}
export function checkArray(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
checkMapKeys(caption, arrayToMap(actual, identity), expected);
assert.equal(actual.length, expected.length, `${caption}: incorrect actual number of files, expected:\r\n${expected.join("\r\n")}\r\ngot: ${actual.join("\r\n")}`);
for (const f of expected) {
assert.equal(true, contains(actual, f), `${caption}: expected to find ${f} in ${actual}`);
assert.isTrue(contains(actual, f), `${caption}: expected to find ${f} in ${actual}`);
}
}
@@ -934,7 +937,12 @@ interface Array<T> {}`
const folder = this.fs.get(base) as FsFolder;
Debug.assert(isFsFolder(folder));
this.addFileOrFolderInFolder(folder, file);
if (!this.fs.has(file.path)) {
this.addFileOrFolderInFolder(folder, file);
}
else {
this.modifyFile(path, content);
}
}
write(message: string) {
+1
View File
@@ -4,6 +4,7 @@ namespace ts.server {
export const ActionSet: ActionSet = "action::set";
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
export const ActionPackageInstalled: ActionPackageInstalled = "action::packageInstalled";
export const ActionValueInspected: ActionValueInspected = "action::valueInspected";
export const EventTypesRegistry: EventTypesRegistry = "event::typesRegistry";
export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes";
export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes";
+16 -3
View File
@@ -2,6 +2,7 @@ declare namespace ts.server {
export type ActionSet = "action::set";
export type ActionInvalidate = "action::invalidate";
export type ActionPackageInstalled = "action::packageInstalled";
export type ActionValueInspected = "action::valueInspected";
export type EventTypesRegistry = "event::typesRegistry";
export type EventBeginInstallTypes = "event::beginInstallTypes";
export type EventEndInstallTypes = "event::endInstallTypes";
@@ -12,7 +13,7 @@ declare namespace ts.server {
}
export interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | ActionValueInspected | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
export interface TypingInstallerRequestWithProjectName {
@@ -20,7 +21,7 @@ declare namespace ts.server {
}
/* @internal */
export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest;
export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest | InspectValueRequest;
export interface DiscoverTypings extends TypingInstallerRequestWithProjectName {
readonly fileNames: string[];
@@ -47,6 +48,12 @@ declare namespace ts.server {
readonly projectRootPath: Path;
}
/* @internal */
export interface InspectValueRequest {
readonly kind: "inspectValue";
readonly options: InspectValueOptions;
}
/* @internal */
export interface TypesRegistryResponse extends TypingInstallerResponse {
readonly kind: EventTypesRegistry;
@@ -59,6 +66,12 @@ declare namespace ts.server {
readonly message: string;
}
/* @internal */
export interface InspectValueResponse {
readonly kind: ActionValueInspected;
readonly result: ValueInfo;
}
export interface InitializationFailedResponse extends TypingInstallerResponse {
readonly kind: EventInitializationFailed;
readonly message: string;
@@ -106,5 +119,5 @@ declare namespace ts.server {
}
/* @internal */
export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse;
export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InspectValueResponse | InstallTypes | InitializationFailedResponse;
}
+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> {
+61 -1
View File
@@ -295,6 +295,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;
@@ -1350,7 +1410,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];
+116 -42
View File
@@ -5,6 +5,8 @@ namespace ts.server {
// tslint:disable variable-name
export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
export const ProjectLoadingStartEvent = "projectLoadingStart";
export const ProjectLoadingFinishEvent = "projectLoadingFinish";
export const SurveyReady = "surveyReady";
export const LargeFileReferencedEvent = "largeFileReferenced";
export const ConfigFileDiagEvent = "configFileDiag";
@@ -18,6 +20,16 @@ namespace ts.server {
data: { openFiles: string[]; };
}
export interface ProjectLoadingStartEvent {
eventName: typeof ProjectLoadingStartEvent;
data: { project: Project; reason: string; };
}
export interface ProjectLoadingFinishEvent {
eventName: typeof ProjectLoadingFinishEvent;
data: { project: Project; };
}
export interface SurveyReady {
eventName: typeof SurveyReady;
data: { surveyId: string; };
@@ -44,6 +56,24 @@ namespace ts.server {
readonly data: ProjectInfoTelemetryEventData;
}
/* __GDPR__
"projectInfo" : {
"${include}": ["${TypeScriptCommonProperties}"],
"projectId": { "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight", "endpoint": "ProjectId" },
"fileStats": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"compilerOptions": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extends": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"files": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"include": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"exclude": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"compileOnSave": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"typeAcquisition": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"configFileName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"projectType": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"languageServiceEnabled": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"version": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
export interface ProjectInfoTelemetryEventData {
/** Cryptographically secure hash of project file location. */
readonly projectId: string;
@@ -104,7 +134,15 @@ namespace ts.server {
readonly checkJs: boolean;
}
export type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
export type ProjectServiceEvent = LargeFileReferencedEvent |
SurveyReady |
ProjectsUpdatedInBackgroundEvent |
ProjectLoadingStartEvent |
ProjectLoadingFinishEvent |
ConfigFileDiagEvent |
ProjectLanguageServiceStateEvent |
ProjectInfoTelemetryEvent |
OpenFileInfoTelemetryEvent;
export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
@@ -448,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 */
@@ -600,14 +638,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();
}
}
@@ -703,6 +741,33 @@ namespace ts.server {
this.eventHandler(event);
}
/* @internal */
sendProjectLoadingStartEvent(project: ConfiguredProject, reason: string) {
if (!this.eventHandler) {
return;
}
project.sendLoadingProjectFinish = true;
const event: ProjectLoadingStartEvent = {
eventName: ProjectLoadingStartEvent,
data: { project, reason }
};
this.eventHandler(event);
}
/* @internal */
sendProjectLoadingFinishEvent(project: ConfiguredProject) {
if (!this.eventHandler || !project.sendLoadingProjectFinish) {
return;
}
project.sendLoadingProjectFinish = false;
const event: ProjectLoadingFinishEvent = {
eventName: ProjectLoadingFinishEvent,
data: { project }
};
this.eventHandler(event);
}
/* @internal */
delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project: Project) {
this.delayUpdateProjectGraph(project);
@@ -853,15 +918,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);
}
}
}
@@ -937,6 +1007,7 @@ namespace ts.server {
else {
this.logConfigFileWatchUpdate(project.getConfigFilePath(), project.canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingInferredRootFiles);
project.pendingReload = ConfigFileProgramReloadLevel.Full;
project.pendingReloadReason = "Change in config file detected";
this.delayUpdateProjectGraph(project);
// As we scheduled the update on configured project graph,
// we would need to schedule the project reload for only the root of inferred projects
@@ -1595,22 +1666,23 @@ namespace ts.server {
}
/* @internal */
private createConfiguredProjectWithDelayLoad(configFileName: NormalizedPath) {
private createConfiguredProjectWithDelayLoad(configFileName: NormalizedPath, reason: string) {
const project = this.createConfiguredProject(configFileName);
project.pendingReload = ConfigFileProgramReloadLevel.Full;
project.pendingReloadReason = reason;
return project;
}
/* @internal */
private createAndLoadConfiguredProject(configFileName: NormalizedPath) {
private createAndLoadConfiguredProject(configFileName: NormalizedPath, reason: string) {
const project = this.createConfiguredProject(configFileName);
this.loadConfiguredProject(project);
this.loadConfiguredProject(project, reason);
return project;
}
/* @internal */
private createLoadAndUpdateConfiguredProject(configFileName: NormalizedPath) {
const project = this.createAndLoadConfiguredProject(configFileName);
private createLoadAndUpdateConfiguredProject(configFileName: NormalizedPath, reason: string) {
const project = this.createAndLoadConfiguredProject(configFileName, reason);
project.updateGraph();
return project;
}
@@ -1619,7 +1691,9 @@ namespace ts.server {
* Read the config file of the project, and update the project root file names.
*/
/* @internal */
private loadConfiguredProject(project: ConfiguredProject) {
private loadConfiguredProject(project: ConfiguredProject, reason: string) {
this.sendProjectLoadingStartEvent(project, reason);
// Read updated contents from disk
const configFilename = normalizePath(project.getConfigFilePath());
@@ -1656,6 +1730,7 @@ namespace ts.server {
};
}
project.configFileSpecs = parsedCommandLine.configFileSpecs;
project.canConfigFileJsonReportNoInputFiles = canJsonReportNoInutFiles(parsedCommandLine.raw);
project.setProjectErrors(configFileErrors);
project.updateReferences(parsedCommandLine.projectReferences);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, compilerOptions, parsedCommandLine.fileNames, fileNamePropertyReader);
@@ -1748,7 +1823,7 @@ namespace ts.server {
const configFileSpecs = project.configFileSpecs!; // TODO: GH#18217
const configFileName = project.getConfigFilePath();
const fileNamesResult = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions);
project.updateErrorOnNoInputFiles(fileNamesResult.fileNames.length !== 0);
project.updateErrorOnNoInputFiles(fileNamesResult);
this.updateNonInferredProjectFiles(project, fileNamesResult.fileNames.concat(project.getExternalFiles()), fileNamePropertyReader);
return project.updateGraph();
}
@@ -1757,7 +1832,7 @@ namespace ts.server {
* Read the config file of the project again by clearing the cache and update the project graph
*/
/* @internal */
reloadConfiguredProject(project: ConfiguredProject) {
reloadConfiguredProject(project: ConfiguredProject, reason: string) {
// At this point, there is no reason to not have configFile in the host
const host = project.getCachedDirectoryStructureHost();
@@ -1767,7 +1842,7 @@ namespace ts.server {
this.logger.info(`Reloading configured project ${configFileName}`);
// Load project from the disk
this.loadConfiguredProject(project);
this.loadConfiguredProject(project, reason);
project.updateGraph();
this.sendConfigFileDiagEvent(project, configFileName);
@@ -2120,7 +2195,6 @@ namespace ts.server {
if (project.hasExternalProjectRef() &&
project.pendingReload === ConfigFileProgramReloadLevel.Full &&
!this.pendingProjectUpdates.has(project.getProjectName())) {
this.loadConfiguredProject(project);
project.updateGraph();
}
});
@@ -2152,7 +2226,7 @@ namespace ts.server {
// as there is no need to load contents of the files from the disk
// Reload Projects
this.reloadConfiguredProjectForFiles(this.openFiles, /*delayReload*/ false, returnTrue);
this.reloadConfiguredProjectForFiles(this.openFiles, /*delayReload*/ false, returnTrue, "User requested reload projects");
this.ensureProjectForOpenFiles();
}
@@ -2163,7 +2237,8 @@ namespace ts.server {
/*delayReload*/ true,
ignoreIfNotRootOfInferredProject ?
isRootOfInferredProject => isRootOfInferredProject : // Reload open files if they are root of inferred project
returnTrue // Reload all the open files impacted by config file
returnTrue, // Reload all the open files impacted by config file
"Change in config file detected"
);
this.delayEnsureProjectForOpenFiles();
}
@@ -2175,7 +2250,7 @@ namespace ts.server {
* If the there is no existing project it just opens the configured project for the config file
* reloadForInfo provides a way to filter out files to reload configured project for
*/
private reloadConfiguredProjectForFiles<T>(openFiles: Map<T>, delayReload: boolean, shouldReloadProjectFor: (openFileValue: T) => boolean) {
private reloadConfiguredProjectForFiles<T>(openFiles: Map<T>, delayReload: boolean, shouldReloadProjectFor: (openFileValue: T) => boolean, reason: string) {
const updatedProjects = createMap<true>();
// try to reload config file for all open files
openFiles.forEach((openFileValue, path) => {
@@ -2196,11 +2271,12 @@ namespace ts.server {
if (!updatedProjects.has(configFileName)) {
if (delayReload) {
project.pendingReload = ConfigFileProgramReloadLevel.Full;
project.pendingReloadReason = reason;
this.delayUpdateProjectGraph(project);
}
else {
// reload from the disk
this.reloadConfiguredProject(project);
this.reloadConfiguredProject(project, reason);
}
updatedProjects.set(configFileName, true);
}
@@ -2287,7 +2363,8 @@ namespace ts.server {
const configFileName = this.getConfigFileNameForFile(originalFileInfo);
if (!configFileName) return undefined;
const configuredProject = this.findConfiguredProjectByProjectName(configFileName) || this.createAndLoadConfiguredProject(configFileName);
const configuredProject = this.findConfiguredProjectByProjectName(configFileName) ||
this.createAndLoadConfiguredProject(configFileName, `Creating project for original file: ${originalFileInfo.fileName} for location: ${location.fileName}`);
updateProjectIfDirty(configuredProject);
// Keep this configured project as referenced from project
addOriginalConfiguredProject(configuredProject);
@@ -2337,7 +2414,7 @@ namespace ts.server {
if (configFileName) {
project = this.findConfiguredProjectByProjectName(configFileName);
if (!project) {
project = this.createLoadAndUpdateConfiguredProject(configFileName);
project = this.createLoadAndUpdateConfiguredProject(configFileName, `Creating possible configured project for ${fileName} to open`);
// Send the event only if the project got created as part of this open request and info is part of the project
if (info.isOrphan()) {
// Since the file isnt part of configured project, do not send config file info
@@ -2415,17 +2492,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);
}
}
}
});
}
});
@@ -2649,13 +2723,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);
@@ -2778,8 +2852,8 @@ namespace ts.server {
if (!project) {
// errors are stored in the project, do not need to update the graph
project = this.getHostPreferences().lazyConfiguredProjectsFromExternalProject ?
this.createConfiguredProjectWithDelayLoad(tsconfigFile) :
this.createLoadAndUpdateConfiguredProject(tsconfigFile);
this.createConfiguredProjectWithDelayLoad(tsconfigFile, `Creating configured project in external project: ${proj.projectFileName}`) :
this.createLoadAndUpdateConfiguredProject(tsconfigFile, `Creating configured project in external project: ${proj.projectFileName}`);
}
if (project && !contains(exisingConfigFiles, tsconfigFile)) {
// keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project
+53 -32
View File
@@ -254,6 +254,11 @@ namespace ts.server {
installPackage(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult> {
return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) });
}
/* @internal */
inspectValue(options: InspectValueOptions): Promise<ValueInfo> {
return this.typingsCache.inspectValue(options);
}
private get typingsCache(): TypingsCache {
return this.projectService.typingsCache;
}
@@ -276,8 +281,8 @@ namespace ts.server {
return this.projectStateVersion.toString();
}
getProjectReferences(): ReadonlyArray<ProjectReference> {
return emptyArray;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return undefined;
}
getScriptFileNames() {
@@ -352,6 +357,10 @@ namespace ts.server {
return this.projectService.host.readFile(fileName);
}
writeFile(fileName: string, content: string): void {
return this.projectService.host.writeFile(fileName, content);
}
fileExists(file: string): boolean {
// As an optimization, don't hit the disks for files we already know don't exist
// (because we're watching for their creation).
@@ -359,16 +368,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[] {
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[] {
return this.resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference);
}
directoryExists(path: string): boolean {
@@ -574,14 +583,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));
@@ -653,7 +659,7 @@ namespace ts.server {
return this.rootFiles;
}
return map(this.program.getSourceFiles(), sourceFile => {
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath || sourceFile.path);
const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.resolvedPath);
Debug.assert(!!scriptInfo, "getScriptInfo", () => `scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' / '${sourceFile.resolvedPath}' is missing.`);
return scriptInfo!;
});
@@ -916,12 +922,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
@@ -955,11 +968,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);
}
}
}
@@ -1311,10 +1326,15 @@ namespace ts.server {
/* @internal */
pendingReload: ConfigFileProgramReloadLevel;
/* @internal */
pendingReloadReason: string | undefined;
/*@internal*/
configFileSpecs: ConfigFileSpecs | undefined;
/*@internal*/
canConfigFileJsonReportNoInputFiles: boolean;
/** Ref count to the project when opened from external project */
private externalProjectRefCount = 0;
@@ -1327,6 +1347,9 @@ namespace ts.server {
protected isInitialLoadPending: () => boolean = returnTrue;
/*@internal*/
sendLoadingProjectFinish = false;
/*@internal*/
constructor(configFileName: NormalizedPath,
projectService: ProjectService,
@@ -1359,12 +1382,15 @@ namespace ts.server {
result = this.projectService.reloadFileNamesOfConfiguredProject(this);
break;
case ConfigFileProgramReloadLevel.Full:
this.projectService.reloadConfiguredProject(this);
const reason = Debug.assertDefined(this.pendingReloadReason);
this.pendingReloadReason = undefined;
this.projectService.reloadConfiguredProject(this, reason);
result = true;
break;
default:
result = super.updateGraph();
}
this.projectService.sendProjectLoadingFinishEvent(this);
this.projectService.sendProjectTelemetry(this);
this.projectService.sendSurveyReady(this);
return result;
@@ -1379,8 +1405,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) {
@@ -1388,9 +1414,9 @@ 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();
return program && program.forEachResolvedProjectReference(cb);
}
enablePlugins() {
@@ -1531,13 +1557,8 @@ namespace ts.server {
}
/*@internal*/
updateErrorOnNoInputFiles(hasFileNames: boolean) {
if (hasFileNames) {
filterMutate(this.projectErrors!, error => !isErrorNoInputFiles(error)); // TODO: GH#18217
}
else if (!this.configFileSpecs!.filesSpecs && !some(this.projectErrors, isErrorNoInputFiles)) { // TODO: GH#18217
this.projectErrors!.push(getErrorForNoInputFiles(this.configFileSpecs!, this.getConfigFilePath()));
}
updateErrorOnNoInputFiles(fileNameResult: ExpandResult) {
updateErrorForNoInputFiles(fileNameResult, this.getConfigFilePath(), this.configFileSpecs!, this.projectErrors!, this.canConfigFileJsonReportNoInputFiles);
}
}
+51 -9
View File
@@ -1087,23 +1087,18 @@ namespace ts.server.protocol {
/**
* Information about the item to be renamed.
*/
export interface RenameInfo {
export type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
export interface RenameInfoSuccess {
/**
* True if item can be renamed.
*/
canRename: boolean;
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage?: string;
/**
* Display name of the item to be renamed.
*/
@@ -1123,6 +1118,16 @@ namespace ts.server.protocol {
* Optional modifiers for the kind (such as 'public').
*/
kindModifiers: string;
/** Span of text to rename. */
triggerSpan: TextSpan;
}
export interface RenameInfoFailure {
canRename: false;
/**
* Error message if item can not be renamed.
*/
localizedErrorMessage: string;
}
/**
@@ -1132,7 +1137,12 @@ namespace ts.server.protocol {
/** The file to which the spans apply */
file: string;
/** The text spans in this group */
locs: TextSpan[];
locs: RenameTextSpan[];
}
export interface RenameTextSpan extends TextSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
export interface RenameResponseBody {
@@ -2442,6 +2452,30 @@ namespace ts.server.protocol {
openFiles: string[];
}
export type ProjectLoadingStartEventName = "projectLoadingStart";
export interface ProjectLoadingStartEvent extends Event {
event: ProjectLoadingStartEventName;
body: ProjectLoadingStartEventBody;
}
export interface ProjectLoadingStartEventBody {
/** name of the project */
projectName: string;
/** reason for loading */
reason: string;
}
export type ProjectLoadingFinishEventName = "projectLoadingFinish";
export interface ProjectLoadingFinishEvent extends Event {
event: ProjectLoadingFinishEventName;
body: ProjectLoadingFinishEventBody;
}
export interface ProjectLoadingFinishEventBody {
/** name of the project */
projectName: string;
}
export type SurveyReadyEventName = "surveyReady";
export interface SurveyReadyEvent extends Event {
@@ -2734,6 +2768,14 @@ namespace ts.server.protocol {
payload: TypingsInstalledTelemetryEventPayload;
}
/* __GDPR__
"typingsinstalled" : {
"${include}": ["${TypeScriptCommonProperties}"],
"installedPackages": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"installSuccess": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"typingsInstallerVersion": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
export interface TypingsInstalledTelemetryEventPayload {
/**
* Comma separated list of installed typing packages
+73 -23
View File
@@ -336,16 +336,23 @@ namespace ts.server {
function combineProjectOutputForReferences(projects: Projects, defaultProject: Project, initialLocation: sourcemaps.SourceMappableLocation, projectService: ProjectService): ReadonlyArray<ReferencedSymbol> {
const outputs: ReferencedSymbol[] = [];
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(projects, defaultProject, initialLocation, projectService, ({ project, location }, tryAddToTodo) => {
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(projects, defaultProject, initialLocation, projectService, ({ project, location }, getMappedLocation) => {
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.position) || emptyArray) {
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, outputReferencedSymbol.definition));
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
...outputReferencedSymbol.definition,
textSpan: createTextSpan(mappedDefinitionFile.position, outputReferencedSymbol.definition.textSpan.length),
fileName: mappedDefinitionFile.fileName,
};
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
if (!symbolToAddTo) {
symbolToAddTo = { definition: outputReferencedSymbol.definition, references: [] };
symbolToAddTo = { definition, references: [] };
outputs.push(symbolToAddTo);
}
for (const ref of outputReferencedSymbol.references) {
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(ref))) {
// 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);
}
}
@@ -373,12 +380,17 @@ namespace ts.server {
}
}
type CombineProjectOutputCallback<TLocation extends sourcemaps.SourceMappableLocation | undefined> = (
where: ProjectAndLocation<TLocation>,
getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => sourcemaps.SourceMappableLocation | undefined,
) => void;
function combineProjectOutputWorker<TLocation extends sourcemaps.SourceMappableLocation | undefined>(
projects: Projects,
defaultProject: Project,
initialLocation: TLocation,
projectService: ProjectService,
cb: (where: ProjectAndLocation<TLocation>, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
cb: CombineProjectOutputCallback<TLocation>,
getDefinition: (() => sourcemaps.SourceMappableLocation | undefined) | undefined,
): void {
let toDo: ProjectAndLocation<TLocation>[] | undefined;
@@ -417,13 +429,13 @@ namespace ts.server {
projectService: ProjectService,
toDo: ProjectAndLocation<TLocation>[] | undefined,
seenProjects: Map<true>,
cb: (where: ProjectAndLocation<TLocation>, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
cb: CombineProjectOutputCallback<TLocation>,
): ProjectAndLocation<TLocation>[] | undefined {
if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
cb(projectAndLocation, (project, location) => {
seenProjects.set(projectAndLocation.project.projectName, true);
const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location);
if (!originalLocation) return false;
if (!originalLocation) return undefined;
const originalScriptInfo = projectService.getScriptInfo(originalLocation.fileName)!;
toDo = toDo || [];
@@ -437,7 +449,7 @@ namespace ts.server {
for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: originalLocation as TLocation }, toDo!, seenProjects);
});
}
return true;
return originalLocation;
});
return toDo;
}
@@ -478,6 +490,7 @@ namespace ts.server {
globalPlugins?: ReadonlyArray<string>;
pluginProbeLocations?: ReadonlyArray<string>;
allowLocalPluginLoads?: boolean;
typesMapLocation?: string;
}
export class Session implements EventSender {
@@ -538,6 +551,7 @@ namespace ts.server {
globalPlugins: opts.globalPlugins,
pluginProbeLocations: opts.pluginProbeLocations,
allowLocalPluginLoads: opts.allowLocalPluginLoads,
typesMapLocation: opts.typesMapLocation,
syntaxOnly: opts.syntaxOnly,
};
this.projectService = new ProjectService(settings);
@@ -554,9 +568,19 @@ namespace ts.server {
const { openFiles } = event.data;
this.projectsUpdatedInBackgroundEvent(openFiles);
break;
case ProjectLoadingStartEvent:
const { project, reason } = event.data;
this.event<protocol.ProjectLoadingStartEventBody>(
{ projectName: project.getProjectName(), reason },
ProjectLoadingStartEvent);
break;
case ProjectLoadingFinishEvent:
const { project: finishProject } = event.data;
this.event<protocol.ProjectLoadingFinishEventBody>({ projectName: finishProject.getProjectName() }, ProjectLoadingStartEvent);
break;
case LargeFileReferencedEvent:
const { file, fileSize, maxFileSize } = event.data;
this.event<protocol.LargeFileReferencedEventBody>({ file, fileSize, maxFileSize }, "largeFileReferenced");
this.event<protocol.LargeFileReferencedEventBody>({ file, fileSize, maxFileSize }, LargeFileReferencedEvent);
break;
case ConfigFileDiagEvent:
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
@@ -565,14 +589,14 @@ namespace ts.server {
triggerFile,
configFile,
diagnostics: bakedDiags
}, "configFileDiag");
}, ConfigFileDiagEvent);
break;
case SurveyReady:
const { surveyId } = event.data;
this.event<protocol.SurveyReadyEventBody>({ surveyId }, "surveyReady");
this.event<protocol.SurveyReadyEventBody>({ surveyId }, SurveyReady);
break;
case ProjectLanguageServiceStateEvent: {
const eventName: protocol.ProjectLanguageServiceStateEventName = "projectLanguageServiceState";
const eventName: protocol.ProjectLanguageServiceStateEventName = ProjectLanguageServiceStateEvent;
this.event<protocol.ProjectLanguageServiceStateEventBody>({
projectName: event.data.project.getProjectName(),
languageServiceEnabled: event.data.languageServiceEnabled
@@ -603,11 +627,15 @@ namespace ts.server {
// Send project changed event
this.event<protocol.ProjectsUpdatedInBackgroundEventBody>({
openFiles
}, "projectsUpdatedInBackground");
}, ProjectsUpdatedInBackgroundEvent);
}
}
public logError(err: Error, cmd: string) {
public logError(err: Error, cmd: string): void {
this.logErrorWorker(err, cmd);
}
private logErrorWorker(err: Error, cmd: string, fileRequest?: protocol.FileRequestArgs): void {
let msg = "Exception on executing command " + cmd;
if (err.message) {
msg += ":\n" + indent(err.message);
@@ -615,6 +643,19 @@ namespace ts.server {
msg += "\n" + indent((<StackTraceError>err).stack!);
}
}
if (fileRequest && this.logger.hasLevel(LogLevel.verbose)) {
try {
const { file, project } = this.getFileAndProject(fileRequest);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
if (scriptInfo) {
const text = getSnapshotText(scriptInfo.getSnapshot());
msg += `\n\nFile text of ${fileRequest.file}:${indent(text)}\n`;
}
}
catch {} // tslint:disable-line no-empty
}
this.logger.msg(msg, Msg.Err);
}
@@ -1149,21 +1190,28 @@ namespace ts.server {
if (!simplifiedResult) return locations;
const defaultProject = this.getDefaultProject(args);
const renameInfo = Session.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position));
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position), Debug.assertDefined(this.projectService.getScriptInfo(file)));
return { info: renameInfo, locs: this.toSpanGroups(locations) };
}
// strips 'triggerSpan'
private static mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers }: RenameInfo): protocol.RenameInfo {
return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers };
private mapRenameInfo(info: RenameInfo, scriptInfo: ScriptInfo): protocol.RenameInfo {
if (info.canRename) {
const { canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan } = info;
return identity<protocol.RenameInfoSuccess>(
{ canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) });
}
else {
return info;
}
}
private toSpanGroups(locations: ReadonlyArray<RenameLocation>): ReadonlyArray<protocol.SpanGroup> {
const map = createMap<protocol.SpanGroup>();
for (const { fileName, textSpan } of locations) {
for (const { fileName, textSpan, originalTextSpan: _, originalFileName: _1, ...prefixSuffixText } of locations) {
let group = map.get(fileName);
if (!group) map.set(fileName, group = { file: fileName, locs: [] });
group.locs.push(this.toLocationTextSpan(textSpan, Debug.assertDefined(this.projectService.getScriptInfo(fileName))));
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
group.locs.push({ ...this.toLocationTextSpan(textSpan, scriptInfo), ...prefixSuffixText });
}
return arrayFrom(map.values());
}
@@ -1818,8 +1866,8 @@ namespace ts.server {
private applyCodeActionCommand(args: protocol.ApplyCodeActionCommandRequestArgs): {} {
const commands = args.command as CodeActionCommand | CodeActionCommand[]; // They should be sending back the command we sent them.
for (const command of toArray(commands)) {
const { project } = this.getFileAndProject(command);
project.getLanguageService().applyCodeActionCommand(command).then(
const { file, project } = this.getFileAndProject(command);
project.getLanguageService().applyCodeActionCommand(command, this.getFormatOptions(file)).then(
_result => { /* TODO: GH#20447 report success message? */ },
_error => { /* TODO: GH#20447 report errors */ });
}
@@ -2310,8 +2358,10 @@ namespace ts.server {
}
let request: protocol.Request | undefined;
let relevantFile: protocol.FileRequestArgs | undefined;
try {
request = <protocol.Request>JSON.parse(message);
relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined;
const { response, responseRequired } = this.executeCommand(request);
if (this.logger.hasLevel(LogLevel.requestTime)) {
@@ -2337,7 +2387,7 @@ namespace ts.server {
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
return;
}
this.logError(err, message);
this.logErrorWorker(err, message, relevantFile);
this.doOutput(
/*info*/ undefined,
request ? request.command : CommandNames.Unknown,
+7
View File
@@ -8,6 +8,8 @@ namespace ts.server {
export interface ITypingsInstaller {
isKnownTypesPackageName(name: string): boolean;
installPackage(options: InstallPackageOptionsWithProject): Promise<ApplyCodeActionCommandResult>;
/* @internal */
inspectValue(options: InspectValueOptions): Promise<ValueInfo>;
enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string> | undefined): void;
attach(projectService: ProjectService): void;
onProjectClosed(p: Project): void;
@@ -18,6 +20,7 @@ namespace ts.server {
isKnownTypesPackageName: returnFalse,
// Should never be called because we never provide a types registry.
installPackage: notImplemented,
inspectValue: notImplemented,
enqueueInstallTypingsRequest: noop,
attach: noop,
onProjectClosed: noop,
@@ -95,6 +98,10 @@ namespace ts.server {
return this.installer.installPackage(options);
}
inspectValue(options: InspectValueOptions): Promise<ValueInfo> {
return this.installer.inspectValue(options);
}
enqueueInstallTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string> | undefined, forceRefresh: boolean) {
const typeAcquisition = project.getTypeAcquisition();
+4 -2
View File
@@ -246,14 +246,16 @@ namespace ts.server {
return index === 0 || value !== array[index - 1];
}
const indentStr = "\n ";
/* @internal */
export function indent(str: string): string {
return "\n " + str;
return indentStr + str.replace(/\n/g, indentStr);
}
/** Put stringified JSON on the next line, indented. */
/* @internal */
export function stringifyIndented(json: {}): string {
return "\n " + JSON.stringify(json);
return indentStr + JSON.stringify(json);
}
}
+113 -98
View File
@@ -14,32 +14,25 @@ namespace ts.codefix {
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context)),
});
/*
custom type to encapsulate information for variable declarations synthesized in the refactor
numberOfUsesOriginal - number of times the variable should be assigned in the refactor
numberOfUsesSynthesized - count of how many times the variable has been assigned so far
At the end of the refactor, numberOfUsesOriginal should === numberOfUsesSynthesized
*/
interface SynthIdentifier {
identifier: Identifier;
types: Type[];
numberOfAssignmentsOriginal: number;
readonly identifier: Identifier;
readonly types: Type[];
numberOfAssignmentsOriginal: number; // number of times the variable should be assigned in the refactor
}
interface SymbolAndIdentifier {
identifier: Identifier;
symbol: Symbol;
readonly identifier: Identifier;
readonly symbol: Symbol;
}
interface Transformer {
checker: TypeChecker;
synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
allVarNames: SymbolAndIdentifier[];
setOfExpressionsToReturn: Map<true>; // keys are the node ids of the expressions
constIdentifiers: Identifier[];
originalTypeMap: Map<Type>; // keys are the node id of the identifier
isInJSFile: boolean;
readonly checker: TypeChecker;
readonly synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
readonly allVarNames: ReadonlyArray<SymbolAndIdentifier>;
readonly setOfExpressionsToReturn: ReadonlyMap<true>; // keys are the node ids of the expressions
readonly constIdentifiers: Identifier[];
readonly originalTypeMap: ReadonlyMap<Type>; // keys are the node id of the identifier
readonly isInJSFile: boolean;
}
function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker, context: CodeFixContextBase): void {
@@ -68,14 +61,14 @@ namespace ts.codefix {
const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames);
const constIdentifiers = getConstIdentifiers(synthNamesMap);
const returnStatements = getReturnStatementsWithPromiseHandlers(functionToConvertRenamed);
const transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
const transformer: Transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
if (!returnStatements.length) {
return;
}
// add the async keyword
changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, functionToConvert);
changes.insertLastModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, functionToConvert);
function startTransformation(node: CallExpression, nodeToReplace: Node) {
const newNodes = transformExpression(node, transformer, node);
@@ -95,7 +88,7 @@ namespace ts.codefix {
}
// Returns the identifiers that are never reassigned in the refactor
function getConstIdentifiers(synthNamesMap: Map<SynthIdentifier>): Identifier[] {
function getConstIdentifiers(synthNamesMap: ReadonlyMap<SynthIdentifier>): Identifier[] {
const constIdentifiers: Identifier[] = [];
synthNamesMap.forEach((val) => {
if (val.numberOfAssignmentsOriginal === 0) {
@@ -179,9 +172,9 @@ namespace ts.codefix {
// if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg))
// Note - the choice of the last call signature is arbitrary
if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) {
const firstParameter = lastCallSignature.parameters[0];
const ident = isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
if (lastCallSignature && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) {
const firstParameter = firstOrUndefined(lastCallSignature.parameters);
const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
const synthName = getNewNameIfConflict(ident, collidingSymbolMap);
synthNamesMap.set(symbolIdString, synthName);
allVarNames.push({ identifier: synthName.identifier, symbol });
@@ -234,9 +227,7 @@ namespace ts.codefix {
if (renameInfo) {
const type = checker.getTypeAtLocation(node);
if (type) {
originalType.set(getNodeId(clone).toString(), type);
}
originalType.set(getNodeId(clone).toString(), type);
}
}
@@ -258,8 +249,8 @@ namespace ts.codefix {
}
}
function getNewNameIfConflict(name: Identifier, originalNames: Map<Symbol[]>): SynthIdentifier {
const numVarsSameName = (originalNames.get(name.text) || []).length;
function getNewNameIfConflict(name: Identifier, originalNames: ReadonlyMap<Symbol[]>): SynthIdentifier {
const numVarsSameName = (originalNames.get(name.text) || emptyArray).length;
const numberOfAssignmentsOriginal = 0;
const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName);
return { identifier, types: [], numberOfAssignmentsOriginal };
@@ -267,9 +258,9 @@ namespace ts.codefix {
// dispatch function to recursively build the refactoring
// should be kept up to date with isFixablePromiseHandler in suggestionDiagnostics.ts
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
if (!node) {
return [];
return emptyArray;
}
const originalType = isIdentifier(node) && transformer.originalTypeMap.get(getNodeId(node).toString());
@@ -289,10 +280,10 @@ namespace ts.codefix {
}
codeActionSucceeded = false;
return [];
return emptyArray;
}
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const func = node.arguments[0];
const argName = getArgName(func, transformer);
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
@@ -320,7 +311,7 @@ namespace ts.codefix {
const tryBlock = createBlock(transformExpression(node.expression, transformer, node, prevArgName));
const transformationBody = getTransformationBody(func, prevArgName, argName, node, transformer);
const catchArg = argName.identifier.text.length > 0 ? argName.identifier.text : "e";
const catchArg = argName ? argName.identifier.text : "e";
const catchClause = createCatchClause(catchArg, createBlock(transformationBody));
/*
@@ -345,7 +336,7 @@ namespace ts.codefix {
return newSynthName;
}
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const [res, rej] = node.arguments;
if (!res) {
@@ -362,82 +353,91 @@ namespace ts.codefix {
const transformationBody2 = getTransformationBody(rej, prevArgName, argNameRej, node, transformer);
const catchArg = argNameRej.identifier.text.length > 0 ? argNameRej.identifier.text : "e";
const catchArg = argNameRej ? argNameRej.identifier.text : "e";
const catchClause = createCatchClause(catchArg, createBlock(transformationBody2));
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement];
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined)];
}
return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody);
}
function getFlagOfIdentifier(node: Identifier, constIdentifiers: Identifier[]): NodeFlags {
function getFlagOfIdentifier(node: Identifier, constIdentifiers: ReadonlyArray<Identifier>): NodeFlags {
const inArr: boolean = constIdentifiers.some(elem => elem.text === node.text);
return inArr ? NodeFlags.Const : NodeFlags.Let;
}
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
// the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call
const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0;
const originalNodeParent = node.original ? node.original.parent : node.parent;
if (hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
return createVariableDeclarationOrAssignment(prevArgName!, createAwait(node), transformer).concat(); // hack to make the types match
if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
return createTransformedStatement(prevArgName, createAwait(node), transformer);
}
else if (!hasPrevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
return [createStatement(createAwait(node))];
}
return [createReturn(getSynthesizedDeepClone(node))];
}
function createVariableDeclarationOrAssignment(prevArgName: SynthIdentifier, rightHandSide: Expression, transformer: Transformer): NodeArray<Statement> {
if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) {
return createNodeArray([createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]);
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): ReadonlyArray<Statement> {
if (!prevArgName || prevArgName.identifier.text.length === 0) {
// if there's no argName to assign to, there still might be side effects
return [createStatement(rightHandSide)];
}
return createNodeArray([createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))]);
if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) {
// if the variable has already been declared, we don't need "let" or "const"
return [createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))];
}
return [createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))];
}
// should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray<Statement> {
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): ReadonlyArray<Statement> {
const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0;
const hasArgName = argName && argName.identifier.text.length > 0;
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString());
switch (func.kind) {
case SyntaxKind.NullKeyword:
// do not produce a transformed statement for a null argument
break;
case SyntaxKind.Identifier:
// identifier includes undefined
if (!hasArgName) break;
const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, [argName.identifier]);
if (shouldReturn) {
return createNodeArray([createReturn(synthCall)]);
case SyntaxKind.Identifier: // identifier includes undefined
if (!argName) {
// undefined was argument passed to promise handler
break;
}
if (!hasPrevArgName) break;
const synthCall = createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, [argName.identifier]);
if (shouldReturn) {
return [createReturn(synthCall)];
}
const type = transformer.originalTypeMap.get(getNodeId(func).toString());
const callSignatures = type && transformer.checker.getSignaturesOfType(type, SignatureKind.Call);
const returnType = callSignatures && callSignatures[0].getReturnType();
const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, createAwait(synthCall), transformer);
prevArgName!.types.push(returnType!);
const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func);
const callSignatures = transformer.checker.getSignaturesOfType(type, SignatureKind.Call);
if (!callSignatures.length) {
// if identifier in handler has no call signatures, it's invalid
codeActionSucceeded = false;
break;
}
const returnType = callSignatures[0].getReturnType();
const varDeclOrAssignment = createTransformedStatement(prevArgName, createAwait(synthCall), transformer);
if (prevArgName) {
prevArgName.types.push(returnType);
}
return varDeclOrAssignment;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.ArrowFunction: {
const funcBody = (func as FunctionExpression | ArrowFunction).body;
// Arrow functions with block bodies { } will enter this control flow
if (isFunctionLikeDeclaration(func) && func.body && isBlock(func.body) && func.body.statements) {
if (isBlock(funcBody)) {
let refactoredStmts: Statement[] = [];
let seenReturnStatement = false;
for (const statement of func.body.statements) {
for (const statement of funcBody.statements) {
if (isReturnStatement(statement)) {
seenReturnStatement = true;
}
@@ -450,35 +450,43 @@ namespace ts.codefix {
}
}
return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) :
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement);
return shouldReturn ? refactoredStmts.map(s => getSynthesizedDeepClone(s)) :
removeReturns(
refactoredStmts,
prevArgName === undefined ? undefined : prevArgName.identifier,
transformer,
seenReturnStatement);
}
else {
const funcBody = (<ArrowFunction>func).body;
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody as Expression));
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody));
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
if (innerCbBody.length > 0) {
return createNodeArray(innerCbBody);
return innerCbBody;
}
if (hasPrevArgName && !shouldReturn) {
const type = transformer.checker.getTypeAtLocation(func);
const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType();
const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody) as Expression, transformer);
prevArgName!.types.push(returnType);
return varDeclOrAssignment;
const type = transformer.checker.getTypeAtLocation(func);
const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType();
const rightHandSide = getSynthesizedDeepClone(funcBody);
const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? createAwait(rightHandSide) : rightHandSide;
if (!shouldReturn) {
const transformedStatement = createTransformedStatement(prevArgName, possiblyAwaitedRightHandSide, transformer);
if (prevArgName) {
prevArgName.types.push(returnType);
}
return transformedStatement;
}
else {
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]);
return [createReturn(possiblyAwaitedRightHandSide)];
}
}
}
default:
// We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
// If no cases apply, we've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
codeActionSucceeded = false;
break;
}
return createNodeArray([]);
return emptyArray;
}
function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined {
@@ -487,13 +495,19 @@ namespace ts.codefix {
}
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, constIdentifiers: Identifier[], seenReturnStatement: boolean): NodeArray<Statement> {
function removeReturns(stmts: ReadonlyArray<Statement>, prevArgName: Identifier | undefined, transformer: Transformer, seenReturnStatement: boolean): ReadonlyArray<Statement> {
const ret: Statement[] = [];
for (const stmt of stmts) {
if (isReturnStatement(stmt)) {
if (stmt.expression) {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, stmt.expression)], getFlagOfIdentifier(prevArgName, constIdentifiers)))));
const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression;
if (prevArgName === undefined) {
ret.push(createExpressionStatement(possiblyAwaitedExpression));
}
else {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
}
}
}
else {
@@ -502,20 +516,20 @@ namespace ts.codefix {
}
// if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
if (!seenReturnStatement) {
if (!seenReturnStatement && prevArgName !== undefined) {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, constIdentifiers)))));
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
}
return createNodeArray(ret);
return ret;
}
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: Node[], prevArgName?: SynthIdentifier) {
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: ReadonlyArray<Node>, prevArgName?: SynthIdentifier) {
let innerCbBody: Statement[] = [];
for (const stmt of innerRetStmts) {
forEachChild(stmt, function visit(node: Node) {
forEachChild(stmt, function visit(node) {
if (isCallExpression(node)) {
const temp = transformExpression(node, transformer, node, prevArgName);
innerCbBody = innerCbBody.concat(temp);
@@ -531,7 +545,7 @@ namespace ts.codefix {
return innerCbBody;
}
function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier {
function getArgName(funcNode: Expression, transformer: Transformer): SynthIdentifier | undefined {
const numberOfAssignmentsOriginal = 0;
const types: Type[] = [];
@@ -541,20 +555,21 @@ namespace ts.codefix {
if (isFunctionLikeDeclaration(funcNode)) {
if (funcNode.parameters.length > 0) {
const param = funcNode.parameters[0].name as Identifier;
name = getMapEntryIfExists(param);
name = getMapEntryOrDefault(param);
}
}
else if (isIdentifier(funcNode)) {
name = getMapEntryIfExists(funcNode);
name = getMapEntryOrDefault(funcNode);
}
if (!name || name.identifier === undefined || name.identifier.text === "_" || name.identifier.text === "undefined") {
return { identifier: createIdentifier(""), types, numberOfAssignmentsOriginal };
// return undefined argName when arg is null or undefined
if (!name || name.identifier.text === "undefined") {
return undefined;
}
return name;
function getMapEntryIfExists(identifier: Identifier): SynthIdentifier {
function getMapEntryOrDefault(identifier: Identifier): SynthIdentifier {
const originalNode = getOriginalNode(identifier);
const symbol = getSymbol(originalNode);
+131 -13
View File
@@ -1,6 +1,9 @@
/* @internal */
namespace ts.codefix {
const fixId = "fixCannotFindModule";
const fixName = "fixCannotFindModule";
const fixIdInstallTypesPackage = "installTypesPackage";
const fixIdGenerateTypes = "generateTypes";
const errorCodeCannotFindModule = Diagnostics.Cannot_find_module_0.code;
const errorCodes = [
errorCodeCannotFindModule,
@@ -10,26 +13,141 @@ namespace ts.codefix {
errorCodes,
getCodeActions: context => {
const { host, sourceFile, span: { start } } = context;
const packageName = getTypesPackageNameToInstall(host, sourceFile, start, context.errorCode);
return packageName === undefined ? []
: [createCodeFixAction(fixId, /*changes*/ [], [Diagnostics.Install_0, packageName], fixId, Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))];
const packageName = tryGetImportedPackageName(sourceFile, start);
if (packageName === undefined) return undefined;
const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode);
return typesPackageName === undefined
? singleElementArray(tryGetGenerateTypesAction(context, packageName))
: [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))];
},
fixIds: [fixIdInstallTypesPackage, fixIdGenerateTypes],
getAllCodeActions: context => {
let savedTypesDir: string | null | undefined = null; // tslint:disable-line no-null-keyword
return codeFixAll(context, errorCodes, (changes, diag, commands) => {
const packageName = tryGetImportedPackageName(diag.file, diag.start);
if (packageName === undefined) return undefined;
switch (context.fixId) {
case fixIdInstallTypesPackage: {
const pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code);
if (pkg) {
commands.push(getInstallCommand(diag.file.fileName, pkg));
}
break;
}
case fixIdGenerateTypes: {
const typesDir = savedTypesDir !== null ? savedTypesDir : savedTypesDir = getOrCreateTypesDirectory(changes, context);
const command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context);
if (command) commands.push(command);
break;
}
default:
Debug.fail(`Bad fixId: ${context.fixId}`);
}
});
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (_, diag, commands) => {
const pkg = getTypesPackageNameToInstall(context.host, diag.file, diag.start, diag.code);
if (pkg) {
commands.push(getCommand(diag.file.fileName, pkg));
}
}),
});
function getCommand(fileName: string, packageName: string): InstallPackageAction {
function tryGetGenerateTypesAction(context: CodeFixContextBase, packageName: string): CodeFixAction | undefined {
let command: GenerateTypesAction | undefined;
const changes = textChanges.ChangeTracker.with(context, t => {
const typesDir = getOrCreateTypesDirectory(t, context);
command = typesDir === undefined ? undefined : tryGenerateTypes(typesDir, packageName, context);
});
return command && createCodeFixAction(fixName, changes, [Diagnostics.Generate_types_for_0, packageName], fixIdGenerateTypes, Diagnostics.Generate_types_for_all_packages_without_types, command);
}
function tryGenerateTypes(typesDir: string, packageName: string, context: CodeFixContextBase): GenerateTypesAction | undefined {
const file = context.sourceFile.fileName;
const fileToGenerateTypesFor = tryResolveJSModule(packageName, getDirectoryPath(file), context.host as ModuleResolutionHost); // TODO: GH#18217
if (fileToGenerateTypesFor === undefined) return undefined;
const outputFileName = resolvePath(getDirectoryPath(context.program.getCompilerOptions().configFile!.fileName), typesDir, packageName + ".d.ts");
if (context.host.fileExists!(outputFileName)) return undefined;
return { type: "generate types", file, fileToGenerateTypesFor, outputFileName };
}
// If no types directory exists yet, adds it to tsconfig.json
function getOrCreateTypesDirectory(changes: textChanges.ChangeTracker, context: CodeFixContextBase): string | undefined {
const { configFile } = context.program.getCompilerOptions();
if (!configFile) return undefined;
const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile);
if (!tsconfigObjectLiteral) return undefined;
const compilerOptionsProperty = findProperty(tsconfigObjectLiteral, "compilerOptions");
if (!compilerOptionsProperty) {
const newCompilerOptions = createObjectLiteral([makeDefaultBaseUrl(), makeDefaultPaths()]);
changes.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment("compilerOptions", newCompilerOptions));
return defaultTypesDirectoryName;
}
const compilerOptions = compilerOptionsProperty.initializer;
if (!isObjectLiteralExpression(compilerOptions)) return defaultTypesDirectoryName;
const baseUrl = getOrAddBaseUrl(changes, configFile, compilerOptions);
const typesDirectoryFromPathMapping = getOrAddPathMapping(changes, configFile, compilerOptions);
return combinePaths(baseUrl, typesDirectoryFromPathMapping);
}
const defaultBaseUrl = ".";
function makeDefaultBaseUrl(): PropertyAssignment {
return createJsonPropertyAssignment("baseUrl", createStringLiteral(defaultBaseUrl));
}
function getOrAddBaseUrl(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression): string {
const baseUrlProp = findProperty(compilerOptions, "baseUrl");
if (baseUrlProp) {
return isStringLiteral(baseUrlProp.initializer) ? baseUrlProp.initializer.text : defaultBaseUrl;
}
else {
changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultBaseUrl());
return defaultBaseUrl;
}
}
const defaultTypesDirectoryName = "types";
function makeDefaultPathMapping(): PropertyAssignment {
return createJsonPropertyAssignment("*", createArrayLiteral([createStringLiteral(`${defaultTypesDirectoryName}/*`)]));
}
function makeDefaultPaths(): PropertyAssignment {
return createJsonPropertyAssignment("paths", createObjectLiteral([makeDefaultPathMapping()]));
}
function getOrAddPathMapping(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression) {
const paths = findProperty(compilerOptions, "paths");
if (!paths || !isObjectLiteralExpression(paths.initializer)) {
changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultPaths());
return defaultTypesDirectoryName;
}
// Look for an existing path mapping. Should look like `"*": "foo/*"`.
const existing = firstDefined(paths.initializer.properties, prop =>
isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "*" && isArrayLiteralExpression(prop.initializer)
? firstDefined(prop.initializer.elements, value => isStringLiteral(value) ? tryRemoveSuffix(value.text, "/*") : undefined)
: undefined);
if (existing) return existing;
changes.insertNodeAtObjectStart(tsconfig, paths.initializer, makeDefaultPathMapping());
return defaultTypesDirectoryName;
}
function createJsonPropertyAssignment(name: string, initializer: Expression) {
return createPropertyAssignment(createStringLiteral(name), initializer);
}
function findProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined {
return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name);
}
function getInstallCommand(fileName: string, packageName: string): InstallPackageAction {
return { type: "install package", file: fileName, packageName };
}
function getTypesPackageNameToInstall(host: LanguageServiceHost, sourceFile: SourceFile, pos: number, diagCode: number): string | undefined {
function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string | undefined {
const moduleName = cast(getTokenAtPosition(sourceFile, pos), isStringLiteral).text;
const { packageName } = parsePackageName(moduleName);
return isExternalModuleNameRelative(packageName) ? undefined : packageName;
}
function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined {
return diagCode === errorCodeCannotFindModule
? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined)
: (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217
+227
View File
@@ -0,0 +1,227 @@
/* @internal */
namespace ts {
export function generateTypesForModule(name: string, moduleValue: unknown, formatSettings: FormatCodeSettings): string {
return valueInfoToDeclarationFileText(inspectValue(name, moduleValue), formatSettings);
}
export function valueInfoToDeclarationFileText(valueInfo: ValueInfo, formatSettings: FormatCodeSettings): string {
return textChanges.getNewFileText(toStatements(valueInfo, OutputKind.ExportEquals), ScriptKind.TS, "\n", formatting.getFormatContext(formatSettings));
}
const enum OutputKind { ExportEquals, NamedExport, NamespaceMember }
function toNamespaceMemberStatements(info: ValueInfo): ReadonlyArray<Statement> {
return toStatements(info, OutputKind.NamespaceMember);
}
function toStatements(info: ValueInfo, kind: OutputKind): ReadonlyArray<Statement> {
const isDefault = info.name === InternalSymbolName.Default;
const name = isDefault ? "_default" : info.name;
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.NamedExport ? [createModifier(SyntaxKind.ExportKeyword)]
: undefined;
const exportEquals = () => kind === OutputKind.ExportEquals ? [exportEqualsOrDefault(info.name, /*isExportEquals*/ true)] : emptyArray;
const exportDefault = () => isDefault ? [exportEqualsOrDefault("_default", /*isExportEquals*/ false)] : emptyArray;
switch (info.kind) {
case ValueKind.FunctionOrClass:
return [...exportEquals(), ...functionOrClassToStatements(modifiers, name, info)];
case ValueKind.Object:
const { members } = info;
if (kind === OutputKind.ExportEquals) {
return flatMap(members, v => toStatements(v, OutputKind.NamedExport));
}
if (members.some(m => m.kind === ValueKind.FunctionOrClass)) {
// If some member is a function, use a namespace so it gets a FunctionDeclaration or ClassDeclaration.
return [...exportDefault(), createNamespace(modifiers, name, flatMap(members, toNamespaceMemberStatements))];
}
// falls through
case ValueKind.Const:
case ValueKind.Array: {
const comment = info.kind === ValueKind.Const ? info.comment : undefined;
const constVar = createVariableStatement(modifiers, createVariableDeclarationList([createVariableDeclaration(name, toType(info))], NodeFlags.Const));
return [...exportEquals(), ...exportDefault(), addComment(constVar, comment)];
}
default:
return Debug.assertNever(info);
}
}
function exportEqualsOrDefault(name: string, isExportEquals: boolean): ExportAssignment {
return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, createIdentifier(name));
}
function functionOrClassToStatements(modifiers: Modifiers, name: string, { source, prototypeMembers, namespaceMembers }: ValueInfoFunctionOrClass): ReadonlyArray<Statement> {
const fnAst = parseClassOrFunctionBody(source);
const { parameters, returnType } = fnAst === undefined ? { parameters: emptyArray, returnType: anyType() } : getParametersAndReturnType(fnAst);
const instanceProperties = typeof fnAst === "object" ? getConstructorFunctionInstanceProperties(fnAst) : emptyArray;
const classStaticMembers: ClassElement[] | undefined =
instanceProperties.length !== 0 || prototypeMembers.length !== 0 || fnAst === undefined || typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor ? [] : undefined;
const namespaceStatements = flatMap(namespaceMembers, info => {
if (!isValidIdentifier(info.name)) return undefined;
if (classStaticMembers) {
switch (info.kind) {
case ValueKind.Object:
if (info.members.some(m => m.kind === ValueKind.FunctionOrClass)) {
break;
}
// falls through
case ValueKind.Array:
case ValueKind.Const:
classStaticMembers.push(
addComment(
createProperty(/*decorators*/ undefined, [createModifier(SyntaxKind.StaticKeyword)], info.name, /*questionOrExclamationToken*/ undefined, toType(info), /*initializer*/ undefined),
info.kind === ValueKind.Const ? info.comment : undefined));
return undefined;
case ValueKind.FunctionOrClass:
if (!info.namespaceMembers.length) { // Else, can't merge a static method with a namespace. Must make it a function on the namespace.
const sig = tryGetMethod(info, [createModifier(SyntaxKind.StaticKeyword)]);
if (sig) {
classStaticMembers.push(sig);
return undefined;
}
}
}
}
return toStatements(info, OutputKind.NamespaceMember);
});
const decl = classStaticMembers
? createClassDeclaration(
/*decorators*/ undefined,
modifiers,
name,
/*typeParameters*/ undefined,
/*heritageClauses*/ undefined,
[
...classStaticMembers,
...(parameters.length ? [createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, parameters, /*body*/ undefined)] : emptyArray),
...instanceProperties,
// ignore non-functions on the prototype
...mapDefined(prototypeMembers, info => info.kind === ValueKind.FunctionOrClass ? tryGetMethod(info) : undefined),
])
: createFunctionDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, name, /*typeParameters*/ undefined, parameters, returnType, /*body*/ undefined);
return [decl, ...(namespaceStatements.length === 0 ? emptyArray : [createNamespace(modifiers && modifiers.map(m => getSynthesizedDeepClone(m)), name, namespaceStatements)])];
}
function tryGetMethod({ name, source }: ValueInfoFunctionOrClass, modifiers?: Modifiers): MethodDeclaration | undefined {
if (!isValidIdentifier(name)) return undefined;
const fnAst = parseClassOrFunctionBody(source);
if (fnAst === undefined || (typeof fnAst !== "number" && fnAst.kind === SyntaxKind.Constructor)) return undefined;
const sig = getParametersAndReturnType(fnAst);
return sig && createMethod(
/*decorators*/ undefined,
modifiers,
/*asteriskToken*/ undefined,
name,
/*questionToken*/ undefined,
/*typeParameters*/ undefined,
sig.parameters,
sig.returnType,
/*body*/ undefined);
}
function toType(info: ValueInfo): TypeNode {
switch (info.kind) {
case ValueKind.Const:
return createTypeReferenceNode(info.typeName, /*typeArguments*/ undefined);
case ValueKind.Array:
return createArrayTypeNode(toType(info.inner));
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)));
default:
return Debug.assertNever(info);
}
}
// Parses assignments to "this.x" in the constructor into class property declarations
function getConstructorFunctionInstanceProperties(fnAst: FunctionOrConstructorNode): ReadonlyArray<PropertyDeclaration> {
const members: PropertyDeclaration[] = [];
forEachOwnNodeOfFunction(fnAst, node => {
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) &&
isPropertyAccessExpression(node.left) && node.left.expression.kind === SyntaxKind.ThisKeyword) {
const name = node.left.name.text;
if (!isJsPrivate(name)) members.push(createProperty(/*decorators*/ undefined, /*modifiers*/ undefined, name, /*questionOrExclamationToken*/ undefined, anyType(), /*initializer*/ undefined));
}
});
return members;
}
interface ParametersAndReturnType { readonly parameters: ReadonlyArray<ParameterDeclaration>; readonly returnType: TypeNode; }
function getParametersAndReturnType(fnAst: FunctionOrConstructor): ParametersAndReturnType {
if (typeof fnAst === "number") {
return { parameters: fill(fnAst, i => makeParameter(`p${i}`, anyType())), returnType: anyType() };
}
let usedArguments = false, hasReturn = false;
forEachOwnNodeOfFunction(fnAst, node => {
usedArguments = usedArguments || isIdentifier(node) && node.text === "arguments";
hasReturn = hasReturn || isReturnStatement(node) && !!node.expression && node.expression.kind !== SyntaxKind.VoidExpression;
});
const parameters = [
...fnAst.parameters.map(p => makeParameter(`${p.name.getText()}`, inferParameterType(fnAst, p))),
...(usedArguments ? [makeRestParameter()] : emptyArray),
];
return { parameters, returnType: hasReturn ? anyType() : createKeywordTypeNode(SyntaxKind.VoidKeyword) };
}
function makeParameter(name: string, type: TypeNode): ParameterDeclaration {
return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name, /*questionToken*/ undefined, type);
}
function makeRestParameter(): ParameterDeclaration {
return createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken), "args", /*questionToken*/ undefined, createArrayTypeNode(anyType()));
}
type FunctionOrConstructorNode = FunctionExpression | ArrowFunction | ConstructorDeclaration | MethodDeclaration;
type FunctionOrConstructor = FunctionOrConstructorNode | number; // number is for native function
/** Returns 'undefined' for class with no declared constructor */
function parseClassOrFunctionBody(source: string | number): FunctionOrConstructor | undefined {
if (typeof source === "number") return source;
const classOrFunction = tryCast(parseExpression(source), (node): node is FunctionExpression | ArrowFunction | ClassExpression => isFunctionExpression(node) || isArrowFunction(node) || isClassExpression(node));
return classOrFunction
? isClassExpression(classOrFunction) ? find(classOrFunction.members, isConstructorDeclaration) : classOrFunction
// If that didn't parse, it's a method `m() {}`. Parse again inside of an object literal.
: cast(first(cast(parseExpression(`{ ${source} }`), isObjectLiteralExpression).properties), isMethodDeclaration);
}
function parseExpression(expr: string): Expression {
const text = `const _ = ${expr}`;
const srcFile = createSourceFile("test.ts", text, ScriptTarget.Latest, /*setParentNodes*/ true);
return first(cast(first(srcFile.statements), isVariableStatement).declarationList.declarations).initializer!;
}
function inferParameterType(_fn: FunctionOrConstructor, _param: ParameterDeclaration): TypeNode {
// TODO: Inspect function body for clues (see inferFromUsage.ts)
return anyType();
}
// Descends through all nodes in a function, but not in nested functions.
function forEachOwnNodeOfFunction(fnAst: FunctionOrConstructorNode, cb: (node: Node) => void) {
fnAst.body!.forEachChild(function recur(node) {
cb(node);
if (!isFunctionLike(node)) node.forEachChild(recur);
});
}
function isValidIdentifier(name: string): boolean {
const keyword = stringToToken(name);
return !(keyword && isNonContextualKeyword(keyword)) && isIdentifierText(name, ScriptTarget.ESNext);
}
type Modifiers = ReadonlyArray<Modifier> | undefined;
function addComment<T extends Node>(node: T, comment: string | undefined): T {
if (comment !== undefined) addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, comment);
return node;
}
function anyType(): KeywordTypeNode {
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
function createNamespace(modifiers: Modifiers, name: string, statements: ReadonlyArray<Statement>): NamespaceDeclaration {
return createModuleDeclaration(/*decorators*/ undefined, modifiers, createIdentifier(name), createModuleBlock(statements), NodeFlags.Namespace) as NamespaceDeclaration;
}
}
+6 -6
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(
@@ -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 {
+96 -43
View File
@@ -25,24 +25,21 @@ namespace ts.codefix {
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,7 +47,7 @@ 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
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:
return Diagnostics.Infer_parameter_types_from_usage;
default:
@@ -58,8 +55,8 @@ namespace ts.codefix {
}
}
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) {
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;
}
@@ -69,7 +66,15 @@ namespace ts.codefix {
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 = type && getTypeNodeIfAccessible(type, parent, program, host);
if (typeNode) {
changes.tryInsertJSDocType(sourceFile, parent, typeNode);
}
return parent;
}
return undefined;
@@ -77,7 +82,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 +97,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, param, containingFunction, sourceFile, program, host, cancellationToken);
return param;
}
return undefined;
@@ -108,16 +113,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 +132,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);
}
}
@@ -145,40 +150,67 @@ namespace ts.codefix {
return false;
}
function annotateParameters(changes: textChanges.ChangeTracker, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): void {
function annotateParameters(changes: textChanges.ChangeTracker, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, 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) : undefined
}));
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);
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 | undefined, program: Program, host: LanguageServiceHost): void {
const typeNode = type && getTypeNodeIfAccessible(type, declaration, program, host);
if (typeNode) {
if (isInJSFile(sourceFile) && declaration.kind !== SyntaxKind.PropertySignature) {
changes.tryInsertJSDocType(sourceFile, declaration, typeNode);
}
else {
changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode);
}
}
}
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, checker: TypeChecker): TypeNode | undefined {
function annotateJSDocParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterInferences: ParameterInference[], program: Program, host: LanguageServiceHost): void {
const result = mapDefined(parameterInferences, inference => {
const param = inference.declaration;
const typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host);
return typeNode && !param.initializer && !getJSDocType(param) ? { ...inference, typeNode } : undefined;
});
changes.tryInsertJSDocParameters(sourceFile, result);
}
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 +221,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;
}
@@ -196,14 +236,14 @@ namespace ts.codefix {
function getReferences(token: PropertyName | Token<SyntaxKind.ConstructorKeyword>, program: Program, cancellationToken: CancellationToken): ReadonlyArray<Identifier> {
// Position shouldn't matter since token is not a SourceFile.
return mapDefined(FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), entry =>
entry.type === "node" ? tryCast(entry.node, isIdentifier) : undefined);
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 inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): (Type | undefined)[] | undefined {
function inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
switch (containingFunction.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionExpression:
@@ -219,6 +259,13 @@ namespace ts.codefix {
}
}
interface ParameterInference {
declaration: ParameterDeclaration;
type?: Type;
typeNode?: TypeNode;
isOptional?: boolean;
}
namespace InferFromReference {
interface CallContext {
argumentTypes: Type[];
@@ -246,7 +293,7 @@ namespace ts.codefix {
return getTypeFromUsageContext(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, checker: TypeChecker, cancellationToken: CancellationToken): ParameterInference[] | undefined {
if (references.length === 0) {
return undefined;
}
@@ -265,8 +312,10 @@ namespace ts.codefix {
return callContexts && declaration.parameters.map((parameter, parameterIndex) => {
const types: Type[] = [];
const isRest = isRestParameter(parameter);
let isOptional = false;
for (const callContext of callContexts) {
if (callContext.argumentTypes.length <= parameterIndex) {
isOptional = isInJSFile(declaration);
continue;
}
@@ -280,10 +329,14 @@ namespace ts.codefix {
}
}
if (!types.length) {
return undefined;
return { declaration: parameter };
}
const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
return isRest ? checker.createArrayType(type) : type;
return {
type: isRest ? checker.createArrayType(type) : type,
isOptional: isOptional && !isRest,
declaration: parameter
};
});
}
+17 -13
View File
@@ -43,7 +43,7 @@ namespace ts.Completions {
}
const contextToken = findPrecedingToken(position, sourceFile);
if (triggerCharacter && (!contextToken || !isValidTrigger(sourceFile, triggerCharacter, contextToken, position))) return undefined;
if (triggerCharacter && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) return undefined;
if (isInString(sourceFile, position, contextToken)) {
return !contextToken || !isStringLiteralLike(contextToken)
@@ -1200,9 +1200,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;
@@ -1397,7 +1397,7 @@ namespace ts.Completions {
if (resolvedModuleSymbol !== moduleSymbol &&
// Don't add another completion for `export =` of a symbol that's already global.
// So in `declare namespace foo {} declare module "foo" { export = foo; }`, there will just be the global completion for `foo`.
resolvedModuleSymbol.declarations.some(d => !!d.getSourceFile().externalModuleIndicator)) {
some(resolvedModuleSymbol.declarations, d => !!d.getSourceFile().externalModuleIndicator)) {
symbols.push(resolvedModuleSymbol);
symbolToOriginInfoMap[getSymbolId(resolvedModuleSymbol)] = { kind: SymbolOriginInfoKind.Export, moduleSymbol, isDefaultExport: false };
}
@@ -1410,7 +1410,7 @@ namespace ts.Completions {
// 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 (typeChecker.getMergedSymbol(symbol.parent!) !== resolvedModuleSymbol
|| some(symbol.declarations, d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) {
|| some(symbol.declarations, d => isExportSpecifier(d) && !d.propertyName && !!d.parent.parent.moduleSpecifier)) {
continue;
}
@@ -1713,6 +1713,9 @@ namespace ts.Completions {
break;
case SyntaxKind.AsteriskToken:
return isMethodDeclaration(parent) ? tryCast(parent.parent, isObjectLiteralExpression) : undefined;
case SyntaxKind.Identifier:
return (contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent)
? contextToken.parent.parent : undefined;
}
}
@@ -1928,7 +1931,6 @@ namespace ts.Completions {
// Previous token may have been a keyword that was converted to an identifier.
switch (keywordForNode(contextToken)) {
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.ClassKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.DeclareKeyword:
@@ -1943,6 +1945,8 @@ namespace ts.Completions {
case SyntaxKind.VarKeyword:
case SyntaxKind.YieldKeyword:
return true;
case SyntaxKind.AsyncKeyword:
return isPropertyDeclaration(contextToken.parent);
}
return isDeclarationName(contextToken)
@@ -2146,7 +2150,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);
@@ -2207,7 +2211,7 @@ namespace ts.Completions {
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,7 +2276,7 @@ namespace ts.Completions {
return !!type.getStringIndexType() || !!type.getNumberIndexType();
}
function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node, position: number): boolean {
function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node | undefined, position: number): boolean {
switch (triggerCharacter) {
case ".":
case "@":
@@ -2281,14 +2285,14 @@ namespace ts.Completions {
case "'":
case "`":
// Only automatically bring up completions if this is an opening quote.
return isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
return !!contextToken && isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
case "<":
// Opening JSX tag
return contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
case "/":
return isStringLiteralLike(contextToken)
return !!contextToken && (isStringLiteralLike(contextToken)
? !!tryGetImportFromModuleSpecifier(contextToken)
: contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent);
: contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent));
default:
return Debug.assertNever(triggerCharacter);
}
+126 -83
View File
@@ -13,19 +13,20 @@ namespace ts.FindAllReferences {
| { readonly type: DefinitionKind.This; readonly node: Node }
| { readonly type: DefinitionKind.String; readonly node: StringLiteral };
export const enum EntryKind { Span, Node, StringLiteral, SearchedLocalFoundProperty, SearchedPropertyFoundLocal }
export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal;
export type Entry = NodeEntry | SpanEntry;
export interface NodeEntry {
type: "node";
node: Node;
isInString?: true;
readonly kind: NodeEntryKind;
readonly node: Node;
}
export interface SpanEntry {
type: "span";
fileName: string;
textSpan: TextSpan;
readonly kind: EntryKind.Span;
readonly fileName: string;
readonly textSpan: TextSpan;
}
export function nodeEntry(node: Node, isInString?: true): NodeEntry {
return { type: "node", node: (node as NamedDeclaration).name || node, isInString };
export function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry {
return { kind, node: (node as NamedDeclaration).name || node };
}
export interface Options {
@@ -33,7 +34,7 @@ namespace ts.FindAllReferences {
readonly findInComments?: boolean;
/**
* True if we are renaming the symbol.
* If so, we will find fewer references -- if it is referenced by several different names, we sill only find references for the original name.
* If so, we will find fewer references -- if it is referenced by several different names, we still only find references for the original name.
*/
readonly isForRename?: boolean;
/** True if we are searching for implementations. We will have a different method of adding references if so. */
@@ -84,10 +85,15 @@ namespace ts.FindAllReferences {
}
}
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number, options: Options | undefined): ReferenceEntry[] | undefined {
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), toReferenceEntry);
export function findReferenceOrRenameEntries<T>(
program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, node: Node, position: number, options: Options | undefined,
convertEntry: ToReferenceOrRenameEntry<T>,
): T[] | undefined {
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node));
}
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 {
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
}
@@ -137,32 +143,70 @@ 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 };
}
function toReferenceEntry(entry: Entry): ReferenceEntry {
if (entry.type === "span") {
return { textSpan: entry.textSpan, fileName: entry.fileName, isWriteAccess: false, isDefinition: false };
}
export function toRenameLocation(entry: Entry, originalNode: Node): RenameLocation {
return { ...entryToDocumentSpan(entry), ...getPrefixAndSuffixText(entry, originalNode) };
}
const { node, isInString } = entry;
const sourceFile = node.getSourceFile();
export function toReferenceEntry(entry: Entry): ReferenceEntry {
const { textSpan, fileName } = entryToDocumentSpan(entry);
if (entry.kind === EntryKind.Span) {
return { textSpan, fileName, isWriteAccess: false, isDefinition: false };
}
const { kind, node } = entry;
return {
fileName: sourceFile.fileName,
textSpan: getTextSpan(node, sourceFile),
textSpan,
fileName,
isWriteAccess: isWriteAccessForReference(node),
isDefinition: node.kind === SyntaxKind.DefaultKeyword
|| !!getDeclarationFromName(node)
|| isLiteralComputedPropertyDeclarationName(node),
isInString,
isInString: kind === EntryKind.StringLiteral ? true : undefined,
};
}
function entryToDocumentSpan(entry: Entry): DocumentSpan {
if (entry.kind === EntryKind.Span) {
return { textSpan: entry.textSpan, fileName: entry.fileName };
}
else {
const sourceFile = entry.node.getSourceFile();
return { textSpan: getTextSpan(entry.node, sourceFile), fileName: sourceFile.fileName };
}
}
function getPrefixAndSuffixText(entry: Entry, originalNode: Node): { readonly prefixText?: string, readonly suffixText?: string } {
if (entry.kind !== EntryKind.Span && isIdentifier(originalNode)) {
const { node, kind } = entry;
const name = originalNode.text;
const isShorthandAssignment = isShorthandPropertyAssignment(node.parent);
if (isShorthandAssignment || isObjectBindingElementWithoutPropertyName(node.parent)) {
if (kind === EntryKind.SearchedLocalFoundProperty) {
return { prefixText: name + ": " };
}
else if (kind === EntryKind.SearchedPropertyFoundLocal) {
return { suffixText: ": " + name };
}
else {
return isShorthandAssignment
// In `const o = { x }; o.x`, symbolAtLocation at `x` in `{ x }` is the property symbol.
? { suffixText: ": " + name }
// For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol.
: { prefixText: name + ": " };
}
}
}
return emptyOptions;
}
function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation {
if (entry.type === "node") {
if (entry.kind !== EntryKind.Span) {
const { node } = entry;
const sourceFile = node.getSourceFile();
return { textSpan: getTextSpan(node, sourceFile), fileName: sourceFile.fileName, ...implementationKindDisplayParts(node, checker) };
@@ -196,18 +240,18 @@ namespace ts.FindAllReferences {
}
export function toHighlightSpan(entry: Entry): { fileName: string, span: HighlightSpan } {
if (entry.type === "span") {
if (entry.kind === EntryKind.Span) {
const { fileName, textSpan } = entry;
return { fileName, span: { textSpan, kind: HighlightSpanKind.reference } };
}
const { node, isInString } = entry;
const { node, kind } = entry;
const sourceFile = node.getSourceFile();
const writeAccess = isWriteAccessForReference(node);
const span: HighlightSpan = {
textSpan: getTextSpan(node, sourceFile),
kind: writeAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference,
isInString
isInString: kind === EntryKind.StringLiteral ? true : undefined,
};
return { fileName: sourceFile.fileName, span };
}
@@ -348,11 +392,11 @@ namespace ts.FindAllReferences.Core {
}
}
// import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
return { type: "node", node: reference.literal };
return nodeEntry(reference.literal);
}
else {
return {
type: "span",
kind: EntryKind.Span,
fileName: reference.referencingFile.fileName,
textSpan: createTextSpanFromRange(reference.ref),
};
@@ -366,7 +410,7 @@ namespace ts.FindAllReferences.Core {
break;
case SyntaxKind.ModuleDeclaration:
if (sourceFilesSet.has(decl.getSourceFile().fileName)) {
references.push({ type: "node", node: (decl as ModuleDeclaration).name });
references.push(nodeEntry((decl as ModuleDeclaration).name));
}
break;
default:
@@ -422,7 +466,7 @@ namespace ts.FindAllReferences.Core {
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
}
else {
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] });
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.isForRename, !!options.implementations) : [symbol] });
// Try to get the smallest valid scope that we can limit our search to;
// otherwise we'll need to search globally (i.e. include each file).
@@ -581,21 +625,21 @@ namespace ts.FindAllReferences.Core {
* Callback to add references for a particular searched symbol.
* This initializes a reference group, so only call this if you will add at least one reference.
*/
referenceAdder(searchSymbol: Symbol): (node: Node) => void {
referenceAdder(searchSymbol: Symbol): (node: Node, kind?: NodeEntryKind) => void {
const symbolId = getSymbolId(searchSymbol);
let references = this.symbolIdToReferences[symbolId];
if (!references) {
references = this.symbolIdToReferences[symbolId] = [];
this.result.push({ definition: { type: DefinitionKind.Symbol, symbol: searchSymbol }, references });
}
return node => references.push(nodeEntry(node));
return (node, kind) => references.push(nodeEntry(node, kind));
}
/** Add a reference with no associated definition. */
addStringOrCommentReference(fileName: string, textSpan: TextSpan): void {
this.result.push({
definition: undefined,
references: [{ type: "span", fileName, textSpan }]
references: [{ kind: EntryKind.Span, fileName, textSpan }]
});
}
@@ -707,21 +751,6 @@ namespace ts.FindAllReferences.Core {
: undefined;
}
function getObjectBindingElementWithoutPropertyName(symbol: Symbol): BindingElement & { name: Identifier } | undefined {
const bindingElement = getDeclarationOfKind<BindingElement>(symbol, SyntaxKind.BindingElement);
if (bindingElement &&
bindingElement.parent.kind === SyntaxKind.ObjectBindingPattern &&
isIdentifier(bindingElement.name) &&
!bindingElement.propertyName) {
return bindingElement as BindingElement & { name: Identifier };
}
}
function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined {
const bindingElement = getObjectBindingElementWithoutPropertyName(symbol);
return bindingElement && getPropertySymbolFromBindingElement(checker, bindingElement);
}
/**
* Determines the smallest scope in which a symbol may have named references.
* Note that not every construct has been accounted for. This function can
@@ -754,7 +783,7 @@ namespace ts.FindAllReferences.Core {
// If symbol is of object binding pattern element without property name we would want to
// look for property too and that could be anywhere
if (getObjectBindingElementWithoutPropertyName(symbol)) {
if (declarations.some(isObjectBindingElementWithoutPropertyName)) {
return undefined;
}
@@ -1099,13 +1128,14 @@ namespace ts.FindAllReferences.Core {
}
}
function addReference(referenceLocation: Node, relatedSymbol: Symbol, state: State): void {
const addRef = state.referenceAdder(relatedSymbol);
function addReference(referenceLocation: Node, relatedSymbol: Symbol | RelatedSymbol, state: State): void {
const { kind, symbol } = "kind" in relatedSymbol ? relatedSymbol : { kind: undefined, symbol: relatedSymbol };
const addRef = state.referenceAdder(symbol);
if (state.options.implementations) {
addImplementationReferences(referenceLocation, addRef, state);
}
else {
addRef(referenceLocation);
addRef(referenceLocation, kind);
}
}
@@ -1428,7 +1458,7 @@ namespace ts.FindAllReferences.Core {
const references = flatMap(sourceFiles, sourceFile => {
cancellationToken.throwIfCancellationRequested();
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref =>
isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, /*isInString*/ true) : undefined);
isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, EntryKind.StringLiteral) : undefined);
});
return [{
@@ -1439,35 +1469,21 @@ namespace ts.FindAllReferences.Core {
// For certain symbol kinds, we need to include other symbols in the search set.
// This is not needed when searching for re-exports.
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, implementations: boolean): Symbol[] {
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, implementations: boolean): Symbol[] {
const result: Symbol[] = [];
forEachRelatedSymbol<void>(symbol, location, checker,
forEachRelatedSymbol<void>(symbol, location, checker, isForRename,
(sym, root, base) => { result.push(base || root || sym); },
/*allowBaseTypes*/ () => !implementations);
return result;
}
function forEachRelatedSymbol<T>(
symbol: Symbol, location: Node, checker: TypeChecker,
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol) => T | undefined,
symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean,
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol, kind?: NodeEntryKind) => T | undefined,
allowBaseTypes: (rootSymbol: Symbol) => boolean,
): T | undefined {
const containingObjectLiteralElement = getContainingObjectLiteralElement(location);
if (containingObjectLiteralElement) {
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
const contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
const res = contextualType && firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), fromRoot);
if (res) return res;
// If the location is name of property symbol from object literal destructuring pattern
// Search the property symbol
// for ( { property: p2 } of elems) { }
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
const res1 = propertySymbol && cbSymbol(propertySymbol);
if (res1) return res1;
/* Because in short-hand property assignment, location has two meaning : property name and as value of the property
* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
* property name and variable declaration of the identifier.
@@ -1479,8 +1495,29 @@ namespace ts.FindAllReferences.Core {
* so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
* will be included correctly.
*/
const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent);
const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol);
const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); // gets the local symbol
if (shorthandValueSymbol && isForRenamePopulateSearchSymbolSet) {
// When renaming 'x' in `const o = { x }`, just rename the local variable, not the property.
return cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty);
}
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
const contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
const res = contextualType && firstDefined(
getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true),
sym => fromRoot(sym, EntryKind.SearchedPropertyFoundLocal));
if (res) return res;
// If the location is name of property symbol from object literal destructuring pattern
// Search the property symbol
// for ( { property: p2 } of elems) { }
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
const res1 = propertySymbol && cbSymbol(propertySymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedPropertyFoundLocal);
if (res1) return res1;
const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, EntryKind.SearchedLocalFoundProperty);
if (res2) return res2;
}
@@ -1494,12 +1531,14 @@ namespace ts.FindAllReferences.Core {
return fromRoot(symbol.flags & SymbolFlags.FunctionScopedVariable ? paramProps[1] : paramProps[0]);
}
// If this is symbol of binding element without propertyName declaration in Object binding pattern
// Include the property in the search
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol);
// symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
// Don't do this when populating search set for a rename -- just rename the local.
if (!isForRenamePopulateSearchSymbolSet) {
const bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal);
}
function fromRoot(sym: Symbol): T | undefined {
function fromRoot(sym: Symbol, kind?: NodeEntryKind): T | undefined {
// If this is a union property:
// - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types.
// - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search.
@@ -1507,20 +1546,24 @@ namespace ts.FindAllReferences.Core {
// - In populateSearchSymbolsSet, add the root the list
// - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.)
return firstDefined(checker.getRootSymbols(sym), rootSymbol =>
cbSymbol(sym, rootSymbol)
cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind)
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
|| (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface) && allowBaseTypes(rootSymbol)
? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base))
? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base, kind))
: undefined));
}
}
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): Symbol | undefined {
interface RelatedSymbol {
readonly symbol: Symbol;
readonly kind: NodeEntryKind | undefined;
}
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined {
const { checker } = state;
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker,
(sym, rootSymbol, baseSymbol) => search.includes(baseSymbol || rootSymbol || sym)
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
(sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => search.includes(baseSymbol || rootSymbol || sym)
// For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
? rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
: undefined,
/*allowBaseTypes*/ rootSymbol =>
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker))));
+3 -3
View File
@@ -753,17 +753,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);
}
+1 -1
View File
@@ -72,7 +72,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") {
+1 -1
View File
@@ -385,7 +385,7 @@ namespace ts.FindAllReferences {
}
/** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T): T | undefined {
function forEachPossibleImportOrExportStatement<T>(sourceFileLike: SourceFileLike, action: (statement: Statement) => T) {
return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217
action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action)));
}
+33 -8
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);
@@ -631,28 +634,50 @@ namespace ts.NavigationBar {
}
function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string {
const { parent } = node;
if (node.name && getFullWidth(node.name) > 0) {
return declarationNameToString(node.name);
}
// See if it is a var initializer. If so, use the var name.
else if (node.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((node.parent as VariableDeclaration).name);
else if (isVariableDeclaration(parent)) {
return declarationNameToString(parent.name);
}
// See if it is of the form "<expr> = function(){...}". If so, use the text from the left-hand side.
else if (node.parent.kind === SyntaxKind.BinaryExpression &&
(node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
return nodeText((node.parent as BinaryExpression).left).replace(whiteSpaceRegex, "");
else if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken) {
return nodeText(parent.left).replace(whiteSpaceRegex, "");
}
// See if it is a property assignment, and if so use the property name
else if (node.parent.kind === SyntaxKind.PropertyAssignment && (node.parent as PropertyAssignment).name) {
return nodeText((node.parent as PropertyAssignment).name);
else if (isPropertyAssignment(parent)) {
return nodeText(parent.name);
}
// Default exports are named "default"
else if (getModifierFlags(node) & ModifierFlags.Default) {
return "default";
}
else if (isClassLike(node)) {
return "<class>";
}
else if (isCallExpression(parent)) {
const name = getCalledExpressionName(parent.expression);
if (name !== undefined) {
const args = mapDefined(parent.arguments, a => isStringLiteral(a) ? a.getText(curSourceFile) : undefined).join(", ");
return `${name}(${args}) callback`;
}
}
return "<function>";
}
function getCalledExpressionName(expr: Expression): string | undefined {
if (isIdentifier(expr)) {
return expr.text;
}
else if (isPropertyAccessExpression(expr)) {
const left = getCalledExpressionName(expr.expression);
const right = expr.name.text;
return left === undefined ? right : `${left}.${right}`;
}
else {
return isClassLike(node) ? "<class>" : "<function>";
return undefined;
}
}
@@ -226,7 +226,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
const { file, program, cancellationToken } = context;
const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken!), entry => // TODO: GH#18217
(entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined);
(entry.kind !== FindAllReferences.EntryKind.Span && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined);
forEach(referenceEntries, entry => {
const parent = entry.parent;
+24 -5
View File
@@ -158,7 +158,7 @@ namespace ts.refactor {
const shouldMove = (name: Identifier): boolean => {
const symbol = isBindingElement(name.parent)
? getPropertySymbolFromBindingElement(checker, name.parent as BindingElement & { name: Identifier })
? getPropertySymbolFromBindingElement(checker, name.parent as ObjectBindingElementWithoutPropertyName)
: skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217
return !!symbol && movedSymbols.has(symbol);
};
@@ -612,7 +612,7 @@ namespace ts.refactor {
| ImportEqualsDeclaration;
type TopLevelDeclarationStatement = NonVariableTopLevelDeclaration | VariableStatement;
interface TopLevelVariableDeclaration extends VariableDeclaration { parent: VariableDeclarationList & { parent: VariableStatement; }; }
type TopLevelDeclaration = NonVariableTopLevelDeclaration | TopLevelVariableDeclaration;
type TopLevelDeclaration = NonVariableTopLevelDeclaration | TopLevelVariableDeclaration | BindingElement;
function isTopLevelDeclaration(node: Node): node is TopLevelDeclaration {
return isNonVariableTopLevelDeclaration(node) && isSourceFile(node.parent) || isVariableDeclaration(node) && isSourceFile(node.parent.parent.parent);
}
@@ -653,7 +653,7 @@ namespace ts.refactor {
return cb(statement as FunctionDeclaration | ClassDeclaration | EnumDeclaration | ModuleDeclaration | TypeAliasDeclaration | InterfaceDeclaration | ImportEqualsDeclaration);
case SyntaxKind.VariableStatement:
return forEach((statement as VariableStatement).declarationList.declarations as ReadonlyArray<TopLevelVariableDeclaration>, cb);
return firstDefined((statement as VariableStatement).declarationList.declarations, decl => forEachTopLevelDeclarationInBindingName(decl.name, cb));
case SyntaxKind.ExpressionStatement: {
const { expression } = statement as ExpressionStatement;
@@ -663,13 +663,32 @@ namespace ts.refactor {
}
}
}
function forEachTopLevelDeclarationInBindingName<T>(name: BindingName, cb: (node: TopLevelDeclaration) => T): T | undefined {
switch (name.kind) {
case SyntaxKind.Identifier:
return cb(cast(name.parent, (x): x is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(x) || isBindingElement(x)));
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ObjectBindingPattern:
return firstDefined(name.elements, em => isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb));
default:
return Debug.assertNever(name);
}
}
function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined {
return d.kind === SyntaxKind.ExpressionStatement ? d.expression.left.name : tryCast(d.name, isIdentifier);
return isExpressionStatement(d) ? d.expression.left.name : tryCast(d.name, isIdentifier);
}
function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement {
return isVariableDeclaration(d) ? d.parent.parent : d;
switch (d.kind) {
case SyntaxKind.VariableDeclaration:
return d.parent.parent;
case SyntaxKind.BindingElement:
return getTopLevelDeclarationStatement(
cast(d.parent.parent, (p): p is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(p) || isBindingElement(p)));
default:
return d;
}
}
function addExportToChanges(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, changes: textChanges.ChangeTracker, useEs6Exports: boolean): void {
+11 -15
View File
@@ -39,47 +39,43 @@ namespace ts.Rename {
}
function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined {
if (!isExternalModuleNameRelative(node.text)) {
return getRenameInfoError(Diagnostics.You_cannot_rename_a_module_via_a_global_import);
}
const moduleSourceFile = find(moduleSymbol.declarations, isSourceFile);
if (!moduleSourceFile) return undefined;
const withoutIndex = node.text.endsWith("/index") || node.text.endsWith("/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index");
const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex;
const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory;
const indexAfterLastSlash = node.text.lastIndexOf("/") + 1;
// Span should only be the last component of the path. + 1 to account for the quote character.
const triggerSpan = createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash);
return {
canRename: true,
fileToRename: name,
kind,
displayName: name,
localizedErrorMessage: undefined,
fullDisplayName: name,
kindModifiers: ScriptElementKindModifier.none,
triggerSpan: createTriggerSpanForNode(node, sourceFile),
triggerSpan,
};
}
function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfo {
function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfoSuccess {
return {
canRename: true,
fileToRename: undefined,
kind,
displayName,
localizedErrorMessage: undefined,
fullDisplayName,
kindModifiers,
triggerSpan: createTriggerSpanForNode(node, sourceFile)
};
}
function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfo {
// TODO: GH#18217
return {
canRename: false,
localizedErrorMessage: getLocaleSpecificMessage(diagnostic),
displayName: undefined!,
fullDisplayName: undefined!,
kind: undefined!,
kindModifiers: undefined!,
triggerSpan: undefined!
};
function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfoFailure {
return { canRename: false, localizedErrorMessage: getLocaleSpecificMessage(diagnostic) };
}
function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) {
+37 -21
View File
@@ -541,6 +541,7 @@ namespace ts {
public fileName: string;
public path: Path;
public resolvedPath: Path;
public originalFileName: string;
public text: string;
public scriptSnapshot: IScriptSnapshot;
public lineMap: ReadonlyArray<number>;
@@ -1218,6 +1219,10 @@ namespace ts {
getDirectories: path => {
return host.getDirectories ? host.getDirectories(path) : [];
},
readDirectory(path, extensions, exclude, include, depth) {
Debug.assertDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'");
return host.readDirectory!(path, extensions, exclude, include, depth);
},
onReleaseOldSourceFile,
hasInvalidatedResolution,
hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames
@@ -1227,11 +1232,11 @@ namespace ts {
}
if (host.resolveModuleNames) {
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames);
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames, redirectedReference);
}
if (host.resolveTypeReferenceDirectives) {
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => {
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile);
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile, redirectedReference) => {
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile, redirectedReference);
};
}
@@ -1271,7 +1276,7 @@ namespace ts {
// not part of the new program.
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions);
documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey);
documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey);
}
function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
@@ -1378,7 +1383,7 @@ namespace ts {
// Therefore only get diagnostics for given file.
const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
if (!program.getCompilerOptions().declaration) {
if (!getEmitDeclarations(program.getCompilerOptions())) {
return semanticDiagnostics.slice();
}
@@ -1539,20 +1544,20 @@ namespace ts {
const node = getTouchingPropertyName(sourceFile, position);
if (isIdentifier(node) && isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) {
const { openingElement, closingElement } = node.parent.parent;
return [openingElement, closingElement].map((node): RenameLocation => ({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
return [openingElement, closingElement].map((node): RenameLocation =>
({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
}
else {
const refs = getReferences(node, position, { findInStrings, findInComments, isForRename: true });
return refs && refs.map(({ fileName, textSpan }): RenameLocation => ({ fileName, textSpan }));
return getReferencesWorker(node, position, { findInStrings, findInComments, isForRename: true }, FindAllReferences.toRenameLocation);
}
}
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
synchronizeHostData();
return getReferences(getTouchingPropertyName(getValidSourceFile(fileName), position), position);
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, {}, FindAllReferences.toReferenceEntry);
}
function getReferences(node: Node, position: number, options?: FindAllReferences.Options): ReferenceEntry[] | undefined {
function getReferencesWorker<T>(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry<T>): T[] | undefined {
synchronizeHostData();
// Exclude default library when renaming as commonly user don't want to change that file.
@@ -1560,7 +1565,7 @@ namespace ts {
? program.getSourceFiles().filter(sourceFile => !program.isSourceFileDefaultLibrary(sourceFile))
: program.getSourceFiles();
return FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, node, position, options);
return FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb);
}
function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined {
@@ -1804,25 +1809,36 @@ namespace ts {
return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions), preferences, sourceMapper);
}
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
function applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>;
function applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrUndefined?: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]> {
const action = typeof fileName === "string" ? actionOrUndefined! : fileName as CodeActionCommand[];
return isArray(action) ? Promise.all(action.map(applySingleCodeActionCommand)) : applySingleCodeActionCommand(action);
function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]> {
const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] : fileName as CodeActionCommand[];
const formatSettings = typeof fileName !== "string" ? actionOrFormatSettingsOrUndefined as FormatCodeSettings : undefined;
return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a, formatSettings))) : applySingleCodeActionCommand(action, formatSettings);
}
function applySingleCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult> {
function applySingleCodeActionCommand(action: CodeActionCommand, formatSettings: FormatCodeSettings | undefined): Promise<ApplyCodeActionCommandResult> {
const getPath = (path: string): Path => toPath(path, currentDirectory, getCanonicalFileName);
switch (action.type) {
case "install package":
return host.installPackage
? host.installPackage({ fileName: toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName })
? host.installPackage({ fileName: getPath(action.file), packageName: action.packageName })
: Promise.reject("Host does not implement `installPackage`");
case "generate types": {
const { fileToGenerateTypesFor, outputFileName } = action;
if (!host.inspectValue) return Promise.reject("Host does not implement `installPackage`");
const valueInfoPromise = host.inspectValue({ fileNameToRequire: fileToGenerateTypesFor });
return valueInfoPromise.then(valueInfo => {
const fullOut = getPath(outputFileName);
host.writeFile!(fullOut, valueInfoToDeclarationFileText(valueInfo, formatSettings || testFormatSettings)); // TODO: GH#18217
return { successMessage: `Wrote types to '${fullOut}'` };
});
}
default:
return Debug.fail();
// TODO: Debug.assertNever(action); will only work if there is more than one type.
return Debug.assertNever(action);
}
}
+4 -3
View File
@@ -38,7 +38,8 @@ namespace ts.SignatureHelp {
return undefined;
}
const argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile, typeChecker);
const isManuallyInvoked = !!triggerReason && triggerReason.kind === "invoked";
const argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile, typeChecker, isManuallyInvoked);
if (!argumentInfo) return undefined;
cancellationToken.throwIfCancellationRequested();
@@ -450,8 +451,8 @@ namespace ts.SignatureHelp {
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined {
for (let n = node; !isBlock(n) && !isSourceFile(n); n = n.parent) {
function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker, isManuallyInvoked: boolean): ArgumentListInfo | undefined {
for (let n = node; isManuallyInvoked || (!isBlock(n) && !isSourceFile(n)); n = n.parent) {
// If the node is not a subspan of its parent, this is a big problem.
// There have been crashes that might be caused by this violation.
Debug.assert(rangeContainsRange(n.parent, n), "Not a subspan", () => `Child: ${Debug.showSyntaxKind(n)}, parent: ${Debug.showSyntaxKind(n.parent)}`);
+1 -1
View File
@@ -82,7 +82,7 @@ namespace ts {
switch (statement.kind) {
case SyntaxKind.VariableStatement:
return (statement as VariableStatement).declarationList.declarations.some(decl =>
isRequireCall(propertyAccessLeftHandSide(decl.initializer!), /*checkArgumentIsStringLiteralLike*/ true)); // TODO: GH#18217
!!decl.initializer && isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true));
case SyntaxKind.ExpressionStatement: {
const { expression } = statement as ExpressionStatement;
if (!isBinaryExpression(expression)) return isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true);
+101 -23
View File
@@ -209,10 +209,16 @@ namespace ts.textChanges {
export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature;
interface JSDocParameter {
declaration: ParameterDeclaration;
typeNode: TypeNode;
isOptional?: boolean;
}
export class ChangeTracker {
private readonly changes: Change[] = [];
private readonly newFiles: { readonly oldFile: SourceFile, readonly fileName: string, readonly statements: ReadonlyArray<Statement> }[] = [];
private readonly classesWithNodesInsertedAtStart = createMap<ClassDeclaration>(); // Set<ClassDeclaration> implemented as Map<node id, ClassDeclaration>
private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: ReadonlyArray<Statement> }[] = [];
private readonly classesWithNodesInsertedAtStart = createMap<{ readonly node: ClassDeclaration | InterfaceDeclaration | ObjectLiteralExpression, readonly sourceFile: SourceFile }>(); // Set<ClassDeclaration> implemented as Map<node id, ClassDeclaration>
private readonly deletedNodes: { readonly sourceFile: SourceFile, readonly node: Node | NodeArray<TypeParameterDeclaration> }[] = [];
public static fromContext(context: TextChangesContext): ChangeTracker {
@@ -295,7 +301,7 @@ namespace ts.textChanges {
}
private insertNodesAt(sourceFile: SourceFile, pos: number, newNodes: ReadonlyArray<Node>, options: ReplaceWithMultipleNodesOptions = {}): void {
this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, options, nodes: newNodes, range: { pos, end: pos } });
this.replaceRangeWithNodes(sourceFile, createRange(pos), newNodes, options);
}
public insertNodeAtTopOfFile(sourceFile: SourceFile, newNode: Statement, blankLineBetween: boolean): void {
@@ -312,7 +318,17 @@ namespace ts.textChanges {
public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void {
const pos = before.getStart(sourceFile);
this.replaceRange(sourceFile, { pos, end: pos }, createToken(modifier), { suffix: " " });
this.insertNodeAt(sourceFile, pos, createToken(modifier), { suffix: " " });
}
public insertLastModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void {
if (!before.modifiers) {
this.insertModifierBefore(sourceFile, modifier, before);
return;
}
const pos = before.modifiers.end;
this.insertNodeAt(sourceFile, pos, createToken(modifier), { prefix: " " });
}
public insertCommentBeforeLine(sourceFile: SourceFile, lineNumber: number, position: number, commentText: string): void {
@@ -329,6 +345,12 @@ namespace ts.textChanges {
this.insertText(sourceFile, token.getStart(sourceFile), text);
}
public insertCommentThenNewline(sourceFile: SourceFile, character: number, position: number, commentText: string): void {
const token = getTouchingToken(sourceFile, position);
const text = "/**" + commentText + "*/" + this.newLineCharacter + repeatString(" ", character);
this.insertText(sourceFile, token.getStart(sourceFile), text);
}
public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string) {
this.changes.push({ kind: ChangeKind.Text, sourceFile, range, text });
}
@@ -337,6 +359,23 @@ namespace ts.textChanges {
this.replaceRangeWithText(sourceFile, createRange(pos), text);
}
public tryInsertJSDocParameters(sourceFile: SourceFile, parameters: JSDocParameter[]) {
if (parameters.length === 0) {
return;
}
const parent = parameters[0].declaration.parent;
const indent = getLineAndCharacterOfPosition(sourceFile, parent.getStart()).character;
let commentText = "\n";
for (const { declaration, typeNode, isOptional } of parameters) {
if (isIdentifier(declaration.name)) {
const printed = changesToText.getNonformattedText(typeNode, sourceFile, this.newLineCharacter).text;
commentText += this.printJSDocParameter(indent, printed, declaration.name, isOptional);
}
}
commentText += repeatString(" ", indent + 1);
this.insertCommentThenNewline(sourceFile, indent, parent.getStart(), commentText);
}
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
public tryInsertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void {
let endNode: Node | undefined;
@@ -355,6 +394,27 @@ namespace ts.textChanges {
this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " });
}
public tryInsertJSDocType(sourceFile: SourceFile, node: Node, type: TypeNode): void {
const printed = changesToText.getNonformattedText(type, sourceFile, this.newLineCharacter).text;
let commentText;
if (isGetAccessorDeclaration(node)) {
commentText = ` @return {${printed}} `;
}
else {
commentText = ` @type {${printed}} `;
node = node.parent;
}
this.insertCommentThenNewline(sourceFile, getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).character, node.getStart(sourceFile), commentText);
}
private printJSDocParameter(indent: number, printed: string, name: Identifier, isOptionalParameter: boolean | undefined) {
let printName = unescapeLeadingUnderscores(name.escapedText);
if (isOptionalParameter) {
printName = `[${printName}]`;
}
return repeatString(" ", indent) + ` * @param {${printed}} ${printName}\n`;
}
public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: ReadonlyArray<TypeParameterDeclaration>): void {
// If no `(`, is an arrow function `x => x`, so use the pos of the first parameter
const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart(sourceFile);
@@ -403,32 +463,40 @@ namespace ts.textChanges {
public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void {
const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}, Position.Start);
this.replaceRange(sourceFile, { pos, end: pos }, newNode, {
this.insertNodeAt(sourceFile, pos, newNode, {
prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
suffix: this.newLineCharacter
});
}
public insertNodeAtClassStart(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void {
this.insertNodeAtStartWorker(sourceFile, cls, newElement);
}
public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void {
this.insertNodeAtStartWorker(sourceFile, obj, newElement);
}
private insertNodeAtStartWorker(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, newElement: ClassElement | ObjectLiteralElementLike): void {
const clsStart = cls.getStart(sourceFile);
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options)
+ this.formatContext.options.indentSize!;
this.insertNodeAt(sourceFile, cls.members.pos, newElement, { indentation, ...this.getInsertNodeAtClassStartPrefixSuffix(sourceFile, cls) });
this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, { indentation, ...this.getInsertNodeAtStartPrefixSuffix(sourceFile, cls) });
}
private getInsertNodeAtClassStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration): { prefix: string, suffix: string } {
if (cls.members.length === 0) {
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), cls)) {
private getInsertNodeAtStartPrefixSuffix(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): { prefix: string, suffix: string } {
const comma = isObjectLiteralExpression(cls) ? "," : "";
if (getMembersOrProperties(cls).length === 0) {
if (addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(cls), { node: cls, sourceFile })) {
// For `class C {\n}`, don't add the trailing "\n"
const shouldSuffix = (positionsAreOnSameLine as any)(...getClassBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any'
return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" };
const shouldSuffix = (positionsAreOnSameLine as any)(...getClassOrObjectBraceEnds(cls, sourceFile), sourceFile); // TODO: GH#4130 remove 'as any'
return { prefix: this.newLineCharacter, suffix: comma + (shouldSuffix ? this.newLineCharacter : "") };
}
else {
return { prefix: "", suffix: this.newLineCharacter };
return { prefix: "", suffix: comma + this.newLineCharacter };
}
}
else {
return { prefix: this.newLineCharacter, suffix: "" };
return { prefix: this.newLineCharacter, suffix: comma };
}
}
@@ -647,9 +715,8 @@ namespace ts.textChanges {
}
private finishClassesWithNodesInsertedAtStart(): void {
this.classesWithNodesInsertedAtStart.forEach(cls => {
const sourceFile = cls.getSourceFile();
const [openBraceEnd, closeBraceEnd] = getClassBraceEnds(cls, sourceFile);
this.classesWithNodesInsertedAtStart.forEach(({ node, sourceFile }) => {
const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile);
// For `class C { }` remove the whitespace inside the braces.
if (positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) {
this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1));
@@ -698,7 +765,7 @@ namespace ts.textChanges {
return changes;
}
public createNewFile(oldFile: SourceFile, fileName: string, statements: ReadonlyArray<Statement>) {
public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>) {
this.newFiles.push({ oldFile, fileName, statements });
}
}
@@ -708,12 +775,19 @@ namespace ts.textChanges {
return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
}
function getClassBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration, sourceFile: SourceFile): [number, number] {
function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number, number] {
return [findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile)!.end, findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)!.end];
}
function getMembersOrProperties(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression): NodeArray<Node> {
return isObjectLiteralExpression(cls) ? cls.properties : cls.members;
}
export type ValidateNonFormattedText = (node: Node, text: string) => void;
export function getNewFileText(statements: ReadonlyArray<Statement>, scriptKind: ScriptKind, newLineCharacter: string, formatContext: formatting.FormatContext): string {
return changesToText.newFileChangesWorker(/*oldFile*/ undefined, scriptKind, statements, newLineCharacter, formatContext);
}
namespace changesToText {
export function getTextChangesFromChanges(changes: ReadonlyArray<Change>, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] {
return group(changes, c => c.sourceFile.path).map(changesInFile => {
@@ -732,13 +806,17 @@ namespace ts.textChanges {
});
}
export function newFileChanges(oldFile: SourceFile, fileName: string, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges {
export function newFileChanges(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges {
const text = newFileChangesWorker(oldFile, getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext);
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
}
export function newFileChangesWorker(oldFile: SourceFile | undefined, scriptKind: ScriptKind, statements: ReadonlyArray<Statement>, newLineCharacter: string, formatContext: formatting.FormatContext): string {
// TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this
const nonFormattedText = statements.map(s => getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter);
const sourceFile = createSourceFile(fileName, nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true);
const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind);
const changes = formatting.formatDocument(sourceFile, formatContext);
const text = applyChanges(nonFormattedText, changes);
return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true };
return applyChanges(nonFormattedText, changes);
}
function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
@@ -778,7 +856,7 @@ namespace ts.textChanges {
}
/** Note: output node may be mutated input node. */
function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } {
export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } {
const writer = new Writer(newLineCharacter);
const newLine = newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed;
createPrinter({ newLine, neverAsciiEscape: true }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
+1
View File
@@ -48,6 +48,7 @@ namespace ts {
options.paths = undefined;
options.rootDirs = undefined;
options.declaration = undefined;
options.composite = undefined;
options.declarationDir = undefined;
options.out = undefined;
options.outFile = undefined;
+2 -1
View File
@@ -69,6 +69,7 @@
"codefixes/inferFromUsage.ts",
"codefixes/fixInvalidImportSyntax.ts",
"codefixes/fixStrictClassInitialization.ts",
"codefixes/generateTypes.ts",
"codefixes/requireInTs.ts",
"codefixes/useDefaultImport.ts",
"codefixes/fixAddModuleReferTypeMissingTypeof.ts",
@@ -82,6 +83,6 @@
"services.ts",
"breakpoints.ts",
"transform.ts",
"shims.ts"
"shims.ts",
]
}
+55 -12
View File
@@ -212,9 +212,9 @@ namespace ts {
*
* If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too.
*/
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[];
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): ResolvedModule[];
getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): ResolvedTypeReferenceDirective[];
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
@@ -231,6 +231,8 @@ namespace ts {
isKnownTypesPackageName?(name: string): boolean;
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
/* @internal */ inspectValue?(options: InspectValueOptions): Promise<ValueInfo>;
writeFile?(fileName: string, content: string): void;
}
/* @internal */
@@ -331,9 +333,9 @@ namespace ts {
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 */
@@ -526,12 +528,22 @@ namespace ts {
// Publicly, this type is just `{}`. Internally it is a union of all the actions we use.
// See `commands?: {}[]` in protocol.ts
export type CodeActionCommand = InstallPackageAction;
export type CodeActionCommand = InstallPackageAction | GenerateTypesAction;
export interface InstallPackageAction {
/* @internal */ file: string;
/* @internal */ type: "install package";
/* @internal */ packageName: string;
/* @internal */ readonly type: "install package";
/* @internal */ readonly file: string;
/* @internal */ readonly packageName: string;
}
export interface GenerateTypesAction extends GenerateTypesOptions {
/* @internal */ readonly type: "generate types";
}
export interface GenerateTypesOptions {
readonly file: string; // File that was importing fileToGenerateTypesFor; used for formatting options.
readonly fileToGenerateTypesFor: string;
readonly outputFileName: string;
}
/**
@@ -607,6 +619,8 @@ namespace ts {
}
export interface RenameLocation extends DocumentSpan {
readonly prefixText?: string;
readonly suffixText?: string;
}
export interface ReferenceEntry extends DocumentSpan {
@@ -717,6 +731,31 @@ namespace ts {
indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
}
/* @internal */
export const testFormatSettings: FormatCodeSettings = {
baseIndentSize: 0,
indentSize: 4,
tabSize: 4,
newLineCharacter: "\n",
convertTabsToSpaces: true,
indentStyle: IndentStyle.Smart,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterConstructor: false,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceAfterTypeAssertion: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
insertSpaceBeforeTypeAnnotation: false
};
export interface DefinitionInfo extends DocumentSpan {
kind: ScriptElementKind;
name: string;
@@ -782,20 +821,24 @@ namespace ts {
tags?: JSDocTagInfo[];
}
export interface RenameInfo {
canRename: boolean;
export type RenameInfo = RenameInfoSuccess | RenameInfoFailure;
export interface RenameInfoSuccess {
canRename: true;
/**
* File or directory to rename.
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
*/
fileToRename?: string;
localizedErrorMessage?: string;
displayName: string;
fullDisplayName: string;
kind: ScriptElementKind;
kindModifiers: string;
triggerSpan: TextSpan;
}
export interface RenameInfoFailure {
canRename: false;
localizedErrorMessage: string;
}
export interface SignatureHelpParameter {
name: string;
+14 -8
View File
@@ -368,6 +368,9 @@ namespace ts {
const kind = getAssignmentDeclarationKind(node as BinaryExpression);
const { right } = node as BinaryExpression;
switch (kind) {
case AssignmentDeclarationKind.ObjectDefinePropertyValue:
case AssignmentDeclarationKind.ObjectDefinePropertyExports:
case AssignmentDeclarationKind.ObjectDefinePrototypeProperty:
case AssignmentDeclarationKind.None:
return ScriptElementKind.unknown;
case AssignmentDeclarationKind.ExportsProperty:
@@ -1325,15 +1328,18 @@ namespace ts {
});
}
export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: BindingElement & { name: Identifier }) {
export type ObjectBindingElementWithoutPropertyName = BindingElement & { name: Identifier };
export function isObjectBindingElementWithoutPropertyName(bindingElement: Node): bindingElement is ObjectBindingElementWithoutPropertyName {
return isBindingElement(bindingElement) &&
isObjectBindingPattern(bindingElement.parent) &&
isIdentifier(bindingElement.name) &&
!bindingElement.propertyName;
}
export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: ObjectBindingElementWithoutPropertyName): Symbol | undefined {
const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent);
const propSymbol = typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text);
if (propSymbol && propSymbol.flags & SymbolFlags.Accessor) {
// See GH#16922
Debug.assert(!!(propSymbol.flags & SymbolFlags.Transient));
return (propSymbol as TransientSymbol).target;
}
return propSymbol;
return typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text);
}
/**
+16 -14
View File
@@ -1,6 +1,6 @@
const fs = require("fs");
const path = require("path");
const del = require("del");
const fs: typeof import("fs") = require("fs");
const path: typeof import("path") = require("path");
const del: typeof import("del") = require("del");
interface ExecResult {
stdout: Buffer;
@@ -40,7 +40,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
const timeout = 600_000; // 10 minutes
describe(directoryName, function(this: Mocha.ISuiteCallbackContext) {
this.timeout(timeout);
const cp = require("child_process");
const cp: typeof import("child_process") = require("child_process");
it("should build successfully", () => {
let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName);
@@ -49,12 +49,9 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
let types: string[] | undefined;
if (fs.existsSync(path.join(cwd, "test.json"))) {
const submoduleDir = path.join(cwd, directoryName);
const reset = cp.spawnSync("git", ["reset", "HEAD", "--hard"], { cwd: submoduleDir, timeout, shell: true, stdio });
if (reset.status !== 0) throw new Error(`git reset for ${directoryName} failed: ${reset.stderr.toString()}`);
const clean = cp.spawnSync("git", ["clean", "-f"], { cwd: submoduleDir, timeout, shell: true, stdio });
if (clean.status !== 0) throw new Error(`git clean for ${directoryName} failed: ${clean.stderr.toString()}`);
const update = cp.spawnSync("git", ["submodule", "update", "--remote", "."], { cwd: submoduleDir, timeout, shell: true, stdio });
if (update.status !== 0) throw new Error(`git submodule update for ${directoryName} failed: ${update.stderr.toString()}`);
exec("git", ["reset", "HEAD", "--hard"], { cwd: submoduleDir });
exec("git", ["clean", "-f"], { cwd: submoduleDir });
exec("git", ["submodule", "update", "--init", "--remote", "."], { cwd: submoduleDir });
const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig;
ts.Debug.assert(!!config.types, "Bad format from test.json: Types field must be present.");
@@ -69,18 +66,23 @@ abstract class ExternalCompileRunnerBase extends RunnerBase {
if (fs.existsSync(path.join(cwd, "node_modules"))) {
del.sync(path.join(cwd, "node_modules"), { force: true });
}
const install = cp.spawnSync(`npm`, ["i", "--ignore-scripts"], { cwd, timeout: timeout / 2, shell: true, stdio }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure
if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed: ${install.stderr.toString()}`);
exec("npm", ["i", "--ignore-scripts"], { cwd, timeout: timeout / 2 }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure
}
const args = [path.join(Harness.IO.getWorkspaceRoot(), "built/local/tsc.js")];
if (types) {
args.push("--types", types.join(","));
// Also actually install those types (for, eg, the js projects which need node)
const install = cp.spawnSync(`npm`, ["i", ...types.map(t => `@types/${t}`), "--no-save", "--ignore-scripts"], { cwd: originalCwd, timeout: timeout / 2, shell: true, stdio }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure
if (install.status !== 0) throw new Error(`NPM Install types for ${directoryName} failed: ${install.stderr.toString()}`);
exec("npm", ["i", ...types.map(t => `@types/${t}`), "--no-save", "--ignore-scripts"], { cwd: originalCwd, timeout: timeout / 2 }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure
}
args.push("--noEmit");
Harness.Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, cls.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd));
function exec(command: string, args: string[], options: { cwd: string, timeout?: number }): void {
const res = cp.spawnSync(command, args, { timeout, shell: true, stdio, ...options });
if (res.status !== 0) {
throw new Error(`${command} ${args.join(" ")} for ${directoryName} failed: ${res.stderr && res.stderr.toString()}`);
}
}
});
});
}
-1
View File
@@ -138,7 +138,6 @@ function handleTestConfig() {
case "compiler":
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
runners.push(new project.ProjectRunner());
break;
case "conformance":
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
+1 -1
View File
@@ -36,7 +36,7 @@ namespace ts.projectSystem {
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: nullLogger,
logger: createHasErrorMessageLogger().logger,
canUseEvents: false
};
return new server.Session(opts);
@@ -96,6 +96,11 @@ namespace ts {
include: null,
files: ["../main.ts"]
}),
"dev/configs/fifth.json": JSON.stringify({
extends: "./fourth",
include: ["../tests/utils.ts"],
files: []
}),
"dev/extends.json": JSON.stringify({ extends: 42 }),
"dev/extends2.json": JSON.stringify({ extends: "configs/base" }),
"dev/main.ts": "",
@@ -244,6 +249,29 @@ namespace ts {
}, [
combinePaths(basePath, "main.ts")
]);
testSuccess("can overwrite top-level files using extended []", "configs/fifth.json", {
allowJs: true,
noImplicitAny: true,
strictNullChecks: true,
module: ModuleKind.System
}, [
combinePaths(basePath, "tests/utils.ts")
]);
it("adds extendedSourceFiles only once", () => {
const sourceFile = readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path));
const dir = combinePaths(basePath, "configs");
const expected = [
combinePaths(dir, "third.json"),
combinePaths(dir, "second.json"),
combinePaths(dir, "base.json"),
];
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json");
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json");
assert.deepEqual(sourceFile.extendedSourceFiles, expected);
});
});
});
});
@@ -1,33 +1,50 @@
namespace ts {
describe("convertCompilerOptionsFromJson", () => {
function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const formatDiagnosticHost: FormatDiagnosticsHost = {
getCurrentDirectory: () => "/apath/",
getCanonicalFileName: createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ true),
getNewLine: () => "\n"
};
interface ExpectedResultWithParsingSuccess {
compilerOptions: CompilerOptions;
errors: ReadonlyArray<Diagnostic>;
}
interface ExpectedResultWithParsingFailure {
compilerOptions: CompilerOptions;
hasParseErrors: true;
}
type ExpectedResult = ExpectedResultWithParsingSuccess | ExpectedResultWithParsingFailure;
function isExpectedResultWithParsingFailure(expectedResult: ExpectedResult): expectedResult is ExpectedResultWithParsingFailure {
return !!(expectedResult as ExpectedResultWithParsingFailure).hasParseErrors;
}
function assertCompilerOptions(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
assertCompilerOptionsWithJson(json, configFileName, expectedResult);
assertCompilerOptionsWithJsonNode(json, configFileName, expectedResult);
}
function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName);
function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
const { options: actualCompilerOptions, errors: actualErrors } = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName);
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
const expectedCompilerOptions = JSON.stringify({ ...expectedResult.compilerOptions, configFilePath: configFileName });
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
const expectedErrors = expectedResult.errors;
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
for (let i = 0; i < actualErrors.length; i++) {
const actualError = actualErrors[i];
const expectedError = expectedErrors[i];
assert.equal(actualError.code, expectedError.code);
assert.equal(actualError.category, expectedError.category);
assert.equal(actualError.messageText, expectedError.messageText);
}
verifyErrors(actualErrors, expectedResult.errors, /*ignoreLocation*/ true);
}
function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
const fileText = JSON.stringify(json);
function assertCompilerOptionsWithJsonNode(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) {
assertCompilerOptionsWithJsonText(JSON.stringify(json), configFileName, expectedResult);
}
function assertCompilerOptionsWithJsonText(fileText: string, configFileName: string, expectedResult: ExpectedResult) {
const result = parseJsonText(configFileName, fileText);
assert(!result.parseDiagnostics.length);
assert(!!result.endOfFileToken);
assert.equal(!!result.parseDiagnostics.length, isExpectedResultWithParsingFailure(expectedResult));
const host: ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" }));
const { options: actualCompilerOptions, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName);
expectedResult.compilerOptions.configFilePath = configFileName;
@@ -37,17 +54,32 @@ namespace ts {
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
assert.equal(actualCompilerOptions.configFile, result);
const actualErrors = filter(actualParseErrors, error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
const expectedErrors = expectedResult.errors;
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
if (!isExpectedResultWithParsingFailure(expectedResult)) {
verifyErrors(actualParseErrors.filter(error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code), expectedResult.errors);
}
}
function verifyErrors(actualErrors: Diagnostic[], expectedErrors: ReadonlyArray<Diagnostic>, ignoreLocation?: boolean) {
assert.isTrue(expectedErrors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedErrors.map(getDiagnosticString), undefined, " ")}. Actual error: ${JSON.stringify(actualErrors.map(getDiagnosticString), undefined, " ")}.`);
for (let i = 0; i < actualErrors.length; i++) {
const actualError = actualErrors[i];
const expectedError = expectedErrors[i];
assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`);
assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`);
assert(actualError.file);
assert(actualError.start);
assert(actualError.length);
if (!ignoreLocation) {
assert(actualError.file);
assert(actualError.start);
assert(actualError.length);
}
}
function getDiagnosticString(diagnostic: Diagnostic) {
if (ignoreLocation) {
const { file, ...rest } = diagnostic;
diagnostic = { file: undefined, ...rest };
}
return formatDiagnostic(diagnostic, formatDiagnosticHost);
}
}
@@ -539,5 +571,36 @@ namespace ts {
}
);
});
it("Convert tsconfig options when there are multiple invalid strings", () => {
assertCompilerOptionsWithJsonText(`{
"compilerOptions": {
"target": "<%- options.useTsWithBabel ? 'esnext' : 'es5' %>",
"module": "esnext",
<%_ if (options.classComponent) { _%>
"experimentalDecorators": true,
<%_ } _%>
"sourceMap": true,
"types": [
"webpack-env"<% if (hasMocha || hasJest) { %>,<% } %>
<%_ if (hasMocha) { _%>
"mocha",
"chai"
<%_ } else if (hasJest) { _%>
"jest"
<%_ } _%>
]
}
}
`, "tsconfig.json",
{
compilerOptions: {
target: undefined,
module: ModuleKind.ESNext
},
hasParseErrors: true
}
);
});
});
}
@@ -292,7 +292,7 @@ interface Array<T> {}`
cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
preferences: emptyOptions,
host: notImplementedHost,
formatContext: formatting.getFormatContext(testFormatOptions)
formatContext: formatting.getFormatContext(testFormatSettings)
};
const diagnostics = languageService.getSuggestionDiagnostics(f.path);
@@ -416,6 +416,20 @@ function [#|f|](): Promise<void> {
return fetch('https://typescriptlang.org').then( () => console.log("done") );
}`
);
_testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs3", `
function [#|f|](): Promise<void> {
return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") );
}`
);
_testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs4", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(res);
}
function res(){
console.log("done");
}`
);
_testConvertToAsyncFunction("convertToAsyncFunction_Method", `
class Parser {
[#|f|]():Promise<void> {
@@ -473,6 +487,12 @@ function [#|f|]():Promise<void | Response> {
function [#|f|]() {
return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection));
}
`
);
_testConvertToAsyncFunction("convertToAsyncFunction_NoCatchHandler", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined);
}
`
);
_testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", `
@@ -817,7 +837,7 @@ function [#|f|]() {
);
_testConvertToAsyncFunction("convertToAsyncFunction_Scope1", `
function [#|f|]() {
var var1:Promise<Response>, var2;
var var1: Response, var2;
return fetch('https://typescriptlang.org').then( _ =>
Promise.resolve().then( res => {
var2 = "test";
@@ -1183,6 +1203,70 @@ function [#|f|]() {
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_runEffectfulContinuation", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done"));
}
function res(result) {
return Promise.resolve().then(x => console.log(result));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromise", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseInBlock", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5);
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsFixablePromise", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseLastInChain", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsRejectedPromiseInTryBlock", `
function [#|f|]() {
return Promise.resolve(1)
.then(x => Promise.reject(x))
.catch(err => console.log(err));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", `
function [#|f|]() {
return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_noArgs", `
function delay(millis: number): Promise<void> {
throw "no"
}
function [#|main2|]() {
console.log("Please wait. Loading.");
return delay(500)
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
.then(() => { console.log("."); return delay(500); })
}
`);
_testConvertToAsyncFunction("convertToAsyncFunction_exportModifier", `
export function [#|foo|]() {
return fetch('https://typescriptlang.org').then(s => console.log(s));
}
`);
});
function _testConvertToAsyncFunction(caption: string, text: string) {
@@ -1192,4 +1276,4 @@ function [#|f|]() {
function _testConvertToAsyncFunctionFailed(caption: string, text: string) {
testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*expectFailure*/ true);
}
}
}

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