Skip to content

Commit d2122c0

Browse files
committed
refactor(editor): flatten flags options
1 parent 1611b4f commit d2122c0

File tree

6 files changed

+126
-52
lines changed

6 files changed

+126
-52
lines changed

editors/vscode/README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,22 @@ Following configuration are supported via `settings.json` and can be changed for
6464
| `oxc.tsConfigPath` | `null` | `null` \| `<string>` | Path to TypeScript configuration. If your `tsconfig.json` is not at the root, alias paths will not be resolve correctly for the `import` plugin. |
6565
| `oxc.unusedDisableDirectives` | `allow` | `allow` \| `warn` \| `deny` | Define how directive comments like `// oxlint-disable-line` should be reported, when no errors would have been reported on that line anyway. |
6666
| `oxc.typeAware` | `false` | `false` \| `true` | Enable type aware linting. |
67-
| `oxc.flags` | - | `Record<string, string>` | Custom flags passed to the language server. |
67+
| `oxc.disableNestedConfig` | `false` | `false` \| `true` | Disable searching for nested configuration files. |
68+
| `oxc.fixKind` | `safe_fix` | [FixKind](#fixkind) | Specify the kind of fixes to suggest/apply. |
6869
| `oxc.fmt.experimental` | `false` | `false` \| `true` | Enable experimental formatting support. This feature is experimental and might not work as expected. |
6970
| `oxc.fmt.configPath` | `null` | `<string>` \| `null` | Path to an oxfmt configuration file. When `null`, the server will use `.oxfmtrc.json` at the workspace root. |
71+
| `oxc.flags` | - | `Record<string, string>` | (deprecated) Custom flags passed to the language |
7072

71-
#### Flags
73+
#### FixKind
74+
75+
- `"safe_fix"` (default)
76+
- `"safe_fix_or_suggestion"`
77+
- `"dangerous_fix"`
78+
- `"dangerous_fix_or_suggestion"`
79+
- `"none"`
80+
- `"all"`
81+
82+
#### Flags (deprecated)
7283

7384
- `key: disable_nested_config`: Disabled nested configuration and searches only for `configPath`
7485
- `key: fix_kind`: default: `"safe_fix"`, possible values `"safe_fix" | "safe_fix_or_suggestion" | "dangerous_fix" | "dangerous_fix_or_suggestion" | "none" | "all"`

editors/vscode/client/WorkspaceConfig.ts

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ export type Trigger = 'onSave' | 'onType';
77

88
type UnusedDisableDirectives = 'allow' | 'warn' | 'deny';
99

10+
export enum FixKind {
11+
SafeFix = 'safe_fix',
12+
SafeFixOrSuggestion = 'safe_fix_or_suggestion',
13+
DangerousFix = 'dangerous_fix',
14+
DangerousFixOrSuggestion = 'dangerous_fix_or_suggestion',
15+
None = 'none',
16+
All = 'all',
17+
}
18+
1019
/**
1120
* See `"contributes.configuration"` in `package.json`
1221
*/
@@ -54,6 +63,20 @@ export interface WorkspaceConfigInterface {
5463
*/
5564
typeAware: boolean;
5665

66+
/**
67+
* Disable nested config files detection
68+
* `oxc.disableNestedConfig`
69+
* @default false
70+
*/
71+
disableNestedConfig: boolean;
72+
73+
/**
74+
* Fix kind to use when applying fixes
75+
* `oxc.fixKind`
76+
* @default 'safe_fix
77+
*/
78+
fixKind: FixKind;
79+
5780
/**
5881
* Additional flags to pass to the LSP binary
5982
* `oxc.flags`
@@ -83,7 +106,8 @@ export class WorkspaceConfig {
83106
private _runTrigger: Trigger = 'onType';
84107
private _unusedDisableDirectives: UnusedDisableDirectives = 'allow';
85108
private _typeAware: boolean = false;
86-
private _flags: Record<string, string> = {};
109+
private _disableNestedConfig: boolean = false;
110+
private _fixKind: FixKind = FixKind.SafeFix;
87111
private _formattingExperimental: boolean = false;
88112
private _formattingConfigPath: string | null = null;
89113

@@ -97,16 +121,16 @@ export class WorkspaceConfig {
97121

98122
public refresh(): void {
99123
const flags = this.configuration.get<Record<string, string>>('flags') ?? {};
100-
const useNestedConfigs = !('disable_nested_config' in flags);
101124

102125
this._runTrigger = this.configuration.get<Trigger>('lint.run') || 'onType';
103-
this._configPath =
104-
this.configuration.get<string | null>('configPath') || (useNestedConfigs ? null : oxlintConfigFileName);
126+
this._configPath = this.configuration.get<string | null>('configPath') ?? null;
105127
this._tsConfigPath = this.configuration.get<string | null>('tsConfigPath') ?? null;
106128
this._unusedDisableDirectives =
107129
this.configuration.get<UnusedDisableDirectives>('unusedDisableDirectives') ?? 'allow';
108130
this._typeAware = this.configuration.get<boolean>('typeAware') ?? false;
109-
this._flags = flags;
131+
this._disableNestedConfig =
132+
this.configuration.get<boolean>('disableNestedConfig') ?? flags.disable_nested_config === 'true';
133+
this._fixKind = this.configuration.get<FixKind>('fixKind') ?? (flags.fix_kind as FixKind) ?? FixKind.SafeFix;
110134
this._formattingExperimental = this.configuration.get<boolean>('fmt.experimental') ?? false;
111135
this._formattingConfigPath = this.configuration.get<string | null>('fmt.configPath') ?? null;
112136
}
@@ -127,7 +151,10 @@ export class WorkspaceConfig {
127151
if (event.affectsConfiguration(`${ConfigService.namespace}.typeAware`, this.workspace)) {
128152
return true;
129153
}
130-
if (event.affectsConfiguration(`${ConfigService.namespace}.flags`, this.workspace)) {
154+
if (event.affectsConfiguration(`${ConfigService.namespace}.disableNestedConfig`, this.workspace)) {
155+
return true;
156+
}
157+
if (event.affectsConfiguration(`${ConfigService.namespace}.fixKind`, this.workspace)) {
131158
return true;
132159
}
133160
if (event.affectsConfiguration(`${ConfigService.namespace}.fmt.experimental`, this.workspace)) {
@@ -136,6 +163,10 @@ export class WorkspaceConfig {
136163
if (event.affectsConfiguration(`${ConfigService.namespace}.fmt.configPath`, this.workspace)) {
137164
return true;
138165
}
166+
// deprecated settings in flags
167+
if (event.affectsConfiguration(`${ConfigService.namespace}.flags`, this.workspace)) {
168+
return true;
169+
}
139170
return false;
140171
}
141172

@@ -188,13 +219,22 @@ export class WorkspaceConfig {
188219
return this.configuration.update('typeAware', value, ConfigurationTarget.WorkspaceFolder);
189220
}
190221

191-
get flags(): Record<string, string> {
192-
return this._flags;
222+
get disableNestedConfig(): boolean {
223+
return this._disableNestedConfig;
224+
}
225+
226+
updateDisableNestedConfig(value: boolean): PromiseLike<void> {
227+
this._disableNestedConfig = value;
228+
return this.configuration.update('disableNestedConfig', value, ConfigurationTarget.WorkspaceFolder);
229+
}
230+
231+
get fixKind(): FixKind {
232+
return this._fixKind;
193233
}
194234

195-
updateFlags(value: Record<string, string>): PromiseLike<void> {
196-
this._flags = value;
197-
return this.configuration.update('flags', value, ConfigurationTarget.WorkspaceFolder);
235+
updateFixKind(value: FixKind): PromiseLike<void> {
236+
this._fixKind = value;
237+
return this.configuration.update('fixKind', value, ConfigurationTarget.WorkspaceFolder);
198238
}
199239

200240
get formattingExperimental(): boolean {
@@ -222,9 +262,15 @@ export class WorkspaceConfig {
222262
tsConfigPath: this.tsConfigPath ?? null,
223263
unusedDisableDirectives: this.unusedDisableDirectives,
224264
typeAware: this.typeAware,
225-
flags: this.flags,
265+
disableNestedConfig: this.disableNestedConfig,
266+
fixKind: this.fixKind,
226267
['fmt.experimental']: this.formattingExperimental,
227268
['fmt.configPath']: this.formattingConfigPath ?? null,
269+
// deprecated, kept for backward compatibility
270+
flags: {
271+
disable_nested_config: this.disableNestedConfig ? 'true' : 'false',
272+
...(this.fixKind ? { fix_kind: this.fixKind } : {}),
273+
},
228274
};
229275
}
230276
}

editors/vscode/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,39 @@
147147
"default": false,
148148
"description": "Enable type-aware linting."
149149
},
150+
"oxc.disableNestedConfig": {
151+
"type": "boolean",
152+
"scope": "resource",
153+
"default": false,
154+
"description": "Disable searching for nested configuration files. When set to true, only the configuration file specified in `oxc.configPath` (if any) will be used."
155+
},
156+
"oxc.fixKind": {
157+
"type": "string",
158+
"scope": "resource",
159+
"enum": [
160+
"safe_fix",
161+
"safe_fix_or_suggestion",
162+
"dangerous_fix",
163+
"dangerous_fix_or_suggestion",
164+
"none",
165+
"all"
166+
],
167+
"enumDescriptions": [
168+
"Only safe fixes will be applied",
169+
"Safe fixes or suggestions will be applied",
170+
"Safe and dangerous fixes will be applied",
171+
"Safe and dangerous fixes or suggestions will be applied",
172+
"No fixes will be applied",
173+
"All fixes and suggestions will be applied"
174+
],
175+
"default": "safe_fix",
176+
"description": "Specify the kind of fixes to suggest/apply."
177+
},
150178
"oxc.flags": {
151179
"type": "object",
152180
"scope": "resource",
153181
"default": {},
182+
"deprecationMessage": "deprecated since 1.25.0, use `oxc.fixKind` or `oxc.disableNestedConfig` instead.",
154183
"description": "Specific Oxlint flags to pass to the language server."
155184
},
156185
"oxc.fmt.experimental": {

editors/vscode/tests/WorkspaceConfig.spec.ts

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
import { deepStrictEqual, strictEqual } from 'assert';
1+
import { strictEqual } from 'assert';
22
import { ConfigurationTarget, workspace } from 'vscode';
3-
import { WorkspaceConfig } from '../client/WorkspaceConfig.js';
3+
import { FixKind, WorkspaceConfig } from '../client/WorkspaceConfig.js';
44
import { WORKSPACE_FOLDER } from './test-helpers.js';
55

6-
const keys = ['lint.run', 'configPath', 'tsConfigPath', 'flags', 'unusedDisableDirectives', 'typeAware', 'fmt.experimental', 'fmt.configPath'];
6+
const keys = [
7+
'lint.run',
8+
'configPath',
9+
'tsConfigPath',
10+
'unusedDisableDirectives',
11+
'typeAware',
12+
'disableNestedConfig',
13+
'fixKind',
14+
'fmt.experimental',
15+
'fmt.configPath',
16+
// deprecated
17+
'flags'
18+
];
719

820
suite('WorkspaceConfig', () => {
921
setup(async () => {
@@ -34,33 +46,12 @@ suite('WorkspaceConfig', () => {
3446
strictEqual(config.tsConfigPath, null);
3547
strictEqual(config.unusedDisableDirectives, 'allow');
3648
strictEqual(config.typeAware, false);
37-
deepStrictEqual(config.flags, {});
49+
strictEqual(config.disableNestedConfig, false);
50+
strictEqual(config.fixKind, "safe_fix");
3851
strictEqual(config.formattingExperimental, false);
3952
strictEqual(config.formattingConfigPath, null);
4053
});
4154

42-
test('configPath defaults to null when using nested configs and configPath is empty', async () => {
43-
const wsConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
44-
await wsConfig.update('configPath', '', ConfigurationTarget.WorkspaceFolder);
45-
await wsConfig.update('flags', {}, ConfigurationTarget.WorkspaceFolder);
46-
47-
const config = new WorkspaceConfig(WORKSPACE_FOLDER);
48-
49-
deepStrictEqual(config.flags, {});
50-
strictEqual(config.configPath, null);
51-
});
52-
53-
test('configPath defaults to .oxlintrc.json when not using nested configs and configPath is empty', async () => {
54-
const wsConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
55-
await wsConfig.update('configPath', undefined, ConfigurationTarget.WorkspaceFolder);
56-
await wsConfig.update('flags', { disable_nested_config: '' }, ConfigurationTarget.WorkspaceFolder);
57-
58-
const config = new WorkspaceConfig(WORKSPACE_FOLDER);
59-
60-
deepStrictEqual(config.flags, { disable_nested_config: '' });
61-
strictEqual(config.configPath, '.oxlintrc.json');
62-
});
63-
6455
test('updating values updates the workspace configuration', async () => {
6556
const config = new WorkspaceConfig(WORKSPACE_FOLDER);
6657

@@ -70,7 +61,8 @@ suite('WorkspaceConfig', () => {
7061
config.updateTsConfigPath('./tsconfig.json'),
7162
config.updateUnusedDisableDirectives('deny'),
7263
config.updateTypeAware(true),
73-
config.updateFlags({ test: 'value' }),
64+
config.updateDisableNestedConfig(true),
65+
config.updateFixKind(FixKind.DangerousFix),
7466
config.updateFormattingExperimental(true),
7567
config.updateFormattingConfigPath('./oxfmt.json'),
7668
]);
@@ -82,7 +74,8 @@ suite('WorkspaceConfig', () => {
8274
strictEqual(wsConfig.get('tsConfigPath'), './tsconfig.json');
8375
strictEqual(wsConfig.get('unusedDisableDirectives'), 'deny');
8476
strictEqual(wsConfig.get('typeAware'), true);
85-
deepStrictEqual(wsConfig.get('flags'), { test: 'value' });
77+
strictEqual(wsConfig.get('disableNestedConfig'), true);
78+
strictEqual(wsConfig.get('fixKind'), 'dangerous_fix');
8679
strictEqual(wsConfig.get('fmt.experimental'), true);
8780
strictEqual(wsConfig.get('fmt.configPath'), './oxfmt.json');
8881
});

editors/vscode/tests/code_actions.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ teardown(async () => {
2929
const vsConfig = workspace.getConfiguration('oxc');
3030
const wsConfig = workspace.getConfiguration('oxc', fixturesWorkspaceUri());
3131
await vsConfig.update('unusedDisableDirectives', undefined);
32-
await wsConfig.update('flags', undefined, ConfigurationTarget.WorkspaceFolder);
33-
32+
await wsConfig.update('fixKind', undefined, ConfigurationTarget.WorkspaceFolder);
3433
await workspace.getConfiguration('editor').update('codeActionsOnSave', undefined);
3534
await workspace.saveAll();
3635
});
@@ -154,9 +153,7 @@ suite('code actions', () => {
154153
);
155154
strictEqual(quickFixesNoFix.length, 2);
156155

157-
await workspace.getConfiguration('oxc', fixturesWorkspaceUri()).update('flags', {
158-
'fix_kind': 'dangerous_fix',
159-
}, ConfigurationTarget.WorkspaceFolder);
156+
await workspace.getConfiguration('oxc', fixturesWorkspaceUri()).update('fixKind', 'dangerous_fix', ConfigurationTarget.WorkspaceFolder);
160157
await workspace.saveAll();
161158

162159
const codeActionsWithFix: ProviderResult<Array<CodeAction>> = await commands.executeCommand(

editors/vscode/tests/e2e_server.spec.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ suiteSetup(async () => {
3232
});
3333

3434
teardown(async () => {
35-
await workspace.getConfiguration('oxc').update('flags', undefined);
35+
await workspace.getConfiguration('oxc').update('fixKind', undefined);
3636
await workspace.getConfiguration('oxc').update('tsConfigPath', undefined);
3737
await workspace.getConfiguration('oxc').update('typeAware', undefined);
3838
await workspace.getConfiguration('oxc').update('fmt.experimental', undefined);
@@ -137,7 +137,7 @@ suite('E2E Diagnostics', () => {
137137
// We can check the changed with kind with `vscode.executeCodeActionProvider`
138138
// but to be safe that everything works, we will check the applied changes.
139139
// This way we can be sure that everything works as expected.
140-
test('auto detect changing `fix_kind` flag with fixAll command', async () => {
140+
test('auto detect changing `fixKind` with fixAll command', async () => {
141141
const originalContent = 'if (foo == null) { bar();}';
142142

143143
await createOxlintConfiguration({
@@ -163,9 +163,7 @@ suite('E2E Diagnostics', () => {
163163
const content = await workspace.fs.readFile(fileUri);
164164

165165
strictEqual(content.toString(), originalContent);
166-
await workspace.getConfiguration('oxc').update('flags', {
167-
fix_kind: 'all',
168-
});
166+
await workspace.getConfiguration('oxc').update('fixKind', 'all');
169167
// wait for server to update the internal linter
170168
await sleep(500);
171169
await workspace.saveAll();

0 commit comments

Comments
 (0)