Skip to content

Commit

Permalink
Merge pull request #5405 from 50Wliu/users/winstonliu/coreclr-debug-n…
Browse files Browse the repository at this point in the history
…ullability

coreclr-debug nullability
  • Loading branch information
JoeRobich authored Oct 13, 2022
2 parents 1f2d7de + 9b5d381 commit e3960a0
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 232 deletions.
33 changes: 13 additions & 20 deletions src/coreclr-debug/ParsedEnvironmentFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as fs from 'fs-extra';
import * as fs from 'fs';

export class ParsedEnvironmentFile {
public Env: { [key: string]: any };
public Warning: string | null;
public Warning: string | undefined;

private constructor(env: { [key: string]: any }, warning: string | null) {
private constructor(env: { [key: string]: any }, warning: string | undefined) {
this.Env = env;
this.Warning = warning;
}
Expand All @@ -20,26 +20,22 @@ export class ParsedEnvironmentFile {
}

public static CreateFromContent(content: string, envFile: string, initialEnv: { [key: string]: any } | undefined): ParsedEnvironmentFile {

// Remove UTF-8 BOM if present
if (content.charAt(0) === '\uFEFF') {
content = content.substr(1);
content = content.substring(1);
}

let parseErrors: string[] = [];
let env: { [key: string]: any } = initialEnv;
if (!env) {
env = {};
}
let env = initialEnv ?? {};

content.split("\n").forEach(line => {
// Split the line between key and value
const r: RegExpMatchArray = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
const match = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);

if (r !== null) {
const key: string = r[1];
let value: string = r[2] || "";
if ((value.length > 0) && (value.charAt(0) === '"') && (value.charAt(value.length - 1) === '"')) {
if (match !== null) {
const key = match[1];
let value = match[2] ?? "";
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, "\n");
}

Expand All @@ -57,14 +53,11 @@ export class ParsedEnvironmentFile {
});

// show error message if single lines cannot get parsed
let warning: string = null;
let warning: string | undefined;
if (parseErrors.length !== 0) {
warning = "Ignoring non-parseable lines in envFile " + envFile + ": ";
parseErrors.forEach(function (value, idx, array) {
warning += "\"" + value + "\"" + ((idx !== array.length - 1) ? ", " : ".");
});
warning = `Ignoring non-parseable lines in envFile ${envFile}: ${parseErrors.join(", ")}.`;
}

return new ParsedEnvironmentFile(env, warning);
}
}
}
72 changes: 35 additions & 37 deletions src/coreclr-debug/activate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,26 @@ import { DebuggerPrerequisiteWarning, DebuggerPrerequisiteFailure, DebuggerNotIn
import { EventStream } from '../EventStream';
import CSharpExtensionExports from '../CSharpExtensionExports';
import { getRuntimeDependencyPackageWithId } from '../tools/RuntimeDependencyPackageUtils';
import { getDotnetInfo, DotnetInfo } from '../utils/getDotnetInfo';
import { getDotnetInfo } from '../utils/getDotnetInfo';
import { DotnetDebugConfigurationProvider } from './debugConfigurationProvider';
import { Options } from '../omnisharp/options';

let _debugUtil: CoreClrDebugUtil = null;

export async function activate(thisExtension: vscode.Extension<CSharpExtensionExports>, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream, options: Options) {
_debugUtil = new CoreClrDebugUtil(context.extensionPath);
const debugUtil = new CoreClrDebugUtil(context.extensionPath);

if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) {
if (!CoreClrDebugUtil.existsSync(debugUtil.debugAdapterDir())) {
let isValidArchitecture: boolean = await checkIsValidArchitecture(platformInformation, eventStream);
// If this is a valid architecture, we should have had a debugger, so warn if we didn't, otherwise
// a warning was already issued, so do nothing.
if (isValidArchitecture) {
eventStream.post(new DebuggerPrerequisiteFailure("[ERROR]: C# Extension failed to install the debugger package."));
showInstallErrorMessage(eventStream);
}
} else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) {
completeDebuggerInstall(platformInformation, eventStream, options);
} else if (!CoreClrDebugUtil.existsSync(debugUtil.installCompleteFilePath())) {
completeDebuggerInstall(debugUtil, platformInformation, eventStream, options);
}

const factory = new DebugAdapterExecutableFactory(platformInformation, eventStream, thisExtension.packageJSON, thisExtension.extensionPath, options);
const factory = new DebugAdapterExecutableFactory(debugUtil, platformInformation, eventStream, thisExtension.packageJSON, thisExtension.extensionPath, options);
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new DotnetDebugConfigurationProvider(platformInformation)));
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('clr', new DotnetDebugConfigurationProvider(platformInformation)));
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('coreclr', factory));
Expand Down Expand Up @@ -74,30 +72,29 @@ async function checkIsValidArchitecture(platformInformation: PlatformInformation
return false;
}

async function completeDebuggerInstall(platformInformation: PlatformInformation, eventStream: EventStream, options: Options): Promise<boolean> {
return _debugUtil.checkDotNetCli(options.dotNetCliPaths)
.then(async (dotnetInfo: DotnetInfo) => {
async function completeDebuggerInstall(debugUtil: CoreClrDebugUtil, platformInformation: PlatformInformation, eventStream: EventStream, options: Options): Promise<boolean> {
try {
await debugUtil.checkDotNetCli(options.dotNetCliPaths);
const isValidArchitecture = await checkIsValidArchitecture(platformInformation, eventStream);
if (!isValidArchitecture) {
eventStream.post(new DebuggerNotInstalledFailure());
vscode.window.showErrorMessage('Failed to complete the installation of the C# extension. Please see the error in the output window below.');
return false;
}

let isValidArchitecture: boolean = await checkIsValidArchitecture(platformInformation, eventStream);
// Write install.complete
CoreClrDebugUtil.writeEmptyFile(debugUtil.installCompleteFilePath());

if (!isValidArchitecture) {
eventStream.post(new DebuggerNotInstalledFailure());
vscode.window.showErrorMessage('Failed to complete the installation of the C# extension. Please see the error in the output window below.');
return false;
}

// Write install.complete
CoreClrDebugUtil.writeEmptyFile(_debugUtil.installCompleteFilePath());
return true;
} catch (err) {
const error = err as Error;

return true;
}, (err) => {
// Check for dotnet tools failed. pop the UI
// err is a DotNetCliError but use defaults in the unexpected case that it's not
showDotnetToolsWarning(err.ErrorMessage || _debugUtil.defaultDotNetCliErrorMessage());
eventStream.post(new DebuggerPrerequisiteWarning(err.ErrorString || err));
// TODO: log telemetry?
return false;
});
// Check for dotnet tools failed. pop the UI
showDotnetToolsWarning(error.message);
eventStream.post(new DebuggerPrerequisiteWarning(error.message));
// TODO: log telemetry?
return false;
}
}

function showInstallErrorMessage(eventStream: EventStream) {
Expand Down Expand Up @@ -133,7 +130,7 @@ function showDotnetToolsWarning(message: string): void {
// Else it will launch the debug adapter
export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescriptorFactory {

constructor(private readonly platformInfo: PlatformInformation, private readonly eventStream: EventStream, private readonly packageJSON: any, private readonly extensionPath: string, private readonly options: Options) {
constructor(private readonly debugUtil: CoreClrDebugUtil, private readonly platformInfo: PlatformInformation, private readonly eventStream: EventStream, private readonly packageJSON: any, private readonly extensionPath: string, private readonly options: Options) {
}

async createDebugAdapterDescriptor(_session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): Promise<vscode.DebugAdapterDescriptor> {
Expand Down Expand Up @@ -161,8 +158,7 @@ export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescrip
}
// install.complete does not exist, check dotnetCLI to see if we can complete.
else if (!CoreClrDebugUtil.existsSync(util.installCompleteFilePath())) {
let success: boolean = await completeDebuggerInstall(this.platformInfo, this.eventStream, this.options);

let success = await completeDebuggerInstall(this.debugUtil, this.platformInfo, this.eventStream, this.options);
if (!success) {
this.eventStream.post(new DebuggerNotInstalledFailure());
throw new Error('Failed to complete the installation of the C# extension. Please see the error in the output window below.');
Expand All @@ -172,14 +168,16 @@ export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescrip

// debugger has finished installation, kick off our debugger process

// Check for targetArchitecture
let dotNetInfo = await getDotnetInfo(this.options.dotNetCliPaths);
const targetArchitecture: string = getTargetArchitecture(this.platformInfo, _session.configuration.targetArchitecture, dotNetInfo);

// use the executable specified in the package.json if it exists or determine it based on some other information (e.g. the session)
if (!executable) {
const dotNetInfo = await getDotnetInfo(this.options.dotNetCliPaths);
const targetArchitecture = getTargetArchitecture(this.platformInfo, _session.configuration.targetArchitecture, dotNetInfo);
const command = path.join(common.getExtensionPath(), ".debugger", targetArchitecture, "vsdbg-ui" + CoreClrDebugUtil.getPlatformExeExtension());
executable = new vscode.DebugAdapterExecutable(command, [], { env: { 'DOTNET_ROOT' : dotNetInfo.CliPath ? path.dirname(dotNetInfo.CliPath) : '' } });
executable = new vscode.DebugAdapterExecutable(command, [], {
env: {
DOTNET_ROOT: dotNetInfo.CliPath ? path.dirname(dotNetInfo.CliPath) : '',
}
});
}

// make VS Code launch the DA executable
Expand Down
14 changes: 7 additions & 7 deletions src/coreclr-debug/debugConfigurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PlatformInformation } from '../platform';
export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
constructor(public platformInformation: PlatformInformation) {}

public async resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration>
public async resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration | null | undefined>
{
if (!debugConfiguration)
{
Expand All @@ -21,7 +21,7 @@ export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurati
// Process Id is empty, handle Attach to Process Dialog.
if (debugConfiguration.request === "attach" && !debugConfiguration.processId && !debugConfiguration.processName)
{
let process: AttachItem = undefined;
let process: AttachItem | undefined;
if (debugConfiguration.pipeTransport)
{
process = await RemoteAttachPicker.ShowAttachEntries(debugConfiguration, this.platformInformation);
Expand All @@ -33,15 +33,15 @@ export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurati
process = await attacher.ShowAttachEntries();
}

if (process)
if (process !== undefined)
{
debugConfiguration.processId = process.id;

if (debugConfiguration.type == "coreclr" &&
this.platformInformation.isMacOS() &&
if (debugConfiguration.type == "coreclr" &&
this.platformInformation.isMacOS() &&
this.platformInformation.architecture == 'arm64')
{
// For Apple Silicon M1, it is possible that the process we are attaching to is being emulated as x86_64.
// For Apple Silicon M1, it is possible that the process we are attaching to is being emulated as x86_64.
// The process is emulated if it has process flags has P_TRANSLATED (0x20000).
if (process.flags & 0x20000)
{
Expand All @@ -62,4 +62,4 @@ export class DotnetDebugConfigurationProvider implements vscode.DebugConfigurati

return debugConfiguration;
}
}
}
Loading

0 comments on commit e3960a0

Please sign in to comment.