Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ target/
/editors/vscode/out/
/editors/vscode/*.vsix
/editors/vscode/test_workspace/
/editors/vscode/test_workspace_second/
/editors/vscode/*.test.code-workspace

# Cloned conformance repos
tasks/coverage/babel/
Expand Down
66 changes: 49 additions & 17 deletions editors/vscode/.vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -1,27 +1,59 @@
import { defineConfig } from '@vscode/test-cli';
import { existsSync, mkdirSync } from 'node:fs';
import { mkdirSync, writeFileSync } from 'node:fs';
import path from 'node:path';

// create dir if not exists
if (!existsSync('./test_workspace')) {
mkdirSync('./test_workspace');
}
const multiRootWorkspaceFile = './multi-root.test.code-workspace';

mkdirSync('./test_workspace', { recursive: true });
mkdirSync('./test_workspace_second', { recursive: true });

const multiRootWorkspaceConfig = {
'folders': [
{ 'path': 'test_workspace' },
{ 'path': 'test_workspace_second' },
],
};
writeFileSync(multiRootWorkspaceFile, JSON.stringify(multiRootWorkspaceConfig, null, 2));

const ext = process.platform === 'win32' ? '.exe' : '';

export default defineConfig({
tests: [{
files: 'out/**/*.spec.js',
workspaceFolder: './test_workspace',
launchArgs: [
// This disables all extensions except the one being testing
'--disable-extensions',
],
env: {
SERVER_PATH_DEV: path.resolve(import.meta.dirname, `./target/debug/oxc_language_server${ext}`),
tests: [
{
files: 'out/**/*.spec.js',
workspaceFolder: './test_workspace',
launchArgs: [
// This disables all extensions except the one being testing
'--disable-extensions',
],
env: {
SINGLE_FOLDER_WORKSPACE: 'true',
SERVER_PATH_DEV: path.resolve(
import.meta.dirname,
`./target/debug/oxc_language_server${ext}`,
),
},
mocha: {
timeout: 10_000,
},
},
mocha: {
timeout: 10_000,
{
files: 'out/**/*.spec.js',
workspaceFolder: multiRootWorkspaceFile,
launchArgs: [
// This disables all extensions except the one being testing
'--disable-extensions',
],
env: {
MULTI_FOLDER_WORKSPACE: 'true',
SERVER_PATH_DEV: path.resolve(
import.meta.dirname,
`./target/debug/oxc_language_server${ext}`,
),
},
mocha: {
timeout: 10_000,
},
},
}],
],
});
67 changes: 0 additions & 67 deletions editors/vscode/client/WorkspaceConfig.spec.ts

This file was deleted.

5 changes: 5 additions & 0 deletions editors/vscode/fixtures/debugger_error/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-debugger": "error"
}
}
1 change: 1 addition & 0 deletions editors/vscode/fixtures/debugger_error/debugger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* 😊 */debugger;
2 changes: 1 addition & 1 deletion editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
"server:build:debug": "cross-env CARGO_TARGET_DIR=./target cargo build -p oxc_language_server",
"server:build:release": "cross-env CARGO_TARGET_DIR=./target cargo build -p oxc_language_server --release",
"lint": "npx oxlint --tsconfig=tsconfig.json",
"test": "esbuild client/*.spec.ts --bundle --outdir=out --external:vscode --format=cjs --platform=node --target=node16 --minify --sourcemap && vscode-test",
"test": "esbuild tests/*.spec.ts --bundle --outdir=out --external:vscode --format=cjs --platform=node --target=node16 --sourcemap && vscode-test",
"type-check": "tsc --noEmit"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { strictEqual } from 'assert';
import { Uri, workspace, WorkspaceEdit } from 'vscode';
import { VSCodeConfig } from './VSCodeConfig.js';
import { workspace } from 'vscode';
import { VSCodeConfig } from '../client/VSCodeConfig.js';
import { testSingleFolderMode } from './test-helpers.js';

const conf = workspace.getConfiguration('oxc');

Expand All @@ -11,23 +12,21 @@ suite('VSCodeConfig', () => {
await Promise.all(keys.map(key => conf.update(key, undefined)));
});

suiteTeardown(async () => {
const WORKSPACE_DIR = workspace.workspaceFolders![0].uri.toString();
const file = Uri.parse(WORKSPACE_DIR + '/.vscode/settings.json');
const edit = new WorkspaceEdit();
edit.deleteFile(file);
await workspace.applyEdit(edit);
teardown(async () => {
const keys = ['enable', 'trace.server', 'path.server'];

await Promise.all(keys.map(key => conf.update(key, undefined)));
});

test('default values on initialization', () => {
testSingleFolderMode('default values on initialization', () => {
const config = new VSCodeConfig();

strictEqual(config.enable, true);
strictEqual(config.trace, 'off');
strictEqual(config.binPath, '');
});

test('updating values updates the workspace configuration', async () => {
testSingleFolderMode('updating values updates the workspace configuration', async () => {
const config = new VSCodeConfig();

await Promise.all([
Expand Down
73 changes: 73 additions & 0 deletions editors/vscode/tests/WorkspaceConfig.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { deepStrictEqual, strictEqual } from 'assert';
import { ConfigurationTarget, workspace } from 'vscode';
import { WorkspaceConfig } from '../client/WorkspaceConfig.js';
import { WORKSPACE_FOLDER } from './test-helpers.js';

suite('WorkspaceConfig', () => {
setup(async () => {
const workspaceConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
const globalConfig = workspace.getConfiguration('oxc');
const keys = ['lint.run', 'configPath', 'flags'];

await Promise.all(keys.map(key => workspaceConfig.update(key, undefined, ConfigurationTarget.WorkspaceFolder)));
// VSCode will not save different workspace configuration inside a `.code-workspace` file.
// Do not fail, we will make sure the global config is empty too.
await Promise.all(keys.map(key => globalConfig.update(key, undefined)));
});

teardown(async () => {
const workspaceConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
const globalConfig = workspace.getConfiguration('oxc');
const keys = ['lint.run', 'configPath', 'flags'];

await Promise.all(keys.map(key => workspaceConfig.update(key, undefined, ConfigurationTarget.WorkspaceFolder)));
// VSCode will not save different workspace configuration inside a `.code-workspace` file.
// Do not fail, we will make sure the global config is empty too.
await Promise.all(keys.map(key => globalConfig.update(key, undefined)));
});

test('default values on initialization', () => {
const config = new WorkspaceConfig(WORKSPACE_FOLDER);
strictEqual(config.runTrigger, 'onType');
strictEqual(config.configPath, null);
deepStrictEqual(config.flags, {});
});

test('configPath defaults to null when using nested configs and configPath is empty', async () => {
const wsConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
await wsConfig.update('configPath', '', ConfigurationTarget.WorkspaceFolder);
await wsConfig.update('flags', {}, ConfigurationTarget.WorkspaceFolder);

const config = new WorkspaceConfig(WORKSPACE_FOLDER);

deepStrictEqual(config.flags, {});
strictEqual(config.configPath, null);
});

test('configPath defaults to .oxlintrc.json when not using nested configs and configPath is empty', async () => {
const wsConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);
await wsConfig.update('configPath', undefined, ConfigurationTarget.WorkspaceFolder);
await wsConfig.update('flags', { disable_nested_config: '' }, ConfigurationTarget.WorkspaceFolder);

const config = new WorkspaceConfig(WORKSPACE_FOLDER);

deepStrictEqual(config.flags, { disable_nested_config: '' });
strictEqual(config.configPath, '.oxlintrc.json');
});

test('updating values updates the workspace configuration', async () => {
const config = new WorkspaceConfig(WORKSPACE_FOLDER);

await Promise.all([
config.updateRunTrigger('onSave'),
config.updateConfigPath('./somewhere'),
config.updateFlags({ test: 'value' }),
]);

const wsConfig = workspace.getConfiguration('oxc', WORKSPACE_FOLDER);

strictEqual(wsConfig.get('lint.run'), 'onSave');
strictEqual(wsConfig.get('configPath'), './somewhere');
deepStrictEqual(wsConfig.get('flags'), { test: 'value' });
});
});
112 changes: 112 additions & 0 deletions editors/vscode/tests/code_actions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

import { deepStrictEqual, strictEqual } from 'assert';
import {
commands,
Position,
Range,
Uri,
window,
workspace,
WorkspaceEdit
} from 'vscode';
import {
activateExtension,
loadFixture,
sleep,
WORKSPACE_DIR
} from './test-helpers';
import assert = require('assert');

const fileUri = Uri.joinPath(WORKSPACE_DIR, 'debugger.js');


suiteSetup(async () => {
await activateExtension();
});

teardown(async () => {
const edit = new WorkspaceEdit();
edit.deleteFile(fileUri, {
ignoreIfNotExists: true,
});
await workspace.applyEdit(edit);
});

suite('code actions', () => {
test('listed code actions', async () => {
const edit = new WorkspaceEdit();
edit.createFile(fileUri, {
contents: Buffer.from('debugger;'),
overwrite: true,
});

await workspace.applyEdit(edit);
await window.showTextDocument(fileUri);

const codeActions = await commands.executeCommand(
'vscode.executeCodeActionProvider',
fileUri,
{
start: { line: 0, character: 8 },
end: { line: 0, character: 9 },
},
);

assert(Array.isArray(codeActions));
const quickFixes = codeActions.filter(
(action) => action.kind?.value === 'quickfix',
);
strictEqual(quickFixes.length, 3);
deepStrictEqual(
quickFixes.map(({ edit: _edit, kind: _kind, ...fix }) => ({
...fix,
})),
[
{
isPreferred: true,
title: 'Remove the debugger statement',
},
{
isPreferred: false,
title: 'Disable no-debugger for this line',
},
{
isPreferred: false,
title: 'Disable no-debugger for this file',
},
],
);
});

// https://github.com/oxc-project/oxc/issues/10422
test('code action `source.fixAll.oxc` on editor.codeActionsOnSave', async () => {
let file = Uri.joinPath(WORKSPACE_DIR, 'fixtures', 'file.js');
let expectedFile = Uri.joinPath(WORKSPACE_DIR, 'fixtures', 'expected.txt');

await workspace.getConfiguration('editor').update('codeActionsOnSave', {
'source.fixAll.oxc': 'always',
});
await workspace.saveAll();

const range = new Range(new Position(0, 0), new Position(0, 0));
const edit = new WorkspaceEdit();
edit.replace(file, range, ' ');

await sleep(1000);

await loadFixture('fixall_with_code_actions_on_save');
await workspace.openTextDocument(file);
await workspace.applyEdit(edit);
await sleep(1000);
await workspace.saveAll();
await sleep(500);

const content = await workspace.fs.readFile(file);
const expected = await workspace.fs.readFile(expectedFile);

strictEqual(content.toString(), expected.toString());

await workspace.getConfiguration('editor').update('codeActionsOnSave', undefined);
await workspace.saveAll();
});
});
Loading
Loading