diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets index 1f028d0d6..f95c9e746 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets @@ -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)" /> diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets index affb1f803..27482bacb 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets @@ -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)" diff --git a/src/IKVM.Tools.Importer/CompilerClassLoader.cs b/src/IKVM.Tools.Importer/CompilerClassLoader.cs index 53b9222b1..e5b3d5fd8 100644 --- a/src/IKVM.Tools.Importer/CompilerClassLoader.cs +++ b/src/IKVM.Tools.Importer/CompilerClassLoader.cs @@ -3411,8 +3411,8 @@ sealed class CompilerOptions internal uint fileAlignment; internal bool highentropyva; internal List sharedclassloader; // should *not* be deep copied in Copy(), because we want the list of all compilers that share a class loader - internal Dictionary suppressWarnings = new Dictionary(); - internal Dictionary errorWarnings = new Dictionary(); // treat specific warnings as errors + internal HashSet suppressWarnings = new HashSet(StringComparer.OrdinalIgnoreCase); + internal HashSet errorWarnings = new HashSet(StringComparer.OrdinalIgnoreCase); internal bool warnaserror; // treat all warnings as errors internal FileInfo writeSuppressWarningsFile; internal List proxies = new List(); @@ -3434,8 +3434,8 @@ internal CompilerOptions Copy() { copy.externalResources = new Dictionary(externalResources); } - copy.suppressWarnings = new Dictionary(suppressWarnings); - copy.errorWarnings = new Dictionary(errorWarnings); + copy.suppressWarnings = new(suppressWarnings, StringComparer.OrdinalIgnoreCase); + copy.errorWarnings = new(errorWarnings, StringComparer.OrdinalIgnoreCase); return copy; } diff --git a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs index 2b8d100d7..ff50f00a1 100644 --- a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs +++ b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs @@ -748,15 +748,7 @@ 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") { @@ -764,15 +756,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } 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:")) { @@ -1449,10 +1433,11 @@ internal static void IssueMessage(StaticCompiler compiler, CompilerOptions optio return; } - string key = ((int)msgId).ToString(); + var msgIdKey = $"{(int)msgId}"; + string key = msgIdKey; for (int i = 0; ; i++) { - if (options.suppressWarnings.ContainsKey(key)) + if (options.suppressWarnings.Contains(key)) { return; } @@ -1460,9 +1445,9 @@ internal static void IssueMessage(StaticCompiler compiler, CompilerOptions optio { break; } - key += ":" + values[i]; + key = $"{key}:{values[i]}"; } - options.suppressWarnings.Add(key, key); + options.suppressWarnings.Add(key); if (options.writeSuppressWarningsFile != null) { File.AppendAllText(options.writeSuppressWarningsFile.FullName, "-nowarn:" + key + Environment.NewLine); @@ -1668,8 +1653,8 @@ internal static void IssueMessage(StaticCompiler compiler, CompilerOptions optio } bool error = msgId >= Message.StartErrors || (options.warnaserror && msgId >= Message.StartWarnings) - || options.errorWarnings.ContainsKey(key) - || options.errorWarnings.ContainsKey(((int)msgId).ToString()); + || options.errorWarnings.Contains(key) + || options.errorWarnings.Contains(msgIdKey); Console.Error.Write("{0} IKVMC{1:D4}: ", error ? "error" : msgId < Message.StartWarnings ? "note" : "warning", (int)msgId); if (error && Message.StartWarnings <= msgId && msgId < Message.StartErrors) { @@ -1689,6 +1674,41 @@ internal static void IssueMessage(StaticCompiler compiler, CompilerOptions optio } } + internal static void HandleWarnArg(ICollection target, string arg) + { + foreach (var w in arg.Split(',')) + { + // Strip IKVMC prefix + int prefixStart = w.StartsWith("IKVMC", 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(parse, out var namedResult)) + { + continue; // silently continue + } + + // Warnings are handled as int. + intResult = (int)namedResult; + } + + // Check IssueMessage + target.Add($"{intResult}{context}"); + } + } } } diff --git a/src/IKVM.Tools.Importer/StaticCompiler.cs b/src/IKVM.Tools.Importer/StaticCompiler.cs index bfc78180a..ea2460cae 100644 --- a/src/IKVM.Tools.Importer/StaticCompiler.cs +++ b/src/IKVM.Tools.Importer/StaticCompiler.cs @@ -230,7 +230,7 @@ internal void IssueMissingTypeMessage(Type type) internal void SuppressWarning(CompilerOptions options, Message message, string name) { - options.suppressWarnings[(int)message + ":" + name] = null; + options.suppressWarnings.Add($"{(int)message}:{name}"); } internal void IssueMessage(Message msgId, params string[] values) @@ -240,250 +240,7 @@ internal void IssueMessage(Message msgId, params string[] values) internal void IssueMessage(CompilerOptions options, Message msgId, params string[] values) { - if (errorCount != 0 && msgId < Message.StartErrors && !options.warnaserror) - { - // don't display any warnings after we've emitted an error message - return; - } - - string key = ((int)msgId).ToString(); - for (int i = 0; ; i++) - { - if (options.suppressWarnings.ContainsKey(key)) - { - return; - } - if (i == values.Length) - { - break; - } - key += ":" + values[i]; - } - options.suppressWarnings.Add(key, key); - if (options.writeSuppressWarningsFile != null) - { - File.AppendAllText(options.writeSuppressWarningsFile.FullName, "-nowarn:" + key + Environment.NewLine); - } - string msg; - switch (msgId) - { - case Message.MainMethodFound: - msg = "Found main method in class \"{0}\""; - break; - case Message.OutputFileIs: - msg = "Output file is \"{0}\""; - break; - case Message.AutoAddRef: - msg = "Automatically adding reference to \"{0}\""; - break; - case Message.MainMethodFromManifest: - msg = "Using main class \"{0}\" based on jar manifest"; - break; - case Message.ClassNotFound: - msg = "Class \"{0}\" not found"; - break; - case Message.ClassFormatError: - msg = "Unable to compile class \"{0}\"" + Environment.NewLine + - " (class format error \"{1}\")"; - break; - case Message.DuplicateClassName: - msg = "Duplicate class name: \"{0}\""; - break; - case Message.IllegalAccessError: - msg = "Unable to compile class \"{0}\"" + Environment.NewLine + - " (illegal access error \"{1}\")"; - break; - case Message.VerificationError: - msg = "Unable to compile class \"{0}\"" + Environment.NewLine + - " (verification error \"{1}\")"; - break; - case Message.NoClassDefFoundError: - msg = "Unable to compile class \"{0}\"" + Environment.NewLine + - " (missing class \"{1}\")"; - break; - case Message.GenericUnableToCompileError: - msg = "Unable to compile class \"{0}\"" + Environment.NewLine + - " (\"{1}\": \"{2}\")"; - break; - case Message.DuplicateResourceName: - msg = "Skipping resource (name clash): \"{0}\""; - break; - case Message.SkippingReferencedClass: - msg = "Skipping class: \"{0}\"" + Environment.NewLine + - " (class is already available in referenced assembly \"{1}\")"; - break; - case Message.NoJniRuntime: - msg = "Unable to load runtime JNI assembly"; - break; - case Message.EmittedNoClassDefFoundError: - msg = "Emitted java.lang.NoClassDefFoundError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedIllegalAccessError: - msg = "Emitted java.lang.IllegalAccessError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedInstantiationError: - msg = "Emitted java.lang.InstantiationError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedIncompatibleClassChangeError: - msg = "Emitted java.lang.IncompatibleClassChangeError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedNoSuchFieldError: - msg = "Emitted java.lang.NoSuchFieldError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedAbstractMethodError: - msg = "Emitted java.lang.AbstractMethodError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedNoSuchMethodError: - msg = "Emitted java.lang.NoSuchMethodError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedLinkageError: - msg = "Emitted java.lang.LinkageError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedVerificationError: - msg = "Emitted java.lang.VerificationError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.EmittedClassFormatError: - msg = "Emitted java.lang.ClassFormatError in \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.InvalidCustomAttribute: - msg = "Error emitting \"{0}\" custom attribute" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.IgnoredCustomAttribute: - msg = "Custom attribute \"{0}\" was ignored" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.AssumeAssemblyVersionMatch: - msg = "Assuming assembly reference \"{0}\" matches \"{1}\", you may need to supply runtime policy"; - break; - case Message.InvalidDirectoryInLibOptionPath: - msg = "Directory \"{0}\" specified in -lib option is not valid"; - break; - case Message.InvalidDirectoryInLibEnvironmentPath: - msg = "Directory \"{0}\" specified in LIB environment is not valid"; - break; - case Message.LegacySearchRule: - msg = "Found assembly \"{0}\" using legacy search rule, please append '.dll' to the reference"; - break; - case Message.AssemblyLocationIgnored: - msg = "Assembly \"{0}\" is ignored as previously loaded assembly \"{1}\" has the same identity \"{2}\""; - break; - case Message.InterfaceMethodCantBeInternal: - msg = "Ignoring @ikvm.lang.Internal annotation on interface method" + Environment.NewLine + - " (\"{0}.{1}{2}\")"; - break; - case Message.NonPrimaryAssemblyReference: - msg = "Referenced assembly \"{0}\" is not the primary assembly of a shared class loader group, please reference primary assembly \"{1}\" instead"; - break; - case Message.MissingType: - msg = "Reference to type \"{0}\" claims it is defined in \"{1}\", but it could not be found"; - break; - case Message.MissingReference: - msg = "The type '{0}' is defined in an assembly that is not referenced. You must add a reference to assembly '{1}'"; - break; - case Message.DuplicateAssemblyReference: - msg = "Duplicate assembly reference \"{0}\""; - break; - case Message.UnableToResolveType: - msg = "Reference in \"{0}\" to type \"{1}\" claims it is defined in \"{2}\", but it could not be found"; - break; - case Message.StubsAreDeprecated: - msg = "Compiling stubs is deprecated. Please add a reference to assembly \"{0}\" instead."; - break; - case Message.WrongClassName: - msg = "Unable to compile \"{0}\" (wrong name: \"{1}\")"; - break; - case Message.ReflectionCallerClassRequiresCallerID: - msg = "Reflection.getCallerClass() called from non-CallerID method" + Environment.NewLine + - " (\"{0}.{1}{2}\")"; - break; - case Message.LegacyAssemblyAttributesFound: - msg = "Legacy assembly attributes container found. Please use the -assemblyattributes: option."; - break; - case Message.UnableToCreateLambdaFactory: - msg = "Unable to create static lambda factory."; - break; - case Message.UnableToCreateProxy: - msg = "Unable to create proxy \"{0}\"" + Environment.NewLine + - " (\"{1}\")"; - break; - case Message.DuplicateProxy: - msg = "Duplicate proxy \"{0}\""; - break; - case Message.MapXmlUnableToResolveOpCode: - msg = "Unable to resolve opcode in remap file: {0}"; - break; - case Message.MapXmlError: - msg = "Error in remap file: {0}"; - break; - case Message.InputFileNotFound: - msg = "Source file '{0}' not found"; - break; - case Message.UnknownFileType: - msg = "Unknown file type: {0}"; - break; - case Message.UnknownElementInMapFile: - msg = "Unknown element {0} in remap file, line {1}, column {2}"; - break; - case Message.UnknownAttributeInMapFile: - msg = "Unknown attribute {0} in remap file, line {1}, column {2}"; - break; - case Message.InvalidMemberNameInMapFile: - msg = "Invalid {0} name '{1}' in remap file in class {2}"; - break; - case Message.InvalidMemberSignatureInMapFile: - msg = "Invalid {0} signature '{3}' in remap file for {0} {1}.{2}"; - break; - case Message.InvalidPropertyNameInMapFile: - msg = "Invalid property {0} name '{3}' in remap file for property {1}.{2}"; - break; - case Message.InvalidPropertySignatureInMapFile: - msg = "Invalid property {0} signature '{3}' in remap file for property {1}.{2}"; - break; - case Message.UnknownWarning: - msg = "{0}"; - break; - case Message.CallerSensitiveOnUnsupportedMethod: - msg = "CallerSensitive annotation on unsupported method" + Environment.NewLine + - " (\"{0}.{1}{2}\")"; - break; - case Message.RemappedTypeMissingDefaultInterfaceMethod: - msg = "{0} does not implement default interface method {1}"; - break; - default: - throw new InvalidProgramException(); - } - bool error = msgId >= Message.StartErrors - || (options.warnaserror && msgId >= Message.StartWarnings) - || options.errorWarnings.ContainsKey(key) - || options.errorWarnings.ContainsKey(((int)msgId).ToString()); - Console.Error.Write("{0} IKVMC{1:D4}: ", error ? "error" : msgId < Message.StartWarnings ? "note" : "warning", (int)msgId); - if (error && Message.StartWarnings <= msgId && msgId < Message.StartErrors) - { - Console.Error.Write("Warning as Error: "); - } - Console.Error.WriteLine(msg, values); - if (options != this.rootTarget && options.path != null) - { - Console.Error.WriteLine(" (in {0})", options.path); - } - if (error) - { - if (++errorCount == 100) - { - throw new FatalCompilerErrorException(Message.MaximumErrorCountReached); - } - } + IkvmImporterInternal.IssueMessage(this, options, msgId, values); } }