@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.
Files changed (188) hide show
  1. package/README.md +125 -43
  2. package/go.mod +5 -4
  3. package/internal/rulecode/rulecode.go +88 -0
  4. package/lib/index.d.ts +10 -1
  5. package/lib/index.js +45 -17
  6. package/lib/index.js.map +1 -1
  7. package/lib/structures/ITtscLintConfig.d.ts +3 -0
  8. package/lib/structures/TtscLintRuleSetting.d.ts +3 -2
  9. package/lib/structures/format/ITtscLintFormat.d.ts +3 -2
  10. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +20 -4
  11. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +80 -8
  12. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +6 -8
  13. package/lib/structures/rules/ITtscLintContributorRules.d.ts +18 -2
  14. package/lib/structures/rules/ITtscLintCoreRuleOptions.d.ts +347 -0
  15. package/lib/structures/rules/ITtscLintCoreRuleOptions.js +3 -0
  16. package/lib/structures/rules/ITtscLintCoreRuleOptions.js.map +1 -0
  17. package/lib/structures/rules/ITtscLintCoreRules.d.ts +101 -67
  18. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +7 -2
  19. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +53 -7
  20. package/lib/structures/rules/ITtscLintRules.d.ts +6 -2
  21. package/lib/structures/rules/ITtscLintSolidRules.d.ts +0 -8
  22. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.d.ts +206 -0
  23. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js +8 -0
  24. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js.map +1 -0
  25. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +55 -42
  26. package/lib/structures/rules/ITtscLintUnicornRuleOptions.d.ts +276 -0
  27. package/lib/structures/rules/ITtscLintUnicornRuleOptions.js +3 -0
  28. package/lib/structures/rules/ITtscLintUnicornRuleOptions.js.map +1 -0
  29. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +44 -36
  30. package/lib/structures/rules/index.d.ts +3 -0
  31. package/lib/structures/rules/index.js +3 -0
  32. package/lib/structures/rules/index.js.map +1 -1
  33. package/linthost/ast_helpers.go +521 -23
  34. package/linthost/ast_selector_matcher.go +1628 -0
  35. package/linthost/ast_selector_parser.go +628 -0
  36. package/linthost/comment_scan.go +154 -0
  37. package/linthost/compile.go +129 -79
  38. package/linthost/config.go +352 -88
  39. package/linthost/config_format.go +15 -1
  40. package/linthost/contrib_adapter.go +47 -8
  41. package/linthost/declaration_rules.go +12 -11
  42. package/linthost/directives.go +9 -67
  43. package/linthost/dispatch.go +37 -3
  44. package/linthost/engine.go +368 -53
  45. package/linthost/escape_string.go +77 -0
  46. package/linthost/fix.go +133 -23
  47. package/linthost/flags_gen.go +18 -17
  48. package/linthost/format.go +73 -167
  49. package/linthost/format_editor_settings.go +134 -26
  50. package/linthost/grapheme_tables_gen.go +1920 -0
  51. package/linthost/host.go +159 -61
  52. package/linthost/literal_escape_scan.go +117 -0
  53. package/linthost/lsp.go +545 -98
  54. package/linthost/numeric_literal_precision.go +228 -0
  55. package/linthost/polyfill_browserslist.go +1439 -0
  56. package/linthost/polyfill_browserslist_config.go +603 -0
  57. package/linthost/polyfill_corejs.go +750 -0
  58. package/linthost/polyfill_data.go +113 -0
  59. package/linthost/polyfill_data_gen.json +39868 -0
  60. package/linthost/print_nodes_array.go +7 -1
  61. package/linthost/print_nodes_object.go +7 -1
  62. package/linthost/project_engine.go +231 -0
  63. package/linthost/project_rules.go +78 -0
  64. package/linthost/regex_clean.go +191 -0
  65. package/linthost/regex_tree.go +1544 -0
  66. package/linthost/regex_tree_optimizer.go +1685 -0
  67. package/linthost/regexp_cache.go +44 -0
  68. package/linthost/rule_codes.go +105 -0
  69. package/linthost/rule_codes.json +745 -0
  70. package/linthost/rules_ban_ts_comment.go +312 -0
  71. package/linthost/rules_boundaries.go +128 -43
  72. package/linthost/rules_boundaries_dependencies.go +1013 -0
  73. package/linthost/rules_core_extra.go +62 -92
  74. package/linthost/rules_cypress.go +1 -1
  75. package/linthost/rules_default_case.go +87 -11
  76. package/linthost/rules_dupes.go +38 -13
  77. package/linthost/rules_empty.go +188 -20
  78. package/linthost/rules_escape.go +62 -48
  79. package/linthost/rules_format_arrow_parens.go +19 -5
  80. package/linthost/rules_format_bracket_spacing.go +1 -1
  81. package/linthost/rules_format_clause_join.go +1 -1
  82. package/linthost/rules_format_declaration_header.go +31 -19
  83. package/linthost/rules_format_indent.go +1 -1
  84. package/linthost/rules_format_jsdoc.go +1 -1
  85. package/linthost/rules_format_orphan_semi.go +1 -1
  86. package/linthost/rules_format_parameter_properties.go +17 -7
  87. package/linthost/rules_format_print_width.go +1 -1
  88. package/linthost/rules_format_quote_props.go +1 -1
  89. package/linthost/rules_format_quotes.go +1 -1
  90. package/linthost/rules_format_semi.go +106 -79
  91. package/linthost/rules_format_sort_imports.go +79 -45
  92. package/linthost/rules_format_statement_split.go +1 -1
  93. package/linthost/rules_format_ternary_nullish_parens.go +1 -1
  94. package/linthost/rules_format_trailing_comma.go +64 -1
  95. package/linthost/rules_format_whitespace.go +1 -1
  96. package/linthost/rules_functional.go +21 -22
  97. package/linthost/rules_gap.go +80 -3
  98. package/linthost/rules_grouped_accessor_pairs.go +84 -25
  99. package/linthost/rules_guard_for_in.go +64 -147
  100. package/linthost/rules_jsx_a11y.go +232 -22
  101. package/linthost/rules_logic.go +84 -38
  102. package/linthost/rules_nextjs.go +105 -16
  103. package/linthost/rules_no_class_assign.go +70 -0
  104. package/linthost/rules_no_duplicate_imports.go +266 -0
  105. package/linthost/rules_no_else_return.go +156 -38
  106. package/linthost/rules_no_extend_native.go +113 -17
  107. package/linthost/rules_no_fallthrough.go +1013 -0
  108. package/linthost/rules_no_func_assign.go +70 -0
  109. package/linthost/rules_no_import_assign.go +278 -86
  110. package/linthost/rules_no_inner_declarations.go +186 -0
  111. package/linthost/rules_no_loop_func.go +438 -53
  112. package/linthost/rules_no_mixed_operators.go +208 -52
  113. package/linthost/rules_no_param_reassign.go +376 -61
  114. package/linthost/rules_no_promise_executor_return.go +156 -0
  115. package/linthost/rules_no_restricted_imports.go +1013 -57
  116. package/linthost/rules_no_restricted_syntax.go +190 -26
  117. package/linthost/rules_no_useless_constructor.go +6 -36
  118. package/linthost/rules_problems.go +154 -311
  119. package/linthost/rules_promise.go +2578 -109
  120. package/linthost/rules_react_extras.go +71 -45
  121. package/linthost/rules_react_hooks.go +18 -2
  122. package/linthost/rules_react_perf.go +1 -0
  123. package/linthost/rules_react_refresh.go +1 -1
  124. package/linthost/rules_regexp.go +230 -14
  125. package/linthost/rules_security.go +45 -19
  126. package/linthost/rules_self.go +21 -1
  127. package/linthost/rules_solid.go +13 -7
  128. package/linthost/rules_storybook.go +1 -1
  129. package/linthost/rules_suggestions.go +490 -84
  130. package/linthost/rules_testing_library.go +12 -1
  131. package/linthost/rules_ts.go +227 -54
  132. package/linthost/rules_ts_async.go +0 -131
  133. package/linthost/rules_ts_no_base_to_string.go +3 -4
  134. package/linthost/rules_ts_no_misused_promises.go +817 -0
  135. package/linthost/rules_ts_no_restricted_types.go +320 -34
  136. package/linthost/rules_ts_no_unnecessary_qualifier.go +132 -55
  137. package/linthost/rules_ts_no_unsafe_assignment.go +608 -60
  138. package/linthost/rules_ts_require_array_sort_compare.go +5 -5
  139. package/linthost/rules_ts_switch_exhaustiveness_check.go +556 -86
  140. package/linthost/rules_unicorn_better_regex.go +224 -16
  141. package/linthost/rules_unicorn_consistent_destructuring.go +1002 -7
  142. package/linthost/rules_unicorn_consistent_existence_index_check.go +208 -29
  143. package/linthost/rules_unicorn_consistent_function_scoping.go +1041 -8
  144. package/linthost/rules_unicorn_consistent_template_literal_escape.go +178 -7
  145. package/linthost/rules_unicorn_escape_case.go +30 -19
  146. package/linthost/rules_unicorn_filename_case.go +763 -16
  147. package/linthost/rules_unicorn_import_style.go +783 -17
  148. package/linthost/rules_unicorn_isolated_functions.go +934 -14
  149. package/linthost/rules_unicorn_no_hex_escape.go +26 -11
  150. package/linthost/rules_unicorn_no_typeof_undefined.go +234 -25
  151. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +376 -21
  152. package/linthost/rules_unicorn_no_unused_properties.go +756 -19
  153. package/linthost/rules_unicorn_number_literal_case.go +58 -39
  154. package/linthost/rules_unicorn_prefer_at.go +7 -3
  155. package/linthost/rules_unicorn_prefer_number_properties.go +381 -48
  156. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
  157. package/linthost/rules_unicorn_prefer_simple_condition_first.go +597 -19
  158. package/linthost/rules_unicorn_prefer_string_raw.go +147 -16
  159. package/linthost/rules_unicorn_prevent_abbreviations.go +1963 -95
  160. package/linthost/rules_unicorn_string_content.go +611 -15
  161. package/linthost/rules_unicorn_switch_case_break_position.go +172 -15
  162. package/linthost/rules_unicorn_template_indent.go +923 -18
  163. package/linthost/rules_unicorn_text_encoding_identifier_case.go +202 -42
  164. package/linthost/rules_unicorn_throw_new_error.go +218 -26
  165. package/linthost/rules_var.go +829 -142
  166. package/linthost/string_length.go +222 -0
  167. package/package.json +4 -3
  168. package/rule/project.go +206 -0
  169. package/rule/rule.go +58 -1
  170. package/src/index.ts +58 -17
  171. package/src/structures/ITtscLintConfig.ts +3 -0
  172. package/src/structures/TtscLintRuleSetting.ts +3 -2
  173. package/src/structures/format/ITtscLintFormat.ts +3 -2
  174. package/src/structures/format/ITtscLintFormatSortImports.ts +21 -4
  175. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +122 -8
  176. package/src/structures/rules/ITtscLintBoundariesRules.ts +6 -8
  177. package/src/structures/rules/ITtscLintContributorRules.ts +18 -2
  178. package/src/structures/rules/ITtscLintCoreRuleOptions.ts +465 -0
  179. package/src/structures/rules/ITtscLintCoreRules.ts +122 -67
  180. package/src/structures/rules/ITtscLintRegexpRules.ts +7 -2
  181. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -7
  182. package/src/structures/rules/ITtscLintRules.ts +7 -2
  183. package/src/structures/rules/ITtscLintSolidRules.ts +0 -9
  184. package/src/structures/rules/ITtscLintTypeScriptRuleOptions.ts +248 -0
  185. package/src/structures/rules/ITtscLintTypeScriptRules.ts +64 -42
  186. package/src/structures/rules/ITtscLintUnicornRuleOptions.ts +350 -0
  187. package/src/structures/rules/ITtscLintUnicornRules.ts +60 -36
  188. package/src/structures/rules/index.ts +3 -0
@@ -1,47 +1,211 @@
1
- // noRestrictedSyntax: a project-level escape hatch that lets a team
2
- // ban specific AST node kinds outright. Upstream ESLint accepts an
3
- // arbitrary selector list and a per-entry message; without the
4
- // rule-options plumbing, this baseline ships a fixed default set that
5
- // covers the two syntactic constructs almost every modern TypeScript
6
- // project forbids: `with` (replaced by destructuring / explicit access
7
- // long ago) and labeled statements (used only to bridge complex
8
- // nested loops, which are themselves better refactored). The full
9
- // configurable surface is deferred projects that need a custom
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
- // noRestrictedSyntaxDefault is the built-in denylist surfaced when no
19
- // config is supplied. Each entry pairs a banned node kind with the
20
- // short, actionable message reported at the offending node.
21
- var noRestrictedSyntaxDefault = map[shimast.Kind]string{
22
- shimast.KindWithStatement: "`with` statements are restricted — use explicit property access instead.",
23
- shimast.KindLabeledStatement: "Labeled statements are restricted — refactor the surrounding control flow instead.",
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 noRestrictedSyntax struct{}
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
- kinds := make([]shimast.Kind, 0, len(noRestrictedSyntaxDefault))
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
- message, banned := noRestrictedSyntaxDefault[node.Kind]
41
- if !banned {
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
- ctx.Report(node, message)
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
- // a TypeScript parameter-property modifier (`public`, `private`,
77
- // `protected`, or `readonly`). Such a parameter declares an instance
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()&(shimast.ModifierFlagsPrivate|shimast.ModifierFlagsProtected|shimast.ModifierFlagsReadonly) != 0 {
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
- // Accessibility modifier on the parameter would already have been
198
- // caught by hasParameterProperty above, but guard locally too.
199
- if param.ModifierFlags()&(shimast.ModifierFlagsPrivate|shimast.ModifierFlagsProtected|shimast.ModifierFlagsReadonly) != 0 {
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())