@ttsc/lint 0.12.3 → 0.13.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/lib/defaultFormat.d.ts +10 -11
- package/lib/defaultFormat.js +10 -11
- package/lib/defaultFormat.js.map +1 -1
- package/lib/index.js +233 -135
- 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/ITtscLintPluginConfig.d.ts +10 -77
- 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/lib/structures/TtscLintRuleOptions.d.ts +14 -0
- package/linthost/ast_helpers.go +80 -11
- package/linthost/compile.go +116 -112
- package/linthost/config.go +647 -687
- package/linthost/config_format.go +272 -247
- package/linthost/contrib_adapter.go +7 -0
- package/linthost/directives.go +116 -0
- package/linthost/dispatch.go +33 -33
- package/linthost/engine.go +156 -43
- package/linthost/fix.go +47 -27
- package/linthost/flags_gen.go +31 -0
- package/linthost/format.go +119 -3
- package/linthost/host.go +115 -5
- package/linthost/print_dispatch.go +128 -28
- package/linthost/print_doc.go +23 -0
- package/linthost/print_engine.go +168 -4
- package/linthost/print_nodes_array.go +17 -7
- package/linthost/print_nodes_call.go +138 -20
- package/linthost/print_nodes_function.go +353 -0
- package/linthost/print_nodes_imports.go +46 -29
- package/linthost/print_nodes_list.go +86 -5
- package/linthost/print_nodes_object.go +56 -11
- 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 +35 -3
- 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 +270 -15
- package/linthost/rules_format_quotes.go +3 -0
- package/linthost/rules_format_sort_imports.go +4 -0
- package/linthost/rules_gap.go +75 -3
- package/linthost/rules_imports.go +5 -7
- package/linthost/rules_logic.go +75 -5
- 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 +89 -22
- package/linthost/rules_promise.go +15 -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 +174 -9
- 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 +15 -2
- 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 +257 -168
- package/src/structures/ITtscLintConfig.ts +2 -2
- package/src/structures/ITtscLintFormatConfig.ts +53 -55
- package/src/structures/ITtscLintPluginConfig.ts +10 -83
- package/src/structures/ITtscLintPluginMeta.ts +9 -1
- package/src/structures/TtscLintRule.ts +10 -1
- package/src/structures/TtscLintRuleMap.ts +17 -18
- package/src/structures/TtscLintRuleOptions.ts +15 -0
- package/linthost/eslint_runtime.go +0 -320
|
@@ -3,10 +3,10 @@ import type { TtscLintSeverity } from "./TtscLintSeverity";
|
|
|
3
3
|
* Prettier-style flat configuration for the `format/*` rules.
|
|
4
4
|
*
|
|
5
5
|
* The `format` block is the recommended way to enable formatting in
|
|
6
|
-
* `@ttsc/lint`. Each key mirrors a Prettier option of the same name —
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* `@ttsc/lint`. Each key mirrors a Prettier option of the same name — users
|
|
7
|
+
* coming from a `.prettierrc` can copy their config almost verbatim. The block
|
|
8
|
+
* is opt-in by presence: a `lint.config.ts` with no `format` field keeps every
|
|
9
|
+
* format rule off, exactly as before.
|
|
10
10
|
*
|
|
11
11
|
* Once present, the block configures a curated set of format rules at
|
|
12
12
|
* Prettier-aligned defaults. `ttsc format` uses these rules to rewrite source.
|
|
@@ -18,37 +18,37 @@ import type { TtscLintSeverity } from "./TtscLintSeverity";
|
|
|
18
18
|
* import type { ITtscLintConfig } from "@ttsc/lint";
|
|
19
19
|
*
|
|
20
20
|
* export default {
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
21
|
+
* rules: { "no-var": "error" },
|
|
22
|
+
* format: {
|
|
23
|
+
* severity: "warning",
|
|
24
|
+
* printWidth: 100,
|
|
25
|
+
* singleQuote: true,
|
|
26
|
+
* importOrder: ["<THIRD_PARTY_MODULES>", "^[./]"],
|
|
27
|
+
* },
|
|
28
28
|
* } satisfies ITtscLintConfig;
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
30
|
+
* Deviations from Prettier:
|
|
31
|
+
* - `endOfLine` is restricted to `"lf"` and `"crlf"`. Prettier's
|
|
32
|
+
* `"cr"` and `"auto"` modes are intentionally unsupported — the
|
|
33
|
+
* printer does not auto-detect terminators.
|
|
34
|
+
* - Many Prettier knobs (`bracketSpacing`, `arrowParens`,
|
|
35
|
+
* `quoteProps`, JSX-specific switches) are not yet implemented.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
37
|
+
* Rule enablement matrix (when the `format` block is present):
|
|
38
38
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
39
|
+
* - `format/semi` — always on. `semi: false` flips it to `prefer:
|
|
40
|
+
* "never"`.
|
|
41
|
+
* - `format/quotes` — always on. `singleQuote: true` flips to
|
|
42
|
+
* `prefer: "single"`.
|
|
43
|
+
* - `format/trailing-comma` — always on. `trailingComma: "none"`
|
|
44
|
+
* disables the rule's edits without removing the surface.
|
|
45
|
+
* - `format/print-width` — always on, driven by `printWidth`,
|
|
46
|
+
* `tabWidth`, `useTabs`, `endOfLine`.
|
|
47
|
+
* - `format/sort-imports` — opt-in. Setting `importOrder` enables it.
|
|
48
|
+
* - `format/jsdoc` — opt-in. Setting `jsdoc` enables it.
|
|
49
49
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
50
|
+
* Format findings produced from this block are off by default. Set `severity`
|
|
51
|
+
* only when a project intentionally wants check-time format diagnostics.
|
|
52
52
|
*/
|
|
53
53
|
export interface ITtscLintFormatConfig {
|
|
54
54
|
/**
|
|
@@ -62,30 +62,30 @@ export interface ITtscLintFormatConfig {
|
|
|
62
62
|
*/
|
|
63
63
|
severity?: TtscLintSeverity;
|
|
64
64
|
/**
|
|
65
|
-
* Insert trailing semicolons on ASI-terminated statements. Mirrors
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* Insert trailing semicolons on ASI-terminated statements. Mirrors Prettier's
|
|
66
|
+
* `semi`. `false` flips the rule to require _no_ trailing semicolon (rare;
|
|
67
|
+
* matches prettier's `semi: false`).
|
|
68
68
|
*
|
|
69
69
|
* @default true
|
|
70
70
|
*/
|
|
71
71
|
semi?: boolean;
|
|
72
72
|
/**
|
|
73
|
-
* Prefer single-quoted strings. Mirrors Prettier's `singleQuote`.
|
|
74
|
-
*
|
|
73
|
+
* Prefer single-quoted strings. Mirrors Prettier's `singleQuote`. `false`
|
|
74
|
+
* means double quotes (Prettier's default).
|
|
75
75
|
*
|
|
76
76
|
* @default false
|
|
77
77
|
*/
|
|
78
78
|
singleQuote?: boolean;
|
|
79
79
|
/**
|
|
80
|
-
* Trailing-comma policy. Mirrors Prettier's `trailingComma`. The
|
|
81
|
-
*
|
|
80
|
+
* Trailing-comma policy. Mirrors Prettier's `trailingComma`. The `"none"`
|
|
81
|
+
* mode disables the rule's edits.
|
|
82
82
|
*
|
|
83
83
|
* @default "all"
|
|
84
84
|
*/
|
|
85
85
|
trailingComma?: "all" | "es5" | "none";
|
|
86
86
|
/**
|
|
87
|
-
* Maximum column width before broken-form layout is chosen.
|
|
88
|
-
*
|
|
87
|
+
* Maximum column width before broken-form layout is chosen. Mirrors
|
|
88
|
+
* Prettier's `printWidth`.
|
|
89
89
|
*
|
|
90
90
|
* @default 80
|
|
91
91
|
*/
|
|
@@ -103,19 +103,18 @@ export interface ITtscLintFormatConfig {
|
|
|
103
103
|
*/
|
|
104
104
|
useTabs?: boolean;
|
|
105
105
|
/**
|
|
106
|
-
* Line terminator the printer emits on reflow. `@ttsc/lint`
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* auto-detect line endings.
|
|
106
|
+
* Line terminator the printer emits on reflow. `@ttsc/lint` supports `"lf"`
|
|
107
|
+
* and `"crlf"`. Prettier's `"cr"` and `"auto"` are intentionally unsupported
|
|
108
|
+
* because the printer does not auto-detect line endings.
|
|
110
109
|
*
|
|
111
110
|
* @default "lf"
|
|
112
111
|
*/
|
|
113
112
|
endOfLine?: "lf" | "crlf";
|
|
114
113
|
/**
|
|
115
|
-
* Group order for `format/sort-imports`. Setting this enables the
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
114
|
+
* Group order for `format/sort-imports`. Setting this enables the rule;
|
|
115
|
+
* mirrors `@trivago/prettier-plugin-sort-imports`' `importOrder`. The
|
|
116
|
+
* `<THIRD_PARTY_MODULES>` literal is the catch-all placeholder for specifiers
|
|
117
|
+
* that match no other group.
|
|
119
118
|
*/
|
|
120
119
|
importOrder?: readonly ("<THIRD_PARTY_MODULES>" | (string & {}))[];
|
|
121
120
|
/**
|
|
@@ -125,8 +124,7 @@ export interface ITtscLintFormatConfig {
|
|
|
125
124
|
*/
|
|
126
125
|
importOrderSeparation?: boolean;
|
|
127
126
|
/**
|
|
128
|
-
* Sort named import specifiers alphabetically within each
|
|
129
|
-
* declaration.
|
|
127
|
+
* Sort named import specifiers alphabetically within each declaration.
|
|
130
128
|
*
|
|
131
129
|
* @default true
|
|
132
130
|
*/
|
|
@@ -138,13 +136,13 @@ export interface ITtscLintFormatConfig {
|
|
|
138
136
|
*/
|
|
139
137
|
importOrderCaseInsensitive?: boolean;
|
|
140
138
|
/**
|
|
141
|
-
* Enable `format/jsdoc`. Pass `true` to turn it on with built-in
|
|
142
|
-
*
|
|
139
|
+
* Enable `format/jsdoc`. Pass `true` to turn it on with built-in defaults, or
|
|
140
|
+
* an object to customize:
|
|
143
141
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
142
|
+
* - `tagSynonyms` — extra `from → to` rewrites layered on the built-in synonym
|
|
143
|
+
* table.
|
|
144
|
+
* - `sortTags` — sort JSDoc tags into canonical order (reserved; today's MVP
|
|
145
|
+
* only rewrites tag names).
|
|
148
146
|
*
|
|
149
147
|
* @default false (off)
|
|
150
148
|
*/
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ITtscLintFormatConfig } from "./ITtscLintFormatConfig";
|
|
2
|
-
import type { TtscLintRuleMap } from "./TtscLintRuleMap";
|
|
3
1
|
/** `compilerOptions.plugins[]` entry shape consumed by `@ttsc/lint`. */
|
|
4
2
|
export interface ITtscLintPluginConfig {
|
|
5
3
|
/** Set to `false` to keep the entry while disabling this plugin. */
|
|
@@ -7,89 +5,24 @@ export interface ITtscLintPluginConfig {
|
|
|
7
5
|
/** Plugin module specifier. */
|
|
8
6
|
transform?: string;
|
|
9
7
|
/**
|
|
10
|
-
*
|
|
8
|
+
* Path to the lint config file, overriding auto-discovery.
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* contributor rule namespaces in the same entry.
|
|
10
|
+
* Relative paths are resolved from the tsconfig directory; absolute paths are
|
|
11
|
+
* used as-is. Accepts the usual `lint.config.*` / `ttsc-lint.config.*`
|
|
12
|
+
* extensions (`.ts`, `.cts`, `.mts`, `.js`, `.cjs`, `.mjs`, `.json`).
|
|
16
13
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* "transform": "@ttsc/lint",
|
|
20
|
-
* "rules": { "no-var": "error", "prefer-const": "warning" }
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
rules?: TtscLintRuleMap;
|
|
25
|
-
/**
|
|
26
|
-
* Path to a standalone lint config file whose rules should be applied to this
|
|
27
|
-
* project. Relative paths are resolved from the tsconfig directory. Accepts
|
|
28
|
-
* the usual `lint.config.*` / `ttsc-lint.config.*` / `eslint.config.*`
|
|
29
|
-
* extensions.
|
|
30
|
-
*
|
|
31
|
-
* Mirrors the `extends` field of an ESLint flat-config entry — "inherit this
|
|
32
|
-
* file's configuration".
|
|
33
|
-
*
|
|
34
|
-
* ```jsonc
|
|
35
|
-
* {
|
|
36
|
-
* "transform": "@ttsc/lint",
|
|
37
|
-
* "extends": "./lint.config.ts"
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*
|
|
41
|
-
* `rules` and `extends` are mutually exclusive on a single plugin entry; the
|
|
42
|
-
* sidecar surfaces a loud error when both are set.
|
|
43
|
-
*/
|
|
44
|
-
extends?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Contributor lint plugins to compile into the `@ttsc/lint` binary.
|
|
47
|
-
*
|
|
48
|
-
* Each entry maps a namespace (rule-name prefix) to an npm specifier or
|
|
49
|
-
* relative path. The factory resolves the package, reads its exported
|
|
50
|
-
* `ITtscLintPlugin` descriptor, and forwards the Go source directory to
|
|
51
|
-
* ttsc's plugin builder via the `contributors` field.
|
|
14
|
+
* When omitted, `@ttsc/lint` discovers a `lint.config.*` /
|
|
15
|
+
* `ttsc-lint.config.*` file by walking upward from the tsconfig directory.
|
|
52
16
|
*
|
|
53
17
|
* ```jsonc
|
|
54
18
|
* {
|
|
55
19
|
* "transform": "@ttsc/lint",
|
|
56
|
-
* "
|
|
57
|
-
* "rules": { "demo/no-todo-comment": "error" }
|
|
20
|
+
* "configFile": "./lint.config.ts"
|
|
58
21
|
* }
|
|
59
22
|
* ```
|
|
60
|
-
*/
|
|
61
|
-
plugins?: Record<string, string>;
|
|
62
|
-
/**
|
|
63
|
-
* Prettier-style flat configuration for the `format/*` rules. Sibling of
|
|
64
|
-
* `rules`. See {@link ITtscLintFormatConfig} for the full surface.
|
|
65
|
-
*
|
|
66
|
-
* ```jsonc
|
|
67
|
-
* {
|
|
68
|
-
* "transform": "@ttsc/lint",
|
|
69
|
-
* "format": { "printWidth": 100, "singleQuote": true }
|
|
70
|
-
* }
|
|
71
|
-
* ```
|
|
72
|
-
*
|
|
73
|
-
* Combines with `rules` (per-rule overrides win on collision). Cannot be
|
|
74
|
-
* combined with `extends` on the same plugin entry — put format options
|
|
75
|
-
* inside the extends-target lint.config.ts instead.
|
|
76
|
-
*/
|
|
77
|
-
format?: ITtscLintFormatConfig;
|
|
78
|
-
/**
|
|
79
|
-
* Inline rule map or path to a standalone lint config file.
|
|
80
|
-
*
|
|
81
|
-
* @deprecated Use `rules` for inline severity maps or `extends` for a config
|
|
82
|
-
* file path. The sidecar maps a legacy `config` entry onto the appropriate
|
|
83
|
-
* new field and emits a one-time stderr deprecation notice. Removed in a
|
|
84
|
-
* future minor.
|
|
85
23
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* accepts those two shapes; widening the TS type to the full config object
|
|
89
|
-
* would silently let unsupported nested shapes pass type-checking and fail
|
|
90
|
-
* at runtime.
|
|
24
|
+
* Every rule, format, and plugin setting lives in the config file — the
|
|
25
|
+
* tsconfig plugin entry carries nothing but this pointer.
|
|
91
26
|
*/
|
|
92
|
-
|
|
93
|
-
/** Extra plugin-owned fields are passed through unchanged. */
|
|
94
|
-
[key: string]: unknown;
|
|
27
|
+
configFile?: string;
|
|
95
28
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-level metadata exposed on `ITtscLintPlugin.meta`.
|
|
3
|
+
*
|
|
4
|
+
* All fields are optional. When `namespace` is absent, `@ttsc/lint` falls back
|
|
5
|
+
* to the key used in the tsconfig `plugins` map (or `lint.config.*` `plugins`
|
|
6
|
+
* object) as the rule-name prefix. `name` and `version` are purely
|
|
7
|
+
* informational — they appear in diagnostic messages and are not validated at
|
|
8
|
+
* build time.
|
|
9
|
+
*/
|
|
2
10
|
export interface ITtscLintPluginMeta {
|
|
3
11
|
/** Plugin package name as published on npm. */
|
|
4
12
|
name?: string;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Union of every built-in lint rule name understood by the `@ttsc/lint` native
|
|
3
|
+
* sidecar.
|
|
3
4
|
*
|
|
4
5
|
* These names intentionally mirror familiar ESLint / TypeScript-ESLint rule
|
|
5
6
|
* names so a `compilerOptions.plugins[]` entry can configure native linting
|
|
6
7
|
* without introducing a separate lint config file.
|
|
8
|
+
*
|
|
9
|
+
* The `format/*` members at the bottom of the union are applied by `ttsc
|
|
10
|
+
* format`; their severity also controls whether `ttsc check` surfaces
|
|
11
|
+
* unformatted code as a diagnostic.
|
|
12
|
+
*
|
|
13
|
+
* This type is used as the key constraint in `TtscLintRuleMap` for rules that
|
|
14
|
+
* carry no per-rule options. Rules with typed option objects are additionally
|
|
15
|
+
* listed in `ITtscLintRuleOptionsMap`.
|
|
7
16
|
*/
|
|
8
17
|
export type TtscLintRule = "adjacent-overload-signatures" | "array-type" | "await-thenable" | "ban-ts-comment" | "ban-tslint-comment" | "consistent-indexed-object-style" | "consistent-type-assertions" | "consistent-type-definitions" | "consistent-type-imports" | "default-param-last" | "dot-notation" | "eqeqeq" | "for-direction" | "no-alert" | "no-array-constructor" | "no-array-delete" | "no-async-promise-executor" | "no-bitwise" | "no-caller" | "no-case-declarations" | "no-class-assign" | "no-compare-neg-zero" | "no-cond-assign" | "no-confusing-non-null-assertion" | "no-console" | "no-constant-condition" | "no-continue" | "no-control-regex" | "no-debugger" | "no-delete-var" | "no-dupe-args" | "no-dupe-else-if" | "no-dupe-keys" | "no-duplicate-case" | "no-duplicate-enum-values" | "no-dynamic-delete" | "no-empty" | "no-empty-character-class" | "no-empty-function" | "no-empty-interface" | "no-empty-object-type" | "no-empty-pattern" | "no-empty-static-block" | "no-eq-null" | "no-eval" | "no-ex-assign" | "no-explicit-any" | "no-extra-bind" | "no-extra-boolean-cast" | "no-extra-non-null-assertion" | "no-fallthrough" | "no-func-assign" | "no-import-type-side-effects" | "no-inferrable-types" | "no-inner-declarations" | "no-irregular-whitespace" | "no-iterator" | "no-labels" | "no-lone-blocks" | "no-lonely-if" | "no-loss-of-precision" | "no-misleading-character-class" | "no-misused-new" | "no-mixed-enums" | "no-multi-assign" | "no-multi-str" | "no-namespace" | "no-negated-condition" | "no-nested-ternary" | "no-new" | "no-new-func" | "no-new-wrappers" | "no-non-null-asserted-nullish-coalescing" | "no-non-null-asserted-optional-chain" | "no-non-null-assertion" | "no-obj-calls" | "no-object-constructor" | "no-octal" | "no-octal-escape" | "no-plusplus" | "no-promise-executor-return" | "no-proto" | "no-prototype-builtins" | "no-regex-spaces" | "no-require-imports" | "no-return-assign" | "no-script-url" | "no-self-assign" | "no-self-compare" | "no-sequences" | "no-setter-return" | "no-shadow-restricted-names" | "no-sparse-arrays" | "no-template-curly-in-string" | "no-this-alias" | "no-throw-literal" | "no-undef-init" | "no-undefined" | "no-unnecessary-type-constraint" | "no-unneeded-ternary" | "no-unsafe-declaration-merging" | "no-unsafe-finally" | "no-unsafe-function-type" | "no-unsafe-negation" | "no-unused-expressions" | "no-unused-labels" | "no-useless-call" | "no-useless-catch" | "no-useless-computed-key" | "no-useless-concat" | "no-useless-constructor" | "no-useless-escape" | "no-useless-rename" | "no-var" | "no-with" | "no-wrapper-object-types" | "object-shorthand" | "operator-assignment" | "prefer-as-const" | "prefer-const" | "prefer-enum-initializers" | "prefer-exponentiation-operator" | "prefer-for-of" | "prefer-function-type" | "prefer-literal-enum-member" | "prefer-namespace-keyword" | "prefer-spread" | "prefer-template" | "radix" | "require-yield" | "triple-slash-reference" | "use-isnan" | "valid-typeof" | "vars-on-top" | "yoda" | "format/semi" | "format/quotes" | "format/trailing-comma" | "format/sort-imports" | "format/jsdoc" | "format/print-width";
|
|
@@ -10,8 +10,8 @@ import type { TtscLintSeverity } from "./TtscLintSeverity";
|
|
|
10
10
|
* `[severity, options]`, with the options type picked per rule key.
|
|
11
11
|
* - Every other built-in rule accepts `severity` or `[severity]`.
|
|
12
12
|
* - Namespaced contributor plugin rules accept `severity`, `[severity]`, or
|
|
13
|
-
* `[severity, unknownOptions]` because the host type surface no longer
|
|
14
|
-
*
|
|
13
|
+
* `[severity, unknownOptions]` because the host type surface no longer knows
|
|
14
|
+
* contributor rule schemas.
|
|
15
15
|
*
|
|
16
16
|
* Splitting the two halves (instead of folding them into one mapped type with a
|
|
17
17
|
* conditional value) keeps TypeScript's contextual typing intact inside the
|
|
@@ -89,6 +89,20 @@ export interface ITtscLintPrintWidthRuleOptions {
|
|
|
89
89
|
* @default "lf"
|
|
90
90
|
*/
|
|
91
91
|
endOfLine?: "lf" | "crlf";
|
|
92
|
+
/**
|
|
93
|
+
* Trailing-comma policy the reflow honors when it breaks a list across
|
|
94
|
+
* lines. Mirrors prettier's `trailingComma` and must match the
|
|
95
|
+
* `format/trailing-comma` rule's `mode`; otherwise the two rules
|
|
96
|
+
* disagree on every cascade pass and oscillate against each other.
|
|
97
|
+
*
|
|
98
|
+
* When a `format` block is configured, `format.trailingComma` is mirrored
|
|
99
|
+
* into this option automatically. Set it directly only when overriding
|
|
100
|
+
* the print-width rule via a `rules` tuple — see the conflict-resolution
|
|
101
|
+
* notes in the README.
|
|
102
|
+
*
|
|
103
|
+
* @default "all"
|
|
104
|
+
*/
|
|
105
|
+
trailingComma?: "all" | "es5" | "none";
|
|
92
106
|
}
|
|
93
107
|
/** `format/jsdoc` rule options. */
|
|
94
108
|
export interface ITtscLintJsdocRuleOptions {
|
package/linthost/ast_helpers.go
CHANGED
|
@@ -96,6 +96,10 @@ func findKeyword(file *shimast.SourceFile, pos, end int, keyword string) int {
|
|
|
96
96
|
return -1
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// tokenRange returns the half-open byte range [pos, end) of `node` with
|
|
100
|
+
// leading trivia stripped, mirroring what ReportFix would anchor to.
|
|
101
|
+
// Returns (-1, -1) when either argument is nil or the computed range is
|
|
102
|
+
// out of bounds.
|
|
99
103
|
func tokenRange(file *shimast.SourceFile, node *shimast.Node) (int, int) {
|
|
100
104
|
if file == nil || node == nil {
|
|
101
105
|
return -1, -1
|
|
@@ -109,6 +113,10 @@ func tokenRange(file *shimast.SourceFile, node *shimast.Node) (int, int) {
|
|
|
109
113
|
return pos, end
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
// isIdentifierPart reports whether `ch` can appear inside a JavaScript
|
|
117
|
+
// identifier — used as a word-boundary guard by keyword search helpers.
|
|
118
|
+
// Handles only ASCII; multibyte Unicode identifier parts are treated as
|
|
119
|
+
// non-identifier (conservative; callers only need ASCII keyword tokens).
|
|
112
120
|
func isIdentifierPart(ch byte) bool {
|
|
113
121
|
return (ch >= 'a' && ch <= 'z') ||
|
|
114
122
|
(ch >= 'A' && ch <= 'Z') ||
|
|
@@ -272,28 +280,89 @@ func walkDescendants(node *shimast.Node, visit func(*shimast.Node)) {
|
|
|
272
280
|
})
|
|
273
281
|
}
|
|
274
282
|
|
|
275
|
-
|
|
283
|
+
// assignmentTargetNames collects the identifier names written by an
|
|
284
|
+
// assignment's left-hand side. A bare Identifier yields one name. A
|
|
285
|
+
// destructuring-assignment target — parsed as an ArrayLiteralExpression
|
|
286
|
+
// (`[a, b] = …`) or ObjectLiteralExpression (`({a} = …)`) rather than a
|
|
287
|
+
// binding pattern — is walked so every nested write position is counted:
|
|
288
|
+
// array elements, object property values, shorthand properties, defaults
|
|
289
|
+
// (`[a = 1]`, `{a = 1}`), nested patterns, and rest elements.
|
|
290
|
+
//
|
|
291
|
+
// Property names in `{key: target}` are read positions, not writes, so
|
|
292
|
+
// only the property value contributes; member-access targets (`obj.x`)
|
|
293
|
+
// declare no local binding and are skipped. Returns nil for other shapes.
|
|
294
|
+
func assignmentTargetNames(node *shimast.Node) []string {
|
|
276
295
|
if node == nil {
|
|
277
296
|
return nil
|
|
278
297
|
}
|
|
279
298
|
if name := identifierText(node); name != "" {
|
|
280
299
|
return []string{name}
|
|
281
300
|
}
|
|
282
|
-
if node.Kind != shimast.KindObjectBindingPattern && node.Kind != shimast.KindArrayBindingPattern {
|
|
283
|
-
return nil
|
|
284
|
-
}
|
|
285
301
|
var names []string
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
302
|
+
collectAssignmentTargetNames(node, &names)
|
|
303
|
+
return names
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// collectAssignmentTargetNames appends to `names` every identifier in a
|
|
307
|
+
// destructuring-assignment target. It descends only through write-target
|
|
308
|
+
// positions so reads (object property keys, computed-member expressions)
|
|
309
|
+
// never count as reassignments.
|
|
310
|
+
func collectAssignmentTargetNames(node *shimast.Node, names *[]string) {
|
|
311
|
+
if node == nil {
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
switch node.Kind {
|
|
315
|
+
case shimast.KindIdentifier:
|
|
316
|
+
if name := identifierText(node); name != "" {
|
|
317
|
+
*names = append(*names, name)
|
|
289
318
|
}
|
|
290
|
-
|
|
291
|
-
|
|
319
|
+
case shimast.KindParenthesizedExpression:
|
|
320
|
+
collectAssignmentTargetNames(stripParens(node), names)
|
|
321
|
+
case shimast.KindArrayLiteralExpression:
|
|
322
|
+
if arr := node.AsArrayLiteralExpression(); arr != nil && arr.Elements != nil {
|
|
323
|
+
for _, el := range arr.Elements.Nodes {
|
|
324
|
+
collectAssignmentTargetNames(el, names)
|
|
325
|
+
}
|
|
292
326
|
}
|
|
293
|
-
|
|
294
|
-
|
|
327
|
+
case shimast.KindObjectLiteralExpression:
|
|
328
|
+
if obj := node.AsObjectLiteralExpression(); obj != nil && obj.Properties != nil {
|
|
329
|
+
for _, prop := range obj.Properties.Nodes {
|
|
330
|
+
collectAssignmentTargetNames(prop, names)
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
case shimast.KindSpreadElement:
|
|
334
|
+
if spread := node.AsSpreadElement(); spread != nil {
|
|
335
|
+
collectAssignmentTargetNames(spread.Expression, names)
|
|
336
|
+
}
|
|
337
|
+
case shimast.KindSpreadAssignment:
|
|
338
|
+
if spread := node.AsSpreadAssignment(); spread != nil {
|
|
339
|
+
collectAssignmentTargetNames(spread.Expression, names)
|
|
340
|
+
}
|
|
341
|
+
case shimast.KindShorthandPropertyAssignment:
|
|
342
|
+
// `{a}` and `{a = 1}` — the property name is the write target; any
|
|
343
|
+
// ObjectAssignmentInitializer is a default value, not a target.
|
|
344
|
+
if short := node.AsShorthandPropertyAssignment(); short != nil {
|
|
345
|
+
collectAssignmentTargetNames(short.Name(), names)
|
|
346
|
+
}
|
|
347
|
+
case shimast.KindPropertyAssignment:
|
|
348
|
+
// `{key: target}` — only the value (initializer) is written to.
|
|
349
|
+
if assignment := node.AsPropertyAssignment(); assignment != nil {
|
|
350
|
+
collectAssignmentTargetNames(assignment.Initializer, names)
|
|
351
|
+
}
|
|
352
|
+
case shimast.KindBinaryExpression:
|
|
353
|
+
// A default inside a pattern (`[a = 1]`, `{key: a = 1}`) parses as an
|
|
354
|
+
// `=` BinaryExpression; only its left side is the write target.
|
|
355
|
+
if expr := node.AsBinaryExpression(); expr != nil &&
|
|
356
|
+
expr.OperatorToken != nil && expr.OperatorToken.Kind == shimast.KindEqualsToken {
|
|
357
|
+
collectAssignmentTargetNames(expr.Left, names)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
295
360
|
}
|
|
296
361
|
|
|
362
|
+
// isLiteralLike reports whether `node` (after stripping parentheses) is a
|
|
363
|
+
// compile-time constant expression: a bare literal or a unary `+`/`-`
|
|
364
|
+
// applied to a numeric or bigint literal. Used by rules that flag
|
|
365
|
+
// constant-valued operands (e.g. `no-constant-condition`).
|
|
297
366
|
func isLiteralLike(node *shimast.Node) bool {
|
|
298
367
|
node = stripParens(node)
|
|
299
368
|
if node == nil {
|