Skip to content

Commit

Permalink
Fix multiple workspace behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita Romanov committed Feb 8, 2023
1 parent 2bd7844 commit 7c589bd
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 129 deletions.
9 changes: 1 addition & 8 deletions src/DotNet.Meteor.Debug/CLI/ConsoleUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static void AllDevices(string[] args) {
}

public static void AndroidSdkPath(string[] args) {
string path = DotNet.Meteor.Android.PathUtils.SdkLocation();
string path = Android.PathUtils.SdkLocation();
Console.WriteLine(JsonSerializer.Serialize(path));
}

Expand All @@ -46,13 +46,6 @@ public static void AnalyzeWorkspace(string[] args) {
Console.WriteLine(JsonSerializer.Serialize(projects));
}

public static void AnalyzeProject(string[] args) {
if (args.Length < 2)
throw new Exception ($"Missing parameter: {Program.CommandHandler[args[0]].Item1[1]}");
Project project = WorkspaceAnalyzer.AnalyzeProject(args[1], logger.Debug);
Console.WriteLine(JsonSerializer.Serialize(project));
}

public static void StartSession(string[] args) {
Console.WriteLine("Starting Mono debugger session...");
var debugSession = new MonoDebugSession();
Expand Down
5 changes: 0 additions & 5 deletions src/DotNet.Meteor.Debug/CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ public class Program {
"Find all executable projects in workspace", "<cwd-path>"
}, ConsoleUtils.AnalyzeWorkspace)
},
{
"--analyze-project", new Tuple<string[], Action<string[]>>(new []{
"Get info about specified project", "<project-path>"
}, ConsoleUtils.AnalyzeProject)
},
{
"--start-session", new Tuple<string[], Action<string[]>>(new []{
"Launch mono debugger session"
Expand Down
19 changes: 6 additions & 13 deletions src/VSCode.Extension/bridge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import path = require('path');
import { execSync, exec } from 'child_process';
import { Configuration } from './configuration';
import { Project, Device } from './models';
import { extensions } from 'vscode';
import * as res from './resources';
Expand All @@ -11,26 +10,20 @@ export class CommandInterface {
extensions.getExtension(`${res.extensionPublisher}.${res.extensionId}`)?.extensionPath ?? "?",
"extension", "bin", "DotNet.Meteor.Debug.dll");

public static mobileDevicesAsync(callback: (items: Device[]) => any) {
public static devicesAsync(callback: (items: Device[]) => any) {
ProcessRunner.runAsync<Device[]>(new ProcessArgumentBuilder("dotnet")
.appendQuoted(this.toolPath)
.appendQuoted(CommandInterface.toolPath)
.append("--all-devices"), callback);
}
public static analyzeWorkspaceAsync(callback: (items: Project[]) => any) {
public static analyzeWorkspaceAsync(folders: string[], callback: (items: Project[]) => any) {
ProcessRunner.runAsync<Project[]>(new ProcessArgumentBuilder("dotnet")
.appendQuoted(this.toolPath)
.appendQuoted(CommandInterface.toolPath)
.append("--analyze-workspace")
.appendRangeQuoted(Configuration.workspacesPath()), callback);
}
public static analyzeProject(projectFile: string): Project {
return ProcessRunner.run<Project>(new ProcessArgumentBuilder("dotnet")
.appendQuoted(this.toolPath)
.append("--analyze-project")
.appendQuoted(projectFile));
.appendRangeQuoted(folders), callback);
}
public static androidSdk(): string {
return ProcessRunner.run<string>(new ProcessArgumentBuilder("dotnet")
.appendQuoted(this.toolPath)
.appendQuoted(CommandInterface.toolPath)
.append("--android-sdk-path"));
}
}
Expand Down
62 changes: 20 additions & 42 deletions src/VSCode.Extension/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,48 @@
import { Project, Device, Target } from "./models"
import { window, workspace } from 'vscode';
import { UIController } from "./controller";
import { CommandInterface } from "./bridge";
import * as res from './resources';


export class Configuration {
public static selectedProject: Project;
public static selectedDevice: Device;
public static selectedTarget: Target;
public static project: Project | undefined;
public static device: Device | undefined;
public static target: Target;

public static getAndroidSdkDirectory() {
return CommandInterface.androidSdk();
public static getSetting<TResult>(id: string, fallback: TResult): TResult {
return workspace.getConfiguration(res.configId).get(id) ?? fallback;
}
public static getDebuggingPort(): number {
if (Configuration.isAndroid())
return workspace.getConfiguration(res.configId)
.get(res.configIdMonoSdbDebuggerPortAndroid) ?? res.configDefaultMonoSdbDebuggerPortAndroid;

if (Configuration.isApple())
return workspace.getConfiguration(res.configId)
.get(res.configIdMonoSdbDebuggerPortApple) ?? res.configDefaultMonoSdbDebuggerPortApple;

if (Configuration.isAndroid()) return Configuration.getSetting(
res.configIdMonoSdbDebuggerPortAndroid,
res.configDefaultMonoSdbDebuggerPortAndroid
);
if (Configuration.isApple()) return Configuration.getSetting(
res.configIdMonoSdbDebuggerPortApple,
res.configDefaultMonoSdbDebuggerPortApple
);
if (Configuration.isMacCatalyst() || Configuration.isWindows())
return 0;

return -1;
}

public static isAndroid(): boolean {
return Configuration.selectedDevice.platform?.includes('android') ?? false;
}
public static isApple(): boolean {
return Configuration.selectedDevice.platform?.includes('ios') ?? false;
}
public static isMacCatalyst(): boolean {
return Configuration.selectedDevice.platform?.includes('maccatalyst') ?? false;
}
public static isWindows(): boolean {
return Configuration.selectedDevice.platform?.includes('windows') ?? false;
}
public static isAndroid() { return Configuration.device?.platform?.includes('android') ?? false; }
public static isApple() { return Configuration.device?.platform?.includes('ios') ?? false; }
public static isMacCatalyst() { return Configuration.device?.platform?.includes('maccatalyst') ?? false; }
public static isWindows() { return Configuration.device?.platform?.includes('windows') ?? false; }


public static updateSelectedProject() {
const project = CommandInterface.analyzeProject(Configuration.selectedProject!.path);
Configuration.selectedProject = project;
}
public static workspacesPath(): string[] {
return workspace.workspaceFolders!.map(it => it.uri.fsPath);
}
public static targetFramework(): string | undefined {
const devicePlatform = Configuration.selectedDevice!.platform;
return Configuration.selectedProject!.frameworks?.find(it => it.includes(devicePlatform!));
}


public static validate(): boolean {
if (!Configuration.selectedProject || !Configuration.selectedProject.path) {
if (!Configuration.project || !Configuration.project.path) {
window.showErrorMessage(res.messageNoProjectFound);
return false;
}
if (!Configuration.selectedDevice || !Configuration.selectedDevice.platform) {
if (!Configuration.device || !Configuration.device.platform) {
window.showErrorMessage(res.messageNoDeviceFound);
return false;
}
if (!UIController.mobileDevices.some(it => it.name === Configuration.selectedDevice!.name)) {
if (!UIController.devices.some(it => it.name === Configuration.device?.name)) {
window.showErrorMessage(res.messageDeviceNotExists);
return false;
}
Expand Down
73 changes: 35 additions & 38 deletions src/VSCode.Extension/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,56 @@ import * as vscode from 'vscode';


export class UIController {
public static projectStatusItem: vscode.StatusBarItem;
public static targetStatusItem: vscode.StatusBarItem;
public static deviceStatusItem: vscode.StatusBarItem;
public static workspaceProjects: models.Project[];
public static mobileDevices: models.Device[];
private static _projectStatusItem: vscode.StatusBarItem;
private static _targetStatusItem: vscode.StatusBarItem;
private static _deviceStatusItem: vscode.StatusBarItem;

private static _isActivated: boolean = true;
public static projects: models.Project[];
public static devices: models.Device[];


public static activate(context: vscode.ExtensionContext) {
this.projectStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
this.targetStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 90);
this.deviceStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 80);
UIController._projectStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
UIController._targetStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 90);
UIController._deviceStatusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 80);

this.targetStatusItem.command = res.commandIdSelectActiveConfiguration;
this.projectStatusItem.command = res.commandIdSelectActiveProject;
this.deviceStatusItem.command = res.commandIdSelectActiveDevice;
UIController._targetStatusItem.command = res.commandIdSelectActiveConfiguration;
UIController._projectStatusItem.command = res.commandIdSelectActiveProject;
UIController._deviceStatusItem.command = res.commandIdSelectActiveDevice;

context.subscriptions.push(this.projectStatusItem);
context.subscriptions.push(this.targetStatusItem);
context.subscriptions.push(this.deviceStatusItem);
context.subscriptions.push(UIController._projectStatusItem);
context.subscriptions.push(UIController._targetStatusItem);
context.subscriptions.push(UIController._deviceStatusItem);
}

public static deactivate() {
this.projectStatusItem.hide();
this.targetStatusItem.hide();
this.deviceStatusItem.hide();
this._isActivated = false;
public static show() {
UIController._projectStatusItem.show();
UIController._targetStatusItem.show();
UIController._deviceStatusItem.show();
}
public static hide() {
UIController._projectStatusItem.hide();
UIController._targetStatusItem.hide();
UIController._deviceStatusItem.hide();
}

public static performSelectProject(item: models.Project | undefined = undefined) {
if (!this._isActivated) return;
Configuration.selectedProject = item ?? UIController.workspaceProjects[0];
this.projectStatusItem.text = `${models.Icon.project} ${Configuration.selectedProject?.name}`;
UIController.workspaceProjects.length === 1 ? this.projectStatusItem.hide() : this.projectStatusItem.show();
Configuration.project = item ?? UIController.projects[0];
UIController._projectStatusItem.text = `${models.Icon.project} ${Configuration.project?.name}`;
UIController.projects.length === 1 ? UIController._projectStatusItem.hide() : UIController._projectStatusItem.show();
}
public static performSelectTarget(target: models.Target | undefined = undefined) {
if (!this._isActivated) return;
Configuration.selectedTarget = target ?? models.Target.Debug;
this.targetStatusItem.text = `${models.Icon.target} ${Configuration.selectedTarget} | Any CPU`;
this.targetStatusItem.show();
public static performSelectTarget(item: models.Target | undefined = undefined) {
Configuration.target = item ?? models.Target.Debug;
UIController._targetStatusItem.text = `${models.Icon.target} ${Configuration.target} | Any CPU`;
}
public static performSelectDevice(item: models.Device | undefined = undefined) {
if (!this._isActivated) return;
Configuration.selectedDevice = item ?? UIController.mobileDevices[0];
const icon = Configuration.selectedDevice.is_mobile ? models.Icon.device : models.Icon.computer;
this.deviceStatusItem.text = `${icon} ${Configuration.selectedDevice?.name}`;
this.deviceStatusItem.show();
Configuration.device = item ?? UIController.devices[0];
const icon = Configuration.device.is_mobile ? models.Icon.device : models.Icon.computer;
UIController._deviceStatusItem.text = `${icon} ${Configuration.device?.name}`;
}


public static async showQuickPickProject() {
const items = UIController.workspaceProjects.map(project => new models.ProjectItem(project));
const items = UIController.projects.map(project => new models.ProjectItem(project));
const options = { placeHolder: res.commandTitleSelectActiveProject };
const selectedItem = await vscode.window.showQuickPick(items, options);

Expand Down Expand Up @@ -87,8 +84,8 @@ export class UIController {
picker.hide();
});

CommandInterface.mobileDevicesAsync(items => {
UIController.mobileDevices = items;
CommandInterface.devicesAsync(items => {
UIController.devices = items;
picker.items = items.map(device => new models.DeviceItem(device));
picker.placeholder = res.commandTitleSelectActiveDevice;
picker.busy = false;
Expand Down
29 changes: 17 additions & 12 deletions src/VSCode.Extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,37 @@ export function activate(context: vscode.ExtensionContext) {
/* Events */
context.subscriptions.push(vscode.debug.onDidStartDebugSession(() => vscode.commands.executeCommand(res.commandIdFocusOnDebug)));
context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(analyzeWorkspace));
context.subscriptions.push(vscode.workspace.onDidSaveTextDocument(ev => {
if (ev.fileName.endsWith('.csproj') || ev.fileName.endsWith('.props'))
analyzeWorkspace();
}));
}


function analyzeWorkspace() {
CommandInterface.analyzeWorkspaceAsync(items => {
const folders = vscode.workspace.workspaceFolders!.map(it => it.uri.fsPath);
CommandInterface.analyzeWorkspaceAsync(folders, items => {
if (items.length === 0) {
UIController.deactivate();
Configuration.project = undefined;
UIController.hide();
return;
}

UIController.workspaceProjects = items;
if (!Configuration.selectedProject)
UIController.performSelectTarget();
if (!Configuration.selectedProject || !items.some(it => it.path === Configuration.selectedProject.path))
UIController.performSelectProject();
UIController.projects = items;
UIController.show();

Configuration.project = items.find(it => it.path === Configuration.project?.path);
UIController.performSelectProject(Configuration.project);
UIController.performSelectTarget(Configuration.target);
});
}

function analyzeDevices() {
CommandInterface.mobileDevicesAsync(items => {
if (items.length === 0) {
UIController.deactivate();
CommandInterface.devicesAsync(items => {
if (items.length === 0)
return;
}

UIController.mobileDevices = items;
UIController.devices = items;
UIController.performSelectDevice();
});
}
16 changes: 9 additions & 7 deletions src/VSCode.Extension/tasks/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ProcessArgumentBuilder } from '../bridge';
import { Configuration } from '../configuration';
import { CommandInterface } from '../bridge';
import * as res from '../resources';
import * as vscode from 'vscode';

Expand All @@ -10,6 +11,8 @@ interface DotNetTaskDefinition extends vscode.TaskDefinition {
}

export class DotNetTaskProvider implements vscode.TaskProvider {
private androidSdkDirectory: string = CommandInterface.androidSdk();

resolveTask(task: vscode.Task, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Task> {
const resolvedTask = this.getTask(task.definition as DotNetTaskDefinition);
return resolvedTask ? resolvedTask : task;
Expand All @@ -26,15 +29,14 @@ export class DotNetTaskProvider implements vscode.TaskProvider {
return task ? [ task ] : [];
}
private getTask(definition: DotNetTaskDefinition): vscode.Task | undefined {
Configuration.updateSelectedProject();
if (!Configuration.validate())
return undefined;

const framework = Configuration.targetFramework();
const framework = Configuration.project!.frameworks?.find(it => it.includes(Configuration.device!.platform!))
const builder = new ProcessArgumentBuilder('dotnet')
.append(definition.target.toLowerCase())
.appendQuoted(Configuration.selectedProject.path)
.append(`-c:${Configuration.selectedTarget}`)
.appendQuoted(Configuration.project!.path)
.append(`-c:${Configuration.target}`)
.append(`-f:${framework}`);

if (definition.target.toLowerCase() === 'build')
Expand All @@ -45,12 +47,12 @@ export class DotNetTaskProvider implements vscode.TaskProvider {
return undefined;
}

if (Configuration.selectedDevice.runtime_id && Configuration.selectedDevice.runtime_id !== 'maccatalyst-x64') {
builder.append(`-p:RuntimeIdentifier=${Configuration.selectedDevice.runtime_id}`);
if (Configuration.device!.runtime_id && Configuration.device!.runtime_id !== 'maccatalyst-x64') {
builder.append(`-p:RuntimeIdentifier=${Configuration.device!.runtime_id}`);
}
if (Configuration.isAndroid()) {
builder.append('-p:EmbedAssembliesIntoApk=true');
builder.append(`-p:AndroidSdkDirectory="${Configuration.getAndroidSdkDirectory()}"`);
builder.append(`-p:AndroidSdkDirectory="${this.androidSdkDirectory}"`);
}
if (Configuration.isWindows()) {
builder.append('-p:WindowsPackageType=None');
Expand Down
8 changes: 4 additions & 4 deletions src/VSCode.Extension/tasks/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class DotNetDebuggerConfiguration implements vscode.DebugConfigurationPro
vscode.window.showErrorMessage(res.messageDebugNotSupportedWin);
return undefined;
}
if (Configuration.selectedTarget === Target.Release) {
if (Configuration.target === Target.Release) {
vscode.window.showErrorMessage(res.messageDebugNotSupported);
return undefined;
}
Expand All @@ -29,9 +29,9 @@ export class DotNetDebuggerConfiguration implements vscode.DebugConfigurationPro
config.request = 'launch';
}

config['selected_project'] = Configuration.selectedProject;
config['selected_device'] = Configuration.selectedDevice;
config['selected_target'] = Configuration.selectedTarget;
config['selected_project'] = Configuration.project;
config['selected_device'] = Configuration.device;
config['selected_target'] = Configuration.target;
config['debugging_port'] = Configuration.getDebuggingPort();

return config;
Expand Down

0 comments on commit 7c589bd

Please sign in to comment.