Merge branch 'master' into shebang-comments

This commit is contained in:
Klaus Meinhardt
2019-01-03 17:38:25 +01:00
committed by GitHub
1570 changed files with 123796 additions and 239404 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.2.0-dev.201xxxxx
**TypeScript Version:** 3.3.0-dev.201xxxxx
<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
+1 -5
View File
@@ -16,11 +16,7 @@ matrix:
branches:
only:
- master
- release-2.7
- release-2.8
- release-2.9
- release-3.0
- release-3.1
- /^release-.*/
install:
- npm uninstall typescript --no-save
+14 -7
View File
@@ -82,19 +82,26 @@ Your pull request should:
* To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration
## Contributing `lib.d.ts` fixes
The library sources are in: [src/lib](https://github.com/Microsoft/TypeScript/tree/master/src/lib)
Library files in `built/local/` are updated by running
```Shell
There are three relevant locations to be aware of when it comes to TypeScript's library declaration files:
* `src/lib`: the location of the sources themselves.
* `lib`: the location of the last-known-good (LKG) versions of the files which are updated periodically.
* `built/local`: the build output location, including where `src/lib` files will be copied to.
Any changes should be made to [src/lib](https://github.com/Microsoft/TypeScript/tree/master/src/lib). **Most** of these files can be updated by hand, with the exception of any generated files (see below).
Library files in `built/local/` are updated automatically by running the standard build task:
```sh
jake
```
The files in `lib/` are used to bootstrap compilation and usually do not need to be updated.
The files in `lib/` are used to bootstrap compilation and usually **should not** be updated unless publishing a new version or updating the LKG.
#### `src/lib/dom.generated.d.ts` and `src/lib/webworker.generated.d.ts`
### Modifying generated library files
These two files represent the DOM typings and are auto-generated. To make any modifications to them, please submit a PR to https://github.com/Microsoft/TSJS-lib-generator
The files `src/lib/dom.generated.d.ts` and `src/lib/webworker.generated.d.ts` both represent type declarations for the DOM and are auto-generated. To make any modifications to them, you will have to direct changes to https://github.com/Microsoft/TSJS-lib-generator
## Running the Tests
+2 -1
View File
@@ -117,7 +117,8 @@ const generatedLCGFile = "built/local/enu/diagnosticMessages.generated.json.lcg"
* 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg'
* generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json
*/
const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"]
const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"]
.map(f => f.toLowerCase())
.map(f => `built/local/${f}/diagnosticMessages.generated.json`)
.concat(generatedLCGFile);
-15
View File
@@ -24,8 +24,6 @@ else if (process.env.PATH !== undefined) {
const host = process.env.TYPESCRIPT_HOST || process.env.host || "node";
const locales = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"];
const defaultTestTimeout = 40000;
let useDebugMode = true;
@@ -709,19 +707,6 @@ const Travis = {
}
};
function buildLocalizedTargets() {
/**
* The localization target produces the two following transformations:
* 1. 'src\loc\lcl\<locale>\diagnosticMessages.generated.json.lcl' => 'built\local\<locale>\diagnosticMessages.generated.json'
* convert localized resources into a .json file the compiler can understand
* 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg'
* generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json
*/
const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"]
.map(f => path.join(Paths.builtLocal,f))
.concat(path.dirname(Paths.generatedLCGFile));
}
function toNs(diff) {
return diff[0] * 1e9 + diff[1];
}
+1 -1
View File
@@ -29,7 +29,7 @@ There are many ways to [contribute](https://github.com/Microsoft/TypeScript/blob
* [Submit bugs](https://github.com/Microsoft/TypeScript/issues) and help us verify fixes as they are checked in.
* Review the [source code changes](https://github.com/Microsoft/TypeScript/pulls).
* Engage with other TypeScript users and developers on [StackOverflow](https://stackoverflow.com/questions/tagged/typescript).
* Join the [#typescript](https://twitter.com/#!/search/realtime/%23typescript) discussion on Twitter.
* Join the [#typescript](https://twitter.com/search?q=%23TypeScript) discussion on Twitter.
* [Contribute bug fixes](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md).
* Read the language specification ([docx](https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.docx?raw=true),
[pdf](https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true), [md](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)).
+197 -23
View File
@@ -51,6 +51,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_memb_2422" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A class can only implement an object type or intersection of object types with statically known members.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_class_declaration_without_the_default_modifier_must_have_a_name_1211" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A class declaration without the 'default' modifier must have a name.]]></Val>
@@ -63,12 +69,6 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_class_may_only_implement_another_class_or_interface_2422" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A class may only implement another class or interface.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";A_class_member_cannot_have_the_0_keyword_1248" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[A class member cannot have the '{0}' keyword.]]></Val>
@@ -693,6 +693,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_new_operator_to_all_calls_95072" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'new' operator to all calls]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_new_operator_to_call_95071" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'new' operator to call]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -705,12 +717,24 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_names_to_all_parameters_without_names_95073" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add names to all parameters without names]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_or_remove_braces_in_an_arrow_function_95058" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add or remove braces in an arrow function]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_parameter_name_90034" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add parameter name]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_qualifier_to_all_unresolved_variables_matching_a_member_name_95037" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add qualifier to all unresolved variables matching a member name]]></Val>
@@ -741,6 +765,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_unknown_conversion_for_non_overlapping_types_95069" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'unknown' conversion for non-overlapping types]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_unknown_to_all_conversions_of_non_overlapping_types_95070" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'unknown' to all conversions of non-overlapping types]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -873,9 +909,9 @@
</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">
<Item ItemId=";An_arithmetic_operand_must_be_of_type_any_number_bigint_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>
<Val><![CDATA[An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -1065,9 +1101,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_interface_may_only_extend_a_class_or_another_interface_2312" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_me_2312" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An interface may only extend a class or another interface.]]></Val>
<Val><![CDATA[An interface can only extend an object type or intersection of object types with statically known members.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -1107,6 +1143,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_outer_value_of_this_is_shadowed_by_this_container_2738" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An outer value of 'this' is shadowed by this container.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";An_overload_signature_cannot_be_declared_as_a_generator_1222" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[An overload signature cannot be declared as a generator.]]></Val>
@@ -1191,9 +1233,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Base_constructor_return_type_0_is_not_a_class_or_interface_type_2509" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_2509" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Base constructor return type '{0}' is not a class or interface type.]]></Val>
<Val><![CDATA[Base constructor return type '{0}' is not an object type or intersection of object types with statically known members.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -1215,6 +1257,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";BigInt_literals_are_not_available_when_targeting_lower_than_ESNext_2737" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[BigInt literals are not available when targeting lower than ESNext.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Binary_digit_expected_1177" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Binary digit expected.]]></Val>
@@ -1293,9 +1341,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property_2540" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";Cannot_assign_to_0_because_it_is_a_constant_2588" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot assign to '{0}' because it is a constant or a read-only property.]]></Val>
<Val><![CDATA[Cannot assign to '{0}' because it is a constant.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Cannot_assign_to_0_because_it_is_a_read_only_property_2540" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Cannot assign to '{0}' because it is a read-only property.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -1433,19 +1487,19 @@
</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>
<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` and then add `jest` or `mocha` to the types field in your tsconfig.]]></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">
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_types_Slashjquery_an_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>
<Val><![CDATA[Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.]]></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">
<Item ItemId=";Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_types_Slashnode_and_th_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>
<Val><![CDATA[Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -2049,6 +2103,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1_2735" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Did you mean for '{0}' to be constrained to type 'new (...args: any[]5D;) => {1}'?]]></Val>
</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>
@@ -2763,12 +2823,24 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_0_errors_6217" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found {0} errors.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_0_errors_Watching_for_file_changes_6194" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found {0} errors. Watching for file changes.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_1_error_6216" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 1 error.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Found_1_error_Watching_for_file_changes_6193" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Found 1 error. Watching for file changes.]]></Val>
@@ -2847,6 +2919,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type_7014" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Function type, which lacks return-type annotation, implicitly has an '{0}' return type.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Generate_get_and_set_accessors_95046" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Generate 'get' and 'set' accessors]]></Val>
@@ -3573,6 +3651,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage_7045" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Member '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Merge_conflict_marker_encountered_1185" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Merge conflict marker encountered.]]></Val>
@@ -3939,6 +4023,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Operator_0_cannot_be_applied_to_type_1_2736" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Operator '{0}' cannot be applied to type '{1}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Operator_0_cannot_be_applied_to_types_1_and_2_2365" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Operator '{0}' cannot be applied to types '{1}' and '{2}'.]]></Val>
@@ -4095,6 +4185,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage_7044" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Parameter '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Parameter_0_is_not_in_the_same_position_as_parameter_1_1227" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Parameter '{0}' is not in the same position as parameter '{1}'.]]></Val>
@@ -4233,6 +4329,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1_7051" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Parameter has a name but no type. Did you mean '{0}: {1}'?]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2_4036" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Parameter type of public setter '{0}' from exported class has or is using name '{1}' from private module '{2}'.]]></Val>
@@ -4299,6 +4401,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Print_the_final_configuration_instead_of_building_1350" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Print the final configuration instead of building.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Print_this_message_6017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Print this message.]]></Val>
@@ -4413,6 +4521,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage_7048" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Property '{0}' implicitly has type 'any', but a better type for its get accessor may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage_7049" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Property '{0}' implicitly has type 'any', but a better type for its set accessor may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2_2416" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Property '{0}' in type '{1}' is not assignable to the same property in base type '{2}'.]]></Val>
@@ -4455,6 +4575,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Property_0_is_missing_in_type_1_but_required_in_type_2_2741" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Property '{0}' is missing in type '{1}' but required in type '{2}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Property_0_is_optional_in_type_1_but_required_in_type_2_2327" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Property '{0}' is optional in type '{1}' but required in type '{2}'.]]></Val>
@@ -4869,6 +4995,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage_7047" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Rest parameter '{0}' implicitly has an 'any[]5D;' type, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Rest_signatures_are_incompatible_2572" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Rest signatures are incompatible.]]></Val>
@@ -5445,6 +5577,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_a_2742" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The inferred type of '{0}' cannot be named without a reference to '{1}'. This is likely not portable. A type annotation is necessary.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary_2527" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The inferred type of '{0}' references an inaccessible '{1}' type. A type annotation is necessary.]]></Val>
@@ -5487,9 +5625,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type_2362" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type_2362" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.]]></Val>
<Val><![CDATA[The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5577,9 +5715,9 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type_2363" ItemType="0" PsrId="306" Leaf="true">
<Item ItemId=";The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type_2363" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.]]></Val>
<Val><![CDATA[The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
@@ -5781,6 +5919,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Type_0_is_missing_the_following_properties_from_type_1_Colon_2_2739" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Type '{0}' is missing the following properties from type '{1}': {2}]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more_2740" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Type '{0}' is missing the following properties from type '{1}': {2}, and {3} more.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Type_0_is_not_a_constructor_function_type_2507" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Type '{0}' is not a constructor function type.]]></Val>
@@ -6249,6 +6399,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Using_compiler_options_of_project_reference_redirect_0_6215" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Using compiler options of project reference redirect '{0}'.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";VERSION_6036" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[VERSION]]></Val>
@@ -6273,6 +6429,18 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage_7043" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Variable '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage_7046" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Variable '{0}' implicitly has type '{1}' in some locations, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined_7034" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Variable '{0}' implicitly has type '{1}' in some locations where its type cannot be determined.]]></Val>
@@ -6357,6 +6525,12 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";_0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage_7050" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['{0}' implicitly has an '{1}' return type, but a better type may be inferred from usage.]]></Val>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";_0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_reference_7023" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA['{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.]]></Val>
+3 -3
View File
@@ -3,7 +3,7 @@
"A_0_modifier_cannot_be_used_with_an_interface_declaration_1045": "'{0}' 한정자는 인터페이스 선언에서 사용할 수 없습니다.",
"A_0_parameter_must_be_the_first_parameter_2680": "'{0}' 매개 변수는 첫 번째 매개 변수여야 합니다.",
"A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature_2463": "바인딩 패턴 매개 변수는 구현 서명에서 선택 사항이 될 수 없습니다.",
"A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement_1105": "'break' 문은 이 문을 둘러싼 반복 문 또는 switch 문 내에서만 사용할 수 있습니다.",
"A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement_1105": "'break' 문은 이 문을 둘러싼 반복문 또는 switch 문 내에서만 사용할 수 있습니다.",
"A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement_1116": "'break' 문은 이 문을 둘러싼 문의 레이블로만 이동할 수 있습니다.",
"A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments_2500": "클래스는 선택적 형식 인수가 포함된 식별자/정규화된 이름만 구현할 수 있습니다.",
"A_class_declaration_without_the_default_modifier_must_have_a_name_1211": "'default' 한정자를 사용하지 않는 클래스 선언에는 이름이 있어야 합니다.",
@@ -23,8 +23,8 @@
"A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254": "앰비언트 컨텍스트의 'const' 이니셜라이저는 문자열 또는 숫자 리터럴이어야 합니다.",
"A_constructor_cannot_contain_a_super_call_when_its_class_extends_null_17005": "생성자는 해당 클래스가 'null'을 확장하는 경우 'super' 호출을 포함할 수 없습니다.",
"A_constructor_cannot_have_a_this_parameter_2681": "생성자에는 'this' 매개 변수를 사용할 수 없습니다.",
"A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement_1104": "'continue' 문은 이 문을 둘러싼 반복 문 내에서만 사용할 수 있습니다.",
"A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement_1115": "'continue' 문은 이 문을 둘러싼 반복 문의 레이블로만 이동할 수 있습니다.",
"A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement_1104": "'continue' 문은 이 문을 둘러싼 반복문 내에서만 사용할 수 있습니다.",
"A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement_1115": "'continue' 문은 이 문을 둘러싼 반복문의 레이블로만 이동할 수 있습니다.",
"A_declare_modifier_cannot_be_used_in_an_already_ambient_context_1038": "'declare' 한정자는 이미 존재하는 앰비언트 컨텍스트에서 사용할 수 없습니다.",
"A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file_1046": "'declare' 한정자는 .d.ts 파일의 최상위 선언에 필요합니다.",
"A_decorator_can_only_decorate_a_method_implementation_not_an_overload_1249": "데코레이터는 오버로드가 아니라 메서드 구현만 데코레이팅할 수 있습니다.",
+517 -299
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -29,7 +29,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
@@ -155,7 +155,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> {
+11 -11
View File
@@ -83,7 +83,7 @@ interface SymbolConstructor {
}
interface Symbol {
readonly [Symbol.toStringTag]: "Symbol";
readonly [Symbol.toStringTag]: string;
}
interface Array<T> {
@@ -127,23 +127,23 @@ interface Date {
}
interface Map<K, V> {
readonly [Symbol.toStringTag]: "Map";
readonly [Symbol.toStringTag]: string;
}
interface WeakMap<K extends object, V> {
readonly [Symbol.toStringTag]: "WeakMap";
readonly [Symbol.toStringTag]: string;
}
interface Set<T> {
readonly [Symbol.toStringTag]: "Set";
readonly [Symbol.toStringTag]: string;
}
interface WeakSet<T extends object> {
readonly [Symbol.toStringTag]: "WeakSet";
readonly [Symbol.toStringTag]: string;
}
interface JSON {
readonly [Symbol.toStringTag]: "JSON";
readonly [Symbol.toStringTag]: string;
}
interface Function {
@@ -158,15 +158,15 @@ interface Function {
}
interface GeneratorFunction {
readonly [Symbol.toStringTag]: "GeneratorFunction";
readonly [Symbol.toStringTag]: string;
}
interface Math {
readonly [Symbol.toStringTag]: "Math";
readonly [Symbol.toStringTag]: string;
}
interface Promise<T> {
readonly [Symbol.toStringTag]: "Promise";
readonly [Symbol.toStringTag]: string;
}
interface PromiseConstructor {
@@ -261,11 +261,11 @@ interface String {
}
interface ArrayBuffer {
readonly [Symbol.toStringTag]: "ArrayBuffer";
readonly [Symbol.toStringTag]: string;
}
interface DataView {
readonly [Symbol.toStringTag]: "DataView";
readonly [Symbol.toStringTag]: string;
}
interface Int8Array {
+629
View File
@@ -0,0 +1,629 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface BigInt {
/**
* Returns a string representation of an object.
* @param radix Specifies a radix for converting numeric values to strings.
*/
toString(radix?: number): string;
/** Returns a string representation appropriate to the host environment's current locale. */
toLocaleString(): string;
/** Returns the primitive value of the specified object. */
valueOf(): bigint;
readonly [Symbol.toStringTag]: "BigInt";
}
interface BigIntConstructor {
(value?: any): bigint;
readonly prototype: BigInt;
/**
* Interprets the low bits of a BigInt as a 2's-complement signed integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asIntN(bits: number, int: bigint): bigint;
/**
* Interprets the low bits of a BigInt as an unsigned integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asUintN(bits: number, int: bigint): bigint;
}
declare const BigInt: BigIntConstructor;
/**
* A typed array of 64-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated, an exception is raised.
*/
interface BigInt64Array {
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/** The ArrayBuffer instance referenced by the array. */
readonly buffer: ArrayBufferLike;
/** The length in bytes of the array. */
readonly byteLength: number;
/** The offset in bytes of the array. */
readonly byteOffset: number;
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this;
/** Yields index, value pairs for every entry in the array. */
entries(): IterableIterator<[number, bigint]>;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns false,
* or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: bigint, start?: number, end?: number): this;
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls
* the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: bigint, index: number, array: BigInt64Array) => any, thisArg?: any): BigInt64Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): bigint | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: bigint, index: number, array: BigInt64Array) => void, thisArg?: any): void;
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: bigint, fromIndex?: number): boolean;
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
indexOf(searchElement: bigint, fromIndex?: number): number;
/**
* Adds all the elements of an array separated by the specified separator string.
* @param separator A string used to separate one element of an array from the next in the
* resulting String. If omitted, the array elements are separated with a comma.
*/
join(separator?: string): string;
/** Yields each index in the array. */
keys(): IterableIterator<number>;
/**
* Returns the index of the last occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
lastIndexOf(searchElement: bigint, fromIndex?: number): number;
/** The length of the array. */
readonly length: number;
/**
* Calls a defined callback function on each element of an array, and returns an array that
* contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: bigint, index: number, array: BigInt64Array) => bigint, thisArg?: any): BigInt64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an
* argument instead of an array value.
*/
reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigInt64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduceRight<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigInt64Array) => U, initialValue: U): U;
/** Reverses the elements in the array. */
reverse(): this;
/**
* Sets a value or an array of values.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: ArrayLike<bigint>, offset?: number): void;
/**
* Returns a section of an array.
* @param start The beginning of the specified portion of the array.
* @param end The end of the specified portion of the array.
*/
slice(start?: number, end?: number): BigInt64Array;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the
* callbackfn function for each element in the array until the callbackfn returns true, or until
* the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: bigint, index: number, array: BigInt64Array) => boolean, thisArg?: any): boolean;
/**
* Sorts the array.
* @param compareFn The function used to determine the order of the elements. If omitted, the elements are sorted in ascending order.
*/
sort(compareFn?: (a: bigint, b: bigint) => number | bigint): this;
/**
* Gets a new BigInt64Array view of the ArrayBuffer store for this array, referencing the elements
* at begin, inclusive, up to end, exclusive.
* @param begin The index of the beginning of the array.
* @param end The index of the end of the array.
*/
subarray(begin: number, end?: number): BigInt64Array;
/** Converts the array to a string by using the current locale. */
toLocaleString(): string;
/** Returns a string representation of the array. */
toString(): string;
/** Yields each value in the array. */
values(): IterableIterator<bigint>;
[Symbol.iterator](): IterableIterator<bigint>;
readonly [Symbol.toStringTag]: "BigInt64Array";
[index: number]: bigint;
}
interface BigInt64ArrayConstructor {
readonly prototype: BigInt64Array;
new(length?: number): BigInt64Array;
new(array: Iterable<bigint>): BigInt64Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigInt64Array;
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of(...items: bigint[]): BigInt64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<bigint>): BigInt64Array;
from<U>(arrayLike: ArrayLike<U>, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigInt64Array;
}
declare const BigInt64Array: BigInt64ArrayConstructor;
/**
* A typed array of 64-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated, an exception is raised.
*/
interface BigUint64Array {
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/** The ArrayBuffer instance referenced by the array. */
readonly buffer: ArrayBufferLike;
/** The length in bytes of the array. */
readonly byteLength: number;
/** The offset in bytes of the array. */
readonly byteOffset: number;
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this;
/** Yields index, value pairs for every entry in the array. */
entries(): IterableIterator<[number, bigint]>;
/**
* Determines whether all the members of an array satisfy the specified test.
* @param callbackfn A function that accepts up to three arguments. The every method calls
* the callbackfn function for each element in the array until the callbackfn returns false,
* or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: bigint, start?: number, end?: number): this;
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls
* the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: bigint, index: number, array: BigUint64Array) => any, thisArg?: any): BigUint64Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): bigint | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): number;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: bigint, index: number, array: BigUint64Array) => void, thisArg?: any): void;
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: bigint, fromIndex?: number): boolean;
/**
* Returns the index of the first occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
indexOf(searchElement: bigint, fromIndex?: number): number;
/**
* Adds all the elements of an array separated by the specified separator string.
* @param separator A string used to separate one element of an array from the next in the
* resulting String. If omitted, the array elements are separated with a comma.
*/
join(separator?: string): string;
/** Yields each index in the array. */
keys(): IterableIterator<number>;
/**
* Returns the index of the last occurrence of a value in an array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
* search starts at index 0.
*/
lastIndexOf(searchElement: bigint, fromIndex?: number): number;
/** The length of the array. */
readonly length: number;
/**
* Calls a defined callback function on each element of an array, and returns an array that
* contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the
* callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: bigint, index: number, array: BigUint64Array) => bigint, thisArg?: any): BigUint64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array. The return value of
* the callback function is the accumulated result, and is provided as an argument in the next
* call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the
* callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduce<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an
* argument instead of an array value.
*/
reduceRight(callbackfn: (previousValue: bigint, currentValue: bigint, currentIndex: number, array: BigUint64Array) => bigint): bigint;
/**
* Calls the specified callback function for all the elements in an array, in descending order.
* The return value of the callback function is the accumulated result, and is provided as an
* argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
* the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start
* the accumulation. The first call to the callbackfn function provides this value as an argument
* instead of an array value.
*/
reduceRight<U>(callbackfn: (previousValue: U, currentValue: bigint, currentIndex: number, array: BigUint64Array) => U, initialValue: U): U;
/** Reverses the elements in the array. */
reverse(): this;
/**
* Sets a value or an array of values.
* @param array A typed or untyped array of values to set.
* @param offset The index in the current array at which the values are to be written.
*/
set(array: ArrayLike<bigint>, offset?: number): void;
/**
* Returns a section of an array.
* @param start The beginning of the specified portion of the array.
* @param end The end of the specified portion of the array.
*/
slice(start?: number, end?: number): BigUint64Array;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the
* callbackfn function for each element in the array until the callbackfn returns true, or until
* the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: bigint, index: number, array: BigUint64Array) => boolean, thisArg?: any): boolean;
/**
* Sorts the array.
* @param compareFn The function used to determine the order of the elements. If omitted, the elements are sorted in ascending order.
*/
sort(compareFn?: (a: bigint, b: bigint) => number | bigint): this;
/**
* Gets a new BigUint64Array view of the ArrayBuffer store for this array, referencing the elements
* at begin, inclusive, up to end, exclusive.
* @param begin The index of the beginning of the array.
* @param end The index of the end of the array.
*/
subarray(begin: number, end?: number): BigUint64Array;
/** Converts the array to a string by using the current locale. */
toLocaleString(): string;
/** Returns a string representation of the array. */
toString(): string;
/** Yields each value in the array. */
values(): IterableIterator<bigint>;
[Symbol.iterator](): IterableIterator<bigint>;
readonly [Symbol.toStringTag]: "BigUint64Array";
[index: number]: bigint;
}
interface BigUint64ArrayConstructor {
readonly prototype: BigUint64Array;
new(length?: number): BigUint64Array;
new(array: Iterable<bigint>): BigUint64Array;
new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigUint64Array;
/** The size in bytes of each element in the array. */
readonly BYTES_PER_ELEMENT: number;
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of(...items: bigint[]): BigUint64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<bigint>): BigUint64Array;
from<U>(arrayLike: ArrayLike<U>, mapfn: (v: U, k: number) => bigint, thisArg?: any): BigUint64Array;
}
declare const BigUint64Array: BigUint64ArrayConstructor;
interface DataView {
/**
* Gets the BigInt64 value at the specified byte offset from the start of the view. There is
* no alignment constraint; multi-byte values may be fetched from any offset.
* @param byteOffset The place in the buffer at which the value should be retrieved.
*/
getBigInt64(byteOffset: number, littleEndian?: boolean): bigint;
/**
* Gets the BigUint64 value at the specified byte offset from the start of the view. There is
* no alignment constraint; multi-byte values may be fetched from any offset.
* @param byteOffset The place in the buffer at which the value should be retrieved.
*/
getBigUint64(byteOffset: number, littleEndian?: boolean): bigint;
/**
* Stores a BigInt64 value at the specified byte offset from the start of the view.
* @param byteOffset The place in the buffer at which the value should be set.
* @param value The value to set.
* @param littleEndian If false or undefined, a big-endian value should be written,
* otherwise a little-endian value should be written.
*/
setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void;
/**
* Stores a BigUint64 value at the specified byte offset from the start of the view.
* @param byteOffset The place in the buffer at which the value should be set.
* @param value The value to set.
* @param littleEndian If false or undefined, a big-endian value should be written,
* otherwise a little-endian value should be written.
*/
setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void;
}
+1
View File
@@ -21,5 +21,6 @@ and limitations under the License.
/// <reference lib="es2018" />
/// <reference lib="esnext.asynciterable" />
/// <reference lib="esnext.array" />
/// <reference lib="esnext.bigint" />
/// <reference lib="esnext.symbol" />
/// <reference lib="esnext.intl" />
+1296 -13
View File
File diff suppressed because it is too large Load Diff
+16 -2
View File
@@ -61,7 +61,8 @@ declare namespace ts.server.protocol {
GetApplicableRefactors = "getApplicableRefactors",
GetEditsForRefactor = "getEditsForRefactor",
OrganizeImports = "organizeImports",
GetEditsForFileRename = "getEditsForFileRename"
GetEditsForFileRename = "getEditsForFileRename",
ConfigurePlugin = "configurePlugin"
}
/**
* A TypeScript Server message
@@ -136,6 +137,10 @@ declare namespace ts.server.protocol {
* Contains message body if success === true.
*/
body?: any;
/**
* Contains extra information that plugin can include to be passed on
*/
metadata?: unknown;
}
/**
* Arguments for FileRequest messages.
@@ -781,7 +786,7 @@ declare namespace ts.server.protocol {
/**
* The file locations referencing the symbol.
*/
refs: ReferencesResponseItem[];
refs: ReadonlyArray<ReferencesResponseItem>;
/**
* The name of the symbol.
*/
@@ -1010,6 +1015,14 @@ declare namespace ts.server.protocol {
*/
interface ConfigureResponse extends Response {
}
interface ConfigurePluginRequestArguments {
pluginName: string;
configuration: any;
}
interface ConfigurePluginRequest extends Request {
command: CommandTypes.ConfigurePlugin;
arguments: ConfigurePluginRequestArguments;
}
/**
* Information found in an "open" request.
*/
@@ -1847,6 +1860,7 @@ declare namespace ts.server.protocol {
*/
interface DiagnosticEvent extends Event {
body?: DiagnosticEventBody;
event: DiagnosticEventKind;
}
interface ConfigFileDiagnosticEventBody {
/**
+10765 -9382
View File
File diff suppressed because it is too large Load Diff
+16062 -14239
View File
File diff suppressed because it is too large Load Diff
+558 -502
View File
File diff suppressed because it is too large Load Diff
+16036 -14259
View File
File diff suppressed because it is too large Load Diff
+520 -490
View File
File diff suppressed because it is too large Load Diff
+15714 -14025
View File
File diff suppressed because it is too large Load Diff
+520 -490
View File
File diff suppressed because it is too large Load Diff
+15714 -14025
View File
File diff suppressed because it is too large Load Diff
+11660 -10330
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -406,11 +406,11 @@
"Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions_2521": "運算式會解析成變數宣告 '{0}',而編譯器會使用此宣告支援非同步函式。",
"Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta__2544": "運算式將解析成變數宣告 '_newTarget',而供編譯器用來擷取 'new.target' 中繼屬性參考。",
"Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference_2400": "運算式會解析成變數宣告 '_this',而編譯器會使用此宣告來擷取 'this' 參考 。",
"Extract_constant_95006": "解壓縮常數",
"Extract_function_95005": "解壓縮函式",
"Extract_to_0_in_1_95004": "解壓縮至 {1} 中的 {0}",
"Extract_to_0_in_1_scope_95008": "解壓縮至 {1} 範圍中的 {0}",
"Extract_to_0_in_enclosing_scope_95007": "解壓縮至封閉式範圍中的 {0}",
"Extract_constant_95006": "擷取常數",
"Extract_function_95005": "擷取函式",
"Extract_to_0_in_1_95004": "擷取至 {1} 中的 {0}",
"Extract_to_0_in_1_scope_95008": "擷取至 {1} 範圍中的 {0}",
"Extract_to_0_in_enclosing_scope_95007": "擷取至封閉式範圍中的 {0}",
"FILE_6035": "檔案",
"FILE_OR_DIRECTORY_6040": "檔案或目錄",
"Failed_to_parse_file_0_Colon_1_5014": "無法剖析檔案 '{0}': {1}。",
@@ -584,7 +584,7 @@
"Module_name_0_was_successfully_resolved_to_1_6089": "======== 模組名稱 '{0}' 已成功解析為 '{1}'。========",
"Module_resolution_kind_is_not_specified_using_0_6088": "未指定模組解析種類,將使用 '{0}'。",
"Module_resolution_using_rootDirs_has_failed_6111": "使用 'rootDirs' 解析模組失敗。",
"Move_to_a_new_file_95049": "移至新",
"Move_to_a_new_file_95049": "移至新",
"Multiple_consecutive_numeric_separators_are_not_permitted_6189": "不允許多個連續的數字分隔符號。",
"Multiple_constructor_implementations_are_not_allowed_2392": "不允許多個建構函式實作。",
"NEWLINE_6061": "新行",
+2 -1
View File
@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "https://www.typescriptlang.org/",
"version": "3.2.0",
"version": "3.3.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
@@ -82,6 +82,7 @@
"mocha": "latest",
"mocha-fivemat-progress-reporter": "latest",
"plugin-error": "latest",
"pretty-hrtime": "^1.0.3",
"prex": "^0.4.3",
"q": "latest",
"remove-internal": "^2.9.2",
+9 -3
View File
@@ -683,11 +683,17 @@ function ensureCompileTask(projectGraph, options) {
}
});
}
const js = (projectGraphConfig.resolvedOptions.js ? projectGraphConfig.resolvedOptions.js(stream.js) : stream.js)
const additionalJsOutputs = projectGraphConfig.resolvedOptions.js ? projectGraphConfig.resolvedOptions.js(stream.js)
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.write(sourceMapPath, sourceMapOptions))) : undefined;
const additionalDtsOutputs = projectGraphConfig.resolvedOptions.dts ? projectGraphConfig.resolvedOptions.dts(stream.dts)
.pipe(gulpif(declarationMap, sourcemaps.write(sourceMapPath, sourceMapOptions))) : undefined;
const js = stream.js
.pipe(gulpif(sourceMap || inlineSourceMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
const dts = (projectGraphConfig.resolvedOptions.dts ? projectGraphConfig.resolvedOptions.dts(stream.dts) : stream.dts)
const dts = stream.dts
.pipe(gulpif(declarationMap, sourcemaps.write(sourceMapPath, sourceMapOptions)));
return merge2([js, dts])
return merge2([js, dts, additionalJsOutputs, additionalDtsOutputs].filter(x => !!x))
.pipe(gulp.dest(destPath));
});
}
@@ -36,7 +36,7 @@ function main(): void {
console.error("Unexpected XML file structure. Expected to find result.LCX.$.TgtCul.");
process.exit(1);
}
const outputDirectoryName = getPreferedLocaleName(result.LCX.$.TgtCul);
const outputDirectoryName = getPreferedLocaleName(result.LCX.$.TgtCul).toLowerCase();
if (!outputDirectoryName) {
console.error(`Invalid output locale name for '${result.LCX.$.TgtCul}'.`);
process.exit(1);
+8 -2
View File
@@ -143,7 +143,7 @@ namespace ts {
let symbolCount = 0;
let Symbol: { new (flags: SymbolFlags, name: __String): Symbol }; // tslint:disable-line variable-name
let Symbol: new (flags: SymbolFlags, name: __String) => Symbol; // tslint:disable-line variable-name
let classifiableNames: UnderscoreEscapedMap<true>;
const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
@@ -233,6 +233,11 @@ namespace ts {
symbol.members = createSymbolTable();
}
// On merge of const enum module with class or function, reset const enum only flag (namespaces will already recalculate)
if (symbol.constEnumOnlyModule && (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) {
symbol.constEnumOnlyModule = false;
}
if (symbolFlags & SymbolFlags.Value) {
setValueDeclaration(symbol, node);
}
@@ -1379,6 +1384,7 @@ namespace ts {
}
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) {
node.tagName.parent = node;
if (node.fullName) {
setParentPointers(node, node.fullName);
}
@@ -2607,7 +2613,7 @@ namespace ts {
return true;
}
const node = symbol.valueDeclaration;
if (isCallExpression(node)) {
if (node && isCallExpression(node)) {
return !!getAssignedExpandoInitializer(node);
}
let init = !node ? undefined :
+937 -501
View File
File diff suppressed because it is too large Load Diff
+23 -27
View File
@@ -119,6 +119,18 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Enable_tracing_of_the_name_resolution_process
},
{
name: "diagnostics",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_diagnostic_information
},
{
name: "extendedDiagnostics",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_verbose_diagnostic_information
},
];
/* @internal */
@@ -584,12 +596,6 @@ namespace ts {
category: Diagnostics.Experimental_Options,
description: Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators
},
{
name: "experimentalBigInt",
type: "boolean",
category: Diagnostics.Experimental_Options,
description: Diagnostics.Enables_experimental_support_for_ESNext_BigInt_literals
},
// Advanced
{
@@ -598,18 +604,6 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Specify_the_JSX_factory_function_to_use_when_targeting_react_JSX_emit_e_g_React_createElement_or_h
},
{
name: "diagnostics",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_diagnostic_information
},
{
name: "extendedDiagnostics",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Show_verbose_diagnostic_information
},
{
name: "resolveJsonModule",
type: "boolean",
@@ -1679,13 +1673,13 @@ namespace ts {
const files = map(
filter(
configParseResult.fileNames,
!configParseResult.configFileSpecs ? _ => false : matchesSpecs(
(!configParseResult.configFileSpecs || !configParseResult.configFileSpecs.validatedIncludeSpecs) ? _ => true : matchesSpecs(
configFileName,
configParseResult.configFileSpecs.validatedIncludeSpecs,
configParseResult.configFileSpecs.validatedExcludeSpecs
)
),
f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), f, getCanonicalFileName)
f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName)
);
const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames });
const config = {
@@ -1699,6 +1693,8 @@ namespace ts {
listFiles: undefined,
listEmittedFiles: undefined,
project: undefined,
build: undefined,
version: undefined,
},
references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath, originalPath: undefined })),
files: length(files) ? files : undefined,
@@ -1719,24 +1715,24 @@ namespace ts {
}
function matchesSpecs(path: string, includeSpecs: ReadonlyArray<string> | undefined, excludeSpecs: ReadonlyArray<string> | undefined): (path: string) => boolean {
if (!includeSpecs) return _ => false;
if (!includeSpecs) return _ => true;
const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, sys.useCaseSensitiveFileNames, sys.getCurrentDirectory());
const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, sys.useCaseSensitiveFileNames);
const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, sys.useCaseSensitiveFileNames);
if (includeRe) {
if (excludeRe) {
return path => includeRe.test(path) && !excludeRe.test(path);
return path => !(includeRe.test(path) && !excludeRe.test(path));
}
return path => includeRe.test(path);
return path => !includeRe.test(path);
}
if (excludeRe) {
return path => !excludeRe.test(path);
return path => excludeRe.test(path);
}
return _ => false;
return _ => true;
}
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean" || optionDefinition.type === "object") {
// this is of a type CommandLineOptionOfPrimitiveType
return undefined;
}
@@ -1899,7 +1895,7 @@ namespace ts {
}
result.push(`}`);
return result.join(newLine);
return result.join(newLine) + newLine;
}
}
+11 -7
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.2";
export const versionMajorMinor = "3.3";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}
@@ -112,13 +112,13 @@ namespace ts {
}
// The global Map object. This may not be available, so we must test for it.
declare const Map: { new <T>(): Map<T> } | undefined;
declare const Map: (new <T>() => Map<T>) | undefined;
// Internet Explorer's Map doesn't support iteration, so don't use it.
// tslint:disable-next-line no-in-operator variable-name
export const MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap();
// Keep the class inside a function so it doesn't get compiled if it's not used.
function shimMap(): { new <T>(): Map<T> } {
function shimMap(): new <T>() => Map<T> {
class MapIterator<T, U extends (string | T | [string, T])> {
private data: MapLike<T>;
@@ -1268,9 +1268,9 @@ namespace ts {
}
/** Shims `Array.from`. */
export function arrayFrom<T, U>(iterator: Iterator<T>, map: (t: T) => U): U[];
export function arrayFrom<T>(iterator: Iterator<T>): T[];
export function arrayFrom(iterator: Iterator<any>, map?: (t: any) => any): any[] {
export function arrayFrom<T, U>(iterator: Iterator<T> | IterableIterator<T>, map: (t: T) => U): U[];
export function arrayFrom<T>(iterator: Iterator<T> | IterableIterator<T>): T[];
export function arrayFrom(iterator: Iterator<any> | IterableIterator<any>, map?: (t: any) => any): any[] {
const result: any[] = [];
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
result.push(map ? map(value) : value);
@@ -2165,6 +2165,10 @@ namespace ts {
}
export function fill<T>(length: number, cb: (index: number) => T): T[] {
return new Array(length).fill(0).map((_, i) => cb(i));
const result = Array<T>(length);
for (let i = 0; i < length; i++) {
result[i] = cb(i);
}
return result;
}
}
+68 -21
View File
@@ -1011,10 +1011,18 @@
"category": "Message",
"code": 1350
},
"Experimental support for BigInt is a feature that is subject to change in a future release. Set the 'experimentalBigInt' option to remove this warning.": {
"An identifier or keyword cannot immediately follow a numeric literal.": {
"category": "Error",
"code": 1351
},
"A bigint literal cannot use exponential notation.": {
"category": "Error",
"code": 1352
},
"A bigint literal must be an integer.": {
"category": "Error",
"code": 1353
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -1064,7 +1072,7 @@
"category": "Error",
"code": 2311
},
"An interface may only extend a class or another interface.": {
"An interface can only extend an object type or intersection of object types with statically known members.": {
"category": "Error",
"code": 2312
},
@@ -1492,7 +1500,7 @@
"category": "Error",
"code": 2420
},
"A class may only implement another class or interface.": {
"A class can only implement an object type or intersection of object types with statically known members.": {
"category": "Error",
"code": 2422
},
@@ -1636,14 +1644,6 @@
"category": "Error",
"code": 2458
},
"Type '{0}' has no property '{1}' and no string index signature.": {
"category": "Error",
"code": 2459
},
"Type '{0}' has no property '{1}'.": {
"category": "Error",
"code": 2460
},
"Type '{0}' is not an array type.": {
"category": "Error",
"code": 2461
@@ -1696,7 +1696,7 @@
"category": "Error",
"code": 2473
},
"In 'const' enum declarations member initializer must be constant expression.": {
"const enum member initializers can only contain literal values and other computed enum values.": {
"category": "Error",
"code": 2474
},
@@ -1760,7 +1760,7 @@
"category": "Error",
"code": 2492
},
"Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'.": {
"Tuple type '{0}' of length '{1}' has no element at index '{2}'.": {
"category": "Error",
"code": 2493
},
@@ -1824,7 +1824,7 @@
"category": "Error",
"code": 2508
},
"Base constructor return type '{0}' is not a class or interface type.": {
"Base constructor return type '{0}' is not an object type or intersection of object types with statically known members.": {
"category": "Error",
"code": 2509
},
@@ -1948,7 +1948,7 @@
"category": "Error",
"code": 2539
},
"Cannot assign to '{0}' because it is a constant or a read-only property.": {
"Cannot assign to '{0}' because it is a read-only property.": {
"category": "Error",
"code": 2540
},
@@ -2128,6 +2128,10 @@
"category": "Error",
"code": 2587
},
"Cannot assign to '{0}' because it is a constant.": {
"category": "Error",
"code": 2588
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -2505,7 +2509,7 @@
"category": "Error",
"code": 2736
},
"BigInt literals are not available when targetting lower than ESNext.": {
"BigInt literals are not available when targeting lower than ESNext.": {
"category": "Error",
"code": 2737
},
@@ -2513,6 +2517,30 @@
"category": "Message",
"code": 2738
},
"Type '{0}' is missing the following properties from type '{1}': {2}": {
"category": "Error",
"code": 2739
},
"Type '{0}' is missing the following properties from type '{1}': {2}, and {3} more.": {
"category": "Error",
"code": 2740
},
"Property '{0}' is missing in type '{1}' but required in type '{2}'.": {
"category": "Error",
"code": 2741
},
"The inferred type of '{0}' cannot be named without a reference to '{1}'. This is likely not portable. A type annotation is necessary.": {
"category": "Error",
"code": 2742
},
"No overload expects {0} type arguments, but overloads do exist that expect either {1} or {2} type arguments.": {
"category": "Error",
"code": 2743
},
"Type parameter defaults can only reference previously declared type parameters.": {
"category": "Error",
"code": 2744
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -3921,10 +3949,6 @@
"category": "Error",
"code": 6370
},
"Enables experimental support for ESNext BigInt literals.": {
"category": "Message",
"code": 6371
},
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",
@@ -3967,6 +3991,10 @@
"category": "Error",
"code": 7013
},
"Function type, which lacks return-type annotation, implicitly has an '{0}' return type.": {
"category": "Error",
"code": 7014
},
"Element implicitly has an 'any' type because index expression is not of type 'number'.": {
"category": "Error",
"code": 7015
@@ -4109,6 +4137,10 @@
"category": "Suggestion",
"code": 7050
},
"Parameter has a name but no type. Did you mean '{0}: {1}'?": {
"category": "Error",
"code": 7051
},
"You cannot rename this element.": {
"category": "Error",
@@ -4492,6 +4524,10 @@
"category": "Message",
"code": 90033
},
"Add parameter name": {
"category": "Message",
"code": 90034
},
"Convert function to an ES2015 class": {
"category": "Message",
"code": 95001
@@ -4732,7 +4768,6 @@
"category": "Message",
"code": 95062
},
"Add missing enum member '{0}'": {
"category": "Message",
"code": 95063
@@ -4764,5 +4799,17 @@
"Add 'unknown' to all conversions of non-overlapping types": {
"category": "Message",
"code": 95070
},
"Add missing 'new' operator to call": {
"category": "Message",
"code": 95071
},
"Add missing 'new' operator to all calls": {
"category": "Message",
"code": 95072
},
"Add names to all parameters without names": {
"category": "Message",
"code": 95073
}
}
+18 -9
View File
@@ -1651,11 +1651,17 @@ namespace ts {
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
let indentBeforeDot = false;
let indentAfterDot = false;
const dotRangeFirstCommentStart = skipTrivia(
currentSourceFile!.text,
node.expression.end,
/*stopAfterLineBreak*/ false,
/*stopAtComments*/ true
);
const dotRangeStart = skipTrivia(currentSourceFile!.text, dotRangeFirstCommentStart);
const dotRangeEnd = dotRangeStart + 1;
if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) {
const dotRangeStart = node.expression.end;
const dotRangeEnd = skipTrivia(currentSourceFile!.text, node.expression.end) + 1;
const dotToken = createToken(SyntaxKind.DotToken);
dotToken.pos = dotRangeStart;
dotToken.pos = node.expression.end;
dotToken.end = dotRangeEnd;
indentBeforeDot = needsIndentation(node, node.expression, dotToken);
indentAfterDot = needsIndentation(node, dotToken, node.name);
@@ -1664,7 +1670,8 @@ namespace ts {
emitExpression(node.expression);
increaseIndentIf(indentBeforeDot, /*writeSpaceIfNotIndenting*/ false);
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
const dotHasCommentTrivia = dotRangeFirstCommentStart !== dotRangeStart;
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression, dotHasCommentTrivia);
if (shouldEmitDotDot) {
writePunctuation(".");
}
@@ -1677,13 +1684,15 @@ namespace ts {
// 1..toString is a valid property access, emit a dot after the literal
// Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal
function needsDotDotForPropertyAccess(expression: Expression) {
function needsDotDotForPropertyAccess(expression: Expression, dotHasTrivia: boolean) {
expression = skipPartiallyEmittedExpressions(expression);
if (isNumericLiteral(expression)) {
// check if numeric literal is a decimal literal that was originally written with a dot
const text = getLiteralTextOfNode(<LiteralExpression>expression, /*neverAsciiEscape*/ true);
return !expression.numericLiteralFlags
&& !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
// If he number will be printed verbatim and it doesn't already contain a dot, add one
// if the expression doesn't have any comments that will be emitted.
return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!) &&
(!dotHasTrivia || printerOptions.removeComments);
}
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
// check if constant enum value is integer
@@ -1858,7 +1867,7 @@ namespace ts {
}
function emitSpreadExpression(node: SpreadElement) {
writePunctuation("...");
emitTokenWithComment(SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node);
emitExpression(node.expression);
}
@@ -2715,7 +2724,7 @@ namespace ts {
function emitSpreadAssignment(node: SpreadAssignment) {
if (node.expression) {
writePunctuation("...");
emitTokenWithComment(SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node);
emitExpression(node.expression);
}
}
+10 -10
View File
@@ -40,18 +40,18 @@ namespace ts {
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 seen: unknown[] = [];
const nameStack: string[] = [];
return (obj, name, cbOk, cbFail) => {
if (seen.has(obj) || nameStack.length > 4) {
return cbFail(seen.has(obj), nameStack);
if (seen.indexOf(obj) !== -1 || nameStack.length > 4) {
return cbFail(seen.indexOf(obj) !== -1, nameStack);
}
seen.add(obj);
seen.push(obj);
nameStack.push(name);
const res = cbOk();
nameStack.pop();
seen.delete(obj);
seen.pop();
return res;
};
}
@@ -104,8 +104,8 @@ namespace ts {
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));
const ignoredProperties: ReadonlyArray<string> = ["arguments", "caller", "constructor", "eval", "super_"];
const reservedFunctionProperties: ReadonlyArray<string> = Object.getOwnPropertyNames(noop);
interface ObjectEntry { readonly key: string; readonly value: unknown; }
function getEntriesOfObject(obj: object): ReadonlyArray<ObjectEntry> {
const seen = createMap<true>();
@@ -114,8 +114,8 @@ namespace ts {
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)) &&
ignoredProperties.indexOf(key) === -1 &&
(typeof obj !== "function" || reservedFunctionProperties.indexOf(key) === -1) &&
// Don't add property from a higher prototype if it already exists in a lower one
addToSeen(seen, key)) {
const value = safeGetPropertyOfObject(chain, key);
@@ -148,7 +148,7 @@ namespace ts {
}
export function isJsPrivate(name: string): boolean {
return name.startsWith("_");
return startsWith(name, "_");
}
function tryRequire(fileNameToRequire: string): unknown {
+2 -2
View File
@@ -139,7 +139,7 @@ namespace ts.moduleSpecifiers {
return isPathRelativeToParent(nonRelative) || countPathComponents(relativePath) < countPathComponents(nonRelative) ? relativePath : nonRelative;
}
function countPathComponents(path: string): number {
export function countPathComponents(path: string): number {
let count = 0;
for (let i = startsWith(path, "./") ? 2 : 0; i < path.length; i++) {
if (path.charCodeAt(i) === CharacterCodes.slash) count++;
@@ -203,7 +203,7 @@ namespace ts.moduleSpecifiers {
return; // Don't want to a package to globally import from itself
}
const target = targets.find(t => compareStrings(t.slice(0, resolved.length + 1), resolved + "/") === Comparison.EqualTo);
const target = find(targets, t => compareStrings(t.slice(0, resolved.length + 1), resolved + "/") === Comparison.EqualTo);
if (target === undefined) return;
const relative = getRelativePathFromDirectory(resolved, target, getCanonicalFileName);
+60 -62
View File
@@ -462,52 +462,46 @@ namespace ts {
return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.JSDocPropertyTag:
if ((node as JSDocPropertyLikeTag).isNameFirst) {
return visitNode(cbNode, (<JSDocPropertyLikeTag>node).name) ||
visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression);
}
else {
return visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocPropertyLikeTag>node).name);
}
case SyntaxKind.JSDocReturnTag:
return visitNode(cbNode, (<JSDocReturnTag>node).typeExpression);
case SyntaxKind.JSDocTypeTag:
return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
return visitNode(cbNode, (node as JSDocTag).tagName) ||
((node as JSDocPropertyLikeTag).isNameFirst
? visitNode(cbNode, (<JSDocPropertyLikeTag>node).name) ||
visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression)
: visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocPropertyLikeTag>node).name));
case SyntaxKind.JSDocAugmentsTag:
return visitNode(cbNode, (<JSDocAugmentsTag>node).class);
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (<JSDocAugmentsTag>node).class);
case SyntaxKind.JSDocTemplateTag:
return visitNode(cbNode, (<JSDocTemplateTag>node).constraint) || visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (<JSDocTemplateTag>node).constraint) ||
visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
case SyntaxKind.JSDocTypedefTag:
if ((node as JSDocTypedefTag).typeExpression &&
(node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression) {
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName);
}
else {
return visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression);
}
return visitNode(cbNode, (node as JSDocTag).tagName) ||
((node as JSDocTypedefTag).typeExpression &&
(node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression
? visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName)
: visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression));
case SyntaxKind.JSDocCallbackTag:
return visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
visitNode(cbNode, (node as JSDocCallbackTag).typeExpression);
case SyntaxKind.JSDocReturnTag:
case SyntaxKind.JSDocTypeTag:
case SyntaxKind.JSDocThisTag:
return visitNode(cbNode, (node as JSDocThisTag).typeExpression);
case SyntaxKind.JSDocEnumTag:
return visitNode(cbNode, (node as JSDocEnumTag).typeExpression);
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag).typeExpression);
case SyntaxKind.JSDocSignature:
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
forEach((<JSDocSignature>node).typeParameters, cbNode) ||
return forEach((<JSDocSignature>node).typeParameters, cbNode) ||
forEach((<JSDocSignature>node).parameters, cbNode) ||
visitNode(cbNode, (<JSDocSignature>node).type);
case SyntaxKind.JSDocTypeLiteral:
if ((node as JSDocTypeLiteral).jsDocPropertyTags) {
for (const tag of (node as JSDocTypeLiteral).jsDocPropertyTags!) {
visitNode(cbNode, tag);
}
}
return;
return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode);
case SyntaxKind.JSDocTag:
case SyntaxKind.JSDocClassTag:
return visitNode(cbNode, (node as JSDocTag).tagName);
case SyntaxKind.PartiallyEmittedExpression:
return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
}
@@ -1723,6 +1717,8 @@ namespace ts {
}
function currentNode(parsingContext: ParsingContext): Node | undefined {
// If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse.
//
// If there is an outstanding parse error that we've encountered, but not attached to
// some node, then we cannot get a node from the old source tree. This is because we
// want to mark the next node we encounter as being unusable.
@@ -1730,30 +1726,17 @@ namespace ts {
// Note: This may be too conservative. Perhaps we could reuse the node and set the bit
// on it (or its leftmost child) as having the error. For now though, being conservative
// is nice and likely won't ever affect perf.
if (parseErrorBeforeNextFinishedNode) {
return undefined;
}
if (!syntaxCursor) {
// if we don't have a cursor, we could never return a node from the old tree.
if (!syntaxCursor || !isReusableParsingContext(parsingContext) || parseErrorBeforeNextFinishedNode) {
return undefined;
}
const node = syntaxCursor.currentNode(scanner.getStartPos());
// Can't reuse a missing node.
if (nodeIsMissing(node)) {
return undefined;
}
// Can't reuse a node that intersected the change range.
if (node.intersectsChange) {
return undefined;
}
// Can't reuse a node that contains a parse error. This is necessary so that we
// produce the same set of errors again.
if (containsParseError(node)) {
if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) {
return undefined;
}
@@ -1794,6 +1777,23 @@ namespace ts {
return node;
}
function isReusableParsingContext(parsingContext: ParsingContext): boolean {
switch (parsingContext) {
case ParsingContext.ClassMembers:
case ParsingContext.SwitchClauses:
case ParsingContext.SourceElements:
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauseStatements:
case ParsingContext.EnumMembers:
case ParsingContext.TypeMembers:
case ParsingContext.VariableDeclarations:
case ParsingContext.JSDocParameters:
case ParsingContext.Parameters:
return true;
}
return false;
}
function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
switch (parsingContext) {
case ParsingContext.ClassMembers:
@@ -1820,25 +1820,23 @@ namespace ts {
case ParsingContext.Parameters:
return isReusableParameter(node);
case ParsingContext.RestProperties:
return false;
// Any other lists we do not care about reusing nodes in. But feel free to add if
// you can do so safely. Danger areas involve nodes that may involve speculative
// parsing. If speculative parsing is involved with the node, then the range the
// parser reached while looking ahead might be in the edited range (see the example
// in canReuseVariableDeclaratorNode for a good case of this).
case ParsingContext.HeritageClauses:
// case ParsingContext.HeritageClauses:
// This would probably be safe to reuse. There is no speculative parsing with
// heritage clauses.
case ParsingContext.TypeParameters:
// case ParsingContext.TypeParameters:
// This would probably be safe to reuse. There is no speculative parsing with
// type parameters. Note that that's because type *parameters* only occur in
// unambiguous *type* contexts. While type *arguments* occur in very ambiguous
// *expression* contexts.
case ParsingContext.TupleElementTypes:
// case ParsingContext.TupleElementTypes:
// This would probably be safe to reuse. There is no speculative parsing with
// tuple types.
@@ -1847,28 +1845,28 @@ namespace ts {
// produced from speculative parsing a < as a type argument list), we only have
// the types because speculative parsing succeeded. Thus, the lookahead never
// went past the end of the list and rewound.
case ParsingContext.TypeArguments:
// case ParsingContext.TypeArguments:
// Note: these are almost certainly not safe to ever reuse. Expressions commonly
// need a large amount of lookahead, and we should not reuse them as they may
// have actually intersected the edit.
case ParsingContext.ArgumentExpressions:
// case ParsingContext.ArgumentExpressions:
// This is not safe to reuse for the same reason as the 'AssignmentExpression'
// cases. i.e. a property assignment may end with an expression, and thus might
// have lookahead far beyond it's old node.
case ParsingContext.ObjectLiteralMembers:
// case ParsingContext.ObjectLiteralMembers:
// This is probably not safe to reuse. There can be speculative parsing with
// type names in a heritage clause. There can be generic names in the type
// name list, and there can be left hand side expressions (which can have type
// arguments.)
case ParsingContext.HeritageClauseElement:
// case ParsingContext.HeritageClauseElement:
// Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes
// on any given element. Same for children.
case ParsingContext.JsxAttributes:
case ParsingContext.JsxChildren:
// case ParsingContext.JsxAttributes:
// case ParsingContext.JsxChildren:
}
+148 -22
View File
@@ -73,7 +73,6 @@ namespace ts {
// TODO(shkamat): update this after reworking ts build API
export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
const existingDirectories = createMap<boolean>();
function getCanonicalFileName(fileName: string): string {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
// otherwise use toLowerCase as a canonical form.
@@ -84,7 +83,7 @@ namespace ts {
let text: string | undefined;
try {
performance.mark("beforeIORead");
text = system.readFile(fileName, options.charset);
text = compilerHost.readFile(fileName);
performance.mark("afterIORead");
performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
@@ -113,7 +112,12 @@ namespace ts {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
system.createDirectory(directoryPath);
if (compilerHost.createDirectory) {
compilerHost.createDirectory(directoryPath);
}
else {
system.createDirectory(directoryPath);
}
}
}
@@ -177,8 +181,7 @@ namespace ts {
const newLine = getNewLineCharacter(options, () => system.newLine);
const realpath = system.realpath && ((path: string) => system.realpath!(path));
return {
const compilerHost: CompilerHost = {
getSourceFile,
getDefaultLibLocation,
getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)),
@@ -194,7 +197,117 @@ namespace ts {
getEnvironmentVariable: name => system.getEnvironmentVariable ? system.getEnvironmentVariable(name) : "",
getDirectories: (path: string) => system.getDirectories(path),
realpath,
readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth)
readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth),
createDirectory: d => system.createDirectory(d)
};
return compilerHost;
}
/*@internal*/
export function changeCompilerHostToUseCache(
host: CompilerHost,
toPath: (fileName: string) => Path,
useCacheForSourceFile: boolean
) {
const originalReadFile = host.readFile;
const originalFileExists = host.fileExists;
const originalDirectoryExists = host.directoryExists;
const originalCreateDirectory = host.createDirectory;
const originalWriteFile = host.writeFile;
const originalGetSourceFile = host.getSourceFile;
const readFileCache = createMap<string | false>();
const fileExistsCache = createMap<boolean>();
const directoryExistsCache = createMap<boolean>();
const sourceFileCache = createMap<SourceFile>();
const readFileWithCache = (fileName: string): string | undefined => {
const key = toPath(fileName);
const value = readFileCache.get(key);
if (value !== undefined) return value || undefined;
return setReadFileCache(key, fileName);
};
const setReadFileCache = (key: Path, fileName: string) => {
const newValue = originalReadFile.call(host, fileName);
readFileCache.set(key, newValue || false);
return newValue;
};
host.readFile = fileName => {
const key = toPath(fileName);
const value = readFileCache.get(key);
if (value !== undefined) return value; // could be .d.ts from output
if (!fileExtensionIs(fileName, Extension.Json)) {
return originalReadFile.call(host, fileName);
}
return setReadFileCache(key, fileName);
};
if (useCacheForSourceFile) {
host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
const key = toPath(fileName);
const value = sourceFileCache.get(key);
if (value) return value;
const sourceFile = originalGetSourceFile.call(host, fileName, languageVersion, onError, shouldCreateNewSourceFile);
if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) {
sourceFileCache.set(key, sourceFile);
}
return sourceFile;
};
}
// fileExists for any kind of extension
host.fileExists = fileName => {
const key = toPath(fileName);
const value = fileExistsCache.get(key);
if (value !== undefined) return value;
const newValue = originalFileExists.call(host, fileName);
fileExistsCache.set(key, !!newValue);
return newValue;
};
host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
const key = toPath(fileName);
fileExistsCache.delete(key);
const value = readFileCache.get(key);
if (value && value !== data) {
readFileCache.delete(key);
sourceFileCache.delete(key);
}
else if (useCacheForSourceFile) {
const sourceFile = sourceFileCache.get(key);
if (sourceFile && sourceFile.text !== data) {
sourceFileCache.delete(key);
}
}
originalWriteFile.call(host, fileName, data, writeByteOrderMark, onError, sourceFiles);
};
// directoryExists
if (originalDirectoryExists && originalCreateDirectory) {
host.directoryExists = directory => {
const key = toPath(directory);
const value = directoryExistsCache.get(key);
if (value !== undefined) return value;
const newValue = originalDirectoryExists.call(host, directory);
directoryExistsCache.set(key, !!newValue);
return newValue;
};
host.createDirectory = directory => {
const key = toPath(directory);
directoryExistsCache.delete(key);
originalCreateDirectory.call(host, directory);
};
}
return {
originalReadFile,
originalFileExists,
originalDirectoryExists,
originalCreateDirectory,
originalWriteFile,
originalGetSourceFile,
readFileWithCache
};
}
@@ -674,7 +787,13 @@ namespace ts {
// Key is a file name. Value is the (non-empty, or undefined) list of files that redirect to it.
let redirectTargetsMap = createMultiMap<string>();
const filesByName = createMap<SourceFile | undefined>();
/**
* map with
* - SourceFile if present
* - false if sourceFile missing for source of project reference redirect
* - undefined otherwise
*/
const filesByName = createMap<SourceFile | false | undefined>();
let missingFilePaths: ReadonlyArray<Path> | undefined;
// stores 'filename -> file association' ignoring case
// used to track cases when two file names differ only in casing
@@ -683,6 +802,7 @@ namespace ts {
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
let resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined;
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
@@ -740,7 +860,7 @@ namespace ts {
}
}
missingFilePaths = arrayFrom(filesByName.keys(), p => <Path>p).filter(p => !filesByName.get(p));
missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined));
files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles);
processingDefaultLibFiles = undefined;
processingOtherFiles = undefined;
@@ -1453,7 +1573,7 @@ namespace ts {
}
function getSourceFileByPath(path: Path): SourceFile | undefined {
return filesByName.get(path);
return filesByName.get(path) || undefined;
}
function getDiagnosticsHelper<T extends Diagnostic>(
@@ -1990,7 +2110,7 @@ namespace ts {
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)));
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)) || undefined);
}
function getSourceFileFromReferenceWorker(
@@ -2121,7 +2241,7 @@ namespace ts {
}
}
return file;
return file || undefined;
}
let redirectedPath: Path | undefined;
@@ -2213,9 +2333,12 @@ namespace ts {
}
function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
filesByName.set(path, file);
if (redirectedPath) {
filesByName.set(redirectedPath, file);
filesByName.set(path, file || false);
}
else {
filesByName.set(path, file);
}
}
@@ -2231,7 +2354,6 @@ namespace ts {
if (!referencedProject) {
return undefined;
}
const out = referencedProject.commandLine.options.outFile || referencedProject.commandLine.options.out;
return out ?
changeExtension(out, Extension.Dts) :
@@ -2242,16 +2364,20 @@ namespace ts {
* 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 (mapFromFileToProjectReferenceRedirects === undefined) {
mapFromFileToProjectReferenceRedirects = createMap();
forEachResolvedProjectReference((referencedProject, referenceProjectPath) => {
// not input file from the referenced project, ignore
if (referencedProject &&
toPath(options.configFilePath!) !== referenceProjectPath) {
referencedProject.commandLine.fileNames.forEach(f =>
mapFromFileToProjectReferenceRedirects!.set(toPath(f), referenceProjectPath));
}
});
}
return referencedProject;
});
const referencedProjectPath = mapFromFileToProjectReferenceRedirects.get(toPath(fileName));
return referencedProjectPath && getResolvedProjectReferenceByPath(referencedProjectPath);
}
function forEachResolvedProjectReference<T>(
+47 -4
View File
@@ -337,17 +337,35 @@ namespace ts {
return result;
}
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number {
return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text);
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number;
/* @internal */
// tslint:disable-next-line:unified-signatures
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number;
export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number {
return sourceFile.getPositionOfLineAndCharacter ?
sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) :
computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits);
}
/* @internal */
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string): number {
export function computePositionOfLineAndCharacter(lineStarts: ReadonlyArray<number>, line: number, character: number, debugText?: string, allowEdits?: true): number {
if (line < 0 || line >= lineStarts.length) {
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
if (allowEdits) {
// Clamp line to nearest allowable value
line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line;
}
else {
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
}
}
const res = lineStarts[line] + character;
if (allowEdits) {
// Clamp to nearest allowable values to allow the underlying to be edited without crashing (accuracy is lost, instead)
// TODO: Somehow track edits between file as it was during the creation of sourcemap we have and the current file and
// apply them to the computed position to improve accuracy
return res > lineStarts[line + 1] ? lineStarts[line + 1] : typeof debugText === "string" && res > debugText.length ? debugText.length : res;
}
if (line < lineStarts.length - 1) {
Debug.assert(res < lineStarts[line + 1]);
}
@@ -967,7 +985,9 @@ namespace ts {
else {
result = text.substring(start, end); // No need to use all the fragments; no _ removal needed
}
if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) {
checkForIdentifierStartAfterNumericLiteral(start, decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific));
return {
type: SyntaxKind.NumericLiteral,
value: "" + +result // if value is not an integer, it can be safely coerced to a number
@@ -976,10 +996,33 @@ namespace ts {
else {
tokenValue = result;
const type = checkBigIntSuffix(); // if value is an integer, check whether it is a bigint
checkForIdentifierStartAfterNumericLiteral(start);
return { type, value: tokenValue };
}
}
function checkForIdentifierStartAfterNumericLiteral(numericStart: number, isScientific?: boolean) {
if (!isIdentifierStart(text.charCodeAt(pos), languageVersion)) {
return;
}
const identifierStart = pos;
const { length } = scanIdentifierParts();
if (length === 1 && text[identifierStart] === "n") {
if (isScientific) {
error(Diagnostics.A_bigint_literal_cannot_use_exponential_notation, numericStart, identifierStart - numericStart + 1);
}
else {
error(Diagnostics.A_bigint_literal_must_be_an_integer, numericStart, identifierStart - numericStart + 1);
}
}
else {
error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length);
pos = identifierStart;
}
}
function scanOctalDigits(): number {
const start = pos;
while (isOctalDigit(text.charCodeAt(pos))) {
+24 -14
View File
@@ -266,14 +266,24 @@ namespace ts {
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\s*$/;
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
export interface LineInfo {
getLineCount(): number;
getLineText(line: number): string;
}
export function getLineInfo(text: string, lineStarts: ReadonlyArray<number>): LineInfo {
return {
getLineCount: () => lineStarts.length,
getLineText: line => text.substring(lineStarts[line], lineStarts[line + 1])
};
}
/**
* Tries to find the sourceMappingURL comment at the end of a file.
* @param text The source text of the file.
* @param lineStarts The line starts of the file.
*/
export function tryGetSourceMappingURL(text: string, lineStarts: ReadonlyArray<number> = computeLineStarts(text)) {
for (let index = lineStarts.length - 1; index >= 0; index--) {
const line = text.substring(lineStarts[index], lineStarts[index + 1]);
export function tryGetSourceMappingURL(lineInfo: LineInfo) {
for (let index = lineInfo.getLineCount() - 1; index >= 0; index--) {
const line = lineInfo.getLineText(index);
const comment = sourceMapCommentRegExp.exec(line);
if (comment) {
return comment[1];
@@ -573,7 +583,10 @@ namespace ts {
}
function compareSourcePositions(left: SourceMappedPosition, right: SourceMappedPosition) {
return compareValues(left.sourceIndex, right.sourceIndex);
// Compares sourcePosition without comparing sourceIndex
// since the mappings are grouped by sourceIndex
Debug.assert(left.sourceIndex === right.sourceIndex);
return compareValues(left.sourcePosition, right.sourcePosition);
}
function compareGeneratedPositions(left: MappedPosition, right: MappedPosition) {
@@ -592,11 +605,9 @@ namespace ts {
const mapDirectory = getDirectoryPath(mapPath);
const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory;
const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory);
const generatedCanonicalFilePath = host.getCanonicalFileName(generatedAbsoluteFilePath) as Path;
const generatedFile = host.getSourceFileLike(generatedCanonicalFilePath);
const generatedFile = host.getSourceFileLike(generatedAbsoluteFilePath);
const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot));
const sourceFileCanonicalPaths = sourceFileAbsolutePaths.map(source => host.getCanonicalFileName(source) as Path);
const sourceToSourceIndexMap = createMapFromEntries(sourceFileCanonicalPaths.map((source, i) => [source, i] as [string, number]));
const sourceToSourceIndexMap = createMapFromEntries(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i] as [string, number]));
let decodedMappings: ReadonlyArray<MappedPosition> | undefined;
let generatedMappings: SortedReadonlyArray<MappedPosition> | undefined;
let sourceMappings: ReadonlyArray<SortedReadonlyArray<SourceMappedPosition>> | undefined;
@@ -608,16 +619,15 @@ namespace ts {
function processMapping(mapping: Mapping): MappedPosition {
const generatedPosition = generatedFile !== undefined
? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter)
? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter, /*allowEdits*/ true)
: -1;
let source: string | undefined;
let sourcePosition: number | undefined;
if (isSourceMapping(mapping)) {
const sourceFilePath = sourceFileCanonicalPaths[mapping.sourceIndex];
const sourceFile = host.getSourceFileLike(sourceFilePath);
const sourceFile = host.getSourceFileLike(sourceFileAbsolutePaths[mapping.sourceIndex]);
source = map.sources[mapping.sourceIndex];
sourcePosition = sourceFile !== undefined
? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter)
? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter, /*allowEdits*/ true)
: -1;
}
return {
+11 -1
View File
@@ -45,6 +45,7 @@ namespace ts {
reportInaccessibleThisError,
reportInaccessibleUniqueSymbolError,
reportPrivateInBaseOfClassExpression,
reportLikelyUnsafeImportRequiredError,
moduleResolverHost: host,
trackReferencedAmbientModule,
trackExternalModuleSymbolOfImportTypeNode
@@ -153,6 +154,14 @@ namespace ts {
}
}
function reportLikelyUnsafeImportRequiredError(specifier: string) {
if (errorNameNode) {
context.addDiagnostic(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary,
declarationNameToString(errorNameNode),
specifier));
}
}
function transformRoot(node: Bundle): Bundle;
function transformRoot(node: SourceFile): SourceFile;
function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle;
@@ -1091,7 +1100,8 @@ namespace ts {
if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) {
// We must add a temporary declaration for the extends clause expression
const newId = createOptimisticUniqueName(`${unescapeLeadingUnderscores(input.name!.escapedText)}_base`); // TODO: GH#18217
const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default";
const newId = createOptimisticUniqueName(`${oldId}_base`);
getSymbolAccessibilityDiagnostic = () => ({
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
errorNode: extendsClause,
@@ -389,6 +389,7 @@ namespace ts {
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
break;
case SyntaxKind.ConstructorType:
case SyntaxKind.ConstructSignature:
diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
break;
@@ -410,6 +411,7 @@ namespace ts {
}
break;
case SyntaxKind.FunctionType:
case SyntaxKind.FunctionDeclaration:
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1;
break;
+52 -18
View File
@@ -32,6 +32,8 @@ namespace ts {
pretty?: boolean;
traceResolution?: boolean;
/* @internal */ diagnostics?: boolean;
/* @internal */ extendedDiagnostics?: boolean;
}
enum BuildResultFlags {
@@ -326,6 +328,11 @@ namespace ts {
reportDiagnostic: DiagnosticReporter; // Technically we want to move it out and allow steps of actions on Solution, but for now just merge stuff in build host here
reportSolutionBuilderStatus: DiagnosticReporter;
// TODO: To do better with watch mode and normal build mode api that creates program and emits files
// This currently helps enable --diagnostics and --extendedDiagnostics
beforeCreateProgram?(options: CompilerOptions): void;
afterProgramEmitAndDiagnostics?(program: Program): void;
}
export interface SolutionBuilderHost extends SolutionBuilderHostBase {
@@ -426,6 +433,7 @@ namespace ts {
const missingRoots = createMap<true>();
let globalDependencyGraph: DependencyGraph | undefined;
const writeFileName = (s: string) => host.trace && host.trace(s);
let readFileWithCache = (f: string) => host.readFile(f);
// Watch state
const diagnostics = createFileMap<ReadonlyArray<Diagnostic>>(toPath);
@@ -997,7 +1005,6 @@ namespace ts {
}
}
function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags {
if (options.dry) {
reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj);
@@ -1030,6 +1037,9 @@ namespace ts {
options: configFile.options,
configFileParsingDiagnostics: configFile.errors
};
if (host.beforeCreateProgram) {
host.beforeCreateProgram(options);
}
const program = createProgram(programOptions);
// Don't emit anything in the presence of syntactic errors or options diagnostics
@@ -1041,14 +1051,6 @@ namespace ts {
return buildErrors(syntaxDiagnostics, BuildResultFlags.SyntaxErrors, "Syntactic");
}
// Don't emit .d.ts if there are decl file errors
if (getEmitDeclarations(program.getCompilerOptions())) {
const declDiagnostics = program.getDeclarationDiagnostics();
if (declDiagnostics.length) {
return buildErrors(declDiagnostics, BuildResultFlags.DeclarationEmitErrors, "Declaration file");
}
}
// Same as above but now for semantic diagnostics
const semanticDiagnostics = program.getSemanticDiagnostics();
if (semanticDiagnostics.length) {
@@ -1057,14 +1059,23 @@ namespace ts {
let newestDeclarationFileContentChangedTime = minimumDate;
let anyDtsChanged = false;
let emitDiagnostics: Diagnostic[] | undefined;
const reportEmitDiagnostic = (d: Diagnostic) => (emitDiagnostics || (emitDiagnostics = [])).push(d);
emitFilesAndReportErrors(program, reportEmitDiagnostic, writeFileName, /*reportSummary*/ undefined, (fileName, content, writeBom, onError) => {
let declDiagnostics: Diagnostic[] | undefined;
const reportDeclarationDiagnostics = (d: Diagnostic) => (declDiagnostics || (declDiagnostics = [])).push(d);
const outputFiles: OutputFile[] = [];
emitFilesAndReportErrors(program, reportDeclarationDiagnostics, writeFileName, /*reportSummary*/ undefined, (name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }));
// Don't emit .d.ts if there are decl file errors
if (declDiagnostics) {
return buildErrors(declDiagnostics, BuildResultFlags.DeclarationEmitErrors, "Declaration file");
}
// Actual Emit
const emitterDiagnostics = createDiagnosticCollection();
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
let priorChangeTime: Date | undefined;
if (!anyDtsChanged && isDeclarationFile(fileName)) {
if (!anyDtsChanged && isDeclarationFile(name)) {
// Check for unchanged .d.ts files
if (host.fileExists(fileName) && host.readFile(fileName) === content) {
priorChangeTime = host.getModifiedTime(fileName);
if (host.fileExists(name) && readFileWithCache(name) === text) {
priorChangeTime = host.getModifiedTime(name);
}
else {
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
@@ -1072,14 +1083,15 @@ namespace ts {
}
}
host.writeFile(fileName, content, writeBom, onError, emptyArray);
writeFile(host, emitterDiagnostics, name, text, writeByteOrderMark);
if (priorChangeTime !== undefined) {
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
unchangedOutputs.setValue(fileName, priorChangeTime);
unchangedOutputs.setValue(name, priorChangeTime);
}
});
if (emitDiagnostics) {
const emitDiagnostics = emitterDiagnostics.getDiagnostics();
if (emitDiagnostics.length) {
return buildErrors(emitDiagnostics, BuildResultFlags.EmitErrors, "Emit");
}
@@ -1089,12 +1101,18 @@ namespace ts {
};
diagnostics.removeKey(proj);
projectStatus.setValue(proj, status);
if (host.afterProgramEmitAndDiagnostics) {
host.afterProgramEmitAndDiagnostics(program);
}
return resultFlags;
function buildErrors(diagnostics: ReadonlyArray<Diagnostic>, errorFlags: BuildResultFlags, errorType: string) {
resultFlags |= errorFlags;
reportAndStoreErrors(proj, diagnostics);
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
if (host.afterProgramEmitAndDiagnostics) {
host.afterProgramEmitAndDiagnostics(program);
}
return resultFlags;
}
}
@@ -1167,6 +1185,15 @@ namespace ts {
function buildAllProjects(): ExitStatus {
if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); }
// TODO:: In watch mode as well to use caches for incremental build once we can invalidate caches correctly and have right api
// Override readFile for json files and output .d.ts to cache the text
const { originalReadFile, originalFileExists, originalDirectoryExists,
originalCreateDirectory, originalWriteFile, originalGetSourceFile,
readFileWithCache: newReadFileWithCache
} = changeCompilerHostToUseCache(host, toPath, /*useCacheForSourceFile*/ true);
const savedReadFileWithCache = readFileWithCache;
readFileWithCache = newReadFileWithCache;
const graph = getGlobalDependencyGraph();
reportBuildQueue(graph);
let anyFailed = false;
@@ -1217,6 +1244,13 @@ namespace ts {
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
}
reportErrorSummary();
host.readFile = originalReadFile;
host.fileExists = originalFileExists;
host.directoryExists = originalDirectoryExists;
host.createDirectory = originalCreateDirectory;
host.writeFile = originalWriteFile;
readFileWithCache = savedReadFileWithCache;
host.getSourceFile = originalGetSourceFile;
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
}
+31 -16
View File
@@ -1745,6 +1745,9 @@ namespace ts {
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
/* @internal */
export type AccessExpression = PropertyAccessExpression | ElementAccessExpression;
export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration {
kind: SyntaxKind.PropertyAccessExpression;
expression: LeftHandSideExpression;
@@ -2614,6 +2617,8 @@ namespace ts {
export interface SourceFileLike {
readonly text: string;
lineMap?: ReadonlyArray<number>;
/* @internal */
getPositionOfLineAndCharacter?(line: number, character: number, allowEdits?: true): number;
}
@@ -3103,7 +3108,7 @@ namespace ts {
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined;
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean;
/** Exclude accesses to private properties or methods with a `this` parameter that `type` doesn't satisfy. */
/* @internal */ isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode, type: Type, property: Symbol): boolean;
/* @internal */ isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean;
/** Follow all aliases to get the original symbol. */
getAliasedSymbol(symbol: Symbol): Symbol;
/** Follow a *single* alias to get the immediately aliased symbol. */
@@ -3141,6 +3146,7 @@ namespace ts {
/* @internal */ getNeverType(): Type;
/* @internal */ getUnionType(types: Type[], subtypeReduction?: UnionReduction): Type;
/* @internal */ createArrayType(elementType: Type): Type;
/* @internal */ getElementTypeOfArrayType(arrayType: Type): Type | undefined;
/* @internal */ createPromiseType(type: Type): Type;
/* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
@@ -3261,15 +3267,17 @@ namespace ts {
AllowUniqueESSymbolType = 1 << 20,
AllowEmptyIndexInfoType = 1 << 21,
IgnoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType,
// Errors (cont.)
AllowNodeModulesRelativePaths = 1 << 26,
/* @internal */ DoNotIncludeSymbolChain = 1 << 27, // Skip looking up and printing an accessible symbol chain
IgnoreErrors = AllowThisInObjectLiteral | AllowQualifedNameInPlaceOfIdentifier | AllowAnonymousIdentifier | AllowEmptyUnionOrIntersection | AllowEmptyTuple | AllowEmptyIndexInfoType | AllowNodeModulesRelativePaths,
// State
InObjectTypeLiteral = 1 << 22,
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
@@ -3650,6 +3658,8 @@ namespace ts {
originatingImport?: ImportDeclaration | ImportCall; // Import declaration which produced the symbol, present if the symbol is marked as uncallable but had call signatures in `resolveESModuleSymbol`
lateSymbol?: Symbol; // Late-bound symbol for a computed property
specifierCache?: Map<string>; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings
extendedContainers?: Symbol[]; // Containers (other than the parent) which this symbol is aliased in
extendedContainersByFile?: Map<Symbol[]>; // Containers (other than the parent) which this symbol is aliased in
variances?: Variance[]; // Alias symbol type argument variance cache
}
@@ -3667,15 +3677,17 @@ namespace ts {
Readonly = 1 << 3, // Readonly transient symbol
Partial = 1 << 4, // Synthetic property present in some but not all constituents
HasNonUniformType = 1 << 5, // Synthetic property with non-uniform type in constituents
ContainsPublic = 1 << 6, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 7, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
Late = 1 << 10, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 11, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 12, // Optional parameter
RestParameter = 1 << 13, // Rest parameter
Synthetic = SyntheticProperty | SyntheticMethod
HasLiteralType = 1 << 6, // Synthetic property with at least one literal type in constituents
ContainsPublic = 1 << 7, // Synthetic property with public constituent(s)
ContainsProtected = 1 << 8, // Synthetic property with protected constituent(s)
ContainsPrivate = 1 << 9, // Synthetic property with private constituent(s)
ContainsStatic = 1 << 10, // Synthetic property with static constituent(s)
Late = 1 << 11, // Late-bound symbol for a computed property with a dynamic name
ReverseMapped = 1 << 12, // Property of reverse-inferred homomorphic mapped type
OptionalParameter = 1 << 13, // Optional parameter
RestParameter = 1 << 14, // Rest parameter
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType
}
/* @internal */
@@ -4495,7 +4507,6 @@ namespace ts {
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalBigInt?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
/*@internal*/help?: boolean;
@@ -5010,6 +5021,9 @@ namespace ts {
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
createHash?(data: string): string;
// TODO: later handle this in better way in builder host instead once the api for tsbuild finalizes and doesnt use compilerHost as base
/*@internal*/createDirectory?(directory: string): void;
}
/* @internal */
@@ -5521,9 +5535,9 @@ namespace ts {
/* @internal */
export interface DocumentPositionMapperHost {
getSourceFileLike(path: Path): SourceFileLike | undefined;
getSourceFileLike(fileName: string): SourceFileLike | undefined;
getCanonicalFileName(path: string): string;
log?(text: string): void;
log(text: string): void;
}
/**
@@ -5577,6 +5591,7 @@ namespace ts {
reportInaccessibleThisError?(): void;
reportPrivateInBaseOfClassExpression?(propertyName: string): void;
reportInaccessibleUniqueSymbolError?(): void;
reportLikelyUnsafeImportRequiredError?(specifier: string): void;
moduleResolverHost?: ModuleSpecifierResolutionHost & { getSourceFiles(): ReadonlyArray<SourceFile>, getCommonSourceDirectory(): string };
trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void;
trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void;
+67 -39
View File
@@ -1,4 +1,3 @@
/** Non-internal stuff goes here */
namespace ts {
export function isExternalModuleNameRelative(moduleName: string): boolean {
// TypeScript 1.0 spec (April 2014): 11.2.1
@@ -2091,10 +2090,9 @@ namespace ts {
}
export function isJSDocConstructSignature(node: Node) {
return node.kind === SyntaxKind.JSDocFunctionType &&
(node as JSDocFunctionType).parameters.length > 0 &&
(node as JSDocFunctionType).parameters[0].name &&
((node as JSDocFunctionType).parameters[0].name as Identifier).escapedText === "new";
const param = isJSDocFunctionType(node) ? firstOrUndefined(node.parameters) : undefined;
const name = tryCast(param && param.name, isIdentifier);
return !!name && name.escapedText === "new";
}
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag {
@@ -2123,7 +2121,7 @@ namespace ts {
: undefined;
}
function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
export function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
switch (node.kind) {
case SyntaxKind.VariableStatement:
const v = getSingleVariableOfVariableStatement(node);
@@ -3404,7 +3402,7 @@ namespace ts {
return combinePaths(newDirPath, sourceFilePath);
}
export function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: ReadonlyArray<SourceFile>) {
export function writeFile(host: { writeFile: WriteFileCallback; }, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: ReadonlyArray<SourceFile>) {
host.writeFile(fileName, data, writeByteOrderMark, hostErrorMessage => {
diagnostics.add(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage));
}, sourceFiles);
@@ -4567,6 +4565,35 @@ namespace ts {
export function isObjectTypeDeclaration(node: Node): node is ObjectTypeDeclaration {
return isClassLike(node) || isInterfaceDeclaration(node) || isTypeLiteralNode(node);
}
export function isTypeNodeKind(kind: SyntaxKind) {
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|| kind === SyntaxKind.AnyKeyword
|| kind === SyntaxKind.UnknownKeyword
|| kind === SyntaxKind.NumberKeyword
|| kind === SyntaxKind.BigIntKeyword
|| kind === SyntaxKind.ObjectKeyword
|| kind === SyntaxKind.BooleanKeyword
|| kind === SyntaxKind.StringKeyword
|| kind === SyntaxKind.SymbolKeyword
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.VoidKeyword
|| kind === SyntaxKind.UndefinedKeyword
|| kind === SyntaxKind.NullKeyword
|| kind === SyntaxKind.NeverKeyword
|| kind === SyntaxKind.ExpressionWithTypeArguments
|| kind === SyntaxKind.JSDocAllType
|| kind === SyntaxKind.JSDocUnknownType
|| kind === SyntaxKind.JSDocNullableType
|| kind === SyntaxKind.JSDocNonNullableType
|| kind === SyntaxKind.JSDocOptionalType
|| kind === SyntaxKind.JSDocFunctionType
|| kind === SyntaxKind.JSDocVariadicType;
}
export function isAccessExpression(node: Node): node is AccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression;
}
}
namespace ts {
@@ -6112,6 +6139,10 @@ namespace ts {
|| kind === SyntaxKind.TemplateTail;
}
export function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier {
return isImportSpecifier(node) || isExportSpecifier(node);
}
export function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken {
return node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind);
}
@@ -6286,31 +6317,6 @@ namespace ts {
// Type
function isTypeNodeKind(kind: SyntaxKind) {
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|| kind === SyntaxKind.AnyKeyword
|| kind === SyntaxKind.UnknownKeyword
|| kind === SyntaxKind.NumberKeyword
|| kind === SyntaxKind.BigIntKeyword
|| kind === SyntaxKind.ObjectKeyword
|| kind === SyntaxKind.BooleanKeyword
|| kind === SyntaxKind.StringKeyword
|| kind === SyntaxKind.SymbolKeyword
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.VoidKeyword
|| kind === SyntaxKind.UndefinedKeyword
|| kind === SyntaxKind.NullKeyword
|| kind === SyntaxKind.NeverKeyword
|| kind === SyntaxKind.ExpressionWithTypeArguments
|| kind === SyntaxKind.JSDocAllType
|| kind === SyntaxKind.JSDocUnknownType
|| kind === SyntaxKind.JSDocNullableType
|| kind === SyntaxKind.JSDocNonNullableType
|| kind === SyntaxKind.JSDocOptionalType
|| kind === SyntaxKind.JSDocFunctionType
|| kind === SyntaxKind.JSDocVariadicType;
}
/**
* Node test that determines whether a node is a valid type node.
* This differs from the `isPartOfTypeNode` function which determines whether a node is *part*
@@ -6838,7 +6844,7 @@ namespace ts {
// TODO: determine what this does before making it public.
/* @internal */
export function isJSDocTag(node: Node): boolean {
export function isJSDocTag(node: Node): node is JSDocTag {
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
}
@@ -6980,8 +6986,8 @@ namespace ts {
getSourceMapSourceConstructor: () => <any>SourceMapSource,
};
export function formatStringFromArgs(text: string, args: ArrayLike<string>, baseIndex = 0): string {
return text.replace(/{(\d+)}/g, (_match, index: string) => Debug.assertDefined(args[+index + baseIndex]));
export function formatStringFromArgs(text: string, args: ArrayLike<string | number>, baseIndex = 0): string {
return text.replace(/{(\d+)}/g, (_match, index: string) => "" + Debug.assertDefined(args[+index + baseIndex]));
}
export let localizedDiagnosticMessages: MapLike<string> | undefined;
@@ -7060,7 +7066,7 @@ namespace ts {
};
}
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage, ...args: (string | undefined)[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain | undefined, message: DiagnosticMessage): DiagnosticMessageChain {
let text = getLocaleSpecificMessage(message);
@@ -7685,16 +7691,38 @@ namespace ts {
return path;
}
// check path for these segments: '', '.'. '..'
const relativePathSegmentRegExp = /(^|\/)\.{0,2}($|\/)/;
function comparePathsWorker(a: string, b: string, componentComparer: (a: string, b: string) => Comparison) {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
// NOTE: Performance optimization - shortcut if the root segments differ as there would be no
// need to perform path reduction.
const aRoot = a.substring(0, getRootLength(a));
const bRoot = b.substring(0, getRootLength(b));
const result = compareStringsCaseInsensitive(aRoot, bRoot);
if (result !== Comparison.EqualTo) {
return result;
}
// NOTE: Performance optimization - shortcut if there are no relative path segments in
// the non-root portion of the path
const aRest = a.substring(aRoot.length);
const bRest = b.substring(bRoot.length);
if (!relativePathSegmentRegExp.test(aRest) && !relativePathSegmentRegExp.test(bRest)) {
return componentComparer(aRest, bRest);
}
// The path contains a relative path segment. Normalize the paths and perform a slower component
// by component comparison.
const aComponents = reducePathComponents(getPathComponents(a));
const bComponents = reducePathComponents(getPathComponents(b));
const sharedLength = Math.min(aComponents.length, bComponents.length);
for (let i = 0; i < sharedLength; i++) {
const stringComparer = i === 0 ? compareStringsCaseInsensitive : componentComparer;
const result = stringComparer(aComponents[i], bComponents[i]);
for (let i = 1; i < sharedLength; i++) {
const result = componentComparer(aComponents[i], bComponents[i]);
if (result !== Comparison.EqualTo) {
return result;
}
+2 -2
View File
@@ -37,7 +37,7 @@ namespace ts.server {
private sequence = 0;
private lineMaps: Map<number[]> = createMap<number[]>();
private messages: string[] = [];
private lastRenameEntry: RenameEntry;
private lastRenameEntry: RenameEntry | undefined;
constructor(private host: SessionClientHost) {
}
@@ -431,7 +431,7 @@ namespace ts.server {
this.getRenameInfo(fileName, position, findInStrings, findInComments);
}
return this.lastRenameEntry.locations;
return this.lastRenameEntry!.locations;
}
private decodeNavigationBarItems(items: protocol.NavigationBarItem[] | undefined, fileName: string, lineMap: number[]): NavigationBarItem[] {
+1 -1
View File
@@ -215,7 +215,7 @@ namespace fakes {
private _setParentNodes: boolean;
private _sourceFiles: collections.SortedMap<string, ts.SourceFile>;
private _parseConfigHost: ParseConfigHost;
private _parseConfigHost: ParseConfigHost | undefined;
private _newLine: string;
constructor(sys: System | vfs.FileSystem, options = ts.getDefaultCompilerOptions(), setParentNodes = false) {
+12 -16
View File
@@ -158,7 +158,7 @@ namespace FourSlash {
public lastKnownMarker = "";
// The file that's currently 'opened'
public activeFile: FourSlashFile;
public activeFile!: FourSlashFile;
// Whether or not we should format on keystrokes
public enableFormatting = true;
@@ -571,7 +571,8 @@ namespace FourSlash {
public verifyNoErrors() {
ts.forEachKey(this.inputFiles, fileName => {
if (!ts.isAnySupportedFileExtension(fileName)
|| !this.getProgram().getCompilerOptions().allowJs && !ts.extensionIsTS(ts.extensionFromPath(fileName))) return;
|| Harness.getConfigNameFromFileName(fileName)
|| !this.getProgram().getCompilerOptions().allowJs && !ts.resolutionExtensionIsTSOrJson(ts.extensionFromPath(fileName))) return;
const errors = this.getDiagnostics(fileName).filter(e => e.category !== ts.DiagnosticCategory.Suggestion);
if (errors.length) {
this.printErrorLog(/*expectErrors*/ false, errors);
@@ -599,7 +600,7 @@ namespace FourSlash {
throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName);
}
const evaluation = new Function(`${emit.outputFiles[0].text};\r\nreturn (${expr});`)();
const evaluation = new Function(`${emit.outputFiles[0].text};\r\nreturn (${expr});`)(); // tslint:disable-line:function-constructor
if (evaluation !== value) {
this.raiseError(`Expected evaluation of expression "${expr}" to equal "${value}", but got "${evaluation}"`);
}
@@ -854,9 +855,9 @@ namespace FourSlash {
}
/** Use `getProgram` instead of accessing this directly. */
private _program: ts.Program;
private _program: ts.Program | undefined;
/** Use `getChecker` instead of accessing this directly. */
private _checker: ts.TypeChecker;
private _checker: ts.TypeChecker | undefined;
private getProgram(): ts.Program {
return this._program || (this._program = this.languageService.getProgram()!); // TODO: GH#18217
@@ -2783,11 +2784,6 @@ Actual: ${stringify(fullActual)}`);
assert.deepEqual(unique(this.getApplicableRefactorsAtSelection(), r => r.name), names);
}
public verifyRefactor({ name, actionName, refactors }: FourSlashInterface.VerifyRefactorOptions) {
const actualRefactors = this.getApplicableRefactorsAtSelection().filter(r => r.name === name && r.actions.some(a => a.name === actionName));
this.assertObjectsEqual(actualRefactors, refactors);
}
public verifyApplicableRefactorAvailableForRange(negative: boolean) {
const ranges = this.getRanges();
if (!(ranges && ranges.length === 1)) {
@@ -3738,7 +3734,7 @@ namespace FourSlashInterface {
}
export class VerifyNegatable {
public not: VerifyNegatable;
public not: VerifyNegatable | undefined;
constructor(protected state: FourSlash.TestState, private negative = false) {
if (!negative) {
@@ -3822,10 +3818,6 @@ namespace FourSlashInterface {
this.state.verifyRefactorsAvailable(names);
}
public refactor(options: VerifyRefactorOptions) {
this.state.verifyRefactor(options);
}
public refactorAvailable(name: string, actionName?: string) {
this.state.verifyRefactorAvailable(this.negative, name, actionName);
}
@@ -4447,7 +4439,7 @@ namespace FourSlashInterface {
export const keywords: ReadonlyArray<ExpectedCompletionEntryObject> = keywordsWithUndefined.filter(k => k.name !== "undefined");
export const typeKeywords: ReadonlyArray<ExpectedCompletionEntryObject> =
["false", "null", "true", "void", "any", "boolean", "keyof", "never", "number", "object", "string", "symbol", "undefined", "unique", "unknown"].map(keywordEntry);
["false", "null", "true", "void", "any", "boolean", "keyof", "never", "number", "object", "string", "symbol", "undefined", "unique", "unknown", "bigint"].map(keywordEntry);
const globalTypeDecls: ReadonlyArray<ExpectedCompletionEntryObject> = [
interfaceEntry("Symbol"),
@@ -4458,6 +4450,8 @@ namespace FourSlashInterface {
interfaceEntry("ObjectConstructor"),
constEntry("Function"),
interfaceEntry("FunctionConstructor"),
typeEntry("ThisParameterType"),
typeEntry("OmitThisParameter"),
interfaceEntry("CallableFunction"),
interfaceEntry("NewableFunction"),
interfaceEntry("IArguments"),
@@ -4783,6 +4777,7 @@ namespace FourSlashInterface {
"package",
"yield",
"async",
"await",
].map(keywordEntry);
// TODO: many of these are inappropriate to always provide
@@ -4915,6 +4910,7 @@ namespace FourSlashInterface {
"package",
"yield",
"async",
"await",
].map(keywordEntry);
export const globalKeywordsPlusUndefined: ReadonlyArray<ExpectedCompletionEntryObject> = (() => {
+2 -4
View File
@@ -28,12 +28,10 @@ var assert: typeof _chai.assert = _chai.assert;
};
}
var global: NodeJS.Global = Function("return this").call(undefined);
var global: NodeJS.Global = Function("return this").call(undefined); // tslint:disable-line:function-constructor
declare var window: {};
declare var XMLHttpRequest: {
new(): XMLHttpRequest;
};
declare var XMLHttpRequest: new() => XMLHttpRequest;
interface XMLHttpRequest {
readonly readyState: number;
readonly responseText: string;
+3 -3
View File
@@ -289,8 +289,8 @@ namespace Harness.LanguageService {
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost {
private nativeHost: NativeLanguageServiceHost;
public getModuleResolutionsForFile: (fileName: string) => string;
public getTypeReferenceDirectiveResolutionsForFile: (fileName: string) => string;
public getModuleResolutionsForFile: ((fileName: string) => string) | undefined;
public getTypeReferenceDirectiveResolutionsForFile: ((fileName: string) => string) | undefined;
constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
super(cancellationToken, options);
@@ -639,7 +639,7 @@ namespace Harness.LanguageService {
// Server adapter
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
private client: ts.server.SessionClient;
private client!: ts.server.SessionClient;
constructor(cancellationToken: ts.HostCancellationToken | undefined, settings: ts.CompilerOptions | undefined) {
super(cancellationToken, settings);
+1 -1
View File
@@ -69,7 +69,7 @@ namespace Harness.SourceMapRecorder {
SourceMapDecoder.initializeSourceMapDecoding(sourceMapData);
sourceMapRecorder.WriteLine("===================================================================");
sourceMapRecorder.WriteLine("JsFile: " + sourceMapData.sourceMap.file);
sourceMapRecorder.WriteLine("mapUrl: " + ts.tryGetSourceMappingURL(jsFile.text, jsLineMap));
sourceMapRecorder.WriteLine("mapUrl: " + ts.tryGetSourceMappingURL(ts.getLineInfo(jsFile.text, jsLineMap)));
sourceMapRecorder.WriteLine("sourceRoot: " + sourceMapData.sourceMap.sourceRoot);
sourceMapRecorder.WriteLine("sources: " + sourceMapData.sourceMap.sources);
if (sourceMapData.sourceMap.sourcesContent) {
+1 -1
View File
@@ -21,7 +21,7 @@ interface TypeWriterResult {
}
class TypeWriterWalker {
currentSourceFile: ts.SourceFile;
currentSourceFile!: ts.SourceFile;
private checker: ts.TypeChecker;
+1 -1
View File
@@ -341,7 +341,7 @@ interface Array<T> {}`
private readonly currentDirectory: string;
private readonly dynamicPriorityWatchFile: HostWatchFile | undefined;
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
public require: (initialPath: string, moduleName: string) => server.RequireResult;
public require: ((initialPath: string, moduleName: string) => server.RequireResult) | undefined;
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
+12 -2
View File
@@ -295,6 +295,16 @@ interface FunctionConstructor {
declare const Function: FunctionConstructor;
/**
* Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter.
*/
type ThisParameterType<T> = T extends (this: unknown, ...args: any[]) => any ? unknown : T extends (this: infer U, ...args: any[]) => any ? U : unknown;
/**
* Removes the 'this' parameter from a function type.
*/
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T;
interface CallableFunction extends Function {
/**
* Calls the function with the specified object as the this value and the elements of specified array as the arguments.
@@ -317,7 +327,7 @@ interface CallableFunction extends Function {
* @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>(this: T, thisArg: ThisParameterType<T>): OmitThisParameter<T>;
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;
@@ -347,7 +357,7 @@ interface NewableFunction extends Function {
* @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<T>(this: T, thisArg: any): T;
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;
+258 -14
View File
@@ -123,11 +123,22 @@ namespace ts.server {
export interface FileStats {
readonly js: number;
readonly jsSize?: number;
readonly jsx: number;
readonly jsxSize?: number;
readonly ts: number;
readonly tsSize?: number;
readonly tsx: number;
readonly tsxSize?: number;
readonly dts: number;
readonly dtsSize?: number;
readonly deferred: number;
readonly deferredSize?: number;
}
export interface OpenFileInfo {
@@ -331,6 +342,7 @@ namespace ts.server {
FailedLookupLocation = "Directory of Failed lookup locations in module resolution",
TypeRoots = "Type root directory",
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
MissingSourceMapFile = "Missing source map file"
}
const enum ConfigFileWatcherStatus {
@@ -426,7 +438,8 @@ namespace ts.server {
/**
* Container of all known scripts
*/
private readonly filenameToScriptInfo = createMap<ScriptInfo>();
/*@internal*/
readonly filenameToScriptInfo = createMap<ScriptInfo>();
private readonly scriptInfoInNodeModulesWatchers = createMap <ScriptInfoInNodeModulesWatcher>();
/**
* Contains all the deleted script info's version information so that
@@ -468,7 +481,7 @@ namespace ts.server {
*/
private readonly openFilesWithNonRootedDiskPath = createMap<ScriptInfo>();
private compilerOptionsForInferredProjects: CompilerOptions;
private compilerOptionsForInferredProjects: CompilerOptions | undefined;
private compilerOptionsForInferredProjectsPerProjectRoot = createMap<CompilerOptions>();
/**
* Project size for configured or external projects
@@ -490,7 +503,7 @@ namespace ts.server {
private pendingProjectUpdates = createMap<Project>();
/* @internal */
pendingEnsureProjectForOpenFiles: boolean;
pendingEnsureProjectForOpenFiles = false;
readonly currentDirectory: NormalizedPath;
readonly toCanonicalFileName: (f: string) => string;
@@ -933,10 +946,42 @@ namespace ts.server {
// this file and set of inferred projects
info.delayReloadNonMixedContentFile();
this.delayUpdateProjectGraphs(info.containingProjects);
this.handleSourceMapProjects(info);
}
}
}
private handleSourceMapProjects(info: ScriptInfo) {
// Change in d.ts, update source projects as well
if (info.sourceMapFilePath) {
if (isString(info.sourceMapFilePath)) {
const sourceMapFileInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
this.delayUpdateSourceInfoProjects(sourceMapFileInfo && sourceMapFileInfo.sourceInfos);
}
else {
this.delayUpdateSourceInfoProjects(info.sourceMapFilePath.sourceInfos);
}
}
// Change in mapInfo, update declarationProjects and source projects
this.delayUpdateSourceInfoProjects(info.sourceInfos);
if (info.declarationInfoPath) {
this.delayUpdateProjectsOfScriptInfoPath(info.declarationInfoPath);
}
}
private delayUpdateSourceInfoProjects(sourceInfos: Map<true> | undefined) {
if (sourceInfos) {
sourceInfos.forEach((_value, path) => this.delayUpdateProjectsOfScriptInfoPath(path as Path));
}
}
private delayUpdateProjectsOfScriptInfoPath(path: Path) {
const info = this.getScriptInfoForPath(path);
if (info) {
this.delayUpdateProjectGraphs(info.containingProjects);
}
}
private handleDeletedFile(info: ScriptInfo) {
this.stopWatchingScriptInfo(info);
@@ -950,6 +995,15 @@ namespace ts.server {
// update projects to make sure that set of referenced files is correct
this.delayUpdateProjectGraphs(containingProjects);
this.handleSourceMapProjects(info);
info.closeSourceMapFileWatcher();
// need to recalculate source map from declaration file
if (info.declarationInfoPath) {
const declarationInfo = this.getScriptInfoForPath(info.declarationInfoPath);
if (declarationInfo) {
declarationInfo.sourceMapFilePath = undefined;
}
}
}
}
@@ -1223,7 +1277,8 @@ namespace ts.server {
private setConfigFileExistenceByNewConfiguredProject(project: ConfiguredProject) {
const configFileExistenceInfo = this.getConfigFileExistenceInfo(project);
if (configFileExistenceInfo) {
Debug.assert(configFileExistenceInfo.exists);
// The existance might not be set if the file watcher is not invoked by the time config project is created by external project
configFileExistenceInfo.exists = true;
// close existing watcher
if (configFileExistenceInfo.configFileWatcherForRootOfInferredProject) {
const configFileName = project.getConfigFilePath();
@@ -1600,7 +1655,7 @@ namespace ts.server {
setProjectOptionsUsed(project);
const data: ProjectInfoTelemetryEventData = {
projectId: this.host.createSHA256Hash(project.projectName),
fileStats: countEachFileTypes(project.getScriptInfos()),
fileStats: countEachFileTypes(project.getScriptInfos(), /*includeSizes*/ true),
compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilationSettings()),
typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()),
extends: projectOptions && projectOptions.configHasExtendsProperty,
@@ -1925,7 +1980,7 @@ namespace ts.server {
}
private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject {
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects;
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects!; // TODO: GH#18217
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath, currentDirectory, this.currentPluginConfigOverrides);
if (isSingleInferredProject) {
this.inferredProjects.unshift(project);
@@ -2184,6 +2239,150 @@ namespace ts.server {
return this.filenameToScriptInfo.get(fileName);
}
/*@internal*/
getDocumentPositionMapper(project: Project, generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined {
// Since declaration info and map file watches arent updating project's directory structure host (which can cache file structure) use host
const declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient(generatedFileName, project.currentDirectory, this.host);
if (!declarationInfo) return undefined;
// Try to get from cache
declarationInfo.getSnapshot(); // Ensure synchronized
if (isString(declarationInfo.sourceMapFilePath)) {
// Ensure mapper is synchronized
const sourceMapFileInfo = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
if (sourceMapFileInfo) {
sourceMapFileInfo.getSnapshot();
if (sourceMapFileInfo.documentPositionMapper !== undefined) {
sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo.sourceInfos);
return sourceMapFileInfo.documentPositionMapper ? sourceMapFileInfo.documentPositionMapper : undefined;
}
}
declarationInfo.sourceMapFilePath = undefined;
}
else if (declarationInfo.sourceMapFilePath) {
declarationInfo.sourceMapFilePath.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, declarationInfo.sourceMapFilePath.sourceInfos);
return undefined;
}
else if (declarationInfo.sourceMapFilePath !== undefined) {
// Doesnt have sourceMap
return undefined;
}
// Create the mapper
let sourceMapFileInfo: ScriptInfo | undefined;
let mapFileNameFromDeclarationInfo: string | undefined;
let readMapFile: ReadMapFile | undefined = (mapFileName, mapFileNameFromDts) => {
const mapInfo = this.getOrCreateScriptInfoNotOpenedByClient(mapFileName, project.currentDirectory, this.host);
if (!mapInfo) {
mapFileNameFromDeclarationInfo = mapFileNameFromDts;
return undefined;
}
sourceMapFileInfo = mapInfo;
const snap = mapInfo.getSnapshot();
if (mapInfo.documentPositionMapper !== undefined) return mapInfo.documentPositionMapper;
return snap.getText(0, snap.getLength());
};
const projectName = project.projectName;
const documentPositionMapper = getDocumentPositionMapper(
{ getCanonicalFileName: this.toCanonicalFileName, log: s => this.logger.info(s), getSourceFileLike: f => this.getSourceFileLike(f, projectName, declarationInfo) },
declarationInfo.fileName,
declarationInfo.getLineInfo(),
readMapFile
);
readMapFile = undefined; // Remove ref to project
if (sourceMapFileInfo) {
declarationInfo.sourceMapFilePath = sourceMapFileInfo.path;
sourceMapFileInfo.declarationInfoPath = declarationInfo.path;
sourceMapFileInfo.documentPositionMapper = documentPositionMapper || false;
sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo.sourceInfos);
}
else if (mapFileNameFromDeclarationInfo) {
declarationInfo.sourceMapFilePath = {
watcher: this.addMissingSourceMapFile(
project.currentDirectory === this.currentDirectory ?
mapFileNameFromDeclarationInfo :
getNormalizedAbsolutePath(mapFileNameFromDeclarationInfo, project.currentDirectory),
declarationInfo.path
),
sourceInfos: this.addSourceInfoToSourceMap(sourceFileName, project)
};
}
else {
declarationInfo.sourceMapFilePath = false;
}
return documentPositionMapper;
}
private addSourceInfoToSourceMap(sourceFileName: string | undefined, project: Project, sourceInfos?: Map<true>) {
if (sourceFileName) {
// Attach as source
const sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient(sourceFileName, project.currentDirectory, project.directoryStructureHost)!;
(sourceInfos || (sourceInfos = createMap())).set(sourceInfo.path, true);
}
return sourceInfos;
}
private addMissingSourceMapFile(mapFileName: string, declarationInfoPath: Path) {
const fileWatcher = this.watchFactory.watchFile(
this.host,
mapFileName,
() => {
const declarationInfo = this.getScriptInfoForPath(declarationInfoPath);
if (declarationInfo && declarationInfo.sourceMapFilePath && !isString(declarationInfo.sourceMapFilePath)) {
// Update declaration and source projects
this.delayUpdateProjectGraphs(declarationInfo.containingProjects);
this.delayUpdateSourceInfoProjects(declarationInfo.sourceMapFilePath.sourceInfos);
declarationInfo.closeSourceMapFileWatcher();
}
},
PollingInterval.High,
WatchType.MissingSourceMapFile,
);
return fileWatcher;
}
/*@internal*/
getSourceFileLike(fileName: string, projectNameOrProject: string | Project, declarationInfo?: ScriptInfo) {
const project = (projectNameOrProject as Project).projectName ? projectNameOrProject as Project : this.findProject(projectNameOrProject as string);
if (project) {
const path = project.toPath(fileName);
const sourceFile = project.getSourceFile(path);
if (sourceFile && sourceFile.resolvedPath === path) return sourceFile;
}
// Need to look for other files.
const info = this.getOrCreateScriptInfoNotOpenedByClient(fileName, (project || this).currentDirectory, project ? project.directoryStructureHost : this.host);
if (!info) return undefined;
// Attach as source
if (declarationInfo && isString(declarationInfo.sourceMapFilePath) && info !== declarationInfo) {
const sourceMapInfo = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
if (sourceMapInfo) {
(sourceMapInfo.sourceInfos || (sourceMapInfo.sourceInfos = createMap())).set(info.path, true);
}
}
// Key doesnt matter since its only for text and lines
if (info.cacheSourceFile) return info.cacheSourceFile.sourceFile;
// Create sourceFileLike
if (!info.sourceFileLike) {
info.sourceFileLike = {
get text() {
Debug.fail("shouldnt need text");
return "";
},
getLineAndCharacterOfPosition: pos => {
const lineOffset = info.positionToLineOffset(pos);
return { line: lineOffset.line - 1, character: lineOffset.offset - 1 };
},
getPositionOfLineAndCharacter: (line, character, allowEdits) => info.lineOffsetToPosition(line + 1, character + 1, allowEdits)
};
}
return info.sourceFileLike;
}
setHostConfiguration(args: protocol.ConfigureRequestArguments) {
if (args.file) {
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file));
@@ -2405,7 +2604,7 @@ namespace ts.server {
/** @internal */
fileExists(fileName: NormalizedPath): boolean {
return this.filenameToScriptInfo.has(fileName) || this.host.fileExists(fileName);
return !!this.getScriptInfoForNormalizedPath(fileName) || this.host.fileExists(fileName);
}
private findExternalProjectContainingOpenScriptInfo(info: ScriptInfo): ExternalProject | undefined {
@@ -2479,13 +2678,7 @@ namespace ts.server {
// when some file/s were closed which resulted in project removal.
// It was then postponed to cleanup these script infos so that they can be reused if
// the file from that old project is reopened because of opening file from here.
this.filenameToScriptInfo.forEach(info => {
if (!info.isScriptOpen() && info.isOrphan()) {
// if there are not projects that include this script info - delete it
this.stopWatchingScriptInfo(info);
this.deleteScriptInfo(info);
}
});
this.removeOrphanScriptInfos();
this.printProjects();
@@ -2528,6 +2721,57 @@ namespace ts.server {
}
}
private removeOrphanScriptInfos() {
const toRemoveScriptInfos = cloneMap(this.filenameToScriptInfo);
this.filenameToScriptInfo.forEach(info => {
// If script info is open or orphan, retain it and its dependencies
if (!info.isScriptOpen() && info.isOrphan()) {
// Otherwise if there is any source info that is alive, this alive too
if (!info.sourceMapFilePath) return;
let sourceInfos: Map<true> | undefined;
if (isString(info.sourceMapFilePath)) {
const sourceMapInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
sourceInfos = sourceMapInfo && sourceMapInfo.sourceInfos;
}
else {
sourceInfos = info.sourceMapFilePath.sourceInfos;
}
if (!sourceInfos) return;
if (!forEachKey(sourceInfos, path => {
const info = this.getScriptInfoForPath(path as Path);
return !!info && (info.isScriptOpen() || !info.isOrphan());
})) {
return;
}
}
// Retain this script info
toRemoveScriptInfos.delete(info.path);
if (info.sourceMapFilePath) {
let sourceInfos: Map<true> | undefined;
if (isString(info.sourceMapFilePath)) {
// And map file info and source infos
toRemoveScriptInfos.delete(info.sourceMapFilePath);
const sourceMapInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
sourceInfos = sourceMapInfo && sourceMapInfo.sourceInfos;
}
else {
sourceInfos = info.sourceMapFilePath.sourceInfos;
}
if (sourceInfos) {
sourceInfos.forEach((_value, path) => toRemoveScriptInfos.delete(path));
}
}
});
toRemoveScriptInfos.forEach(info => {
// if there are not projects that include this script info - delete it
this.stopWatchingScriptInfo(info);
this.deleteScriptInfo(info);
info.closeSourceMapFileWatcher();
});
}
private telemetryOnOpenFile(scriptInfo: ScriptInfo): void {
if (this.syntaxOnly || !this.eventHandler || !scriptInfo.isJavaScript() || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) {
return;
+55 -25
View File
@@ -10,26 +10,43 @@ namespace ts.server {
export type Mutable<T> = { -readonly [K in keyof T]: T[K]; };
/* @internal */
export function countEachFileTypes(infos: ScriptInfo[]): FileStats {
const result: Mutable<FileStats> = { js: 0, jsx: 0, ts: 0, tsx: 0, dts: 0, deferred: 0 };
export function countEachFileTypes(infos: ScriptInfo[], includeSizes = false): FileStats {
const result: Mutable<FileStats> = {
js: 0, jsSize: 0,
jsx: 0, jsxSize: 0,
ts: 0, tsSize: 0,
tsx: 0, tsxSize: 0,
dts: 0, dtsSize: 0,
deferred: 0, deferredSize: 0,
};
for (const info of infos) {
const fileSize = includeSizes ? info.getTelemetryFileSize() : 0;
switch (info.scriptKind) {
case ScriptKind.JS:
result.js += 1;
result.jsSize! += fileSize;
break;
case ScriptKind.JSX:
result.jsx += 1;
result.jsxSize! += fileSize;
break;
case ScriptKind.TS:
fileExtensionIs(info.fileName, Extension.Dts)
? result.dts += 1
: result.ts += 1;
if (fileExtensionIs(info.fileName, Extension.Dts)) {
result.dts += 1;
result.dtsSize! += fileSize;
}
else {
result.ts += 1;
result.tsSize! += fileSize;
}
break;
case ScriptKind.TSX:
result.tsx += 1;
result.tsxSize! += fileSize;
break;
case ScriptKind.Deferred:
result.deferred += 1;
result.deferredSize! += fileSize;
break;
}
}
@@ -95,9 +112,9 @@ namespace ts.server {
export abstract class Project implements LanguageServiceHost, ModuleResolutionHost {
private rootFiles: ScriptInfo[] = [];
private rootFilesMap: Map<ProjectRoot> = createMap<ProjectRoot>();
private program: Program;
private externalFiles: SortedReadonlyArray<string>;
private missingFilesMap: Map<FileWatcher>;
private program: Program | undefined;
private externalFiles: SortedReadonlyArray<string> | undefined;
private missingFilesMap: Map<FileWatcher> | undefined;
private plugins: PluginModuleWithName[] = [];
/*@internal*/
@@ -124,7 +141,7 @@ namespace ts.server {
readonly realpath?: (path: string) => string;
/*@internal*/
hasInvalidatedResolution: HasInvalidatedResolution;
hasInvalidatedResolution: HasInvalidatedResolution | undefined;
/*@internal*/
resolutionCache: ResolutionCache;
@@ -137,7 +154,7 @@ namespace ts.server {
/**
* Set of files that was returned from the last call to getChangesSinceVersion.
*/
private lastReportedFileNames: Map<true>;
private lastReportedFileNames: Map<true> | undefined;
/**
* Last version that was reported.
*/
@@ -486,6 +503,16 @@ namespace ts.server {
return this.getLanguageService().getSourceMapper();
}
/*@internal*/
getDocumentPositionMapper(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined {
return this.projectService.getDocumentPositionMapper(this, generatedFileName, sourceFileName);
}
/*@internal*/
getSourceFileLike(fileName: string) {
return this.projectService.getSourceFileLike(fileName, this);
}
private shouldEmitFile(scriptInfo: ScriptInfo) {
return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent();
}
@@ -495,8 +522,8 @@ namespace ts.server {
return [];
}
updateProjectIfDirty(this);
this.builderState = BuilderState.create(this.program, this.projectService.toCanonicalFileName, this.builderState);
return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash!(data)), // TODO: GH#18217
this.builderState = BuilderState.create(this.program!, this.projectService.toCanonicalFileName, this.builderState);
return mapDefined(BuilderState.getFilesAffectedBy(this.builderState, this.program!, scriptInfo.path, this.cancellationToken, data => this.projectService.host.createHash!(data)), // TODO: GH#18217
sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)!) ? sourceFile.fileName : undefined);
}
@@ -577,7 +604,7 @@ namespace ts.server {
/* @internal */
getSourceFileOrConfigFile(path: Path): SourceFile | undefined {
const options = this.program.getCompilerOptions();
const options = this.program!.getCompilerOptions();
return path === options.configFilePath ? options.configFile : this.getSourceFile(path);
}
@@ -664,7 +691,7 @@ namespace ts.server {
// if language service is not enabled - return just root files
return this.rootFiles;
}
return map(this.program.getSourceFiles(), sourceFile => {
return map(this.program!.getSourceFiles(), sourceFile => {
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!;
@@ -732,7 +759,10 @@ namespace ts.server {
}
containsScriptInfo(info: ScriptInfo): boolean {
return this.isRoot(info) || (this.program && this.program.getSourceFileByPath(info.path) !== undefined);
if (this.isRoot(info)) return true;
if (!this.program) return false;
const file = this.program.getSourceFileByPath(info.path);
return !!file && file.resolvedPath === info.path;
}
containsFile(filename: NormalizedPath, requireOpen?: boolean): boolean {
@@ -828,7 +858,7 @@ namespace ts.server {
// (can reuse cached imports for files that were not changed)
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
if (hasNewProgram || changedFiles.length) {
this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program, this.cachedUnresolvedImportsPerFile);
this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program!, this.cachedUnresolvedImportsPerFile);
}
this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles);
@@ -855,7 +885,7 @@ namespace ts.server {
}
/* @internal */
getCurrentProgram() {
getCurrentProgram(): Program | undefined {
return this.program;
}
@@ -894,7 +924,7 @@ namespace ts.server {
}
oldProgram.forEachResolvedProjectReference((resolvedProjectReference, resolvedProjectReferencePath) => {
if (resolvedProjectReference && !this.program.getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) {
if (resolvedProjectReference && !this.program!.getResolvedProjectReferenceByPath(resolvedProjectReferencePath)) {
this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName);
}
});
@@ -950,8 +980,8 @@ namespace ts.server {
this.getCachedDirectoryStructureHost().addOrDeleteFile(fileName, missingFilePath, eventKind);
}
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) {
this.missingFilesMap.delete(missingFilePath);
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap!.has(missingFilePath)) {
this.missingFilesMap!.delete(missingFilePath);
fileWatcher.close();
// When a missing file is created, we should update the graph.
@@ -966,7 +996,7 @@ namespace ts.server {
}
private isWatchedMissingFile(path: Path) {
return this.missingFilesMap && this.missingFilesMap.has(path);
return !!this.missingFilesMap && this.missingFilesMap.has(path);
}
getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo | undefined {
@@ -1327,14 +1357,14 @@ namespace ts.server {
* Otherwise it will create an InferredProject.
*/
export class ConfiguredProject extends Project {
private typeAcquisition: TypeAcquisition;
private typeAcquisition!: TypeAcquisition; // TODO: GH#18217
/* @internal */
configFileWatcher: FileWatcher | undefined;
private directoriesWatchedForWildcards: Map<WildcardDirectoryWatcher> | undefined;
readonly canonicalConfigFilePath: NormalizedPath;
/* @internal */
pendingReload: ConfigFileProgramReloadLevel;
pendingReload: ConfigFileProgramReloadLevel | undefined;
/* @internal */
pendingReloadReason: string | undefined;
@@ -1342,7 +1372,7 @@ namespace ts.server {
configFileSpecs: ConfigFileSpecs | undefined;
/*@internal*/
canConfigFileJsonReportNoInputFiles: boolean;
canConfigFileJsonReportNoInputFiles = false;
/** Ref count to the project when opened from external project */
private externalProjectRefCount = 0;
@@ -1573,7 +1603,7 @@ namespace ts.server {
*/
export class ExternalProject extends Project {
excludedFiles: ReadonlyArray<NormalizedPath> = [];
private typeAcquisition: TypeAcquisition;
private typeAcquisition!: TypeAcquisition; // TODO: GH#18217
/*@internal*/
constructor(public externalProjectName: string,
projectService: ProjectService,
+113 -17
View File
@@ -25,18 +25,26 @@ namespace ts.server {
*/
private lineMap: number[] | undefined;
/**
* When a large file is loaded, text will artificially be set to "".
* In order to be able to report correct telemetry, we store the actual
* file size in this case. (In other cases where text === "", e.g.
* for mixed content or dynamic files, fileSize will be undefined.)
*/
private fileSize: number | undefined;
/**
* True if the text is for the file thats open in the editor
*/
public isOpen: boolean;
public isOpen = false;
/**
* True if the text present is the text from the file on the disk
*/
private ownFileText: boolean;
private ownFileText = false;
/**
* True when reloading contents of file from the disk is pending
*/
private pendingReloadFromDisk: boolean;
private pendingReloadFromDisk = false;
constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath, initialVersion: ScriptInfoVersion | undefined, private readonly info: ScriptInfo) {
this.version = initialVersion || { svc: 0, text: 0 };
@@ -56,10 +64,22 @@ namespace ts.server {
this.switchToScriptVersionCache();
}
private resetSourceMapInfo() {
this.info.sourceFileLike = undefined;
this.info.closeSourceMapFileWatcher();
this.info.sourceMapFilePath = undefined;
this.info.declarationInfoPath = undefined;
this.info.sourceInfos = undefined;
this.info.documentPositionMapper = undefined;
}
/** Public for testing */
public useText(newText?: string) {
this.svc = undefined;
this.text = newText;
this.lineMap = undefined;
this.fileSize = undefined;
this.resetSourceMapInfo();
this.version.text++;
}
@@ -68,13 +88,15 @@ namespace ts.server {
this.ownFileText = false;
this.text = undefined;
this.lineMap = undefined;
this.fileSize = undefined;
this.resetSourceMapInfo();
}
/**
* Set the contents as newText
* returns true if text changed
*/
public reload(newText: string) {
public reload(newText: string): boolean {
Debug.assert(newText !== undefined);
// Reload always has fresh content
@@ -91,6 +113,8 @@ namespace ts.server {
this.ownFileText = false;
return true;
}
return false;
}
/**
@@ -98,7 +122,9 @@ namespace ts.server {
* returns true if text changed
*/
public reloadWithFileText(tempFileName?: string) {
const reloaded = this.reload(this.getFileText(tempFileName));
const { text: newText, fileSize } = this.getFileTextAndSize(tempFileName);
const reloaded = this.reload(newText);
this.fileSize = fileSize; // NB: after reload since reload clears it
this.ownFileText = !tempFileName || tempFileName === this.fileName;
return reloaded;
}
@@ -118,14 +144,31 @@ namespace ts.server {
this.pendingReloadFromDisk = true;
}
/**
* For telemetry purposes, we would like to be able to report the size of the file.
* However, we do not want telemetry to require extra file I/O so we report a size
* that may be stale (e.g. may not reflect change made on disk since the last reload).
* NB: Will read from disk if the file contents have never been loaded because
* telemetry falsely indicating size 0 would be counter-productive.
*/
public getTelemetryFileSize(): number {
return !!this.fileSize
? this.fileSize
: !!this.text // Check text before svc because its length is cheaper
? this.text.length // Could be wrong if this.pendingReloadFromDisk
: !!this.svc
? this.svc.getSnapshot().getLength() // Could be wrong if this.pendingReloadFromDisk
: this.getSnapshot().getLength(); // Should be strictly correct
}
public getSnapshot(): IScriptSnapshot {
return this.useScriptVersionCacheIfValidOrOpen()
? this.svc!.getSnapshot()
: ScriptSnapshot.fromString(this.getOrLoadText());
}
public getLineInfo(line: number): AbsolutePositionAndLineText {
return this.switchToScriptVersionCache().getLineInfo(line);
public getAbsolutePositionAndLineText(line: number): AbsolutePositionAndLineText {
return this.switchToScriptVersionCache().getAbsolutePositionAndLineText(line);
}
/**
* @param line 0 based index
@@ -144,9 +187,9 @@ namespace ts.server {
* @param line 1 based index
* @param offset 1 based index
*/
lineOffsetToPosition(line: number, offset: number): number {
lineOffsetToPosition(line: number, offset: number, allowEdits?: true): number {
if (!this.useScriptVersionCacheIfValidOrOpen()) {
return computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1, this.text);
return computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1, this.text, allowEdits);
}
// TODO: assert this offset is actually on the line
@@ -161,7 +204,7 @@ namespace ts.server {
return this.svc!.positionToLineOffset(position);
}
private getFileText(tempFileName?: string) {
private getFileTextAndSize(tempFileName?: string): { text: string, fileSize?: number } {
let text: string;
const fileName = tempFileName || this.fileName;
const getText = () => text === undefined ? (text = this.host.readFile(fileName) || "") : text;
@@ -173,10 +216,10 @@ namespace ts.server {
const service = this.info.containingProjects[0].projectService;
service.logger.info(`Skipped loading contents of large file ${fileName} for info ${this.info.fileName}: fileSize: ${fileSize}`);
this.info.containingProjects[0].projectService.sendLargeFileReferencedEvent(fileName, fileSize);
return "";
return { text: "", fileSize };
}
}
return getText();
return { text: getText() };
}
private switchToScriptVersionCache(): ScriptVersionCache {
@@ -214,6 +257,17 @@ namespace ts.server {
Debug.assert(!this.svc, "ScriptVersionCache should not be set");
return this.lineMap || (this.lineMap = computeLineStarts(this.getOrLoadText()));
}
getLineInfo(): LineInfo {
if (this.svc) {
return {
getLineCount: () => this.svc!.getLineCount(),
getLineText: line => this.svc!.getAbsolutePositionAndLineText(line + 1).lineText!
};
}
const lineMap = this.getLineMap();
return getLineInfo(this.text!, lineMap);
}
}
/*@internal*/
@@ -227,6 +281,12 @@ namespace ts.server {
sourceFile: SourceFile;
}
/*@internal*/
export interface SourceMapFileWatcher {
watcher: FileWatcher;
sourceInfos?: Map<true>;
}
export class ScriptInfo {
/**
* All projects that include this file
@@ -247,11 +307,25 @@ namespace ts.server {
private realpath: Path | undefined;
/*@internal*/
cacheSourceFile: DocumentRegistrySourceFileCache;
cacheSourceFile: DocumentRegistrySourceFileCache | undefined;
/*@internal*/
mTime?: number;
/*@internal*/
sourceFileLike?: SourceFileLike;
/*@internal*/
sourceMapFilePath?: Path | SourceMapFileWatcher | false;
// Present on sourceMapFile info
/*@internal*/
declarationInfoPath?: Path;
/*@internal*/
sourceInfos?: Map<true>;
/*@internal*/
documentPositionMapper?: DocumentPositionMapper | false;
constructor(
private readonly host: ServerHost,
readonly fileName: NormalizedPath,
@@ -276,6 +350,11 @@ namespace ts.server {
return this.textStorage.version;
}
/*@internal*/
getTelemetryFileSize() {
return this.textStorage.getTelemetryFileSize();
}
/*@internal*/
public isDynamicOrHasMixedContent() {
return this.hasMixedContent || this.isDynamic;
@@ -484,8 +563,8 @@ namespace ts.server {
}
/*@internal*/
getLineInfo(line: number): AbsolutePositionAndLineText {
return this.textStorage.getLineInfo(line);
getAbsolutePositionAndLineText(line: number): AbsolutePositionAndLineText {
return this.textStorage.getAbsolutePositionAndLineText(line);
}
editContent(start: number, end: number, newText: string): void {
@@ -514,8 +593,12 @@ namespace ts.server {
* @param line 1 based index
* @param offset 1 based index
*/
lineOffsetToPosition(line: number, offset: number): number {
return this.textStorage.lineOffsetToPosition(line, offset);
lineOffsetToPosition(line: number, offset: number): number;
/*@internal*/
// tslint:disable-next-line:unified-signatures
lineOffsetToPosition(line: number, offset: number, allowEdits?: true): number;
lineOffsetToPosition(line: number, offset: number, allowEdits?: true): number {
return this.textStorage.lineOffsetToPosition(line, offset, allowEdits);
}
positionToLineOffset(position: number): protocol.Location {
@@ -525,5 +608,18 @@ namespace ts.server {
public isJavaScript() {
return this.scriptKind === ScriptKind.JS || this.scriptKind === ScriptKind.JSX;
}
/*@internal*/
getLineInfo(): LineInfo {
return this.textStorage.getLineInfo();
}
/*@internal*/
closeSourceMapFileWatcher() {
if (this.sourceMapFilePath && !isString(this.sourceMapFilePath)) {
closeFileWatcherOf(this.sourceMapFilePath);
this.sourceMapFilePath = undefined;
}
}
}
}
+14 -6
View File
@@ -41,11 +41,11 @@ namespace ts.server {
// path to start of range
private readonly startPath: LineCollection[];
private readonly endBranch: LineCollection[] = [];
private branchNode: LineNode;
private branchNode: LineNode | undefined;
// path to current node
private readonly stack: LineNode[];
private state = CharRangeSection.Entire;
private lineCollectionAtBranch: LineCollection;
private lineCollectionAtBranch: LineCollection | undefined;
private initialText = "";
private trailingText = "";
@@ -308,8 +308,8 @@ namespace ts.server {
return this._getSnapshot().version;
}
getLineInfo(line: number): AbsolutePositionAndLineText {
return this._getSnapshot().index.lineNumberToInfo(line);
getAbsolutePositionAndLineText(oneBasedLine: number): AbsolutePositionAndLineText {
return this._getSnapshot().index.lineNumberToInfo(oneBasedLine);
}
lineOffsetToPosition(line: number, column: number): number {
@@ -348,6 +348,10 @@ namespace ts.server {
}
}
getLineCount() {
return this._getSnapshot().index.getLineCount();
}
static fromString(script: string) {
const svc = new ScriptVersionCache();
const snap = new LineIndexSnapshot(0, svc, new LineIndex());
@@ -383,7 +387,7 @@ namespace ts.server {
}
export class LineIndex {
root: LineNode;
root!: LineNode;
// set this to true to check each edit for accuracy
checkEdits = false;
@@ -400,8 +404,12 @@ namespace ts.server {
return this.root.charOffsetToLineInfo(1, position);
}
getLineCount() {
return this.root.lineCount();
}
lineNumberToInfo(oneBasedLine: number): AbsolutePositionAndLineText {
const lineCount = this.root.lineCount();
const lineCount = this.getLineCount();
if (oneBasedLine <= lineCount) {
const { position, leaf } = this.root.lineNumberToInfo(oneBasedLine, 0);
return { absolutePosition: position, lineText: leaf && leaf.text };
+6 -9
View File
@@ -516,7 +516,7 @@ namespace ts.server {
protected projectService: ProjectService;
private changeSeq = 0;
private currentRequestId: number;
private currentRequestId!: number;
private errorCheck: MultistepOperation;
protected host: ServerHost;
@@ -1474,7 +1474,7 @@ namespace ts.server {
// only to the previous line. If all this is true, then
// add edits necessary to properly indent the current line.
if ((args.key === "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
const { lineText, absolutePosition } = scriptInfo.getLineInfo(args.line);
const { lineText, absolutePosition } = scriptInfo.getAbsolutePositionAndLineText(args.line);
if (lineText && lineText.search("\\S") < 0) {
const preferredIndent = languageService.getIndentationAtPosition(file, position, formatOptions);
let hasIndent = 0;
@@ -1811,7 +1811,7 @@ namespace ts.server {
return (<protocol.FileLocationRequestArgs>locationOrSpan).line !== undefined;
}
private extractPositionAndRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): { position: number, textRange: TextRange } {
private extractPositionOrRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): number | TextRange {
let position: number | undefined;
let textRange: TextRange | undefined;
if (this.isLocation(args)) {
@@ -1821,7 +1821,7 @@ namespace ts.server {
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
textRange = { pos: startPosition, end: endPosition };
}
return { position: position!, textRange: textRange! }; // TODO: GH#18217
return Debug.assertDefined(position === undefined ? textRange : position);
function getPosition(loc: protocol.FileLocationRequestArgs) {
return loc.position !== undefined ? loc.position : scriptInfo.lineOffsetToPosition(loc.line, loc.offset);
@@ -1831,19 +1831,16 @@ namespace ts.server {
private getApplicableRefactors(args: protocol.GetApplicableRefactorsRequestArgs): protocol.ApplicableRefactorInfo[] {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
const { position, textRange } = this.extractPositionAndRange(args, scriptInfo);
return project.getLanguageService().getApplicableRefactors(file, position || textRange, this.getPreferences(file));
return project.getLanguageService().getApplicableRefactors(file, this.extractPositionOrRange(args, scriptInfo), this.getPreferences(file));
}
private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): RefactorEditInfo | protocol.RefactorEditInfo {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
const { position, textRange } = this.extractPositionAndRange(args, scriptInfo);
const result = project.getLanguageService().getEditsForRefactor(
file,
this.getFormatOptions(file),
position || textRange,
this.extractPositionOrRange(args, scriptInfo),
args.refactor,
args.action,
this.getPreferences(file),
@@ -0,0 +1,37 @@
/* @internal */
namespace ts.codefix {
const fixId = "addNameToNamelessParameter";
const errorCodes = [Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1.code];
registerCodeFix({
errorCodes,
getCodeActions: (context) => {
const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start));
return [createCodeFixAction(fixId, changes, Diagnostics.Add_parameter_name, fixId, Diagnostics.Add_names_to_all_parameters_without_names)];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)),
});
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) {
const token = getTokenAtPosition(sourceFile, pos);
if (!isIdentifier(token)) {
return Debug.fail("add-name-to-nameless-parameter operates on identifiers, but got a " + formatSyntaxKind(token.kind));
}
const param = token.parent;
if (!isParameter(param)) {
return Debug.fail("Tried to add a parameter name to a non-parameter: " + formatSyntaxKind(token.kind));
}
const i = param.parent.parameters.indexOf(param);
Debug.assert(!param.type, "Tried to add a parameter name to a parameter that already had one.");
Debug.assert(i > -1, "Parameter not found in parent parameter list.");
const replacement = createParameter(
/*decorators*/ undefined,
param.modifiers,
param.dotDotDotToken,
"arg" + i,
param.questionToken,
createTypeReferenceNode(token, /*typeArguments*/ undefined),
param.initializer);
changeTracker.replaceNode(sourceFile, token, replacement);
}
}
@@ -4,6 +4,9 @@ namespace ts.codefix {
const errorCodes = [
Diagnostics.Property_0_does_not_exist_on_type_1.code,
Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code,
Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2.code,
Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2.code,
Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more.code
];
const fixId = "addMissingMember";
registerCodeFix({
@@ -0,0 +1,32 @@
/* @internal */
namespace ts.codefix {
const fixId = "addMissingNewOperator";
const errorCodes = [Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new.code];
registerCodeFix({
errorCodes,
getCodeActions(context) {
const { sourceFile, span } = context;
const changes = textChanges.ChangeTracker.with(context, t => addMissingNewOperator(t, sourceFile, span));
return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_new_operator_to_call, fixId, Diagnostics.Add_missing_new_operator_to_all_calls)];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) =>
addMissingNewOperator(changes, context.sourceFile, diag)),
});
function addMissingNewOperator(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan): void {
const call = cast(findAncestorMatchingSpan(sourceFile, span), isCallExpression);
const newExpression = createNew(call.expression, call.typeArguments, call.arguments);
changes.replaceNode(sourceFile, call, newExpression);
}
function findAncestorMatchingSpan(sourceFile: SourceFile, span: TextSpan): Node {
let token = getTokenAtPosition(sourceFile, span.start);
const end = textSpanEnd(span);
while (token.end < end) {
token = token.parent;
}
return token;
}
}
+1 -1
View File
@@ -97,7 +97,7 @@ namespace ts.codefix {
optional: boolean,
body: Block | undefined,
): MethodDeclaration | undefined {
const signatureDeclaration = <MethodDeclaration>checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, NodeBuilderFlags.SuppressAnyReturnType);
const signatureDeclaration = <MethodDeclaration>checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, NodeBuilderFlags.NoTruncation | NodeBuilderFlags.SuppressAnyReturnType);
if (!signatureDeclaration) {
return undefined;
}
+62 -38
View File
@@ -187,24 +187,10 @@ namespace ts.codefix {
}
}
function isApplicableFunctionForInference(declaration: FunctionLike): declaration is MethodDeclaration | FunctionDeclaration | ConstructorDeclaration {
switch (declaration.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.Constructor:
return true;
case SyntaxKind.FunctionExpression:
const parent = declaration.parent;
return isVariableDeclaration(parent) && isIdentifier(parent.name) || !!declaration.name;
}
return false;
}
function annotateParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
if (!isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) {
if (!isIdentifier(parameterDeclaration.name)) {
return;
}
const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
containingFunction.parameters.map<ParameterInference>(p => ({
declaration: p,
@@ -216,11 +202,14 @@ namespace ts.codefix {
annotateJSDocParameters(changes, sourceFile, parameterInferences, program, host);
}
else {
const needParens = isArrowFunction(containingFunction) && !findChildOfKind(containingFunction, SyntaxKind.OpenParenToken, sourceFile);
if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), createToken(SyntaxKind.OpenParenToken));
for (const { declaration, type } of parameterInferences) {
if (declaration && !declaration.type && !declaration.initializer) {
annotate(changes, sourceFile, declaration, type, program, host);
}
}
if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), createToken(SyntaxKind.CloseParenToken));
}
}
@@ -342,12 +331,13 @@ namespace ts.codefix {
return InferFromReference.unifyFromContext(types, checker);
}
function inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
function inferTypeForParametersFromUsage(containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
let searchToken;
switch (containingFunction.kind) {
case SyntaxKind.Constructor:
searchToken = findChildOfKind<Token<SyntaxKind.ConstructorKeyword>>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile);
break;
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionExpression:
const parent = containingFunction.parent;
searchToken = isVariableDeclaration(parent) && isIdentifier(parent.name) ?
@@ -379,8 +369,8 @@ namespace ts.codefix {
interface UsageContext {
isNumber?: boolean;
isString?: boolean;
hasNonVacuousType?: boolean;
hasNonVacuousNonAnonymousType?: boolean;
/** Used ambiguously, eg x + ___ or object[___]; results in string | number if no other evidence exists */
isNumberOrString?: boolean;
candidateTypes?: Type[];
properties?: UnderscoreEscapedMap<UsageContext>;
@@ -399,7 +389,7 @@ namespace ts.codefix {
return inferFromContext(usageContext, checker);
}
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLike, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
const checker = program.getTypeChecker();
if (references.length === 0) {
return undefined;
@@ -413,10 +403,9 @@ namespace ts.codefix {
cancellationToken.throwIfCancellationRequested();
inferTypeFromContext(reference, checker, usageContext);
}
const isConstructor = declaration.kind === SyntaxKind.Constructor;
const callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts;
return callContexts && declaration.parameters.map((parameter, parameterIndex): ParameterInference => {
const types: Type[] = [];
const callContexts = [...usageContext.constructContexts || [], ...usageContext.callContexts || []];
return declaration.parameters.map((parameter, parameterIndex): ParameterInference => {
const types = [];
const isRest = isRestParameter(parameter);
let isOptional = false;
for (const callContext of callContexts) {
@@ -434,7 +423,8 @@ namespace ts.codefix {
}
}
if (isIdentifier(parameter.name)) {
types.push(...inferTypesFromReferences(getReferences(parameter.name, program, cancellationToken), checker, cancellationToken));
const inferred = inferTypesFromReferences(getReferences(parameter.name, program, cancellationToken), checker, cancellationToken);
types.push(...(isRest ? mapDefined(inferred, checker.getElementTypeOfArrayType) : inferred));
}
const type = unifyFromContext(types, checker);
return {
@@ -510,8 +500,7 @@ namespace ts.codefix {
break;
case SyntaxKind.PlusToken:
usageContext.isNumber = true;
usageContext.isString = true;
usageContext.isNumberOrString = true;
break;
// case SyntaxKind.ExclamationToken:
@@ -582,8 +571,7 @@ namespace ts.codefix {
usageContext.isString = true;
}
else {
usageContext.isNumber = true;
usageContext.isString = true;
usageContext.isNumberOrString = true;
}
break;
@@ -657,8 +645,7 @@ namespace ts.codefix {
function inferTypeFromPropertyElementExpressionContext(parent: ElementAccessExpression, node: Expression, checker: TypeChecker, usageContext: UsageContext): void {
if (node === parent.argumentExpression) {
usageContext.isNumber = true;
usageContext.isString = true;
usageContext.isNumberOrString = true;
return;
}
else {
@@ -674,17 +661,50 @@ namespace ts.codefix {
}
}
interface Priority {
high: (t: Type) => boolean;
low: (t: Type) => boolean;
}
function removeLowPriorityInferences(inferences: ReadonlyArray<Type>, priorities: Priority[]): Type[] {
const toRemove: ((t: Type) => boolean)[] = [];
for (const i of inferences) {
for (const { high, low } of priorities) {
if (high(i)) {
Debug.assert(!low(i));
toRemove.push(low);
}
}
}
return inferences.filter(i => toRemove.every(f => !f(i)));
}
export function unifyFromContext(inferences: ReadonlyArray<Type>, checker: TypeChecker, fallback = checker.getAnyType()): Type {
if (!inferences.length) return fallback;
const hasNonVacuousType = inferences.some(i => !(i.flags & (TypeFlags.Any | TypeFlags.Void)));
const hasNonVacuousNonAnonymousType = inferences.some(
i => !(i.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(checker.getObjectFlags(i) & ObjectFlags.Anonymous));
const anons = inferences.filter(i => checker.getObjectFlags(i) & ObjectFlags.Anonymous) as AnonymousType[];
const good = [];
if (!hasNonVacuousNonAnonymousType && anons.length) {
// 1. string or number individually override string | number
// 2. non-any, non-void overrides any or void
// 3. non-nullable, non-any, non-void, non-anonymous overrides anonymous types
const stringNumber = checker.getUnionType([checker.getStringType(), checker.getNumberType()]);
const priorities: Priority[] = [
{
high: t => t === checker.getStringType() || t === checker.getNumberType(),
low: t => t === stringNumber
},
{
high: t => !(t.flags & (TypeFlags.Any | TypeFlags.Void)),
low: t => !!(t.flags & (TypeFlags.Any | TypeFlags.Void))
},
{
high: t => !(t.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(checker.getObjectFlags(t) & ObjectFlags.Anonymous),
low: t => !!(checker.getObjectFlags(t) & ObjectFlags.Anonymous)
}];
let good = removeLowPriorityInferences(inferences, priorities);
const anons = good.filter(i => checker.getObjectFlags(i) & ObjectFlags.Anonymous) as AnonymousType[];
if (anons.length) {
good = good.filter(i => !(checker.getObjectFlags(i) & ObjectFlags.Anonymous));
good.push(unifyAnonymousTypes(anons, checker));
}
good.push(...inferences.filter(i => !(checker.getObjectFlags(i) & ObjectFlags.Anonymous) && !(hasNonVacuousType && i.flags & (TypeFlags.Any | TypeFlags.Void))));
return checker.getWidenedType(checker.getUnionType(good));
}
@@ -731,12 +751,16 @@ namespace ts.codefix {
function inferFromContext(usageContext: UsageContext, checker: TypeChecker) {
const types = [];
if (usageContext.isNumber) {
types.push(checker.getNumberType());
}
if (usageContext.isString) {
types.push(checker.getStringType());
}
if (usageContext.isNumberOrString) {
types.push(checker.getUnionType([checker.getStringType(), checker.getNumberType()]));
}
types.push(...(usageContext.candidateTypes || []).map(t => checker.getBaseTypeOfLiteralType(t)));
@@ -750,7 +774,7 @@ namespace ts.codefix {
}
if (usageContext.numberIndexContext) {
return [checker.createArrayType(recur(usageContext.numberIndexContext))];
types.push(checker.createArrayType(recur(usageContext.numberIndexContext)));
}
else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.stringIndexContext) {
const members = createUnderscoreEscapedMap<Symbol>();
+20 -12
View File
@@ -913,7 +913,7 @@ namespace ts.Completions {
}
else {
for (const symbol of type.getApparentProperties()) {
if (typeChecker.isValidPropertyAccessForCompletions(node.kind === SyntaxKind.ImportType ? <ImportTypeNode>node : <PropertyAccessExpression>node.parent, type, symbol)) {
if (typeChecker.isValidPropertyAccessForCompletions(node.kind === SyntaxKind.ImportType ? <ImportTypeNode>node : <PropertyAccessExpression | QualifiedName>node.parent, type, symbol)) {
addPropertySymbol(symbol);
}
}
@@ -1021,7 +1021,8 @@ namespace ts.Completions {
const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
isInSnippetScope = isSnippetScope(scopeNode);
const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
const isTypeOnly = isTypeOnlyCompletion();
const symbolMeanings = (isTypeOnly ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias;
symbols = Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined");
@@ -1049,12 +1050,10 @@ namespace ts.Completions {
if (sourceFile.externalModuleIndicator) return true;
// If already using commonjs, don't introduce ES6.
if (sourceFile.commonJsModuleIndicator) return false;
// For JS, stay on the safe side.
if (isUncheckedFile) return false;
// If some file is using ES6 modules, assume that it's OK to add more.
if (programContainsEs6Modules(program)) return true;
// If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK.
return compilerOptionsIndicateEs6Modules(program.getCompilerOptions());
if (compilerOptionsIndicateEs6Modules(program.getCompilerOptions())) return true;
// If some file is using ES6 modules, assume that it's OK to add more.
return programContainsEs6Modules(program);
}
function isSnippetScope(scopeNode: Node): boolean {
@@ -1070,9 +1069,9 @@ namespace ts.Completions {
}
function filterGlobalCompletion(symbols: Symbol[]): void {
const isTypeOnlyCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
const allowTypes = isTypeOnlyCompletion || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
if (isTypeOnlyCompletion) keywordFilters = KeywordCompletionFilters.TypeKeywords;
const isTypeOnly = isTypeOnlyCompletion();
const allowTypes = isTypeOnly || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
if (isTypeOnly) keywordFilters = KeywordCompletionFilters.TypeKeywords;
filterMutate(symbols, symbol => {
if (!isSourceFile(location)) {
@@ -1091,7 +1090,7 @@ namespace ts.Completions {
if (allowTypes) {
// Its a type, but you can reach it by namespace.type as well
const symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol);
if (symbolAllowedAsType || isTypeOnlyCompletion) {
if (symbolAllowedAsType || isTypeOnly) {
return symbolAllowedAsType;
}
}
@@ -1102,6 +1101,10 @@ namespace ts.Completions {
});
}
function isTypeOnlyCompletion(): boolean {
return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
}
function isContextTokenValueLocation(contextToken: Node) {
return contextToken &&
contextToken.kind === SyntaxKind.TypeOfKeyword &&
@@ -1532,6 +1535,7 @@ namespace ts.Completions {
if (contextToken) {
const parent = contextToken.parent;
switch (contextToken.kind) {
case SyntaxKind.GreaterThanToken: // End of a type argument list
case SyntaxKind.LessThanSlashToken:
case SyntaxKind.SlashToken:
case SyntaxKind.Identifier:
@@ -1540,6 +1544,10 @@ namespace ts.Completions {
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
if (parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) {
if (contextToken.kind === SyntaxKind.GreaterThanToken) {
const precedingToken = findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined);
if (!(parent as JsxOpeningLikeElement).typeArguments || (precedingToken && precedingToken.kind === SyntaxKind.SlashToken)) break;
}
return <JsxOpeningLikeElement>parent;
}
else if (parent.kind === SyntaxKind.JsxAttribute) {
@@ -1949,7 +1957,7 @@ namespace ts.Completions {
}
function isFunctionLikeBodyKeyword(kind: SyntaxKind) {
return kind === SyntaxKind.AsyncKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
return kind === SyntaxKind.AsyncKeyword || kind === SyntaxKind.AwaitKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
}
function keywordForNode(node: Node): SyntaxKind {
+58 -43
View File
@@ -89,10 +89,10 @@ namespace ts.FindAllReferences {
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));
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node, program.getTypeChecker()));
}
export type ToReferenceOrRenameEntry<T> = (entry: Entry, originalNode: Node) => T;
export type ToReferenceOrRenameEntry<T> = (entry: Entry, originalNode: Node, checker: TypeChecker) => T;
export function getReferenceEntriesForNode(
position: number,
@@ -157,8 +157,8 @@ namespace ts.FindAllReferences {
return { displayParts, kind: symbolKind };
}
export function toRenameLocation(entry: Entry, originalNode: Node): RenameLocation {
return { ...entryToDocumentSpan(entry), ...getPrefixAndSuffixText(entry, originalNode) };
export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker): RenameLocation {
return { ...entryToDocumentSpan(entry), ...getPrefixAndSuffixText(entry, originalNode, checker) };
}
export function toReferenceEntry(entry: Entry): ReferenceEntry {
@@ -188,25 +188,28 @@ namespace ts.FindAllReferences {
}
}
function getPrefixAndSuffixText(entry: Entry, originalNode: Node): { readonly prefixText?: string, readonly suffixText?: string } {
interface PrefixAndSuffix { readonly prefixText?: string; readonly suffixText?: string; }
function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeChecker): PrefixAndSuffix {
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 + ": " };
}
const prefixColon: PrefixAndSuffix = { prefixText: name + ": " };
const suffixColon: PrefixAndSuffix = { suffixText: ": " + name };
return kind === EntryKind.SearchedLocalFoundProperty ? prefixColon
: kind === EntryKind.SearchedPropertyFoundLocal ? suffixColon
// In `const o = { x }; o.x`, symbolAtLocation at `x` in `{ x }` is the property symbol.
// For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol.
: isShorthandAssignment ? suffixColon : prefixColon;
}
else if (isImportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
// If the original symbol was using this alias, just rename the alias.
const originalSymbol = isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode);
return contains(originalSymbol!.declarations, entry.node.parent) ? { prefixText: name + " as " } : emptyOptions;
}
else if (isExportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
return originalNode === entry.node ? { prefixText: name + " as " } : { suffixText: " as " + name };
}
}
@@ -480,8 +483,8 @@ namespace ts.FindAllReferences.Core {
}
/** Core find-all-references algorithm for a normal symbol. */
function getReferencedSymbolsForSymbol(symbol: Symbol, node: Node | undefined, sourceFiles: ReadonlyArray<SourceFile>, sourceFilesSet: ReadonlyMap<true>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
symbol = node && skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol;
function getReferencedSymbolsForSymbol(originalSymbol: Symbol, node: Node | undefined, sourceFiles: ReadonlyArray<SourceFile>, sourceFilesSet: ReadonlyMap<true>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, !!options.isForRename) || originalSymbol;
// Compute the meaning from the location and the symbol it references
const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : SemanticMeaning.All;
@@ -489,7 +492,12 @@ namespace ts.FindAllReferences.Core {
const result: SymbolAndEntries[] = [];
const state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : SpecialSearchKind.None, checker, cancellationToken, searchMeaning, options, result);
if (node && node.kind === SyntaxKind.DefaultKeyword) {
const exportSpecifier = !options.isForRename ? undefined : find(symbol.declarations, isExportSpecifier);
if (exportSpecifier) {
// When renaming at an export specifier, rename the export and not the thing being exported.
getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true);
}
else if (node && node.kind === SyntaxKind.DefaultKeyword) {
addReference(node, symbol, state);
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
}
@@ -530,16 +538,11 @@ namespace ts.FindAllReferences.Core {
}
/** Handle a few special cases relating to export/import specifiers. */
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker): Symbol | undefined {
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker, isForRename: boolean): Symbol | undefined {
const { parent } = node;
if (isExportSpecifier(parent)) {
if (isExportSpecifier(parent) && !isForRename) {
return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker);
}
if (isImportSpecifier(parent) && parent.propertyName === node) {
// We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import.
return checker.getImmediateAliasedSymbol(symbol)!;
}
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
return firstDefined(symbol.declarations, decl => {
if (!decl.parent) {
@@ -741,7 +744,8 @@ namespace ts.FindAllReferences.Core {
}
for (const indirectUser of indirectUsers) {
for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) {
if (isIdentifier(node) && checker.getSymbolAtLocation(node) === exportSymbol) {
// Import specifiers should be handled by importSearches
if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && checker.getSymbolAtLocation(node) === exportSymbol) {
cb(node);
}
}
@@ -754,7 +758,7 @@ namespace ts.FindAllReferences.Core {
// Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;`
if (!isIdentifier(singleRef)) return false;
// At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename.
return !((isExportSpecifier(singleRef.parent) || isImportSpecifier(singleRef.parent)) && singleRef.escapedText === InternalSymbolName.Default);
return !(isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === InternalSymbolName.Default);
}
// Go to the symbol we imported from and find references for it.
@@ -1058,17 +1062,25 @@ namespace ts.FindAllReferences.Core {
getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
}
function getReferencesAtExportSpecifier(referenceLocation: Identifier, referenceSymbol: Symbol, exportSpecifier: ExportSpecifier, search: Search, state: State, addReferencesHere: boolean): void {
function getReferencesAtExportSpecifier(
referenceLocation: Identifier,
referenceSymbol: Symbol,
exportSpecifier: ExportSpecifier,
search: Search,
state: State,
addReferencesHere: boolean,
alwaysGetReferences?: boolean,
): void {
const { parent, propertyName, name } = exportSpecifier;
const exportDeclaration = parent.parent;
const localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker);
if (!search.includes(localSymbol)) {
if (!alwaysGetReferences && !search.includes(localSymbol)) {
return;
}
if (!propertyName) {
// Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export)
if (!(state.options.isForRename && name.escapedText === InternalSymbolName.Default)) {
if (!(state.options.isForRename && (name.escapedText === InternalSymbolName.Default))) {
addRef();
}
}
@@ -1080,7 +1092,7 @@ namespace ts.FindAllReferences.Core {
}
if (addReferencesHere && !state.options.isForRename && state.markSeenReExportRHS(name)) {
addReference(name, referenceSymbol, state);
addReference(name, Debug.assertDefined(exportSpecifier.symbol), state);
}
}
else {
@@ -1090,15 +1102,15 @@ namespace ts.FindAllReferences.Core {
}
// For `export { foo as bar }`, rename `foo`, but not `bar`.
if (!(referenceLocation === propertyName && state.options.isForRename)) {
if (!state.options.isForRename || alwaysGetReferences) {
const exportKind = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker);
if (!exportInfo) return Debug.fail();
searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state);
const exportSymbol = Debug.assertDefined(exportSpecifier.symbol);
const exportInfo = Debug.assertDefined(getExportInfo(exportSymbol, exportKind, state.checker));
searchForImportsOfExport(referenceLocation, exportSymbol, exportInfo, state);
}
// At `export { x } from "foo"`, also search for the imported symbol `"foo".x`.
if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName) {
if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !state.options.isForRename) {
const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
if (imported) searchForImportedSymbol(imported, state);
}
@@ -1133,12 +1145,11 @@ namespace ts.FindAllReferences.Core {
const { symbol } = importOrExport;
if (importOrExport.kind === ImportExport.Import) {
if (!state.options.isForRename || importOrExport.isNamedImport) {
if (!state.options.isForRename) {
searchForImportedSymbol(symbol, state);
}
}
else {
// We don't check for `state.isForRename`, even for default exports, because importers that previously matched the export name should be updated to continue matching.
searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state);
}
}
@@ -1417,6 +1428,10 @@ namespace ts.FindAllReferences.Core {
return [{ definition: { type: DefinitionKind.Symbol, symbol: searchSpaceNode.symbol }, references }];
}
function isParameterName(node: Node) {
return node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node.parent).name === node;
}
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
@@ -1439,7 +1454,7 @@ namespace ts.FindAllReferences.Core {
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
break;
case SyntaxKind.SourceFile:
if (isExternalModule(<SourceFile>searchSpaceNode)) {
if (isExternalModule(<SourceFile>searchSpaceNode) || isParameterName(thisOrSuperKeyword)) {
return undefined;
}
// falls through
@@ -1472,7 +1487,7 @@ namespace ts.FindAllReferences.Core {
// and has the appropriate static modifier from the original container.
return container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag;
case SyntaxKind.SourceFile:
return container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container);
return container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container) && !isParameterName(node);
}
});
}).map(n => nodeEntry(n));
+1 -4
View File
@@ -1106,10 +1106,7 @@ namespace ts.formatting {
* Trimming will be done for lines after the previous range
*/
function trimTrailingWhitespacesForRemainingRange() {
if (!previousRange) {
return;
}
const startPosition = previousRange.end;
const startPosition = previousRange ? previousRange.end : originalRange.pos;
const startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line;
const endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line;
+10 -16
View File
@@ -10,11 +10,11 @@ namespace ts.formatting {
}
export class FormattingContext {
public currentTokenSpan: TextRangeWithKind;
public nextTokenSpan: TextRangeWithKind;
public contextNode: Node;
public currentTokenParent: Node;
public nextTokenParent: Node;
public currentTokenSpan!: TextRangeWithKind;
public nextTokenSpan!: TextRangeWithKind;
public contextNode!: Node;
public currentTokenParent!: Node;
public nextTokenParent!: Node;
private contextNodeAllOnSameLine: boolean | undefined;
private nextNodeAllOnSameLine: boolean | undefined;
@@ -26,17 +26,11 @@ namespace ts.formatting {
}
public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
Debug.assert(commonParent !== undefined, "commonParent is null");
this.currentTokenSpan = currentRange;
this.currentTokenParent = currentTokenParent;
this.nextTokenSpan = nextRange;
this.nextTokenParent = nextTokenParent;
this.contextNode = commonParent;
this.currentTokenSpan = Debug.assertDefined(currentRange);
this.currentTokenParent = Debug.assertDefined(currentTokenParent);
this.nextTokenSpan = Debug.assertDefined(nextRange);
this.nextTokenParent = Debug.assertDefined(nextTokenParent);
this.contextNode = Debug.assertDefined(commonParent);
// drop cached results
this.contextNodeAllOnSameLine = undefined;
+7 -10
View File
@@ -424,7 +424,6 @@ namespace ts.FindAllReferences {
export interface ImportedSymbol {
kind: ImportExport.Import;
symbol: Symbol;
isNamedImport: boolean;
}
export interface ExportedSymbol {
kind: ImportExport.Export;
@@ -467,7 +466,7 @@ namespace ts.FindAllReferences {
}
const lhsSymbol = checker.getSymbolAtLocation(exportNode.name)!;
return { kind: ImportExport.Import, symbol: lhsSymbol, isNamedImport: false };
return { kind: ImportExport.Import, symbol: lhsSymbol };
}
else {
return exportInfo(symbol, getExportKindForDeclaration(exportNode));
@@ -542,7 +541,7 @@ namespace ts.FindAllReferences {
// (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.)
const importedName = symbolEscapedNameNoDefault(importedSymbol);
if (importedName === undefined || importedName === InternalSymbolName.Default || importedName === symbol.escapedName) {
return { kind: ImportExport.Import, symbol: importedSymbol, ...isImport };
return { kind: ImportExport.Import, symbol: importedSymbol };
}
}
@@ -588,22 +587,20 @@ namespace ts.FindAllReferences {
}
}
function isNodeImport(node: Node): { isNamedImport: boolean } | undefined {
function isNodeImport(node: Node): boolean {
const { parent } = node;
switch (parent.kind) {
case SyntaxKind.ImportEqualsDeclaration:
return (parent as ImportEqualsDeclaration).name === node && isExternalModuleImportEquals(parent as ImportEqualsDeclaration)
? { isNamedImport: false }
: undefined;
return (parent as ImportEqualsDeclaration).name === node && isExternalModuleImportEquals(parent as ImportEqualsDeclaration);
case SyntaxKind.ImportSpecifier:
// For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`.
return (parent as ImportSpecifier).propertyName ? undefined : { isNamedImport: true };
return !(parent as ImportSpecifier).propertyName;
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
Debug.assert((parent as ImportClause | NamespaceImport).name === node);
return { isNamedImport: false };
return true;
default:
return undefined;
return false;
}
}
+1 -1
View File
@@ -660,7 +660,7 @@ namespace ts.NavigationBar {
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(", ");
const args = mapDefined(parent.arguments, a => isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined).join(", ");
return `${name}(${args}) callback`;
}
}
+15 -2
View File
@@ -37,6 +37,10 @@ namespace ts.OutliningElementsCollector {
addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out);
}
if (isFunctionExpressionAssignedToVariable(n)) {
addOutliningForLeadingCommentsForNode(n.parent.parent.parent, sourceFile, cancellationToken, out);
}
const span = getOutliningSpanForNode(n, sourceFile);
if (span) out.push(span);
@@ -54,6 +58,14 @@ namespace ts.OutliningElementsCollector {
}
depthRemaining++;
}
function isFunctionExpressionAssignedToVariable(n: Node) {
if (!isFunctionExpression(n) && !isArrowFunction(n)) {
return false;
}
const ancestor = findAncestor(n, isVariableStatement);
return !!ancestor && getSingleInitializerOfVariableStatementOrPropertyDeclaration(ancestor) === n;
}
}
function addRegionOutliningSpans(sourceFile: SourceFile, out: Push<OutliningSpan>): void {
@@ -175,6 +187,7 @@ namespace ts.OutliningElementsCollector {
case SyntaxKind.ModuleBlock:
return spanForNode(n.parent);
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.CaseBlock:
@@ -206,10 +219,10 @@ namespace ts.OutliningElementsCollector {
}
function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined {
// If the block has no leading keywords and is inside an array literal,
// If the block has no leading keywords and is inside an array literal or call expression,
// we only want to collapse the span of the block.
// Otherwise, the collapsed section will include the end of the previous line.
return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent), open);
return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open);
}
function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined {
+2 -4
View File
@@ -449,8 +449,7 @@ namespace ts.refactor.extractSymbol {
case SyntaxKind.ThisKeyword:
rangeFacts |= RangeFacts.UsesThis;
break;
case SyntaxKind.LabeledStatement:
{
case SyntaxKind.LabeledStatement: {
const label = (<LabeledStatement>node).label;
(seenLabels || (seenLabels = [])).push(label.escapedText);
forEachChild(node, visit);
@@ -458,8 +457,7 @@ namespace ts.refactor.extractSymbol {
break;
}
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
{
case SyntaxKind.ContinueStatement: {
const label = (<BreakStatement | ContinueStatement>node).label;
if (label) {
if (!contains(seenLabels, label.escapedText)) {
@@ -16,7 +16,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
readonly declaration: AcceptedDeclaration;
readonly fieldName: AcceptedNameType;
readonly accessorName: AcceptedNameType;
readonly originalName: AcceptedNameType;
readonly originalName: string;
readonly renameAccessor: boolean;
}
@@ -69,7 +69,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
// readonly modifier only existed in classLikeDeclaration
const constructor = getFirstConstructorWithBody(<ClassLikeDeclaration>container);
if (constructor) {
updateReadonlyPropertyInitializerStatementConstructor(changeTracker, context, constructor, fieldName, originalName);
updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, fieldName.text, originalName);
}
}
else {
@@ -135,7 +135,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
isReadonly: hasReadonlyModifier(declaration),
type: getTypeAnnotationNode(declaration),
container: declaration.kind === SyntaxKind.Parameter ? declaration.parent.parent : declaration.parent,
originalName: <AcceptedNameType>declaration.name,
originalName: (<AcceptedNameType>declaration.name).text,
declaration,
fieldName,
accessorName,
@@ -221,22 +221,22 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
: changeTracker.insertNodeAfter(file, declaration, accessor);
}
function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, context: RefactorContext, constructor: ConstructorDeclaration, fieldName: AcceptedNameType, originalName: AcceptedNameType) {
function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, file: SourceFile, constructor: ConstructorDeclaration, fieldName: string, originalName: string) {
if (!constructor.body) return;
const { file, program, cancellationToken } = context;
const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(originalName.parent.pos, originalName, program, [file], cancellationToken!), entry => // TODO: GH#18217
(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;
const accessorName = createIdentifier(fieldName.text);
const node = isBinaryExpression(parent)
? updateBinary(parent, accessorName, parent.right, parent.operatorToken)
: isPropertyAccessExpression(parent)
? updatePropertyAccess(parent, parent.expression, accessorName)
: Debug.fail("Unexpected write access token");
changeTracker.replaceNode(file, parent, node);
constructor.body.forEachChild(function recur(node) {
if (isElementAccessExpression(node) &&
node.expression.kind === SyntaxKind.ThisKeyword &&
isStringLiteral(node.argumentExpression) &&
node.argumentExpression.text === originalName &&
isWriteAccess(node)) {
changeTracker.replaceNode(file, node.argumentExpression, createStringLiteral(fieldName));
}
if (isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword && node.name.text === originalName && isWriteAccess(node)) {
changeTracker.replaceNode(file, node.name, createIdentifier(fieldName));
}
if (!isFunctionLike(node) && !isClassLike(node)) {
node.forEachChild(recur);
}
});
}
}
+1 -1
View File
@@ -45,7 +45,7 @@ namespace ts.Rename {
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 withoutIndex = endsWith(node.text, "/index") || endsWith(node.text, "/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;
+100 -89
View File
@@ -17,9 +17,9 @@ namespace ts {
public end: number;
public flags: NodeFlags;
public parent: Node;
public symbol: Symbol;
public jsDoc: JSDoc[];
public original: Node;
public symbol!: Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined
public jsDoc?: JSDoc[];
public original?: Node;
public transformFlags: TransformFlags;
private _children: Node[] | undefined;
@@ -196,14 +196,14 @@ namespace ts {
}
class TokenOrIdentifierObject implements Node {
public kind: SyntaxKind;
public kind!: SyntaxKind;
public pos: number;
public end: number;
public flags: NodeFlags;
public parent: Node;
public symbol: Symbol;
public jsDocComments: JSDoc[];
public transformFlags: TransformFlags;
public symbol!: Symbol;
public jsDocComments?: JSDoc[];
public transformFlags!: TransformFlags;
constructor(pos: number, end: number) {
// Set properties in same order as NodeObject
@@ -280,8 +280,8 @@ namespace ts {
class SymbolObject implements Symbol {
flags: SymbolFlags;
escapedName: __String;
declarations: Declaration[];
valueDeclaration: Declaration;
declarations!: Declaration[];
valueDeclaration!: Declaration;
// Undefined is used to indicate the value has not been computed. If, after computing, the
// symbol has no doc comment, then the empty array will be returned.
@@ -334,7 +334,7 @@ namespace ts {
}
class TokenObject<TKind extends SyntaxKind> extends TokenOrIdentifierObject implements Token<TKind> {
public symbol: Symbol;
public symbol!: Symbol;
public kind: TKind;
constructor(kind: TKind, pos: number, end: number) {
@@ -344,10 +344,10 @@ namespace ts {
}
class IdentifierObject extends TokenOrIdentifierObject implements Identifier {
public kind: SyntaxKind.Identifier;
public escapedText: __String;
public symbol: Symbol;
public autoGenerateFlags: GeneratedIdentifierFlags;
public kind!: SyntaxKind.Identifier;
public escapedText!: __String;
public symbol!: Symbol;
public autoGenerateFlags!: GeneratedIdentifierFlags;
_primaryExpressionBrand: any;
_memberExpressionBrand: any;
_leftHandSideExpressionBrand: any;
@@ -355,7 +355,7 @@ namespace ts {
_unaryExpressionBrand: any;
_expressionBrand: any;
_declarationBrand: any;
/*@internal*/typeArguments: NodeArray<TypeNode>;
/*@internal*/typeArguments!: NodeArray<TypeNode>;
constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) {
super(pos, end);
}
@@ -370,8 +370,8 @@ namespace ts {
checker: TypeChecker;
flags: TypeFlags;
objectFlags?: ObjectFlags;
id: number;
symbol: Symbol;
id!: number;
symbol!: Symbol;
constructor(checker: TypeChecker, flags: TypeFlags) {
this.checker = checker;
this.flags = flags;
@@ -447,16 +447,16 @@ namespace ts {
class SignatureObject implements Signature {
checker: TypeChecker;
declaration: SignatureDeclaration;
declaration!: SignatureDeclaration;
typeParameters?: TypeParameter[];
parameters: Symbol[];
thisParameter: Symbol;
resolvedReturnType: Type;
parameters!: Symbol[];
thisParameter!: Symbol;
resolvedReturnType!: Type;
resolvedTypePredicate: TypePredicate | undefined;
minTypeArgumentCount: number;
minArgumentCount: number;
hasRestParameter: boolean;
hasLiteralTypes: boolean;
minTypeArgumentCount!: number;
minArgumentCount!: number;
hasRestParameter!: boolean;
hasLiteralTypes!: boolean;
// Undefined is used to indicate the value has not been computed. If, after computing, the
// symbol has no doc comment, then the empty array will be returned.
@@ -536,55 +536,55 @@ namespace ts {
}
class SourceFileObject extends NodeObject implements SourceFile {
public kind: SyntaxKind.SourceFile;
public kind!: SyntaxKind.SourceFile;
public _declarationBrand: any;
public fileName: string;
public path: Path;
public resolvedPath: Path;
public originalFileName: string;
public text: string;
public scriptSnapshot: IScriptSnapshot;
public lineMap: ReadonlyArray<number>;
public fileName!: string;
public path!: Path;
public resolvedPath!: Path;
public originalFileName!: string;
public text!: string;
public scriptSnapshot!: IScriptSnapshot;
public lineMap!: ReadonlyArray<number>;
public statements: NodeArray<Statement>;
public endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
public statements!: NodeArray<Statement>;
public endOfFileToken!: Token<SyntaxKind.EndOfFileToken>;
public amdDependencies: { name: string; path: string }[];
public moduleName: string;
public referencedFiles: FileReference[];
public typeReferenceDirectives: FileReference[];
public libReferenceDirectives: FileReference[];
public amdDependencies!: { name: string; path: string }[];
public moduleName!: string;
public referencedFiles!: FileReference[];
public typeReferenceDirectives!: FileReference[];
public libReferenceDirectives!: FileReference[];
public syntacticDiagnostics: DiagnosticWithLocation[];
public parseDiagnostics: DiagnosticWithLocation[];
public bindDiagnostics: DiagnosticWithLocation[];
public syntacticDiagnostics!: DiagnosticWithLocation[];
public parseDiagnostics!: DiagnosticWithLocation[];
public bindDiagnostics!: DiagnosticWithLocation[];
public bindSuggestionDiagnostics?: DiagnosticWithLocation[];
public isDeclarationFile: boolean;
public isDefaultLib: boolean;
public hasNoDefaultLib: boolean;
public externalModuleIndicator: Node; // The first node that causes this file to be an external module
public commonJsModuleIndicator: Node; // The first node that causes this file to be a CommonJS module
public nodeCount: number;
public identifierCount: number;
public symbolCount: number;
public version: string;
public scriptKind: ScriptKind;
public languageVersion: ScriptTarget;
public languageVariant: LanguageVariant;
public identifiers: Map<string>;
public nameTable: UnderscoreEscapedMap<number>;
public resolvedModules: Map<ResolvedModuleFull>;
public resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
public imports: ReadonlyArray<StringLiteralLike>;
public moduleAugmentations: StringLiteral[];
private namedDeclarations: Map<Declaration[]>;
public ambientModuleNames: string[];
public isDeclarationFile!: boolean;
public isDefaultLib!: boolean;
public hasNoDefaultLib!: boolean;
public externalModuleIndicator!: Node; // The first node that causes this file to be an external module
public commonJsModuleIndicator!: Node; // The first node that causes this file to be a CommonJS module
public nodeCount!: number;
public identifierCount!: number;
public symbolCount!: number;
public version!: string;
public scriptKind!: ScriptKind;
public languageVersion!: ScriptTarget;
public languageVariant!: LanguageVariant;
public identifiers!: Map<string>;
public nameTable: UnderscoreEscapedMap<number> | undefined;
public resolvedModules: Map<ResolvedModuleFull> | undefined;
public resolvedTypeReferenceDirectiveNames!: Map<ResolvedTypeReferenceDirective>;
public imports!: ReadonlyArray<StringLiteralLike>;
public moduleAugmentations!: StringLiteral[];
private namedDeclarations: Map<Declaration[]> | undefined;
public ambientModuleNames!: string[];
public checkJsDirective: CheckJsDirective | undefined;
public possiblyContainDynamicImport: boolean;
public pragmas: PragmaMap;
public localJsxFactory: EntityName;
public localJsxNamespace: __String;
public possiblyContainDynamicImport?: boolean;
public pragmas!: PragmaMap;
public localJsxFactory: EntityName | undefined;
public localJsxNamespace: __String | undefined;
constructor(kind: SyntaxKind, pos: number, end: number) {
super(kind, pos, end);
@@ -602,8 +602,8 @@ namespace ts {
return getLineStarts(this);
}
public getPositionOfLineAndCharacter(line: number, character: number): number {
return getPositionOfLineAndCharacter(this, line, character);
public getPositionOfLineAndCharacter(line: number, character: number, allowEdits?: true): number {
return computePositionOfLineAndCharacter(getLineStarts(this), line, character, this.text, allowEdits);
}
public getLineEndOfPosition(pos: number): number {
@@ -774,7 +774,7 @@ namespace ts {
}
class SourceMapSourceObject implements SourceMapSource {
lineMap: number[];
lineMap!: number[];
constructor(public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) { }
public getLineAndCharacterOfPosition(pos: number): LineAndCharacter {
@@ -955,10 +955,10 @@ namespace ts {
class SyntaxTreeCache {
// For our syntactic only features, we also keep a cache of the syntax tree for the
// currently edited file.
private currentFileName: string;
private currentFileVersion: string;
private currentFileScriptSnapshot: IScriptSnapshot;
private currentSourceFile: SourceFile;
private currentFileName: string | undefined;
private currentFileVersion: string | undefined;
private currentFileScriptSnapshot: IScriptSnapshot | undefined;
private currentSourceFile: SourceFile | undefined;
constructor(private host: LanguageServiceHost) {
}
@@ -980,8 +980,8 @@ namespace ts {
}
else if (this.currentFileVersion !== version) {
// This is the same file, just a newer version. Incrementally parse the file.
const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot!);
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile!, scriptSnapshot, version, editRange);
}
if (sourceFile) {
@@ -992,7 +992,7 @@ namespace ts {
this.currentSourceFile = sourceFile;
}
return this.currentSourceFile;
return this.currentSourceFile!;
}
}
@@ -1139,7 +1139,16 @@ namespace ts {
const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host);
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
const sourceMapper = getSourceMapper(useCaseSensitiveFileNames, currentDirectory, log, host, () => program);
const sourceMapper = getSourceMapper({
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
getCurrentDirectory: () => currentDirectory,
getProgram,
fileExists: host.fileExists && (f => host.fileExists!(f)),
readFile: host.readFile && ((f, encoding) => host.readFile!(f, encoding)),
getDocumentPositionMapper: host.getDocumentPositionMapper && ((generatedFileName, sourceFileName) => host.getDocumentPositionMapper!(generatedFileName, sourceFileName)),
getSourceFileLike: host.getSourceFileLike && (f => host.getSourceFileLike!(f)),
log
});
function getValidSourceFile(fileName: string): SourceFile {
const sourceFile = program.getSourceFile(fileName);
@@ -1203,15 +1212,7 @@ namespace ts {
writeFile: noop,
getCurrentDirectory: () => currentDirectory,
fileExists,
readFile(fileName) {
// stub missing host functionality
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const entry = hostCache && hostCache.getEntryByPath(path);
if (entry) {
return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot);
}
return host.readFile && host.readFile(fileName);
},
readFile,
realpath: host.realpath && (path => host.realpath!(path)),
directoryExists: directoryName => {
return directoryProbablyExists(directoryName, host);
@@ -1272,6 +1273,16 @@ namespace ts {
(!!host.fileExists && host.fileExists(fileName));
}
function readFile(fileName: string) {
// stub missing host functionality
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const entry = hostCache && hostCache.getEntryByPath(path);
if (entry) {
return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot);
}
return host.readFile && host.readFile(fileName);
}
// Release any files we have acquired in the old program but are
// not part of the new program.
function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) {
@@ -1481,7 +1492,7 @@ namespace ts {
function shouldGetType(sourceFile: SourceFile, node: Node, position: number): boolean {
switch (node.kind) {
case SyntaxKind.Identifier:
return !isLabelName(node);
return !isLabelName(node) && !isTagName(node);
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.QualifiedName:
// Don't return quickInfo if inside the comment in `a/**/.b`
@@ -2159,7 +2170,7 @@ namespace ts {
function initializeNameTable(sourceFile: SourceFile): void {
const nameTable = sourceFile.nameTable = createUnderscoreEscapedMap<number>();
sourceFile.forEachChild(function walk(node) {
if (isIdentifier(node) && node.escapedText || isStringOrNumericLiteralLike(node) && literalIsName(node)) {
if (isIdentifier(node) && !isTagName(node) && node.escapedText || isStringOrNumericLiteralLike(node) && literalIsName(node)) {
const text = getEscapedTextOfIdentifierOrLiteral(node);
nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
}
+11 -5
View File
@@ -331,9 +331,9 @@ namespace ts {
private loggingEnabled = false;
private tracingEnabled = false;
public resolveModuleNames: (moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[];
public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[];
public directoryExists: (directoryName: string) => boolean;
public resolveModuleNames: ((moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]) | undefined;
public resolveTypeReferenceDirectives: ((typeDirectiveNames: string[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[]) | undefined;
public directoryExists: ((directoryName: string) => boolean) | undefined;
constructor(private shimHost: LanguageServiceShimHost) {
// if shimHost is a COM object then property check will become method call with no arguments.
@@ -490,13 +490,19 @@ namespace ts {
public useCaseSensitiveFileNames: boolean;
constructor(private shimHost: CoreServicesShimHost) {
this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
if ("directoryExists" in this.shimHost) {
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
}
else {
this.directoryExists = undefined!; // TODO: GH#18217
}
if ("realpath" in this.shimHost) {
this.realpath = path => this.shimHost.realpath!(path); // TODO: GH#18217
}
else {
this.realpath = undefined!; // TODO: GH#18217
}
}
public readDirectory(rootDir: string, extensions: ReadonlyArray<string>, exclude: ReadonlyArray<string>, include: ReadonlyArray<string>, depth?: number): string[] {
@@ -1182,7 +1188,7 @@ namespace ts {
export class TypeScriptServicesFactory implements ShimFactory {
private _shims: Shim[] = [];
private documentRegistry: DocumentRegistry;
private documentRegistry: DocumentRegistry | undefined;
/*
* Returns script API version.
+134 -103
View File
@@ -9,151 +9,182 @@ namespace ts {
clearCache(): void;
}
export function getSourceMapper(
useCaseSensitiveFileNames: boolean,
currentDirectory: string,
log: (message: string) => void,
host: LanguageServiceHost,
getProgram: () => Program,
): SourceMapper {
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
let sourcemappedFileCache: SourceFileLikeCache;
export interface SourceMapperHost {
useCaseSensitiveFileNames(): boolean;
getCurrentDirectory(): string;
getProgram(): Program | undefined;
fileExists?(path: string): boolean;
readFile?(path: string, encoding?: string): string | undefined;
getSourceFileLike?(fileName: string): SourceFileLike | undefined;
getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined;
log(s: string): void;
}
export function getSourceMapper(host: SourceMapperHost): SourceMapper {
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
const currentDirectory = host.getCurrentDirectory();
const sourceFileLike = createMap<SourceFileLike | false>();
const documentPositionMappers = createMap<DocumentPositionMapper>();
return { tryGetSourcePosition, tryGetGeneratedPosition, toLineColumnOffset, clearCache };
function toPath(fileName: string) {
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
}
function scanForSourcemapURL(fileName: string) {
const mappedFile = sourcemappedFileCache.get(toPath(fileName));
if (!mappedFile) {
return;
}
function getDocumentPositionMapper(generatedFileName: string, sourceFileName?: string) {
const path = toPath(generatedFileName);
const value = documentPositionMappers.get(path);
if (value) return value;
return tryGetSourceMappingURL(mappedFile.text, getLineStarts(mappedFile));
}
function convertDocumentToSourceMapper(file: { sourceMapper?: DocumentPositionMapper }, contents: string, mapFileName: string) {
const map = tryParseRawSourceMap(contents);
if (!map || !map.sources || !map.file || !map.mappings) {
// obviously invalid map
return file.sourceMapper = identitySourceMapConsumer;
let mapper: DocumentPositionMapper | undefined;
if (host.getDocumentPositionMapper) {
mapper = host.getDocumentPositionMapper(generatedFileName, sourceFileName);
}
const program = getProgram();
return file.sourceMapper = createDocumentPositionMapper({
getSourceFileLike: s => {
// Lookup file in program, if provided
const file = program && program.getSourceFileByPath(s);
// file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file
if (file === undefined || file.resolvedPath !== s) {
// Otherwise check the cache (which may hit disk)
return sourcemappedFileCache.get(s);
}
return file;
},
getCanonicalFileName,
log,
}, map, mapFileName);
}
function getSourceMapper(fileName: string, file: SourceFileLike): DocumentPositionMapper {
if (!host.readFile || !host.fileExists) {
return file.sourceMapper = identitySourceMapConsumer;
else if (host.readFile) {
const file = getSourceFileLike(generatedFileName);
mapper = file && ts.getDocumentPositionMapper(
{ getSourceFileLike, getCanonicalFileName, log: s => host.log(s) },
generatedFileName,
getLineInfo(file.text, getLineStarts(file)),
f => !host.fileExists || host.fileExists(f) ? host.readFile!(f) : undefined
);
}
if (file.sourceMapper) {
return file.sourceMapper;
}
let mapFileName = scanForSourcemapURL(fileName);
if (mapFileName) {
const match = base64UrlRegExp.exec(mapFileName);
if (match) {
if (match[1]) {
const base64Object = match[1];
return convertDocumentToSourceMapper(file, base64decode(sys, base64Object), fileName);
}
// Not a data URL we can parse, skip it
mapFileName = undefined;
}
}
const possibleMapLocations: string[] = [];
if (mapFileName) {
possibleMapLocations.push(mapFileName);
}
possibleMapLocations.push(fileName + ".map");
for (const location of possibleMapLocations) {
const mapPath = ts.toPath(location, getDirectoryPath(fileName), getCanonicalFileName);
if (host.fileExists(mapPath)) {
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
}
}
return file.sourceMapper = identitySourceMapConsumer;
documentPositionMappers.set(path, mapper || identitySourceMapConsumer);
return mapper || identitySourceMapConsumer;
}
function tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined {
if (!isDeclarationFileName(info.fileName)) return undefined;
const file = getFile(info.fileName);
const file = getSourceFile(info.fileName);
if (!file) return undefined;
const newLoc = getSourceMapper(info.fileName, file).getSourcePosition(info);
return newLoc === info ? undefined : tryGetSourcePosition(newLoc) || newLoc;
const newLoc = getDocumentPositionMapper(info.fileName).getSourcePosition(info);
return !newLoc || newLoc === info ? undefined : tryGetSourcePosition(newLoc) || newLoc;
}
function tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined {
const program = getProgram();
if (isDeclarationFileName(info.fileName)) return undefined;
const sourceFile = getSourceFile(info.fileName);
if (!sourceFile) return undefined;
const program = host.getProgram()!;
const options = program.getCompilerOptions();
const outPath = options.outFile || options.out;
const declarationPath = outPath ?
removeFileExtension(outPath) + Extension.Dts :
getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName);
if (declarationPath === undefined) return undefined;
const declarationFile = getFile(declarationPath);
if (!declarationFile) return undefined;
const newLoc = getSourceMapper(declarationPath, declarationFile).getGeneratedPosition(info);
const newLoc = getDocumentPositionMapper(declarationPath, info.fileName).getGeneratedPosition(info);
return newLoc === info ? undefined : newLoc;
}
function getFile(fileName: string): SourceFileLike | undefined {
function getSourceFile(fileName: string) {
const program = host.getProgram();
if (!program) return undefined;
const path = toPath(fileName);
const file = getProgram().getSourceFileByPath(path);
if (file && file.resolvedPath === path) {
return file;
// file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file
const file = program.getSourceFileByPath(path);
return file && file.resolvedPath === path ? file : undefined;
}
function getOrCreateSourceFileLike(fileName: string): SourceFileLike | undefined {
const path = toPath(fileName);
const fileFromCache = sourceFileLike.get(path);
if (fileFromCache !== undefined) return fileFromCache ? fileFromCache : undefined;
if (!host.readFile || host.fileExists && !host.fileExists(path)) {
sourceFileLike.set(path, false);
return undefined;
}
return sourcemappedFileCache.get(path);
// And failing that, check the disk
const text = host.readFile(path);
const file = text ? createSourceFileLike(text) : false;
sourceFileLike.set(path, file);
return file ? file : undefined;
}
// This can be called from source mapper in either source program or program that includes generated file
function getSourceFileLike(fileName: string) {
return !host.getSourceFileLike ?
getSourceFile(fileName) || getOrCreateSourceFileLike(fileName) :
host.getSourceFileLike(fileName);
}
function toLineColumnOffset(fileName: string, position: number): LineAndCharacter {
const file = getFile(fileName)!; // TODO: GH#18217
const file = getSourceFileLike(fileName)!; // TODO: GH#18217
return file.getLineAndCharacterOfPosition(position);
}
function clearCache(): void {
sourcemappedFileCache = createSourceFileLikeCache(host);
sourceFileLike.clear();
documentPositionMappers.clear();
}
}
interface SourceFileLikeCache {
get(path: Path): SourceFileLike | undefined;
/**
* string | undefined to contents of map file to create DocumentPositionMapper from it
* DocumentPositionMapper | false to give back cached DocumentPositionMapper
*/
export type ReadMapFile = (mapFileName: string, mapFileNameFromDts: string | undefined) => string | undefined | DocumentPositionMapper | false;
export function getDocumentPositionMapper(
host: DocumentPositionMapperHost,
generatedFileName: string,
generatedFileLineInfo: LineInfo,
readMapFile: ReadMapFile) {
let mapFileName = tryGetSourceMappingURL(generatedFileLineInfo);
if (mapFileName) {
const match = base64UrlRegExp.exec(mapFileName);
if (match) {
if (match[1]) {
const base64Object = match[1];
return convertDocumentToSourceMapper(host, base64decode(sys, base64Object), generatedFileName);
}
// Not a data URL we can parse, skip it
mapFileName = undefined;
}
}
const possibleMapLocations: string[] = [];
if (mapFileName) {
possibleMapLocations.push(mapFileName);
}
possibleMapLocations.push(generatedFileName + ".map");
const originalMapFileName = mapFileName && getNormalizedAbsolutePath(mapFileName, getDirectoryPath(generatedFileName));
for (const location of possibleMapLocations) {
const mapFileName = getNormalizedAbsolutePath(location, getDirectoryPath(generatedFileName));
const mapFileContents = readMapFile(mapFileName, originalMapFileName);
if (isString(mapFileContents)) {
return convertDocumentToSourceMapper(host, mapFileContents, mapFileName);
}
if (mapFileContents !== undefined) {
return mapFileContents || undefined;
}
}
return undefined;
}
function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
const cached = createMap<SourceFileLike>();
function convertDocumentToSourceMapper(host: DocumentPositionMapperHost, contents: string, mapFileName: string) {
const map = tryParseRawSourceMap(contents);
if (!map || !map.sources || !map.file || !map.mappings) {
// obviously invalid map
return undefined;
}
return createDocumentPositionMapper(host, map, mapFileName);
}
function createSourceFileLike(text: string, lineMap?: SourceFileLike["lineMap"]): SourceFileLike {
return {
get(path: Path) {
if (cached.has(path)) {
return cached.get(path);
}
if (!host.fileExists || !host.readFile || !host.fileExists(path)) return;
// And failing that, check the disk
const text = host.readFile(path)!; // TODO: GH#18217
const file = {
text,
lineMap: undefined,
getLineAndCharacterOfPosition(pos: number) {
return computeLineAndCharacterOfPosition(getLineStarts(this), pos);
}
} as SourceFileLike;
cached.set(path, file);
return file;
text,
lineMap,
getLineAndCharacterOfPosition(pos: number) {
return computeLineAndCharacterOfPosition(getLineStarts(this), pos);
}
};
}
+6 -13
View File
@@ -281,33 +281,26 @@ namespace ts.Completions.StringCompletions {
* Takes a script path and returns paths for all potential folders that could be merged with its
* containing folder via the "rootDirs" compiler option
*/
function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptPath: string, ignoreCase: boolean): string[] {
function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptDirectory: string, ignoreCase: boolean): ReadonlyArray<string> {
// Make all paths absolute/normalized if they are not already
rootDirs = rootDirs.map(rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory)));
// Determine the path to the directory containing the script relative to the root directory it is contained within
const relativeDirectory = firstDefined(rootDirs, rootDirectory =>
containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217
containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) ? scriptDirectory.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217
// Now find a path for each potential directory that is to be merged with the one containing the script
return deduplicate<string>(
rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)),
[...rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)), scriptDirectory],
equateStringsCaseSensitive,
compareStringsCaseSensitive);
}
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensionOptions: ExtensionOptions, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): NameAndKind[] {
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude: string): ReadonlyArray<NameAndKind> {
const basePath = compilerOptions.project || host.getCurrentDirectory();
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase);
const result: NameAndKind[] = [];
for (const baseDirectory of baseDirectories) {
getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude, result);
}
return result;
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase);
return flatMap(baseDirectories, baseDirectory => getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude));
}
/**
+21 -7
View File
@@ -1,5 +1,7 @@
/* @internal */
namespace ts {
const visitedNestedConvertibleFunctions = createMap<true>();
export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): DiagnosticWithLocation[] {
program.getSemanticDiagnostics(sourceFile, cancellationToken);
const diags: DiagnosticWithLocation[] = [];
@@ -13,6 +15,7 @@ namespace ts {
const isJsFile = isSourceFileJS(sourceFile);
visitedNestedConvertibleFunctions.clear();
check(sourceFile);
if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
@@ -114,17 +117,22 @@ namespace ts {
}
function addConvertToAsyncFunctionDiagnostics(node: FunctionLikeDeclaration, checker: TypeChecker, diags: Push<DiagnosticWithLocation>): void {
if (!isAsyncFunction(node) &&
node.body &&
isBlock(node.body) &&
hasReturnStatementWithPromiseHandler(node.body) &&
returnsPromise(node, checker)) {
// need to check function before checking map so that deeper levels of nested callbacks are checked
if (isConvertibleFunction(node, checker) && !visitedNestedConvertibleFunctions.has(getKeyFromNode(node))) {
diags.push(createDiagnosticForNode(
!node.name && isVariableDeclaration(node.parent) && isIdentifier(node.parent.name) ? node.parent.name : node,
Diagnostics.This_may_be_converted_to_an_async_function));
}
}
function isConvertibleFunction(node: FunctionLikeDeclaration, checker: TypeChecker) {
return !isAsyncFunction(node) &&
node.body &&
isBlock(node.body) &&
hasReturnStatementWithPromiseHandler(node.body) &&
returnsPromise(node, checker);
}
function returnsPromise(node: FunctionLikeDeclaration, checker: TypeChecker): boolean {
const functionType = checker.getTypeAtLocation(node);
const callSignatures = checker.getSignaturesOfType(functionType, SignatureKind.Call);
@@ -169,14 +177,20 @@ namespace ts {
// should be kept up to date with getTransformationBody in convertToAsyncFunction.ts
function isFixablePromiseArgument(arg: Expression): boolean {
switch (arg.kind) {
case SyntaxKind.NullKeyword:
case SyntaxKind.Identifier: // identifier includes undefined
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
visitedNestedConvertibleFunctions.set(getKeyFromNode(arg as FunctionLikeDeclaration), true);
/* falls through */
case SyntaxKind.NullKeyword:
case SyntaxKind.Identifier: // identifier includes undefined
return true;
default:
return false;
}
}
function getKeyFromNode(exp: FunctionLikeDeclaration) {
return `${exp.pos.toString()}:${exp.end.toString()}`;
}
}
+22 -27
View File
@@ -228,9 +228,8 @@ namespace ts.textChanges {
/** Public for tests only. Other callers should use `ChangeTracker.with`. */
constructor(private readonly newLineCharacter: string, private readonly formatContext: formatting.FormatContext) {}
public deleteRange(sourceFile: SourceFile, range: TextRange) {
public deleteRange(sourceFile: SourceFile, range: TextRange): void {
this.changes.push({ kind: ChangeKind.Remove, sourceFile, range });
return this;
}
delete(sourceFile: SourceFile, node: Node | NodeArray<TypeParameterDeclaration>): void {
@@ -241,11 +240,10 @@ namespace ts.textChanges {
this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) });
}
public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = {}) {
public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = {}): void {
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
const endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
return this;
}
public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = {}): void {
@@ -254,34 +252,32 @@ namespace ts.textChanges {
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
}
public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}) {
public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}): void {
this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile, range, options, node: newNode });
return this;
}
public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions) {
return this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options);
public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void {
this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options);
}
public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions) {
public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void {
this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options);
}
private replaceRangeWithNodes(sourceFile: SourceFile, range: TextRange, newNodes: ReadonlyArray<Node>, options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}) {
private replaceRangeWithNodes(sourceFile: SourceFile, range: TextRange, newNodes: ReadonlyArray<Node>, options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}): void {
this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, range, options, nodes: newNodes });
return this;
}
public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: ReadonlyArray<Node>, options: ChangeNodeOptions = useNonAdjustedPositions) {
return this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options);
public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: ReadonlyArray<Node>, options: ChangeNodeOptions = useNonAdjustedPositions): void {
this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options);
}
public replaceNodeWithText(sourceFile: SourceFile, oldNode: Node, text: string): void {
this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text);
}
public replaceNodeRangeWithNodes(sourceFile: SourceFile, startNode: Node, endNode: Node, newNodes: ReadonlyArray<Node>, options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions) {
return this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options);
public replaceNodeRangeWithNodes(sourceFile: SourceFile, startNode: Node, endNode: Node, newNodes: ReadonlyArray<Node>, options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions): void {
this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options);
}
private nextCommaToken(sourceFile: SourceFile, node: Node): Node | undefined {
@@ -289,12 +285,12 @@ namespace ts.textChanges {
return next && next.kind === SyntaxKind.CommaToken ? next : undefined;
}
public replacePropertyAssignment(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment) {
public replacePropertyAssignment(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment): void {
const suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter);
return this.replaceNode(sourceFile, oldNode, newNode, { suffix });
this.replaceNode(sourceFile, oldNode, newNode, { suffix });
}
public insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}) {
public insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}): void {
this.replaceRange(sourceFile, createRange(pos), newNode, options);
}
@@ -310,7 +306,7 @@ namespace ts.textChanges {
});
}
public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false) {
public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false): void {
this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}, Position.Start), newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween));
}
@@ -343,7 +339,7 @@ namespace ts.textChanges {
this.insertText(sourceFile, token.getStart(sourceFile), text);
}
public insertJsdocCommentBefore(sourceFile: SourceFile, node: HasJSDoc, tag: JSDoc) {
public insertJsdocCommentBefore(sourceFile: SourceFile, node: HasJSDoc, tag: JSDoc): void {
const fnStart = node.getStart(sourceFile);
if (node.jsDoc) {
for (const jsdoc of node.jsDoc) {
@@ -358,7 +354,7 @@ namespace ts.textChanges {
this.insertNodeAt(sourceFile, fnStart, tag, { preserveLeadingWhitespace: false, suffix: this.newLineCharacter + indent });
}
public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string) {
public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string): void {
this.changes.push({ kind: ChangeKind.Text, sourceFile, range, text });
}
@@ -500,7 +496,7 @@ namespace ts.textChanges {
return endPosition;
}
private getInsertNodeAfterOptions(sourceFile: SourceFile, after: Node) {
private getInsertNodeAfterOptions(sourceFile: SourceFile, after: Node): InsertNodeOptions {
const options = this.getInsertNodeAfterOptionsWorker(after);
return {
...options,
@@ -571,14 +567,14 @@ namespace ts.textChanges {
* i.e. arguments in arguments lists, parameters in parameter lists etc.
* Note that separators are part of the node in statements and class elements.
*/
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node, containingList = formatting.SmartIndenter.getContainingList(after, sourceFile)) {
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node, containingList = formatting.SmartIndenter.getContainingList(after, sourceFile)): void {
if (!containingList) {
Debug.fail("node is not a list element");
return this;
return;
}
const index = indexOfNode(containingList, after);
if (index < 0) {
return this;
return;
}
const end = after.getEnd();
if (index !== containingList.length - 1) {
@@ -680,7 +676,6 @@ namespace ts.textChanges {
this.replaceRange(sourceFile, createRange(end), newNode, { prefix: `${tokenToString(separator)} ` });
}
}
return this;
}
private finishClassesWithNodesInsertedAtStart(): void {
@@ -734,7 +729,7 @@ namespace ts.textChanges {
return changes;
}
public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>) {
public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: ReadonlyArray<Statement>): void {
this.newFiles.push({ oldFile, fileName, statements });
}
}
+2
View File
@@ -45,6 +45,7 @@
"refactorProvider.ts",
"codefixes/addConvertToUnknownForNonOverlappingTypes.ts",
"codefixes/addMissingInvocationForDecorator.ts",
"codefixes/addNameToNamelessParameter.ts",
"codefixes/annotateWithTypeFromJSDoc.ts",
"codefixes/inferFromUsage.ts",
"codefixes/convertFunctionToEs6Class.ts",
@@ -55,6 +56,7 @@
"codefixes/importFixes.ts",
"codefixes/fixSpelling.ts",
"codefixes/fixAddMissingMember.ts",
"codefixes/fixAddMissingNewOperator.ts",
"codefixes/fixCannotFindModule.ts",
"codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
"codefixes/fixClassSuperMustPrecedeThisAccess.ts",
+6 -2
View File
@@ -91,7 +91,6 @@ namespace ts {
export interface SourceFileLike {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
/*@internal*/ sourceMapper?: DocumentPositionMapper;
}
export interface SourceMapSource {
@@ -233,6 +232,11 @@ namespace ts {
installPackage?(options: InstallPackageOptions): Promise<ApplyCodeActionCommandResult>;
/* @internal */ inspectValue?(options: InspectValueOptions): Promise<ValueInfo>;
writeFile?(fileName: string, content: string): void;
/* @internal */
getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined;
/* @internal */
getSourceFileLike?(fileName: string): SourceFileLike | undefined;
}
/* @internal */
@@ -489,7 +493,7 @@ namespace ts {
position: number;
}
export class TextChange {
export interface TextChange {
span: TextSpan;
newText: string;
}
+8 -5
View File
@@ -246,6 +246,10 @@ namespace ts {
return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node);
}
export function isTagName(node: Node): boolean {
return isJSDocTag(node.parent) && node.parent.tagName === node;
}
export function isRightSideOfQualifiedName(node: Node) {
return node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node;
}
@@ -1212,6 +1216,7 @@ namespace ts {
export const typeKeywords: ReadonlyArray<SyntaxKind> = [
SyntaxKind.AnyKeyword,
SyntaxKind.BigIntKeyword,
SyntaxKind.BooleanKeyword,
SyntaxKind.FalseKeyword,
SyntaxKind.KeyOfKeyword,
@@ -1277,11 +1282,11 @@ namespace ts {
return !!compilerOptions.module || compilerOptions.target! >= ScriptTarget.ES2015 || !!compilerOptions.noEmit;
}
export function hostUsesCaseSensitiveFileNames(host: LanguageServiceHost): boolean {
export function hostUsesCaseSensitiveFileNames(host: { useCaseSensitiveFileNames?(): boolean; }): boolean {
return host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false;
}
export function hostGetCanonicalFileName(host: LanguageServiceHost): GetCanonicalFileName {
export function hostGetCanonicalFileName(host: { useCaseSensitiveFileNames?(): boolean; }): GetCanonicalFileName {
return createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(host));
}
@@ -1628,9 +1633,7 @@ namespace ts {
}
export function isImportOrExportSpecifierName(location: Node): location is Identifier {
return !!location.parent &&
(location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) &&
(<ImportOrExportSpecifier>location.parent).propertyName === location;
return !!location.parent && isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location;
}
/**
+1 -1
View File
@@ -13,7 +13,7 @@ class CompilerBaselineRunner extends RunnerBase {
private testSuiteName: TestRunnerKind;
private emit: boolean;
public options: string;
public options: string | undefined;
constructor(public testType: CompilerTestType) {
super();
+2
View File
@@ -21,6 +21,8 @@ class FourSlashRunner extends RunnerBase {
this.basePath = "tests/cases/fourslash/server";
this.testSuiteName = "fourslash-server";
break;
default:
throw ts.Debug.assertNever(testType);
}
}
+2 -2
View File
@@ -28,9 +28,9 @@ namespace Harness.Parallel.Host {
let totalCost = 0;
class RemoteSuite extends Mocha.Suite {
suites: RemoteSuite[];
suites!: RemoteSuite[];
suiteMap = ts.createMap<RemoteSuite>();
tests: RemoteTest[];
tests!: RemoteTest[];
constructor(title: string) {
super(title);
this.pending = false;
+1 -1
View File
@@ -67,7 +67,7 @@ namespace project {
class ProjectCompilerHost extends fakes.CompilerHost {
private _testCase: ProjectRunnerTestCase & ts.CompilerOptions;
private _projectParseConfigHost: ProjectParseConfigHost;
private _projectParseConfigHost: ProjectParseConfigHost | undefined;
constructor(sys: fakes.System | vfs.FileSystem, compilerOptions: ts.CompilerOptions, _testCaseJustName: string, testCase: ProjectRunnerTestCase & ts.CompilerOptions, _moduleKind: ts.ModuleKind) {
super(sys, compilerOptions);
+143 -100
View File
@@ -1,100 +1,143 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"outFile": "../../built/local/run.js",
"composite": false,
"declaration": false,
"declarationMap": false,
"types": [
"node", "mocha", "chai"
],
"lib": [
"es6",
"scripthost"
]
},
"references": [
{ "path": "../compiler", "prepend": true },
{ "path": "../services", "prepend": true },
{ "path": "../jsTyping", "prepend": true },
{ "path": "../server", "prepend": true },
{ "path": "../typingsInstallerCore", "prepend": true },
{ "path": "../harness", "prepend": true }
],
"files": [
"fourslashRunner.ts",
"compilerRunner.ts",
"projectsRunner.ts",
"rwcRunner.ts",
"externalCompileRunner.ts",
"test262Runner.ts",
"parallel/host.ts",
"parallel/worker.ts",
"parallel/shared.ts",
"runner.ts",
"unittests/extractTestHelpers.ts",
"unittests/tsserverProjectSystem.ts",
"unittests/typingsInstaller.ts",
"unittests/asserts.ts",
"unittests/base64.ts",
"unittests/builder.ts",
"unittests/cancellableLanguageServiceOperations.ts",
"unittests/commandLineParsing.ts",
"unittests/comments.ts",
"unittests/compileOnSave.ts",
"unittests/compilerCore.ts",
"unittests/configurationExtension.ts",
"unittests/convertCompilerOptionsFromJson.ts",
"unittests/convertToAsyncFunction.ts",
"unittests/convertToBase64.ts",
"unittests/convertTypeAcquisitionFromJson.ts",
"unittests/customTransforms.ts",
"unittests/extractConstants.ts",
"unittests/extractFunctions.ts",
"unittests/extractRanges.ts",
"unittests/factory.ts",
"unittests/hostNewLineSupport.ts",
"unittests/incrementalParser.ts",
"unittests/initializeTSConfig.ts",
"unittests/jsDocParsing.ts",
"unittests/languageService.ts",
"unittests/matchFiles.ts",
"unittests/moduleResolution.ts",
"unittests/organizeImports.ts",
"unittests/parsePseudoBigInt.ts",
"unittests/paths.ts",
"unittests/printer.ts",
"unittests/programMissingFiles.ts",
"unittests/programNoParseFalsyFileNames.ts",
"unittests/projectErrors.ts",
"unittests/projectReferences.ts",
"unittests/publicApi.ts",
"unittests/reuseProgramStructure.ts",
"unittests/session.ts",
"unittests/semver.ts",
"unittests/showConfig.ts",
"unittests/symbolWalker.ts",
"unittests/telemetry.ts",
"unittests/textChanges.ts",
"unittests/textStorage.ts",
"unittests/transform.ts",
"unittests/transpile.ts",
"unittests/tsbuild.ts",
"unittests/tsbuildWatchMode.ts",
"unittests/tsconfigParsing.ts",
"unittests/tscWatchMode.ts",
"unittests/versionCache.ts",
"unittests/evaluation/asyncArrow.ts",
"unittests/evaluation/asyncGenerator.ts",
"unittests/evaluation/forAwaitOf.ts",
"unittests/services/colorization.ts",
"unittests/services/documentRegistry.ts",
"unittests/services/patternMatcher.ts",
"unittests/services/preProcessFile.ts"
]
}
{
"extends": "../tsconfig-base",
"compilerOptions": {
"outFile": "../../built/local/run.js",
"composite": false,
"declaration": false,
"declarationMap": false,
"types": [
"node", "mocha", "chai"
],
"lib": [
"es6",
"scripthost"
]
},
"references": [
{ "path": "../compiler", "prepend": true },
{ "path": "../services", "prepend": true },
{ "path": "../jsTyping", "prepend": true },
{ "path": "../server", "prepend": true },
{ "path": "../typingsInstallerCore", "prepend": true },
{ "path": "../harness", "prepend": true }
],
"files": [
"fourslashRunner.ts",
"compilerRunner.ts",
"projectsRunner.ts",
"rwcRunner.ts",
"externalCompileRunner.ts",
"test262Runner.ts",
"parallel/host.ts",
"parallel/worker.ts",
"parallel/shared.ts",
"runner.ts",
"unittests/services/extract/helpers.ts",
"unittests/tscWatch/helpers.ts",
"unittests/tsserver/helpers.ts",
"unittests/asserts.ts",
"unittests/base64.ts",
"unittests/builder.ts",
"unittests/compilerCore.ts",
"unittests/convertToBase64.ts",
"unittests/customTransforms.ts",
"unittests/factory.ts",
"unittests/incrementalParser.ts",
"unittests/jsDocParsing.ts",
"unittests/moduleResolution.ts",
"unittests/parsePseudoBigInt.ts",
"unittests/paths.ts",
"unittests/printer.ts",
"unittests/programApi.ts",
"unittests/publicApi.ts",
"unittests/reuseProgramStructure.ts",
"unittests/semver.ts",
"unittests/transform.ts",
"unittests/tsbuild.ts",
"unittests/tsbuildWatchMode.ts",
"unittests/config/commandLineParsing.ts",
"unittests/config/configurationExtension.ts",
"unittests/config/convertCompilerOptionsFromJson.ts",
"unittests/config/convertTypeAcquisitionFromJson.ts",
"unittests/config/initializeTSConfig.ts",
"unittests/config/matchFiles.ts",
"unittests/config/projectReferences.ts",
"unittests/config/showConfig.ts",
"unittests/config/tsconfigParsing.ts",
"unittests/evaluation/asyncArrow.ts",
"unittests/evaluation/asyncGenerator.ts",
"unittests/evaluation/forAwaitOf.ts",
"unittests/services/cancellableLanguageServiceOperations.ts",
"unittests/services/colorization.ts",
"unittests/services/convertToAsyncFunction.ts",
"unittests/services/documentRegistry.ts",
"unittests/services/extract/constants.ts",
"unittests/services/extract/functions.ts",
"unittests/services/extract/symbolWalker.ts",
"unittests/services/extract/ranges.ts",
"unittests/services/hostNewLineSupport.ts",
"unittests/services/languageService.ts",
"unittests/services/organizeImports.ts",
"unittests/services/patternMatcher.ts",
"unittests/services/preProcessFile.ts",
"unittests/services/textChanges.ts",
"unittests/services/transpile.ts",
"unittests/tscWatch/consoleClearing.ts",
"unittests/tscWatch/emit.ts",
"unittests/tscWatch/programUpdates.ts",
"unittests/tscWatch/resolutionCache.ts",
"unittests/tscWatch/watchEnvironment.ts",
"unittests/tscWatch/watchApi.ts",
"unittests/tsserver/cachingFileSystemInformation.ts",
"unittests/tsserver/cancellationToken.ts",
"unittests/tsserver/compileOnSave.ts",
"unittests/tsserver/completions.ts",
"unittests/tsserver/configFileSearch.ts",
"unittests/tsserver/configuredProjects.ts",
"unittests/tsserver/declarationFileMaps.ts",
"unittests/tsserver/documentRegistry.ts",
"unittests/tsserver/duplicatePackages.ts",
"unittests/tsserver/events/largeFileReferenced.ts",
"unittests/tsserver/events/projectLanguageServiceState.ts",
"unittests/tsserver/events/projectLoading.ts",
"unittests/tsserver/events/projectUpdatedInBackground.ts",
"unittests/tsserver/events/surveyReady.ts",
"unittests/tsserver/externalProjects.ts",
"unittests/tsserver/forceConsistentCasingInFileNames.ts",
"unittests/tsserver/formatSettings.ts",
"unittests/tsserver/getApplicableRefactors.ts",
"unittests/tsserver/getEditsForFileRename.ts",
"unittests/tsserver/importHelpers.ts",
"unittests/tsserver/inferredProjects.ts",
"unittests/tsserver/languageService.ts",
"unittests/tsserver/maxNodeModuleJsDepth.ts",
"unittests/tsserver/metadataInResponse.ts",
"unittests/tsserver/navTo.ts",
"unittests/tsserver/occurences.ts",
"unittests/tsserver/openFile.ts",
"unittests/tsserver/projectErrors.ts",
"unittests/tsserver/projectReferences.ts",
"unittests/tsserver/projects.ts",
"unittests/tsserver/refactors.ts",
"unittests/tsserver/reload.ts",
"unittests/tsserver/rename.ts",
"unittests/tsserver/resolutionCache.ts",
"unittests/tsserver/session.ts",
"unittests/tsserver/skipLibCheck.ts",
"unittests/tsserver/symLinks.ts",
"unittests/tsserver/syntaxOperations.ts",
"unittests/tsserver/textStorage.ts",
"unittests/tsserver/telemetry.ts",
"unittests/tsserver/typeAquisition.ts",
"unittests/tsserver/typeReferenceDirectives.ts",
"unittests/tsserver/typingsInstaller.ts",
"unittests/tsserver/untitledFiles.ts",
"unittests/tsserver/versionCache.ts",
"unittests/tsserver/watchEnvironment.ts"
]
}
+1 -1
View File
@@ -1,5 +1,5 @@
namespace ts {
describe("assert", () => {
describe("unittests:: assert", () => {
it("deepEqual", () => {
assert.throws(() => assert.deepEqual(createNodeArray([createIdentifier("A")]), createNodeArray([createIdentifier("B")])));
assert.throws(() => assert.deepEqual(createNodeArray([], /*hasTrailingComma*/ true), createNodeArray([], /*hasTrailingComma*/ false)));
+1 -1
View File
@@ -1,5 +1,5 @@
namespace ts {
describe("base64", () => {
describe("unittests:: base64", () => {
describe("base64decode", () => {
it("can decode input strings correctly without needing a host implementation", () => {
const tests = [
+1 -1
View File
@@ -1,5 +1,5 @@
namespace ts {
describe("builder", () => {
describe("unittests:: builder", () => {
it("emits dependent files", () => {
const files: NamedSourceText[] = [
{ name: "/a.ts", text: SourceText.New("", 'import { b } from "./b";', "") },
+1 -1
View File
@@ -1,5 +1,5 @@
namespace ts {
describe("compilerCore", () => {
describe("unittests:: compilerCore", () => {
describe("equalOwnProperties", () => {
it("correctly equates objects", () => {
assert.isTrue(equalOwnProperties({}, {}));
@@ -1,5 +1,5 @@
namespace ts {
describe("parseCommandLine", () => {
describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => {
function assertParseResult(commandLine: string[], expectedParsedCommandLine: ParsedCommandLine) {
const parsed = parseCommandLine(commandLine);
@@ -367,7 +367,7 @@ namespace ts {
});
});
describe("parseBuildOptions", () => {
describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => {
function assertParseResult(commandLine: string[], expectedParsedBuildCommand: ParsedBuildCommand) {
const parsed = parseBuildCommand(commandLine);
const parsedBuildOptions = JSON.stringify(parsed.buildOptions);
@@ -208,7 +208,7 @@ namespace ts {
}
}
describe("configurationExtension", () => {
describe("unittests:: config:: configurationExtension", () => {
forEach<[string, string, fakes.ParseConfigHost], void>([
["under a case insensitive host", caseInsensitiveBasePath, caseInsensitiveHost],
["under a case sensitive host", caseSensitiveBasePath, caseSensitiveHost]
@@ -1,5 +1,5 @@
namespace ts {
describe("convertCompilerOptionsFromJson", () => {
describe("unittests:: config:: convertCompilerOptionsFromJson", () => {
const formatDiagnosticHost: FormatDiagnosticsHost = {
getCurrentDirectory: () => "/apath/",
getCanonicalFileName: createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ true),
@@ -1,6 +1,6 @@
namespace ts {
interface ExpectedResult { typeAcquisition: TypeAcquisition; errors: Diagnostic[]; }
describe("convertTypeAcquisitionFromJson", () => {
describe("unittests:: config:: convertTypeAcquisitionFromJson", () => {
function assertTypeAcquisition(json: any, configFileName: string, expectedResult: ExpectedResult) {
assertTypeAcquisitionWithJson(json, configFileName, expectedResult);
assertTypeAcquisitionWithJsonNode(json, configFileName, expectedResult);
@@ -1,5 +1,5 @@
namespace ts {
describe("initTSConfig", () => {
describe("unittests:: config:: initTSConfig", () => {
function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) {
describe(name, () => {
const commandLine = parseCommandLine(commandLinesArgs);
@@ -30,4 +30,4 @@ namespace ts {
initTSConfigCorrectly("Initialized TSConfig with advanced options", ["--init", "--declaration", "--declarationDir", "lib", "--skipLibCheck", "--noErrorTruncation"]);
});
}
}
@@ -143,7 +143,7 @@ namespace ts {
return createFileDiagnostic(file, start, length, diagnosticMessage, arg0);
}
describe("matchFiles", () => {
describe("unittests:: config:: matchFiles", () => {
it("with defaults", () => {
const json = {};
const expected: ParsedCommandLine = {
@@ -96,7 +96,7 @@ namespace ts {
checkResult(prog, host);
}
describe("project-references meta check", () => {
describe("unittests:: config:: project-references meta check", () => {
it("default setup was created correctly", () => {
const spec: TestSpecification = {
"/primary": {
@@ -118,7 +118,7 @@ namespace ts {
/**
* Validate that we enforce the basic settings constraints for referenced projects
*/
describe("project-references constraint checking for settings", () => {
describe("unittests:: config:: project-references constraint checking for settings", () => {
it("errors when declaration = false", () => {
const spec: TestSpecification = {
"/primary": {
@@ -248,7 +248,7 @@ namespace ts {
/**
* Path mapping behavior
*/
describe("project-references path mapping", () => {
describe("unittests:: config:: project-references path mapping", () => {
it("redirects to the output .d.ts file", () => {
const spec: TestSpecification = {
"/alpha": {
@@ -268,7 +268,7 @@ namespace ts {
});
});
describe("project-references nice-behavior", () => {
describe("unittests:: config:: project-references nice-behavior", () => {
it("issues a nice error when the input file is missing", () => {
const spec: TestSpecification = {
"/alpha": {
@@ -289,7 +289,7 @@ namespace ts {
/**
* 'composite' behavior
*/
describe("project-references behavior changes under composite: true", () => {
describe("unittests:: config:: project-references behavior changes under composite: true", () => {
it("doesn't infer the rootDir from source paths", () => {
const spec: TestSpecification = {
"/alpha": {
@@ -308,7 +308,7 @@ namespace ts {
});
});
describe("errors when a file in a composite project occurs outside the root", () => {
describe("unittests:: config:: project-references errors when a file in a composite project occurs outside the root", () => {
it("Errors when a file is outside the rootdir", () => {
const spec: TestSpecification = {
"/alpha": {

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