ts-codemod-lib 3.5.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/functions/ast-transformers/append-as-const.d.mts +13 -4
- package/dist/functions/ast-transformers/append-as-const.d.mts.map +1 -1
- package/dist/functions/ast-transformers/append-as-const.mjs +80 -7
- package/dist/functions/ast-transformers/append-as-const.mjs.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts +23 -4
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.mjs +40 -19
- package/dist/functions/ast-transformers/convert-to-readonly.mjs.map +1 -1
- package/dist/functions/constants/index.d.mts +1 -0
- package/dist/functions/constants/index.d.mts.map +1 -1
- package/dist/functions/constants/index.mjs +1 -0
- package/dist/functions/constants/index.mjs.map +1 -1
- package/dist/functions/constants/mutable-prefixes.d.mts +23 -0
- package/dist/functions/constants/mutable-prefixes.d.mts.map +1 -0
- package/dist/functions/constants/mutable-prefixes.mjs +28 -0
- package/dist/functions/constants/mutable-prefixes.mjs.map +1 -0
- package/package.json +2 -2
- package/src/functions/ast-transformers/append-as-const.mts +152 -18
- package/src/functions/ast-transformers/append-as-const.test.mts +79 -1
- package/src/functions/ast-transformers/convert-to-readonly.mts +124 -41
- package/src/functions/ast-transformers/convert-to-readonly.test.mts +321 -41
- package/src/functions/constants/index.mts +1 -0
- package/src/functions/constants/mutable-prefixes.mts +28 -0
|
@@ -1980,6 +1980,7 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
1980
1980
|
}
|
|
1981
1981
|
}
|
|
1982
1982
|
`,
|
|
1983
|
+
options: { mutablePropertyPrefixes: ['_mut_'] },
|
|
1983
1984
|
},
|
|
1984
1985
|
{
|
|
1985
1986
|
name: 'Method with "draft" prefix',
|
|
@@ -1997,6 +1998,7 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
1997
1998
|
}
|
|
1998
1999
|
}
|
|
1999
2000
|
`,
|
|
2001
|
+
options: { mutablePropertyPrefixes: ['draft'] },
|
|
2000
2002
|
},
|
|
2001
2003
|
{
|
|
2002
2004
|
name: 'Method without mut_ prefix should be transformed',
|
|
@@ -3977,15 +3979,20 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
3977
3979
|
type T = { draftItems: number[]; readonly b: readonly string[] };
|
|
3978
3980
|
type U = { mutable_items: number[]; readonly b: readonly string[] };
|
|
3979
3981
|
`,
|
|
3980
|
-
options: {
|
|
3982
|
+
options: {
|
|
3983
|
+
mutableVariablePrefixes: ['draft', 'mutable_'],
|
|
3984
|
+
mutablePropertyPrefixes: ['draft', 'mutable_'],
|
|
3985
|
+
},
|
|
3981
3986
|
},
|
|
3982
3987
|
{
|
|
3983
|
-
name: '
|
|
3988
|
+
name: '"mut_" alone is the default: it covers "#mut_" and no longer "_mut_"',
|
|
3984
3989
|
source: dedent`
|
|
3985
3990
|
type T = { _mut_items: number[]; b: string[] };
|
|
3991
|
+
class C { #mut_items: number[] = []; c: string[] = []; }
|
|
3986
3992
|
`,
|
|
3987
3993
|
expected: dedent`
|
|
3988
|
-
type T = { _mut_items: number[];
|
|
3994
|
+
type T = Readonly<{ _mut_items: readonly number[]; b: readonly string[] }>;
|
|
3995
|
+
class C { #mut_items: number[] = []; readonly c: readonly string[] = []; }
|
|
3989
3996
|
`,
|
|
3990
3997
|
},
|
|
3991
3998
|
{
|
|
@@ -4291,7 +4298,7 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4291
4298
|
expected: dedent`
|
|
4292
4299
|
type T = Readonly<{ mut_a: readonly number[]; b: readonly string[] }>;
|
|
4293
4300
|
`,
|
|
4294
|
-
options: {
|
|
4301
|
+
options: { mutableVariablePrefixes: [], mutablePropertyPrefixes: [] },
|
|
4295
4302
|
},
|
|
4296
4303
|
])('$name', testFn);
|
|
4297
4304
|
|
|
@@ -4849,7 +4856,7 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4849
4856
|
])('$name', testFn);
|
|
4850
4857
|
});
|
|
4851
4858
|
|
|
4852
|
-
describe('
|
|
4859
|
+
describe('mutableVariablePrefixes and mutablePropertyPrefixes options', () => {
|
|
4853
4860
|
test.each([
|
|
4854
4861
|
{
|
|
4855
4862
|
name: 'Variable declarations',
|
|
@@ -4872,10 +4879,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4872
4879
|
{
|
|
4873
4880
|
name: 'Type aliases',
|
|
4874
4881
|
source: dedent`
|
|
4875
|
-
type
|
|
4882
|
+
type MutableFoo = number[]
|
|
4876
4883
|
`,
|
|
4877
4884
|
expected: dedent`
|
|
4878
|
-
type
|
|
4885
|
+
type MutableFoo = number[]
|
|
4879
4886
|
`,
|
|
4880
4887
|
},
|
|
4881
4888
|
{
|
|
@@ -4889,7 +4896,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4889
4896
|
readonly normalValue: readonly string[];
|
|
4890
4897
|
};
|
|
4891
4898
|
`,
|
|
4892
|
-
options: {
|
|
4899
|
+
options: {
|
|
4900
|
+
mutableVariablePrefixes: ['mut_'],
|
|
4901
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
4902
|
+
},
|
|
4893
4903
|
},
|
|
4894
4904
|
{
|
|
4895
4905
|
name: 'Multiple ignore prefixes',
|
|
@@ -4903,7 +4913,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4903
4913
|
readonly normalValue: readonly boolean[];
|
|
4904
4914
|
};
|
|
4905
4915
|
`,
|
|
4906
|
-
options: {
|
|
4916
|
+
options: {
|
|
4917
|
+
mutableVariablePrefixes: ['mut_', 'mutable_'],
|
|
4918
|
+
mutablePropertyPrefixes: ['mut_', 'mutable_'],
|
|
4919
|
+
},
|
|
4907
4920
|
},
|
|
4908
4921
|
{
|
|
4909
4922
|
name: 'Ignore prefix in nested properties',
|
|
@@ -4923,7 +4936,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4923
4936
|
};
|
|
4924
4937
|
}>;
|
|
4925
4938
|
`,
|
|
4926
|
-
options: {
|
|
4939
|
+
options: {
|
|
4940
|
+
mutableVariablePrefixes: ['mut_'],
|
|
4941
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
4942
|
+
},
|
|
4927
4943
|
},
|
|
4928
4944
|
{
|
|
4929
4945
|
name: 'Ignore prefix in interface',
|
|
@@ -4939,7 +4955,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4939
4955
|
readonly roles: readonly string[];
|
|
4940
4956
|
}
|
|
4941
4957
|
`,
|
|
4942
|
-
options: {
|
|
4958
|
+
options: {
|
|
4959
|
+
mutableVariablePrefixes: ['mut_'],
|
|
4960
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
4961
|
+
},
|
|
4943
4962
|
},
|
|
4944
4963
|
{
|
|
4945
4964
|
name: 'Ignore prefixes for various name node types in interface',
|
|
@@ -4961,7 +4980,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4961
4980
|
readonly ['mu' + 't_d']: readonly string[]; // ComputedPropertyName
|
|
4962
4981
|
}
|
|
4963
4982
|
`,
|
|
4964
|
-
options: {
|
|
4983
|
+
options: {
|
|
4984
|
+
mutableVariablePrefixes: ['mut_'],
|
|
4985
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
4986
|
+
},
|
|
4965
4987
|
},
|
|
4966
4988
|
{
|
|
4967
4989
|
name: 'Ignore prefix with index signature',
|
|
@@ -4979,7 +5001,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4979
5001
|
};
|
|
4980
5002
|
};
|
|
4981
5003
|
`,
|
|
4982
|
-
options: {
|
|
5004
|
+
options: {
|
|
5005
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5006
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5007
|
+
},
|
|
4983
5008
|
},
|
|
4984
5009
|
{
|
|
4985
5010
|
name: 'Index signature in ignored property',
|
|
@@ -4997,21 +5022,27 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
4997
5022
|
};
|
|
4998
5023
|
}
|
|
4999
5024
|
`,
|
|
5000
|
-
options: {
|
|
5025
|
+
options: {
|
|
5026
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5027
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5028
|
+
},
|
|
5001
5029
|
},
|
|
5002
5030
|
{
|
|
5003
5031
|
name: 'Type alias with ignored prefix',
|
|
5004
5032
|
source: dedent`
|
|
5005
|
-
type
|
|
5033
|
+
type MutableConfig = {
|
|
5006
5034
|
items: string[];
|
|
5007
5035
|
};
|
|
5008
5036
|
`,
|
|
5009
5037
|
expected: dedent`
|
|
5010
|
-
type
|
|
5038
|
+
type MutableConfig = {
|
|
5011
5039
|
items: string[];
|
|
5012
5040
|
};
|
|
5013
5041
|
`,
|
|
5014
|
-
options: {
|
|
5042
|
+
options: {
|
|
5043
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5044
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5045
|
+
},
|
|
5015
5046
|
},
|
|
5016
5047
|
{
|
|
5017
5048
|
name: 'Function with ignored prefix',
|
|
@@ -5021,21 +5052,27 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5021
5052
|
expected: dedent`
|
|
5022
5053
|
function mut_process(data: string[]): number[] { return []; }
|
|
5023
5054
|
`,
|
|
5024
|
-
options: {
|
|
5055
|
+
options: {
|
|
5056
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5057
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5058
|
+
},
|
|
5025
5059
|
},
|
|
5026
5060
|
{
|
|
5027
5061
|
name: 'Class with ignored prefix',
|
|
5028
5062
|
source: dedent`
|
|
5029
|
-
class
|
|
5063
|
+
class MutableStore {
|
|
5030
5064
|
items: string[] = [];
|
|
5031
5065
|
}
|
|
5032
5066
|
`,
|
|
5033
5067
|
expected: dedent`
|
|
5034
|
-
class
|
|
5068
|
+
class MutableStore {
|
|
5035
5069
|
items: string[] = [];
|
|
5036
5070
|
}
|
|
5037
5071
|
`,
|
|
5038
|
-
options: {
|
|
5072
|
+
options: {
|
|
5073
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5074
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5075
|
+
},
|
|
5039
5076
|
},
|
|
5040
5077
|
{
|
|
5041
5078
|
name: 'Variable declaration with ignored prefix',
|
|
@@ -5045,37 +5082,46 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5045
5082
|
expected: dedent`
|
|
5046
5083
|
const mut_items: string[] = []
|
|
5047
5084
|
`,
|
|
5048
|
-
options: {
|
|
5085
|
+
options: {
|
|
5086
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5087
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5088
|
+
},
|
|
5049
5089
|
},
|
|
5050
5090
|
{
|
|
5051
5091
|
name: 'Generic type with ignored prefix',
|
|
5052
5092
|
source: dedent`
|
|
5053
|
-
type
|
|
5093
|
+
type MutableList<T> = {
|
|
5054
5094
|
items: T[]
|
|
5055
5095
|
}
|
|
5056
5096
|
`,
|
|
5057
5097
|
expected: dedent`
|
|
5058
|
-
type
|
|
5098
|
+
type MutableList<T> = {
|
|
5059
5099
|
items: T[];
|
|
5060
5100
|
};
|
|
5061
5101
|
`,
|
|
5062
|
-
options: {
|
|
5102
|
+
options: {
|
|
5103
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5104
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5105
|
+
},
|
|
5063
5106
|
},
|
|
5064
5107
|
{
|
|
5065
5108
|
name: 'Union type with ignored prefix members',
|
|
5066
5109
|
source: dedent`
|
|
5067
|
-
type Result =
|
|
5068
|
-
type
|
|
5110
|
+
type Result = MutableSuccess | Error;
|
|
5111
|
+
type MutableSuccess = {
|
|
5069
5112
|
data: string[]
|
|
5070
5113
|
};
|
|
5071
5114
|
`,
|
|
5072
5115
|
expected: dedent`
|
|
5073
|
-
type Result =
|
|
5074
|
-
type
|
|
5116
|
+
type Result = MutableSuccess | Error;
|
|
5117
|
+
type MutableSuccess = {
|
|
5075
5118
|
data: string[];
|
|
5076
5119
|
};
|
|
5077
5120
|
`,
|
|
5078
|
-
options: {
|
|
5121
|
+
options: {
|
|
5122
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5123
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5124
|
+
},
|
|
5079
5125
|
},
|
|
5080
5126
|
{
|
|
5081
5127
|
name: 'Property with ignored prefix in class',
|
|
@@ -5091,7 +5137,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5091
5137
|
readonly items: readonly number[] = [];
|
|
5092
5138
|
}
|
|
5093
5139
|
`,
|
|
5094
|
-
options: {
|
|
5140
|
+
options: {
|
|
5141
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5142
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5143
|
+
},
|
|
5095
5144
|
},
|
|
5096
5145
|
{
|
|
5097
5146
|
name: 'Method parameter with ignored prefix',
|
|
@@ -5105,7 +5154,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5105
5154
|
process(mut_data: string[], data: readonly number[]) {}
|
|
5106
5155
|
}
|
|
5107
5156
|
`,
|
|
5108
|
-
options: {
|
|
5157
|
+
options: {
|
|
5158
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5159
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5160
|
+
},
|
|
5109
5161
|
},
|
|
5110
5162
|
{
|
|
5111
5163
|
name: 'Function expression with ignored prefix',
|
|
@@ -5115,7 +5167,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5115
5167
|
expected: dedent`
|
|
5116
5168
|
const fn = function mut_process(data: string[]): number[] { return []; }
|
|
5117
5169
|
`,
|
|
5118
|
-
options: {
|
|
5170
|
+
options: {
|
|
5171
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5172
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5173
|
+
},
|
|
5119
5174
|
},
|
|
5120
5175
|
{
|
|
5121
5176
|
name: 'Array binding pattern in variable declaration (not implemented)',
|
|
@@ -5125,7 +5180,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5125
5180
|
expected: dedent`
|
|
5126
5181
|
const [mut_first, mut_second]: readonly [readonly string[], readonly number[]] = [[], []];
|
|
5127
5182
|
`,
|
|
5128
|
-
options: {
|
|
5183
|
+
options: {
|
|
5184
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5185
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5186
|
+
},
|
|
5129
5187
|
},
|
|
5130
5188
|
{
|
|
5131
5189
|
// The binding pattern itself is not looked at (see the TODO in
|
|
@@ -5137,7 +5195,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5137
5195
|
expected: dedent`
|
|
5138
5196
|
const { mut_arr, mut_obj }: { mut_arr: string[], mut_obj: number[] } = { mut_arr: [], mut_obj: [] };
|
|
5139
5197
|
`,
|
|
5140
|
-
options: {
|
|
5198
|
+
options: {
|
|
5199
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5200
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5201
|
+
},
|
|
5141
5202
|
},
|
|
5142
5203
|
{
|
|
5143
5204
|
name: 'Parameter with ignored prefix in class constructor',
|
|
@@ -5151,7 +5212,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5151
5212
|
constructor(mut_config: string[]) {}
|
|
5152
5213
|
}
|
|
5153
5214
|
`,
|
|
5154
|
-
options: {
|
|
5215
|
+
options: {
|
|
5216
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5217
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5218
|
+
},
|
|
5155
5219
|
},
|
|
5156
5220
|
{
|
|
5157
5221
|
name: 'Parameter with ignored prefix in type literal method',
|
|
@@ -5165,7 +5229,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5165
5229
|
process(mut_data: string[]): void;
|
|
5166
5230
|
}>;
|
|
5167
5231
|
`,
|
|
5168
|
-
options: {
|
|
5232
|
+
options: {
|
|
5233
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5234
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5235
|
+
},
|
|
5169
5236
|
},
|
|
5170
5237
|
{
|
|
5171
5238
|
name: 'Multiple parameters with ignored prefix',
|
|
@@ -5179,7 +5246,10 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5179
5246
|
update(mut_id: string, mut_data: object[], data: readonly string[]): void;
|
|
5180
5247
|
}
|
|
5181
5248
|
`,
|
|
5182
|
-
options: {
|
|
5249
|
+
options: {
|
|
5250
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5251
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5252
|
+
},
|
|
5183
5253
|
},
|
|
5184
5254
|
{
|
|
5185
5255
|
name: 'Arrow function with ignored prefix parameters',
|
|
@@ -5189,18 +5259,228 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
5189
5259
|
expected: dedent`
|
|
5190
5260
|
const handler = (mut_event: Event[], event: readonly CustomEvent[]) => {};
|
|
5191
5261
|
`,
|
|
5192
|
-
options: {
|
|
5262
|
+
options: {
|
|
5263
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5264
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5265
|
+
},
|
|
5193
5266
|
},
|
|
5194
5267
|
{
|
|
5195
|
-
name: '
|
|
5268
|
+
name: '"draft" is not a default prefix',
|
|
5196
5269
|
source: dedent`
|
|
5197
5270
|
const handler = (draft: Event[], event: CustomEvent[]) => {};
|
|
5271
|
+
type T = { draft: boolean; items: string[] };
|
|
5272
|
+
`,
|
|
5273
|
+
expected: dedent`
|
|
5274
|
+
const handler = (draft: readonly Event[], event: readonly CustomEvent[]) => {};
|
|
5275
|
+
type T = Readonly<{ draft: boolean; items: readonly string[] }>;
|
|
5276
|
+
`,
|
|
5277
|
+
},
|
|
5278
|
+
{
|
|
5279
|
+
name: '"Mutable" and "mut_" are the default type prefixes',
|
|
5280
|
+
source: dedent`
|
|
5281
|
+
type MutableFoo = { a: string[] };
|
|
5282
|
+
interface MutableBar { a: string[] }
|
|
5283
|
+
class MutableBaz { a: string[] = []; }
|
|
5284
|
+
const Q = class MutableQ { a: string[] = []; };
|
|
5285
|
+
type mut_Qux = { a: string[] };
|
|
5286
|
+
type Foo = { a: MutableFoo[] };
|
|
5287
|
+
`,
|
|
5288
|
+
expected: dedent`
|
|
5289
|
+
type MutableFoo = { a: string[] };
|
|
5290
|
+
interface MutableBar { a: string[] }
|
|
5291
|
+
class MutableBaz { a: string[] = []; }
|
|
5292
|
+
const Q = class MutableQ { a: string[] = []; };
|
|
5293
|
+
type mut_Qux = { a: string[] };
|
|
5294
|
+
type Foo = Readonly<{ a: readonly MutableFoo[] }>;
|
|
5295
|
+
`,
|
|
5296
|
+
},
|
|
5297
|
+
{
|
|
5298
|
+
name: 'Variable and property prefixes are separate',
|
|
5299
|
+
source: dedent`
|
|
5300
|
+
const handler = (draft: Event[]) => {};
|
|
5301
|
+
type T = { draft: boolean; items: string[] };
|
|
5302
|
+
`,
|
|
5303
|
+
expected: dedent`
|
|
5304
|
+
const handler = (draft: Event[]) => {};
|
|
5305
|
+
type T = Readonly<{ draft: boolean; items: readonly string[] }>;
|
|
5306
|
+
`,
|
|
5307
|
+
options: { mutableVariablePrefixes: ['draft'] },
|
|
5308
|
+
},
|
|
5309
|
+
{
|
|
5310
|
+
name: 'Each kind of name is matched against its own list: variables',
|
|
5311
|
+
source: dedent`
|
|
5312
|
+
type mut_T = { a: string[] };
|
|
5313
|
+
interface mut_I { a: string[] }
|
|
5314
|
+
class mut_C { a: string[] = []; }
|
|
5315
|
+
function mut_f(a: string[]): void {}
|
|
5316
|
+
const mut_x: string[] = [];
|
|
5317
|
+
type U = [mut_a: string[], b: string[]];
|
|
5318
|
+
class D { #mut_p: string[] = []; 'mut_q': string[] = []; }
|
|
5319
|
+
type V = { mut_r: string[]; s: string[] };
|
|
5320
|
+
interface J { mut_a: string[]; f(mut_p: string[]): void }
|
|
5321
|
+
type W = { mut_m(): string[]; b: string[] };
|
|
5322
|
+
class E { mut_m(x: string[]): string[] { return []; } get mut_g(): string[] { return []; } }
|
|
5323
|
+
`,
|
|
5324
|
+
expected: dedent`
|
|
5325
|
+
type mut_T = Readonly<{ a: readonly string[] }>;
|
|
5326
|
+
interface mut_I { readonly a: readonly string[] }
|
|
5327
|
+
class mut_C { readonly a: readonly string[] = []; }
|
|
5328
|
+
function mut_f(a: string[]): void {}
|
|
5329
|
+
const mut_x: string[] = [];
|
|
5330
|
+
type U = readonly [mut_a: readonly string[], b: readonly string[]];
|
|
5331
|
+
class D { readonly #mut_p: readonly string[] = []; readonly 'mut_q': readonly string[] = []; }
|
|
5332
|
+
type V = Readonly<{ mut_r: readonly string[]; s: readonly string[] }>;
|
|
5333
|
+
interface J { readonly mut_a: readonly string[]; f(mut_p: string[]): void }
|
|
5334
|
+
type W = Readonly<{ mut_m(): readonly string[]; b: readonly string[] }>;
|
|
5335
|
+
class E { mut_m(x: readonly string[]): readonly string[] { return []; } get mut_g(): readonly string[] { return []; } }
|
|
5336
|
+
`,
|
|
5337
|
+
options: {
|
|
5338
|
+
mutableVariablePrefixes: ['mut_'],
|
|
5339
|
+
mutableTypePrefixes: [],
|
|
5340
|
+
mutablePropertyPrefixes: [],
|
|
5341
|
+
},
|
|
5342
|
+
},
|
|
5343
|
+
{
|
|
5344
|
+
name: 'Each kind of name is matched against its own list: types',
|
|
5345
|
+
source: dedent`
|
|
5346
|
+
type mut_T = { a: string[] };
|
|
5347
|
+
interface mut_I { a: string[] }
|
|
5348
|
+
class mut_C { a: string[] = []; }
|
|
5349
|
+
function mut_f(a: string[]): void {}
|
|
5350
|
+
const mut_x: string[] = [];
|
|
5351
|
+
type U = [mut_a: string[], b: string[]];
|
|
5352
|
+
class D { #mut_p: string[] = []; 'mut_q': string[] = []; }
|
|
5353
|
+
type V = { mut_r: string[]; s: string[] };
|
|
5354
|
+
interface J { mut_a: string[]; f(mut_p: string[]): void }
|
|
5355
|
+
type W = { mut_m(): string[]; b: string[] };
|
|
5356
|
+
class E { mut_m(x: string[]): string[] { return []; } get mut_g(): string[] { return []; } }
|
|
5357
|
+
`,
|
|
5358
|
+
expected: dedent`
|
|
5359
|
+
type mut_T = { a: string[] };
|
|
5360
|
+
interface mut_I { a: string[] }
|
|
5361
|
+
class mut_C { a: string[] = []; }
|
|
5362
|
+
function mut_f(a: readonly string[]): void {}
|
|
5363
|
+
const mut_x: readonly string[] = [];
|
|
5364
|
+
type U = readonly [mut_a: readonly string[], b: readonly string[]];
|
|
5365
|
+
class D { readonly #mut_p: readonly string[] = []; readonly 'mut_q': readonly string[] = []; }
|
|
5366
|
+
type V = Readonly<{ mut_r: readonly string[]; s: readonly string[] }>;
|
|
5367
|
+
interface J { readonly mut_a: readonly string[]; f(mut_p: readonly string[]): void }
|
|
5368
|
+
type W = Readonly<{ mut_m(): readonly string[]; b: readonly string[] }>;
|
|
5369
|
+
class E { mut_m(x: readonly string[]): readonly string[] { return []; } get mut_g(): readonly string[] { return []; } }
|
|
5370
|
+
`,
|
|
5371
|
+
options: {
|
|
5372
|
+
mutableVariablePrefixes: [],
|
|
5373
|
+
mutableTypePrefixes: ['mut_'],
|
|
5374
|
+
mutablePropertyPrefixes: [],
|
|
5375
|
+
},
|
|
5376
|
+
},
|
|
5377
|
+
{
|
|
5378
|
+
name: 'Each kind of name is matched against its own list: properties',
|
|
5379
|
+
source: dedent`
|
|
5380
|
+
type mut_T = { a: string[] };
|
|
5381
|
+
interface mut_I { a: string[] }
|
|
5382
|
+
class mut_C { a: string[] = []; }
|
|
5383
|
+
function mut_f(a: string[]): void {}
|
|
5384
|
+
const mut_x: string[] = [];
|
|
5385
|
+
type U = [mut_a: string[], b: string[]];
|
|
5386
|
+
class D { #mut_p: string[] = []; 'mut_q': string[] = []; }
|
|
5387
|
+
type V = { mut_r: string[]; s: string[] };
|
|
5388
|
+
interface J { mut_a: string[]; f(mut_p: string[]): void }
|
|
5389
|
+
type W = { mut_m(): string[]; b: string[] };
|
|
5390
|
+
class E { mut_m(x: string[]): string[] { return []; } get mut_g(): string[] { return []; } }
|
|
5391
|
+
`,
|
|
5392
|
+
expected: dedent`
|
|
5393
|
+
type mut_T = Readonly<{ a: readonly string[] }>;
|
|
5394
|
+
interface mut_I { readonly a: readonly string[] }
|
|
5395
|
+
class mut_C { readonly a: readonly string[] = []; }
|
|
5396
|
+
function mut_f(a: readonly string[]): void {}
|
|
5397
|
+
const mut_x: readonly string[] = [];
|
|
5398
|
+
type U = readonly [mut_a: string[], b: readonly string[]];
|
|
5399
|
+
class D { #mut_p: string[] = []; 'mut_q': string[] = []; }
|
|
5400
|
+
type V = { mut_r: string[]; readonly s: readonly string[] };
|
|
5401
|
+
interface J { mut_a: string[]; f(mut_p: readonly string[]): void }
|
|
5402
|
+
type W = { mut_m(): string[]; readonly b: readonly string[] };
|
|
5403
|
+
class E { mut_m(x: string[]): string[] { return []; } get mut_g(): string[] { return []; } }
|
|
5404
|
+
`,
|
|
5405
|
+
options: {
|
|
5406
|
+
mutableVariablePrefixes: [],
|
|
5407
|
+
mutableTypePrefixes: [],
|
|
5408
|
+
mutablePropertyPrefixes: ['mut_'],
|
|
5409
|
+
},
|
|
5410
|
+
},
|
|
5411
|
+
{
|
|
5412
|
+
name: 'A property prefix with a "#" covers private names only',
|
|
5413
|
+
source: dedent`
|
|
5414
|
+
class C { #mut_a: string[] = []; mut_b: string[] = []; }
|
|
5415
|
+
`,
|
|
5416
|
+
expected: dedent`
|
|
5417
|
+
class C { #mut_a: string[] = []; readonly mut_b: readonly string[] = []; }
|
|
5418
|
+
`,
|
|
5419
|
+
options: { mutablePropertyPrefixes: ['#mut_'] },
|
|
5420
|
+
},
|
|
5421
|
+
{
|
|
5422
|
+
name: 'A property prefix does not apply to variables',
|
|
5423
|
+
source: dedent`
|
|
5424
|
+
const handler = (draft: Event[]) => {};
|
|
5425
|
+
type T = { draft: boolean; items: string[] };
|
|
5198
5426
|
`,
|
|
5199
5427
|
expected: dedent`
|
|
5200
|
-
const handler = (draft:
|
|
5428
|
+
const handler = (draft: readonly Event[]) => {};
|
|
5429
|
+
type T = { draft: boolean; readonly items: readonly string[] };
|
|
5201
5430
|
`,
|
|
5431
|
+
options: { mutablePropertyPrefixes: ['draft'] },
|
|
5432
|
+
},
|
|
5433
|
+
{
|
|
5434
|
+
name: 'A constructor parameter property is a property',
|
|
5435
|
+
source: dedent`
|
|
5436
|
+
class C {
|
|
5437
|
+
draftA: string[] = [];
|
|
5438
|
+
constructor(private draftB: string[], readonly draftD: string[], draftC: string[]) {}
|
|
5439
|
+
}
|
|
5440
|
+
`,
|
|
5441
|
+
expected: dedent`
|
|
5442
|
+
class C {
|
|
5443
|
+
draftA: string[] = [];
|
|
5444
|
+
constructor(private draftB: string[], readonly draftD: string[], draftC: readonly string[]) {}
|
|
5445
|
+
}
|
|
5446
|
+
`,
|
|
5447
|
+
options: { mutablePropertyPrefixes: ['draft'] },
|
|
5448
|
+
},
|
|
5449
|
+
{
|
|
5450
|
+
name: 'A constructor parameter that is not a property is a variable',
|
|
5451
|
+
source: dedent`
|
|
5452
|
+
class C {
|
|
5453
|
+
draftA: string[] = [];
|
|
5454
|
+
constructor(private draftB: string[], draftC: string[]) {}
|
|
5455
|
+
}
|
|
5456
|
+
`,
|
|
5457
|
+
expected: dedent`
|
|
5458
|
+
class C {
|
|
5459
|
+
readonly draftA: readonly string[] = [];
|
|
5460
|
+
constructor(private readonly draftB: readonly string[], draftC: string[]) {}
|
|
5461
|
+
}
|
|
5462
|
+
`,
|
|
5463
|
+
options: { mutableVariablePrefixes: ['draft'] },
|
|
5202
5464
|
},
|
|
5203
5465
|
])('$name', testFn);
|
|
5466
|
+
|
|
5467
|
+
test('the removed ignorePrefixes option is refused', () => {
|
|
5468
|
+
expect(() =>
|
|
5469
|
+
convertToReadonlyTransformer(
|
|
5470
|
+
// @ts-expect-error removed in 4.0.0
|
|
5471
|
+
{ ignorePrefixes: ['mut_'] },
|
|
5472
|
+
),
|
|
5473
|
+
).toThrow('mutableVariablePrefixes');
|
|
5474
|
+
});
|
|
5475
|
+
|
|
5476
|
+
test('an unset ignorePrefixes option is accepted', () => {
|
|
5477
|
+
expect(() =>
|
|
5478
|
+
convertToReadonlyTransformer(
|
|
5479
|
+
// @ts-expect-error removed in 4.0.0
|
|
5480
|
+
{ ignorePrefixes: undefined },
|
|
5481
|
+
),
|
|
5482
|
+
).not.toThrow();
|
|
5483
|
+
});
|
|
5204
5484
|
});
|
|
5205
5485
|
|
|
5206
5486
|
describe('Disable comment handling', () => {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The default `mutableVariablePrefixes` and `mutablePropertyPrefixes` of the
|
|
3
|
+
* transformers: a name that starts with one of these is left mutable. A
|
|
4
|
+
* private name (`#mut_x`) is matched with or after its `#`.
|
|
5
|
+
*
|
|
6
|
+
* The ESLint counterpart is `ignoredMutablePattern` in
|
|
7
|
+
* `libs/eslint-config-typed/src/rules/eslint-functional-rules.mts` (and, for a
|
|
8
|
+
* property, the `ignoreAccessorPattern` of `functional/immutable-data` there);
|
|
9
|
+
* `libs/eslint-config-typed/src/rules/eslint-functional-rules.test.mts` fails
|
|
10
|
+
* when the two differ; it reads this package's `dist/`, so build first.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_MUTABLE_PREFIXES: readonly string[] = Object.freeze([
|
|
13
|
+
'mut_',
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The default `mutableTypePrefixes` of the transformers: a type alias, an
|
|
18
|
+
* interface or a class whose name starts with one of these is left mutable,
|
|
19
|
+
* and `append-as-const` adds no `as const` where the value has to be
|
|
20
|
+
* assignable to it (an annotated variable, `satisfies`, an arrow's return).
|
|
21
|
+
* `Mutable` suits the PascalCase of type names; `mut_` is accepted as for
|
|
22
|
+
* variables. No ESLint rule reads type names, so there is no counterpart to
|
|
23
|
+
* keep in step.
|
|
24
|
+
*/
|
|
25
|
+
export const DEFAULT_MUTABLE_TYPE_PREFIXES: readonly string[] = Object.freeze([
|
|
26
|
+
'Mutable',
|
|
27
|
+
'mut_',
|
|
28
|
+
]);
|