@ttsc/lint 0.18.4 → 0.19.1
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 +125 -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 +47 -8
- 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 +159 -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 +231 -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 +206 -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,47 +1,211 @@
|
|
|
1
|
-
// noRestrictedSyntax
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// denylist can stack additional rules until option decoding lands.
|
|
1
|
+
// noRestrictedSyntax applies only the AST selectors configured by the
|
|
2
|
+
// project. It has no built-in denylist: a severity without selector options is
|
|
3
|
+
// intentionally silent, matching ESLint's official rule contract.
|
|
4
|
+
//
|
|
5
|
+
// Selectors use esquery's grammar over the TypeScript-Go AST. Native kind
|
|
6
|
+
// names (without the Kind prefix) are authoritative; common ESTree aliases are
|
|
7
|
+
// accepted where the two trees have equivalent nodes. Tree combinators follow
|
|
8
|
+
// TypeScript-Go's parent/ForEachChild relationships, so TypeScript-only syntax
|
|
9
|
+
// participates without a parallel or monkeypatched AST.
|
|
11
10
|
// https://eslint.org/docs/latest/rules/no-restricted-syntax
|
|
12
11
|
package linthost
|
|
13
12
|
|
|
14
13
|
import (
|
|
14
|
+
"bytes"
|
|
15
|
+
"encoding/json"
|
|
16
|
+
"fmt"
|
|
17
|
+
"io"
|
|
18
|
+
"sort"
|
|
19
|
+
"strings"
|
|
20
|
+
|
|
15
21
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
16
22
|
)
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
type noRestrictedSyntax struct{ optionsRule }
|
|
25
|
+
|
|
26
|
+
type noRestrictedSyntaxOption struct {
|
|
27
|
+
selector string
|
|
28
|
+
message string
|
|
29
|
+
messageSet bool
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type noRestrictedSyntaxOptionKey struct {
|
|
33
|
+
selector string
|
|
34
|
+
message string
|
|
35
|
+
messageSet bool
|
|
36
|
+
structured bool
|
|
24
37
|
}
|
|
25
38
|
|
|
26
|
-
type
|
|
39
|
+
type compiledNoRestrictedSyntaxOption struct {
|
|
40
|
+
selector *astSelector
|
|
41
|
+
message string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type noRestrictedSyntaxMatch struct {
|
|
45
|
+
node *shimast.Node
|
|
46
|
+
message string
|
|
47
|
+
}
|
|
27
48
|
|
|
28
49
|
func (noRestrictedSyntax) Name() string { return "no-restricted-syntax" }
|
|
29
50
|
func (noRestrictedSyntax) Visits() []shimast.Kind {
|
|
30
|
-
|
|
31
|
-
for kind := range noRestrictedSyntaxDefault {
|
|
32
|
-
kinds = append(kinds, kind)
|
|
33
|
-
}
|
|
34
|
-
return kinds
|
|
51
|
+
return []shimast.Kind{shimast.KindSourceFile}
|
|
35
52
|
}
|
|
53
|
+
|
|
54
|
+
// ValidateOptions is consumed by the engine's optional rule-options
|
|
55
|
+
// validation interface. Parsing here makes malformed selectors/configuration a
|
|
56
|
+
// project configuration error before any file is linted.
|
|
57
|
+
func (noRestrictedSyntax) ValidateOptions(raw json.RawMessage) error {
|
|
58
|
+
_, err := compileNoRestrictedSyntaxOptions(raw)
|
|
59
|
+
return err
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
func (noRestrictedSyntax) Check(ctx *Context, node *shimast.Node) {
|
|
37
|
-
if node == nil {
|
|
63
|
+
if ctx == nil || node == nil {
|
|
38
64
|
return
|
|
39
65
|
}
|
|
40
|
-
|
|
41
|
-
if
|
|
66
|
+
options, err := compileNoRestrictedSyntaxOptions(ctx.Options)
|
|
67
|
+
if err != nil {
|
|
68
|
+
// Engine construction already records this as ConfigError. Check stays
|
|
69
|
+
// side-effect-free for direct contributor calls that bypass validation.
|
|
42
70
|
return
|
|
43
71
|
}
|
|
44
|
-
|
|
72
|
+
matches := make([]noRestrictedSyntaxMatch, 0)
|
|
73
|
+
for _, option := range options {
|
|
74
|
+
for _, restricted := range matchASTSelector(node, option.selector) {
|
|
75
|
+
matches = append(matches, noRestrictedSyntaxMatch{node: restricted, message: option.message})
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
sort.SliceStable(matches, func(left, right int) bool {
|
|
79
|
+
return matches[left].node.Pos() < matches[right].node.Pos()
|
|
80
|
+
})
|
|
81
|
+
for _, match := range matches {
|
|
82
|
+
ctx.Report(match.node, match.message)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
func compileNoRestrictedSyntaxOptions(raw json.RawMessage) ([]compiledNoRestrictedSyntaxOption, error) {
|
|
87
|
+
options, err := decodeNoRestrictedSyntaxOptions(raw)
|
|
88
|
+
if err != nil {
|
|
89
|
+
return nil, err
|
|
90
|
+
}
|
|
91
|
+
compiled := make([]compiledNoRestrictedSyntaxOption, 0, len(options))
|
|
92
|
+
selectorIndexes := make(map[string]int, len(options))
|
|
93
|
+
for index, option := range options {
|
|
94
|
+
selector, err := parseASTSelector(option.selector)
|
|
95
|
+
if err != nil {
|
|
96
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d: invalid selector %q: %w", index+1, option.selector, err)
|
|
97
|
+
}
|
|
98
|
+
message := "Using '" + option.selector + "' is not allowed."
|
|
99
|
+
if option.messageSet && option.message != "" {
|
|
100
|
+
message = option.message
|
|
101
|
+
}
|
|
102
|
+
entry := compiledNoRestrictedSyntaxOption{
|
|
103
|
+
selector: selector,
|
|
104
|
+
message: message,
|
|
105
|
+
}
|
|
106
|
+
if previous, exists := selectorIndexes[option.selector]; exists {
|
|
107
|
+
// ESLint registers selector listeners in an object. Reusing a selector
|
|
108
|
+
// therefore replaces its listener/message rather than reporting twice.
|
|
109
|
+
compiled[previous] = entry
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
selectorIndexes[option.selector] = len(compiled)
|
|
113
|
+
compiled = append(compiled, entry)
|
|
114
|
+
}
|
|
115
|
+
return compiled, nil
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func decodeNoRestrictedSyntaxOptions(raw json.RawMessage) ([]noRestrictedSyntaxOption, error) {
|
|
119
|
+
raw = bytes.TrimSpace(raw)
|
|
120
|
+
if len(raw) == 0 || bytes.Equal(raw, []byte("null")) {
|
|
121
|
+
return nil, nil
|
|
122
|
+
}
|
|
123
|
+
encoded := make([]json.RawMessage, 0, 1)
|
|
124
|
+
if raw[0] == '[' {
|
|
125
|
+
if err := decodeStrictJSON(raw, &encoded); err != nil {
|
|
126
|
+
return nil, fmt.Errorf("no-restricted-syntax options must be selector strings or {selector,message} objects: %w", err)
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
encoded = append(encoded, append(json.RawMessage(nil), raw...))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
options := make([]noRestrictedSyntaxOption, 0, len(encoded))
|
|
133
|
+
seen := make(map[noRestrictedSyntaxOptionKey]struct{}, len(encoded))
|
|
134
|
+
for index, item := range encoded {
|
|
135
|
+
item = bytes.TrimSpace(item)
|
|
136
|
+
if len(item) == 0 {
|
|
137
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d is empty", index+1)
|
|
138
|
+
}
|
|
139
|
+
option := noRestrictedSyntaxOption{}
|
|
140
|
+
uniquenessKey := noRestrictedSyntaxOptionKey{}
|
|
141
|
+
switch item[0] {
|
|
142
|
+
case '"':
|
|
143
|
+
if err := decodeStrictJSON(item, &option.selector); err != nil {
|
|
144
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d must be a selector string: %w", index+1, err)
|
|
145
|
+
}
|
|
146
|
+
uniquenessKey.selector = option.selector
|
|
147
|
+
case '{':
|
|
148
|
+
object := struct {
|
|
149
|
+
Selector json.RawMessage `json:"selector"`
|
|
150
|
+
Message json.RawMessage `json:"message"`
|
|
151
|
+
}{}
|
|
152
|
+
if err := decodeStrictJSON(item, &object); err != nil {
|
|
153
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d must contain only selector and message: %w", index+1, err)
|
|
154
|
+
}
|
|
155
|
+
if len(object.Selector) == 0 {
|
|
156
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d is missing selector", index+1)
|
|
157
|
+
}
|
|
158
|
+
if err := decodeNoRestrictedSyntaxString(object.Selector, &option.selector); err != nil {
|
|
159
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d selector must be a string: %w", index+1, err)
|
|
160
|
+
}
|
|
161
|
+
if len(object.Message) != 0 {
|
|
162
|
+
if err := decodeNoRestrictedSyntaxString(object.Message, &option.message); err != nil {
|
|
163
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d message must be a string: %w", index+1, err)
|
|
164
|
+
}
|
|
165
|
+
option.messageSet = true
|
|
166
|
+
}
|
|
167
|
+
uniquenessKey = noRestrictedSyntaxOptionKey{
|
|
168
|
+
selector: option.selector,
|
|
169
|
+
message: option.message,
|
|
170
|
+
messageSet: option.messageSet,
|
|
171
|
+
structured: true,
|
|
172
|
+
}
|
|
173
|
+
default:
|
|
174
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d must be a selector string or {selector,message} object", index+1)
|
|
175
|
+
}
|
|
176
|
+
if strings.TrimSpace(option.selector) == "" {
|
|
177
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d selector must not be empty", index+1)
|
|
178
|
+
}
|
|
179
|
+
if _, duplicate := seen[uniquenessKey]; duplicate {
|
|
180
|
+
return nil, fmt.Errorf("no-restricted-syntax option %d duplicates an earlier option", index+1)
|
|
181
|
+
}
|
|
182
|
+
seen[uniquenessKey] = struct{}{}
|
|
183
|
+
options = append(options, option)
|
|
184
|
+
}
|
|
185
|
+
return options, nil
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
func decodeNoRestrictedSyntaxString(raw json.RawMessage, out *string) error {
|
|
189
|
+
trimmed := bytes.TrimSpace(raw)
|
|
190
|
+
if len(trimmed) < 2 || trimmed[0] != '"' {
|
|
191
|
+
return fmt.Errorf("expected JSON string")
|
|
192
|
+
}
|
|
193
|
+
return decodeStrictJSON(trimmed, out)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
func decodeStrictJSON(raw json.RawMessage, out any) error {
|
|
197
|
+
decoder := json.NewDecoder(bytes.NewReader(raw))
|
|
198
|
+
decoder.DisallowUnknownFields()
|
|
199
|
+
if err := decoder.Decode(out); err != nil {
|
|
200
|
+
return err
|
|
201
|
+
}
|
|
202
|
+
if err := decoder.Decode(&struct{}{}); err != io.EOF {
|
|
203
|
+
if err == nil {
|
|
204
|
+
return fmt.Errorf("multiple JSON values")
|
|
205
|
+
}
|
|
206
|
+
return err
|
|
207
|
+
}
|
|
208
|
+
return nil
|
|
45
209
|
}
|
|
46
210
|
|
|
47
211
|
func init() {
|
|
@@ -73,42 +73,15 @@ func (noUselessConstructor) Check(ctx *Context, node *shimast.Node) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// hasParameterProperty reports whether any constructor parameter carries
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// field, so the constructor is doing real work even if its body is
|
|
76
|
+
// TypeScript's canonical parameter-property modifier flag. Such parameters
|
|
77
|
+
// declare instance fields, so the constructor is doing real work even if its body is
|
|
79
78
|
// empty — removing it would drop the field.
|
|
80
79
|
func hasParameterProperty(node *shimast.Node) bool {
|
|
81
80
|
for _, p := range node.Parameters() {
|
|
82
81
|
if p == nil {
|
|
83
82
|
continue
|
|
84
83
|
}
|
|
85
|
-
if p.ModifierFlags()&
|
|
86
|
-
return true
|
|
87
|
-
}
|
|
88
|
-
// `public` is not represented by any of the above flags but does
|
|
89
|
-
// still create a parameter property. Inspect the raw modifier
|
|
90
|
-
// list for a PublicKeyword.
|
|
91
|
-
decl := p.AsParameterDeclaration()
|
|
92
|
-
if decl == nil {
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
if hasPublicModifier(decl.Modifiers()) {
|
|
96
|
-
return true
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return false
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// hasPublicModifier reports whether `mods` includes a `public` keyword.
|
|
103
|
-
// `public` is a parameter-property qualifier that does not set any of
|
|
104
|
-
// the Private/Protected/Readonly modifier flags, so we walk the raw
|
|
105
|
-
// modifier list to detect it.
|
|
106
|
-
func hasPublicModifier(mods *shimast.ModifierList) bool {
|
|
107
|
-
if mods == nil {
|
|
108
|
-
return false
|
|
109
|
-
}
|
|
110
|
-
for _, m := range mods.Nodes {
|
|
111
|
-
if m != nil && m.Kind == shimast.KindPublicKeyword {
|
|
84
|
+
if p.ModifierFlags()&shimast.ModifierFlagsParameterPropertyModifier != 0 {
|
|
112
85
|
return true
|
|
113
86
|
}
|
|
114
87
|
}
|
|
@@ -194,12 +167,9 @@ func plainParamIdentifier(param *shimast.Node) (string, bool, bool) {
|
|
|
194
167
|
if decl.Initializer != nil || decl.QuestionToken != nil {
|
|
195
168
|
return "", false, false
|
|
196
169
|
}
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
if param.ModifierFlags()&
|
|
200
|
-
return "", false, false
|
|
201
|
-
}
|
|
202
|
-
if hasPublicModifier(decl.Modifiers()) {
|
|
170
|
+
// A parameter-property modifier would already have been caught by
|
|
171
|
+
// hasParameterProperty above, but guard locally too.
|
|
172
|
+
if param.ModifierFlags()&shimast.ModifierFlagsParameterPropertyModifier != 0 {
|
|
203
173
|
return "", false, false
|
|
204
174
|
}
|
|
205
175
|
name := identifierText(decl.Name())
|