From 8f281a582a6a13e7016487f65acc955b134fff58 Mon Sep 17 00:00:00 2001 From: Jerome Haltom Date: Thu, 22 Aug 2024 15:25:50 -0500 Subject: [PATCH] Replace IssueMessage with various versions of Report. It's still a bit weird how there are special calls for CompilerClassLoader. This is because its the only thing that holds the options. Problem is not all Types are part of a ClassLoader. Some are shared between class loaders. Maybe it makes sense to have some fundamental class loader for them. --- src/IKVM.CoreLib/Diagnostics/DiagnosticId.cs | 6 + .../Diagnostics}/IDiagnosticHandler.cs | 6 +- src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj | 2 +- src/IKVM.Runtime/AttributeHelper.cs | 3 +- src/IKVM.Runtime/ByteCodeHelperMethods.cs | 4 +- src/IKVM.Runtime/ClassFile.Method.cs | 6 +- src/IKVM.Runtime/JVM.Diagnostics.cs | 45 +++ src/IKVM.Runtime/JVM.Internal.cs | 2 +- src/IKVM.Runtime/LambdaMetafactory.cs | 3 +- src/IKVM.Runtime/MethodAnalyzer.cs | 26 +- .../RuntimeAssemblyClassLoader.cs | 6 +- .../RuntimeByteCodeJavaType.JavaTypeImpl.cs | 6 +- src/IKVM.Runtime/RuntimeByteCodeJavaType.cs | 12 +- .../RuntimeByteCodePropertyJavaField.cs | 7 +- src/IKVM.Runtime/RuntimeClassLoader.cs | 13 +- src/IKVM.Runtime/RuntimeClassLoaderFactory.cs | 6 +- src/IKVM.Runtime/RuntimeContext.cs | 18 +- .../RuntimeManagedByteCodeJavaType.cs | 3 +- ...gedJavaType.AttributeAnnotationJavaType.cs | 10 +- src/IKVM.Runtime/System/Index.cs | 5 +- src/IKVM.Runtime/System/Range.cs | 5 +- src/IKVM.Runtime/compiler.cs | 5 +- src/IKVM.Runtime/intrinsics.cs | 6 +- .../IkvmExporterInternal.cs | 15 +- src/IKVM.Tools.Exporter/StaticCompiler.cs | 1 + .../CompilerClassLoader.cs | 141 +++---- .../FatalCompilerErrorException.cs | 167 +------- .../IkvmImporterInternal.cs | 377 +++++------------- src/IKVM.Tools.Importer/MapXml/Ldtoken.cs | 11 +- src/IKVM.Tools.Importer/Message.cs | 135 ------- src/IKVM.Tools.Importer/Proxy.cs | 7 +- .../RuntimeImportByteCodeJavaType.cs | 3 +- src/IKVM.Tools.Importer/StaticCompiler.cs | 270 +------------ 33 files changed, 348 insertions(+), 984 deletions(-) rename src/{IKVM.Runtime => IKVM.CoreLib/Diagnostics}/IDiagnosticHandler.cs (76%) create mode 100644 src/IKVM.Runtime/JVM.Diagnostics.cs delete mode 100644 src/IKVM.Tools.Importer/Message.cs diff --git a/src/IKVM.CoreLib/Diagnostics/DiagnosticId.cs b/src/IKVM.CoreLib/Diagnostics/DiagnosticId.cs index 3b037ff57c..f5e891c72d 100644 --- a/src/IKVM.CoreLib/Diagnostics/DiagnosticId.cs +++ b/src/IKVM.CoreLib/Diagnostics/DiagnosticId.cs @@ -10,6 +10,12 @@ record struct DiagnosticId(int Value) public static implicit operator DiagnosticId(int id) => new DiagnosticId(id); + /// + public override string ToString() + { + return Value.ToString(); + } + } } diff --git a/src/IKVM.Runtime/IDiagnosticHandler.cs b/src/IKVM.CoreLib/Diagnostics/IDiagnosticHandler.cs similarity index 76% rename from src/IKVM.Runtime/IDiagnosticHandler.cs rename to src/IKVM.CoreLib/Diagnostics/IDiagnosticHandler.cs index 8db4524123..8a1f2d28fc 100644 --- a/src/IKVM.Runtime/IDiagnosticHandler.cs +++ b/src/IKVM.CoreLib/Diagnostics/IDiagnosticHandler.cs @@ -1,12 +1,10 @@ -using IKVM.CoreLib.Diagnostics; - -namespace IKVM.Runtime +namespace IKVM.CoreLib.Diagnostics { /// /// Accepts a and routes it to the appropriate source. /// - internal interface IDiagnosticHandler + interface IDiagnosticHandler { /// diff --git a/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj b/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj index 054b520bbb..c315a05186 100644 --- a/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj +++ b/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/IKVM.Runtime/AttributeHelper.cs b/src/IKVM.Runtime/AttributeHelper.cs index a8da1548c4..d38c6b8452 100644 --- a/src/IKVM.Runtime/AttributeHelper.cs +++ b/src/IKVM.Runtime/AttributeHelper.cs @@ -28,6 +28,7 @@ Jeroen Frijters using System.Runtime.CompilerServices; using IKVM.Attributes; +using IKVM.CoreLib.Diagnostics; using IKVM.ByteCode.Buffers; using IKVM.ByteCode.Decoding; using IKVM.ByteCode.Encoding; @@ -199,7 +200,7 @@ object ParseValue(RuntimeClassLoader loader, RuntimeJavaType tw, string val) } else if (tw.IsUnloadable) { - throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, tw.Name); + throw new FatalCompilerErrorException(Diagnostic.MapFileTypeNotFound.Event([tw.Name])); } else if (tw.TypeAsTBD.IsEnum) { diff --git a/src/IKVM.Runtime/ByteCodeHelperMethods.cs b/src/IKVM.Runtime/ByteCodeHelperMethods.cs index c424a33e93..8cd03badb9 100644 --- a/src/IKVM.Runtime/ByteCodeHelperMethods.cs +++ b/src/IKVM.Runtime/ByteCodeHelperMethods.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.Runtime; +using IKVM.CoreLib.Diagnostics; #if IMPORTER using IKVM.Reflection; @@ -179,7 +179,7 @@ static MethodInfo GetHelper(Type type, string method, Type[] parameters) var mi = parameters == null ? type.GetMethod(method) : type.GetMethod(method, parameters); if (mi == null) #if IMPORTER - throw new FatalCompilerErrorException(Message.RuntimeMethodMissing, method); + throw new FatalCompilerErrorException(Diagnostic.RuntimeMethodMissing.Event([method])); #else throw new InternalException("Missing ByteCodeHelper method in runtime."); #endif diff --git a/src/IKVM.Runtime/ClassFile.Method.cs b/src/IKVM.Runtime/ClassFile.Method.cs index 140e0b1d3b..c326067aaf 100644 --- a/src/IKVM.Runtime/ClassFile.Method.cs +++ b/src/IKVM.Runtime/ClassFile.Method.cs @@ -24,6 +24,8 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode; using IKVM.ByteCode.Decoding; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER using IKVM.Tools.Importer; @@ -181,7 +183,7 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt { if (classFile.IsInterface) { - classFile.context.StaticCompiler.IssueMessage(Message.InterfaceMethodCantBeInternal, classFile.Name, Name, Signature); + classFile.context.Report(Diagnostic.InterfaceMethodCantBeInternal.Event([classFile.Name, Name, Signature])); } else { @@ -206,7 +208,7 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt { if (classFile.IsInterface || IsConstructor || IsClassInitializer || IsPrivate || IsStatic == false) { - classFile.context.StaticCompiler.IssueMessage(Message.ModuleInitializerMethodRequirements, classFile.Name, Name, Signature); + classFile.context.Report(Diagnostic.ModuleInitializerMethodRequirements.Event([classFile.Name, Name, Signature])); } else { diff --git a/src/IKVM.Runtime/JVM.Diagnostics.cs b/src/IKVM.Runtime/JVM.Diagnostics.cs new file mode 100644 index 0000000000..0236e1c202 --- /dev/null +++ b/src/IKVM.Runtime/JVM.Diagnostics.cs @@ -0,0 +1,45 @@ +using IKVM.CoreLib.Diagnostics; + +namespace IKVM.Runtime +{ + +#if FIRST_PASS == false && IMPORTER == false && EXPORTER == false + + static partial class JVM + { + + /// + /// Handles diagnostic events during runtime. + /// + class DiagnosticHandler : IDiagnosticHandler + { + + public void Report(in DiagnosticEvent evnt) + { + switch (evnt.Diagnostic.Level) + { + case DiagnosticLevel.Trace: + break; + case DiagnosticLevel.Informational: + break; + case DiagnosticLevel.Warning: + break; + case DiagnosticLevel.Error: + break; + case DiagnosticLevel.Fatal: + break; + } + } + + } + + /// + /// Gets the JVM diagnostic handler. + /// + static IDiagnosticHandler Diagnostics { get; } = new DiagnosticHandler(); + + } + +#endif + +} diff --git a/src/IKVM.Runtime/JVM.Internal.cs b/src/IKVM.Runtime/JVM.Internal.cs index 3527d5fb2e..ca1cd7bfdb 100644 --- a/src/IKVM.Runtime/JVM.Internal.cs +++ b/src/IKVM.Runtime/JVM.Internal.cs @@ -34,7 +34,7 @@ internal static class Internal #if FIRST_PASS == false && IMPORTER == false && EXPORTER == false internal static readonly RuntimeContextOptions contextOptions = new RuntimeContextOptions(); - internal static readonly RuntimeContext context = new RuntimeContext(contextOptions, new Resolver(), false); + internal static readonly RuntimeContext context = new RuntimeContext(contextOptions, Diagnostics, new Resolver(), false); internal static readonly VfsTable vfs = VfsTable.BuildDefaultTable(new VfsRuntimeContext(context), Properties.HomePath); internal static readonly Lazy systemThreadGroup = new Lazy(() => ThreadGroupAccessor.Init()); internal static readonly Lazy mainThreadGroup = new Lazy(() => ThreadGroupAccessor.Init(null, SystemThreadGroup, "main")); diff --git a/src/IKVM.Runtime/LambdaMetafactory.cs b/src/IKVM.Runtime/LambdaMetafactory.cs index c02667c77f..2c13c79d28 100644 --- a/src/IKVM.Runtime/LambdaMetafactory.cs +++ b/src/IKVM.Runtime/LambdaMetafactory.cs @@ -26,6 +26,7 @@ Jeroen Frijters using System.Diagnostics; using IKVM.ByteCode; +using IKVM.CoreLib.Diagnostics; #if IMPORTER using IKVM.Reflection; @@ -60,7 +61,7 @@ internal static bool Emit(RuntimeByteCodeJavaType.FinishContext context, ClassFi #if IMPORTER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) { - context.Context.StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); + context.Context.Report(Diagnostic.UnableToCreateLambdaFactory.Event([])); } #endif return false; diff --git a/src/IKVM.Runtime/MethodAnalyzer.cs b/src/IKVM.Runtime/MethodAnalyzer.cs index 9a72cb836b..65f9802d9f 100644 --- a/src/IKVM.Runtime/MethodAnalyzer.cs +++ b/src/IKVM.Runtime/MethodAnalyzer.cs @@ -26,6 +26,8 @@ Jeroen Frijters using System.Diagnostics; using IKVM.ByteCode; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER using IKVM.Tools.Importer; @@ -2484,38 +2486,38 @@ private void SetHardError(RuntimeClassLoader classLoader, ref ClassFile.Method.I { string text = string.Format(message, args); #if IMPORTER - Message msg; + Diagnostic msg; switch (hardError) { case HardError.NoClassDefFoundError: - msg = Message.EmittedNoClassDefFoundError; + msg = Diagnostic.EmittedNoClassDefFoundError; break; case HardError.IllegalAccessError: - msg = Message.EmittedIllegalAccessError; + msg = Diagnostic.EmittedIllegalAccessError; break; case HardError.InstantiationError: - msg = Message.EmittedIllegalAccessError; + msg = Diagnostic.EmittedIllegalAccessError; break; case HardError.IncompatibleClassChangeError: case HardError.IllegalAccessException: - msg = Message.EmittedIncompatibleClassChangeError; + msg = Diagnostic.EmittedIncompatibleClassChangeError; break; case HardError.NoSuchFieldError: - msg = Message.EmittedNoSuchFieldError; + msg = Diagnostic.EmittedNoSuchFieldError; break; case HardError.AbstractMethodError: - msg = Message.EmittedAbstractMethodError; + msg = Diagnostic.EmittedAbstractMethodError; break; case HardError.NoSuchMethodError: - msg = Message.EmittedNoSuchMethodError; + msg = Diagnostic.EmittedNoSuchMethodError; break; case HardError.LinkageError: - msg = Message.EmittedLinkageError; + msg = Diagnostic.EmittedLinkageError; break; default: throw new InvalidOperationException(); } - classLoader.IssueMessage(msg, classFile.Name + "." + method.Name + method.Signature, text); + classLoader.Report(msg.Event([classFile.Name + "." + method.Name + method.Signature, text])); #endif instruction.SetHardError(hardError, AllocErrorMessage(text)); } @@ -2868,7 +2870,7 @@ private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, RuntimeJ #if NETFRAMEWORK if (cpi.GetRetType() != mw.ReturnType && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) #else - if (cpi.GetRetType() != mw.ReturnType && cpi.GetRetType().Name != mw.ReturnType.Name && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) + if (cpi.GetRetType() != mw.ReturnType && cpi.GetRetType().Name != mw.ReturnType.Name && !cpi.GetRetType().IsUnloadable && !mw.ReturnType.IsUnloadable) #endif { #if IMPORTER @@ -2883,7 +2885,7 @@ private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, RuntimeJ #if NETFRAMEWORK if (here[i] != there[i] && !here[i].IsUnloadable && !there[i].IsUnloadable) #else - if (here[i] != there[i] && here[i].Name != there[i].Name && !here[i].IsUnloadable && !there[i].IsUnloadable) + if (here[i] != there[i] && here[i].Name != there[i].Name && !here[i].IsUnloadable && !there[i].IsUnloadable) #endif { #if IMPORTER diff --git a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs index 3cba3e77d8..a49fb5dee0 100644 --- a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs +++ b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs @@ -27,12 +27,12 @@ Jeroen Frijters using System.Diagnostics; using System.Threading; using System.Runtime.Serialization; +using System.Runtime.CompilerServices; +using IKVM.CoreLib.Diagnostics; using IKVM.Attributes; using IKVM.Runtime.Syntax; -using System.Runtime.CompilerServices; - #if IMPORTER || EXPORTER using IKVM.Reflection; @@ -715,7 +715,7 @@ internal virtual RuntimeJavaType GetJavaTypeFromAssemblyType(Type type) if (javaType.TypeAsTBD != type && (!javaType.IsRemapped || javaType.TypeAsBaseType != type)) { #if IMPORTER - throw new FatalCompilerErrorException(Message.AssemblyContainsDuplicateClassNames, type.FullName, javaType.TypeAsTBD.FullName, javaType.Name, type.Assembly.FullName); + throw new FatalCompilerErrorException(Diagnostic.AssemblyContainsDuplicateClassNames.Event([type.FullName, javaType.TypeAsTBD.FullName, javaType.Name, type.Assembly.FullName])); #else throw new InternalException($"\nType \"{type.FullName}\" and \"{javaType.TypeAsTBD.FullName}\" both map to the same name \"{javaType.Name}\"."); #endif diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs index ea07b61031..f8efbb36b1 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs @@ -24,9 +24,11 @@ Jeroen Frijters using System; using System.Collections.Generic; using System.Diagnostics; +using System.Collections.Concurrent; using IKVM.Attributes; -using System.Collections.Concurrent; + +using IKVM.CoreLib.Diagnostics; #if IMPORTER using IKVM.Reflection; @@ -225,7 +227,7 @@ bool SupportsCallerID(ClassFile.Method method) { // If we end up here, we either have to add support or add them to the white-list in the above clause // to allow them to fall back to dynamic stack walking. - wrapper.Context.StaticCompiler.IssueMessage(Message.CallerSensitiveOnUnsupportedMethod, classFile.Name, method.Name, method.Signature); + wrapper.Context.Report(Diagnostic.CallerSensitiveOnUnsupportedMethod.Event([classFile.Name, method.Name, method.Signature])); return false; } } diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs index 6e0e3f7b95..c1798f518e 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs @@ -26,6 +26,8 @@ Jeroen Frijters using System.Diagnostics; using IKVM.Attributes; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER using IKVM.Reflection; @@ -97,10 +99,10 @@ private static void CheckMissing(RuntimeJavaType prev, RuntimeJavaType tw) Type mt = ReflectUtil.GetMissingType(missing.MissingType); if (mt.Assembly.__IsMissing) { - throw new FatalCompilerErrorException(Message.MissingBaseTypeReference, mt.FullName, mt.Assembly.FullName); + throw new FatalCompilerErrorException(Diagnostic.MissingBaseTypeReference.Event([mt.FullName, mt.Assembly.FullName])); } - throw new FatalCompilerErrorException(Message.MissingBaseType, mt.FullName, mt.Assembly.FullName, - prev.TypeAsBaseType.FullName, prev.TypeAsBaseType.Module.Name); + + throw new FatalCompilerErrorException(Diagnostic.MissingBaseType.Event([mt.FullName, mt.Assembly.FullName, prev.TypeAsBaseType.FullName, prev.TypeAsBaseType.Module.Name])); } foreach (RuntimeJavaType iface in tw.Interfaces) { @@ -1064,10 +1066,10 @@ internal void EmitLevel4Warning(HardError error, string message) switch (error) { case HardError.AbstractMethodError: - GetClassLoader().IssueMessage(Message.EmittedAbstractMethodError, this.Name, message); + GetClassLoader().Report(Diagnostic.EmittedAbstractMethodError.Event([this.Name, message])); break; case HardError.IncompatibleClassChangeError: - GetClassLoader().IssueMessage(Message.EmittedIncompatibleClassChangeError, this.Name, message); + GetClassLoader().Report(Diagnostic.EmittedIncompatibleClassChangeError.Event([this.Name, message])); break; default: throw new InvalidOperationException(); diff --git a/src/IKVM.Runtime/RuntimeByteCodePropertyJavaField.cs b/src/IKVM.Runtime/RuntimeByteCodePropertyJavaField.cs index caf7fe431f..2837d195bf 100644 --- a/src/IKVM.Runtime/RuntimeByteCodePropertyJavaField.cs +++ b/src/IKVM.Runtime/RuntimeByteCodePropertyJavaField.cs @@ -23,11 +23,14 @@ Jeroen Frijters */ using System; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; using Type = IKVM.Reflection.Type; + #else using System.Reflection; using System.Reflection.Emit; @@ -141,7 +144,7 @@ protected override void EmitGetImpl(CodeEmitter ilgen) internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, RuntimeJavaType type, RuntimeJavaMember member) { #if IMPORTER - type.Context.StaticCompiler.IssueMessage(Message.EmittedNoSuchMethodError, "", member.DeclaringType.Name + "." + member.Name + member.Signature); + type.Context.StaticCompiler.Report(Diagnostic.EmittedNoSuchMethodError.Event(["", member.DeclaringType.Name + "." + member.Name + member.Signature])); #endif // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); @@ -186,7 +189,7 @@ protected override void EmitSetImpl(CodeEmitter ilgen) internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, RuntimeJavaMember member) { #if IMPORTER - member.DeclaringType.Context.StaticCompiler.IssueMessage(Message.EmittedNoSuchMethodError, "", member.DeclaringType.Name + "." + member.Name + member.Signature); + member.DeclaringType.Context.Report(Diagnostic.EmittedNoSuchMethodError.Event(["", member.DeclaringType.Name + "." + member.Name + member.Signature])); #endif // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); diff --git a/src/IKVM.Runtime/RuntimeClassLoader.cs b/src/IKVM.Runtime/RuntimeClassLoader.cs index 044b4189a5..0e6a78ca76 100644 --- a/src/IKVM.Runtime/RuntimeClassLoader.cs +++ b/src/IKVM.Runtime/RuntimeClassLoader.cs @@ -27,6 +27,9 @@ Jeroen Frijters using System.Diagnostics; using System.Threading; +using IKVM.Runtime.Accessors.Java.Lang; +using IKVM.CoreLib.Diagnostics; + #if NETCOREAPP using System.Runtime.Loader; #endif @@ -40,10 +43,6 @@ Jeroen Frijters using System.Reflection; using ProtectionDomain = java.security.ProtectionDomain; - -using IKVM.Runtime.Accessors.Java.Lang; - -using System.Text; #endif #if IMPORTER @@ -371,7 +370,7 @@ internal RuntimeJavaType LoadClass(string name, LoadMode mode) #if IMPORTER if (!(name.Length > 1 && name[0] == '[') && ((mode & LoadMode.WarnClassNotFound) != 0) || WarningLevelHigh) - IssueMessage(Message.ClassNotFound, name); + Context.Report(Diagnostic.ClassNotFound.Event([name])); #else @@ -943,11 +942,11 @@ internal static RuntimeClassLoader FromCallerID(ikvm.@internal.CallerID callerID #endif #if IMPORTER - internal virtual void IssueMessage(Message msgId, params string[] values) + internal virtual void Report(in DiagnosticEvent evt) { // it's not ideal when we end up here (because it means we're emitting a warning that is not associated with a specific output target), // but it happens when we're decoding something in a referenced assembly that either doesn't make sense or contains an unloadable type - Context.StaticCompiler.IssueMessage(msgId, values); + Context.StaticCompiler.Report(evt); } #endif diff --git a/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs b/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs index e50f60cba2..0fe7aa28ea 100644 --- a/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs +++ b/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; -using IKVM.Runtime; +using IKVM.CoreLib.Diagnostics; #if NETCOREAPP using System.Runtime.Loader; @@ -111,7 +111,7 @@ internal void LoadRemappedTypes() else { #if IMPORTER - throw new FatalCompilerErrorException(Message.CoreClassesMissing); + throw new FatalCompilerErrorException(Diagnostic.CoreClassesMissing.Event([])); #else throw new InternalException("Failed to find core classes in core library."); #endif @@ -292,7 +292,7 @@ internal RuntimeJavaType LoadClassCritical(string name) #if IMPORTER var wrapper = GetBootstrapClassLoader().TryLoadClassByName(name); if (wrapper == null) - throw new FatalCompilerErrorException(Message.CriticalClassNotFound, name); + throw new FatalCompilerErrorException(Diagnostic.CriticalClassNotFound.Event([name])); return wrapper; #else diff --git a/src/IKVM.Runtime/RuntimeContext.cs b/src/IKVM.Runtime/RuntimeContext.cs index fd1dea7a1c..218cc80cf6 100644 --- a/src/IKVM.Runtime/RuntimeContext.cs +++ b/src/IKVM.Runtime/RuntimeContext.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Concurrent; +using IKVM.CoreLib.Diagnostics; + + #if IMPORTER using IKVM.Tools.Importer; #endif @@ -23,6 +26,7 @@ class RuntimeContext { readonly RuntimeContextOptions options; + readonly IDiagnosticHandler diagnostics; readonly IManagedTypeResolver resolver; readonly bool bootstrap; readonly ConcurrentDictionary singletons = new(); @@ -72,11 +76,13 @@ class RuntimeContext /// Initializes a new instance. /// /// + /// /// /// - public RuntimeContext(RuntimeContextOptions options, IManagedTypeResolver resolver, bool bootstrap, StaticCompiler staticCompiler) + public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, IManagedTypeResolver resolver, bool bootstrap, StaticCompiler staticCompiler) { this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); this.resolver = resolver ?? throw new ArgumentNullException(nameof(resolver)); this.bootstrap = bootstrap; this.staticCompiler = staticCompiler; @@ -88,11 +94,13 @@ public RuntimeContext(RuntimeContextOptions options, IManagedTypeResolver resolv /// Initializes a new instance. /// /// + /// /// /// - public RuntimeContext(RuntimeContextOptions options, IManagedTypeResolver resolver, bool bootstrap) + public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, IManagedTypeResolver resolver, bool bootstrap) { this.options = options ?? throw new ArgumentNullException(nameof(options)); + this.diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); this.resolver = resolver ?? throw new ArgumentNullException(nameof(resolver)); this.bootstrap = bootstrap; } @@ -274,6 +282,12 @@ T GetOrCreateSingleton(ref T value, Func create) #endif + /// + /// Reports a . + /// + /// + public void Report(in DiagnosticEvent evt) => diagnostics.Report(evt); + } } diff --git a/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs b/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs index 5e39d3bafb..46d4fab64e 100644 --- a/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs +++ b/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs @@ -25,6 +25,7 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; +using IKVM.CoreLib.Diagnostics; using IKVM.Attributes; using IKVM.Runtime.Syntax; using IKVM.ByteCode; @@ -317,7 +318,7 @@ private RuntimeJavaType[] GetInterfaces() if (interfaceWrappers[i] == null) { #if IMPORTER - throw new FatalCompilerErrorException(Message.UnableToResolveInterface, interfaceNames[i], this); + throw new FatalCompilerErrorException(Diagnostic.UnableToResolveInterface.Event([interfaceNames[i], this])); #else throw new InternalException($"Unable to resolve interface {interfaceNames[i]} on type {this}"); #endif diff --git a/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs b/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs index 56b62ea80c..293afe2008 100644 --- a/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs +++ b/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs @@ -24,12 +24,14 @@ Jeroen Frijters using System; using System.Collections.Generic; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; using Type = IKVM.Reflection.Type; -using System.Net.Mime; + #else using System.Reflection; using System.Reflection.Emit; @@ -543,7 +545,7 @@ internal override void Apply(RuntimeClassLoader loader, TypeBuilder tb, object a // we have to handle this explicitly, because if we apply an illegal StructLayoutAttribute, // TypeBuilder.CreateType() will later on throw an exception. #if IMPORTER - loader.IssueMessage(Message.IgnoredCustomAttribute, type.FullName, "Type '" + tb.FullName + "' does not extend cli.System.Object"); + loader.Report(Diagnostic.IgnoredCustomAttribute.Event([type.FullName, "Type '" + tb.FullName + "' does not extend cli.System.Object"])); #else Tracer.Error(Tracer.Runtime, "StructLayoutAttribute cannot be applied to {0}, because it does not directly extend cli.System.Object", tb.FullName); #endif @@ -590,7 +592,7 @@ internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, obje } else { - loader.IssueMessage(Message.InvalidCustomAttribute, type.FullName, "The version '" + str + "' is invalid."); + loader.Report(Diagnostic.InvalidCustomAttribute.Event([type.FullName, "The version '" + str + "' is invalid."])); } } else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyCultureAttribute).FullName)) @@ -605,7 +607,7 @@ internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, obje || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyFileAttribute).FullName) || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyNameAttribute).FullName)) { - loader.IssueMessage(Message.IgnoredCustomAttribute, type.FullName, "Please use the corresponding compiler switch."); + loader.Report(Diagnostic.IgnoredCustomAttribute.Event([type.FullName, "Please use the corresponding compiler switch."])); } else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyAlgorithmIdAttribute).FullName)) { diff --git a/src/IKVM.Runtime/System/Index.cs b/src/IKVM.Runtime/System/Index.cs index 566d892d32..f29a3ab473 100644 --- a/src/IKVM.Runtime/System/Index.cs +++ b/src/IKVM.Runtime/System/Index.cs @@ -3,9 +3,6 @@ // See the LICENSE file in the project root for more information. #if NETSTANDARD2_1 || NET -using System.Runtime.CompilerServices; - -[assembly: TypeForwardedTo(typeof(System.Index))] #else using System.Runtime.CompilerServices; @@ -19,7 +16,7 @@ namespace System; /// int lastElement = someArray[^1]; // lastElement = 5 /// /// -public readonly struct Index : IEquatable +readonly struct Index : IEquatable { private readonly int _value; diff --git a/src/IKVM.Runtime/System/Range.cs b/src/IKVM.Runtime/System/Range.cs index 7d536244c0..eeda47db4d 100644 --- a/src/IKVM.Runtime/System/Range.cs +++ b/src/IKVM.Runtime/System/Range.cs @@ -3,9 +3,6 @@ // See the LICENSE file in the project root for more information. #if NETSTANDARD2_1 || NET -using System.Runtime.CompilerServices; - -[assembly: TypeForwardedTo(typeof(global::System.Range))] #else using System.Runtime.CompilerServices; @@ -20,7 +17,7 @@ namespace System; /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } /// /// -public readonly struct Range : IEquatable +readonly struct Range : IEquatable { /// Represent the inclusive start index of the Range. public Index Start { get; } diff --git a/src/IKVM.Runtime/compiler.cs b/src/IKVM.Runtime/compiler.cs index d141799c86..5c8b1addce 100644 --- a/src/IKVM.Runtime/compiler.cs +++ b/src/IKVM.Runtime/compiler.cs @@ -26,6 +26,7 @@ Jeroen Frijters using System.Diagnostics; using System.Diagnostics.SymbolStore; +using IKVM.CoreLib.Diagnostics; using IKVM.Attributes; using IKVM.ByteCode; @@ -608,7 +609,7 @@ internal static void Compile(RuntimeByteCodeJavaType.FinishContext finish, Runti catch (VerifyError x) { #if IMPORTER - classLoader.IssueMessage(Message.EmittedVerificationError, classFile.Name + "." + m.Name + m.Signature, x.Message); + classLoader.Report(Diagnostic.EmittedVerificationError.Event([ classFile.Name + "." + m.Name + m.Signature, x.Message])); #endif Tracer.Error(Tracer.Verifier, x.ToString()); clazz.SetHasVerifyError(); @@ -620,7 +621,7 @@ internal static void Compile(RuntimeByteCodeJavaType.FinishContext finish, Runti catch (ClassFormatError x) { #if IMPORTER - classLoader.IssueMessage(Message.EmittedClassFormatError, classFile.Name + "." + m.Name + m.Signature, x.Message); + classLoader.Report(Diagnostic.EmittedClassFormatError.Event([ classFile.Name + "." + m.Name + m.Signature, x.Message])); #endif Tracer.Error(Tracer.Verifier, x.ToString()); clazz.SetHasClassFormatError(); diff --git a/src/IKVM.Runtime/intrinsics.cs b/src/IKVM.Runtime/intrinsics.cs index 6a197ef6b9..7133df1498 100644 --- a/src/IKVM.Runtime/intrinsics.cs +++ b/src/IKVM.Runtime/intrinsics.cs @@ -25,6 +25,8 @@ Jeroen Frijters using System; using System.Collections.Generic; +using IKVM.CoreLib.Diagnostics; + #if IMPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; @@ -353,7 +355,7 @@ static bool Reflection_getCallerClass(EmitIntrinsicContext eic) } else { - eic.Context.TypeWrapper.Context.StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature); + eic.Context.TypeWrapper.Context.Report(Diagnostic.ReflectionCallerClassRequiresCallerID.Event([eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature])); } return false; } @@ -372,7 +374,7 @@ private static bool CallerID_getCallerID(EmitIntrinsicContext eic) } else { - throw new FatalCompilerErrorException(Message.CallerIDRequiresHasCallerIDAnnotation); + throw new FatalCompilerErrorException(Diagnostic.CallerIDRequiresHasCallerIDAnnotation.Event([])); } } diff --git a/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs b/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs index 5c183d22fb..20e79c2c97 100644 --- a/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs +++ b/src/IKVM.Tools.Exporter/IkvmExporterInternal.cs @@ -7,6 +7,7 @@ using System.Reflection.PortableExecutable; using System.Security.Cryptography.Xml; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Runtime; using IKVM.Tools.Importer; @@ -22,6 +23,16 @@ namespace IKVM.Tools.Exporter static class IkvmExporterInternal { + class DiagnosticHandler : IDiagnosticHandler + { + + public void Report(in DiagnosticEvent evnt) + { + throw new NotImplementedException(); + } + + } + class ManagedResolver : IManagedTypeResolver { @@ -191,7 +202,7 @@ public static int Execute(IkvmExporterOptions options) } compiler = new StaticCompiler(universe, assemblyResolver, runtimeAssembly); - context = new RuntimeContext(new RuntimeContextOptions(), new ManagedResolver(compiler, null), true, compiler); + context = new RuntimeContext(new RuntimeContextOptions(), new DiagnosticHandler(), new ManagedResolver(compiler, null), true, compiler); context.ClassLoaderFactory.SetBootstrapClassLoader(new RuntimeBootstrapClassLoader(context)); } else @@ -218,7 +229,7 @@ public static int Execute(IkvmExporterOptions options) } compiler = new StaticCompiler(universe, assemblyResolver, runtimeAssembly); - context = new RuntimeContext(new RuntimeContextOptions(), new ManagedResolver(compiler, baseAssembly), false, compiler); + context = new RuntimeContext(new RuntimeContextOptions(), new DiagnosticHandler(), new ManagedResolver(compiler, baseAssembly), false, compiler); } if (context.AttributeHelper.IsJavaModule(assembly.ManifestModule)) diff --git a/src/IKVM.Tools.Exporter/StaticCompiler.cs b/src/IKVM.Tools.Exporter/StaticCompiler.cs index 57f27fbfd1..0fe5e51b09 100644 --- a/src/IKVM.Tools.Exporter/StaticCompiler.cs +++ b/src/IKVM.Tools.Exporter/StaticCompiler.cs @@ -23,6 +23,7 @@ Jeroen Frijters */ using System; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Tools.Importer; diff --git a/src/IKVM.Tools.Importer/CompilerClassLoader.cs b/src/IKVM.Tools.Importer/CompilerClassLoader.cs index b03d8b4388..5ed1268498 100644 --- a/src/IKVM.Tools.Importer/CompilerClassLoader.cs +++ b/src/IKVM.Tools.Importer/CompilerClassLoader.cs @@ -35,6 +35,7 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -292,27 +293,27 @@ RuntimeJavaType GetTypeWrapperCompilerHook(string name) } catch (UnsupportedClassVersionException e) { - Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); - Context.StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, e.Message); + Context.StaticCompiler.SuppressWarning(options, Diagnostic.ClassNotFound, name); + Context.StaticCompiler.Report(options, Diagnostic.ClassFormatError.Event([name, e.Message])); return null; } catch (ByteCodeException e) { - Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); - Context.StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, e.Message); + Context.StaticCompiler.SuppressWarning(options, Diagnostic.ClassNotFound, name); + Context.StaticCompiler.Report(options, Diagnostic.ClassFormatError.Event([name, e.Message])); return null; } catch (ClassFormatError e) { - Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); - Context.StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, e.Message); + Context.StaticCompiler.SuppressWarning(options, Diagnostic.ClassNotFound, name); + Context.StaticCompiler.Report(options, Diagnostic.ClassFormatError.Event([name, e.Message])); return null; } if (f.Name != name) { - Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); - Context.StaticCompiler.IssueMessage(options, Message.WrongClassName, name, f.Name); + Context.StaticCompiler.SuppressWarning(options, Diagnostic.ClassNotFound, name); + Context.StaticCompiler.Report(options, Diagnostic.WrongClassName.Event([name, f.Name])); return null; } @@ -396,31 +397,31 @@ RuntimeJavaType GetTypeWrapperCompilerHook(string name) } catch (ClassFormatError x) { - Context.StaticCompiler.IssueMessage(options, Message.ClassFormatError, name, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.ClassFormatError.Event([name, x.Message])); } catch (IllegalAccessError x) { - Context.StaticCompiler.IssueMessage(options, Message.IllegalAccessError, name, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.IllegalAccessError.Event([name, x.Message])); } catch (VerifyError x) { - Context.StaticCompiler.IssueMessage(options, Message.VerificationError, name, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.VerificationError.Event([name, x.Message])); } catch (NoClassDefFoundError x) { if ((options.codegenoptions & CodeGenOptions.DisableDynamicBinding) != 0) { - Context.StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.NoClassDefFoundError.Event([name, x.Message])); } - Context.StaticCompiler.IssueMessage(options, Message.ClassNotFound, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.ClassNotFound.Event([x.Message])); } catch (RetargetableJavaException x) { - Context.StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message); + Context.StaticCompiler.Report(options, Diagnostic.GenericUnableToCompileError.Event([name, x.GetType().Name, x.Message])); } - Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name); + Context.StaticCompiler.SuppressWarning(options, Diagnostic.ClassNotFound, name); return null; } else @@ -626,11 +627,11 @@ void Save() } catch (IOException x) { - throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorWritingFile.Event([GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message])); } catch (UnauthorizedAccessException x) { - throw new FatalCompilerErrorException(Message.ErrorWritingFile, GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorWritingFile.Event([GetTypeWrapperFactory().ModuleBuilder.FullyQualifiedName, x.Message])); } } else @@ -643,11 +644,11 @@ void Save() } catch (IOException x) { - throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorWritingFile.Event([Path.Combine(assemblyDir, assemblyFile), x.Message])); } catch (UnauthorizedAccessException x) { - throw new FatalCompilerErrorException(Message.ErrorWritingFile, Path.Combine(assemblyDir, assemblyFile), x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorWritingFile.Event([Path.Combine(assemblyDir, assemblyFile), x.Message])); } } } @@ -1013,7 +1014,7 @@ internal void LoadInterfaces(IKVM.Tools.Importer.MapXml.Class c) { if (GetMethodWrapper(mw.Name, mw.Signature, true) == null) { - DeclaringTypeWrapper.Context.StaticCompiler.IssueMessage(Message.RemappedTypeMissingDefaultInterfaceMethod, Name, iface.Name + "." + mw.Name + mw.Signature); + DeclaringTypeWrapper.Context.Report(Diagnostic.RemappedTypeMissingDefaultInterfaceMethod.Event([Name, iface.Name + "." + mw.Name + mw.Signature])); } } } @@ -2155,8 +2156,9 @@ internal void EmitRemappedTypes() { if (classes.ContainsKey(c.Name)) { - Context.StaticCompiler.IssueMessage(Message.DuplicateClassName, c.Name); + Context.StaticCompiler.Report(options, Diagnostic.DuplicateClassName.Event([c.Name])); } + remapped.Add(c.Name, new RemapperTypeWrapper(Context, this, c, map)); hasRemappedTypes = true; } @@ -2486,22 +2488,19 @@ internal static int Compile(RuntimeContext context, StaticCompiler compiler, str { // runtime assembly is required if (compiler.runtimeAssembly == null) - throw new FatalCompilerErrorException(Message.RuntimeNotFound); + throw new FatalCompilerErrorException(Diagnostic.RuntimeNotFound.Event([])); // some unknown error - throw new FatalCompilerErrorException(Message.FileNotFound); + throw new FatalCompilerErrorException(Diagnostic.FileNotFound.Event([])); } Tracer.Info(Tracer.Compiler, "Loaded runtime assembly: {0}", compiler.runtimeAssembly.FullName); - List loaders = new List(); - foreach (CompilerOptions options in optionsList) + var loaders = new List(); + foreach (var options in optionsList) { - CompilerClassLoader loader = null; - int rc = CreateCompiler(context, compiler, options, out loader); + int rc = CreateCompiler(context, compiler, options, out var loader); if (rc != 0) - { return rc; - } loaders.Add(loader); options.sharedclassloader?.Add(loader); @@ -2520,8 +2519,7 @@ internal static int Compile(RuntimeContext context, StaticCompiler compiler, str { if (loader.options.sharedclassloader != null) { - Type mainAssemblyType; - if (!mainAssemblyTypes.TryGetValue(loader.options.sharedclassloader[0], out mainAssemblyType)) + if (!mainAssemblyTypes.TryGetValue(loader.options.sharedclassloader[0], out var mainAssemblyType)) { var tb = loader.options.sharedclassloader[0].GetTypeWrapperFactory().ModuleBuilder.DefineType("__", TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.SpecialName); loader.Context.AttributeHelper.HideFromJava(tb); @@ -2533,40 +2531,36 @@ internal static int Compile(RuntimeContext context, StaticCompiler compiler, str ((AssemblyBuilder)loader.GetTypeWrapperFactory().ModuleBuilder.Assembly).__AddTypeForwarder(mainAssemblyType); } } + loader.CompilePass1(); } - foreach (CompilerClassLoader loader in loaders) + foreach (var loader in loaders) { loader.CompilePass2(); } if (context.Bootstrap) - foreach (CompilerClassLoader loader in loaders) + foreach (var loader in loaders) loader.EmitRemappedTypes2ndPass(); - foreach (CompilerClassLoader loader in loaders) + foreach (var loader in loaders) { int rc = loader.CompilePass3(); if (rc != 0) - { return rc; - } } Tracer.Info(Tracer.Compiler, "CompilerClassLoader.Save..."); - foreach (CompilerClassLoader loader in loaders) - { + foreach (var loader in loaders) loader.PrepareSave(); - } + if (compiler.errorCount > 0) - { return 1; - } + foreach (CompilerClassLoader loader in loaders) - { loader.Save(); - } + return compiler.errorCount == 0 ? 0 : 1; } @@ -2592,14 +2586,14 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi // TODO we really should support binding redirects here to allow different revisions to be mixed if (asmref.FullName != runtimeAssemblyName.FullName) { - throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName); + throw new FatalCompilerErrorException(Diagnostic.RuntimeMismatch.Event([reference.Location, runtimeAssemblyName.FullName, asmref.FullName])); } } else { if (asmref.GetPublicKeyToken() != null && asmref.GetPublicKeyToken().Length != 0) { - throw new FatalCompilerErrorException(Message.RuntimeMismatch, reference.Location, runtimeAssemblyName.FullName, asmref.FullName); + throw new FatalCompilerErrorException(Diagnostic.RuntimeMismatch.Event([reference.Location, runtimeAssemblyName.FullName, asmref.FullName])); } } } @@ -2625,7 +2619,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi string className = name.Substring(0, name.Length - 6).Replace('/', '.'); if (h.ContainsKey(className)) { - compiler.IssueMessage(Message.DuplicateClassName, className); + compiler.Report(options, Diagnostic.DuplicateClassName.Event([className])); Jar.Item itemRef = h[className]; if ((options.classesJar != -1 && itemRef.Jar == options.jars[options.classesJar]) || jar != itemRef.Jar) { @@ -2663,7 +2657,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi // HACK remove "assembly" type that exists only as a placeholder for assembly attributes h.Remove(f.Name); assemblyType.Remove(); - compiler.IssueMessage(Message.LegacyAssemblyAttributesFound); + compiler.Report(options, Diagnostic.LegacyAssemblyAttributesFound.Event([])); } } catch (ByteCodeException) @@ -2691,7 +2685,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi { if (m.IsPublic && m.IsStatic && m.Name == "main" && m.Signature == "([Ljava.lang.String;)V") { - compiler.IssueMessage(Message.MainMethodFound, f.Name); + compiler.Report(options, Diagnostic.MainMethodFound.Event([f.Name])); options.mainClass = f.Name; goto break_outer; } @@ -2713,12 +2707,12 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi if (options.target != PEFileKinds.Dll && options.mainClass == null) { - throw new FatalCompilerErrorException(Message.ExeRequiresMainClass); + throw new FatalCompilerErrorException(Diagnostic.ExeRequiresMainClass.Event([])); } if (options.target == PEFileKinds.Dll && options.props.Count != 0) { - throw new FatalCompilerErrorException(Message.PropertiesRequireExe); + throw new FatalCompilerErrorException(Diagnostic.PropertiesRequireExe.Event([])); } if (options.path == null) @@ -2738,14 +2732,14 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi { options.path = IkvmImporterInternal.GetFileInfo(options.assembly + ".exe"); } - compiler.IssueMessage(Message.OutputFileIs, options.path.ToString()); + compiler.Report(options, Diagnostic.OutputFileIs.Event([options.path.ToString()])); } if (options.targetIsModule) { if (options.classLoader != null) { - throw new FatalCompilerErrorException(Message.ModuleCannotHaveClassLoader); + throw new FatalCompilerErrorException(Diagnostic.ModuleCannotHaveClassLoader.Event([])); } // TODO if we're overwriting a user specified assembly name, we need to emit a warning options.assembly = options.path.Name; @@ -2761,7 +2755,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi var acl = context.AssemblyClassLoaderFactory.FromAssembly(references[i]); if (referencedAssemblies.Contains(acl)) - compiler.IssueMessage(options, Message.DuplicateAssemblyReference, acl.MainAssembly.FullName); + compiler.Report(options, Diagnostic.DuplicateAssemblyReference.Event([acl.MainAssembly.FullName])); referencedAssemblies.Add(acl); } @@ -2781,7 +2775,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi } catch (Exception e) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, options.remapfile, e.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([options.remapfile, e.Message])); } try @@ -2794,7 +2788,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi } catch (MapXml.MapXmlException x) { - throw new FatalCompilerErrorException(Message.ErrorParsingMapFile, options.remapfile, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorParsingMapFile.Event([options.remapfile, x.Message])); } if (loader.ValidateAndSetMap(map) == false) @@ -2838,7 +2832,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi if (compiler.baseAssembly == null) { - throw new FatalCompilerErrorException(Message.BootstrapClassesMissing); + throw new FatalCompilerErrorException(Diagnostic.BootstrapClassesMissing.Event([])); } // we need to scan again for remapped types, now that we've loaded the core library @@ -2853,7 +2847,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, Compi if ((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed) { - throw new FatalCompilerErrorException(Message.StrongNameRequiresStrongNamedRefs); + throw new FatalCompilerErrorException(Diagnostic.StrongNameRequiresStrongNamedRefs.Event([])); } if (loader.map != null) @@ -2919,7 +2913,7 @@ void CompilePass1() if (loader != this) { if (loader is RuntimeAssemblyClassLoader) - Context.StaticCompiler.IssueMessage(options, Message.SkippingReferencedClass, s, ((RuntimeAssemblyClassLoader)loader).GetAssembly(javaType).FullName); + Context.StaticCompiler.Report(options, Diagnostic.SkippingReferencedClass.Event([s, ((RuntimeAssemblyClassLoader)loader).GetAssembly(javaType).FullName])); continue; } @@ -2977,22 +2971,22 @@ int CompilePass3() } if (wrapper == null) { - throw new FatalCompilerErrorException(Message.MainClassNotFound); + throw new FatalCompilerErrorException(Diagnostic.MainClassNotFound.Event([])); } var mw = wrapper.GetMethodWrapper("main", "([Ljava.lang.String;)V", false); if (mw == null || !mw.IsStatic) - throw new FatalCompilerErrorException(Message.MainMethodNotFound); + throw new FatalCompilerErrorException(Diagnostic.MainMethodNotFound.Event([])); mw.Link(); var method = mw.GetMethod() as MethodInfo; if (method == null) - throw new FatalCompilerErrorException(Message.UnsupportedMainMethod); + throw new FatalCompilerErrorException(Diagnostic.UnsupportedMainMethod.Event([])); if (!ReflectUtil.IsFromAssembly(method.DeclaringType, assemblyBuilder) && (!method.IsPublic || !method.DeclaringType.IsPublic)) { - throw new FatalCompilerErrorException(Message.ExternalMainNotAccessible); + throw new FatalCompilerErrorException(Diagnostic.ExternalMainNotAccessible.Event([])); } var apartmentAttributeType = options.apartment switch @@ -3062,20 +3056,20 @@ int CompilePass3() } if (classLoaderType == null) - throw new FatalCompilerErrorException(Message.ClassLoaderNotFound); + throw new FatalCompilerErrorException(Diagnostic.ClassLoaderNotFound.Event([])); if (classLoaderType.IsPublic == false && ReflectUtil.IsFromAssembly(classLoaderType.TypeAsBaseType, assemblyBuilder) == false) - throw new FatalCompilerErrorException(Message.ClassLoaderNotAccessible); + throw new FatalCompilerErrorException(Diagnostic.ClassLoaderNotAccessible.Event([])); if (classLoaderType.IsAbstract) - throw new FatalCompilerErrorException(Message.ClassLoaderIsAbstract); + throw new FatalCompilerErrorException(Diagnostic.ClassLoaderIsAbstract.Event([])); if (classLoaderType.IsAssignableTo(Context.ClassLoaderFactory.LoadClassCritical("java.lang.ClassLoader")) == false) - throw new FatalCompilerErrorException(Message.ClassLoaderNotClassLoader); + throw new FatalCompilerErrorException(Diagnostic.ClassLoaderNotClassLoader.Event([])); var classLoaderInitMethod = classLoaderType.GetMethodWrapper("", "(Lcli.System.Reflection.Assembly;)V", false); if (classLoaderInitMethod == null) - throw new FatalCompilerErrorException(Message.ClassLoaderConstructorMissing); + throw new FatalCompilerErrorException(Diagnostic.ClassLoaderConstructorMissing.Event([])); // apply custom attribute specifying custom class loader var ci = Context.Resolver.ResolveRuntimeType(typeof(CustomAssemblyClassLoaderAttribute).FullName).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { Context.Types.Type }, null); @@ -3184,12 +3178,12 @@ private void ValidateNameSig(string member, string clazz, string name, string si if (!IsValidName(name)) { valid = false; - Context.StaticCompiler.IssueMessage(Message.InvalidMemberNameInMapFile, member, name, clazz); + Context.StaticCompiler.Report(options, Diagnostic.InvalidMemberNameInMapFile.Event([member, name, clazz])); } if (!IsValidSig(sig, field)) { valid = false; - Context.StaticCompiler.IssueMessage(Message.InvalidMemberSignatureInMapFile, member, clazz, name, sig); + Context.StaticCompiler.Report(options, Diagnostic.InvalidMemberSignatureInMapFile.Event([member, clazz, name, sig])); } } @@ -3200,12 +3194,12 @@ void ValidatePropertyGetterSetter(string getterOrSetter, string clazz, string pr if (!IsValidName(method.Name)) { valid = false; - Context.StaticCompiler.IssueMessage(Message.InvalidPropertyNameInMapFile, getterOrSetter, clazz, property, method.Name); + Context.StaticCompiler.Report(options, Diagnostic.InvalidPropertyNameInMapFile.Event([getterOrSetter, clazz, property, method.Name])); } if (!IKVM.Runtime.ClassFile.IsValidMethodSig(method.Sig)) { valid = false; - Context.StaticCompiler.IssueMessage(Message.InvalidPropertySignatureInMapFile, getterOrSetter, clazz, property, method.Sig); + Context.StaticCompiler.Report(options, Diagnostic.InvalidPropertySignatureInMapFile.Event([getterOrSetter, clazz, property, method.Sig])); } } } @@ -3233,11 +3227,6 @@ internal Type GetTypeFromReferencedAssembly(string name) return null; } - internal override void IssueMessage(Message msgId, params string[] values) - { - Context.StaticCompiler.IssueMessage(options, msgId, values); - } - internal override bool WarningLevelHigh { get { return options.warningLevelHigh; } diff --git a/src/IKVM.Tools.Importer/FatalCompilerErrorException.cs b/src/IKVM.Tools.Importer/FatalCompilerErrorException.cs index a953792fb3..03c8e7fb79 100644 --- a/src/IKVM.Tools.Importer/FatalCompilerErrorException.cs +++ b/src/IKVM.Tools.Importer/FatalCompilerErrorException.cs @@ -1,29 +1,6 @@ -/* - Copyright (C) 2002-2014 Jeroen Frijters +using System; - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -using System; - -using IKVM.Runtime; +using IKVM.CoreLib.Diagnostics; namespace IKVM.Tools.Importer { @@ -31,140 +8,20 @@ namespace IKVM.Tools.Importer sealed class FatalCompilerErrorException : Exception { - internal FatalCompilerErrorException(Message id, params object[] args) : - base($"fatal error IKVMC{(int)id}: {(args.Length == 0 ? GetMessage(id) : string.Format(GetMessage(id), args))}") + /// + /// Initializes a new instance. + /// + /// + internal FatalCompilerErrorException(in DiagnosticEvent evt) : +#if NET8_0_OR_GREATER + base($"fatal error IKVMC{evt.Diagnostic.Id}: {string.Format(null, evt.Diagnostic.Message, evt.Args)}") +#else + base($"fatal error IKVMC{evt.Diagnostic.Id}: {string.Format(evt.Diagnostic.Message, evt.Args.ToArray())}") +#endif { } - private static string GetMessage(Message id) - { - switch (id) - { - case IKVM.Tools.Importer.Message.ResponseFileDepthExceeded: - return "Response file nesting depth exceeded"; - case IKVM.Tools.Importer.Message.ErrorReadingFile: - return "Unable to read file: {0}\n\t({1})"; - case IKVM.Tools.Importer.Message.NoTargetsFound: - return "No targets found"; - case IKVM.Tools.Importer.Message.FileFormatLimitationExceeded: - return "File format limitation exceeded: {0}"; - case IKVM.Tools.Importer.Message.CannotSpecifyBothKeyFileAndContainer: - return "You cannot specify both a key file and container"; - case IKVM.Tools.Importer.Message.DelaySignRequiresKey: - return "You cannot delay sign without a key file or container"; - case IKVM.Tools.Importer.Message.InvalidStrongNameKeyPair: - return "Invalid key {0} specified.\n\t(\"{1}\")"; - case IKVM.Tools.Importer.Message.ReferenceNotFound: - return "Reference not found: {0}"; - case IKVM.Tools.Importer.Message.OptionsMustPreceedChildLevels: - return "You can only specify options before any child levels"; - case IKVM.Tools.Importer.Message.UnrecognizedTargetType: - return "Invalid value '{0}' for -target option"; - case IKVM.Tools.Importer.Message.UnrecognizedPlatform: - return "Invalid value '{0}' for -platform option"; - case IKVM.Tools.Importer.Message.UnrecognizedApartment: - return "Invalid value '{0}' for -apartment option"; - case IKVM.Tools.Importer.Message.MissingFileSpecification: - return "Missing file specification for '{0}' option"; - case IKVM.Tools.Importer.Message.PathTooLong: - return "Path too long: {0}"; - case IKVM.Tools.Importer.Message.PathNotFound: - return "Path not found: {0}"; - case IKVM.Tools.Importer.Message.InvalidPath: - return "Invalid path: {0}"; - case IKVM.Tools.Importer.Message.InvalidOptionSyntax: - return "Invalid option: {0}"; - case IKVM.Tools.Importer.Message.ExternalResourceNotFound: - return "External resource file does not exist: {0}"; - case IKVM.Tools.Importer.Message.ExternalResourceNameInvalid: - return "External resource file may not include path specification: {0}"; - case IKVM.Tools.Importer.Message.InvalidVersionFormat: - return "Invalid version specified: {0}"; - case IKVM.Tools.Importer.Message.InvalidFileAlignment: - return "Invalid value '{0}' for -filealign option"; - case IKVM.Tools.Importer.Message.ErrorWritingFile: - return "Unable to write file: {0}\n\t({1})"; - case IKVM.Tools.Importer.Message.UnrecognizedOption: - return "Unrecognized option: {0}"; - case IKVM.Tools.Importer.Message.NoOutputFileSpecified: - return "No output file specified"; - case IKVM.Tools.Importer.Message.SharedClassLoaderCannotBeUsedOnModuleTarget: - return "Incompatible options: -target:module and -sharedclassloader cannot be combined"; - case IKVM.Tools.Importer.Message.RuntimeNotFound: - return "Unable to load runtime assembly"; - case IKVM.Tools.Importer.Message.MainClassRequiresExe: - return "Main class cannot be specified for library or module"; - case IKVM.Tools.Importer.Message.ExeRequiresMainClass: - return "No main method found"; - case IKVM.Tools.Importer.Message.PropertiesRequireExe: - return "Properties cannot be specified for library or module"; - case IKVM.Tools.Importer.Message.ModuleCannotHaveClassLoader: - return "Cannot specify assembly class loader for modules"; - case IKVM.Tools.Importer.Message.ErrorParsingMapFile: - return "Unable to parse remap file: {0}\n\t({1})"; - case IKVM.Tools.Importer.Message.BootstrapClassesMissing: - return "Bootstrap classes missing and core assembly not found"; - case IKVM.Tools.Importer.Message.StrongNameRequiresStrongNamedRefs: - return "All referenced assemblies must be strong named, to be able to sign the output assembly"; - case IKVM.Tools.Importer.Message.MainClassNotFound: - return "Main class not found"; - case IKVM.Tools.Importer.Message.MainMethodNotFound: - return "Main method not found"; - case IKVM.Tools.Importer.Message.UnsupportedMainMethod: - return "Redirected main method not supported"; - case IKVM.Tools.Importer.Message.ExternalMainNotAccessible: - return "External main method must be public and in a public class"; - case IKVM.Tools.Importer.Message.ClassLoaderNotFound: - return "Custom assembly class loader class not found"; - case IKVM.Tools.Importer.Message.ClassLoaderNotAccessible: - return "Custom assembly class loader class is not accessible"; - case IKVM.Tools.Importer.Message.ClassLoaderIsAbstract: - return "Custom assembly class loader class is abstract"; - case IKVM.Tools.Importer.Message.ClassLoaderNotClassLoader: - return "Custom assembly class loader class does not extend java.lang.ClassLoader"; - case IKVM.Tools.Importer.Message.ClassLoaderConstructorMissing: - return "Custom assembly class loader constructor is missing"; - case IKVM.Tools.Importer.Message.MapFileTypeNotFound: - return "Type '{0}' referenced in remap file was not found"; - case IKVM.Tools.Importer.Message.MapFileClassNotFound: - return "Class '{0}' referenced in remap file was not found"; - case IKVM.Tools.Importer.Message.MaximumErrorCountReached: - return "Maximum error count reached"; - case IKVM.Tools.Importer.Message.LinkageError: - return "Link error: {0}"; - case IKVM.Tools.Importer.Message.RuntimeMismatch: - return "Referenced assembly {0} was compiled with an incompatible IKVM.Runtime version\n" + - "\tCurrent runtime: {1}\n" + - "\tReferenced assembly runtime: {2}"; - case IKVM.Tools.Importer.Message.CoreClassesMissing: - return "Failed to find core classes in core library"; - case IKVM.Tools.Importer.Message.CriticalClassNotFound: - return "Unable to load critical class '{0}'"; - case IKVM.Tools.Importer.Message.AssemblyContainsDuplicateClassNames: - return "Type '{0}' and '{1}' both map to the same name '{2}'\n\t({3})"; - case IKVM.Tools.Importer.Message.CallerIDRequiresHasCallerIDAnnotation: - return "CallerID.getCallerID() requires a HasCallerID annotation"; - case IKVM.Tools.Importer.Message.UnableToResolveInterface: - return "Unable to resolve interface '{0}' on type '{1}'"; - case IKVM.Tools.Importer.Message.MissingBaseType: - return "The base class or interface '{0}' in assembly '{1}' referenced by type '{2}' in '{3}' could not be resolved"; - case IKVM.Tools.Importer.Message.MissingBaseTypeReference: - return "The type '{0}' is defined in an assembly that is not referenced. You must add a reference to assembly '{1}'"; - case IKVM.Tools.Importer.Message.FileNotFound: - return "File not found: {0}"; - case IKVM.Tools.Importer.Message.RuntimeMethodMissing: - return "Runtime method '{0}' not found"; - case IKVM.Tools.Importer.Message.MapFileFieldNotFound: - return "Field '{0}' referenced in remap file was not found in class '{1}'"; - case IKVM.Tools.Importer.Message.GhostInterfaceMethodMissing: - return "Remapped class '{0}' does not implement ghost interface method\n\t({1}.{2}{3})"; - case Importer.Message.ModuleInitializerMethodRequirements: - return "Method '{1}.{2}{3}' does not meet the requirements of a module initializer."; - default: - return "Missing Error IKVM.Tools.Importer.Message. Please file a bug."; - } - } } } diff --git a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs index 96da26085b..a20e5440bf 100644 --- a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs +++ b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs @@ -29,7 +29,7 @@ Jeroen Frijters using System.Threading; using IKVM.ByteCode; -using IKVM.ByteCode.Decoding; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -59,7 +59,7 @@ static void AddArg(List arglist, string s, int depth) { if (depth++ > 16) { - throw new FatalCompilerErrorException(Message.ResponseFileDepthExceeded); + throw new FatalCompilerErrorException(Diagnostic.ResponseFileDepthExceeded.Event([])); } try { @@ -82,7 +82,7 @@ static void AddArg(List arglist, string s, int depth) } catch (Exception x) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, s.Substring(1), x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([s.Substring(1), x.Message])); } } else @@ -172,7 +172,7 @@ static int Compile(string[] args) var importer = new IkvmImporterInternal(); var targets = new List(); var rootTarget = new CompilerOptions(); - var context = new RuntimeContext(new RuntimeContextOptions(), new ManagedResolver(compiler), argList.Contains("-bootstrap"), compiler); + var context = new RuntimeContext(new RuntimeContextOptions(), compiler, new ManagedResolver(compiler), argList.Contains("-bootstrap"), compiler); compiler.rootTarget = rootTarget; importer.ParseCommandLine(context, compiler, argList.GetEnumerator(), targets, rootTarget); @@ -184,7 +184,7 @@ static int Compile(string[] args) if (targets.Count == 0) { - throw new FatalCompilerErrorException(Message.NoTargetsFound); + throw new FatalCompilerErrorException(Diagnostic.NoTargetsFound.Event([])); } if (compiler.errorCount != 0) { @@ -197,7 +197,7 @@ static int Compile(string[] args) } catch (FileFormatLimitationExceededException x) { - throw new FatalCompilerErrorException(Message.FileFormatLimitationExceeded, x.Message); + throw new FatalCompilerErrorException(Diagnostic.FileFormatLimitationExceeded.Event([x.Message])); } } @@ -206,22 +206,22 @@ static void loader_Warning(StaticCompiler compiler, AssemblyResolver.WarningId w switch (warning) { case AssemblyResolver.WarningId.HigherVersion: - IssueMessage(compiler, Message.AssumeAssemblyVersionMatch, parameters); + Report(compiler, Diagnostic.AssumeAssemblyVersionMatch.Event([parameters])); break; case AssemblyResolver.WarningId.InvalidLibDirectoryOption: - IssueMessage(compiler, Message.InvalidDirectoryInLibOptionPath, parameters); + Report(compiler, Diagnostic.InvalidDirectoryInLibOptionPath.Event([parameters])); break; case AssemblyResolver.WarningId.InvalidLibDirectoryEnvironment: - IssueMessage(compiler, Message.InvalidDirectoryInLibEnvironmentPath, parameters); + Report(compiler, Diagnostic.InvalidDirectoryInLibEnvironmentPath.Event([parameters])); break; case AssemblyResolver.WarningId.LegacySearchRule: - IssueMessage(compiler, Message.LegacySearchRule, parameters); + Report(compiler, Diagnostic.LegacySearchRule.Event([parameters])); break; case AssemblyResolver.WarningId.LocationIgnored: - IssueMessage(compiler, Message.AssemblyLocationIgnored, parameters); + Report(compiler, Diagnostic.AssemblyLocationIgnored.Event([parameters])); break; default: - IssueMessage(compiler, Message.UnknownWarning, string.Format(message, parameters)); + Report(compiler, Diagnostic.UnknownWarning.Event([string.Format(message, parameters)])); break; } } @@ -231,10 +231,10 @@ static void ResolveStrongNameKeys(List targets) foreach (var options in targets) { if (options.keyfile != null && options.keycontainer != null) - throw new FatalCompilerErrorException(Message.CannotSpecifyBothKeyFileAndContainer); + throw new FatalCompilerErrorException(Diagnostic.CannotSpecifyBothKeyFileAndContainer.Event([])); if (options.keyfile == null && options.keycontainer == null && options.delaysign) - throw new FatalCompilerErrorException(Message.DelaySignRequiresKey); + throw new FatalCompilerErrorException(Diagnostic.DelaySignRequiresKey.Event([])); if (options.keyfile != null) { @@ -278,7 +278,7 @@ internal static byte[] ReadAllBytes(FileInfo path) } catch (Exception x) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, path.ToString(), x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([path.ToString(), x.Message])); } } @@ -432,7 +432,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } else if (nonleaf) { - throw new FatalCompilerErrorException(Message.OptionsMustPreceedChildLevels); + throw new FatalCompilerErrorException(Diagnostic.OptionsMustPreceedChildLevels.Event([])); } else if (s[0] == '-') { @@ -475,7 +475,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I options.guessFileKind = false; break; default: - throw new FatalCompilerErrorException(Message.UnrecognizedTargetType, s.Substring(8)); + throw new FatalCompilerErrorException(Diagnostic.UnrecognizedTargetType.Event([s.Substring(8)])); } } else if (s.StartsWith("-platform:")) @@ -507,7 +507,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I options.imageFileMachine = ImageFileMachine.UNKNOWN; break; default: - throw new FatalCompilerErrorException(Message.UnrecognizedPlatform, s.Substring(10)); + throw new FatalCompilerErrorException(Diagnostic.UnrecognizedPlatform.Event([s.Substring(10)])); } } else if (s.StartsWith("-apartment:")) @@ -524,7 +524,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I options.apartment = ApartmentState.Unknown; break; default: - throw new FatalCompilerErrorException(Message.UnrecognizedApartment, s.Substring(11)); + throw new FatalCompilerErrorException(Diagnostic.UnrecognizedApartment.Event([s.Substring(11)])); } } else if (s == "-noglobbing") @@ -567,7 +567,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I { var r = s.Substring(s.IndexOf(':') + 1); if (r == "") - throw new FatalCompilerErrorException(Message.MissingFileSpecification, s); + throw new FatalCompilerErrorException(Diagnostic.MissingFileSpecification.Event([s])); ArrayAppend(ref options.unresolvedReferences, r); } @@ -608,26 +608,26 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } catch (PathTooLongException) { - throw new FatalCompilerErrorException(Message.PathTooLong, spec); + throw new FatalCompilerErrorException(Diagnostic.PathTooLong.Event([spec])); } catch (DirectoryNotFoundException) { - throw new FatalCompilerErrorException(Message.PathNotFound, spec); + throw new FatalCompilerErrorException(Diagnostic.PathNotFound.Event([spec])); } catch (ArgumentException) { - throw new FatalCompilerErrorException(Message.InvalidPath, spec); + throw new FatalCompilerErrorException(Diagnostic.InvalidPath.Event([spec])); } } if (!found) - throw new FatalCompilerErrorException(Message.FileNotFound, spec); + throw new FatalCompilerErrorException(Diagnostic.FileNotFound.Event([spec])); } else if (s.StartsWith("-resource:")) { var spec = s.Substring(10).Split('='); if (spec.Length != 2) - throw new FatalCompilerErrorException(Message.InvalidOptionSyntax, s); + throw new FatalCompilerErrorException(Diagnostic.InvalidOptionSyntax.Event([s])); var fileInfo = GetFileInfo(spec[1]); var fileName = spec[0].TrimStart('/').TrimEnd('/'); @@ -637,11 +637,11 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I { var spec = s.Substring(18).Split('='); if (spec.Length != 2) - throw new FatalCompilerErrorException(Message.InvalidOptionSyntax, s); + throw new FatalCompilerErrorException(Diagnostic.InvalidOptionSyntax.Event([s])); if (!File.Exists(spec[1])) - throw new FatalCompilerErrorException(Message.ExternalResourceNotFound, spec[1]); + throw new FatalCompilerErrorException(Diagnostic.ExternalResourceNotFound.Event([spec[1]])); if (Path.GetFileName(spec[1]) != spec[1]) - throw new FatalCompilerErrorException(Message.ExternalResourceNameInvalid, spec[1]); + throw new FatalCompilerErrorException(Diagnostic.ExternalResourceNameInvalid.Event([spec[1]])); // TODO resource name clashes should be tested options.externalResources ??= new Dictionary(); @@ -659,7 +659,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I { var str = s.Substring(9); if (!TryParseVersion(s.Substring(9), out options.version)) - throw new FatalCompilerErrorException(Message.InvalidVersionFormat, str); + throw new FatalCompilerErrorException(Diagnostic.InvalidVersionFormat.Event([str])); } else if (s.StartsWith("-fileversion:")) { @@ -805,7 +805,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I else if (s.StartsWith("-filealign:")) { if (!uint.TryParse(s.Substring(11), out var filealign) || filealign < 512 || filealign > 8192 || (filealign & (filealign - 1)) != 0) - throw new FatalCompilerErrorException(Message.InvalidFileAlignment, s.Substring(11)); + throw new FatalCompilerErrorException(Diagnostic.InvalidFileAlignment.Event([s.Substring(11)])); options.fileAlignment = filealign; } @@ -841,14 +841,14 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } catch (Exception x) { - throw new FatalCompilerErrorException(Message.ErrorWritingFile, options.writeSuppressWarningsFile, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorWritingFile.Event([options.writeSuppressWarningsFile, x.Message])); } } else if (s.StartsWith("-proxy:")) // currently undocumented! { var proxy = s.Substring(7); if (options.proxies.Contains(proxy)) - IssueMessage(compiler, Message.DuplicateProxy, proxy); + Report(compiler, Diagnostic.DuplicateProxy.Event([proxy])); options.proxies.Add(proxy); } @@ -887,7 +887,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } else { - throw new FatalCompilerErrorException(Message.UnrecognizedOption, s); + throw new FatalCompilerErrorException(Diagnostic.UnrecognizedOption.Event([s])); } } else @@ -896,7 +896,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I } if (options.targetIsModule && options.sharedclassloader != null) { - throw new FatalCompilerErrorException(Message.SharedClassLoaderCannotBeUsedOnModuleTarget); + throw new FatalCompilerErrorException(Diagnostic.SharedClassLoaderCannotBeUsedOnModuleTarget.Event([])); } } @@ -911,7 +911,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I { var basename = options.path == null ? defaultAssemblyName : options.path.Name; if (basename == null) - throw new FatalCompilerErrorException(Message.NoOutputFileSpecified); + throw new FatalCompilerErrorException(Diagnostic.NoOutputFileSpecified.Event([])); int idx = basename.LastIndexOf('.'); if (idx > 0) @@ -930,7 +930,7 @@ void ContinueParseCommandLine(RuntimeContext context, StaticCompiler compiler, I if (options.mainClass == null && manifestMainClass != null && (options.guessFileKind || options.target != PEFileKinds.Dll)) { - IssueMessage(compiler, options, Message.MainMethodFromManifest, manifestMainClass); + Report(compiler, options, Diagnostic.MainMethodFromManifest.Event([manifestMainClass])); options.mainClass = manifestMainClass; } @@ -945,26 +945,26 @@ internal static FileInfo GetFileInfo(string path) if (fileInfo.Directory == null) { // this happens with an incorrect unc path (e.g. "\\foo\bar") - throw new FatalCompilerErrorException(Message.InvalidPath, path); + throw new FatalCompilerErrorException(Diagnostic.InvalidPath.Event([path])); } return fileInfo; } catch (ArgumentException) { - throw new FatalCompilerErrorException(Message.InvalidPath, path); + throw new FatalCompilerErrorException(Diagnostic.InvalidPath.Event([path])); } catch (NotSupportedException) { - throw new FatalCompilerErrorException(Message.InvalidPath, path); + throw new FatalCompilerErrorException(Diagnostic.InvalidPath.Event([path])); } catch (PathTooLongException) { - throw new FatalCompilerErrorException(Message.PathTooLong, path); + throw new FatalCompilerErrorException(Diagnostic.PathTooLong.Event([path])); } catch (UnauthorizedAccessException) { // this exception does not appear to be possible - throw new FatalCompilerErrorException(Message.InvalidPath, path); + throw new FatalCompilerErrorException(Diagnostic.InvalidPath.Event([path])); } } @@ -999,7 +999,7 @@ private void ReadFiles(RuntimeContext context, StaticCompiler compiler, Compiler catch { } if (files == null || files.Length == 0) { - IssueMessage(compiler, Message.InputFileNotFound, fileName); + Report(compiler, Diagnostic.InputFileNotFound.Event([fileName])); } else { @@ -1066,7 +1066,7 @@ static void SetStrongNameKeyPair(ref StrongNameKeyPair strongNameKeyPair, FileIn } catch (Exception x) { - throw new FatalCompilerErrorException(Message.InvalidStrongNameKeyPair, keyFile != null ? "file" : "container", x.Message); + throw new FatalCompilerErrorException(Diagnostic.InvalidStrongNameKeyPair.Event([keyFile != null ? "file" : "container", x.Message])); } } @@ -1089,7 +1089,7 @@ static void ResolveReferences(StaticCompiler compiler, List tar } if (!resolver.ResolveReference(cache, ref target.references, reference)) { - throw new FatalCompilerErrorException(Message.ReferenceNotFound, reference); + throw new FatalCompilerErrorException(Diagnostic.ReferenceNotFound.Event([reference])); } next_reference:; } @@ -1106,7 +1106,7 @@ static void ResolveReferences(StaticCompiler compiler, List tar Type forwarder = asm.GetType("__"); if (forwarder != null && forwarder.Assembly != asm) { - IssueMessage(compiler, Message.NonPrimaryAssemblyReference, asm.Location, forwarder.Assembly.GetName().Name); + Report(compiler, Diagnostic.NonPrimaryAssemblyReference.Event([asm.Location, forwarder.Assembly.GetName().Name])); } } } @@ -1199,13 +1199,13 @@ static bool EmitStubWarning(RuntimeContext context, StaticCompiler compiler, Com foreach (Match m in mc) { options.legacyStubReferences[m.Groups[1].Value] = null; - IssueMessage(compiler, options, Message.StubsAreDeprecated, m.Groups[1].Value); + Report(compiler, options, Diagnostic.StubsAreDeprecated.Event([m.Groups[1].Value])); } } else { options.legacyStubReferences[cf.IKVMAssemblyAttribute] = null; - IssueMessage(compiler, options, Message.StubsAreDeprecated, cf.IKVMAssemblyAttribute); + Report(compiler, options, Diagnostic.StubsAreDeprecated.Event([cf.IKVMAssemblyAttribute])); } return true; @@ -1302,7 +1302,7 @@ bool ProcessZipFile(RuntimeContext context, StaticCompiler compiler, CompilerOpt } catch (InvalidDataException x) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, file, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([file, x.Message])); } } @@ -1333,13 +1333,13 @@ void ProcessFile(RuntimeContext context, StaticCompiler compiler, CompilerOption } catch (ClassFormatError x) { - IssueMessage(compiler, Message.ClassFormatError, file, x.Message); + Report(compiler, Diagnostic.ClassFormatError.Event([file, x.Message])); } } if (baseDir == null) { - IssueMessage(compiler, Message.UnknownFileType, file); + Report(compiler, Diagnostic.UnknownFileType.Event([file])); } else { @@ -1415,7 +1415,7 @@ private static void ProcessExclusionFile(ref string[] classesToExclude, string f } catch (Exception x) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, filename, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([filename, x.Message])); } } @@ -1429,261 +1429,66 @@ static void ProcessAttributeAnnotationsClass(RuntimeContext context, ref object[ } catch (Exception x) { - throw new FatalCompilerErrorException(Message.ErrorReadingFile, filename, x.Message); + throw new FatalCompilerErrorException(Diagnostic.ErrorReadingFile.Event([filename, x.Message])); } } - internal static void IssueMessage(StaticCompiler compiler, Message msgId, params string[] values) + /// + /// Handles a . + /// + /// + /// + internal static void Report(StaticCompiler compiler, in DiagnosticEvent evt) { - IssueMessage(compiler, compiler.rootTarget, msgId, values); + Report(compiler, compiler.rootTarget, evt); } - internal static void IssueMessage(StaticCompiler compiler, CompilerOptions options, Message msgId, params string[] values) + /// + /// Handles a . + /// + /// + /// + /// + /// + internal static void Report(StaticCompiler compiler, CompilerOptions options, in DiagnosticEvent evt) { - if (compiler.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(); + var key = evt.Diagnostic.Id.Value.ToString(); for (int i = 0; ; i++) { if (options.suppressWarnings.ContainsKey(key)) - { return; - } - if (i == values.Length) - { + + if (i == evt.Args.Length) break; - } - key += ":" + values[i]; + + key += ":" + evt.Args[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) - { + +#if NET8_0_OR_GREATER + var msg = evt.Diagnostic.Message.Format; +#else + var msg = evt.Diagnostic.Message; +#endif + var err = + evt.Diagnostic.Level is DiagnosticLevel.Error or DiagnosticLevel.Fatal || + evt.Diagnostic.Level is DiagnosticLevel.Warning && options.errorWarnings.ContainsKey(key) || + evt.Diagnostic.Level is DiagnosticLevel.Warning && options.errorWarnings.ContainsKey(evt.Diagnostic.Id.Value.ToString()); + + Console.Error.Write("{0} IKVMC{1:D4}: ", err ? "error" : evt.Diagnostic.Level is DiagnosticLevel.Informational or DiagnosticLevel.Trace ? "note" : "warning", evt.Diagnostic.Id.Value); + if (err && evt.Diagnostic.Level is DiagnosticLevel.Warning) Console.Error.Write("Warning as Error: "); - } - Console.Error.WriteLine(msg, values); + + Console.Error.WriteLine(msg, evt.Args.ToArray()); if (options != compiler.rootTarget && options.path != null) - { Console.Error.WriteLine(" (in {0})", options.path); - } - if (error) - { + + if (err) if (++compiler.errorCount == 100) - { - throw new FatalCompilerErrorException(Message.MaximumErrorCountReached); - } - } + throw new FatalCompilerErrorException(Diagnostic.MaximumErrorCountReached.Event([])); } } diff --git a/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs b/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs index b342906e36..2dabe84f98 100644 --- a/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs +++ b/src/IKVM.Tools.Importer/MapXml/Ldtoken.cs @@ -25,6 +25,7 @@ Jeroen Frijters using System; using System.Xml.Linq; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -106,7 +107,7 @@ internal override void Generate(CodeGenContext context, CodeEmitter ilgen) } else { - context.ClassLoader.Context.StaticCompiler.IssueMessage(Message.MapXmlUnableToResolveOpCode, ToString()); + context.ClassLoader.Context.Report(Diagnostic.MapXmlUnableToResolveOpCode.Event([ToString()])); } } @@ -116,7 +117,7 @@ private bool Validate(CodeGenContext context) { if (Method != null || Field != null || Sig != null) { - context.ClassLoader.Context.StaticCompiler.IssueMessage(Message.MapXmlError, "not implemented: cannot use 'type' attribute with 'method' or 'field' attribute for ldtoken"); + context.ClassLoader.Context.Report(Diagnostic.MapXmlError.Event(["not implemented: cannot use 'type' attribute with 'method' or 'field' attribute for ldtoken"])); return false; } return true; @@ -127,20 +128,20 @@ private bool Validate(CodeGenContext context) { if (Sig != null) { - context.ClassLoader.Context.StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify 'sig' attribute without either 'method' or 'field' attribute for ldtoken"); + context.ClassLoader.Context.Report(Diagnostic.MapXmlError.Event(["cannot specify 'sig' attribute without either 'method' or 'field' attribute for ldtoken"])); } return true; } if (Method != null && Field != null) { - context.ClassLoader.Context.StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify both 'method' and 'field' attribute for ldtoken"); + context.ClassLoader.Context.Report(Diagnostic.MapXmlError.Event(["cannot specify both 'method' and 'field' attribute for ldtoken"])); return false; } return true; } else { - context.ClassLoader.Context.StaticCompiler.IssueMessage(Message.MapXmlError, "must specify either 'type' or 'class' attribute for ldtoken"); + context.ClassLoader.Context.Report(Diagnostic.MapXmlError.Event(["must specify either 'type' or 'class' attribute for ldtoken"])); return false; } } diff --git a/src/IKVM.Tools.Importer/Message.cs b/src/IKVM.Tools.Importer/Message.cs deleted file mode 100644 index dc5c93409a..0000000000 --- a/src/IKVM.Tools.Importer/Message.cs +++ /dev/null @@ -1,135 +0,0 @@ -namespace IKVM.Tools.Importer -{ - - internal enum Message - { - - // These are the informational messages - MainMethodFound = 1, - OutputFileIs = 2, - AutoAddRef = 3, - MainMethodFromManifest = 4, - // This is were the warnings start - StartWarnings = 100, - ClassNotFound = 100, - ClassFormatError = 101, - DuplicateClassName = 102, - IllegalAccessError = 103, - VerificationError = 104, - NoClassDefFoundError = 105, - GenericUnableToCompileError = 106, - DuplicateResourceName = 107, - SkippingReferencedClass = 109, - NoJniRuntime = 110, - EmittedNoClassDefFoundError = 111, - EmittedIllegalAccessError = 112, - EmittedInstantiationError = 113, - EmittedIncompatibleClassChangeError = 114, - EmittedNoSuchFieldError = 115, - EmittedAbstractMethodError = 116, - EmittedNoSuchMethodError = 117, - EmittedLinkageError = 118, - EmittedVerificationError = 119, - EmittedClassFormatError = 120, - InvalidCustomAttribute = 121, - IgnoredCustomAttribute = 122, - AssumeAssemblyVersionMatch = 123, - InvalidDirectoryInLibOptionPath = 124, - InvalidDirectoryInLibEnvironmentPath = 125, - LegacySearchRule = 126, - AssemblyLocationIgnored = 127, - InterfaceMethodCantBeInternal = 128, - DuplicateAssemblyReference = 132, - UnableToResolveType = 133, - StubsAreDeprecated = 134, - WrongClassName = 135, - ReflectionCallerClassRequiresCallerID = 136, - LegacyAssemblyAttributesFound = 137, - UnableToCreateLambdaFactory = 138, - UnknownWarning = 999, - // This is where the errors start - StartErrors = 4000, - UnableToCreateProxy = 4001, - DuplicateProxy = 4002, - MapXmlUnableToResolveOpCode = 4003, - MapXmlError = 4004, - InputFileNotFound = 4005, - UnknownFileType = 4006, - UnknownElementInMapFile = 4007, - UnknownAttributeInMapFile = 4008, - InvalidMemberNameInMapFile = 4009, - InvalidMemberSignatureInMapFile = 4010, - InvalidPropertyNameInMapFile = 4011, - InvalidPropertySignatureInMapFile = 4012, - NonPrimaryAssemblyReference = 4013, - MissingType = 4014, - MissingReference = 4015, - CallerSensitiveOnUnsupportedMethod = 4016, - RemappedTypeMissingDefaultInterfaceMethod = 4017, - // Fatal errors - ResponseFileDepthExceeded = 5000, - ErrorReadingFile = 5001, - NoTargetsFound = 5002, - FileFormatLimitationExceeded = 5003, - CannotSpecifyBothKeyFileAndContainer = 5004, - DelaySignRequiresKey = 5005, - InvalidStrongNameKeyPair = 5006, - ReferenceNotFound = 5007, - OptionsMustPreceedChildLevels = 5008, - UnrecognizedTargetType = 5009, - UnrecognizedPlatform = 5010, - UnrecognizedApartment = 5011, - MissingFileSpecification = 5012, - PathTooLong = 5013, - PathNotFound = 5014, - InvalidPath = 5015, - InvalidOptionSyntax = 5016, - ExternalResourceNotFound = 5017, - ExternalResourceNameInvalid = 5018, - InvalidVersionFormat = 5019, - InvalidFileAlignment = 5020, - ErrorWritingFile = 5021, - UnrecognizedOption = 5022, - NoOutputFileSpecified = 5023, - SharedClassLoaderCannotBeUsedOnModuleTarget = 5024, - RuntimeNotFound = 5025, - MainClassRequiresExe = 5026, - ExeRequiresMainClass = 5027, - PropertiesRequireExe = 5028, - ModuleCannotHaveClassLoader = 5029, - ErrorParsingMapFile = 5030, - BootstrapClassesMissing = 5031, - StrongNameRequiresStrongNamedRefs = 5032, - MainClassNotFound = 5033, - MainMethodNotFound = 5034, - UnsupportedMainMethod = 5035, - ExternalMainNotAccessible = 5036, - ClassLoaderNotFound = 5037, - ClassLoaderNotAccessible = 5038, - ClassLoaderIsAbstract = 5039, - ClassLoaderNotClassLoader = 5040, - ClassLoaderConstructorMissing = 5041, - MapFileTypeNotFound = 5042, - MapFileClassNotFound = 5043, - MaximumErrorCountReached = 5044, - LinkageError = 5045, - RuntimeMismatch = 5046, - RuntimeMismatchStrongName = 5047, - CoreClassesMissing = 5048, - CriticalClassNotFound = 5049, - AssemblyContainsDuplicateClassNames = 5050, - CallerIDRequiresHasCallerIDAnnotation = 5051, - UnableToResolveInterface = 5052, - MissingBaseType = 5053, - MissingBaseTypeReference = 5054, - FileNotFound = 5055, - RuntimeMethodMissing = 5056, - MapFileFieldNotFound = 5057, - GhostInterfaceMethodMissing = 5058, - - // ModuleInitializer attribute placed on inappropriate method - ModuleInitializerMethodRequirements = 5059, - - } - -} diff --git a/src/IKVM.Tools.Importer/Proxy.cs b/src/IKVM.Tools.Importer/Proxy.cs index 47824dfdb2..6f4f7667cb 100644 --- a/src/IKVM.Tools.Importer/Proxy.cs +++ b/src/IKVM.Tools.Importer/Proxy.cs @@ -25,6 +25,7 @@ Jeroen Frijters using System.Collections.Generic; using IKVM.Attributes; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -104,7 +105,7 @@ internal void Create(CompilerClassLoader loader, string proxy) if (wrappers[i] == null) { - loader.Context.StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, "unable to load interface " + interfaces[i]); + loader.Context.Report(Diagnostic.UnableToCreateProxy.Event([proxy, "unable to load interface " + interfaces[i]])); return; } } @@ -121,12 +122,12 @@ private void Create(CompilerClassLoader loader, string proxy, RuntimeJavaType[] } catch (RetargetableJavaException x) { - loader.Context.StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, x.Message); + loader.Context.Report(Diagnostic.UnableToCreateProxy.Event([proxy, x.Message])); return; } catch (ProxyException x) { - loader.Context.StaticCompiler.IssueMessage(Message.UnableToCreateProxy, proxy, x.Message); + loader.Context.Report(Diagnostic.UnableToCreateProxy.Event([proxy, x.Message])); return; } diff --git a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs index db78dd01d2..1619d0b054 100644 --- a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs +++ b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs @@ -26,6 +26,7 @@ Jeroen Frijters using System.Collections.Generic; using IKVM.Attributes; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -689,7 +690,7 @@ protected override void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] if (methods[i].IsAbstract) { // This should only happen for remapped types (defined in map.xml), because normally you'd get a miranda method. - throw new FatalCompilerErrorException(Message.GhostInterfaceMethodMissing, implementers[j].Name, Name, methods[i].Name, methods[i].Signature); + throw new FatalCompilerErrorException(Diagnostic.GhostInterfaceMethodMissing.Event([implementers[j].Name, Name, methods[i].Name, methods[i].Signature])); } // We're inheriting a default method ilgen.Emit(OpCodes.Pop); diff --git a/src/IKVM.Tools.Importer/StaticCompiler.cs b/src/IKVM.Tools.Importer/StaticCompiler.cs index bfc78180af..767e8787a6 100644 --- a/src/IKVM.Tools.Importer/StaticCompiler.cs +++ b/src/IKVM.Tools.Importer/StaticCompiler.cs @@ -29,6 +29,7 @@ Jeroen Frijters using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using IKVM.CoreLib.Diagnostics; using IKVM.Reflection; using IKVM.Reflection.Diagnostics; using IKVM.Runtime; @@ -38,7 +39,7 @@ Jeroen Frijters namespace IKVM.Tools.Importer { - class StaticCompiler + class StaticCompiler : IDiagnosticHandler { readonly ConcurrentDictionary runtimeTypeCache = new(); @@ -142,7 +143,7 @@ void ResolvedMissingMember(Module requestingModule, MemberInfo member) { if (requestingModule != null && member is Type) { - IssueMessage(Message.UnableToResolveType, requestingModule.Name, ((Type)member).FullName, member.Module.FullyQualifiedName); + Report(Diagnostic.UnableToResolveType.Event([requestingModule.Name, ((Type)member).FullName, member.Module.FullyQualifiedName])); } } @@ -167,19 +168,19 @@ internal Type GetRuntimeType(string name) internal Type GetTypeForMapXml(RuntimeClassLoader loader, string name) { - return GetType(loader, name) ?? throw new FatalCompilerErrorException(Message.MapFileTypeNotFound, name); + return GetType(loader, name) ?? throw new FatalCompilerErrorException(Diagnostic.MapFileTypeNotFound.Event([name])); } internal RuntimeJavaType GetClassForMapXml(RuntimeClassLoader loader, string name) { - return loader.TryLoadClassByName(name) ?? throw new FatalCompilerErrorException(Message.MapFileClassNotFound, name); + return loader.TryLoadClassByName(name) ?? throw new FatalCompilerErrorException(Diagnostic.MapFileClassNotFound.Event([name])); } internal RuntimeJavaField GetFieldForMapXml(RuntimeClassLoader loader, string clazz, string name, string sig) { var fw = GetClassForMapXml(loader, clazz).GetFieldWrapper(name, sig); if (fw == null) - throw new FatalCompilerErrorException(Message.MapFileFieldNotFound, name, clazz); + throw new FatalCompilerErrorException(Diagnostic.MapFileFieldNotFound.Event([name, clazz])); fw.Link(); return fw; @@ -203,7 +204,7 @@ internal static void LinkageError(string msg, RuntimeJavaType actualType, Runtim str += string.Format("\n\t(Please add a reference to {0})", expectedType.TypeAsBaseType.Assembly.Location); } - throw new FatalCompilerErrorException(Message.LinkageError, str); + throw new FatalCompilerErrorException(Diagnostic.LinkageError.Event([str])); } static string AssemblyQualifiedName(RuntimeJavaType tw) @@ -225,265 +226,22 @@ static string AssemblyQualifiedName(RuntimeJavaType tw) internal void IssueMissingTypeMessage(Type type) { type = ReflectUtil.GetMissingType(type); - IssueMessage(type.Assembly.__IsMissing ? Message.MissingReference : Message.MissingType, type.FullName, type.Assembly.FullName); + Report((type.Assembly.__IsMissing ? Diagnostic.MissingReference : Diagnostic.MissingType).Event([type.FullName, type.Assembly.FullName])); } - internal void SuppressWarning(CompilerOptions options, Message message, string name) + internal void SuppressWarning(CompilerOptions options, Diagnostic diagnostic, string name) { - options.suppressWarnings[(int)message + ":" + name] = null; + options.suppressWarnings[diagnostic.Id.Value + ":" + name] = null; } - internal void IssueMessage(Message msgId, params string[] values) + public void Report(in DiagnosticEvent evt) { - IssueMessage(rootTarget, msgId, values); + IkvmImporterInternal.Report(this, evt); } - internal void IssueMessage(CompilerOptions options, Message msgId, params string[] values) + internal void Report(CompilerOptions options, in DiagnosticEvent evt) { - 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.Report(this, options, evt); } }