@ttsc/lint 0.18.3 → 0.19.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 +95 -43
- package/go.mod +5 -4
- package/internal/rulecode/rulecode.go +88 -0
- package/lib/index.d.ts +10 -1
- package/lib/index.js +45 -17
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +3 -0
- package/lib/structures/TtscLintRuleSetting.d.ts +3 -2
- package/lib/structures/format/ITtscLintFormat.d.ts +3 -2
- package/lib/structures/format/ITtscLintFormatSortImports.d.ts +20 -4
- package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +80 -8
- package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +6 -8
- package/lib/structures/rules/ITtscLintContributorRules.d.ts +18 -2
- package/lib/structures/rules/ITtscLintCoreRuleOptions.d.ts +347 -0
- package/lib/structures/rules/ITtscLintCoreRuleOptions.js +3 -0
- package/lib/structures/rules/ITtscLintCoreRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintCoreRules.d.ts +101 -67
- package/lib/structures/rules/ITtscLintRegexpRules.d.ts +7 -2
- package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +53 -7
- package/lib/structures/rules/ITtscLintRules.d.ts +6 -2
- package/lib/structures/rules/ITtscLintSolidRules.d.ts +0 -8
- package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.d.ts +206 -0
- package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js +8 -0
- package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +55 -42
- package/lib/structures/rules/ITtscLintUnicornRuleOptions.d.ts +276 -0
- package/lib/structures/rules/ITtscLintUnicornRuleOptions.js +3 -0
- package/lib/structures/rules/ITtscLintUnicornRuleOptions.js.map +1 -0
- package/lib/structures/rules/ITtscLintUnicornRules.d.ts +44 -36
- package/lib/structures/rules/index.d.ts +3 -0
- package/lib/structures/rules/index.js +3 -0
- package/lib/structures/rules/index.js.map +1 -1
- package/linthost/ast_helpers.go +521 -23
- package/linthost/ast_selector_matcher.go +1628 -0
- package/linthost/ast_selector_parser.go +628 -0
- package/linthost/comment_scan.go +154 -0
- package/linthost/compile.go +129 -79
- package/linthost/config.go +352 -88
- package/linthost/config_format.go +15 -1
- package/linthost/contrib_adapter.go +129 -25
- package/linthost/declaration_rules.go +12 -11
- package/linthost/directives.go +9 -67
- package/linthost/dispatch.go +37 -3
- package/linthost/engine.go +368 -53
- package/linthost/escape_string.go +77 -0
- package/linthost/fix.go +133 -23
- package/linthost/flags_gen.go +18 -17
- package/linthost/format.go +73 -167
- package/linthost/format_editor_settings.go +134 -26
- package/linthost/grapheme_tables_gen.go +1920 -0
- package/linthost/host.go +160 -61
- package/linthost/literal_escape_scan.go +117 -0
- package/linthost/lsp.go +545 -98
- package/linthost/numeric_literal_precision.go +228 -0
- package/linthost/polyfill_browserslist.go +1439 -0
- package/linthost/polyfill_browserslist_config.go +603 -0
- package/linthost/polyfill_corejs.go +750 -0
- package/linthost/polyfill_data.go +113 -0
- package/linthost/polyfill_data_gen.json +39868 -0
- package/linthost/print_nodes_array.go +7 -1
- package/linthost/print_nodes_object.go +7 -1
- package/linthost/project_engine.go +151 -0
- package/linthost/project_rules.go +78 -0
- package/linthost/regex_clean.go +191 -0
- package/linthost/regex_tree.go +1544 -0
- package/linthost/regex_tree_optimizer.go +1685 -0
- package/linthost/regexp_cache.go +44 -0
- package/linthost/rule_codes.go +105 -0
- package/linthost/rule_codes.json +745 -0
- package/linthost/rules_ban_ts_comment.go +312 -0
- package/linthost/rules_boundaries.go +128 -43
- package/linthost/rules_boundaries_dependencies.go +1013 -0
- package/linthost/rules_core_extra.go +62 -92
- package/linthost/rules_cypress.go +1 -1
- package/linthost/rules_default_case.go +87 -11
- package/linthost/rules_dupes.go +38 -13
- package/linthost/rules_empty.go +188 -20
- package/linthost/rules_escape.go +62 -48
- package/linthost/rules_format_arrow_parens.go +19 -5
- package/linthost/rules_format_bracket_spacing.go +1 -1
- package/linthost/rules_format_clause_join.go +1 -1
- package/linthost/rules_format_declaration_header.go +31 -19
- package/linthost/rules_format_indent.go +1 -1
- package/linthost/rules_format_jsdoc.go +1 -1
- package/linthost/rules_format_orphan_semi.go +1 -1
- package/linthost/rules_format_parameter_properties.go +17 -7
- package/linthost/rules_format_print_width.go +1 -1
- package/linthost/rules_format_quote_props.go +1 -1
- package/linthost/rules_format_quotes.go +1 -1
- package/linthost/rules_format_semi.go +106 -79
- package/linthost/rules_format_sort_imports.go +79 -45
- package/linthost/rules_format_statement_split.go +1 -1
- package/linthost/rules_format_ternary_nullish_parens.go +1 -1
- package/linthost/rules_format_trailing_comma.go +64 -1
- package/linthost/rules_format_whitespace.go +1 -1
- package/linthost/rules_functional.go +21 -22
- package/linthost/rules_gap.go +80 -3
- package/linthost/rules_grouped_accessor_pairs.go +84 -25
- package/linthost/rules_guard_for_in.go +64 -147
- package/linthost/rules_jsx_a11y.go +232 -22
- package/linthost/rules_logic.go +84 -38
- package/linthost/rules_nextjs.go +105 -16
- package/linthost/rules_no_class_assign.go +70 -0
- package/linthost/rules_no_duplicate_imports.go +266 -0
- package/linthost/rules_no_else_return.go +156 -38
- package/linthost/rules_no_extend_native.go +113 -17
- package/linthost/rules_no_fallthrough.go +1013 -0
- package/linthost/rules_no_func_assign.go +70 -0
- package/linthost/rules_no_import_assign.go +278 -86
- package/linthost/rules_no_inner_declarations.go +186 -0
- package/linthost/rules_no_loop_func.go +438 -53
- package/linthost/rules_no_mixed_operators.go +208 -52
- package/linthost/rules_no_param_reassign.go +376 -61
- package/linthost/rules_no_promise_executor_return.go +156 -0
- package/linthost/rules_no_restricted_imports.go +1013 -57
- package/linthost/rules_no_restricted_syntax.go +190 -26
- package/linthost/rules_no_useless_constructor.go +6 -36
- package/linthost/rules_problems.go +154 -311
- package/linthost/rules_promise.go +2578 -109
- package/linthost/rules_react_extras.go +71 -45
- package/linthost/rules_react_hooks.go +18 -2
- package/linthost/rules_react_perf.go +1 -0
- package/linthost/rules_react_refresh.go +1 -1
- package/linthost/rules_regexp.go +230 -14
- package/linthost/rules_security.go +45 -19
- package/linthost/rules_self.go +21 -1
- package/linthost/rules_solid.go +13 -7
- package/linthost/rules_storybook.go +1 -1
- package/linthost/rules_suggestions.go +490 -84
- package/linthost/rules_testing_library.go +12 -1
- package/linthost/rules_ts.go +227 -54
- package/linthost/rules_ts_async.go +0 -131
- package/linthost/rules_ts_no_base_to_string.go +3 -4
- package/linthost/rules_ts_no_misused_promises.go +817 -0
- package/linthost/rules_ts_no_restricted_types.go +320 -34
- package/linthost/rules_ts_no_unnecessary_qualifier.go +132 -55
- package/linthost/rules_ts_no_unsafe_assignment.go +608 -60
- package/linthost/rules_ts_require_array_sort_compare.go +5 -5
- package/linthost/rules_ts_switch_exhaustiveness_check.go +556 -86
- package/linthost/rules_unicorn_better_regex.go +224 -16
- package/linthost/rules_unicorn_consistent_destructuring.go +1002 -7
- package/linthost/rules_unicorn_consistent_existence_index_check.go +208 -29
- package/linthost/rules_unicorn_consistent_function_scoping.go +1041 -8
- package/linthost/rules_unicorn_consistent_template_literal_escape.go +178 -7
- package/linthost/rules_unicorn_escape_case.go +30 -19
- package/linthost/rules_unicorn_filename_case.go +763 -16
- package/linthost/rules_unicorn_import_style.go +783 -17
- package/linthost/rules_unicorn_isolated_functions.go +934 -14
- package/linthost/rules_unicorn_no_hex_escape.go +26 -11
- package/linthost/rules_unicorn_no_typeof_undefined.go +234 -25
- package/linthost/rules_unicorn_no_unnecessary_polyfills.go +376 -21
- package/linthost/rules_unicorn_no_unused_properties.go +756 -19
- package/linthost/rules_unicorn_number_literal_case.go +58 -39
- package/linthost/rules_unicorn_prefer_at.go +7 -3
- package/linthost/rules_unicorn_prefer_number_properties.go +381 -48
- package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
- package/linthost/rules_unicorn_prefer_simple_condition_first.go +597 -19
- package/linthost/rules_unicorn_prefer_string_raw.go +147 -16
- package/linthost/rules_unicorn_prevent_abbreviations.go +1963 -95
- package/linthost/rules_unicorn_string_content.go +611 -15
- package/linthost/rules_unicorn_switch_case_break_position.go +172 -15
- package/linthost/rules_unicorn_template_indent.go +923 -18
- package/linthost/rules_unicorn_text_encoding_identifier_case.go +202 -42
- package/linthost/rules_unicorn_throw_new_error.go +218 -26
- package/linthost/rules_var.go +829 -142
- package/linthost/string_length.go +222 -0
- package/package.json +4 -3
- package/rule/project.go +145 -0
- package/rule/rule.go +58 -1
- package/src/index.ts +58 -17
- package/src/structures/ITtscLintConfig.ts +3 -0
- package/src/structures/TtscLintRuleSetting.ts +3 -2
- package/src/structures/format/ITtscLintFormat.ts +3 -2
- package/src/structures/format/ITtscLintFormatSortImports.ts +21 -4
- package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +122 -8
- package/src/structures/rules/ITtscLintBoundariesRules.ts +6 -8
- package/src/structures/rules/ITtscLintContributorRules.ts +18 -2
- package/src/structures/rules/ITtscLintCoreRuleOptions.ts +465 -0
- package/src/structures/rules/ITtscLintCoreRules.ts +122 -67
- package/src/structures/rules/ITtscLintRegexpRules.ts +7 -2
- package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -7
- package/src/structures/rules/ITtscLintRules.ts +7 -2
- package/src/structures/rules/ITtscLintSolidRules.ts +0 -9
- package/src/structures/rules/ITtscLintTypeScriptRuleOptions.ts +248 -0
- package/src/structures/rules/ITtscLintTypeScriptRules.ts +64 -42
- package/src/structures/rules/ITtscLintUnicornRuleOptions.ts +350 -0
- package/src/structures/rules/ITtscLintUnicornRules.ts +60 -36
- package/src/structures/rules/index.ts +3 -0
|
@@ -1,34 +1,28 @@
|
|
|
1
|
-
// typescript/no-unsafe-assignment
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// https://typescript-eslint.io/rules/no-unsafe-assignment/
|
|
7
|
-
//
|
|
8
|
-
// Type-aware. The rule visits two shapes:
|
|
9
|
-
//
|
|
10
|
-
// - `VariableDeclaration` — the initializer of `let x: T = ...` or
|
|
11
|
-
// `const x: T = ...`. Without a typed target the assignment is
|
|
12
|
-
// trivially safe (the local becomes `any` too), so the rule
|
|
13
|
-
// requires an explicit type annotation OR a target that resolves
|
|
14
|
-
// to a non-`any` type.
|
|
15
|
-
// - `BinaryExpression` with `=` operator — a plain reassignment like
|
|
16
|
-
// `x = anyValue`. The LHS already has a static type from its
|
|
17
|
-
// declaration; the rule fires when the RHS is `any` and the LHS is
|
|
18
|
-
// not.
|
|
19
|
-
//
|
|
20
|
-
// As with the rest of the unsafe-* family `unknown` is intentionally
|
|
21
|
-
// NOT flagged: it forces a narrowing assertion before the value can be
|
|
22
|
-
// stored in a typed slot, which is the explicit ergonomic the upstream
|
|
23
|
-
// rule pushes toward.
|
|
1
|
+
// typescript/no-unsafe-assignment rejects `any` values that escape through an
|
|
2
|
+
// assignment boundary. It follows @typescript-eslint/no-unsafe-assignment's
|
|
3
|
+
// assignment sites and generic comparison boundary: direct `any` is unsafe
|
|
4
|
+
// unless the receiver is `unknown`, while nested type arguments are compared
|
|
5
|
+
// only when both sides are references to the same generic target.
|
|
24
6
|
package linthost
|
|
25
7
|
|
|
26
8
|
import (
|
|
9
|
+
"fmt"
|
|
10
|
+
"strconv"
|
|
11
|
+
"strings"
|
|
12
|
+
|
|
27
13
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
14
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
28
15
|
)
|
|
29
16
|
|
|
30
17
|
type noUnsafeAssignment struct{}
|
|
31
18
|
|
|
19
|
+
type noUnsafeAssignmentComparison uint8
|
|
20
|
+
|
|
21
|
+
const (
|
|
22
|
+
noUnsafeAssignmentComparisonNone noUnsafeAssignmentComparison = iota
|
|
23
|
+
noUnsafeAssignmentComparisonBasic
|
|
24
|
+
)
|
|
25
|
+
|
|
32
26
|
func (noUnsafeAssignment) Name() string { return "typescript/no-unsafe-assignment" }
|
|
33
27
|
func (noUnsafeAssignment) NeedsTypeChecker() bool {
|
|
34
28
|
return true
|
|
@@ -36,66 +30,620 @@ func (noUnsafeAssignment) NeedsTypeChecker() bool {
|
|
|
36
30
|
func (noUnsafeAssignment) Visits() []shimast.Kind {
|
|
37
31
|
return []shimast.Kind{
|
|
38
32
|
shimast.KindVariableDeclaration,
|
|
33
|
+
shimast.KindParameter,
|
|
34
|
+
shimast.KindPropertyDeclaration,
|
|
35
|
+
shimast.KindBindingElement,
|
|
39
36
|
shimast.KindBinaryExpression,
|
|
37
|
+
shimast.KindPropertyAssignment,
|
|
38
|
+
shimast.KindShorthandPropertyAssignment,
|
|
39
|
+
shimast.KindSpreadElement,
|
|
40
|
+
shimast.KindJsxAttribute,
|
|
40
41
|
}
|
|
41
42
|
}
|
|
43
|
+
|
|
42
44
|
func (noUnsafeAssignment) Check(ctx *Context, node *shimast.Node) {
|
|
43
|
-
if ctx.Checker == nil {
|
|
45
|
+
if ctx.Checker == nil || node == nil {
|
|
44
46
|
return
|
|
45
47
|
}
|
|
48
|
+
|
|
46
49
|
switch node.Kind {
|
|
47
50
|
case shimast.KindVariableDeclaration:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
noUnsafeAssignmentCheckVariable(ctx, node)
|
|
52
|
+
case shimast.KindParameter:
|
|
53
|
+
noUnsafeAssignmentCheckParameter(ctx, node)
|
|
54
|
+
case shimast.KindPropertyDeclaration:
|
|
55
|
+
noUnsafeAssignmentCheckPropertyDeclaration(ctx, node)
|
|
56
|
+
case shimast.KindBindingElement:
|
|
57
|
+
noUnsafeAssignmentCheckBindingDefault(ctx, node)
|
|
58
|
+
case shimast.KindBinaryExpression:
|
|
59
|
+
noUnsafeAssignmentCheckBinary(ctx, node)
|
|
60
|
+
case shimast.KindPropertyAssignment:
|
|
61
|
+
noUnsafeAssignmentCheckObjectProperty(ctx, node)
|
|
62
|
+
case shimast.KindShorthandPropertyAssignment:
|
|
63
|
+
noUnsafeAssignmentCheckShorthandProperty(ctx, node)
|
|
64
|
+
case shimast.KindSpreadElement:
|
|
65
|
+
noUnsafeAssignmentCheckArraySpread(ctx, node)
|
|
66
|
+
case shimast.KindJsxAttribute:
|
|
67
|
+
noUnsafeAssignmentCheckJsxAttribute(ctx, node)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func noUnsafeAssignmentCheckVariable(ctx *Context, node *shimast.Node) {
|
|
72
|
+
decl := node.AsVariableDeclaration()
|
|
73
|
+
if decl == nil || decl.Name() == nil || decl.Initializer == nil {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
comparison := noUnsafeAssignmentComparisonNone
|
|
77
|
+
if decl.Type != nil {
|
|
78
|
+
comparison = noUnsafeAssignmentComparisonBasic
|
|
79
|
+
}
|
|
80
|
+
noUnsafeAssignmentCheckSite(ctx, decl.Name(), decl.Initializer, node, comparison)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func noUnsafeAssignmentCheckParameter(ctx *Context, node *shimast.Node) {
|
|
84
|
+
decl := node.AsParameterDeclaration()
|
|
85
|
+
if decl == nil || decl.Name() == nil || decl.Initializer == nil {
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
// A default initializer is an AssignmentPattern upstream. The parameter has
|
|
89
|
+
// an established receiver type even when it has no written annotation.
|
|
90
|
+
noUnsafeAssignmentCheckSite(
|
|
91
|
+
ctx,
|
|
92
|
+
decl.Name(),
|
|
93
|
+
decl.Initializer,
|
|
94
|
+
node,
|
|
95
|
+
noUnsafeAssignmentComparisonBasic,
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func noUnsafeAssignmentCheckPropertyDeclaration(ctx *Context, node *shimast.Node) {
|
|
100
|
+
decl := node.AsPropertyDeclaration()
|
|
101
|
+
if decl == nil || decl.Name() == nil || decl.Initializer == nil {
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
comparison := noUnsafeAssignmentComparisonNone
|
|
105
|
+
if decl.Type != nil {
|
|
106
|
+
comparison = noUnsafeAssignmentComparisonBasic
|
|
107
|
+
}
|
|
108
|
+
noUnsafeAssignmentCheck(
|
|
109
|
+
ctx,
|
|
110
|
+
decl.Name(),
|
|
111
|
+
decl.Initializer,
|
|
112
|
+
node,
|
|
113
|
+
comparison,
|
|
114
|
+
nil,
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func noUnsafeAssignmentCheckBindingDefault(ctx *Context, node *shimast.Node) {
|
|
119
|
+
binding := node.AsBindingElement()
|
|
120
|
+
if binding == nil || binding.Name() == nil || binding.Initializer == nil {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
noUnsafeAssignmentCheckSite(
|
|
124
|
+
ctx,
|
|
125
|
+
binding.Name(),
|
|
126
|
+
binding.Initializer,
|
|
127
|
+
node,
|
|
128
|
+
noUnsafeAssignmentComparisonBasic,
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
func noUnsafeAssignmentCheckBinary(ctx *Context, node *shimast.Node) {
|
|
133
|
+
expression := node.AsBinaryExpression()
|
|
134
|
+
if expression == nil || expression.OperatorToken == nil ||
|
|
135
|
+
expression.OperatorToken.Kind != shimast.KindEqualsToken ||
|
|
136
|
+
expression.Left == nil || expression.Right == nil {
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
noUnsafeAssignmentCheckSite(
|
|
140
|
+
ctx,
|
|
141
|
+
expression.Left,
|
|
142
|
+
expression.Right,
|
|
143
|
+
node,
|
|
144
|
+
noUnsafeAssignmentComparisonBasic,
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
func noUnsafeAssignmentCheckObjectProperty(ctx *Context, node *shimast.Node) {
|
|
149
|
+
property := node.AsPropertyAssignment()
|
|
150
|
+
if property == nil || property.Name() == nil || property.Initializer == nil ||
|
|
151
|
+
node.Parent == nil || node.Parent.Kind != shimast.KindObjectLiteralExpression ||
|
|
152
|
+
isDestructuringAssignmentTarget(node) {
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
receiverType := ctx.Checker.GetContextualTypeForObjectLiteralElement(node, 0)
|
|
156
|
+
noUnsafeAssignmentCheck(
|
|
157
|
+
ctx,
|
|
158
|
+
property.Name(),
|
|
159
|
+
property.Initializer,
|
|
160
|
+
node,
|
|
161
|
+
noUnsafeAssignmentComparisonBasic,
|
|
162
|
+
receiverType,
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
func noUnsafeAssignmentCheckShorthandProperty(ctx *Context, node *shimast.Node) {
|
|
167
|
+
property := node.AsShorthandPropertyAssignment()
|
|
168
|
+
if property == nil || property.Name() == nil {
|
|
169
|
+
return
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// `{ value = fallback }` in a destructuring assignment is represented by a
|
|
173
|
+
// shorthand property with an object-assignment initializer in the tsgo AST.
|
|
174
|
+
if property.ObjectAssignmentInitializer != nil {
|
|
175
|
+
noUnsafeAssignmentCheckSite(
|
|
176
|
+
ctx,
|
|
177
|
+
property.Name(),
|
|
178
|
+
property.ObjectAssignmentInitializer,
|
|
179
|
+
node,
|
|
180
|
+
noUnsafeAssignmentComparisonBasic,
|
|
181
|
+
)
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if node.Parent == nil || node.Parent.Kind != shimast.KindObjectLiteralExpression ||
|
|
186
|
+
isDestructuringAssignmentTarget(node) {
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
receiverType := ctx.Checker.GetContextualTypeForObjectLiteralElement(node, 0)
|
|
190
|
+
noUnsafeAssignmentCheck(
|
|
191
|
+
ctx,
|
|
192
|
+
property.Name(),
|
|
193
|
+
property.Name(),
|
|
194
|
+
node,
|
|
195
|
+
noUnsafeAssignmentComparisonBasic,
|
|
196
|
+
receiverType,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
func noUnsafeAssignmentCheckArraySpread(ctx *Context, node *shimast.Node) {
|
|
201
|
+
spread := node.AsSpreadElement()
|
|
202
|
+
if spread == nil || spread.Expression == nil || node.Parent == nil ||
|
|
203
|
+
node.Parent.Kind != shimast.KindArrayLiteralExpression ||
|
|
204
|
+
isDestructuringAssignmentTarget(node) {
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
senderType := ctx.Checker.GetTypeAtLocation(spread.Expression)
|
|
208
|
+
if typeIsUnsafeAny(senderType) || noUnsafeAssignmentIsAnyArray(ctx.Checker, senderType) {
|
|
209
|
+
ctx.Report(node, "Unsafe spread of an `any` value in an array.")
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
func noUnsafeAssignmentCheckJsxAttribute(ctx *Context, node *shimast.Node) {
|
|
214
|
+
attribute := node.AsJsxAttribute()
|
|
215
|
+
if attribute == nil || attribute.Initializer == nil ||
|
|
216
|
+
attribute.Initializer.Kind != shimast.KindJsxExpression {
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
container := attribute.Initializer.AsJsxExpression()
|
|
220
|
+
if container == nil || container.Expression == nil {
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
receiverType := ctx.Checker.GetContextualTypeForJsxAttribute(node)
|
|
224
|
+
noUnsafeAssignmentCheck(
|
|
225
|
+
ctx,
|
|
226
|
+
attribute.Name(),
|
|
227
|
+
container.Expression,
|
|
228
|
+
container.Expression,
|
|
229
|
+
noUnsafeAssignmentComparisonBasic,
|
|
230
|
+
receiverType,
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// noUnsafeAssignmentCheckSite checks the main assignment and then, only when
|
|
235
|
+
// that boundary did not report, checks unsafe leaves exposed by destructuring.
|
|
236
|
+
func noUnsafeAssignmentCheckSite(
|
|
237
|
+
ctx *Context,
|
|
238
|
+
receiverNode *shimast.Node,
|
|
239
|
+
senderNode *shimast.Node,
|
|
240
|
+
reportingNode *shimast.Node,
|
|
241
|
+
comparison noUnsafeAssignmentComparison,
|
|
242
|
+
) {
|
|
243
|
+
if noUnsafeAssignmentCheck(
|
|
244
|
+
ctx,
|
|
245
|
+
receiverNode,
|
|
246
|
+
senderNode,
|
|
247
|
+
reportingNode,
|
|
248
|
+
comparison,
|
|
249
|
+
nil,
|
|
250
|
+
) {
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
senderType := ctx.Checker.GetTypeAtLocation(stripParens(senderNode))
|
|
254
|
+
if noUnsafeAssignmentCheckArrayDestructure(ctx, stripParens(receiverNode), senderType, senderNode) {
|
|
255
|
+
return
|
|
256
|
+
}
|
|
257
|
+
noUnsafeAssignmentCheckObjectDestructure(ctx, stripParens(receiverNode), senderType, senderNode)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// noUnsafeAssignmentCheck returns true when it reports this assignment.
|
|
261
|
+
func noUnsafeAssignmentCheck(
|
|
262
|
+
ctx *Context,
|
|
263
|
+
receiverNode *shimast.Node,
|
|
264
|
+
senderNode *shimast.Node,
|
|
265
|
+
reportingNode *shimast.Node,
|
|
266
|
+
comparison noUnsafeAssignmentComparison,
|
|
267
|
+
contextualReceiver *shimchecker.Type,
|
|
268
|
+
) bool {
|
|
269
|
+
senderNode = stripParens(senderNode)
|
|
270
|
+
if receiverNode == nil || senderNode == nil {
|
|
271
|
+
return false
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
receiverType := contextualReceiver
|
|
275
|
+
if receiverType == nil {
|
|
276
|
+
receiverType = ctx.Checker.GetTypeAtLocation(stripParens(receiverNode))
|
|
277
|
+
}
|
|
278
|
+
senderType := ctx.Checker.GetTypeAtLocation(senderNode)
|
|
279
|
+
if receiverType == nil || senderType == nil {
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if typeIsUnsafeAny(senderType) {
|
|
284
|
+
if noUnsafeAssignmentIsUnknown(receiverType) {
|
|
285
|
+
return false
|
|
51
286
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
287
|
+
ctx.Report(reportingNode, "Unsafe assignment of an `any` value.")
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if comparison == noUnsafeAssignmentComparisonNone {
|
|
292
|
+
return false
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
result := noUnsafeAssignmentCompareTypes(
|
|
296
|
+
ctx.Checker,
|
|
297
|
+
senderType,
|
|
298
|
+
receiverType,
|
|
299
|
+
senderNode,
|
|
300
|
+
make(map[*shimchecker.Type]map[*shimchecker.Type]struct{}),
|
|
301
|
+
)
|
|
302
|
+
if result == nil {
|
|
303
|
+
return false
|
|
304
|
+
}
|
|
305
|
+
ctx.Report(
|
|
306
|
+
reportingNode,
|
|
307
|
+
fmt.Sprintf(
|
|
308
|
+
"Unsafe assignment of type `%s` to a variable of type `%s`.",
|
|
309
|
+
ctx.Checker.TypeToString(result.sender),
|
|
310
|
+
ctx.Checker.TypeToString(result.receiver),
|
|
311
|
+
),
|
|
312
|
+
)
|
|
313
|
+
return true
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
type noUnsafeAssignmentTypePair struct {
|
|
317
|
+
sender *shimchecker.Type
|
|
318
|
+
receiver *shimchecker.Type
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
func noUnsafeAssignmentCompareTypes(
|
|
322
|
+
checker *shimchecker.Checker,
|
|
323
|
+
sender *shimchecker.Type,
|
|
324
|
+
receiver *shimchecker.Type,
|
|
325
|
+
senderNode *shimast.Node,
|
|
326
|
+
visited map[*shimchecker.Type]map[*shimchecker.Type]struct{},
|
|
327
|
+
) *noUnsafeAssignmentTypePair {
|
|
328
|
+
if sender == nil || receiver == nil {
|
|
329
|
+
return nil
|
|
330
|
+
}
|
|
331
|
+
if typeIsUnsafeAny(sender) {
|
|
332
|
+
if noUnsafeAssignmentIsUnknown(receiver) || typeIsUnsafeAny(receiver) {
|
|
333
|
+
return nil
|
|
334
|
+
}
|
|
335
|
+
return &noUnsafeAssignmentTypePair{sender: sender, receiver: receiver}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
receivers := visited[sender]
|
|
339
|
+
if receivers == nil {
|
|
340
|
+
receivers = make(map[*shimchecker.Type]struct{})
|
|
341
|
+
visited[sender] = receivers
|
|
342
|
+
} else if _, ok := receivers[receiver]; ok {
|
|
343
|
+
return nil
|
|
344
|
+
}
|
|
345
|
+
receivers[receiver] = struct{}{}
|
|
346
|
+
|
|
347
|
+
if !noUnsafeAssignmentIsTypeReference(sender) ||
|
|
348
|
+
!noUnsafeAssignmentIsTypeReference(receiver) ||
|
|
349
|
+
sender.Target() != receiver.Target() {
|
|
350
|
+
return nil
|
|
351
|
+
}
|
|
352
|
+
if noUnsafeAssignmentIsEmptyMapConstructor(senderNode) {
|
|
353
|
+
return nil
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
senderArguments := checker.GetTypeArguments(sender)
|
|
357
|
+
receiverArguments := checker.GetTypeArguments(receiver)
|
|
358
|
+
for index, senderArgument := range senderArguments {
|
|
359
|
+
if index >= len(receiverArguments) {
|
|
360
|
+
return nil
|
|
361
|
+
}
|
|
362
|
+
if noUnsafeAssignmentCompareTypes(
|
|
363
|
+
checker,
|
|
364
|
+
senderArgument,
|
|
365
|
+
receiverArguments[index],
|
|
366
|
+
senderNode,
|
|
367
|
+
visited,
|
|
368
|
+
) != nil {
|
|
369
|
+
return &noUnsafeAssignmentTypePair{sender: sender, receiver: receiver}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return nil
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
func noUnsafeAssignmentIsTypeReference(value *shimchecker.Type) bool {
|
|
376
|
+
return value != nil &&
|
|
377
|
+
value.Flags()&shimchecker.TypeFlagsObject != 0 &&
|
|
378
|
+
value.ObjectFlags()&shimchecker.ObjectFlagsReference != 0
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
func noUnsafeAssignmentIsUnknown(value *shimchecker.Type) bool {
|
|
382
|
+
return value != nil && value.Flags()&shimchecker.TypeFlagsUnknown != 0
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
func noUnsafeAssignmentIsEmptyMapConstructor(node *shimast.Node) bool {
|
|
386
|
+
node = stripParens(node)
|
|
387
|
+
if node == nil || node.Kind != shimast.KindNewExpression {
|
|
388
|
+
return false
|
|
389
|
+
}
|
|
390
|
+
expression := node.AsNewExpression()
|
|
391
|
+
if expression == nil || identifierText(expression.Expression) != "Map" ||
|
|
392
|
+
expression.TypeArguments != nil {
|
|
393
|
+
return false
|
|
394
|
+
}
|
|
395
|
+
return expression.Arguments == nil || len(expression.Arguments.Nodes) == 0
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
func noUnsafeAssignmentIsAnyArray(checker *shimchecker.Checker, value *shimchecker.Type) bool {
|
|
399
|
+
if checker == nil || value == nil {
|
|
400
|
+
return false
|
|
401
|
+
}
|
|
402
|
+
return typeIsUnsafeAny(checker.GetElementTypeOfArrayType(value))
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
func noUnsafeAssignmentCheckArrayDestructure(
|
|
406
|
+
ctx *Context,
|
|
407
|
+
receiver *shimast.Node,
|
|
408
|
+
senderType *shimchecker.Type,
|
|
409
|
+
senderNode *shimast.Node,
|
|
410
|
+
) bool {
|
|
411
|
+
if receiver == nil || senderType == nil ||
|
|
412
|
+
(receiver.Kind != shimast.KindArrayBindingPattern &&
|
|
413
|
+
receiver.Kind != shimast.KindArrayLiteralExpression) {
|
|
414
|
+
return false
|
|
415
|
+
}
|
|
416
|
+
if noUnsafeAssignmentIsAnyArray(ctx.Checker, senderType) {
|
|
417
|
+
ctx.Report(receiver, "Unsafe array destructuring of an `any` array value.")
|
|
418
|
+
return true
|
|
419
|
+
}
|
|
420
|
+
if !shimchecker.IsTupleType(senderType) {
|
|
421
|
+
return false
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
senderElements := ctx.Checker.GetTypeArguments(senderType)
|
|
425
|
+
receiverElements := noUnsafeAssignmentArrayPatternElements(receiver)
|
|
426
|
+
didReport := false
|
|
427
|
+
for index, element := range receiverElements {
|
|
428
|
+
if element == nil || index >= len(senderElements) {
|
|
429
|
+
continue
|
|
430
|
+
}
|
|
431
|
+
target, reportingNode, canRecurse := noUnsafeAssignmentArrayPatternTarget(element)
|
|
432
|
+
if target == nil {
|
|
433
|
+
continue
|
|
57
434
|
}
|
|
58
|
-
|
|
59
|
-
if
|
|
60
|
-
|
|
435
|
+
elementType := senderElements[index]
|
|
436
|
+
if typeIsUnsafeAny(elementType) {
|
|
437
|
+
ctx.Report(reportingNode, "Unsafe array destructuring of a tuple element with an `any` value.")
|
|
438
|
+
didReport = true
|
|
439
|
+
continue
|
|
61
440
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
441
|
+
if !canRecurse {
|
|
442
|
+
continue
|
|
65
443
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
444
|
+
if noUnsafeAssignmentCheckArrayDestructure(ctx, target, elementType, senderNode) ||
|
|
445
|
+
noUnsafeAssignmentCheckObjectDestructure(ctx, target, elementType, senderNode) {
|
|
446
|
+
didReport = true
|
|
69
447
|
}
|
|
70
|
-
|
|
448
|
+
}
|
|
449
|
+
return didReport
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
func noUnsafeAssignmentArrayPatternElements(receiver *shimast.Node) []*shimast.Node {
|
|
453
|
+
switch receiver.Kind {
|
|
454
|
+
case shimast.KindArrayBindingPattern:
|
|
455
|
+
pattern := receiver.AsBindingPattern()
|
|
456
|
+
if pattern != nil && pattern.Elements != nil {
|
|
457
|
+
return pattern.Elements.Nodes
|
|
458
|
+
}
|
|
459
|
+
case shimast.KindArrayLiteralExpression:
|
|
460
|
+
pattern := receiver.AsArrayLiteralExpression()
|
|
461
|
+
if pattern != nil && pattern.Elements != nil {
|
|
462
|
+
return pattern.Elements.Nodes
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return nil
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
func noUnsafeAssignmentArrayPatternTarget(element *shimast.Node) (
|
|
469
|
+
target *shimast.Node,
|
|
470
|
+
reportingNode *shimast.Node,
|
|
471
|
+
canRecurse bool,
|
|
472
|
+
) {
|
|
473
|
+
switch element.Kind {
|
|
474
|
+
case shimast.KindOmittedExpression, shimast.KindSpreadElement:
|
|
475
|
+
return nil, nil, false
|
|
476
|
+
case shimast.KindBindingElement:
|
|
477
|
+
binding := element.AsBindingElement()
|
|
478
|
+
if binding == nil || binding.DotDotDotToken != nil || binding.Name() == nil {
|
|
479
|
+
return nil, nil, false
|
|
480
|
+
}
|
|
481
|
+
if binding.Initializer != nil {
|
|
482
|
+
return binding.Name(), element, false
|
|
483
|
+
}
|
|
484
|
+
return binding.Name(), binding.Name(), true
|
|
71
485
|
case shimast.KindBinaryExpression:
|
|
72
|
-
|
|
73
|
-
if
|
|
74
|
-
|
|
486
|
+
expression := element.AsBinaryExpression()
|
|
487
|
+
if expression == nil || expression.OperatorToken == nil ||
|
|
488
|
+
expression.OperatorToken.Kind != shimast.KindEqualsToken {
|
|
489
|
+
return element, element, true
|
|
75
490
|
}
|
|
76
|
-
|
|
77
|
-
|
|
491
|
+
return expression.Left, element, false
|
|
492
|
+
default:
|
|
493
|
+
return element, element, true
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
func noUnsafeAssignmentCheckObjectDestructure(
|
|
498
|
+
ctx *Context,
|
|
499
|
+
receiver *shimast.Node,
|
|
500
|
+
senderType *shimchecker.Type,
|
|
501
|
+
senderNode *shimast.Node,
|
|
502
|
+
) bool {
|
|
503
|
+
if receiver == nil || senderType == nil ||
|
|
504
|
+
(receiver.Kind != shimast.KindObjectBindingPattern &&
|
|
505
|
+
receiver.Kind != shimast.KindObjectLiteralExpression) {
|
|
506
|
+
return false
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
properties := make(map[string]*shimchecker.Type)
|
|
510
|
+
for _, symbol := range shimchecker.Checker_getPropertiesOfType(ctx.Checker, senderType) {
|
|
511
|
+
if symbol == nil {
|
|
512
|
+
continue
|
|
78
513
|
}
|
|
79
|
-
|
|
80
|
-
|
|
514
|
+
properties[symbol.Name] = shimchecker.Checker_getTypeOfSymbolAtLocation(
|
|
515
|
+
ctx.Checker,
|
|
516
|
+
symbol,
|
|
517
|
+
senderNode,
|
|
518
|
+
)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
didReport := false
|
|
522
|
+
for _, property := range noUnsafeAssignmentObjectPatternProperties(receiver) {
|
|
523
|
+
keyNode, target, reportingNode, canRecurse := noUnsafeAssignmentObjectPatternTarget(property)
|
|
524
|
+
key, ok := noUnsafeAssignmentPropertyName(keyNode)
|
|
525
|
+
if !ok || target == nil {
|
|
526
|
+
continue
|
|
527
|
+
}
|
|
528
|
+
propertyType := properties[key]
|
|
529
|
+
if propertyType == nil {
|
|
530
|
+
continue
|
|
81
531
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
532
|
+
if typeIsUnsafeAny(propertyType) {
|
|
533
|
+
ctx.Report(reportingNode, "Unsafe object destructuring of a property with an `any` value.")
|
|
534
|
+
didReport = true
|
|
535
|
+
continue
|
|
85
536
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return
|
|
537
|
+
if !canRecurse {
|
|
538
|
+
continue
|
|
89
539
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
540
|
+
if noUnsafeAssignmentCheckArrayDestructure(ctx, target, propertyType, senderNode) ||
|
|
541
|
+
noUnsafeAssignmentCheckObjectDestructure(ctx, target, propertyType, senderNode) {
|
|
542
|
+
didReport = true
|
|
93
543
|
}
|
|
94
|
-
ctx.Report(node, noUnsafeAssignmentMessage)
|
|
95
544
|
}
|
|
545
|
+
return didReport
|
|
96
546
|
}
|
|
97
547
|
|
|
98
|
-
|
|
548
|
+
func noUnsafeAssignmentObjectPatternProperties(receiver *shimast.Node) []*shimast.Node {
|
|
549
|
+
switch receiver.Kind {
|
|
550
|
+
case shimast.KindObjectBindingPattern:
|
|
551
|
+
pattern := receiver.AsBindingPattern()
|
|
552
|
+
if pattern != nil && pattern.Elements != nil {
|
|
553
|
+
return pattern.Elements.Nodes
|
|
554
|
+
}
|
|
555
|
+
case shimast.KindObjectLiteralExpression:
|
|
556
|
+
pattern := receiver.AsObjectLiteralExpression()
|
|
557
|
+
if pattern != nil && pattern.Properties != nil {
|
|
558
|
+
return pattern.Properties.Nodes
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return nil
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
func noUnsafeAssignmentObjectPatternTarget(property *shimast.Node) (
|
|
565
|
+
key *shimast.Node,
|
|
566
|
+
target *shimast.Node,
|
|
567
|
+
reportingNode *shimast.Node,
|
|
568
|
+
canRecurse bool,
|
|
569
|
+
) {
|
|
570
|
+
if property == nil {
|
|
571
|
+
return nil, nil, nil, false
|
|
572
|
+
}
|
|
573
|
+
switch property.Kind {
|
|
574
|
+
case shimast.KindBindingElement:
|
|
575
|
+
binding := property.AsBindingElement()
|
|
576
|
+
if binding == nil || binding.DotDotDotToken != nil || binding.Name() == nil {
|
|
577
|
+
return nil, nil, nil, false
|
|
578
|
+
}
|
|
579
|
+
key = binding.PropertyName
|
|
580
|
+
if key == nil {
|
|
581
|
+
key = binding.Name()
|
|
582
|
+
}
|
|
583
|
+
if binding.Initializer != nil {
|
|
584
|
+
return key, binding.Name(), property, false
|
|
585
|
+
}
|
|
586
|
+
return key, binding.Name(), binding.Name(), true
|
|
587
|
+
case shimast.KindPropertyAssignment:
|
|
588
|
+
assignment := property.AsPropertyAssignment()
|
|
589
|
+
if assignment == nil || assignment.Name() == nil || assignment.Initializer == nil {
|
|
590
|
+
return nil, nil, nil, false
|
|
591
|
+
}
|
|
592
|
+
canRecurse = assignment.Initializer.Kind != shimast.KindBinaryExpression
|
|
593
|
+
return assignment.Name(), assignment.Initializer, assignment.Initializer, canRecurse
|
|
594
|
+
case shimast.KindShorthandPropertyAssignment:
|
|
595
|
+
assignment := property.AsShorthandPropertyAssignment()
|
|
596
|
+
if assignment == nil || assignment.Name() == nil {
|
|
597
|
+
return nil, nil, nil, false
|
|
598
|
+
}
|
|
599
|
+
if assignment.ObjectAssignmentInitializer != nil {
|
|
600
|
+
return assignment.Name(), assignment.Name(), property, false
|
|
601
|
+
}
|
|
602
|
+
return assignment.Name(), assignment.Name(), assignment.Name(), true
|
|
603
|
+
}
|
|
604
|
+
return nil, nil, nil, false
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
func noUnsafeAssignmentPropertyName(node *shimast.Node) (string, bool) {
|
|
608
|
+
node = stripParens(node)
|
|
609
|
+
if node == nil {
|
|
610
|
+
return "", false
|
|
611
|
+
}
|
|
612
|
+
switch node.Kind {
|
|
613
|
+
case shimast.KindIdentifier:
|
|
614
|
+
return identifierText(node), true
|
|
615
|
+
case shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral:
|
|
616
|
+
return stringLiteralText(node), true
|
|
617
|
+
case shimast.KindNumericLiteral, shimast.KindBigIntLiteral:
|
|
618
|
+
return noUnsafeAssignmentNormalizeNumericKey(numericLiteralText(node)), true
|
|
619
|
+
case shimast.KindTrueKeyword:
|
|
620
|
+
return "true", true
|
|
621
|
+
case shimast.KindFalseKeyword:
|
|
622
|
+
return "false", true
|
|
623
|
+
case shimast.KindNullKeyword:
|
|
624
|
+
return "null", true
|
|
625
|
+
case shimast.KindComputedPropertyName:
|
|
626
|
+
computed := node.AsComputedPropertyName()
|
|
627
|
+
if computed != nil {
|
|
628
|
+
return noUnsafeAssignmentPropertyName(computed.Expression)
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return "", false
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
func noUnsafeAssignmentNormalizeNumericKey(value string) string {
|
|
635
|
+
value = strings.ReplaceAll(strings.TrimSuffix(value, "n"), "_", "")
|
|
636
|
+
if integer, err := strconv.ParseInt(value, 0, 64); err == nil {
|
|
637
|
+
return strconv.FormatInt(integer, 10)
|
|
638
|
+
}
|
|
639
|
+
if integer, err := strconv.ParseUint(value, 0, 64); err == nil {
|
|
640
|
+
return strconv.FormatUint(integer, 10)
|
|
641
|
+
}
|
|
642
|
+
if number, err := strconv.ParseFloat(value, 64); err == nil {
|
|
643
|
+
return strconv.FormatFloat(number, 'g', -1, 64)
|
|
644
|
+
}
|
|
645
|
+
return value
|
|
646
|
+
}
|
|
99
647
|
|
|
100
648
|
func init() {
|
|
101
649
|
Register(noUnsafeAssignment{})
|