Skip to content
Draft
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 build/all_projects.settings.targets
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<ToolsHome>$(MIEngineRoot)\tools</ToolsHome>
<IntermediateOutputPath>$(MIEngineRoot)obj\$(Configuration)\$(MSBuildProjectName)\</IntermediateOutputPath>
<NuGetExePath>$(ToolsHome)\NuGet\NuGet.exe</NuGetExePath>
<!--NOTE: This is the same language version that is the default for .NET 8 projects -->
<LangVersion>12.0</LangVersion>
</PropertyGroup>

<!-- Source Link -->
Expand Down
10 changes: 5 additions & 5 deletions src/DebugEngineHost.Common/HostLogChannel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

/*
Expand Down Expand Up @@ -51,18 +51,18 @@ public interface ILogChannel
public class HostLogChannel : ILogChannel
{
private readonly Action<string> _log;
private StreamWriter _logFile;
private StreamWriter? _logFile;
private LogLevel _minLevelToBeLogged;

private readonly object _lock = new object();

private HostLogChannel() { }
private HostLogChannel() { _log = null!; }

public HostLogChannel(Action<string> logAction, string file, LogLevel logLevel)
public HostLogChannel(Action<string> logAction, string? file, LogLevel logLevel)
{
_log = logAction;

if (!string.IsNullOrEmpty(file))
if (!IsNullOrEmpty(file))
{
_logFile = File.CreateText(file);
}
Expand Down
7 changes: 7 additions & 0 deletions src/DebugEngineHost.Stub/DebugEngineHost.Stub.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<!--Fix the assembly version for DebugEngineHost as all the versions of this dll must have the same assembly identity
NOTE: Ths must be set BEFORE improting miengine.settings.targets-->
<AssemblyVersion>1.0.0</AssemblyVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..\..\build\miengine.settings.targets" />
<PropertyGroup>
Expand All @@ -23,6 +24,12 @@

<Import Project="..\..\build\Debugger.PIAs.Portable.Packages.settings.targets" />

<ItemGroup>
<Compile Include="$(MIEngineRoot)\src\Shared\NullableAttributes.cs">
<Link>Shared\%(Filename).cs</Link>
</Compile>
</ItemGroup>

<ItemGroup Label="NuGet Packages">
<PackageReference Include="Microsoft.VisualStudioEng.MicroBuild.Core" Version="$(Microsoft_VisualStudioEng_MicroBuild_Core_Version)" GeneratePathProperty="true"/>
</ItemGroup>
Expand Down
26 changes: 13 additions & 13 deletions src/DebugEngineHost.Stub/DebugEngineHost.ref.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.VisualStudio.Debugger.Interop;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using ConditionalAttribute = global::System.Diagnostics.ConditionalAttribute;
using System.Threading;


Expand Down Expand Up @@ -88,7 +88,7 @@ public void Dispose() { }
/// <param name="valueName">Name of the value to obtain</param>
/// <returns>[Optional] null if the value doesn't exist, otherwise the value
/// </returns>
public object GetValue(string valueName)
public object? GetValue(string valueName)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -146,7 +146,7 @@ public string RegistryRoot
/// </summary>
/// <param name="metric">The metric to read.</param>
/// <returns>[Optional] value of the metric. Null if the metric is not defined.</returns>
public object GetEngineMetric(string metric)
public object? GetEngineMetric(string metric)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -178,7 +178,7 @@ public T GetDebuggerConfigurationSetting<T>(string settingName, T defaultValue)
/// </summary>
/// <param name="launcherTypeName">launch options type name</param>
/// <returns></returns>
public object GetCustomLauncher(string launcherTypeName)
public object? GetCustomLauncher(string launcherTypeName)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -277,8 +277,8 @@ public static void EnableNatvisDiagnostics(Action<string> callback, LogLevel lev
/// <summary>
/// Sets the log file to write to.
/// </summary>
/// <param name="logFile">The file to write engine logs to.</param>
public static void SetEngineLogFile(string logFile)
/// <param name="logFile">The file to write engine logs to, or null if none</param>
public static void SetEngineLogFile(string? logFile)
{
throw new NotImplementedException();
}
Expand All @@ -287,7 +287,7 @@ public static void SetEngineLogFile(string logFile)
/// Gets the engine log channel created by 'EnableHostLogging'
/// </summary>
/// <returns>A logger object if logging is enabled, or null if it is not</returns>
public static ILogChannel GetEngineLogChannel()
public static ILogChannel? GetEngineLogChannel()
{
throw new NotImplementedException();
}
Expand All @@ -296,7 +296,7 @@ public static ILogChannel GetEngineLogChannel()
/// Gets the Natvis log channel if its been created.
/// </summary>
/// <returns>A logger object if logging is enabled, or null if it is not</returns>
public static ILogChannel GetNatvisLogChannel()
public static ILogChannel? GetNatvisLogChannel()
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -339,7 +339,7 @@ public static class HostLoader
/// <param name="clsid">CLSID to CoCreate</param>
/// <returns>[Optional] loaded object. Null if the type is not registered, or points to a type that doesn't exist</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Co")]
public static object VsCoCreateManagedObject(HostConfigurationStore configStore, Guid clsid)
public static object? VsCoCreateManagedObject(HostConfigurationStore configStore, Guid clsid)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -472,15 +472,15 @@ public static void FindNatvis(NatvisLoader loader)
/// <summary>
/// Enable's tracking the VS 'Natvis Diagnostic Messages (C++ only)' setting.
/// </summary>
public static IDisposable WatchNatvisOptionSetting(HostConfigurationStore configStore, ILogChannel natvisLogger)
public static IDisposable? WatchNatvisOptionSetting(HostConfigurationStore configStore, ILogChannel natvisLogger)
{
throw new NotImplementedException();
}

/// <summary>
/// Return the solution's root directory, null if no solution
/// </summary>
public static string FindSolutionRoot()
public static string? FindSolutionRoot()
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -663,7 +663,7 @@ public static void SendEvent(string eventName, params KeyValuePair<string, objec
/// </summary>
/// <param name="currentException">Exception object to report.</param>
/// <param name="engineName">Name of the engine reporting the exception. Ex:Microsoft.MIEngine</param>
public static void ReportCurrentException(Exception currentException, string engineName)
public static void ReportCurrentException(Exception currentException, string? engineName)
{
throw new NotImplementedException();
}
Expand Down
151 changes: 151 additions & 0 deletions src/DebugEngineHost.Stub/Shared/NullableHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

global using static global::Microsoft.DebugEngineHost.NullableHelpers;

namespace Microsoft.DebugEngineHost
{
using System.Diagnostics.CodeAnalysis;
using ConditionalAttribute = System.Diagnostics.ConditionalAttribute;
using SysDebug = System.Diagnostics.Debug;

#pragma warning disable 8763 // A method marked [DoesNotReturn] should not return.

/// <summary>
/// Helper class to support nullable reference work when compiling against .NET Standard / .NET Framework
/// </summary>
public static class NullableHelpers
{
/// <summary>
/// Wrapper around string.IsNullOrEmpty to add the `[NotNullWhen(false)]` annotation
/// </summary>
/// <param name="s">string to test</param>
/// <returns>True if the string is null or empty</returns>
static public bool IsNullOrEmpty([NotNullWhen(false)] string? s)
{
return string.IsNullOrEmpty(s);
}

/// <summary>
/// Wrapper around string.IsNullOrWhiteSpace to add the `[NotNullWhen(false)]` annotation
/// </summary>
/// <param name="s">string to test</param>
/// <returns>True if the string is null, empty, or only whitespace</returns>
static public bool IsNullOrWhiteSpace([NotNullWhen(false)] string? s)
{
return string.IsNullOrWhiteSpace(s);
}

/// <summary>
/// This is a shim on top of the <see cref="System.Diagnostics.Debug"/> class which adds attributes used
/// in nullability analysis. This is important because without the DoesNotReturnIf/DoesNotReturn attributes,
/// on Debug.Assert/Debug.Fail the C# compiler will see code like:
/// <code>
/// Debug.Assert(myArg != null, "Invalid argument")
/// </code>
/// And decide that because the code was attempting to handle 'myArg' being null, that it must be possible
/// for it to be null.
/// </summary>
[System.Diagnostics.DebuggerNonUserCode()]
public static class Debug
{
/// <summary>
/// Checks for a condition; if the condition is false, displays a message box that shows the call stack.
/// </summary>
/// <param name="condition">The conditional expression to evaluate. If the condition is true, a failure message is not sent and the message box is not displayed.</param>
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition)
{
SysDebug.Assert(condition);
}

/// <summary>
/// Checks for a condition; if the condition is false, outputs a specified message and displays a message box that shows the call stack.
/// </summary>
/// <param name="condition">The conditional expression to evaluate. If the condition is true, the specified message is not sent and the message box is not displayed.</param>
/// <param name="message">The message to send to the <see cref="System.Diagnostics.Trace.Listeners"/> collection.</param>
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, string message)
{
SysDebug.Assert(condition, message);
}

/// <summary>
/// Checks for a condition; if the condition is false, outputs two specified messages and displays a message box that shows the call stack.
/// </summary>
/// <param name="condition">The conditional expression to evaluate. If the condition is true, the specified messages are not sent and the message box is not displayed.</param>
/// <param name="message">The message to send to the <see cref="System.Diagnostics.Trace.Listeners"/> collection.</param>
/// <param name="detailMessage">The detailed message to send to the <see cref="System.Diagnostics.Trace.Listeners"/> collection.</param>
[Conditional("DEBUG")]
public static void Assert([DoesNotReturnIf(false)] bool condition, string message, string detailMessage)
{
SysDebug.Assert(condition, message, detailMessage);
}

/// <summary>
/// Emits the specified error message.
/// </summary>
/// <param name="message">A message to emit.</param>
[Conditional("DEBUG")]
[DoesNotReturn]
public static void Fail(string message)
{
SysDebug.Fail(message);
}
Comment thread
gregg-miskelly marked this conversation as resolved.

/// <summary>
/// Emits an error message and a detailed error message.
/// </summary>
/// <param name="message">A message to emit.</param>
/// <param name="detailMessage">A detailed message to emit.</param>
[Conditional("DEBUG")]
[DoesNotReturn]
public static void Fail(string message, string detailMessage)
{
SysDebug.Fail(message, detailMessage);
}
Comment thread
gregg-miskelly marked this conversation as resolved.

/// <summary>
/// Writes a message followed by a line terminator to the debugger.
/// </summary>
/// <param name="message">A message to write.</param>
[Conditional("DEBUG")]
public static void WriteLine(string message)
{
SysDebug.WriteLine(message);
}

/// <summary>
/// Writes the value of the object's <see cref="object.ToString"/> method to the debugger.
/// </summary>
/// <param name="value">An object whose value is sent to the debugger.</param>
[Conditional("DEBUG")]
public static void WriteLine(object value)
{
SysDebug.WriteLine(value);
}

/// <summary>
/// Writes a category name and message to the debugger.
/// </summary>
/// <param name="message">A message to write.</param>
/// <param name="category">A category name used to organize the output.</param>
[Conditional("DEBUG")]
public static void WriteLine(string message, string category)
{
SysDebug.WriteLine(message, category);
}

/// <summary>
/// Writes a category name and the value of the object's <see cref="object.ToString"/> method to the debugger.
/// </summary>
/// <param name="value">An object whose value is sent to the debugger.</param>
/// <param name="category">A category name used to organize the output.</param>
[Conditional("DEBUG")]
public static void WriteLine(object value, string category)
{
SysDebug.WriteLine(value, category);
}
}
}
}
16 changes: 11 additions & 5 deletions src/DebugEngineHost.VSCode/DebugEngineHost.VSCode.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<!--Fix the assembly version for DebugEngineHost as all the versions of this dll must have the same assembly identity
NOTE: Ths must be set BEFORE importing miengine.settings.targets-->
<AssemblyVersion>1.0.0</AssemblyVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..\..\build\miengine.settings.targets" />
<PropertyGroup>
Expand All @@ -20,11 +21,16 @@
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup Label="Compile Shared Interfaces">
<Compile Include="$(MIEngineRoot)\src\DebugEngineHost.Stub\Shared\Microsoft.VisualStudio.Debugger.Interop.DAP.cs" />
<Compile Include="..\DebugEngineHost.Stub\Shared\Microsoft.VisualStudio.Debugger.Interop.MI.cs" Link="Microsoft.VisualStudio.Debugger.Interop.MI.cs" />

<Compile Include="$(MIEngineRoot)\src\DebugEngineHost.Common\HostLogChannel.cs" />
<ItemGroup>
<Compile Include="$(MIEngineRoot)\src\DebugEngineHost.Stub\Shared\*.cs">
<Link>Shared\%(Filename).cs</Link>
</Compile>
<Compile Include="$(MIEngineRoot)\src\DebugEngineHost.Common\*.cs">
<Link>Shared\%(Filename).cs</Link>
</Compile>
<Compile Include="$(MIEngineRoot)\src\Shared\NullableAttributes.cs">
<Link>Shared\%(Filename).cs</Link>
</Compile>
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/DebugEngineHost.VSCode/HostConfigurationSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public object GetValue(string valueName)
public object? GetValue(string valueName)
{
ExceptionSettings.TriggerState state;
if (_defaultTriggers.TryGetValue(valueName, out state))
Expand Down
11 changes: 6 additions & 5 deletions src/DebugEngineHost.VSCode/HostConfigurationStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ public sealed class HostConfigurationStore

public HostConfigurationStore(string adapterId)
{
_config = EngineConfiguration.TryGet(adapterId);
if (_config == null)
EngineConfiguration? config = EngineConfiguration.TryGet(adapterId);
if (config is null)
{
throw new ArgumentOutOfRangeException(nameof(adapterId));
}
_config = config;
}

public void SetEngineGuid(Guid value)
Expand All @@ -35,12 +36,12 @@ public string RegistryRoot
}
}

public object GetCustomLauncher(string launcherTypeName)
public object? GetCustomLauncher(string launcherTypeName)
{
throw new NotImplementedException();
}

public object GetEngineMetric(string metric)
public object? GetEngineMetric(string metric)
{
if (string.CompareOrdinal("GlobalVisualizersDirectory", metric) == 0)
{
Expand All @@ -55,7 +56,7 @@ public object GetEngineMetric(string metric)
public void GetExceptionCategorySettings(Guid categoryId, out HostConfigurationSection categoryConfigSection, out string categoryName)
{
var category = _config.ExceptionSettings.Categories.FirstOrDefault((x) => x.Id == categoryId);
if (category == null)
if (category is null)
{
throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, HostResources.Error_ExceptionCategoryMissing, categoryId));
}
Expand Down
Loading
Loading