diff --git a/src/OmniSharp.MSBuild/Logging/ErrorMessages.cs b/src/OmniSharp.MSBuild/Logging/ErrorMessages.cs index 8e35c38a16..1358a2debf 100644 --- a/src/OmniSharp.MSBuild/Logging/ErrorMessages.cs +++ b/src/OmniSharp.MSBuild/Logging/ErrorMessages.cs @@ -2,6 +2,14 @@ namespace OmniSharp.MSBuild.Logging { internal class ErrorMessages { - internal const string ReferenceAssembliesNotFoundUnix = "This project targets .NET version that requires reference assemblies that do not ship with OmniSharp out of the box (e.g. .NET Framework). The most common solution is to make sure Mono is installed on your machine (https://mono-project.com/download/) and that OmniSharp is started with that Mono installation (e.g. 'omnisharp.useGlobalMono':'always' in C# Extension for VS Code)."; + internal const string ReferenceAssembliesNotFoundUnix = "This project targets .NET version that requires reference assemblies that do not ship with OmniSharp out of the box (e.g. .NET Framework). The most common solution is to make sure Mono is installed on your machine (https://mono-project.com/download/) and that OmniSharp is started with that Mono installation (e.g. \"omnisharp.useGlobalMono\":\"always\" in C# Extension for VS Code)."; + + internal const string ReferenceAssembliesNotFoundNet50Unix = "This project targets .NET 5.0 but the currently used MSBuild is not compatible with it - MSBuild 16.8+ is required. To solve this, run OmniSharp on its embedded Mono (e.g. 'omnisharp.useGlobalMono':'never' in C# Extension for VS Code) or, if running on global Mono installation, make sure at least Mono 6.13 is installed on your machine (https://mono-project.com/download/). Alternatively, add 'omnisharp.json' to your project root with the setting { \"msbuild\": { \"useBundledOnly\": true } }."; + + internal const string ReferenceAssembliesNotFoundNet60Unix = "This project targets .NET 6.0 but the currently used MSBuild is not compatible with it - MSBuild 16.9+ is required. To solve this, run OmniSharp on its embedded Mono (e.g. 'omnisharp.useGlobalMono':'never' in C# Extension for VS Code). Alternatively, add 'omnisharp.json' to your project root with the setting { \"msbuild\": { \"useBundledOnly\": true } }."; + + internal const string ReferenceAssembliesNotFoundNet50Windows = "This project targets .NET 5.0 but the currently used MSBuild is not compatible with it - MSBuild 16.8+ is required. To solve this, if you have Visual Studio 2019 installed on your machine, make sure it is updated to version 16.8 or add 'omnisharp.json' to your project root with the setting { \"msbuild\": { \"useBundledOnly\": true } }."; + + internal const string ReferenceAssembliesNotFoundNet60Windows = "This project targets .NET 6.0 but the currently used MSBuild is not compatible with it - MSBuild 16.9+ is required. To solve this, if you have Visual Studio 2019 installed on your machine, make sure it is updated to version 16.9 or add 'omnisharp.json' to your project root with the setting { \"msbuild\": { \"useBundledOnly\": true } }."; } } diff --git a/src/OmniSharp.MSBuild/Logging/MSBuildDiagnostic.cs b/src/OmniSharp.MSBuild/Logging/MSBuildDiagnostic.cs index 92769ad7cf..11f48f0d9a 100644 --- a/src/OmniSharp.MSBuild/Logging/MSBuildDiagnostic.cs +++ b/src/OmniSharp.MSBuild/Logging/MSBuildDiagnostic.cs @@ -36,20 +36,42 @@ public class MSBuildDiagnostic public static MSBuildDiagnostic CreateFrom(Microsoft.Build.Framework.BuildErrorEventArgs args) { + string diagnosticText = null; + // https://github.com/dotnet/msbuild/blob/v16.8.3/src/Tasks/Resources/Strings.resx#L2155-L2158 // for MSB3644, we should print a different message on Unix because the default one is Windows-specific - var diagnosticText = args.Code.Equals("MSB3644", StringComparison.OrdinalIgnoreCase) - && Platform.Current.OperatingSystem != Utilities.OperatingSystem.Windows - ? ErrorMessages.ReferenceAssembliesNotFoundUnix : args.Message; + if (args.Code.Equals("MSB3644", StringComparison.OrdinalIgnoreCase)) + { + // https://github.com/dotnet/msbuild/issues/5820 + // older versions of MSBuild incorrectly treat 'net5.0'/'net6.0' moniker as ".NETFramework,Version=v5.0/6.0" + // this creates a confusing error message which we convert into a more helpful one + if (args.Message.Contains(".NETFramework,Version=v5.0")) + { + diagnosticText = Platform.Current.OperatingSystem == Utilities.OperatingSystem.Windows + ? ErrorMessages.ReferenceAssembliesNotFoundNet50Windows : ErrorMessages.ReferenceAssembliesNotFoundNet50Unix; + } + else if (args.Message.Contains(".NETFramework,Version=v6.0")) + { + diagnosticText = Platform.Current.OperatingSystem == Utilities.OperatingSystem.Windows + ? ErrorMessages.ReferenceAssembliesNotFoundNet60Windows : ErrorMessages.ReferenceAssembliesNotFoundNet60Unix; + } + else + { + diagnosticText = Platform.Current.OperatingSystem != Utilities.OperatingSystem.Windows + ? ErrorMessages.ReferenceAssembliesNotFoundUnix : args.Message; + } + } return new MSBuildDiagnostic(MSBuildDiagnosticSeverity.Error, - diagnosticText, args.File, args.ProjectFile, args.Subcategory, args.Code, + diagnosticText ?? args.Message, args.File, args.ProjectFile, args.Subcategory, args.Code, args.LineNumber, args.ColumnNumber, args.EndLineNumber, args.EndColumnNumber); } public static MSBuildDiagnostic CreateFrom(Microsoft.Build.Framework.BuildWarningEventArgs args) - => new MSBuildDiagnostic(MSBuildDiagnosticSeverity.Error, - args.Message, args.File, args.ProjectFile, args.Subcategory, args.Code, - args.LineNumber, args.ColumnNumber, args.EndLineNumber, args.EndColumnNumber); + { + return new(MSBuildDiagnosticSeverity.Error, + args.Message, args.File, args.ProjectFile, args.Subcategory, args.Code, + args.LineNumber, args.ColumnNumber, args.EndLineNumber, args.EndColumnNumber); + } } }