@ttsc/lint 0.12.3 → 0.12.4
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/lib/defaultFormat.d.ts +10 -11
- package/lib/defaultFormat.js +10 -11
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.js +10 -4
- package/lib/index.js.map +1 -1
- package/lib/structures/ITtscLintConfig.d.ts +2 -2
- package/lib/structures/ITtscLintFormatConfig.d.ts +53 -55
- package/lib/structures/ITtscLintPluginMeta.d.ts +9 -1
- package/lib/structures/TtscLintRule.d.ts +10 -1
- package/lib/structures/TtscLintRuleMap.d.ts +2 -2
- package/linthost/ast_helpers.go +17 -0
- package/linthost/compile.go +37 -0
- package/linthost/config.go +184 -35
- package/linthost/config_format.go +257 -244
- package/linthost/directives.go +72 -0
- package/linthost/dispatch.go +33 -33
- package/linthost/engine.go +4 -0
- package/linthost/eslint_runtime.go +31 -0
- package/linthost/fix.go +29 -0
- package/linthost/format.go +23 -0
- package/linthost/host.go +11 -0
- package/linthost/print_dispatch.go +7 -5
- package/linthost/print_doc.go +4 -0
- package/linthost/print_nodes_call.go +9 -0
- package/linthost/rules_arrays.go +5 -2
- package/linthost/rules_debugger.go +3 -2
- package/linthost/rules_dupes.go +7 -4
- package/linthost/rules_empty.go +3 -2
- package/linthost/rules_escape.go +15 -0
- package/linthost/rules_eval.go +3 -0
- package/linthost/rules_finally.go +11 -0
- package/linthost/rules_format_jsdoc.go +7 -0
- package/linthost/rules_format_print_width.go +3 -0
- package/linthost/rules_format_quotes.go +3 -0
- package/linthost/rules_format_sort_imports.go +4 -0
- package/linthost/rules_gap.go +20 -0
- package/linthost/rules_imports.go +5 -7
- package/linthost/rules_logic.go +11 -0
- package/linthost/rules_loops.go +4 -0
- package/linthost/rules_misc.go +4 -2
- package/linthost/rules_params.go +7 -11
- package/linthost/rules_problems.go +24 -1
- package/linthost/rules_promise.go +12 -0
- package/linthost/rules_protos.go +3 -2
- package/linthost/rules_self.go +6 -0
- package/linthost/rules_strings.go +10 -0
- package/linthost/rules_suggestions.go +14 -4
- package/linthost/rules_throw.go +2 -0
- package/linthost/rules_ts.go +13 -0
- package/linthost/rules_ts_extra.go +25 -8
- package/linthost/rules_var.go +14 -1
- package/package.json +3 -3
- package/plugin/main.go +4 -4
- package/rule/astutil/astutil.go +12 -0
- package/rule/rule.go +123 -123
- package/src/defaultFormat.ts +10 -11
- package/src/index.ts +16 -4
- package/src/structures/ITtscLintConfig.ts +2 -2
- package/src/structures/ITtscLintFormatConfig.ts +53 -55
- package/src/structures/ITtscLintPluginMeta.ts +9 -1
- package/src/structures/TtscLintRule.ts +10 -1
- package/src/structures/TtscLintRuleMap.ts +17 -18
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
package linthost
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"fmt"
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
// expandFormatBlock translates a Prettier-style `format` block into the
|
|
@@ -33,189 +33,193 @@ import (
|
|
|
33
33
|
// semantics) before invoking the existing parsers — `mergeRuleMaps`
|
|
34
34
|
// below performs the merge with the right precedence.
|
|
35
35
|
func expandFormatBlock(raw map[string]any) (map[string]any, error) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
if raw == nil {
|
|
37
|
+
return map[string]any{}, nil
|
|
38
|
+
}
|
|
39
|
+
if err := rejectUnknownFormatKeys(raw); err != nil {
|
|
40
|
+
return nil, err
|
|
41
|
+
}
|
|
42
|
+
severity, err := formatBlockSeverity(raw)
|
|
43
|
+
if err != nil {
|
|
44
|
+
return nil, err
|
|
45
|
+
}
|
|
46
|
+
ruleEntry := func(options map[string]any) []any {
|
|
47
|
+
return []any{severity.String(), options}
|
|
48
|
+
}
|
|
49
|
+
out := map[string]any{}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
// format/semi
|
|
52
|
+
semiPrefer := "always"
|
|
53
|
+
if v, ok := raw["semi"]; ok {
|
|
54
|
+
b, err := asBool("format.semi", v)
|
|
55
|
+
if err != nil {
|
|
56
|
+
return nil, err
|
|
57
|
+
}
|
|
58
|
+
if !b {
|
|
59
|
+
semiPrefer = "never"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
out["format/semi"] = ruleEntry(map[string]any{"prefer": semiPrefer})
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
// format/quotes
|
|
65
|
+
quotesPrefer := "double"
|
|
66
|
+
if v, ok := raw["singleQuote"]; ok {
|
|
67
|
+
b, err := asBool("format.singleQuote", v)
|
|
68
|
+
if err != nil {
|
|
69
|
+
return nil, err
|
|
70
|
+
}
|
|
71
|
+
if b {
|
|
72
|
+
quotesPrefer = "single"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
out["format/quotes"] = ruleEntry(map[string]any{"prefer": quotesPrefer})
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
77
|
+
// format/trailing-comma
|
|
78
|
+
tcMode := "all"
|
|
79
|
+
if v, ok := raw["trailingComma"]; ok {
|
|
80
|
+
s, err := asString("format.trailingComma", v)
|
|
81
|
+
if err != nil {
|
|
82
|
+
return nil, err
|
|
83
|
+
}
|
|
84
|
+
switch s {
|
|
85
|
+
case "all", "es5", "none":
|
|
86
|
+
tcMode = s
|
|
87
|
+
default:
|
|
88
|
+
return nil, fmt.Errorf("@ttsc/lint: format.trailingComma must be \"all\", \"es5\", or \"none\"; got %q", s)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
out["format/trailing-comma"] = ruleEntry(map[string]any{"mode": tcMode})
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
93
|
+
// format/print-width
|
|
94
|
+
pwOpts := map[string]any{}
|
|
95
|
+
if v, ok := raw["printWidth"]; ok {
|
|
96
|
+
n, err := asInt("format.printWidth", v)
|
|
97
|
+
if err != nil {
|
|
98
|
+
return nil, err
|
|
99
|
+
}
|
|
100
|
+
pwOpts["printWidth"] = n
|
|
101
|
+
}
|
|
102
|
+
if v, ok := raw["tabWidth"]; ok {
|
|
103
|
+
n, err := asInt("format.tabWidth", v)
|
|
104
|
+
if err != nil {
|
|
105
|
+
return nil, err
|
|
106
|
+
}
|
|
107
|
+
pwOpts["tabWidth"] = n
|
|
108
|
+
}
|
|
109
|
+
if v, ok := raw["useTabs"]; ok {
|
|
110
|
+
b, err := asBool("format.useTabs", v)
|
|
111
|
+
if err != nil {
|
|
112
|
+
return nil, err
|
|
113
|
+
}
|
|
114
|
+
pwOpts["useTabs"] = b
|
|
115
|
+
}
|
|
116
|
+
if v, ok := raw["endOfLine"]; ok {
|
|
117
|
+
s, err := asString("format.endOfLine", v)
|
|
118
|
+
if err != nil {
|
|
119
|
+
return nil, err
|
|
120
|
+
}
|
|
121
|
+
if s != "lf" && s != "crlf" {
|
|
122
|
+
return nil, fmt.Errorf("@ttsc/lint: format.endOfLine must be \"lf\" or \"crlf\"; got %q", s)
|
|
123
|
+
}
|
|
124
|
+
pwOpts["endOfLine"] = s
|
|
125
|
+
}
|
|
126
|
+
out["format/print-width"] = ruleEntry(pwOpts)
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
128
|
+
// format/sort-imports — opt-in by `importOrder`.
|
|
129
|
+
if v, ok := raw["importOrder"]; ok {
|
|
130
|
+
siOpts := map[string]any{}
|
|
131
|
+
order, err := asStringSlice("format.importOrder", v)
|
|
132
|
+
if err != nil {
|
|
133
|
+
return nil, err
|
|
134
|
+
}
|
|
135
|
+
if len(order) == 0 {
|
|
136
|
+
return nil, fmt.Errorf("@ttsc/lint: format.importOrder must contain at least one entry; omit the field to keep format/sort-imports off")
|
|
137
|
+
}
|
|
138
|
+
siOpts["importOrder"] = order
|
|
139
|
+
if x, ok := raw["importOrderSeparation"]; ok {
|
|
140
|
+
b, err := asBool("format.importOrderSeparation", x)
|
|
141
|
+
if err != nil {
|
|
142
|
+
return nil, err
|
|
143
|
+
}
|
|
144
|
+
siOpts["importOrderSeparation"] = b
|
|
145
|
+
}
|
|
146
|
+
if x, ok := raw["importOrderSortSpecifiers"]; ok {
|
|
147
|
+
b, err := asBool("format.importOrderSortSpecifiers", x)
|
|
148
|
+
if err != nil {
|
|
149
|
+
return nil, err
|
|
150
|
+
}
|
|
151
|
+
siOpts["importOrderSortSpecifiers"] = b
|
|
152
|
+
}
|
|
153
|
+
if x, ok := raw["importOrderCaseInsensitive"]; ok {
|
|
154
|
+
b, err := asBool("format.importOrderCaseInsensitive", x)
|
|
155
|
+
if err != nil {
|
|
156
|
+
return nil, err
|
|
157
|
+
}
|
|
158
|
+
siOpts["importOrderCaseInsensitive"] = b
|
|
159
|
+
}
|
|
160
|
+
out["format/sort-imports"] = ruleEntry(siOpts)
|
|
161
|
+
}
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
163
|
+
// format/jsdoc — opt-in by `jsdoc` truthy (boolean or object).
|
|
164
|
+
if v, ok := raw["jsdoc"]; ok && v != nil {
|
|
165
|
+
jdOpts := map[string]any{}
|
|
166
|
+
enabled := false
|
|
167
|
+
switch j := v.(type) {
|
|
168
|
+
case bool:
|
|
169
|
+
enabled = j
|
|
170
|
+
case map[string]any:
|
|
171
|
+
enabled = true
|
|
172
|
+
for key, val := range j {
|
|
173
|
+
switch key {
|
|
174
|
+
case "tagSynonyms":
|
|
175
|
+
ts, ok := val.(map[string]any)
|
|
176
|
+
if !ok {
|
|
177
|
+
return nil, fmt.Errorf("@ttsc/lint: format.jsdoc.tagSynonyms must be an object, got %T", val)
|
|
178
|
+
}
|
|
179
|
+
// Element values must be strings; surface
|
|
180
|
+
// typos early instead of after a downstream
|
|
181
|
+
// JSON-decode failure.
|
|
182
|
+
for k, v := range ts {
|
|
183
|
+
if _, ok := v.(string); !ok {
|
|
184
|
+
return nil, fmt.Errorf("@ttsc/lint: format.jsdoc.tagSynonyms[%q] must be a string, got %T", k, v)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
jdOpts["tagSynonyms"] = ts
|
|
188
|
+
case "sortTags":
|
|
189
|
+
b, err := asBool("format.jsdoc.sortTags", val)
|
|
190
|
+
if err != nil {
|
|
191
|
+
return nil, err
|
|
192
|
+
}
|
|
193
|
+
jdOpts["sortTags"] = b
|
|
194
|
+
default:
|
|
195
|
+
return nil, fmt.Errorf("@ttsc/lint: format.jsdoc unknown key %q (allowed: tagSynonyms, sortTags)", key)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
default:
|
|
199
|
+
return nil, fmt.Errorf("@ttsc/lint: format.jsdoc must be a boolean or object, got %T", v)
|
|
200
|
+
}
|
|
201
|
+
if enabled {
|
|
202
|
+
out["format/jsdoc"] = ruleEntry(jdOpts)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
return out, nil
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
// formatBlockSeverity extracts the optional `severity` field from a format
|
|
210
|
+
// block. Defaults to SeverityOff so that format rules never produce check/build
|
|
211
|
+
// diagnostics unless the user explicitly opts in. SeverityOff still allows
|
|
212
|
+
// `ttsc format` to apply formatting; it only suppresses error/warning output.
|
|
209
213
|
func formatBlockSeverity(raw map[string]any) (Severity, error) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
214
|
+
value, ok := raw["severity"]
|
|
215
|
+
if !ok || value == nil {
|
|
216
|
+
return SeverityOff, nil
|
|
217
|
+
}
|
|
218
|
+
severity, err := parseSeverity(value)
|
|
219
|
+
if err != nil {
|
|
220
|
+
return SeverityOff, fmt.Errorf("@ttsc/lint: format.severity: %w", err)
|
|
221
|
+
}
|
|
222
|
+
return severity, nil
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
// mergeRuleMaps overlays `overrides` on `base` and returns the merged
|
|
@@ -225,91 +229,100 @@ func formatBlockSeverity(raw map[string]any) (Severity, error) {
|
|
|
225
229
|
// `format/*` rule fully replaces the corresponding entry expanded
|
|
226
230
|
// from the `format` block.
|
|
227
231
|
func mergeRuleMaps(base, overrides map[string]any) map[string]any {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
232
|
+
out := make(map[string]any, len(base)+len(overrides))
|
|
233
|
+
for k, v := range base {
|
|
234
|
+
out[k] = v
|
|
235
|
+
}
|
|
236
|
+
for k, v := range overrides {
|
|
237
|
+
out[k] = v
|
|
238
|
+
}
|
|
239
|
+
return out
|
|
236
240
|
}
|
|
237
241
|
|
|
242
|
+
// asBool coerces a raw config value to a bool, returning a typed error on
|
|
243
|
+
// failure. Used by expandFormatBlock to validate boolean format fields.
|
|
238
244
|
func asBool(field string, v any) (bool, error) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
245
|
+
if b, ok := v.(bool); ok {
|
|
246
|
+
return b, nil
|
|
247
|
+
}
|
|
248
|
+
return false, fmt.Errorf("@ttsc/lint: %s must be a boolean, got %T", field, v)
|
|
243
249
|
}
|
|
244
250
|
|
|
251
|
+
// asString coerces a raw config value to a string, returning a typed error on
|
|
252
|
+
// failure. Used by expandFormatBlock to validate string format fields.
|
|
245
253
|
func asString(field string, v any) (string, error) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
if s, ok := v.(string); ok {
|
|
255
|
+
return s, nil
|
|
256
|
+
}
|
|
257
|
+
return "", fmt.Errorf("@ttsc/lint: %s must be a string, got %T", field, v)
|
|
250
258
|
}
|
|
251
259
|
|
|
260
|
+
// asInt coerces a raw config value to an int. Accepts all integer-shaped Go
|
|
261
|
+
// numeric types plus float64 (the default JSON decode type) and json.Number,
|
|
262
|
+
// rejecting fractional float64 values since no format option takes a non-integer.
|
|
252
263
|
func asInt(field string, v any) (int, error) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
264
|
+
switch n := v.(type) {
|
|
265
|
+
case int:
|
|
266
|
+
return n, nil
|
|
267
|
+
case int32:
|
|
268
|
+
return int(n), nil
|
|
269
|
+
case int64:
|
|
270
|
+
return int(n), nil
|
|
271
|
+
case float64:
|
|
272
|
+
// JSON numbers decode as float64; coerce when integer-valued.
|
|
273
|
+
if float64(int(n)) == n {
|
|
274
|
+
return int(n), nil
|
|
275
|
+
}
|
|
276
|
+
case json.Number:
|
|
277
|
+
i, err := n.Int64()
|
|
278
|
+
if err == nil {
|
|
279
|
+
return int(i), nil
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return 0, fmt.Errorf("@ttsc/lint: %s must be an integer, got %T", field, v)
|
|
272
283
|
}
|
|
273
284
|
|
|
285
|
+
// asStringSlice coerces a raw config value to a []string, returning a typed
|
|
286
|
+
// error on failure. Used by expandFormatBlock to validate importOrder.
|
|
274
287
|
func asStringSlice(field string, v any) ([]string, error) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
+
arr, ok := v.([]any)
|
|
289
|
+
if !ok {
|
|
290
|
+
return nil, fmt.Errorf("@ttsc/lint: %s must be an array of strings, got %T", field, v)
|
|
291
|
+
}
|
|
292
|
+
out := make([]string, 0, len(arr))
|
|
293
|
+
for i, item := range arr {
|
|
294
|
+
s, ok := item.(string)
|
|
295
|
+
if !ok {
|
|
296
|
+
return nil, fmt.Errorf("@ttsc/lint: %s[%d] must be a string, got %T", field, i, item)
|
|
297
|
+
}
|
|
298
|
+
out = append(out, s)
|
|
299
|
+
}
|
|
300
|
+
return out, nil
|
|
288
301
|
}
|
|
289
302
|
|
|
290
303
|
// rejectUnknownFormatKeys surfaces typos in top-level format-block
|
|
291
304
|
// keys at the boundary rather than silently ignoring them. The
|
|
292
305
|
// key set mirrors `ITtscLintFormatConfig` exactly.
|
|
293
306
|
func rejectUnknownFormatKeys(raw map[string]any) error {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
307
|
+
allowed := map[string]struct{}{
|
|
308
|
+
"severity": {},
|
|
309
|
+
"semi": {},
|
|
310
|
+
"singleQuote": {},
|
|
311
|
+
"trailingComma": {},
|
|
312
|
+
"printWidth": {},
|
|
313
|
+
"tabWidth": {},
|
|
314
|
+
"useTabs": {},
|
|
315
|
+
"endOfLine": {},
|
|
316
|
+
"importOrder": {},
|
|
317
|
+
"importOrderSeparation": {},
|
|
318
|
+
"importOrderSortSpecifiers": {},
|
|
319
|
+
"importOrderCaseInsensitive": {},
|
|
320
|
+
"jsdoc": {},
|
|
321
|
+
}
|
|
322
|
+
for key := range raw {
|
|
323
|
+
if _, ok := allowed[key]; !ok {
|
|
324
|
+
return fmt.Errorf("@ttsc/lint: format unknown key %q; see ITtscLintFormatConfig for the allowed surface", key)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return nil
|
|
315
328
|
}
|