ts-codemod-lib 2.0.4 → 2.1.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/dist/cmd/append-as-const.mjs +1 -1
- package/dist/cmd/convert-interface-to-type.mjs +1 -1
- package/dist/cmd/convert-to-readonly.mjs +1 -1
- package/dist/cmd/replace-any-with-unknown.mjs +1 -1
- package/dist/cmd/replace-record-with-unknown-record.mjs +1 -1
- package/dist/cmd/run-transformer-cli.mjs +3 -3
- package/dist/cmd/run-transformer-cli.mjs.map +1 -1
- package/dist/entry-point.mjs +2 -1
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functions/ast-transformers/convert-interface-to-type.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-interface-to-type.mjs +4 -4
- package/dist/functions/ast-transformers/convert-interface-to-type.mjs.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.mjs +31 -12
- package/dist/functions/ast-transformers/convert-to-readonly.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/compare-union-types.mjs +1 -0
- package/dist/functions/ast-transformers/readonly-transformer-helpers/compare-union-types.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/group-union-types.mjs +1 -0
- package/dist/functions/ast-transformers/readonly-transformer-helpers/group-union-types.mjs.map +1 -1
- package/dist/functions/ast-transformers/replace-any-with-unknown.mjs +1 -1
- package/dist/functions/ast-transformers/replace-record-with-unknown-record.mjs +13 -12
- package/dist/functions/ast-transformers/replace-record-with-unknown-record.mjs.map +1 -1
- package/dist/functions/ast-transformers/transform-source-code.d.mts.map +1 -1
- package/dist/functions/ast-transformers/transform-source-code.mjs +41 -13
- package/dist/functions/ast-transformers/transform-source-code.mjs.map +1 -1
- package/dist/functions/constants/ignore-comment-text.d.mts +2 -2
- package/dist/functions/constants/ignore-comment-text.d.mts.map +1 -1
- package/dist/functions/constants/ignore-comment-text.mjs +13 -3
- package/dist/functions/constants/ignore-comment-text.mjs.map +1 -1
- package/dist/functions/constants/index.mjs +1 -1
- package/dist/functions/functions/has-disable-next-line-comment.d.mts +3 -2
- package/dist/functions/functions/has-disable-next-line-comment.d.mts.map +1 -1
- package/dist/functions/functions/has-disable-next-line-comment.mjs +9 -6
- package/dist/functions/functions/has-disable-next-line-comment.mjs.map +1 -1
- package/dist/functions/functions/index.d.mts +1 -0
- package/dist/functions/functions/index.d.mts.map +1 -1
- package/dist/functions/functions/index.mjs +1 -0
- package/dist/functions/functions/index.mjs.map +1 -1
- package/dist/functions/functions/is-as-const-node.d.mts.map +1 -1
- package/dist/functions/functions/is-as-const-node.mjs +2 -1
- package/dist/functions/functions/is-as-const-node.mjs.map +1 -1
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.d.mts +16 -0
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.d.mts.map +1 -0
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs +32 -0
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs.map +1 -0
- package/dist/functions/functions/wrap-with-parentheses.d.mts +13 -1
- package/dist/functions/functions/wrap-with-parentheses.d.mts.map +1 -1
- package/dist/functions/functions/wrap-with-parentheses.mjs +58 -1
- package/dist/functions/functions/wrap-with-parentheses.mjs.map +1 -1
- package/dist/functions/index.mjs +2 -1
- package/dist/functions/index.mjs.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -16
- package/src/cmd/append-as-const.mts +1 -1
- package/src/cmd/convert-interface-to-type.mts +1 -1
- package/src/cmd/convert-to-readonly.mts +1 -1
- package/src/cmd/replace-any-with-unknown.mts +1 -1
- package/src/cmd/replace-record-with-unknown-record.mts +1 -1
- package/src/cmd/run-transformer-cli.mts +3 -3
- package/src/functions/ast-transformers/convert-interface-to-type.mts +6 -7
- package/src/functions/ast-transformers/convert-to-readonly.mts +39 -13
- package/src/functions/ast-transformers/convert-to-readonly.test.mts +79 -0
- package/src/functions/ast-transformers/replace-record-with-unknown-record.mts +15 -12
- package/src/functions/ast-transformers/transform-source-code.mts +44 -15
- package/src/functions/ast-transformers/transformer-specific-ignore.test.mts +129 -0
- package/src/functions/constants/ignore-comment-text.mts +12 -2
- package/src/functions/functions/has-disable-next-line-comment.mts +12 -6
- package/src/functions/functions/index.mts +1 -0
- package/src/functions/functions/is-as-const-node.mts +2 -1
- package/src/functions/functions/should-avoid-parentheses-for-readonly.mts +32 -0
- package/src/functions/functions/wrap-with-parentheses.mts +75 -2
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as tsm from 'ts-morph';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determines if parentheses should be avoided when adding 'readonly' prefix to a type.
|
|
5
|
+
*
|
|
6
|
+
* Parentheses should be AVOIDED in these specific contexts:
|
|
7
|
+
* - Type predicates: `x is [T, U]` -> `x is readonly [T, U]` (not `x is (readonly [T, U])`)
|
|
8
|
+
* because parentheses around the type in a type predicate cause syntax errors
|
|
9
|
+
*
|
|
10
|
+
* For all other contexts, we keep parentheses for safety to avoid precedence issues,
|
|
11
|
+
* relying on prettier to remove unnecessary ones.
|
|
12
|
+
*
|
|
13
|
+
* @param node - The type node to check
|
|
14
|
+
* @returns true if parentheses should be avoided, false otherwise (keep parentheses)
|
|
15
|
+
*/
|
|
16
|
+
export const shouldAvoidParenthesesForReadonly = (node: tsm.Node): boolean => {
|
|
17
|
+
const parent = node.getParent();
|
|
18
|
+
|
|
19
|
+
if (parent === undefined) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check if parent is TypePredicate: x is T
|
|
24
|
+
// In this case, we MUST avoid parentheses: x is readonly T (not x is (readonly T))
|
|
25
|
+
// because `x is (readonly T)` is a syntax error
|
|
26
|
+
if (parent.isKind(tsm.SyntaxKind.TypePredicate)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// For all other cases, keep parentheses for safety
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
@@ -1,2 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a string is already wrapped with a single pair of balanced parentheses
|
|
3
|
+
* that encompasses the entire expression.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* isWrappedWithParentheses('(A)') // true
|
|
7
|
+
* isWrappedWithParentheses('((A))') // true (outer pair wraps everything)
|
|
8
|
+
* isWrappedWithParentheses('(A) | (B)') // false (outer parens don't wrap everything)
|
|
9
|
+
* isWrappedWithParentheses('A') // false
|
|
10
|
+
*/
|
|
11
|
+
import { asUint32, range } from 'ts-data-forge';
|
|
12
|
+
|
|
13
|
+
const isWrappedWithParentheses = (str: string): boolean => {
|
|
14
|
+
const trimmed = str.trim();
|
|
15
|
+
|
|
16
|
+
if (!trimmed.startsWith('(') || !trimmed.endsWith(')')) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Check if the opening and closing parentheses are balanced
|
|
21
|
+
// and the opening parenthesis corresponds to the closing one
|
|
22
|
+
let mut_depth = 0;
|
|
23
|
+
|
|
24
|
+
for (const mut_i of range(0, asUint32(trimmed.length))) {
|
|
25
|
+
const char: string = trimmed.charAt(mut_i);
|
|
26
|
+
|
|
27
|
+
switch (char) {
|
|
28
|
+
case '(': {
|
|
29
|
+
mut_depth += 1;
|
|
30
|
+
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
case ')': {
|
|
35
|
+
mut_depth -= 1;
|
|
36
|
+
|
|
37
|
+
// If we reach depth 0 before the end, the outer parentheses don't wrap everything
|
|
38
|
+
if (mut_depth === 0 && mut_i < trimmed.length - 1) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
default: {
|
|
46
|
+
// Other characters - no action needed
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Wraps a string with parentheses if not already wrapped.
|
|
57
|
+
* Avoids adding redundant parentheses when the expression is already
|
|
58
|
+
* fully wrapped with balanced parentheses.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* wrapWithParentheses('A') // '(A)'
|
|
62
|
+
* wrapWithParentheses('(A)') // '(A)' (not '((A))')
|
|
63
|
+
* wrapWithParentheses('A | B') // '(A | B)'
|
|
64
|
+
* wrapWithParentheses('(A | B)') // '(A | B)' (not '((A | B))')
|
|
65
|
+
* wrapWithParentheses('(A) | (B)') // '((A) | (B))' (needs outer parens)
|
|
66
|
+
*/
|
|
67
|
+
export const wrapWithParentheses = (nodeStr: string): string => {
|
|
68
|
+
const trimmed = nodeStr.trim();
|
|
69
|
+
|
|
70
|
+
if (isWrappedWithParentheses(trimmed)) {
|
|
71
|
+
return trimmed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return `(${trimmed})` as const;
|
|
75
|
+
};
|