Skip to content

Commit

Permalink
Refactored Settings to be testable
Browse files Browse the repository at this point in the history
  • Loading branch information
bneumann committed Oct 2, 2024
1 parent 01c51af commit f8c2eae
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 120 deletions.
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@
"engines": {
"vscode": "^1.63.0"
},
"extensionDependencies": [
"hbenl.vscode-test-explorer"
],
"activationEvents": [
"onStartupFinished"
],
Expand Down
16 changes: 9 additions & 7 deletions src/Domain/CppUTestContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { CppUTest } from "./CppUTest";
import { TestState } from "./TestState";
import { ResultParser } from "./ResultParser";
import ExecutableRunner from "../Infrastructure/ExecutableRunner";
import { SettingsProvider, TestLocationFetchMode } from "../Infrastructure/SettingsProvider";
import { SettingsProvider } from "../Infrastructure/SettingsProvider";
import { TestLocationFetchMode } from '../Infrastructure/TestLocationFetchMode';
import { VscodeAdapter } from "../Infrastructure/VscodeAdapter";

export default class CppUTestContainer {
Expand Down Expand Up @@ -99,7 +100,7 @@ export default class CppUTestContainer {
public async DebugTest(...testId: string[]): Promise<void> {
const config = this.settingsProvider.GetDebugConfiguration();
const workspaceFolders = this.settingsProvider.GetWorkspaceFolders();
if (config === "") {
if (config === undefined) {
throw new Error("No debug configuration found. Not able to debug!");
}
if (!workspaceFolders) {
Expand All @@ -112,11 +113,12 @@ export default class CppUTestContainer {
const isTest = testOrGroup instanceof CppUTest;
const testRunName = isTest ? `${testOrGroup.group}.${testOrGroup.label}` : `${testOrGroup.label}`;
const testRunArg = isTest ? "-t" : "-sg";
(config as DebugConfiguration).name = testRunName;
(config as DebugConfiguration).args = [testRunArg, testRunName];
(config as DebugConfiguration).program = runner.Command;
(config as DebugConfiguration).target = runner.Command;
await this.vscodeAdapter.StartDebugger((workspaceFolders as WorkspaceFolder[]), config);
const debugConfig = config as unknown as DebugConfiguration;
debugConfig.name = testRunName;
debugConfig.args = [testRunArg, testRunName];
debugConfig.program = runner.Command;
debugConfig.target = runner.Command;
await this.vscodeAdapter.StartDebugger((workspaceFolders as WorkspaceFolder[]), debugConfig);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Infrastructure/ExecutableRunner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ExecException } from "child_process";
import { basename, dirname } from "path";
import { ProcessExecuter } from "../Application/ProcessExecuter";
import { TestLocationFetchMode } from "./SettingsProvider";
import { TestLocationFetchMode } from './TestLocationFetchMode';
import { Log } from "vscode-test-adapter-util";

export enum RunResultStatus {
Expand Down
7 changes: 7 additions & 0 deletions src/Infrastructure/IDebugConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export interface IDebugConfiguration {
target?: string;
program?: string;
args?: string[];
name: string;
}
10 changes: 10 additions & 0 deletions src/Infrastructure/IWorkspaceConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

export interface IWorkspaceConfiguration {
testExecutable: string | undefined;
testExecutablePath: string | undefined;
testLocationFetchMode: any;
logfile: string | undefined;
logpanel: boolean;
debugLaunchConfigurationName: string | undefined;
objDumpExecutable: string | undefined;
}
6 changes: 6 additions & 0 deletions src/Infrastructure/IWorkspaceFolder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

export interface IWorkspaceFolder {
readonly uri: any;
readonly name: string;
readonly index: number;
}
13 changes: 13 additions & 0 deletions src/Infrastructure/Infrastructure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { IDebugConfiguration } from "./IDebugConfiguration";
import { IWorkspaceConfiguration } from "./IWorkspaceConfiguration";
import { IWorkspaceFolder } from "./IWorkspaceFolder";
import { SettingsProvider } from "./SettingsProvider";
import { TestLocationFetchMode } from "./TestLocationFetchMode";
import { VscodeAdapter } from "./VscodeAdapter";

export { IDebugConfiguration };
export { TestLocationFetchMode };
export { SettingsProvider };
export { IWorkspaceConfiguration };
export { IWorkspaceFolder };
export { VscodeAdapter };
101 changes: 87 additions & 14 deletions src/Infrastructure/SettingsProvider.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,90 @@
import { DebugConfiguration, WorkspaceFolder } from 'vscode';
import glob = require('glob');
import { Log } from 'vscode-test-adapter-util';
import { IWorkspaceFolder } from './IWorkspaceFolder';
import { IDebugConfiguration } from './IDebugConfiguration';
import { IWorkspaceConfiguration } from './IWorkspaceConfiguration';
import { TestLocationFetchMode } from './TestLocationFetchMode';

export enum TestLocationFetchMode {
Auto,
TestQuery,
DebugDump,
Disabled
}
export abstract class SettingsProvider {

protected log: Log;
protected config: IWorkspaceConfiguration;

constructor(log: Log) {
const configSection = "cpputestTestAdapter";

this.log = log;
this.config = this.GetConfig(configSection);
}

protected abstract GetConfig(section: string): IWorkspaceConfiguration;
abstract GetObjDumpPath(): string;
abstract GetTestRunners(): string[];
abstract GetTestPath(): string;
abstract GetDebugConfiguration(): (IDebugConfiguration | undefined);
abstract GetWorkspaceFolders(): readonly IWorkspaceFolder[] | undefined
protected abstract GetCurrentFilename(): string
protected abstract GetCurrentWorkspaceFolder(): string

public get TestLocationFetchMode(): TestLocationFetchMode {
switch (this.config.testLocationFetchMode) {
case 'test query':
return TestLocationFetchMode.TestQuery;
case 'debug dump':
return TestLocationFetchMode.DebugDump;
case 'auto':
return TestLocationFetchMode.Auto;
case 'disabled':
default:
return TestLocationFetchMode.Disabled;
}
}

protected IsCCppDebugger(config: any) {
const isWin = process.platform === "win32";
// This is my way of saying: If we are using windows check for a config that has an .exe program.
const executionExtension: boolean = isWin ? config.program.endsWith(".exe") : true;
return config.request == 'launch' &&
typeof config.type == 'string' &&
executionExtension &&
(config.type.startsWith('cpp') ||
config.type.startsWith('lldb') ||
config.type.startsWith('gdb'));
}

protected SplitRunners(executablesString: string | undefined): string[] {
if (executablesString) {
if (executablesString.indexOf(";") === -1) {
return [this.ResolveSettingsVariable(executablesString)];
}
return executablesString
.split(";")
.map(r => this.ResolveSettingsVariable(r))
.map(r => glob.sync(r))
.reduce((flatten, arr) => [...flatten, ...arr]);
} else {
return [];
}
}

export interface SettingsProvider {
GetObjDumpPath(): string;
GetTestRunners(): string[];
GetTestPath(): string;
get TestLocationFetchMode(): TestLocationFetchMode;
GetDebugConfiguration(): (DebugConfiguration | string);
GetWorkspaceFolders(): readonly WorkspaceFolder[] | undefined
/**
* This function converts some of the VSCode variables like workspaceFolder
* into their correspoing values. This is a workaround for https://github.com/microsoft/vscode/issues/46471
* @param input Input string from settings.json
*/
protected ResolveSettingsVariable(input: string | undefined): string {
if (input) {
const result: string[] | null = input.match(/\$\{(.*)\}/gmi);
if (result && result.length > 0) {
this.log.info(`replacing config variabe "${input}"`);
input = input.replace(/(\$\{file\})/gmi, this.GetCurrentFilename());
input = input.replace(/(\$\{workspaceFolder\})/gmi, this.GetCurrentWorkspaceFolder());
this.log.info(`replaced variable is now "${input}"`);
}
return input;
}
else {
return "";
}
}
}
7 changes: 7 additions & 0 deletions src/Infrastructure/TestLocationFetchMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export enum TestLocationFetchMode {
Auto,
TestQuery,
DebugDump,
Disabled
}
103 changes: 27 additions & 76 deletions src/Infrastructure/VscodeSettingsProvider.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
import * as vscode from 'vscode';
import { glob } from 'glob';
import { SettingsProvider, TestLocationFetchMode } from './SettingsProvider';
import { SettingsProvider } from './SettingsProvider';
import { IWorkspaceConfiguration } from './IWorkspaceConfiguration';
import { IDebugConfiguration } from './IDebugConfiguration';
import { Log } from 'vscode-test-adapter-util';
import { IWorkspaceFolder } from './IWorkspaceFolder';

export default class VscodeSettingsProvider implements SettingsProvider {
private config: vscode.WorkspaceConfiguration;
private log: Log;

export default class VscodeSettingsProvider extends SettingsProvider {

constructor(log: Log) {
const configSection = "cpputestTestAdapter";
this.config = vscode.workspace.getConfiguration(configSection);
this.log = log;
vscode.workspace.onDidChangeConfiguration(event => {
if (event.affectsConfiguration(configSection)) {
this.config = vscode.workspace.getConfiguration(configSection);
}
})
super(log)

// vscode.workspace.onDidChangeConfiguration(event => {
// if (event.affectsConfiguration(configSection)) {
// this.config = vscode.workspace.getConfiguration(configSection);
// }
// })
}

protected override GetConfig(configSection: string): IWorkspaceConfiguration {
return (vscode.workspace.getConfiguration(configSection) as any);
}

GetObjDumpPath(): string {
return this.ResolveSettingsVariable(this.config.objDumpExecutable);
}

GetWorkspaceFolders(): readonly vscode.WorkspaceFolder[] | undefined {
GetWorkspaceFolders(): readonly IWorkspaceFolder[] | undefined {
return vscode.workspace.workspaceFolders;
}

Expand All @@ -33,30 +38,16 @@ export default class VscodeSettingsProvider implements SettingsProvider {
return this.ResolveSettingsVariable(this.config.testExecutablePath);
}

public get TestLocationFetchMode(): TestLocationFetchMode {
switch(this.config.testLocationFetchMode) {
case 'test query':
return TestLocationFetchMode.TestQuery;
case 'debug dump':
return TestLocationFetchMode.DebugDump;
case 'auto':
return TestLocationFetchMode.Auto;
case 'disabled':
default:
return TestLocationFetchMode.Disabled;
}
}

public GetDebugConfiguration(): (vscode.DebugConfiguration | string) {
public GetDebugConfiguration(): (IDebugConfiguration | undefined) {
// Thanks to: https://github.com/matepek/vscode-catch2-test-adapter/blob/9a2e9f5880ef3907d80ff99f3d6d028270923c95/src/Configurations.ts#L125
if (vscode.workspace.workspaceFolders === undefined) {
return "";
return undefined;
}
const wpLaunchConfigs: string | undefined = vscode.workspace
.getConfiguration('launch', vscode.workspace.workspaceFolders[0].uri)
.get<string>('configurations');

const hasConfiguredLaunchProfiles: boolean = this.config.debugLaunchConfigurationName;
const hasConfiguredLaunchProfiles: boolean = this.config.debugLaunchConfigurationName !== undefined;

if (wpLaunchConfigs && Array.isArray(wpLaunchConfigs) && wpLaunchConfigs.length > 0) {
if(hasConfiguredLaunchProfiles) {
Expand Down Expand Up @@ -85,54 +76,14 @@ export default class VscodeSettingsProvider implements SettingsProvider {

}

return "";
}

private IsCCppDebugger(config: any) {
const isWin = process.platform === "win32";
// This is my way of saying: If we are using windows check for a config that has an .exe program.
const executionExtension: boolean = isWin ? config.program.endsWith(".exe") : true;
return config.request == 'launch' &&
typeof config.type == 'string' &&
executionExtension &&
(config.type.startsWith('cpp') ||
config.type.startsWith('lldb') ||
config.type.startsWith('gdb'));
return undefined;
}

private SplitRunners(executablesString: string | undefined): string[] {
if (executablesString) {
if(executablesString.indexOf(";") === -1){
return [this.ResolveSettingsVariable(executablesString)];
}
return executablesString
.split(";")
.map(r => this.ResolveSettingsVariable(r))
.map(r => glob.sync(r))
.reduce((flatten, arr) => [...flatten, ...arr]);
} else {
return [];
}
protected override GetCurrentFilename(): string {
return vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri.fsPath : "";
}

/**
* This function converts some of the VSCode variables like workspaceFolder
* into their correspoing values. This is a workaround for https://github.com/microsoft/vscode/issues/46471
* @param input Input string from settings.json
*/
private ResolveSettingsVariable(input: string | undefined): string {
if (input) {
const result: string[] | null = input.match(/\$\{(.*)\}/gmi);
if (result && result.length > 0) {
this.log.info(`replacing config variabe "${input}"`);
input = input.replace(/(\$\{file\})/gmi, vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri.fsPath : "");
input = input.replace(/(\$\{workspaceFolder\})/gmi, vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : "");
this.log.info(`replaced variable is now "${input}"`);
}
return input;
}
else {
return "";
}
protected override GetCurrentWorkspaceFolder(): string {
return vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : "";
}
}
Loading

0 comments on commit f8c2eae

Please sign in to comment.