Sprinter: добавить отладку C-исходников и интеграцию VS Code
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
const vm = require('node:vm');
|
||||
|
||||
test('F5 выполняет TaskProvider build и не запускает MAME после ошибки', async () => {
|
||||
let factory, configurationProvider, taskProvider;
|
||||
let onProcess, onEnd, exitCode = 0;
|
||||
const errors = [];
|
||||
const output = {appendLine() {}, dispose() {}};
|
||||
class DebugAdapterExecutable {
|
||||
constructor(command, args, options) {
|
||||
Object.assign(this, {command, args, options});
|
||||
}
|
||||
}
|
||||
class ProcessExecution {
|
||||
constructor(command, args, options) {
|
||||
Object.assign(this, {command, args, options});
|
||||
}
|
||||
}
|
||||
class Task {
|
||||
constructor(definition, scope, name, source, execution, problemMatchers) {
|
||||
Object.assign(this, {definition, scope, name, source,
|
||||
execution, problemMatchers});
|
||||
}
|
||||
}
|
||||
class RelativePattern {
|
||||
constructor(folder, pattern) {Object.assign(this, {folder, pattern});}
|
||||
}
|
||||
const vscode = {
|
||||
workspace: {
|
||||
workspaceFolders: [],
|
||||
getConfiguration: () => ({get: (key, fallback) => fallback}),
|
||||
findFiles: async () => [],
|
||||
},
|
||||
window: {createOutputChannel: () => output,
|
||||
showErrorMessage: message => errors.push(message)},
|
||||
debug: {
|
||||
registerDebugAdapterDescriptorFactory: (type, value) => {
|
||||
assert.equal(type, 'sprinter-mame');
|
||||
factory = value;
|
||||
return {dispose() {}};
|
||||
},
|
||||
registerDebugConfigurationProvider: (type, value) => {
|
||||
assert.equal(type, 'sprinter-mame');
|
||||
configurationProvider = value;
|
||||
return {dispose() {}};
|
||||
},
|
||||
},
|
||||
tasks: {
|
||||
registerTaskProvider: (type, value) => {
|
||||
assert.equal(type, 'sprinter');
|
||||
taskProvider = value;
|
||||
return {dispose() {}};
|
||||
},
|
||||
onDidEndTaskProcess: listener => {
|
||||
onProcess = listener;
|
||||
return {dispose() {onProcess = null;}};
|
||||
},
|
||||
onDidEndTask: listener => {
|
||||
onEnd = listener;
|
||||
return {dispose() {onEnd = null;}};
|
||||
},
|
||||
executeTask: async task => {
|
||||
const execution = {task};
|
||||
onProcess({execution, exitCode});
|
||||
onEnd({execution});
|
||||
return execution;
|
||||
},
|
||||
},
|
||||
commands: {registerCommand: (name) => {
|
||||
assert.equal(name, 'sprinter.buildActive');
|
||||
return {dispose() {}};
|
||||
}},
|
||||
DebugAdapterExecutable,
|
||||
ProcessExecution, Task, RelativePattern,
|
||||
TaskGroup: {Build: 'build'},
|
||||
};
|
||||
const source = fs.readFileSync(path.join(__dirname, 'extension.js'), 'utf8');
|
||||
const module = {exports: {}};
|
||||
vm.runInNewContext(source, {
|
||||
require: name => name === 'vscode' ? vscode : require(name),
|
||||
module, setTimeout,
|
||||
}, {filename: 'extension.js'});
|
||||
const context = {subscriptions: []};
|
||||
module.exports.activate(context);
|
||||
assert.equal(context.subscriptions.length, 5);
|
||||
|
||||
const workspace = path.resolve(__dirname, '..', '..');
|
||||
const session = {
|
||||
workspaceFolder: {uri: {fsPath: workspace}},
|
||||
configuration: {},
|
||||
};
|
||||
const descriptor = factory.createDebugAdapterDescriptor(session);
|
||||
assert.equal(descriptor.command,
|
||||
path.join(require('node:os').homedir(), '.pyenv', 'shims', 'python'));
|
||||
assert.equal(descriptor.args.at(-1),
|
||||
path.join(workspace, 'toolchain', 'sdbg_dap.py'));
|
||||
assert.equal(descriptor.options.cwd, workspace);
|
||||
assert.equal(descriptor.options.env.PYENV_VERSION, '3.12');
|
||||
const configuration = {
|
||||
type: 'sprinter-mame', request: 'launch',
|
||||
build: '${workspaceFolder}/tests/hello/.sprinter-cc-hello',
|
||||
};
|
||||
assert.equal(await configurationProvider.resolveDebugConfiguration(
|
||||
session.workspaceFolder, configuration), configuration, errors.join('\n'));
|
||||
const task = taskProvider.createTask(session.workspaceFolder,
|
||||
path.join(workspace, 'tests', 'hello'));
|
||||
assert.equal(task.name, 'Sprinter: Build tests/hello');
|
||||
assert.equal(task.execution.command, '/usr/bin/make');
|
||||
assert.equal(task.execution.options.cwd,
|
||||
path.join(workspace, 'tests', 'hello'));
|
||||
assert.equal(task.execution.options.env.PYENV_VERSION, '3.12');
|
||||
assert.deepEqual(Array.from(task.execution.args),
|
||||
['SRC_DEBUG=1', `PYTHON=${descriptor.command}`]);
|
||||
assert.equal(task.problemMatchers[0], '$sprinter-sdcc');
|
||||
vscode.workspace.workspaceFolders = [session.workspaceFolder];
|
||||
vscode.workspace.findFiles = async () => [
|
||||
{fsPath: path.join(workspace, 'tests', 'hello', 'Makefile')},
|
||||
{fsPath: path.join(workspace, 'Makefile')},
|
||||
];
|
||||
const discovered = await taskProvider.provideTasks();
|
||||
assert.equal(discovered.length, 1);
|
||||
assert.equal(discovered[0].name, task.name);
|
||||
const unresolved = {scope: session.workspaceFolder,
|
||||
definition: {type: 'sprinter', project: 'tests/hello'}};
|
||||
assert.equal(taskProvider.resolveTask(unresolved).definition,
|
||||
unresolved.definition);
|
||||
exitCode = 1;
|
||||
assert.equal(await configurationProvider.resolveDebugConfiguration(
|
||||
session.workspaceFolder, {...configuration}), undefined);
|
||||
assert.match(errors.at(-1), /MAME не запущен/);
|
||||
});
|
||||
Reference in New Issue
Block a user