Skip to content

Commit

Permalink
Handle MSBuild properties NoWarn, TreatWarningsAsErrors, WarningsAsEr…
Browse files Browse the repository at this point in the history
…rors
  • Loading branch information
AliveDevil committed Aug 26, 2024
1 parent d8db7b1 commit 7d5d455
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 32 deletions.
62 changes: 57 additions & 5 deletions src/IKVM.MSBuild.Tasks/IkvmToolTaskDiagnosticWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using IKVM.Tools.Runner;

using Microsoft.Build.Framework;

namespace IKVM.MSBuild.Tasks
{

Expand Down Expand Up @@ -38,24 +40,74 @@ public Task ReceiveAsync(IkvmToolDiagnosticEvent @event)
if (@event == null)
return Task.CompletedTask;

(
IkvmToolDiagnosticEventLevel Level,
string Code,
string Message
) structuredLog;

#pragma warning disable IDE0079 // Unused suppression (net472 doesn't produce IDE0057)
#pragma warning disable IDE0057 // Suppress net6 & net8 analyzer for range-operations
// unspecified format: "Level: Message"
// MSBuild Format: "Level IKVM0000: Message"
// Longest preamble: "warning IKVM0000: "
// Some write """
// warning IKVMC0000: Message
// (additional information)
// """
// Skip these:
// - StdErr is mapped to Information
// - StdOut is mapped to Debug.
if (@event.Message.Length > 0 && @event.Message[0] is char first
&& !char.IsWhiteSpace(first)
&& @event.Message.IndexOf(": ", 0, 18) is { } firstColon and not -1)
{
structuredLog.Message = @event.Message.Substring(firstColon + 2);

int levelLength;
if (@event.Message.IndexOf("IKVM", 0, firstColon, StringComparison.OrdinalIgnoreCase) is { } codeIndex and not -1)
{
levelLength = codeIndex - 1;
structuredLog.Code = @event.Message.Substring(codeIndex, 8 /* IKVM0000 */);
}
else
{
levelLength = firstColon;
structuredLog.Code = "";
}

structuredLog.Level = @event.Message.Substring(0, levelLength).ToUpperInvariant() switch
{
"ERROR" => IkvmToolDiagnosticEventLevel.Error,
"WARNING" => IkvmToolDiagnosticEventLevel.Warning,
_ => IkvmToolDiagnosticEventLevel.Information
};
}
else
{
// Can't figure out level.
structuredLog = (@event.Level, null, @event.Message);
}
#pragma warning restore

try
{
switch (@event.Level)
switch (structuredLog.Level)
{
case IkvmToolDiagnosticEventLevel.Debug:
logger.LogMessage(Microsoft.Build.Framework.MessageImportance.Low, @event.Message, @event.MessageArgs);
logger.LogMessage(null, structuredLog.Code, null, null, 0, 0, 0, 0, MessageImportance.Low, structuredLog.Message, @event.MessageArgs);
writer?.WriteLine("DEBUG: " + @event.Message, @event.MessageArgs);
break;
case IkvmToolDiagnosticEventLevel.Information:
logger.LogMessage(Microsoft.Build.Framework.MessageImportance.Normal, @event.Message, @event.MessageArgs);
logger.LogMessage(null, structuredLog.Code, null, null, 0, 0, 0, 0, MessageImportance.Normal, structuredLog.Message, @event.MessageArgs);
writer?.WriteLine("INFO: " + @event.Message, @event.MessageArgs);
break;
case IkvmToolDiagnosticEventLevel.Warning:
logger.LogWarning(@event.Message, @event.MessageArgs);
logger.LogWarning(null, structuredLog.Code, null, null, 0, 0, 0, 0, structuredLog.Message, @event.MessageArgs);
writer?.WriteLine("WARN: " + @event.Message, @event.MessageArgs);
break;
case IkvmToolDiagnosticEventLevel.Error:
logger.LogWarning(@event.Message, @event.MessageArgs);
logger.LogError(null, structuredLog.Code, null, null, 0, 0, 0, 0, structuredLog.Message, @event.MessageArgs);
writer?.WriteLine("ERROR: " + @event.Message, @event.MessageArgs);
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ Value = b.ToString();
<_IkvmCompilerArgs Include="-nologo" />
<_IkvmCompilerArgs Include="-bootstrap" Condition=" '$(Bootstrap)' == 'true' " />
<_IkvmCompilerArgs Include="-debug:$(DebugType)" Condition=" '$(DebugType)' != 'none' " />
<_IkvmCompilerArgs Include="-nowarn:$(NoWarn.Replace(';', ','))" Condition=" '$(NoWarn)' != '' " />
<_IkvmCompilerArgs Include="-warnaserror" Condition=" '$(TreatWarningsAsErrors)' == 'true' " />
<_IkvmCompilerArgs Include="-warnaserror:$(WarningsAsErrors.Replace(';', ','))" Condition=" '$(TreatWarningsAsErrors)' != 'true' And '$(WarningsAsErrors)' != '' " />
<_IkvmCompilerArgs Include="-assembly:$(AssemblyName)" />
<_IkvmCompilerArgs Include="-version:$(AssemblyVersion)" />
<_IkvmCompilerArgs Include="-runtime:$(IkvmRuntimeAssembly)" />
Expand Down
3 changes: 3 additions & 0 deletions src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@
Platform="$(PlatformTarget.ToLowerInvariant())"
Main="$(StartupObject)"
Debug="$(DebugType)"
NoWarn="$(NoWarn.Replace(',', ';'))"
WarnAsError="$(TreatWarningsAsErrors)"
WarnAsErrorWarnings="$(WarningsAsErrors.Replace(',', ';'))"
KeyFile="$(KeyOriginatorFile)"
CompressResources="$(CompressResources)"
ClassLoader="$(ClassLoader)"
Expand Down
8 changes: 4 additions & 4 deletions src/IKVM.Tools.Importer/CompilerClassLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3419,8 +3419,8 @@ sealed class CompilerOptions
internal uint fileAlignment;
internal bool highentropyva;
internal List<CompilerClassLoader> sharedclassloader; // should *not* be deep copied in Copy(), because we want the list of all compilers that share a class loader
internal Dictionary<string, string> suppressWarnings = new Dictionary<string, string>();
internal Dictionary<string, string> errorWarnings = new Dictionary<string, string>(); // treat specific warnings as errors
internal HashSet<string> suppressWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
internal HashSet<string> errorWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
internal bool warnaserror; // treat all warnings as errors
internal FileInfo writeSuppressWarningsFile;
internal List<string> proxies = new List<string>();
Expand All @@ -3442,8 +3442,8 @@ internal CompilerOptions Copy()
{
copy.externalResources = new Dictionary<string, string>(externalResources);
}
copy.suppressWarnings = new Dictionary<string, string>(suppressWarnings);
copy.errorWarnings = new Dictionary<string, string>(errorWarnings);
copy.suppressWarnings = new(suppressWarnings, StringComparer.OrdinalIgnoreCase);
copy.errorWarnings = new(errorWarnings, StringComparer.OrdinalIgnoreCase);
return copy;
}

Expand Down
60 changes: 39 additions & 21 deletions src/IKVM.Tools.Importer/IkvmImporterInternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -773,31 +773,15 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I
}
else if (s.StartsWith("-nowarn:"))
{
foreach (var w in s.Substring(8).Split(','))
{
// lame way to chop off the leading zeroes
string ws = w;
while (ws.StartsWith("0"))
ws = ws.Substring(1);

options.suppressWarnings[ws] = ws;
}
HandleWarnArg(options.suppressWarnings, s.Substring(8));
}
else if (s == "-warnaserror")
{
options.warnaserror = true;
}
else if (s.StartsWith("-warnaserror:"))
{
foreach (string w in s.Substring(13).Split(','))
{
// lame way to chop off the leading zeroes
string ws = w;
while (ws.StartsWith("0"))
ws = ws.Substring(1);

options.errorWarnings[ws] = ws;
}
HandleWarnArg(options.errorWarnings, s.Substring(13));
}
else if (s.StartsWith("-runtime:"))
{
Expand Down Expand Up @@ -1479,7 +1463,7 @@ void ReportEvent(CompilerOptions options, in DiagnosticEvent evt)
var key = evt.Diagnostic.Id.ToString();
for (int i = 0; ; i++)
{
if (options.suppressWarnings.ContainsKey(key))
if (options.suppressWarnings.Contains(key))
return;

if (i == evt.Args.Length)
Expand All @@ -1488,7 +1472,7 @@ void ReportEvent(CompilerOptions options, in DiagnosticEvent evt)
key += ":" + evt.Args[i];
}

options.suppressWarnings.Add(key, key);
options.suppressWarnings.Add(key);
if (options.writeSuppressWarningsFile != null)
File.AppendAllText(options.writeSuppressWarningsFile.FullName, "-nowarn:" + key + Environment.NewLine);

Expand All @@ -1505,7 +1489,7 @@ void ReportEvent(CompilerOptions options, in DiagnosticEvent evt)
{
DiagnosticLevel.Trace => "trace",
DiagnosticLevel.Informational => "info",
DiagnosticLevel.Warning when options.errorWarnings.ContainsKey(key) || options.errorWarnings.ContainsKey(evt.Diagnostic.Id.ToString()) => "error",
DiagnosticLevel.Warning when options.errorWarnings.Contains(key) || options.errorWarnings.Contains(evt.Diagnostic.Id.ToString()) => "error",
DiagnosticLevel.Warning => "warning",
DiagnosticLevel.Error => "error",
DiagnosticLevel.Fatal => "error",
Expand All @@ -1526,6 +1510,40 @@ DiagnosticLevel.Warning when options.errorWarnings.ContainsKey(key) || options.e
dst.WriteLine(options.path != null ? $" (in {options.path})" : "");
}

internal static void HandleWarnArg(ICollection<string> target, string arg)
{
foreach (var w in arg.Split(','))
{
// Strip IKVM prefix
int prefixStart = w.StartsWith("IKVM", StringComparison.OrdinalIgnoreCase) ? 5 : 0;
int contextIndex = w.IndexOf(':', prefixStart);
string context = string.Empty;
string parse;
if(contextIndex != -1)
{
// context includes ':' separator
context = w.Substring(contextIndex);
parse = w.Substring(prefixStart, contextIndex - prefixStart);
}
else
{
parse = w.Substring(prefixStart);
}

if (!int.TryParse(parse, out var intResult))
{
if (!Enum.TryParse<Message>(parse, out var namedResult))

Check failure on line 1535 in src/IKVM.Tools.Importer/IkvmImporterInternal.cs

View workflow job for this annotation

GitHub Actions / Build IKVM

The type or namespace name 'Message' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 1535 in src/IKVM.Tools.Importer/IkvmImporterInternal.cs

View workflow job for this annotation

GitHub Actions / Build IKVM

The type or namespace name 'Message' could not be found (are you missing a using directive or an assembly reference?)
{
continue; // silently continue
}

// Warnings are handled as int.
intResult = (int)namedResult;
}

target.Add($"{intResult}{context}");
}
}
}

}
2 changes: 1 addition & 1 deletion src/IKVM.Tools.Importer/StaticCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ internal void IssueMissingTypeMessage(Type type)

internal void SuppressWarning(CompilerOptions options, Diagnostic diagnostic, string name)
{
options.suppressWarnings[diagnostic.Id + ":" + name] = null;
options.suppressWarnings.Add($"{diagnostic.Id}:{name}");
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/IKVM.Tools.Runner/Importer/IkvmImporterLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public async Task<int> ExecuteAsync(IkvmImporterOptions options, CancellationTok
await LogEvent(IkvmToolDiagnosticEventLevel.Debug, "Executing {0} {1}", cli.TargetFilePath, cli.Arguments);

// send output to MSBuild
cli = cli.WithStandardErrorPipe(PipeTarget.ToDelegate(i => LogEvent(IkvmToolDiagnosticEventLevel.Error, i)));
cli = cli.WithStandardErrorPipe(PipeTarget.ToDelegate(i => LogEvent(IkvmToolDiagnosticEventLevel.Warning, i)));
cli = cli.WithStandardOutputPipe(PipeTarget.ToDelegate(i => LogEvent(IkvmToolDiagnosticEventLevel.Debug, i)));

// combine manual cancellation with timeout
Expand Down

0 comments on commit 7d5d455

Please sign in to comment.