diff --git a/.github/workflows/IKVM.yml b/.github/workflows/IKVM.yml index f44b1e07b2..1ec55ca878 100644 --- a/.github/workflows/IKVM.yml +++ b/.github/workflows/IKVM.yml @@ -240,6 +240,16 @@ jobs: path: /tmp/tests--IKVM.Reflection.Tests.tar.gz - name: Delete Tests (IKVM.Reflection.Tests) run: rm /tmp/tests--IKVM.Reflection.Tests.tar.gz + - name: Package Tests (IKVM.CoreLib.Tests) + run: tar czvf /tmp/tests--IKVM.CoreLib.Tests.tar.gz tests/IKVM.CoreLib.Tests + working-directory: dist + - name: Upload Tests (IKVM.CoreLib.Tests) + uses: actions/upload-artifact@v4 + with: + name: tests--IKVM.CoreLib.Tests + path: /tmp/tests--IKVM.CoreLib.Tests.tar.gz + - name: Delete Tests (IKVM.CoreLib.Tests) + run: rm /tmp/tests--IKVM.CoreLib.Tests.tar.gz - name: Package Tests (IKVM.Tests) run: tar czvf /tmp/tests--IKVM.Tests.tar.gz tests/IKVM.Tests working-directory: dist @@ -378,8 +388,9 @@ jobs: $tfm += @( "net6.0" ) } - $run = @( + $run = ( "IKVM.Reflection.Tests", + "IKVM.CoreLib.Tests", "IKVM.Tests", "IKVM.Java.Tests", "IKVM.Tools.Exporter.Tests", diff --git a/IKVM.deps.targets b/IKVM.deps.targets index b5b022c12b..7f0a15af2b 100644 --- a/IKVM.deps.targets +++ b/IKVM.deps.targets @@ -2,7 +2,9 @@ - + + + diff --git a/IKVM.refs.targets b/IKVM.refs.targets index ff52d30390..54c246820f 100644 --- a/IKVM.refs.targets +++ b/IKVM.refs.targets @@ -5,6 +5,11 @@ + + true + all + IkvmLibsItem + true all diff --git a/IKVM.sln b/IKVM.sln index 346f617c4f..d370cca6cc 100644 --- a/IKVM.sln +++ b/IKVM.sln @@ -341,7 +341,9 @@ Project("{6DE1C62B-E8D7-451A-8734-87EAEB46E35B}") = "libsspi_bridge", "src\libss EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.CoreLib", "src\IKVM.CoreLib\IKVM.CoreLib.csproj", "{C6556982-85B8-4E58-A693-1239D4823BD7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.Tools.Core", "src\IKVM.Tools.Core\IKVM.Tools.Core.csproj", "{0D74BDB7-F1FE-4E9E-B195-640C66DA19D2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.Tools.Core", "src\IKVM.Tools.Core\IKVM.Tools.Core.csproj", "{0D74BDB7-F1FE-4E9E-B195-640C66DA19D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IKVM.CoreLib.Tests", "src\IKVM.CoreLib.Tests\IKVM.CoreLib.Tests.csproj", "{21179656-9D00-45C9-A8BF-50E456AA29D4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -921,6 +923,10 @@ Global {0D74BDB7-F1FE-4E9E-B195-640C66DA19D2}.Debug|Any CPU.Build.0 = Debug|Any CPU {0D74BDB7-F1FE-4E9E-B195-640C66DA19D2}.Release|Any CPU.ActiveCfg = Release|Any CPU {0D74BDB7-F1FE-4E9E-B195-640C66DA19D2}.Release|Any CPU.Build.0 = Release|Any CPU + {21179656-9D00-45C9-A8BF-50E456AA29D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21179656-9D00-45C9-A8BF-50E456AA29D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21179656-9D00-45C9-A8BF-50E456AA29D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21179656-9D00-45C9-A8BF-50E456AA29D4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/IKVM.CoreLib.Tests/IKVM.CoreLib.Tests.csproj b/src/IKVM.CoreLib.Tests/IKVM.CoreLib.Tests.csproj new file mode 100644 index 0000000000..7376cc8ede --- /dev/null +++ b/src/IKVM.CoreLib.Tests/IKVM.CoreLib.Tests.csproj @@ -0,0 +1,16 @@ + + + net472;net6.0;net7.0;net8.0 + enable + true + + + + + + + + + + + diff --git a/src/IKVM.CoreLib.Tests/Symbols/IkvmReflection/IkvmReflectionSymbolTests.cs b/src/IKVM.CoreLib.Tests/Symbols/IkvmReflection/IkvmReflectionSymbolTests.cs new file mode 100644 index 0000000000..c683fdbb12 --- /dev/null +++ b/src/IKVM.CoreLib.Tests/Symbols/IkvmReflection/IkvmReflectionSymbolTests.cs @@ -0,0 +1,199 @@ +using System.IO; + +using FluentAssertions; + +using IKVM.CoreLib.Symbols.IkvmReflection; +using IKVM.Reflection; + +using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IKVM.CoreLib.Tests.Symbols.IkvmReflection +{ + + [TestClass] + public class IkvmReflectionSymbolTests + { + + class Foo + { + + T? field; + + bool Method(int p1) => true; + + } + + Universe? universe; + Assembly? coreAssembly; + Assembly? thisAssembly; + + [TestInitialize] + public void Setup() + { + universe = new Universe(typeof(object).Assembly.GetName().Name); + universe.AssemblyResolve += Universe_AssemblyResolve; + coreAssembly = universe.LoadFile(typeof(object).Assembly.GetAssemblyLocation()); + thisAssembly = universe.LoadFile(typeof(IkvmReflectionSymbolTests).Assembly.GetAssemblyLocation()); + } + + /// + /// Attempt to load assembly from system. + /// + /// + /// + /// + Assembly? Universe_AssemblyResolve(object sender, ResolveEventArgs args) + { + try + { + var asm = System.Reflection.Assembly.Load(args.Name); + if (asm != null && File.Exists(asm.Location)) + return universe!.LoadFile(asm.Location); + } + catch + { + + } + + return null; + } + + [TestMethod] + public void SameTypeShouldBeSame() + { + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(universe!.GetBuiltInType("System", "Object")); + var s2 = c.GetOrCreateTypeSymbol(universe!.GetBuiltInType("System", "Object")); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void GenericTypeDefinitionShouldBeSame() + { + var t = thisAssembly!.GetType("IKVM.CoreLib.Tests.Symbols.IkvmReflection.IkvmReflectionSymbolTests+Foo`1"); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void GenericTypeShouldBeSame() + { + var t = thisAssembly!.GetType("IKVM.CoreLib.Tests.Symbols.IkvmReflection.IkvmReflectionSymbolTests+Foo`1").MakeGenericType(universe!.GetBuiltInType("System", "Int32")); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void ArrayTypeShouldBeSame() + { + var t = universe!.GetBuiltInType("System", "Object").MakeArrayType(2); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void SZArrayTypeShouldBeSame() + { + var t = universe!.GetBuiltInType("System", "Object").MakeArrayType(); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public unsafe void PointerTypeShouldBeSame() + { + var t = universe!.GetBuiltInType("System", "Int32").MakePointerType(); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public unsafe void ByRefTypeShouldBeSame() + { + var t = universe!.GetBuiltInType("System", "Int32").MakeByRefType(); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void EnumTypeShouldBeSame() + { + var a = universe!.Load(typeof(System.AttributeTargets).Assembly.FullName); + var t = a.GetType("System.AttributeTargets"); + var c = new IkvmReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(t); + var s2 = c.GetOrCreateTypeSymbol(t); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void CanGetType() + { + var t = universe!.GetBuiltInType("System", "Object"); + var c = new IkvmReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(t); + s.Name.Should().Be("Object"); + s.FullName.Should().Be("System.Object"); + } + + [TestMethod] + public void CanGetFieldOfGenericTypeDefinition() + { + var t = thisAssembly!.GetType("IKVM.CoreLib.Tests.Symbols.IkvmReflection.IkvmReflectionSymbolTests+Foo`1"); + var c = new IkvmReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(t); + s.IsGenericType.Should().BeTrue(); + s.IsGenericTypeDefinition.Should().BeTrue(); + var f = s.GetField("field", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + f.Name.Should().Be("field"); + f.FieldType.IsGenericType.Should().BeFalse(); + f.FieldType.IsGenericParameter.Should().BeTrue(); + } + + [TestMethod] + public void CanGetFieldOfGenericType() + { + var t = thisAssembly!.GetType("IKVM.CoreLib.Tests.Symbols.IkvmReflection.IkvmReflectionSymbolTests+Foo`1").MakeGenericType(universe!.GetBuiltInType("System", "Int32")); + var c = new IkvmReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(t); + s.IsGenericType.Should().BeTrue(); + s.IsGenericTypeDefinition.Should().BeFalse(); + var f = s.GetField("field", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + f.Name.Should().Be("field"); + f.FieldType.IsGenericType.Should().BeFalse(); + f.FieldType.IsGenericParameter.Should().BeFalse(); + f.FieldType.Should().BeSameAs(c.GetOrCreateTypeSymbol(universe!.GetBuiltInType("System", "Int32"))); + } + + [TestMethod] + public void CanGetMethod() + { + var t = universe!.GetBuiltInType("System", "Object"); + var c = new IkvmReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(t); + var m = s.GetMethod("ToString"); + m.Name.Should().Be("ToString"); + m.ReturnType.Should().BeSameAs(c.GetOrCreateTypeSymbol(universe!.GetBuiltInType("System", "String"))); + m.ReturnParameter.ParameterType.Should().BeSameAs(c.GetOrCreateTypeSymbol(universe!.GetBuiltInType("System", "String"))); + m.IsGenericMethod.Should().BeFalse(); + m.IsGenericMethodDefinition.Should().BeFalse(); + m.IsPublic.Should().BeTrue(); + m.IsPrivate.Should().BeFalse(); + } + + } + +} diff --git a/src/IKVM.CoreLib.Tests/Symbols/Reflection/ReflectionSymbolTests.cs b/src/IKVM.CoreLib.Tests/Symbols/Reflection/ReflectionSymbolTests.cs new file mode 100644 index 0000000000..37b66bf096 --- /dev/null +++ b/src/IKVM.CoreLib.Tests/Symbols/Reflection/ReflectionSymbolTests.cs @@ -0,0 +1,147 @@ +using System; + +using FluentAssertions; + +using IKVM.CoreLib.Symbols.Reflection; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IKVM.CoreLib.Tests.Symbols.Reflection +{ + + [TestClass] + public class ReflectionSymbolTests + { + + class Foo + { + T? field; + } + + [TestMethod] + public void SameTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(object)); + var s2 = c.GetOrCreateTypeSymbol(typeof(object)); + s1.Should().BeOfType(); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void GenericTypeDefinitionShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(Foo<>)); + var s2 = c.GetOrCreateTypeSymbol(typeof(Foo<>)); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void GenericTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(Foo)); + var s2 = c.GetOrCreateTypeSymbol(typeof(Foo)); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void ArrayTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(object[,])); + var s2 = c.GetOrCreateTypeSymbol(typeof(object[,])); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void SZArrayTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(object[])); + var s2 = c.GetOrCreateTypeSymbol(typeof(object[])); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public unsafe void PointerTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(int*)); + var s2 = c.GetOrCreateTypeSymbol(typeof(int*)); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public unsafe void ByRefTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(int).MakeByRefType()); + var s2 = c.GetOrCreateTypeSymbol(typeof(int).MakeByRefType()); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void EnumTypeShouldBeSame() + { + var c = new ReflectionSymbolContext(); + var s1 = c.GetOrCreateTypeSymbol(typeof(AttributeTargets)); + var s2 = c.GetOrCreateTypeSymbol(typeof(AttributeTargets)); + s1.Should().BeSameAs(s2); + } + + [TestMethod] + public void CanGetType() + { + var c = new ReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(typeof(object)); + s.Name.Should().Be("Object"); + s.FullName.Should().Be("System.Object"); + } + + [TestMethod] + public void CanGetFieldOfGenericTypeDefinition() + { + var c = new ReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(typeof(Foo<>)); + s.IsGenericType.Should().BeTrue(); + s.IsGenericTypeDefinition.Should().BeTrue(); + var f = s.GetField("field", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + f.Name.Should().Be("field"); + f.FieldType.IsGenericType.Should().BeFalse(); + f.FieldType.IsGenericParameter.Should().BeTrue(); + } + + [TestMethod] + public void CanGetFieldOfGenericType() + { + var c = new ReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(typeof(Foo)); + s.IsGenericType.Should().BeTrue(); + s.IsGenericTypeDefinition.Should().BeFalse(); + var f = s.GetField("field", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + f.Name.Should().Be("field"); + f.FieldType.IsGenericType.Should().BeFalse(); + f.FieldType.IsGenericParameter.Should().BeFalse(); + f.FieldType.Should().BeSameAs(c.GetOrCreateTypeSymbol(typeof(int))); + } + + [TestMethod] + public void CanGetMethod() + { + var c = new ReflectionSymbolContext(); + var s = c.GetOrCreateTypeSymbol(typeof(object)); + var m = s.GetMethod("ToString"); + m.Name.Should().Be("ToString"); + m.ReturnType.Should().BeSameAs(c.GetOrCreateTypeSymbol(typeof(string))); + m.ReturnParameter.ParameterType.Should().BeSameAs(c.GetOrCreateTypeSymbol(typeof(string))); + m.IsGenericMethod.Should().BeFalse(); + m.IsGenericMethodDefinition.Should().BeFalse(); + m.IsPublic.Should().BeTrue(); + m.IsPrivate.Should().BeFalse(); + } + + } + +} diff --git a/src/IKVM.CoreLib/IKVM.CoreLib.csproj b/src/IKVM.CoreLib/IKVM.CoreLib.csproj index 8da6ba6d92..cede1bd120 100644 --- a/src/IKVM.CoreLib/IKVM.CoreLib.csproj +++ b/src/IKVM.CoreLib/IKVM.CoreLib.csproj @@ -7,6 +7,7 @@ + @@ -18,15 +19,24 @@ + + + + + + + + + DiagnosticEvent.g.cs diff --git a/src/IKVM.CoreLib/Symbols/CustomAttributeSymbol.cs b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbol.cs new file mode 100644 index 0000000000..dbdab0f3cb --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbol.cs @@ -0,0 +1,12 @@ +using System.Collections.Immutable; + +namespace IKVM.CoreLib.Symbols +{ + + readonly record struct CustomAttributeSymbol( + ITypeSymbol AttributeType, + IConstructorSymbol Constructor, + ImmutableArray ConstructorArguments, + ImmutableArray NamedArguments); + +} diff --git a/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolNamedArgument.cs b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolNamedArgument.cs new file mode 100644 index 0000000000..c01598e24c --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolNamedArgument.cs @@ -0,0 +1,10 @@ +namespace IKVM.CoreLib.Symbols +{ + + readonly record struct CustomAttributeSymbolNamedArgument( + bool IsField, + IMemberSymbol MemberInfo, + string MemberName, + CustomAttributeSymbolTypedArgument TypedValue); + +} diff --git a/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolTypedArgument.cs b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolTypedArgument.cs new file mode 100644 index 0000000000..0f56df5a32 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/CustomAttributeSymbolTypedArgument.cs @@ -0,0 +1,8 @@ +namespace IKVM.CoreLib.Symbols +{ + + readonly record struct CustomAttributeSymbolTypedArgument( + ITypeSymbol ArgumentType, + object? Value); + +} diff --git a/src/IKVM.CoreLib/Symbols/IAssemblySymbol.cs b/src/IKVM.CoreLib/Symbols/IAssemblySymbol.cs new file mode 100644 index 0000000000..1b0817f280 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IAssemblySymbol.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + interface IAssemblySymbol : ISymbol, ICustomAttributeSymbolProvider + { + + IEnumerable DefinedTypes { get; } + + IMethodSymbol? EntryPoint { get; } + + IEnumerable ExportedTypes { get; } + + string? FullName { get; } + + string ImageRuntimeVersion { get; } + + IModuleSymbol ManifestModule { get; } + + IEnumerable Modules { get; } + + ITypeSymbol[] GetExportedTypes(); + + IModuleSymbol? GetModule(string name); + + IModuleSymbol[] GetModules(); + + IModuleSymbol[] GetModules(bool getResourceModules); + + AssemblyName GetName(); + + AssemblyName GetName(bool copiedName); + + AssemblyName[] GetReferencedAssemblies(); + + ITypeSymbol? GetType(string name, bool throwOnError); + + ITypeSymbol? GetType(string name, bool throwOnError, bool ignoreCase); + + ITypeSymbol? GetType(string name); + + ITypeSymbol[] GetTypes(); + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IConstructorSymbol.cs b/src/IKVM.CoreLib/Symbols/IConstructorSymbol.cs new file mode 100644 index 0000000000..3b5d8a4c23 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IConstructorSymbol.cs @@ -0,0 +1,14 @@ +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of a class constructor and provides access to constructor metadata. + /// + interface IConstructorSymbol : IMethodBaseSymbol + { + + + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/ICustomAttributeSymbolProvider.cs b/src/IKVM.CoreLib/Symbols/ICustomAttributeSymbolProvider.cs new file mode 100644 index 0000000000..d7354b219e --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/ICustomAttributeSymbolProvider.cs @@ -0,0 +1,32 @@ +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Provides custom attributes for reflection objects that support them. + /// + interface ICustomAttributeSymbolProvider + { + + /// + /// Returns an array of all of the custom attributes defined on this member, excluding named attributes, or an empty array if there are no custom attributes. + /// + /// + CustomAttributeSymbol[] GetCustomAttributes(); + + /// + /// Returns an array of custom attributes defined on this member, identified by type, or an empty array if there are no custom attributes of that type. + /// + /// + /// + CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType); + + /// + /// Indicates whether one or more instance of is defined on this member. + /// + /// + /// + bool IsDefined(ITypeSymbol attributeType); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IEventSymbol.cs b/src/IKVM.CoreLib/Symbols/IEventSymbol.cs new file mode 100644 index 0000000000..220a74891c --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IEventSymbol.cs @@ -0,0 +1,96 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of an event and provides access to event metadata. + /// + interface IEventSymbol : IMemberSymbol + { + + /// + /// Gets the attributes for this event. + /// + EventAttributes Attributes { get; } + + /// + /// Gets the object of the underlying event-handler delegate associated with this event. + /// + ITypeSymbol? EventHandlerType { get; } + + /// + /// Gets a value indicating whether the has a name with a special meaning. + /// + bool IsSpecialName { get; } + + /// + /// Returns the method used to add an event handler delegate to the event source. + /// + IMethodSymbol? AddMethod { get; } + + /// + /// Returns the method used to remove an event handler delegate from the event source. + /// + IMethodSymbol? RemoveMethod { get; } + + /// + /// Returns the method that is called when the event is raised. + /// + IMethodSymbol? RaiseMethod { get; } + + /// + /// Returns the method used to add an event handler delegate to the event source. + /// + /// + IMethodSymbol? GetAddMethod(); + + /// + /// Returns the method used to add an event handler delegate to the event source, specifying whether to return non-public methods. + /// + /// + /// + IMethodSymbol? GetAddMethod(bool nonPublic); + + /// + /// Returns the method used to remove an event handler delegate from the event source. + /// + /// + IMethodSymbol? GetRemoveMethod(); + + /// + /// When overridden in a derived class, retrieves the object for removing a method of the event, specifying whether to return non-public methods. + /// + /// + /// + IMethodSymbol? GetRemoveMethod(bool nonPublic); + + /// + /// Returns the method that is called when the event is raised. + /// + /// + IMethodSymbol? GetRaiseMethod(); + + /// + /// When overridden in a derived class, returns the method that is called when the event is raised, specifying whether to return non-public methods. + /// + /// + /// + IMethodSymbol? GetRaiseMethod(bool nonPublic); + + /// + /// Returns the public methods that have been associated with an event in metadata using the .other directive. + /// + /// + IMethodSymbol[] GetOtherMethods(); + + /// + /// Returns the methods that have been associated with the event in metadata using the .other directive, specifying whether to include non-public methods. + /// + /// + /// + IMethodSymbol[] GetOtherMethods(bool nonPublic); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IFieldSymbol.cs b/src/IKVM.CoreLib/Symbols/IFieldSymbol.cs new file mode 100644 index 0000000000..1eee20fe92 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IFieldSymbol.cs @@ -0,0 +1,102 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of a field and provides access to field metadata. + /// + interface IFieldSymbol : IMemberSymbol + { + + /// + /// Gets the attributes associated with this field. + /// + FieldAttributes Attributes { get; } + + /// + /// Gets the type of this field object. + /// + ITypeSymbol FieldType { get; } + + /// + /// Gets a value indicating whether the potential visibility of this field is described by ; that is, the field is visible at most to other types in the same assembly, and is not visible to derived types outside the assembly. + /// + bool IsAssembly { get; } + + /// + /// Gets a value indicating whether the visibility of this field is described by ; that is, the field is visible only within its class and derived classes. + /// + bool IsFamily { get; } + + /// + /// Gets a value indicating whether the visibility of this field is described by ; that is, the field can be accessed from derived classes, but only if they are in the same assembly. + /// + bool IsFamilyAndAssembly { get; } + + /// + /// Gets a value indicating whether the potential visibility of this field is described by ; that is, the field can be accessed by derived classes wherever they are, and by classes in the same assembly. + /// + bool IsFamilyOrAssembly { get; } + + /// + /// Gets a value indicating whether the field can only be set in the body of the constructor. + /// + bool IsInitOnly { get; } + + /// + /// Gets a value indicating whether the value is written at compile time and cannot be changed. + /// + bool IsLiteral { get; } + + /// + /// Gets a value indicating whether this field has the NotSerialized attribute. + /// + bool IsNotSerialized { get; } + + /// + /// Gets a value indicating whether the corresponding PinvokeImpl attribute is set in FieldAttributes. + /// + bool IsPinvokeImpl { get; } + + /// + /// Gets a value indicating whether the field is private. + /// + bool IsPrivate { get; } + + /// + /// Gets a value indicating whether the field is public. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether the corresponding SpecialName attribute is set in the FieldAttributes enumerator. + /// + bool IsSpecialName { get; } + + /// + /// Gets a value indicating whether the field is static. + /// + bool IsStatic { get; } + + /// + /// Returns a literal value associated with the field by a compiler. + /// + /// + object? GetRawConstantValue(); + + /// + /// Gets an array of types that identify the optional custom modifiers of the field. + /// + /// + ITypeSymbol[] GetOptionalCustomModifiers(); + + /// + /// Gets an array of types that identify the required custom modifiers of the property. + /// + /// + ITypeSymbol[] GetRequiredCustomModifiers(); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IMemberSymbol.cs b/src/IKVM.CoreLib/Symbols/IMemberSymbol.cs new file mode 100644 index 0000000000..0613ff1000 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IMemberSymbol.cs @@ -0,0 +1,39 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Obtains information about the attributes of a member and provides access to member metadata. + /// + interface IMemberSymbol : ISymbol, ICustomAttributeSymbolProvider + { + + /// + /// Gets the module in which the type that declares the member represented by the current is defined. + /// + IModuleSymbol Module { get; } + + /// + /// Gets the class that declares this member. + /// + ITypeSymbol? DeclaringType { get; } + + /// + /// When overridden in a derived class, gets a value indicating the type of the member - method, constructor, event, and so on. + /// + MemberTypes MemberType { get; } + + /// + /// Gets a value that identifies a metadata element. + /// + int MetadataToken { get; } + + /// + /// Gets the name of the current member. + /// + string Name { get; } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IMethodBaseSymbol.cs b/src/IKVM.CoreLib/Symbols/IMethodBaseSymbol.cs new file mode 100644 index 0000000000..00b6144a0e --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IMethodBaseSymbol.cs @@ -0,0 +1,127 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Provides information about methods and constructors. + /// + interface IMethodBaseSymbol : IMemberSymbol + { + + /// + /// Gets the attributes associated with this method. + /// + MethodAttributes Attributes { get; } + + /// + /// Gets a value indicating the calling conventions for this method. + /// + CallingConventions CallingConvention { get; } + + /// + /// Gets a value indicating whether the generic method contains unassigned generic type parameters. + /// + bool ContainsGenericParameters { get; } + + /// + /// Gets a value indicating whether the method is abstract. + /// + bool IsAbstract { get; } + + /// + /// Gets a value indicating whether the potential visibility of this method or constructor is described by Assembly; that is, the method or constructor is visible at most to other types in the same assembly, and is not visible to derived types outside the assembly. + /// + bool IsAssembly { get; } + + /// + /// Gets a value indicating whether the method is a constructor. + /// + bool IsConstructor { get; } + + /// + /// Gets a value indicating whether the visibility of this method or constructor is described by Family; that is, the method or constructor is visible only within its class and derived classes. + /// + bool IsFamily { get; } + + /// + /// Gets a value indicating whether the visibility of this method or constructor is described by FamANDAssem; that is, the method or constructor can be called by derived classes, but only if they are in the same assembly. + /// + bool IsFamilyAndAssembly { get; } + + /// + /// Gets a value indicating whether the potential visibility of this method or constructor is described by FamORAssem; that is, the method or constructor can be called by derived classes wherever they are, and by classes in the same assembly. + /// + bool IsFamilyOrAssembly { get; } + + /// + /// Gets a value indicating whether this method is final. + /// + bool IsFinal { get; } + + /// + /// Gets a value indicating whether the method is generic. + /// + bool IsGenericMethod { get; } + + /// + /// Gets a value indicating whether the method is a generic method definition. + /// + bool IsGenericMethodDefinition { get; } + + /// + /// Gets a value indicating whether only a member of the same kind with exactly the same signature is hidden in the derived class. + /// + bool IsHideBySig { get; } + + /// + /// Gets a value indicating whether this member is private. + /// + bool IsPrivate { get; } + + /// + /// Gets a value indicating whether this is a public method. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether the method is static. + /// + bool IsStatic { get; } + + /// + /// Gets a value indicating whether the method is virtual. + /// + bool IsVirtual { get; } + + /// + /// Gets a value indicating whether this method has a special name. + /// + bool IsSpecialName { get; } + + /// + /// Gets the flags that specify the attributes of a method implementation. + /// + MethodImplAttributes MethodImplementationFlags { get; } + + /// + /// Returns an array of objects that represent the type arguments of a generic method or the type parameters of a generic method definition. + /// + /// + ITypeSymbol[] GetGenericArguments(); + + /// + /// When overridden in a derived class, gets the parameters of the specified method or constructor. + /// + /// + IParameterSymbol[] GetParameters(); + + /// + /// When overridden in a derived class, returns the MethodImplAttributes flags. + /// + /// + MethodImplAttributes GetMethodImplementationFlags(); + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IMethodSymbol.cs b/src/IKVM.CoreLib/Symbols/IMethodSymbol.cs new file mode 100644 index 0000000000..08d2f8dcb6 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IMethodSymbol.cs @@ -0,0 +1,46 @@ +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of a method and provides access to method metadata. + /// + interface IMethodSymbol : IMethodBaseSymbol + { + + /// + /// Gets a object that contains information about the return type of the method, such as whether the return type has custom modifiers. + /// + IParameterSymbol ReturnParameter { get; } + + /// + /// Gets the return type of this method. + /// + ITypeSymbol ReturnType { get; } + + /// + /// Gets the custom attributes for the return type. + /// + ICustomAttributeSymbolProvider ReturnTypeCustomAttributes { get; } + + /// + /// When overridden in a derived class, returns the object for the method on the direct or indirect base class in which the method represented by this instance was first declared. + /// + /// + IMethodSymbol GetBaseDefinition(); + + /// + /// Returns a object that represents a generic method definition from which the current method can be constructed. + /// + /// + IMethodSymbol GetGenericMethodDefinition(); + + /// + /// Substitutes the elements of an array of types for the type parameters of the current generic method definition, and returns a MethodInfo object representing the resulting constructed method. + /// + /// + /// + IMethodSymbol MakeGenericMethod(params ITypeSymbol[] typeArguments); + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IModuleSymbol.cs b/src/IKVM.CoreLib/Symbols/IModuleSymbol.cs new file mode 100644 index 0000000000..771d4263c2 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IModuleSymbol.cs @@ -0,0 +1,226 @@ +using System; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Performs reflection on a module. + /// + interface IModuleSymbol : ISymbol, ICustomAttributeSymbolProvider + { + + /// + /// Gets the appropriate for this instance of Module. + /// + IAssemblySymbol Assembly { get; } + + /// + /// Gets a string representing the fully qualified name and path to this module. + /// + string FullyQualifiedName { get; } + + /// + /// Gets a token that identifies the module in metadata. + /// + int MetadataToken { get; } + + /// + /// Gets a universally unique identifier (UUID) that can be used to distinguish between two versions of a module. + /// + Guid ModuleVersionId { get; } + + /// + /// Gets a representing the name of the module with the path removed. + /// + string Name { get; } + + /// + /// Gets a string representing the name of the module. + /// + string ScopeName { get; } + + /// + /// Gets a value indicating whether the object is a resource. + /// + /// + bool IsResource(); + + /// + /// Returns a field having the specified name. + /// + /// + /// + IFieldSymbol? GetField(string name); + + /// + /// Returns a field having the specified name and binding attributes. + /// + /// + /// + /// + IFieldSymbol? GetField(string name, BindingFlags bindingAttr); + + /// + /// Returns the global fields defined on the module that match the specified binding flags. + /// + /// + /// + IFieldSymbol[] GetFields(BindingFlags bindingFlags); + + /// + /// Returns the global fields defined on the module. + /// + /// + IFieldSymbol[] GetFields(); + + /// + /// Returns a method having the specified name. + /// + /// + /// + IMethodSymbol? GetMethod(string name); + + /// + /// Returns a method having the specified name and parameter types. + /// + /// + /// + /// + IMethodSymbol? GetMethod(string name, ITypeSymbol[] types); + + /// + /// Returns a method having the specified name, binding information, calling convention, and parameter types and modifiers. + /// + /// + /// + /// + /// + /// + /// + IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr, CallingConventions callConvention, ITypeSymbol[] types, ParameterModifier[]? modifiers); + + /// + /// Returns the global methods defined on the module. + /// + /// + IMethodSymbol[] GetMethods(); + + /// + /// Returns the global methods defined on the module that match the specified binding flags. + /// + /// + /// + IMethodSymbol[] GetMethods(BindingFlags bindingFlags); + + /// + /// Returns the specified type, performing a case-sensitive search. + /// + /// + /// + ITypeSymbol? GetType(string className); + + /// + /// Returns the specified type, searching the module with the specified case sensitivity. + /// + /// + /// + /// + ITypeSymbol? GetType(string className, bool ignoreCase); + + /// + /// Returns the specified type, specifying whether to make a case-sensitive search of the module and whether to throw an exception if the type cannot be found. + /// + /// + /// + /// + /// + ITypeSymbol? GetType(string className, bool throwOnError, bool ignoreCase); + + /// + /// Returns all the types defined within this module. + /// + /// + ITypeSymbol[] GetTypes(); + + /// + /// Returns the type identified by the specified metadata token. + /// + /// + /// + ITypeSymbol ResolveType(int metadataToken); + + /// + /// Returns the type identified by the specified metadata token, in the context defined by the specified generic type parameters. + /// + /// + /// + /// + /// + ITypeSymbol ResolveType(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments); + + /// + /// Returns the field identified by a metadata token. + /// + /// + /// + IFieldSymbol? ResolveField(int metadataToken); + + /// + /// Returns the field identified by the specified metadata token, in the context defined by the specified generic type parameters. + /// + /// + /// + /// + /// + IFieldSymbol? ResolveField(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments); + + /// + /// Returns the type or member identified by a metadata token. + /// + /// + /// + IMemberSymbol? ResolveMember(int metadataToken); + + /// + /// Returns the type or member identified by the specified metadata token, in the context defined by the specified generic type parameters. + /// + /// + /// + /// + /// + IMemberSymbol? ResolveMember(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments); + + /// + /// Returns the method or constructor identified by the specified metadata token. + /// + /// + /// + IMethodBaseSymbol? ResolveMethod(int metadataToken); + + /// + /// Returns the method or constructor identified by the specified metadata token, in the context defined by the specified generic type parameters. + /// + /// + /// + /// + /// + IMethodBaseSymbol? ResolveMethod(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments); + + /// + /// Returns the signature blob identified by a metadata token. + /// + /// + /// + byte[] ResolveSignature(int metadataToken); + + /// + /// Returns the string identified by the specified metadata token. + /// + /// + /// + string ResolveString(int metadataToken); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IParameterSymbol.cs b/src/IKVM.CoreLib/Symbols/IParameterSymbol.cs new file mode 100644 index 0000000000..033015ae7f --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IParameterSymbol.cs @@ -0,0 +1,79 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of a parameter and provides access to parameter metadata. + /// + interface IParameterSymbol : ISymbol, ICustomAttributeSymbolProvider + { + + /// + /// Gets the attributes for this parameter. + /// + ParameterAttributes Attributes { get; } + + /// + /// Gets a value indicating the member in which the parameter is implemented. + /// + IMemberSymbol Member { get; } + + /// + /// Gets the Type of this parameter. + /// + ITypeSymbol ParameterType { get; } + + /// + /// Gets the name of the parameter. + /// + string? Name { get; } + + /// + /// Gets the zero-based position of the parameter in the formal parameter list. + /// + int Position { get; } + + /// + /// Gets a value that indicates whether this parameter has a default value. + /// + bool HasDefaultValue { get; } + + /// + /// Gets a value indicating the default value if the parameter has a default value. + /// + object? DefaultValue { get; } + + /// + /// Gets a value indicating whether this is an input parameter. + /// + bool IsIn { get; } + + /// + /// Gets a value indicating whether this is an output parameter. + /// + bool IsOut { get; } + + /// + /// Gets a value indicating whether this parameter is optional. + /// + bool IsOptional { get; } + + /// + /// Gets a value indicating whether this parameter is a locale identifier (lcid). + /// + bool IsLcid { get; } + + /// + /// Gets a value indicating whether this is a Retval parameter. + /// + bool IsRetval { get; } + + /// + /// Gets a value that identifies this parameter in metadata. + /// + int MetadataToken { get; } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IPropertySymbol.cs b/src/IKVM.CoreLib/Symbols/IPropertySymbol.cs new file mode 100644 index 0000000000..0b73fbf861 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IPropertySymbol.cs @@ -0,0 +1,118 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Discovers the attributes of a property and provides access to property metadata. + /// + interface IPropertySymbol : IMemberSymbol + { + + /// + /// Gets the attributes for this property. + /// + PropertyAttributes Attributes { get; } + + /// + /// Gets the type of this property. + /// + ITypeSymbol PropertyType { get; } + + /// + /// Gets a value indicating whether the property can be read. + /// + bool CanRead { get; } + + /// + /// Gets a value indicating whether the property can be written to. + /// + bool CanWrite { get; } + + /// + /// Gets a value indicating whether the property is the special name. + /// + bool IsSpecialName { get; } + + /// + /// Returns a literal value associated with the property by a compiler. + /// + /// + object? GetRawConstantValue(); + + /// + /// Gets the get accessor for this property. + /// + IMethodSymbol? GetMethod { get; } + + /// + /// Gets the set accessor for this property. + /// + IMethodSymbol? SetMethod { get; } + + /// + /// Returns an array whose elements reflect the public get and set accessors of the property reflected by the current instance. + /// + /// + IMethodSymbol[] GetAccessors(); + + /// + /// Returns an array whose elements reflect the public and, if specified, non-public get and set accessors of the property reflected by the current instance. + /// + /// + /// + IMethodSymbol[] GetAccessors(bool nonPublic); + + /// + /// Returns the public get accessor for this property. + /// + /// + IMethodSymbol? GetGetMethod(); + + /// + /// When overridden in a derived class, returns the public or non-public get accessor for this property. + /// + /// + /// + IMethodSymbol? GetGetMethod(bool nonPublic); + + /// + /// Returns the public set accessor for this property. + /// + /// + IMethodSymbol? GetSetMethod(); + + /// + /// When overridden in a derived class, returns the set accessor for this property. + /// + /// + /// + IMethodSymbol? GetSetMethod(bool nonPublic); + + /// + /// When overridden in a derived class, returns an array of all the index parameters for the property. + /// + /// + IParameterSymbol[] GetIndexParameters(); + + /// + /// Gets the modified type of this property object. + /// + /// + ITypeSymbol GetModifiedPropertyType(); + + /// + /// Returns an array of types representing the optional custom modifiers of the property. + /// + /// + ITypeSymbol[] GetOptionalCustomModifiers(); + + /// + /// Returns an array of types representing the required custom modifiers of the property. + /// + /// + ITypeSymbol[] GetRequiredCustomModifiers(); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/ISymbol.cs b/src/IKVM.CoreLib/Symbols/ISymbol.cs new file mode 100644 index 0000000000..91abe16390 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/ISymbol.cs @@ -0,0 +1,17 @@ +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Provides common properties and methods for managed symbols. + /// + interface ISymbol + { + + /// + /// Returns true if the symbol is missing. + /// + bool IsMissing { get; } + + } + +} diff --git a/src/IKVM.Runtime/IManagedTypeResolver.cs b/src/IKVM.CoreLib/Symbols/ISymbolResolver.cs similarity index 62% rename from src/IKVM.Runtime/IManagedTypeResolver.cs rename to src/IKVM.CoreLib/Symbols/ISymbolResolver.cs index 1829ccb7bb..5a4815f8d0 100644 --- a/src/IKVM.Runtime/IManagedTypeResolver.cs +++ b/src/IKVM.CoreLib/Symbols/ISymbolResolver.cs @@ -1,20 +1,10 @@ -using System; - -#if IMPORTER || EXPORTER -using IKVM.Reflection; - -using Type = IKVM.Reflection.Type; -#else -using System.Reflection; -#endif - -namespace IKVM.Runtime +namespace IKVM.CoreLib.Symbols { /// - /// Provides an interface to resolve a managed type. + /// Provides an interface to resolve a maaged type symbols. /// - public interface IManagedTypeResolver + interface ISymbolResolver { /// @@ -22,27 +12,27 @@ public interface IManagedTypeResolver /// /// /// - Type ResolveRuntimeType(string typeName); + ITypeSymbol? ResolveRuntimeType(string typeName); /// /// Resolves the named assembly from any reference source. /// /// /// - Assembly ResolveAssembly(string assemblyName); + IAssemblySymbol? ResolveAssembly(string assemblyName); /// /// Resolves the named type from any reference source. /// /// /// - Type ResolveCoreType(string typeName); + ITypeSymbol? ResolveCoreType(string typeName); /// /// Resolves the known Java base assembly. /// /// - Assembly ResolveBaseAssembly(); + IAssemblySymbol? ResolveBaseAssembly(); } diff --git a/src/IKVM.CoreLib/Symbols/ITypeSymbol.cs b/src/IKVM.CoreLib/Symbols/ITypeSymbol.cs new file mode 100644 index 0000000000..377a82aa6f --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/ITypeSymbol.cs @@ -0,0 +1,597 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols +{ + + /// + /// Represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types. + /// + interface ITypeSymbol : IMemberSymbol + { + + /// + /// Gets the attributes associated with the . + /// + TypeAttributes Attributes { get; } + + /// + /// Gets the in which the type is declared. For generic types, gets the in which the generic type is defined. + /// + IAssemblySymbol Assembly { get; } + + /// + /// Gets a that represents the declaring method, if the current represents a type parameter of a generic method. + /// + IMethodBaseSymbol? DeclaringMethod { get; } + + /// + /// Gets the assembly-qualified name of the type, which includes the name of the assembly from which this object was loaded. + /// + string? AssemblyQualifiedName { get; } + + /// + /// Gets the fully qualified name of the type, including its namespace but not its assembly. + /// + string? FullName { get; } + + /// + /// Gets the namespace of the . + /// + string? Namespace { get; } + + /// + /// Gets the type from which the current directly inherits. + /// + ITypeSymbol? BaseType { get; } + + /// + /// Gets a value indicating whether the current object has type parameters that have not been replaced by specific types. + /// + bool ContainsGenericParameters { get; } + + /// + /// Gets a combination of flags that describe the covariance and special constraints of the current generic type parameter. + /// + GenericParameterAttributes GenericParameterAttributes { get; } + + /// + /// Gets the position of the type parameter in the type parameter list of the generic type or method that declared the parameter, when the object represents a type parameter of a generic type or a generic method. + /// + int GenericParameterPosition { get; } + + /// + /// Gets an array of the generic type arguments for this type. + /// + ITypeSymbol[] GenericTypeArguments { get; } + + /// + /// Gets a value that indicates whether this object represents a constructed generic type. You can create instances of a constructed generic type. + /// + bool IsConstructedGenericType { get; } + + /// + /// Gets a value indicating whether the current represents a type parameter in the definition of a generic type or method. + /// + bool IsGenericParameter { get; } + + /// + /// Gets a value indicating whether the current type is a generic type. + /// + bool IsGenericType { get; } + + /// + /// Gets a value indicating whether the fields of the current type are laid out automatically by the common language runtime. + /// + bool IsAutoLayout { get; } + + /// + /// Gets a value indicating whether the fields of the current type are laid out at explicitly specified offsets. + /// + bool IsExplicitLayout { get; } + + /// + /// Gets a value indicating whether the fields of the current type are laid out sequentially, in the order that they were defined or emitted to the metadata. + /// + bool IsLayoutSequential { get; } + + /// + /// Gets a value indicating whether the current encompasses or refers to another type; that is, whether the current is an array, a pointer, or is passed by reference. + /// + bool HasElementType { get; } + + /// + /// Gets a value indicating whether the is a class or a delegate; that is, not a value type or interface. + /// + bool IsClass { get; } + + /// + /// Gets a value indicating whether the is a value type. + /// + bool IsValueType { get; } + + /// + /// Gets a value indicating whether the is an interface; that is, not a class or a value type. + /// + bool IsInterface { get; } + + /// + /// Gets a value indicating whether the is one of the primitive types. + /// + bool IsPrimitive { get; } + + /// + /// Gets a value that indicates whether the type is an array. + /// + bool IsArray { get; } + + /// + /// Gets a value indicating whether the current represents an enumeration. + /// + bool IsEnum { get; } + + /// + /// Gets a value indicating whether the is a pointer. + /// + bool IsPointer { get; } + + /// + /// Gets a value indicating whether the is passed by reference. + /// + bool IsByRef { get; } + + /// + /// Gets a value indicating whether the is abstract and must be overridden. + /// + bool IsAbstract { get; } + + /// + /// Gets a value indicating whether the is declared sealed. + /// + bool IsSealed { get; } + + /// + /// Gets a value indicating whether the can be accessed by code outside the assembly. + /// + bool IsVisible { get; } + + /// + /// Gets a value indicating whether the is declared public. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether the is not declared public. + /// + bool IsNotPublic { get; } + + /// + /// Gets a value indicating whether the current object represents a type whose definition is nested inside the definition of another type. + /// + bool IsNested { get; } + + /// + /// Gets a value indicating whether the is nested and visible only within its own assembly. + /// + bool IsNestedAssembly { get; } + + /// + /// Gets a value indicating whether the is nested and visible only to classes that belong to both its own family and its own assembly. + /// + bool IsNestedFamANDAssem { get; } + + /// + /// Gets a value indicating whether the is nested and visible only within its own family. + /// + bool IsNestedFamily { get; } + + /// + /// Gets a value indicating whether the is nested and visible only to classes that belong to either its own family or to its own assembly. + /// + bool IsNestedFamORAssem { get; } + + /// + /// Gets a value indicating whether the is nested and declared private. + /// + bool IsNestedPrivate { get; } + + /// + /// Gets a value indicating whether a class is nested and declared public. + /// + bool IsNestedPublic { get; } + + /// + /// Gets a value indicating whether the is binary serializable. + /// + bool IsSerializable { get; } + + /// + /// Gets the initializer for the type. + /// + IConstructorSymbol? TypeInitializer { get; } + + /// + /// Gets the number of dimensions in an array. + /// + /// + int GetArrayRank(); + + /// + /// Searches for the members defined for the current whose DefaultMemberAttribute is set. + /// + /// + IMemberSymbol[] GetDefaultMembers(); + + /// + /// When overridden in a derived class, returns the of the object encompassed or referred to by the current array, pointer or reference type. + /// + /// + ITypeSymbol? GetElementType(); + + /// + /// Returns the name of the constant that has the specified value, for the current enumeration type. + /// + /// + /// + string? GetEnumName(object value); + + /// + /// Returns the names of the members of the current enumeration type. + /// + /// + string[] GetEnumNames(); + + /// + /// Returns the underlying type of the current enumeration type. + /// + /// + ITypeSymbol GetEnumUnderlyingType(); + + /// + /// Returns an array of objects that represent the type arguments of a closed generic type or the type parameters of a generic type definition. + /// + /// + ITypeSymbol[] GetGenericArguments(); + + /// + /// Returns an array of objects that represent the constraints on the current generic type parameter. + /// + /// + ITypeSymbol[] GetGenericParameterConstraints(); + + /// + /// Returns a object that represents a generic type definition from which the current generic type can be constructed. + /// + /// + ITypeSymbol GetGenericTypeDefinition(); + + /// + /// Searches for the interface with the specified name. + /// + /// + /// + ITypeSymbol? GetInterface(string name); + + /// + /// When overridden in a derived class, searches for the specified interface, specifying whether to do a case-insensitive search for the interface name. + /// + /// + /// + /// + ITypeSymbol? GetInterface(string name, bool ignoreCase); + + /// + /// When overridden in a derived class, gets all the interfaces implemented or inherited by the current . + /// + /// + ITypeSymbol[] GetInterfaces(); + + /// + /// Returns an interface mapping for the specified interface type. + /// + /// + /// + InterfaceMapping GetInterfaceMap(ITypeSymbol interfaceType); + + /// + /// Searches for the public members with the specified name. + /// + /// + /// + IMemberSymbol[] GetMember(string name); + + /// + /// Searches for the specified members, using the specified binding constraints. + /// + /// + /// + /// + IMemberSymbol[] GetMember(string name, BindingFlags bindingAttr); + + /// + /// Searches for the specified members of the specified member type, using the specified binding constraints. + /// + /// + /// + /// + /// + IMemberSymbol[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr); + + /// + /// Returns all the public members of the current . + /// + /// + IMemberSymbol[] GetMembers(); + + /// + /// When overridden in a derived class, searches for the members defined for the current , using the specified binding constraints. + /// + /// + /// + IMemberSymbol[] GetMembers(BindingFlags bindingAttr); + + /// + /// Searches for a public instance constructor whose parameters match the types in the specified array. + /// + /// + /// + IConstructorSymbol? GetConstructor(ITypeSymbol[] types); + + /// + /// Searches for a constructor whose parameters match the specified argument types, using the specified binding constraints. + /// + /// + /// + /// + IConstructorSymbol? GetConstructor(BindingFlags bindingAttr, ITypeSymbol[] types); + + /// + /// Returns all the public constructors defined for the current . + /// + /// + IConstructorSymbol[] GetConstructors(); + + /// + /// When overridden in a derived class, searches for the constructors defined for the current , using the specified BindingFlags. + /// + /// + /// + IConstructorSymbol[] GetConstructors(BindingFlags bindingAttr); + + /// + /// Searches for the public field with the specified name. + /// + /// + /// + IFieldSymbol? GetField(string name); + + /// + /// Searches for the specified field, using the specified binding constraints. + /// + /// + /// + /// + IFieldSymbol? GetField(string name, BindingFlags bindingAttr); + + /// + /// Returns all the public fields of the current . + /// + /// + IFieldSymbol[] GetFields(); + + /// + /// When overridden in a derived class, searches for the fields defined for the current , using the specified binding constraints. + /// + /// + /// + IFieldSymbol[] GetFields(BindingFlags bindingAttr); + + /// + /// Searches for the public method with the specified name. + /// + /// + /// + IMethodSymbol? GetMethod(string name); + + /// + /// Searches for the specified public method whose parameters match the specified argument types. + /// + /// + /// + /// + IMethodSymbol? GetMethod(string name, ITypeSymbol[] types); + + /// + /// Searches for the specified method, using the specified binding constraints. + /// + /// + /// + /// + IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr); + + /// + /// Searches for the specified method whose parameters match the specified argument types, using the specified binding constraints. + /// + /// + /// + /// + /// + IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr, ITypeSymbol[] types); + + /// + /// Returns all the public methods of the current . + /// + /// + IMethodSymbol[] GetMethods(); + + /// + /// When overridden in a derived class, searches for the methods defined for the current , using the specified binding constraints. + /// + /// + /// + IMethodSymbol[] GetMethods(BindingFlags bindingAttr); + + /// + /// Searches for the public property with the specified name. + /// + /// + /// + IPropertySymbol? GetProperty(string name); + + /// + /// Searches for the specified property, using the specified binding constraints. + /// + /// + /// + /// + IPropertySymbol? GetProperty(string name, BindingFlags bindingAttr); + + /// + /// Searches for the specified public property whose parameters match the specified argument types. + /// + /// + /// + /// + IPropertySymbol? GetProperty(string name, ITypeSymbol[] types); + + /// + /// Searches for the specified public property whose parameters match the specified argument types. + /// + /// + /// + /// + /// + IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType, ITypeSymbol[] types); + + /// + /// Searches for the public property with the specified name and return type. + /// + /// + /// + /// + IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType); + + /// + /// Returns all the public properties of the current . + /// + /// + IPropertySymbol[] GetProperties(); + + /// + /// When overridden in a derived class, searches for the properties of the current , using the specified binding constraints. + /// + /// + /// + IPropertySymbol[] GetProperties(BindingFlags bindingAttr); + + /// + /// Returns the EventInfo object representing the specified public event. + /// + /// + /// + IEventSymbol? GetEvent(string name); + + /// + /// When overridden in a derived class, returns the EventInfo object representing the specified event, using the specified binding constraints. + /// + /// + /// + /// + IEventSymbol? GetEvent(string name, BindingFlags bindingAttr); + + /// + /// Returns all the public events that are declared or inherited by the current . + /// + /// + IEventSymbol[] GetEvents(); + + /// + /// When overridden in a derived class, searches for events that are declared or inherited by the current , using the specified binding constraints. + /// + /// + /// + IEventSymbol[] GetEvents(BindingFlags bindingAttr); + + /// + /// Searches for the public nested type with the specified name. + /// + /// + /// + ITypeSymbol? GetNestedType(string name); + + /// + /// When overridden in a derived class, searches for the specified nested type, using the specified binding constraints. + /// + /// + /// + /// + ITypeSymbol? GetNestedType(string name, BindingFlags bindingAttr); + + /// + /// Returns the public types nested in the current . + /// + /// + ITypeSymbol[] GetNestedTypes(); + + /// + /// When overridden in a derived class, searches for the types nested in the current , using the specified binding constraints. + /// + /// + /// + ITypeSymbol[] GetNestedTypes(BindingFlags bindingAttr); + + /// + /// Determines whether an instance of a specified type c can be assigned to a variable of the current type. + /// + /// + /// + bool IsAssignableFrom(ITypeSymbol? c); + + /// + /// Determines whether the current derives from the specified . + /// + /// + /// + bool IsSubclassOf(ITypeSymbol c); + + /// + /// Returns a value that indicates whether the specified value exists in the current enumeration type. + /// + /// + /// + bool IsEnumDefined(object value); + + /// + /// Returns a object representing a one-dimensional array of the current type, with a lower bound of zero. + /// + /// + ITypeSymbol MakeArrayType(); + + /// + /// Returns a object representing an array of the current type, with the specified number of dimensions. + /// + /// + /// + ITypeSymbol MakeArrayType(int rank); + + /// + /// Substitutes the elements of an array of types for the type parameters of the current generic type definition and returns a object representing the resulting constructed type. + /// + /// + /// + ITypeSymbol MakeGenericType(params ITypeSymbol[] typeArguments); + + /// + /// Returns a object that represents a pointer to the current type. + /// + /// + ITypeSymbol MakePointerType(); + + /// + /// Returns a object that represents the current type when passed as a ref parameter (ByRef parameter in Visual Basic). + /// + /// + ITypeSymbol MakeByRefType(); + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionAssemblySymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionAssemblySymbol.cs new file mode 100644 index 0000000000..12920dd971 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionAssemblySymbol.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +using Assembly = IKVM.Reflection.Assembly; +using AssemblyName = IKVM.Reflection.AssemblyName; +using Module = IKVM.Reflection.Module; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionAssemblySymbol : IkvmReflectionSymbol, IAssemblySymbol + { + + readonly Assembly _assembly; + readonly ConditionalWeakTable _modules = new(); + + System.Reflection.AssemblyName? _assemblyName; + + /// + /// Initializes a new instance. + /// + /// + /// + public IkvmReflectionAssemblySymbol(IkvmReflectionSymbolContext context, Assembly assembly) : + base(context) + { + _assembly = assembly ?? throw new ArgumentNullException(nameof(assembly)); + } + + /// + /// Gets or creates the cached for the module. + /// + /// + /// + /// + internal IkvmReflectionModuleSymbol GetOrCreateModuleSymbol(Module module) + { + Debug.Assert(module.Assembly == _assembly); + return _modules.GetValue(module, _ => new IkvmReflectionModuleSymbol(Context, _)); + } + + internal Assembly ReflectionObject => _assembly; + + public IEnumerable DefinedTypes => ResolveTypeSymbols(_assembly.DefinedTypes); + + public IMethodSymbol? EntryPoint => _assembly.EntryPoint is { } m ? ResolveMethodSymbol(m) : null; + + public IEnumerable ExportedTypes => ResolveTypeSymbols(_assembly.ExportedTypes); + + public string? FullName => _assembly.FullName; + + public string ImageRuntimeVersion => _assembly.ImageRuntimeVersion; + + public IModuleSymbol ManifestModule => ResolveModuleSymbol(_assembly.ManifestModule); + + public IEnumerable Modules => ResolveModuleSymbols(_assembly.Modules); + + public override bool IsMissing => _assembly.__IsMissing; + + public ITypeSymbol[] GetExportedTypes() + { + return ResolveTypeSymbols(_assembly.GetExportedTypes()); + } + + public IModuleSymbol? GetModule(string name) + { + return _assembly.GetModule(name) is Module m ? GetOrCreateModuleSymbol(m) : null; + } + + public IModuleSymbol[] GetModules() + { + return ResolveModuleSymbols(_assembly.GetModules()); + } + + public IModuleSymbol[] GetModules(bool getResourceModules) + { + return ResolveModuleSymbols(_assembly.GetModules(getResourceModules)); + } + + System.Reflection.AssemblyName ToName(AssemblyName src) + { +#pragma warning disable SYSLIB0037 // Type or member is obsolete + return new System.Reflection.AssemblyName() + { + Name = src.Name, + Version = src.Version, + CultureName = src.CultureName, + HashAlgorithm = (System.Configuration.Assemblies.AssemblyHashAlgorithm)src.HashAlgorithm, + Flags = (System.Reflection.AssemblyNameFlags)src.Flags, + ContentType = (System.Reflection.AssemblyContentType)src.ContentType, + }; +#pragma warning restore SYSLIB0037 // Type or member is obsolete + } + + public System.Reflection.AssemblyName GetName() + { + return _assemblyName ??= ToName(_assembly.GetName()); + } + + public System.Reflection.AssemblyName GetName(bool copiedName) + { + return ToName(_assembly.GetName()); + } + + public System.Reflection.AssemblyName[] GetReferencedAssemblies() + { + var l = _assembly.GetReferencedAssemblies(); + var a = new System.Reflection.AssemblyName[l.Length]; + for (int i = 0; i < l.Length; i++) + a[i] = ToName(l[i]); + + return a; + } + + public ITypeSymbol? GetType(string name, bool throwOnError) + { + return _assembly.GetType(name, throwOnError) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol? GetType(string name, bool throwOnError, bool ignoreCase) + { + return _assembly.GetType(name, throwOnError, ignoreCase) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol? GetType(string name) + { + return _assembly.GetType(name) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol[] GetTypes() + { + return ResolveTypeSymbols(_assembly.GetTypes()); + } + + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_assembly.GetCustomAttributesData()); + } + + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_assembly.__GetCustomAttributes(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false)); + } + + public bool IsDefined(ITypeSymbol attributeType) + { + return _assembly.IsDefined(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionConstructorSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionConstructorSymbol.cs new file mode 100644 index 0000000000..4a312beb3f --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionConstructorSymbol.cs @@ -0,0 +1,26 @@ +using ConstructorInfo = IKVM.Reflection.ConstructorInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionConstructorSymbol : IkvmReflectionMethodBaseSymbol, IConstructorSymbol + { + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public IkvmReflectionConstructorSymbol(IkvmReflectionSymbolContext context, IkvmReflectionModuleSymbol module, IkvmReflectionTypeSymbol type, ConstructorInfo ctor) : + base(context, module, type, ctor) + { + + } + + internal new ConstructorInfo ReflectionObject => (ConstructorInfo)base.ReflectionObject; + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionEventSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionEventSymbol.cs new file mode 100644 index 0000000000..6ba509c128 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionEventSymbol.cs @@ -0,0 +1,79 @@ +using System; + +using EventInfo = IKVM.Reflection.EventInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionEventSymbol : IkvmReflectionMemberSymbol, IEventSymbol + { + + readonly EventInfo _event; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionEventSymbol(IkvmReflectionSymbolContext context, IkvmReflectionTypeSymbol type, EventInfo @event) : + base(context, type.ContainingModule, type, @event) + { + _event = @event ?? throw new ArgumentNullException(nameof(@event)); + } + + public IMethodSymbol? AddMethod => _event.AddMethod is { } m ? ResolveMethodSymbol(m) : null; + + public System.Reflection.EventAttributes Attributes => (System.Reflection.EventAttributes)_event.Attributes; + + public ITypeSymbol? EventHandlerType => _event.EventHandlerType is { } m ? ResolveTypeSymbol(m) : null; + + public bool IsSpecialName => _event.IsSpecialName; + + public IMethodSymbol? RaiseMethod => _event.RaiseMethod is { } m ? ResolveMethodSymbol(m) : null; + + public IMethodSymbol? RemoveMethod => _event.RemoveMethod is { } m ? ResolveMethodSymbol(m) : null; + + public IMethodSymbol? GetAddMethod() + { + return _event.GetAddMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetAddMethod(bool nonPublic) + { + return _event.GetAddMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol[] GetOtherMethods() + { + return ResolveMethodSymbols(_event.GetOtherMethods()); + } + + public IMethodSymbol[] GetOtherMethods(bool nonPublic) + { + return ResolveMethodSymbols(_event.GetOtherMethods(nonPublic)); + } + + public IMethodSymbol? GetRaiseMethod() + { + return _event.GetRaiseMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetRaiseMethod(bool nonPublic) + { + return _event.GetRaiseMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetRemoveMethod(bool nonPublic) + { + return _event.GetRemoveMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetRemoveMethod() + { + return _event.GetRemoveMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionFieldSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionFieldSymbol.cs new file mode 100644 index 0000000000..2696069963 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionFieldSymbol.cs @@ -0,0 +1,74 @@ +using System; + +using FieldInfo = IKVM.Reflection.FieldInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionFieldSymbol : IkvmReflectionMemberSymbol, IFieldSymbol + { + + readonly FieldInfo _field; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionFieldSymbol(IkvmReflectionSymbolContext context, IkvmReflectionTypeSymbol type, FieldInfo field) : + base(context, type.ContainingModule, type, field) + { + _field = field ?? throw new ArgumentNullException(nameof(field)); + } + + internal new FieldInfo ReflectionObject => (FieldInfo)base.ReflectionObject; + + public System.Reflection.FieldAttributes Attributes => (System.Reflection.FieldAttributes)_field.Attributes; + + public ITypeSymbol FieldType => ResolveTypeSymbol(_field.FieldType); + + public bool IsAssembly => _field.IsAssembly; + + public bool IsFamily => _field.IsFamily; + + public bool IsFamilyAndAssembly => _field.IsFamilyAndAssembly; + + public bool IsFamilyOrAssembly => _field.IsFamilyOrAssembly; + + public bool IsInitOnly => _field.IsInitOnly; + + public bool IsLiteral => _field.IsLiteral; + +#pragma warning disable SYSLIB0050 // Type or member is obsolete + public bool IsNotSerialized => _field.IsNotSerialized; +#pragma warning restore SYSLIB0050 // Type or member is obsolete + + public bool IsPinvokeImpl => _field.IsPinvokeImpl; + + public bool IsPrivate => _field.IsPrivate; + + public bool IsPublic => _field.IsPublic; + + public bool IsSpecialName => _field.IsSpecialName; + + public bool IsStatic => _field.IsStatic; + + public ITypeSymbol[] GetOptionalCustomModifiers() + { + return ResolveTypeSymbols(_field.GetOptionalCustomModifiers()); + } + + public object? GetRawConstantValue() + { + return _field.GetRawConstantValue(); + } + + public ITypeSymbol[] GetRequiredCustomModifiers() + { + return ResolveTypeSymbols(_field.GetRequiredCustomModifiers()); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMemberSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMemberSymbol.cs new file mode 100644 index 0000000000..e32966d91f --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMemberSymbol.cs @@ -0,0 +1,164 @@ +using System; +using System.Linq; + +using ConstructorInfo = IKVM.Reflection.ConstructorInfo; +using EventInfo = IKVM.Reflection.EventInfo; +using FieldInfo = IKVM.Reflection.FieldInfo; +using MemberInfo = IKVM.Reflection.MemberInfo; +using MethodInfo = IKVM.Reflection.MethodInfo; +using PropertyInfo = IKVM.Reflection.PropertyInfo; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + abstract class IkvmReflectionMemberSymbol : IkvmReflectionSymbol, IMemberSymbol + { + + readonly IkvmReflectionModuleSymbol _module; + readonly IkvmReflectionTypeSymbol? _type; + readonly MemberInfo _member; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public IkvmReflectionMemberSymbol(IkvmReflectionSymbolContext context, IkvmReflectionModuleSymbol module, IkvmReflectionTypeSymbol? type, MemberInfo member) : + base(context) + { + _module = module ?? throw new ArgumentNullException(nameof(module)); + _type = type; + _member = member ?? throw new ArgumentNullException(nameof(member)); + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected internal override IkvmReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + if (_type != null && type == _type.ReflectionObject) + return _type; + else if (type.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(type); + else + return base.ResolveTypeSymbol(type); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected internal override IkvmReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + if (_type != null && ctor.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateConstructorSymbol(ctor); + else if (ctor.DeclaringType != null && ctor.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(ctor.DeclaringType).GetOrCreateConstructorSymbol(ctor); + else + return base.ResolveConstructorSymbol(ctor); + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected internal override IkvmReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + if (_type != null && method.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateMethodSymbol(method); + else if (method.DeclaringType != null && method.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(method.DeclaringType).GetOrCreateMethodSymbol(method); + else + return base.ResolveMethodSymbol(method); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override IkvmReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + if (_type != null && field.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateFieldSymbol(field); + else if (field.DeclaringType != null && field.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(field.DeclaringType).GetOrCreateFieldSymbol(field); + else + return base.ResolveFieldSymbol(field); + } + + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override IkvmReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + + if (_type != null && property.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreatePropertySymbol(property); + else if (property.DeclaringType != null && property.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(property.DeclaringType).GetOrCreatePropertySymbol(property); + else + return base.ResolvePropertySymbol(property); + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected internal override IkvmReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + if (_type != null && @event.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateEventSymbol(@event); + else if (@event.DeclaringType != null && @event.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(@event.DeclaringType).GetOrCreateEventSymbol(@event); + else + return base.ResolveEventSymbol(@event); + } + + internal MemberInfo ReflectionObject => _member; + + internal IkvmReflectionModuleSymbol ContainingModule => _module; + + internal IkvmReflectionTypeSymbol? ContainingType => _type; + + public virtual ITypeSymbol? DeclaringType => _member.DeclaringType is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + + public virtual System.Reflection.MemberTypes MemberType => (System.Reflection.MemberTypes)_member.MemberType; + + public virtual int MetadataToken => _member.MetadataToken; + + public virtual IModuleSymbol Module => Context.GetOrCreateModuleSymbol(_member.Module); + + public virtual string Name => _member.Name; + + public override bool IsMissing => _member.__IsMissing; + + public virtual CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_member.GetCustomAttributesData()); + } + + public virtual CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_member.GetCustomAttributesData()).Where(i => i.AttributeType == attributeType).ToArray(); + } + + public virtual bool IsDefined(ITypeSymbol attributeType) + { + return _member.IsDefined(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodBaseSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodBaseSymbol.cs new file mode 100644 index 0000000000..644d3f05c1 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodBaseSymbol.cs @@ -0,0 +1,129 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; + +using MethodBase = IKVM.Reflection.MethodBase; +using ParameterInfo = IKVM.Reflection.ParameterInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + abstract class IkvmReflectionMethodBaseSymbol : IkvmReflectionMemberSymbol, IMethodBaseSymbol + { + + readonly MethodBase _method; + + ParameterInfo[]? _parametersSource; + IkvmReflectionParameterSymbol?[]? _parameters; + IkvmReflectionParameterSymbol? _returnParameter; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public IkvmReflectionMethodBaseSymbol(IkvmReflectionSymbolContext context, IkvmReflectionModuleSymbol module, IkvmReflectionTypeSymbol? type, MethodBase method) : + base(context, module, type, method) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal IkvmReflectionParameterSymbol GetOrCreateParameterSymbol(ParameterInfo parameter) + { + if (parameter is null) + throw new ArgumentNullException(nameof(parameter)); + + Debug.Assert(parameter.Member == _method); + + if (_parametersSource == null) + Interlocked.CompareExchange(ref _parametersSource, _method.GetParameters().OrderBy(i => i.Position).ToArray(), null); + if (_parameters == null) + Interlocked.CompareExchange(ref _parameters, new IkvmReflectionParameterSymbol?[_parametersSource.Length], null); + + // index of current record + var idx = parameter.Position; + Debug.Assert(idx >= -1); + Debug.Assert(idx < _parametersSource.Length); + + // check that our list is long enough to contain the entire table + if (idx >= 0 && _parameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _returnParameter; + if (idx >= 0) + rec = ref _parameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionParameterSymbol(Context, this, parameter), null); + + // this should never happen + if (rec is not IkvmReflectionParameterSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + public System.Reflection.MethodAttributes Attributes => (System.Reflection.MethodAttributes)_method.Attributes; + + public System.Reflection.CallingConventions CallingConvention => (System.Reflection.CallingConventions)_method.CallingConvention; + + public bool ContainsGenericParameters => _method.ContainsGenericParameters; + + public bool IsAbstract => _method.IsAbstract; + + public bool IsAssembly => _method.IsAssembly; + + public bool IsConstructor => _method.IsConstructor; + + public bool IsFamily => _method.IsFamily; + + public bool IsFamilyAndAssembly => _method.IsFamilyAndAssembly; + + public bool IsFamilyOrAssembly => _method.IsFamilyOrAssembly; + + public bool IsFinal => _method.IsFinal; + + public bool IsGenericMethod => _method.IsGenericMethod; + + public bool IsGenericMethodDefinition => _method.IsGenericMethodDefinition; + + public bool IsHideBySig => _method.IsHideBySig; + + public bool IsPrivate => _method.IsPrivate; + + public bool IsPublic => _method.IsPublic; + + public bool IsSpecialName => _method.IsSpecialName; + + public bool IsStatic => _method.IsStatic; + + public bool IsVirtual => _method.IsVirtual; + + public System.Reflection.MethodImplAttributes MethodImplementationFlags => (System.Reflection.MethodImplAttributes)_method.MethodImplementationFlags; + + public ITypeSymbol[] GetGenericArguments() + { + return ResolveTypeSymbols(_method.GetGenericArguments()); + } + + public System.Reflection.MethodImplAttributes GetMethodImplementationFlags() + { + return (System.Reflection.MethodImplAttributes)_method.GetMethodImplementationFlags(); + } + + public IParameterSymbol[] GetParameters() + { + return ResolveParameterSymbols(_method.GetParameters()); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodSymbol.cs new file mode 100644 index 0000000000..51fbc6a326 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionMethodSymbol.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; + +using MethodInfo = IKVM.Reflection.MethodInfo; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionMethodSymbol : IkvmReflectionMethodBaseSymbol, IMethodSymbol + { + + readonly MethodInfo _method; + + Type[]? _genericParametersSource; + IkvmReflectionTypeSymbol?[]? _genericParameters; + List<(Type[] Arguments, IkvmReflectionMethodSymbol Symbol)>? _genericTypes; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public IkvmReflectionMethodSymbol(IkvmReflectionSymbolContext context, IkvmReflectionModuleSymbol module, IkvmReflectionTypeSymbol? type, MethodInfo method) : + base(context, module, type, method) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal IkvmReflectionTypeSymbol GetOrCreateGenericParameterSymbol(Type genericParameterType) + { + if (genericParameterType is null) + throw new ArgumentNullException(nameof(genericParameterType)); + + Debug.Assert(genericParameterType.DeclaringMethod == _method); + + // initialize tables + _genericParametersSource ??= _method.GetGenericArguments(); + _genericParameters ??= new IkvmReflectionTypeSymbol?[_genericParametersSource.Length]; + + // position of the parameter in the list + var idx = genericParameterType.GenericParameterPosition; + + // check that our list is long enough to contain the entire table + if (_genericParameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _genericParameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionTypeSymbol(Context, ContainingModule, genericParameterType), null); + + // this should never happen + if (rec is not IkvmReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal IkvmReflectionMethodSymbol GetOrCreateGenericTypeSymbol(Type[] genericMethodArguments) + { + if (genericMethodArguments is null) + throw new ArgumentNullException(nameof(genericMethodArguments)); + + if (_method.IsGenericMethodDefinition == false) + throw new InvalidOperationException(); + + // initialize the available parameters + _genericParametersSource ??= _method.GetGenericArguments(); + if (_genericParametersSource.Length != genericMethodArguments.Length) + throw new InvalidOperationException(); + + // initialize generic type map, and lock on it since we're potentially adding items + _genericTypes ??= []; + lock (_genericTypes) + { + // find existing entry + foreach (var i in _genericTypes) + if (i.Arguments.SequenceEqual(genericMethodArguments)) + return i.Symbol; + + // generate new symbol + var sym = new IkvmReflectionMethodSymbol(Context, ContainingModule, ContainingType, _method.MakeGenericMethod(genericMethodArguments)); + _genericTypes.Add((genericMethodArguments, sym)); + return sym; + } + } + + internal new MethodInfo ReflectionObject => (MethodInfo)base.ReflectionObject; + + public IParameterSymbol ReturnParameter => ResolveParameterSymbol(_method.ReturnParameter); + + public ITypeSymbol ReturnType => ResolveTypeSymbol(_method.ReturnType); + + public ICustomAttributeSymbolProvider ReturnTypeCustomAttributes => throw new NotImplementedException(); + + public IMethodSymbol GetBaseDefinition() + { + return ResolveMethodSymbol(_method.GetBaseDefinition()); + } + + public IMethodSymbol GetGenericMethodDefinition() + { + return ResolveMethodSymbol(_method.GetGenericMethodDefinition()); + } + + public IMethodSymbol MakeGenericMethod(params ITypeSymbol[] typeArguments) + { + return ResolveMethodSymbol(_method.MakeGenericMethod(UnpackTypeSymbols(typeArguments))); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionModuleSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionModuleSymbol.cs new file mode 100644 index 0000000000..9c30b305a4 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionModuleSymbol.cs @@ -0,0 +1,357 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Threading; + +using IKVM.Reflection; + +using Module = IKVM.Reflection.Module; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + /// + /// Implementation of derived from System.Reflection. + /// + class IkvmReflectionModuleSymbol : IkvmReflectionSymbol, IModuleSymbol + { + + /// + /// Returns true if the given is a TypeDef. That is, not a modified or substituted or generic parameter type. + /// + /// + /// + static bool IsTypeDefinition(Type type) + { + return type.HasElementType == false && type.IsConstructedGenericType == false && type.IsGenericParameter == false; + } + + readonly Module _module; + + Type[]? _typesSource; + int _typesBaseRow; + IkvmReflectionTypeSymbol?[]? _types; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionModuleSymbol(IkvmReflectionSymbolContext context, Module module) : + base(context) + { + _module = module ?? throw new ArgumentNullException(nameof(module)); + } + + /// + /// Gets the wrapped . + /// + internal Module ReflectionObject => _module; + + /// + /// Gets or creates the cached for the module by type. + /// + /// + /// + /// + internal IkvmReflectionTypeSymbol GetOrCreateTypeSymbol(Type type) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + Debug.Assert(type.Module == _module); + + // type is not a definition, but is substituted + if (IsTypeDefinition(type) == false) + return GetOrCreateTypeSymbolForSpecification(type); + + // look up handle and row + var hnd = MetadataTokens.TypeDefinitionHandle(type.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_typesSource == null) + { + _typesSource = _module.GetTypes().OrderBy(i => i.MetadataToken).ToArray(); + _typesBaseRow = _typesSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_typesSource[0].MetadataToken)) : 0; + } + + // initialize cache table + _types ??= new IkvmReflectionTypeSymbol?[_typesSource.Length]; + + // index of current record is specified row - base + var idx = row - _typesBaseRow; + if (idx < 0) + throw new Exception(); + + Debug.Assert(idx >= 0); + Debug.Assert(idx < _typesSource.Length); + + // check that our type list is long enough to contain the entire table + if (_types.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + if (_types[idx] == null) + Interlocked.CompareExchange(ref _types[idx], new IkvmReflectionTypeSymbol(Context, this, type), null); + + // this should never happen + if (_types[idx] is not IkvmReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// For a given + /// + /// + /// + IkvmReflectionTypeSymbol GetOrCreateTypeSymbolForSpecification(Type type) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + Debug.Assert(type.Module == _module); + + if (type.GetElementType() is { } elementType) + { + var elementTypeSymbol = GetOrCreateTypeSymbol(elementType); + + // handles both SZ arrays and normal arrays + if (type.IsArray) + return (IkvmReflectionTypeSymbol)elementTypeSymbol.MakeArrayType(type.GetArrayRank()); + + if (type.IsPointer) + return (IkvmReflectionTypeSymbol)elementTypeSymbol.MakePointerType(); + + if (type.IsByRef) + return (IkvmReflectionTypeSymbol)elementTypeSymbol.MakeByRefType(); + + throw new InvalidOperationException(); + } + + if (type.IsGenericType) + { + var definitionType = type.GetGenericTypeDefinition(); + var definitionTypeSymbol = GetOrCreateTypeSymbol(definitionType); + return definitionTypeSymbol.GetOrCreateGenericTypeSymbol(type.GetGenericArguments()); + } + + // generic type parameter + if (type.IsGenericParameter && type.DeclaringMethod is null && type.DeclaringType is not null) + { + var declaringType = GetOrCreateTypeSymbol(type.DeclaringType); + return declaringType.GetOrCreateGenericParameterSymbol(type); + } + + // generic method parameter + if (type.IsGenericParameter && type.DeclaringMethod is not null && type.DeclaringMethod.DeclaringType is not null) + { + var declaringMethod = GetOrCreateTypeSymbol(type.DeclaringMethod.DeclaringType); + return declaringMethod.GetOrCreateGenericParameterSymbol(type); + } + + throw new InvalidOperationException(); + } + + /// + public IAssemblySymbol Assembly => Context.GetOrCreateAssemblySymbol(_module.Assembly); + + /// + public string FullyQualifiedName => _module.FullyQualifiedName; + + /// + public int MetadataToken => _module.MetadataToken; + + /// + public Guid ModuleVersionId => _module.ModuleVersionId; + + /// + public string Name => _module.Name; + + /// + public string ScopeName => _module.ScopeName; + + /// + public override bool IsMissing => _module.__IsMissing; + + /// + public IFieldSymbol? GetField(string name) + { + return _module.GetField(name) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol? GetField(string name, System.Reflection.BindingFlags bindingAttr) + { + return _module.GetField(name, (BindingFlags)bindingAttr) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol[] GetFields(System.Reflection.BindingFlags bindingFlags) + { + return ResolveFieldSymbols(_module.GetFields((BindingFlags)bindingFlags)); + } + + /// + public IFieldSymbol[] GetFields() + { + return ResolveFieldSymbols(_module.GetFields()); + } + + /// + public IMethodSymbol? GetMethod(string name) + { + return _module.GetMethod(name) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetMethod(string name, ITypeSymbol[] types) + { + return _module.GetMethod(name, UnpackTypeSymbols(types)) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetMethod(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.CallingConventions callConvention, ITypeSymbol[] types, System.Reflection.ParameterModifier[]? modifiers) + { + if (modifiers != null) + throw new NotImplementedException(); + + return _module.GetMethod(name, (BindingFlags)bindingAttr, null, (CallingConventions)callConvention, UnpackTypeSymbols(types), null) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol[] GetMethods() + { + return ResolveMethodSymbols(_module.GetMethods()); + } + + /// + public IMethodSymbol[] GetMethods(System.Reflection.BindingFlags bindingFlags) + { + return ResolveMethodSymbols(_module.GetMethods((BindingFlags)bindingFlags)); + } + /// + + public ITypeSymbol? GetType(string className) + { + return _module.GetType(className) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol? GetType(string className, bool ignoreCase) + { + return _module.GetType(className, ignoreCase) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol? GetType(string className, bool throwOnError, bool ignoreCase) + { + return _module.GetType(className, throwOnError, ignoreCase) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol[] GetTypes() + { + return ResolveTypeSymbols(_module.GetTypes()); + } + + /// + public bool IsResource() + { + return _module.IsResource(); + } + + /// + public IFieldSymbol? ResolveField(int metadataToken) + { + return _module.ResolveField(metadataToken) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol? ResolveField(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveField(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IMemberSymbol? ResolveMember(int metadataToken) + { + return _module.ResolveMember(metadataToken) is { } m ? ResolveMemberSymbol(m) : null; + } + + /// + public IMemberSymbol? ResolveMember(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveMember(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } m ? ResolveMemberSymbol(m) : null; + } + + /// + public IMethodBaseSymbol? ResolveMethod(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveMethod(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } m ? ResolveMethodBaseSymbol(m) : null; + } + + /// + public IMethodBaseSymbol? ResolveMethod(int metadataToken) + { + return _module.ResolveMethod(metadataToken) is { } m ? ResolveMethodBaseSymbol(m) : null; + } + + /// + public byte[] ResolveSignature(int metadataToken) + { + return _module.ResolveSignature(metadataToken); + } + + /// + public string ResolveString(int metadataToken) + { + return _module.ResolveString(metadataToken); + } + + /// + public ITypeSymbol ResolveType(int metadataToken) + { + return ResolveTypeSymbol(_module.ResolveType(metadataToken)); + } + + /// + public ITypeSymbol ResolveType(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return ResolveTypeSymbol(_module.ResolveType(metadataToken, _genericTypeArguments, _genericMethodArguments)); + } + + /// + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_module.GetCustomAttributesData()); + } + + /// + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_module.__GetCustomAttributes(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false)); + } + + /// + public bool IsDefined(ITypeSymbol attributeType) + { + return _module.IsDefined(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionParameterSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionParameterSymbol.cs new file mode 100644 index 0000000000..c63d92cad6 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionParameterSymbol.cs @@ -0,0 +1,72 @@ +using System; + +using ParameterInfo = IKVM.Reflection.ParameterInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionParameterSymbol : IkvmReflectionSymbol, IParameterSymbol + { + + readonly ParameterInfo _parameter; + readonly IkvmReflectionMethodBaseSymbol _method; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionParameterSymbol(IkvmReflectionSymbolContext context, IkvmReflectionMethodBaseSymbol method, ParameterInfo parameter) : + base(context) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + _parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); + } + + internal IkvmReflectionMethodBaseSymbol ContainingMethod => _method; + + public System.Reflection.ParameterAttributes Attributes => (System.Reflection.ParameterAttributes)_parameter.Attributes; + + public object DefaultValue => _parameter.RawDefaultValue; + + public bool HasDefaultValue => _parameter.HasDefaultValue; + + public bool IsIn => _parameter.IsIn; + + public bool IsLcid => _parameter.IsLcid; + + public bool IsOptional => _parameter.IsOptional; + + public bool IsOut => _parameter.IsOut; + + public bool IsRetval => _parameter.IsRetval; + + public IMemberSymbol Member => ResolveMemberSymbol(_parameter.Member); + + public int MetadataToken => _parameter.MetadataToken; + + public string? Name => _parameter.Name; + + public ITypeSymbol ParameterType => ResolveTypeSymbol(_parameter.ParameterType); + + public int Position => _parameter.Position; + + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_parameter.GetCustomAttributesData()); + } + + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_parameter.__GetCustomAttributes(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false)); + } + + public bool IsDefined(ITypeSymbol attributeType) + { + return _parameter.IsDefined(((IkvmReflectionTypeSymbol)attributeType).ReflectionObject, false); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionPropertySymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionPropertySymbol.cs new file mode 100644 index 0000000000..f16d0b9a08 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionPropertySymbol.cs @@ -0,0 +1,117 @@ +using System; + +using IKVM.Reflection; + +using PropertyInfo = IKVM.Reflection.PropertyInfo; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionPropertySymbol : IkvmReflectionMemberSymbol, IPropertySymbol + { + + readonly PropertyInfo _property; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionPropertySymbol(IkvmReflectionSymbolContext context, IkvmReflectionTypeSymbol type, PropertyInfo property) : + base(context, type.ContainingModule, type, property) + { + _property = property ?? throw new ArgumentNullException(nameof(property)); + } + + public new PropertyInfo ReflectionObject => (PropertyInfo)base.ReflectionObject; + + /// + public System.Reflection.PropertyAttributes Attributes => (System.Reflection.PropertyAttributes)_property.Attributes; + + /// + public ITypeSymbol PropertyType => ResolveTypeSymbol(_property.PropertyType); + + /// + public bool CanRead => _property.CanRead; + + /// + public bool CanWrite => _property.CanWrite; + + /// + public bool IsSpecialName => _property.IsSpecialName; + + /// + public IMethodSymbol? GetMethod => _property.GetMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public IMethodSymbol? SetMethod => _property.SetMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public object? GetRawConstantValue() + { + return _property.GetRawConstantValue(); + } + + /// + public IParameterSymbol[] GetIndexParameters() + { + return ResolveParameterSymbols(_property.GetIndexParameters()); + } + + /// + public ITypeSymbol GetModifiedPropertyType() + { + throw new NotImplementedException(); + } + + /// + public IMethodSymbol[] GetAccessors() + { + return ResolveMethodSymbols(_property.GetAccessors()); + } + + /// + public IMethodSymbol[] GetAccessors(bool nonPublic) + { + throw new NotImplementedException(); + } + + /// + public IMethodSymbol? GetGetMethod() + { + return _property.GetGetMethod() is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetGetMethod(bool nonPublic) + { + return _property.GetGetMethod(nonPublic) is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetSetMethod() + { + return _property.GetSetMethod() is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetSetMethod(bool nonPublic) + { + return _property.GetSetMethod(nonPublic) is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public ITypeSymbol[] GetOptionalCustomModifiers() + { + return ResolveTypeSymbols(_property.GetOptionalCustomModifiers()); + } + + /// + public ITypeSymbol[] GetRequiredCustomModifiers() + { + return ResolveTypeSymbols(_property.GetRequiredCustomModifiers()); + } + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbol.cs new file mode 100644 index 0000000000..e1bf81bf8c --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbol.cs @@ -0,0 +1,427 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +using IKVM.Reflection; + +using ConstructorInfo = IKVM.Reflection.ConstructorInfo; +using EventInfo = IKVM.Reflection.EventInfo; +using FieldInfo = IKVM.Reflection.FieldInfo; +using MemberInfo = IKVM.Reflection.MemberInfo; +using MethodBase = IKVM.Reflection.MethodBase; +using MethodInfo = IKVM.Reflection.MethodInfo; +using Module = IKVM.Reflection.Module; +using ParameterInfo = IKVM.Reflection.ParameterInfo; +using PropertyInfo = IKVM.Reflection.PropertyInfo; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + abstract class IkvmReflectionSymbol : ISymbol + { + + readonly IkvmReflectionSymbolContext _context; + + /// + /// Initializes a new instance. + /// + /// + public IkvmReflectionSymbol(IkvmReflectionSymbolContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + /// + /// Gets the associated . + /// + protected IkvmReflectionSymbolContext Context => _context; + + /// + public virtual bool IsMissing => false; + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual internal IkvmReflectionModuleSymbol ResolveModuleSymbol(Module module) + { + return _context.GetOrCreateModuleSymbol(module); + } + + /// + /// Resolves the symbols for the specified modules. + /// + /// + /// + protected internal IkvmReflectionModuleSymbol[] ResolveModuleSymbols(Module[] modules) + { + var a = new IkvmReflectionModuleSymbol[modules.Length]; + for (int i = 0; i < modules.Length; i++) + a[i] = ResolveModuleSymbol(modules[i]); + + return a; + } + + /// + /// Resolves the symbols for the specified modules. + /// + /// + /// + protected internal IEnumerable ResolveModuleSymbols(IEnumerable modules) + { + foreach (var module in modules) + yield return ResolveModuleSymbol(module); + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal Module[] UnpackModuleSymbols(IModuleSymbol[] modules) + { + var a = new Module[modules.Length]; + for (int i = 0; i < modules.Length; i++) + a[i] = ((IkvmReflectionModuleSymbol)modules[i]).ReflectionObject; + + return a; + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual IkvmReflectionMemberSymbol ResolveMemberSymbol(MemberInfo member) + { + return member.MemberType switch + { + MemberTypes.Constructor => ResolveConstructorSymbol((ConstructorInfo)member), + MemberTypes.Event => ResolveEventSymbol((EventInfo)member), + MemberTypes.Field => ResolveFieldSymbol((FieldInfo)member), + MemberTypes.Method => ResolveMethodSymbol((MethodInfo)member), + MemberTypes.Property => ResolvePropertySymbol((PropertyInfo)member), + MemberTypes.TypeInfo => ResolveTypeSymbol((Type)member), + MemberTypes.NestedType => ResolveTypeSymbol((Type)member), + MemberTypes.Custom => throw new NotImplementedException(), + MemberTypes.All => throw new NotImplementedException(), + _ => throw new InvalidOperationException(), + }; + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal IkvmReflectionMemberSymbol[] ResolveMemberSymbols(MemberInfo[] types) + { + var a = new IkvmReflectionMemberSymbol[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ResolveMemberSymbol(types[i]); + + return a; + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal MemberInfo[] UnpackMemberSymbols(IMemberSymbol[] members) + { + var a = new MemberInfo[members.Length]; + for (int i = 0; i < members.Length; i++) + a[i] = ((IkvmReflectionMemberSymbol)members[i]).ReflectionObject; + + return a; + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual internal IkvmReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + return _context.GetOrCreateTypeSymbol(type); + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal IkvmReflectionTypeSymbol[] ResolveTypeSymbols(Type[] types) + { + var a = new IkvmReflectionTypeSymbol[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ResolveTypeSymbol(types[i]); + + return a; + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal IEnumerable ResolveTypeSymbols(IEnumerable types) + { + foreach (var type in types) + yield return ResolveTypeSymbol(type); + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal Type[] UnpackTypeSymbols(ITypeSymbol[] types) + { + var a = new Type[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ((IkvmReflectionTypeSymbol)types[i]).ReflectionObject; + + return a; + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected virtual internal IkvmReflectionMethodBaseSymbol ResolveMethodBaseSymbol(MethodBase method) + { + if (method.IsConstructor) + return ResolveConstructorSymbol((ConstructorInfo)method); + else + return ResolveMethodSymbol((MethodInfo)method); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected virtual internal IkvmReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + return _context.GetOrCreateConstructorSymbol(ctor); + } + + /// + /// Resolves the symbols for the specified constructors. + /// + /// + /// + protected internal IkvmReflectionConstructorSymbol[] ResolveConstructorSymbols(ConstructorInfo[] ctors) + { + var a = new IkvmReflectionConstructorSymbol[ctors.Length]; + for (int i = 0; i < ctors.Length; i++) + a[i] = ResolveConstructorSymbol(ctors[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected virtual internal IkvmReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + return _context.GetOrCreateMethodSymbol(method); + } + + /// + /// Resolves the symbols for the specified methods. + /// + /// + /// + protected internal IkvmReflectionMethodSymbol[] ResolveMethodSymbols(MethodInfo[] methods) + { + var a = new IkvmReflectionMethodSymbol[methods.Length]; + for (int i = 0; i < methods.Length; i++) + a[i] = ResolveMethodSymbol(methods[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified parameter. + /// + /// + /// + protected virtual internal IkvmReflectionParameterSymbol ResolveParameterSymbol(ParameterInfo parameter) + { + return _context.GetOrCreateParameterSymbol(parameter); + } + + /// + /// Resolves the symbols for the specified parameters. + /// + /// + /// + protected internal IkvmReflectionParameterSymbol[] ResolveParameterSymbols(ParameterInfo[] parameters) + { + var a = new IkvmReflectionParameterSymbol[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + a[i] = ResolveParameterSymbol(parameters[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected virtual internal IkvmReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + return _context.GetOrCreateFieldSymbol(field); + } + + /// + /// Resolves the symbols for the specified fields. + /// + /// + /// + protected internal IkvmReflectionFieldSymbol[] ResolveFieldSymbols(FieldInfo[] fields) + { + var a = new IkvmReflectionFieldSymbol[fields.Length]; + for (int i = 0; i < fields.Length; i++) + a[i] = ResolveFieldSymbol(fields[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected virtual internal IkvmReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + return _context.GetOrCreatePropertySymbol(property); + } + + /// + /// Resolves the symbols for the specified properties. + /// + /// + /// + protected internal IkvmReflectionPropertySymbol[] ResolvePropertySymbols(PropertyInfo[] properties) + { + var a = new IkvmReflectionPropertySymbol[properties.Length]; + for (int i = 0; i < properties.Length; i++) + a[i] = ResolvePropertySymbol(properties[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected virtual internal IkvmReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + return _context.GetOrCreateEventSymbol(@event); + } + + /// + /// Resolves the symbols for the specified events. + /// + /// + /// + protected internal IkvmReflectionEventSymbol[] ResolveEventSymbols(EventInfo[] events) + { + var a = new IkvmReflectionEventSymbol[events.Length]; + for (int i = 0; i < events.Length; i++) + a[i] = ResolveEventSymbol(events[i]); + + return a; + } + + /// + /// Transforms a custom set of custom attribute data records to a symbol record. + /// + /// + /// + protected internal CustomAttributeSymbol[] ResolveCustomAttributes(IList attributes) + { + var a = new CustomAttributeSymbol[attributes.Count]; + for (int i = 0; i < attributes.Count; i++) + a[i] = ResolveCustomAttribute(attributes[i]); + + return a; + } + + /// + /// Transforms a custom attribute data record to a symbol record. + /// + /// + /// + /// + protected internal CustomAttributeSymbol ResolveCustomAttribute(CustomAttributeData customAttributeData) + { + return new CustomAttributeSymbol( + ResolveTypeSymbol(customAttributeData.AttributeType), + ResolveConstructorSymbol(customAttributeData.Constructor), + ResolveCustomAttributeTypedArguments(customAttributeData.ConstructorArguments), + ResolveCustomAttributeNamedArguments(customAttributeData.NamedArguments)); + } + + /// + /// Transforms a list of values into symbols. + /// + /// + /// + ImmutableArray ResolveCustomAttributeTypedArguments(IList args) + { + var a = new CustomAttributeSymbolTypedArgument[args.Count]; + for (int i = 0; i < args.Count; i++) + a[i] = ResolveCustomAttributeTypedArgument(args[i]); + + return a.ToImmutableArray(); + } + + /// + /// Transforms a values into a symbol. + /// + /// + /// + CustomAttributeSymbolTypedArgument ResolveCustomAttributeTypedArgument(CustomAttributeTypedArgument arg) + { + return new CustomAttributeSymbolTypedArgument(ResolveTypeSymbol(arg.ArgumentType), arg.Value); + } + + /// + /// Transforms a list of values into symbols. + /// + /// + /// + ImmutableArray ResolveCustomAttributeNamedArguments(IList args) + { + var a = new CustomAttributeSymbolNamedArgument[args.Count]; + for (int i = 0; i < args.Count; i++) + a[i] = ResolveCustomAttributeNamedArgument(args[i]); + + return a.ToImmutableArray(); + } + + /// + /// Transforms a values into a symbol. + /// + /// + /// + CustomAttributeSymbolNamedArgument ResolveCustomAttributeNamedArgument(CustomAttributeNamedArgument arg) + { + return new CustomAttributeSymbolNamedArgument(arg.IsField, ResolveMemberSymbol(arg.MemberInfo), arg.MemberName, ResolveCustomAttributeTypedArgument(arg.TypedValue)); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbolContext.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbolContext.cs new file mode 100644 index 0000000000..fcbc6d34d1 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionSymbolContext.cs @@ -0,0 +1,153 @@ +using System; +using System.Runtime.CompilerServices; + +using Assembly = IKVM.Reflection.Assembly; +using ConstructorInfo = IKVM.Reflection.ConstructorInfo; +using EventInfo = IKVM.Reflection.EventInfo; +using FieldInfo = IKVM.Reflection.FieldInfo; +using MethodBase = IKVM.Reflection.MethodBase; +using MethodInfo = IKVM.Reflection.MethodInfo; +using Module = IKVM.Reflection.Module; +using ParameterInfo = IKVM.Reflection.ParameterInfo; +using PropertyInfo = IKVM.Reflection.PropertyInfo; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + /// + /// Holds references to symbols derived from System.Reflection. + /// + class IkvmReflectionSymbolContext + { + + readonly ConditionalWeakTable _assemblies = new(); + + /// + /// Initializes a new instance. + /// + public IkvmReflectionSymbolContext() + { + + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionAssemblySymbol GetOrCreateAssemblySymbol(Assembly assembly) + { + if (assembly is null) + throw new ArgumentNullException(nameof(assembly)); + + return _assemblies.GetValue(assembly, _ => new IkvmReflectionAssemblySymbol(this, _)); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionModuleSymbol GetOrCreateModuleSymbol(Module module) + { + if (module is null) + throw new ArgumentNullException(nameof(module)); + + return GetOrCreateAssemblySymbol(module.Assembly).GetOrCreateModuleSymbol(module); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionTypeSymbol GetOrCreateTypeSymbol(Type type) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + return GetOrCreateModuleSymbol(type.Module).GetOrCreateTypeSymbol(type); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionConstructorSymbol GetOrCreateConstructorSymbol(ConstructorInfo ctor) + { + if (ctor is null) + throw new ArgumentNullException(nameof(ctor)); + + return GetOrCreateAssemblySymbol(ctor.Module.Assembly).GetOrCreateModuleSymbol(ctor.Module).GetOrCreateTypeSymbol(ctor.DeclaringType!).GetOrCreateConstructorSymbol(ctor); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionMethodSymbol GetOrCreateMethodSymbol(MethodInfo method) + { + if (method is null) + throw new ArgumentNullException(nameof(method)); + + return GetOrCreateAssemblySymbol(method.Module.Assembly).GetOrCreateModuleSymbol(method.Module).GetOrCreateTypeSymbol(method.DeclaringType!).GetOrCreateMethodSymbol(method); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionParameterSymbol GetOrCreateParameterSymbol(ParameterInfo parameter) + { + if (parameter is null) + throw new ArgumentNullException(nameof(parameter)); + + return GetOrCreateAssemblySymbol(parameter.Member.Module.Assembly).GetOrCreateModuleSymbol(parameter.Member.Module).GetOrCreateTypeSymbol(parameter.Member.DeclaringType!).GetOrCreateMethodBaseSymbol((MethodBase)parameter.Member).GetOrCreateParameterSymbol(parameter); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionFieldSymbol GetOrCreateFieldSymbol(FieldInfo field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + + return GetOrCreateAssemblySymbol(field.Module.Assembly).GetOrCreateModuleSymbol(field.Module).GetOrCreateTypeSymbol(field.DeclaringType!).GetOrCreateFieldSymbol(field); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionPropertySymbol GetOrCreatePropertySymbol(PropertyInfo property) + { + if (property is null) + throw new ArgumentNullException(nameof(property)); + + return GetOrCreateAssemblySymbol(property.Module.Assembly).GetOrCreateModuleSymbol(property.Module).GetOrCreateTypeSymbol(property.DeclaringType!).GetOrCreatePropertySymbol(property); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public IkvmReflectionEventSymbol GetOrCreateEventSymbol(EventInfo @event) + { + if (@event is null) + throw new ArgumentNullException(nameof(@event)); + + return GetOrCreateAssemblySymbol(@event.Module.Assembly).GetOrCreateModuleSymbol(@event.Module).GetOrCreateTypeSymbol(@event.DeclaringType!).GetOrCreateEventSymbol(@event); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionTypeSymbol.cs b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionTypeSymbol.cs new file mode 100644 index 0000000000..84c73c8988 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/IkvmReflection/IkvmReflectionTypeSymbol.cs @@ -0,0 +1,864 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Threading; + +using IKVM.Reflection; + +using ConstructorInfo = IKVM.Reflection.ConstructorInfo; +using EventInfo = IKVM.Reflection.EventInfo; +using FieldInfo = IKVM.Reflection.FieldInfo; +using MethodBase = IKVM.Reflection.MethodBase; +using MethodInfo = IKVM.Reflection.MethodInfo; +using PropertyInfo = IKVM.Reflection.PropertyInfo; +using Type = IKVM.Reflection.Type; + +namespace IKVM.CoreLib.Symbols.IkvmReflection +{ + + class IkvmReflectionTypeSymbol : IkvmReflectionMemberSymbol, ITypeSymbol + { + + const BindingFlags DefaultBindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + + readonly Type _type; + + MethodBase[]? _methodsSource; + int _methodsBaseRow; + IkvmReflectionMethodBaseSymbol?[]? _methods; + + FieldInfo[]? _fieldsSource; + int _fieldsBaseRow; + IkvmReflectionFieldSymbol?[]? _fields; + + PropertyInfo[]? _propertiesSource; + int _propertiesBaseRow; + IkvmReflectionPropertySymbol?[]? _properties; + + EventInfo[]? _eventsSource; + int _eventsBaseRow; + IkvmReflectionEventSymbol?[]? _events; + + IkvmReflectionTypeSymbol?[]? _asArray; + IkvmReflectionTypeSymbol? _asSZArray; + IkvmReflectionTypeSymbol? _asPointer; + IkvmReflectionTypeSymbol? _asByRef; + + Type[]? _genericParametersSource; + IkvmReflectionTypeSymbol?[]? _genericParameters; + List<(Type[] Arguments, IkvmReflectionTypeSymbol Symbol)>? _genericTypes; + ReaderWriterLockSlim? _genericTypesLock; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public IkvmReflectionTypeSymbol(IkvmReflectionSymbolContext context, IkvmReflectionModuleSymbol module, Type type) : + base(context, module, null, type) + { + Debug.Assert(module.ReflectionObject == type.Module); + _type = type ?? throw new ArgumentNullException(nameof(type)); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal IkvmReflectionMethodSymbol GetOrCreateMethodSymbol(MethodInfo method) + { + return (IkvmReflectionMethodSymbol)GetOrCreateMethodBaseSymbol(method); + } + + /// + /// Gets or creates the cached for the type by ctor. + /// + /// + /// + internal IkvmReflectionConstructorSymbol GetOrCreateConstructorSymbol(ConstructorInfo ctor) + { + return (IkvmReflectionConstructorSymbol)GetOrCreateMethodBaseSymbol(ctor); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal IkvmReflectionMethodBaseSymbol GetOrCreateMethodBaseSymbol(MethodBase method) + { + if (method is null) + throw new ArgumentNullException(nameof(method)); + + Debug.Assert(method.DeclaringType == _type); + + var hnd = MetadataTokens.MethodDefinitionHandle(method.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_methodsSource == null) + { + Interlocked.CompareExchange(ref _methodsSource, _type.GetConstructors(DefaultBindingFlags).Cast().Concat(_type.GetMethods(DefaultBindingFlags)).OrderBy(i => i.MetadataToken).ToArray(), null); + _methodsBaseRow = _methodsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_methodsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_methods == null) + Interlocked.CompareExchange(ref _methods, new IkvmReflectionMethodBaseSymbol?[_methodsSource.Length], null); + + // index of current record is specified row - base + var idx = row - _methodsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _methodsSource.Length); + + // check that our list is long enough to contain the entire table + if (_methods.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _methods[idx]; + if (rec == null) + { + switch (method) + { + case ConstructorInfo c: + Interlocked.CompareExchange(ref rec, new IkvmReflectionConstructorSymbol(Context, ContainingModule, this, c), null); + break; + case MethodInfo m: + Interlocked.CompareExchange(ref rec, new IkvmReflectionMethodSymbol(Context, ContainingModule, this, m), null); + break; + } + } + + // this should never happen + if (rec is not IkvmReflectionMethodBaseSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by field. + /// + /// + /// + /// + internal IkvmReflectionFieldSymbol GetOrCreateFieldSymbol(FieldInfo field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + + Debug.Assert(field.DeclaringType == _type); + + var hnd = MetadataTokens.FieldDefinitionHandle(field.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_fieldsSource == null) + { + Interlocked.CompareExchange(ref _fieldsSource, _type.GetFields(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _fieldsBaseRow = _fieldsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_fieldsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_fields == null) + Interlocked.CompareExchange(ref _fields, new IkvmReflectionFieldSymbol?[_fieldsSource.Length], null); + + // index of current field is specified row - base + var idx = row - _fieldsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _fieldsSource.Length); + + // check that our list is long enough to contain the entire table + if (_fields.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _fields[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionFieldSymbol(Context, this, field), null); + + // this should never happen + if (rec is not IkvmReflectionFieldSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by property. + /// + /// + /// + /// + internal IkvmReflectionPropertySymbol GetOrCreatePropertySymbol(PropertyInfo property) + { + if (property is null) + throw new ArgumentNullException(nameof(property)); + + Debug.Assert(property.DeclaringType == _type); + + var hnd = MetadataTokens.PropertyDefinitionHandle(property.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_propertiesSource == null) + { + Interlocked.CompareExchange(ref _propertiesSource, _type.GetProperties(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _propertiesBaseRow = _propertiesSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_propertiesSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_properties == null) + Interlocked.CompareExchange(ref _properties, new IkvmReflectionPropertySymbol?[_propertiesSource.Length], null); + + // index of current property is specified row - base + var idx = row - _propertiesBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _propertiesSource.Length); + + // check that our list is long enough to contain the entire table + if (_properties.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _properties[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionPropertySymbol(Context, this, property), null); + + // this should never happen + if (rec is not IkvmReflectionPropertySymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by event. + /// + /// + /// + /// + internal IkvmReflectionEventSymbol GetOrCreateEventSymbol(EventInfo @event) + { + if (@event is null) + throw new ArgumentNullException(nameof(@event)); + + Debug.Assert(@event.DeclaringType == _type); + + var hnd = MetadataTokens.PropertyDefinitionHandle(@event.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source events + if (_eventsSource == null) + { + Interlocked.CompareExchange(ref _eventsSource, _type.GetEvents(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _eventsBaseRow = _eventsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.EventDefinitionHandle(_eventsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_events == null) + Interlocked.CompareExchange(ref _events, new IkvmReflectionEventSymbol?[_eventsSource.Length], null); + + // index of current event is specified row - base + var idx = row - _eventsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _eventsSource.Length); + + // check that our list is long enough to contain the entire table + if (_events.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _events[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionEventSymbol(Context, this, @event), null); + + // this should never happen + if (rec is not IkvmReflectionEventSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal IkvmReflectionTypeSymbol GetOrCreateGenericParameterSymbol(Type genericTypeParameterType) + { + if (genericTypeParameterType is null) + throw new ArgumentNullException(nameof(genericTypeParameterType)); + + Debug.Assert(genericTypeParameterType.DeclaringType == _type); + + // initialize tables + if (_genericParametersSource == null) + Interlocked.CompareExchange(ref _genericParametersSource, _type.GetGenericArguments(), null); + if (_genericParameters == null) + Interlocked.CompareExchange(ref _genericParameters, new IkvmReflectionTypeSymbol?[_genericParametersSource.Length], null); + + // position of the parameter in the list + var idx = genericTypeParameterType.GenericParameterPosition; + + // check that our list is long enough to contain the entire table + if (_genericParameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _genericParameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new IkvmReflectionTypeSymbol(Context, ContainingModule, genericTypeParameterType), null); + + // this should never happen + if (rec is not IkvmReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal IkvmReflectionTypeSymbol GetOrCreateGenericTypeSymbol(Type[] genericTypeArguments) + { + if (genericTypeArguments is null) + throw new ArgumentNullException(nameof(genericTypeArguments)); + + if (_type.IsGenericTypeDefinition == false) + throw new InvalidOperationException(); + + // initialize the available parameters + if (_genericParametersSource == null) + Interlocked.CompareExchange(ref _genericParametersSource, _type.GetGenericArguments(), null); + if (_genericParametersSource.Length != genericTypeArguments.Length) + throw new InvalidOperationException(); + + // initialize generic type map, and lock on it since we're potentially adding items + if (_genericTypes == null) + Interlocked.CompareExchange(ref _genericTypes, [], null); + if (_genericTypesLock == null) + Interlocked.CompareExchange(ref _genericTypesLock, new(), null); + + try + { + _genericTypesLock.EnterUpgradeableReadLock(); + + // find existing entry + foreach (var i in _genericTypes) + if (i.Arguments.SequenceEqual(genericTypeArguments)) + return i.Symbol; + + try + { + _genericTypesLock.EnterWriteLock(); + + // generate new symbol + var sym = new IkvmReflectionTypeSymbol(Context, ContainingModule, _type.MakeGenericType(genericTypeArguments)); + _genericTypes.Add((genericTypeArguments, sym)); + return sym; + } + finally + { + _genericTypesLock.ExitWriteLock(); + } + } + finally + { + _genericTypesLock.ExitUpgradeableReadLock(); + } + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected internal override IkvmReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + if (type == _type) + return this; + else + return base.ResolveTypeSymbol(type); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected internal override IkvmReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + if (ctor.DeclaringType == _type) + return GetOrCreateConstructorSymbol(ctor); + else + return base.ResolveConstructorSymbol(ctor); + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected internal override IkvmReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + if (method.DeclaringType == _type) + return GetOrCreateMethodSymbol(method); + else + return base.ResolveMethodSymbol(method); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override IkvmReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + if (field.DeclaringType == _type) + return GetOrCreateFieldSymbol(field); + else + return base.ResolveFieldSymbol(field); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override IkvmReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + if (property.DeclaringType == _type) + return GetOrCreatePropertySymbol(property); + else + return base.ResolvePropertySymbol(property); + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected internal override IkvmReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + if (@event.DeclaringType == _type) + return GetOrCreateEventSymbol(@event); + else + return base.ResolveEventSymbol(@event); + } + + /// + /// Gets the wrapped . + /// + internal new Type ReflectionObject => _type; + + public IAssemblySymbol Assembly => Context.GetOrCreateAssemblySymbol(_type.Assembly); + + public string? AssemblyQualifiedName => _type.AssemblyQualifiedName; + + public System.Reflection.TypeAttributes Attributes => (System.Reflection.TypeAttributes)(int)_type.Attributes; + + public ITypeSymbol? BaseType => _type.BaseType != null ? ResolveTypeSymbol(_type.BaseType) : null; + + public bool ContainsGenericParameters => _type.ContainsGenericParameters; + + public IMethodBaseSymbol? DeclaringMethod => _type.DeclaringMethod is MethodInfo m ? ResolveMethodSymbol(m) : null; + + public string? FullName => _type.FullName; + + public System.Reflection.GenericParameterAttributes GenericParameterAttributes => (System.Reflection.GenericParameterAttributes)(int)_type.GenericParameterAttributes; + + public int GenericParameterPosition => _type.GenericParameterPosition; + + public ITypeSymbol[] GenericTypeArguments => ResolveTypeSymbols(_type.GenericTypeArguments); + + public bool HasElementType => _type.HasElementType; + + public bool IsAbstract => _type.IsAbstract; + + public bool IsArray => _type.IsArray; + + public bool IsAutoLayout => _type.IsAutoLayout; + + public bool IsByRef => _type.IsByRef; + + public bool IsClass => _type.IsClass; + + public bool IsConstructedGenericType => _type.IsConstructedGenericType; + + public bool IsEnum => _type.IsEnum; + + public bool IsExplicitLayout => _type.IsExplicitLayout; + + public bool IsGenericParameter => _type.IsGenericParameter; + + public bool IsGenericType => _type.IsGenericType; + + public bool IsGenericTypeDefinition => _type.IsGenericTypeDefinition; + + public bool IsInterface => _type.IsInterface; + + public bool IsLayoutSequential => _type.IsLayoutSequential; + + public bool IsNested => _type.IsNested; + + public bool IsNestedAssembly => _type.IsNestedAssembly; + + public bool IsNestedFamANDAssem => _type.IsNestedFamANDAssem; + + public bool IsNestedFamORAssem => _type.IsNestedFamORAssem; + + public bool IsNestedFamily => _type.IsNestedFamily; + + public bool IsNestedPrivate => _type.IsNestedPrivate; + + public bool IsNestedPublic => _type.IsNestedPublic; + + public bool IsNotPublic => _type.IsNotPublic; + + public bool IsPointer => _type.IsPointer; + + public bool IsPrimitive => _type.IsPrimitive; + + public bool IsPublic => _type.IsPublic; + + public bool IsSealed => _type.IsSealed; + +#pragma warning disable SYSLIB0050 // Type or member is obsolete + public bool IsSerializable => _type.IsSerializable; +#pragma warning restore SYSLIB0050 // Type or member is obsolete + + public bool IsValueType => _type.IsValueType; + + public bool IsVisible => _type.IsVisible; + + public string? Namespace => _type.Namespace; + + public IConstructorSymbol? TypeInitializer => _type.TypeInitializer is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + + public int GetArrayRank() + { + return _type.GetArrayRank(); + } + + public IConstructorSymbol? GetConstructor(System.Reflection.BindingFlags bindingAttr, ITypeSymbol[] types) + { + return _type.GetConstructor((BindingFlags)bindingAttr, binder: null, UnpackTypeSymbols(types), modifiers: null) is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + } + + public IConstructorSymbol? GetConstructor(ITypeSymbol[] types) + { + return _type.GetConstructor(UnpackTypeSymbols(types)) is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + } + + public IConstructorSymbol[] GetConstructors() + { + return ResolveConstructorSymbols(_type.GetConstructors()); + } + + public IConstructorSymbol[] GetConstructors(System.Reflection.BindingFlags bindingAttr) + { + return ResolveConstructorSymbols(_type.GetConstructors((BindingFlags)bindingAttr)); + } + + public IMemberSymbol[] GetDefaultMembers() + { + return ResolveMemberSymbols(_type.GetDefaultMembers()); + } + + public ITypeSymbol? GetElementType() + { + return _type.GetElementType() is Type t ? ResolveTypeSymbol(t) : null; + } + + public string? GetEnumName(object value) + { + return _type.GetEnumName(value); + } + + public string[] GetEnumNames() + { + return _type.GetEnumNames(); + } + + public ITypeSymbol GetEnumUnderlyingType() + { + return ResolveTypeSymbol(_type.GetEnumUnderlyingType()); + } + + public IEventSymbol? GetEvent(string name, System.Reflection.BindingFlags bindingAttr) + { + return _type.GetEvent(name, (BindingFlags)bindingAttr) is { } f ? ResolveEventSymbol(f) : null; + } + + public IEventSymbol? GetEvent(string name) + { + return _type.GetEvent(name) is { } f ? ResolveEventSymbol(f) : null; + } + + public IEventSymbol[] GetEvents() + { + return ResolveEventSymbols(_type.GetEvents()); + } + + public IEventSymbol[] GetEvents(System.Reflection.BindingFlags bindingAttr) + { + return ResolveEventSymbols(_type.GetEvents((BindingFlags)bindingAttr)); + } + + public IFieldSymbol? GetField(string name) + { + return _type.GetField(name) is FieldInfo f ? ResolveFieldSymbol(f) : null; + } + + public IFieldSymbol? GetField(string name, System.Reflection.BindingFlags bindingAttr) + { + return _type.GetField(name, (BindingFlags)bindingAttr) is FieldInfo f ? ResolveFieldSymbol(f) : null; + } + + public IFieldSymbol[] GetFields() + { + return ResolveFieldSymbols(_type.GetFields()); + } + + public IFieldSymbol[] GetFields(System.Reflection.BindingFlags bindingAttr) + { + return ResolveFieldSymbols(_type.GetFields((BindingFlags)bindingAttr)); + } + + public ITypeSymbol[] GetGenericArguments() + { + return ResolveTypeSymbols(_type.GetGenericArguments()); + } + + public ITypeSymbol[] GetGenericParameterConstraints() + { + return ResolveTypeSymbols(_type.GetGenericParameterConstraints()); + } + + public ITypeSymbol GetGenericTypeDefinition() + { + return ResolveTypeSymbol(_type.GetGenericTypeDefinition()); + } + + public ITypeSymbol? GetInterface(string name) + { + return _type.GetInterface(name) is { } i ? ResolveTypeSymbol(i) : null; + } + + public ITypeSymbol? GetInterface(string name, bool ignoreCase) + { + return _type.GetInterface(name, ignoreCase) is { } i ? ResolveTypeSymbol(i) : null; + } + + public InterfaceMapping GetInterfaceMap(ITypeSymbol interfaceType) + { + throw new NotImplementedException(); + } + + public ITypeSymbol[] GetInterfaces() + { + return ResolveTypeSymbols(_type.GetInterfaces()); + } + + public IMemberSymbol[] GetMember(string name) + { + return ResolveMemberSymbols(_type.GetMember(name)); + } + + public IMemberSymbol[] GetMember(string name, System.Reflection.BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMember(name, (BindingFlags)bindingAttr)); + } + + public IMemberSymbol[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMember(name, (MemberTypes)type, (BindingFlags)bindingAttr)); + } + + public IMemberSymbol[] GetMembers(System.Reflection.BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMembers((BindingFlags)bindingAttr)); + } + + public IMemberSymbol[] GetMembers() + { + return ResolveMemberSymbols(_type.GetMembers()); + } + + public IMethodSymbol? GetMethod(string name, System.Reflection.BindingFlags bindingAttr) + { + return _type.GetMethod(name, (BindingFlags)bindingAttr) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name, System.Reflection.BindingFlags bindingAttr, ITypeSymbol[] types) + { + return _type.GetMethod(name, (BindingFlags)bindingAttr, null, UnpackTypeSymbols(types), null) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name, ITypeSymbol[] types) + { + return _type.GetMethod(name, UnpackTypeSymbols(types)) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name) + { + return _type.GetMethod(name) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name, ITypeSymbol[] types, System.Reflection.ParameterModifier[]? modifiers) + { + if (modifiers != null) + throw new NotImplementedException(); + + return _type.GetMethod(name, UnpackTypeSymbols(types), null) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol[] GetMethods(System.Reflection.BindingFlags bindingAttr) + { + return ResolveMethodSymbols(_type.GetMethods((BindingFlags)bindingAttr)); + } + + public IMethodSymbol[] GetMethods() + { + return ResolveMethodSymbols(_type.GetMethods()); + } + + public ITypeSymbol? GetNestedType(string name) + { + return _type.GetNestedType(name) is Type t ? ResolveTypeSymbol(t) : null; + } + + public ITypeSymbol? GetNestedType(string name, System.Reflection.BindingFlags bindingAttr) + { + return _type.GetNestedType(name, (BindingFlags)bindingAttr) is Type t ? ResolveTypeSymbol(t) : null; + } + + public ITypeSymbol[] GetNestedTypes() + { + return ResolveTypeSymbols(_type.GetNestedTypes()); + } + + public ITypeSymbol[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr) + { + return ResolveTypeSymbols(_type.GetNestedTypes((BindingFlags)bindingAttr)); + } + + public IPropertySymbol[] GetProperties() + { + return ResolvePropertySymbols(_type.GetProperties()); + } + + public IPropertySymbol[] GetProperties(System.Reflection.BindingFlags bindingAttr) + { + return ResolvePropertySymbols(_type.GetProperties((BindingFlags)bindingAttr)); + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType, ITypeSymbol[] types, System.Reflection.ParameterModifier[]? modifiers) + { + if (modifiers != null) + throw new NotImplementedException(); + + var _returnType = returnType != null ? ((IkvmReflectionTypeSymbol)returnType).ReflectionObject : null; + return _type.GetProperty(name, _returnType, UnpackTypeSymbols(types), null) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol[] types) + { + return _type.GetProperty(name, UnpackTypeSymbols(types)) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType, ITypeSymbol[] types) + { + var _returnType = returnType != null ? ((IkvmReflectionTypeSymbol)returnType).ReflectionObject : null; + return _type.GetProperty(name, _returnType, UnpackTypeSymbols(types)) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, System.Reflection.BindingFlags bindingAttr) + { + return _type.GetProperty(name, (BindingFlags)bindingAttr) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name) + { + return _type.GetProperty(name) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType) + { + var _returnType = returnType != null ? ((IkvmReflectionTypeSymbol)returnType).ReflectionObject : null; + + return _type.GetProperty(name, _returnType) is { } p ? ResolvePropertySymbol(p) : null; + } + + public bool IsAssignableFrom(ITypeSymbol? c) + { + return _type.IsAssignableFrom(c != null ? ((IkvmReflectionTypeSymbol)c).ReflectionObject : null); + } + + public bool IsEnumDefined(object value) + { + return _type.IsEnumDefined(value); + } + + public bool IsSubclassOf(ITypeSymbol c) + { + return _type.IsSubclassOf(((IkvmReflectionTypeSymbol)c).ReflectionObject); + } + + public ITypeSymbol MakeArrayType() + { + if (_asSZArray == null) + Interlocked.CompareExchange(ref _asSZArray, new IkvmReflectionTypeSymbol(Context, ContainingModule, _type.MakeArrayType()), null); + + return _asSZArray; + } + + public ITypeSymbol MakeArrayType(int rank) + { + if (rank == 1) + return MakeArrayType(); + + if (_asArray == null) + Interlocked.CompareExchange(ref _asArray, new IkvmReflectionTypeSymbol?[32], null); + + ref var asArray = ref _asArray[rank]; + if (asArray == null) + Interlocked.CompareExchange(ref asArray, new IkvmReflectionTypeSymbol(Context, ContainingModule, _type.MakeArrayType(rank)), null); + + return asArray; + } + + public ITypeSymbol MakeByRefType() + { + if (_asByRef == null) + Interlocked.CompareExchange(ref _asByRef, new IkvmReflectionTypeSymbol(Context, ContainingModule, _type.MakeByRefType()), null); + + return _asByRef; + } + + public ITypeSymbol MakeGenericType(params ITypeSymbol[] typeArguments) + { + throw new NotImplementedException(); + } + + public ITypeSymbol MakePointerType() + { + if (_asPointer == null) + Interlocked.CompareExchange(ref _asPointer, new IkvmReflectionTypeSymbol(Context, ContainingModule, _type.MakePointerType()), null); + + return _asPointer; + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/InterfaceMapping.cs b/src/IKVM.CoreLib/Symbols/InterfaceMapping.cs new file mode 100644 index 0000000000..e2208e0e02 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/InterfaceMapping.cs @@ -0,0 +1,16 @@ +using System.Collections.Immutable; + +namespace IKVM.CoreLib.Symbols +{ + + readonly struct InterfaceMapping + { + + public readonly ImmutableArray InterfaceMethods; + public readonly ITypeSymbol InterfaceType; + public readonly ImmutableArray TargetMethods; + public readonly ITypeSymbol TargetType; + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionAssemblySymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionAssemblySymbol.cs new file mode 100644 index 0000000000..5165146189 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionAssemblySymbol.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionAssemblySymbol : ReflectionSymbol, IAssemblySymbol + { + + readonly Assembly _assembly; + readonly ConditionalWeakTable _modules = new(); + + /// + /// Initializes a new instance. + /// + /// + /// + public ReflectionAssemblySymbol(ReflectionSymbolContext context, Assembly assembly) : + base(context) + { + _assembly = assembly ?? throw new ArgumentNullException(nameof(assembly)); + } + + internal Assembly ReflectionObject => _assembly; + + /// + /// Gets or creates the cached for the module. + /// + /// + /// + /// + internal ReflectionModuleSymbol GetOrCreateModuleSymbol(Module module) + { + Debug.Assert(module.Assembly == _assembly); + return _modules.GetValue(module, _ => new ReflectionModuleSymbol(Context, _)); + } + + public IEnumerable DefinedTypes => ResolveTypeSymbols(_assembly.DefinedTypes); + + public IMethodSymbol? EntryPoint => _assembly.EntryPoint is { } m ? ResolveMethodSymbol(m) : null; + + public IEnumerable ExportedTypes => ResolveTypeSymbols(_assembly.ExportedTypes); + + public string? FullName => _assembly.FullName; + + public string ImageRuntimeVersion => _assembly.ImageRuntimeVersion; + + public IModuleSymbol ManifestModule => ResolveModuleSymbol(_assembly.ManifestModule); + + public IEnumerable Modules => ResolveModuleSymbols(_assembly.Modules); + + public ITypeSymbol[] GetExportedTypes() + { + return ResolveTypeSymbols(_assembly.GetExportedTypes()); + } + + public IModuleSymbol? GetModule(string name) + { + return _assembly.GetModule(name) is Module m ? GetOrCreateModuleSymbol(m) : null; + } + + public IModuleSymbol[] GetModules() + { + return ResolveModuleSymbols(_assembly.GetModules()); + } + + public IModuleSymbol[] GetModules(bool getResourceModules) + { + return ResolveModuleSymbols(_assembly.GetModules(getResourceModules)); + } + + public AssemblyName GetName() + { + return _assembly.GetName(); + } + + public AssemblyName GetName(bool copiedName) + { + return _assembly.GetName(copiedName); + } + + public AssemblyName[] GetReferencedAssemblies() + { + return _assembly.GetReferencedAssemblies(); + } + + public ITypeSymbol? GetType(string name, bool throwOnError) + { + return _assembly.GetType(name, throwOnError) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol? GetType(string name, bool throwOnError, bool ignoreCase) + { + return _assembly.GetType(name, throwOnError, ignoreCase) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol? GetType(string name) + { + return _assembly.GetType(name) is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + } + + public ITypeSymbol[] GetTypes() + { + return ResolveTypeSymbols(_assembly.GetTypes()); + } + + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_assembly.GetCustomAttributesData()); + } + + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_assembly.GetCustomAttributesData()).Where(i => i.AttributeType == attributeType).ToArray(); + } + + public bool IsDefined(ITypeSymbol attributeType) + { + return _assembly.IsDefined(((ReflectionTypeSymbol)attributeType).ReflectionObject); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionConstructorSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionConstructorSymbol.cs new file mode 100644 index 0000000000..aba5e173f4 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionConstructorSymbol.cs @@ -0,0 +1,26 @@ +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionConstructorSymbol : ReflectionMethodBaseSymbol, IConstructorSymbol + { + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public ReflectionConstructorSymbol(ReflectionSymbolContext context, ReflectionModuleSymbol module, ReflectionTypeSymbol type, ConstructorInfo ctor) : + base(context, module, type, ctor) + { + + } + + internal new ConstructorInfo ReflectionObject => (ConstructorInfo)base.ReflectionObject; + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionEventSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionEventSymbol.cs new file mode 100644 index 0000000000..7c4a37a7b2 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionEventSymbol.cs @@ -0,0 +1,97 @@ +using System; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionEventSymbol : ReflectionMemberSymbol, IEventSymbol + { + + readonly EventInfo _event; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionEventSymbol(ReflectionSymbolContext context, ReflectionTypeSymbol type, EventInfo @event) : + base(context, type.ContainingModule, type, @event) + { + _event = @event ?? throw new ArgumentNullException(nameof(@event)); + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal new EventInfo ReflectionObject => _event; + + /// + public EventAttributes Attributes => _event.Attributes; + + /// + public ITypeSymbol? EventHandlerType => _event.EventHandlerType is { } m ? ResolveTypeSymbol(m) : null; + + /// + public bool IsSpecialName => _event.IsSpecialName; + + /// + public IMethodSymbol? AddMethod => _event.AddMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public IMethodSymbol? RemoveMethod => _event.RemoveMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public IMethodSymbol? RaiseMethod => _event.RaiseMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public IMethodSymbol? GetAddMethod() + { + return _event.GetAddMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetAddMethod(bool nonPublic) + { + return _event.GetAddMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetRemoveMethod() + { + return _event.GetRemoveMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetRemoveMethod(bool nonPublic) + { + return _event.GetRemoveMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetRaiseMethod() + { + return _event.GetRaiseMethod() is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetRaiseMethod(bool nonPublic) + { + return _event.GetRaiseMethod(nonPublic) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol[] GetOtherMethods() + { + return ResolveMethodSymbols(_event.GetOtherMethods()); + } + + /// + public IMethodSymbol[] GetOtherMethods(bool nonPublic) + { + return ResolveMethodSymbols(_event.GetOtherMethods(nonPublic)); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionFieldSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionFieldSymbol.cs new file mode 100644 index 0000000000..8ba9a0eb66 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionFieldSymbol.cs @@ -0,0 +1,93 @@ +using System; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionFieldSymbol : ReflectionMemberSymbol, IFieldSymbol + { + + readonly FieldInfo _field; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionFieldSymbol(ReflectionSymbolContext context, ReflectionTypeSymbol type, FieldInfo field) : + base(context, type.ContainingModule, type, field) + { + _field = field ?? throw new ArgumentNullException(nameof(field)); + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal new FieldInfo ReflectionObject => (FieldInfo)base.ReflectionObject; + + /// + public FieldAttributes Attributes => _field.Attributes; + + /// + public ITypeSymbol FieldType => ResolveTypeSymbol(_field.FieldType); + + /// + public bool IsSpecialName => _field.IsSpecialName; + + /// + public bool IsAssembly => _field.IsAssembly; + + /// + public bool IsFamily => _field.IsFamily; + + /// + public bool IsFamilyAndAssembly => _field.IsFamilyAndAssembly; + + /// + public bool IsFamilyOrAssembly => _field.IsFamilyOrAssembly; + + /// + public bool IsInitOnly => _field.IsInitOnly; + + /// + public bool IsLiteral => _field.IsLiteral; + +#pragma warning disable SYSLIB0050 // Type or member is obsolete + /// + public bool IsNotSerialized => _field.IsNotSerialized; +#pragma warning restore SYSLIB0050 // Type or member is obsolete + + /// + public bool IsPinvokeImpl => _field.IsPinvokeImpl; + + /// + public bool IsPrivate => _field.IsPrivate; + + /// + public bool IsPublic => _field.IsPublic; + + /// + public bool IsStatic => _field.IsStatic; + + /// + public ITypeSymbol[] GetOptionalCustomModifiers() + { + return ResolveTypeSymbols(_field.GetOptionalCustomModifiers()); + } + + /// + public ITypeSymbol[] GetRequiredCustomModifiers() + { + return ResolveTypeSymbols(_field.GetRequiredCustomModifiers()); + } + + /// + public object? GetRawConstantValue() + { + return _field.GetRawConstantValue(); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMemberSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMemberSymbol.cs new file mode 100644 index 0000000000..28e417cab8 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMemberSymbol.cs @@ -0,0 +1,175 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + /// + /// Obtains information about the attributes of a member and provides access to member metadata. + /// + abstract class ReflectionMemberSymbol : ReflectionSymbol, IMemberSymbol + { + + readonly ReflectionModuleSymbol _module; + readonly ReflectionTypeSymbol? _type; + readonly MemberInfo _member; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public ReflectionMemberSymbol(ReflectionSymbolContext context, ReflectionModuleSymbol module, ReflectionTypeSymbol? type, MemberInfo member) : + base(context) + { + _module = module ?? throw new ArgumentNullException(nameof(module)); + _type = type; + _member = member ?? throw new ArgumentNullException(nameof(member)); + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected internal override ReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + if (_type != null && type == _type.ReflectionObject) + return _type; + else if (type.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(type); + else + return base.ResolveTypeSymbol(type); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected internal override ReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + if (_type != null && ctor.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateConstructorSymbol(ctor); + else if (ctor.DeclaringType != null && ctor.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(ctor.DeclaringType).GetOrCreateConstructorSymbol(ctor); + else + return base.ResolveConstructorSymbol(ctor); + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected internal override ReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + if (_type != null && method.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateMethodSymbol(method); + else if (method.DeclaringType != null && method.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(method.DeclaringType).GetOrCreateMethodSymbol(method); + else + return base.ResolveMethodSymbol(method); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override ReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + if (_type != null && field.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateFieldSymbol(field); + else if (field.DeclaringType != null && field.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(field.DeclaringType).GetOrCreateFieldSymbol(field); + else + return base.ResolveFieldSymbol(field); + } + + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override ReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + + if (_type != null && property.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreatePropertySymbol(property); + else if (property.DeclaringType != null && property.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(property.DeclaringType).GetOrCreatePropertySymbol(property); + else + return base.ResolvePropertySymbol(property); + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected internal override ReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + if (_type != null && @event.DeclaringType == _type.ReflectionObject) + return _type.GetOrCreateEventSymbol(@event); + else if (@event.DeclaringType != null && @event.Module == _member.Module) + return _module.GetOrCreateTypeSymbol(@event.DeclaringType).GetOrCreateEventSymbol(@event); + else + return base.ResolveEventSymbol(@event); + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal MemberInfo ReflectionObject => _member; + + /// + /// Gets the which contains the metadata of this member. + /// + internal ReflectionModuleSymbol ContainingModule => _module; + + /// + /// Gets the which contains the metadata of this member, or null if the member is not a member of a type. + /// + internal ReflectionTypeSymbol? ContainingType => _type; + + /// + public virtual IModuleSymbol Module => Context.GetOrCreateModuleSymbol(_member.Module); + + /// + public virtual ITypeSymbol? DeclaringType => _member.DeclaringType is Type t ? Context.GetOrCreateTypeSymbol(t) : null; + + /// + public virtual MemberTypes MemberType => _member.MemberType; + + /// + public virtual int MetadataToken => _member.MetadataToken; + + /// + public virtual string Name => _member.Name; + + /// + public virtual CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_member.GetCustomAttributesData()); + } + + /// + public virtual CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_member.GetCustomAttributesData()).Where(i => i.AttributeType == attributeType).ToArray(); + } + + /// + public virtual bool IsDefined(ITypeSymbol attributeType) + { + return _member.IsDefined(((ReflectionTypeSymbol)attributeType).ReflectionObject); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodBaseSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodBaseSymbol.cs new file mode 100644 index 0000000000..5f1aaa9aa4 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodBaseSymbol.cs @@ -0,0 +1,154 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + abstract class ReflectionMethodBaseSymbol : ReflectionMemberSymbol, IMethodBaseSymbol + { + + readonly MethodBase _method; + + ParameterInfo[]? _parametersSource; + ReflectionParameterSymbol?[]? _parameters; + ReflectionParameterSymbol? _returnParameter; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public ReflectionMethodBaseSymbol(ReflectionSymbolContext context, ReflectionModuleSymbol module, ReflectionTypeSymbol? type, MethodBase method) : + base(context, module, type, method) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal ReflectionParameterSymbol GetOrCreateParameterSymbol(ParameterInfo parameter) + { + if (parameter is null) + throw new ArgumentNullException(nameof(parameter)); + + Debug.Assert(parameter.Member == _method); + + if (_parametersSource == null) + Interlocked.CompareExchange(ref _parametersSource, _method.GetParameters().OrderBy(i => i.Position).ToArray(), null); + if (_parameters == null) + Interlocked.CompareExchange(ref _parameters, new ReflectionParameterSymbol?[_parametersSource.Length], null); + + // index of current record + var idx = parameter.Position; + Debug.Assert(idx >= -1); + Debug.Assert(idx < _parametersSource.Length); + + // check that our list is long enough to contain the entire table + if (idx >= 0 && _parameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _returnParameter; + if (idx >= 0) + rec = ref _parameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionParameterSymbol(Context, this, parameter), null); + + // this should never happen + if (rec is not ReflectionParameterSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal new MethodBase ReflectionObject => _method; + + /// + public MethodAttributes Attributes => _method.Attributes; + + /// + public CallingConventions CallingConvention => _method.CallingConvention; + + /// + public bool ContainsGenericParameters => _method.ContainsGenericParameters; + + /// + public bool IsAbstract => _method.IsAbstract; + + /// + public bool IsAssembly => _method.IsAssembly; + + /// + public bool IsConstructor => _method.IsConstructor; + + /// + public bool IsFamily => _method.IsFamily; + + /// + public bool IsFamilyAndAssembly => _method.IsFamilyAndAssembly; + + /// + public bool IsFamilyOrAssembly => _method.IsFamilyOrAssembly; + + /// + public bool IsFinal => _method.IsFinal; + + /// + public bool IsGenericMethod => _method.IsGenericMethod; + + /// + public bool IsGenericMethodDefinition => _method.IsGenericMethodDefinition; + + /// + public bool IsHideBySig => _method.IsHideBySig; + + /// + public bool IsPrivate => _method.IsPrivate; + + /// + public bool IsPublic => _method.IsPublic; + + /// + public bool IsStatic => _method.IsStatic; + + /// + public bool IsVirtual => _method.IsVirtual; + + /// + public bool IsSpecialName => _method.IsSpecialName; + + /// + public MethodImplAttributes MethodImplementationFlags => _method.MethodImplementationFlags; + + /// + public ITypeSymbol[] GetGenericArguments() + { + return ResolveTypeSymbols(_method.GetGenericArguments()); + } + + /// + public MethodImplAttributes GetMethodImplementationFlags() + { + return _method.GetMethodImplementationFlags(); + } + + /// + public IParameterSymbol[] GetParameters() + { + return ResolveParameterSymbols(_method.GetParameters()); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodSymbol.cs new file mode 100644 index 0000000000..fdbb45b38b --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionMethodSymbol.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionMethodSymbol : ReflectionMethodBaseSymbol, IMethodSymbol + { + + readonly MethodInfo _method; + + Type[]? _genericParametersSource; + ReflectionTypeSymbol?[]? _genericParameters; + List<(Type[] Arguments, ReflectionMethodSymbol Symbol)>? _genericTypes; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public ReflectionMethodSymbol(ReflectionSymbolContext context, ReflectionModuleSymbol module, ReflectionTypeSymbol? type, MethodInfo method) : + base(context, module, type, method) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal ReflectionTypeSymbol GetOrCreateGenericParameterSymbol(Type genericParameterType) + { + if (genericParameterType is null) + throw new ArgumentNullException(nameof(genericParameterType)); + + Debug.Assert(genericParameterType.DeclaringMethod == _method); + + // initialize tables + _genericParametersSource ??= _method.GetGenericArguments(); + _genericParameters ??= new ReflectionTypeSymbol?[_genericParametersSource.Length]; + + // position of the parameter in the list + var idx = genericParameterType.GenericParameterPosition; + + // check that our list is long enough to contain the entire table + if (_genericParameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _genericParameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionTypeSymbol(Context, ContainingModule, genericParameterType), null); + + // this should never happen + if (rec is not ReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal ReflectionMethodSymbol GetOrCreateGenericTypeSymbol(Type[] genericMethodArguments) + { + if (genericMethodArguments is null) + throw new ArgumentNullException(nameof(genericMethodArguments)); + + if (_method.IsGenericMethodDefinition == false) + throw new InvalidOperationException(); + + // initialize the available parameters + if (_genericParametersSource == null) + Interlocked.CompareExchange(ref _genericParametersSource, _method.GetGenericArguments(), null); + if (_genericParametersSource.Length != genericMethodArguments.Length) + throw new InvalidOperationException(); + + // initialize generic type map, and lock on it since we're potentially adding items + if (_genericTypes == null) + Interlocked.CompareExchange(ref _genericTypes, [], null); + + lock (_genericTypes) + { + // find existing entry + foreach (var i in _genericTypes) + if (i.Arguments.SequenceEqual(genericMethodArguments)) + return i.Symbol; + + // generate new symbol + var sym = new ReflectionMethodSymbol(Context, ContainingModule, ContainingType, _method.MakeGenericMethod(genericMethodArguments)); + _genericTypes.Add((genericMethodArguments, sym)); + return sym; + } + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal new MethodInfo ReflectionObject => _method; + + /// + public IParameterSymbol ReturnParameter => ResolveParameterSymbol(_method.ReturnParameter); + + /// + public ITypeSymbol ReturnType => ResolveTypeSymbol(_method.ReturnType); + + /// + public ICustomAttributeSymbolProvider ReturnTypeCustomAttributes => throw new NotImplementedException(); + + /// + public IMethodSymbol GetBaseDefinition() + { + return ResolveMethodSymbol(_method.GetBaseDefinition()); + } + + /// + public IMethodSymbol GetGenericMethodDefinition() + { + return ResolveMethodSymbol(_method.GetGenericMethodDefinition()); + } + + /// + public IMethodSymbol MakeGenericMethod(params ITypeSymbol[] typeArguments) + { + return ResolveMethodSymbol(_method.MakeGenericMethod(UnpackTypeSymbols(typeArguments))); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionModuleSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionModuleSymbol.cs new file mode 100644 index 0000000000..3b96124816 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionModuleSymbol.cs @@ -0,0 +1,352 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata.Ecma335; +using System.Threading; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + /// + /// Implementation of derived from System.Reflection. + /// + class ReflectionModuleSymbol : ReflectionSymbol, IModuleSymbol + { + + /// + /// Returns true if the given is a TypeDef. That is, not a modified or substituted or generic parameter type. + /// + /// + /// + static bool IsTypeDefinition(Type type) + { +#if NET + return type.IsTypeDefinition; +#else + return type.HasElementType == false && type.IsConstructedGenericType == false && type.IsGenericParameter == false; +#endif + } + + readonly Module _module; + + Type[]? _typesSource; + int _typesBaseRow; + ReflectionTypeSymbol?[]? _types; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionModuleSymbol(ReflectionSymbolContext context, Module module) : + base(context) + { + _module = module ?? throw new ArgumentNullException(nameof(module)); + } + + /// + /// Gets the wrapped . + /// + internal Module ReflectionModule => _module; + + /// + /// Gets or creates the cached for the module by type. + /// + /// + /// + /// + internal ReflectionTypeSymbol GetOrCreateTypeSymbol(Type type) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + Debug.Assert(type.Module == _module); + + // type is not a definition, but is substituted + if (IsTypeDefinition(type) == false) + return GetOrCreateTypeSymbolForSpecification(type); + + // look up handle and row + var hnd = MetadataTokens.TypeDefinitionHandle(type.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_typesSource == null) + { + Interlocked.CompareExchange(ref _typesSource, _module.GetTypes().OrderBy(i => i.MetadataToken).ToArray(), null); + _typesBaseRow = _typesSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_typesSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_types == null) + Interlocked.CompareExchange(ref _types, new ReflectionTypeSymbol?[_typesSource.Length], null); + + // index of current record is specified row - base + var idx = row - _typesBaseRow; + if (idx < 0) + throw new Exception(); + + Debug.Assert(idx >= 0); + Debug.Assert(idx < _typesSource.Length); + + // check that our type list is long enough to contain the entire table + if (_types.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + if (_types[idx] == null) + Interlocked.CompareExchange(ref _types[idx], new ReflectionTypeSymbol(Context, this, type), null); + + // this should never happen + if (_types[idx] is not ReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// For a given + /// + /// + /// + ReflectionTypeSymbol GetOrCreateTypeSymbolForSpecification(Type type) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + Debug.Assert(type.Module == _module); + + if (type.GetElementType() is { } elementType) + { + var elementTypeSymbol = GetOrCreateTypeSymbol(elementType); + + // handles both SZ arrays and normal arrays + if (type.IsArray) + return (ReflectionTypeSymbol)elementTypeSymbol.MakeArrayType(type.GetArrayRank()); + + if (type.IsPointer) + return (ReflectionTypeSymbol)elementTypeSymbol.MakePointerType(); + + if (type.IsByRef) + return (ReflectionTypeSymbol)elementTypeSymbol.MakeByRefType(); + + throw new InvalidOperationException(); + } + + if (type.IsGenericType) + { + var definitionType = type.GetGenericTypeDefinition(); + var definitionTypeSymbol = GetOrCreateTypeSymbol(definitionType); + return definitionTypeSymbol.GetOrCreateGenericTypeSymbol(type.GetGenericArguments()); + } + + // generic type parameter + if (type.IsGenericParameter && type.DeclaringMethod is null && type.DeclaringType is not null) + { + var declaringType = GetOrCreateTypeSymbol(type.DeclaringType); + return declaringType.GetOrCreateGenericParameterSymbol(type); + } + + // generic method parameter + if (type.IsGenericParameter && type.DeclaringMethod is not null && type.DeclaringMethod.DeclaringType is not null) + { + var declaringMethod = GetOrCreateTypeSymbol(type.DeclaringMethod.DeclaringType); + return declaringMethod.GetOrCreateGenericParameterSymbol(type); + } + + throw new InvalidOperationException(); + } + + /// + public IAssemblySymbol Assembly => Context.GetOrCreateAssemblySymbol(_module.Assembly); + + /// + public string FullyQualifiedName => _module.FullyQualifiedName; + + /// + public int MetadataToken => _module.MetadataToken; + + /// + public Guid ModuleVersionId => _module.ModuleVersionId; + + /// + public string Name => _module.Name; + + /// + public string ScopeName => _module.ScopeName; + + /// + public IFieldSymbol? GetField(string name) + { + return _module.GetField(name) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol? GetField(string name, BindingFlags bindingAttr) + { + return _module.GetField(name, bindingAttr) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol[] GetFields(BindingFlags bindingFlags) + { + return ResolveFieldSymbols(_module.GetFields(bindingFlags)); + } + + /// + public IFieldSymbol[] GetFields() + { + return ResolveFieldSymbols(_module.GetFields()); + } + + /// + public IMethodSymbol? GetMethod(string name) + { + return _module.GetMethod(name) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetMethod(string name, ITypeSymbol[] types) + { + return _module.GetMethod(name, UnpackTypeSymbols(types)) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr, CallingConventions callConvention, ITypeSymbol[] types, ParameterModifier[]? modifiers) + { + return _module.GetMethod(name, bindingAttr, null, callConvention, UnpackTypeSymbols(types), modifiers) is { } m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol[] GetMethods() + { + return ResolveMethodSymbols(_module.GetMethods()); + } + + /// + public IMethodSymbol[] GetMethods(BindingFlags bindingFlags) + { + return ResolveMethodSymbols(_module.GetMethods(bindingFlags)); + } + + /// + public ITypeSymbol? GetType(string className) + { + return _module.GetType(className) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol? GetType(string className, bool ignoreCase) + { + return _module.GetType(className, ignoreCase) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol? GetType(string className, bool throwOnError, bool ignoreCase) + { + return _module.GetType(className, throwOnError, ignoreCase) is { } t ? ResolveTypeSymbol(t) : null; + } + + /// + public ITypeSymbol[] GetTypes() + { + return ResolveTypeSymbols(_module.GetTypes()); + } + + /// + public bool IsResource() + { + return _module.IsResource(); + } + + /// + public IFieldSymbol? ResolveField(int metadataToken) + { + return _module.ResolveField(metadataToken) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IFieldSymbol? ResolveField(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveField(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } f ? ResolveFieldSymbol(f) : null; + } + + /// + public IMemberSymbol? ResolveMember(int metadataToken) + { + return _module.ResolveMember(metadataToken) is { } m ? ResolveMemberSymbol(m) : null; + } + + /// + public IMemberSymbol? ResolveMember(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveMember(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } m ? ResolveMemberSymbol(m) : null; + } + + /// + public IMethodBaseSymbol? ResolveMethod(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return _module.ResolveMethod(metadataToken, _genericTypeArguments, _genericMethodArguments) is { } m ? ResolveMethodBaseSymbol(m) : null; + } + + /// + public IMethodBaseSymbol? ResolveMethod(int metadataToken) + { + return _module.ResolveMethod(metadataToken) is { } m ? ResolveMethodBaseSymbol(m) : null; + } + + /// + public byte[] ResolveSignature(int metadataToken) + { + return _module.ResolveSignature(metadataToken); + } + + /// + public string ResolveString(int metadataToken) + { + return _module.ResolveString(metadataToken); + } + + /// + public ITypeSymbol ResolveType(int metadataToken) + { + return ResolveTypeSymbol(_module.ResolveType(metadataToken)); + } + + /// + public ITypeSymbol ResolveType(int metadataToken, ITypeSymbol[]? genericTypeArguments, ITypeSymbol[]? genericMethodArguments) + { + var _genericTypeArguments = genericTypeArguments != null ? UnpackTypeSymbols(genericTypeArguments) : null; + var _genericMethodArguments = genericMethodArguments != null ? UnpackTypeSymbols(genericMethodArguments) : null; + return ResolveTypeSymbol(_module.ResolveType(metadataToken, _genericTypeArguments, _genericMethodArguments)); + } + + /// + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_module.GetCustomAttributesData()); + } + + /// + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_module.GetCustomAttributesData()).Where(i => i.AttributeType == attributeType).ToArray(); + } + + /// + public bool IsDefined(ITypeSymbol attributeType) + { + return _module.IsDefined(((ReflectionTypeSymbol)attributeType).ReflectionObject); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionParameterSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionParameterSymbol.cs new file mode 100644 index 0000000000..1bf805672e --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionParameterSymbol.cs @@ -0,0 +1,72 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionParameterSymbol : ReflectionSymbol, IParameterSymbol + { + + readonly ParameterInfo _parameter; + readonly ReflectionMethodBaseSymbol _method; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionParameterSymbol(ReflectionSymbolContext context, ReflectionMethodBaseSymbol method, ParameterInfo parameter) : + base(context) + { + _method = method ?? throw new ArgumentNullException(nameof(method)); + _parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); + } + + internal ReflectionMethodBaseSymbol ContainingMethod => _method; + + public ParameterAttributes Attributes => _parameter.Attributes; + + public object? DefaultValue => _parameter.DefaultValue; + + public bool HasDefaultValue => _parameter.HasDefaultValue; + + public bool IsIn => _parameter.IsIn; + + public bool IsLcid => _parameter.IsLcid; + + public bool IsOptional => _parameter.IsOptional; + + public bool IsOut => _parameter.IsOut; + + public bool IsRetval => _parameter.IsRetval; + + public IMemberSymbol Member => ResolveMemberSymbol(_parameter.Member); + + public int MetadataToken => _parameter.MetadataToken; + + public string? Name => _parameter.Name; + + public ITypeSymbol ParameterType => ResolveTypeSymbol(_parameter.ParameterType); + + public int Position => _parameter.Position; + + public CustomAttributeSymbol[] GetCustomAttributes() + { + return ResolveCustomAttributes(_parameter.GetCustomAttributesData()); + } + + public CustomAttributeSymbol[] GetCustomAttributes(ITypeSymbol attributeType) + { + return ResolveCustomAttributes(_parameter.GetCustomAttributesData()).Where(i => i.AttributeType == attributeType).ToArray(); + } + + public bool IsDefined(ITypeSymbol attributeType) + { + return _parameter.IsDefined(((ReflectionTypeSymbol)attributeType).ReflectionObject); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionPropertySymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionPropertySymbol.cs new file mode 100644 index 0000000000..8e82493beb --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionPropertySymbol.cs @@ -0,0 +1,117 @@ +using System; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionPropertySymbol : ReflectionMemberSymbol, IPropertySymbol + { + + readonly PropertyInfo _property; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionPropertySymbol(ReflectionSymbolContext context, ReflectionTypeSymbol type, PropertyInfo property) : + base(context, type.ContainingModule, type, property) + { + _property = property ?? throw new ArgumentNullException(nameof(property)); + } + + /// + /// Gets the underlying wrapped by this symbol. + /// + internal new PropertyInfo ReflectionObject => _property; + + /// + public PropertyAttributes Attributes => _property.Attributes; + + /// + public bool CanRead => _property.CanRead; + + /// + public bool CanWrite => _property.CanWrite; + + /// + public bool IsSpecialName => _property.IsSpecialName; + + /// + public ITypeSymbol PropertyType => ResolveTypeSymbol(_property.PropertyType); + + /// + public IMethodSymbol? GetMethod => _property.GetMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public IMethodSymbol? SetMethod => _property.SetMethod is { } m ? ResolveMethodSymbol(m) : null; + + /// + public object? GetRawConstantValue() + { + return _property.GetRawConstantValue(); + } + + /// + public IMethodSymbol[] GetAccessors() + { + return ResolveMethodSymbols(_property.GetAccessors()); + } + + /// + public IMethodSymbol[] GetAccessors(bool nonPublic) + { + return ResolveMethodSymbols(_property.GetAccessors(nonPublic)); + } + + /// + public IParameterSymbol[] GetIndexParameters() + { + return ResolveParameterSymbols(_property.GetIndexParameters()); + } + + /// + public IMethodSymbol? GetGetMethod() + { + return _property.GetGetMethod() is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetGetMethod(bool nonPublic) + { + return _property.GetGetMethod(nonPublic) is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetSetMethod() + { + return _property.GetSetMethod() is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public IMethodSymbol? GetSetMethod(bool nonPublic) + { + return _property.GetSetMethod(nonPublic) is MethodInfo m ? ResolveMethodSymbol(m) : null; + } + + /// + public ITypeSymbol GetModifiedPropertyType() + { + throw new NotImplementedException(); + } + + /// + public ITypeSymbol[] GetOptionalCustomModifiers() + { + return ResolveTypeSymbols(_property.GetOptionalCustomModifiers()); + } + + /// + public ITypeSymbol[] GetRequiredCustomModifiers() + { + return ResolveTypeSymbols(_property.GetRequiredCustomModifiers()); + } + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbol.cs new file mode 100644 index 0000000000..03ad96cf32 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbol.cs @@ -0,0 +1,418 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Reflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + /// + /// Base class for managed symbols. + /// + abstract class ReflectionSymbol : ISymbol + { + + readonly ReflectionSymbolContext _context; + + /// + /// Initializes a new instance. + /// + /// + public ReflectionSymbol(ReflectionSymbolContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + /// + /// Gets the associated . + /// + protected ReflectionSymbolContext Context => _context; + + /// + public virtual bool IsMissing => false; + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual internal ReflectionModuleSymbol ResolveModuleSymbol(Module module) + { + return _context.GetOrCreateModuleSymbol(module); + } + + /// + /// Resolves the symbols for the specified modules. + /// + /// + /// + protected internal ReflectionModuleSymbol[] ResolveModuleSymbols(Module[] modules) + { + var a = new ReflectionModuleSymbol[modules.Length]; + for (int i = 0; i < modules.Length; i++) + a[i] = ResolveModuleSymbol(modules[i]); + + return a; + } + + /// + /// Resolves the symbols for the specified modules. + /// + /// + /// + protected internal IEnumerable ResolveModuleSymbols(IEnumerable modules) + { + foreach (var module in modules) + yield return ResolveModuleSymbol(module); + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal Module[] UnpackModuleSymbols(IModuleSymbol[] modules) + { + var a = new Module[modules.Length]; + for (int i = 0; i < modules.Length; i++) + a[i] = ((ReflectionModuleSymbol)modules[i]).ReflectionModule; + + return a; + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual ReflectionMemberSymbol ResolveMemberSymbol(MemberInfo member) + { + return member.MemberType switch + { + MemberTypes.Constructor => ResolveConstructorSymbol((ConstructorInfo)member), + MemberTypes.Event => ResolveEventSymbol((EventInfo)member), + MemberTypes.Field => ResolveFieldSymbol((FieldInfo)member), + MemberTypes.Method => ResolveMethodSymbol((MethodInfo)member), + MemberTypes.Property => ResolvePropertySymbol((PropertyInfo)member), + MemberTypes.TypeInfo => ResolveTypeSymbol((Type)member), + MemberTypes.NestedType => ResolveTypeSymbol((Type)member), + MemberTypes.Custom => throw new NotImplementedException(), + MemberTypes.All => throw new NotImplementedException(), + _ => throw new InvalidOperationException(), + }; + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal ReflectionMemberSymbol[] ResolveMemberSymbols(MemberInfo[] types) + { + var a = new ReflectionMemberSymbol[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ResolveMemberSymbol(types[i]); + + return a; + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal MemberInfo[] UnpackMemberSymbols(IMemberSymbol[] members) + { + var a = new MemberInfo[members.Length]; + for (int i = 0; i < members.Length; i++) + a[i] = ((ReflectionMemberSymbol)members[i]).ReflectionObject; + + return a; + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected virtual internal ReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + return _context.GetOrCreateTypeSymbol(type); + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal ReflectionTypeSymbol[] ResolveTypeSymbols(Type[] types) + { + var a = new ReflectionTypeSymbol[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ResolveTypeSymbol(types[i]); + + return a; + } + + /// + /// Resolves the symbols for the specified types. + /// + /// + /// + protected internal IEnumerable ResolveTypeSymbols(IEnumerable types) + { + foreach (var type in types) + yield return ResolveTypeSymbol(type); + } + + /// + /// Unpacks the symbols into their original type. + /// + /// + /// + protected internal Type[] UnpackTypeSymbols(ITypeSymbol[] types) + { + var a = new Type[types.Length]; + for (int i = 0; i < types.Length; i++) + a[i] = ((ReflectionTypeSymbol)types[i]).ReflectionObject; + + return a; + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected virtual internal ReflectionMethodBaseSymbol ResolveMethodBaseSymbol(MethodBase method) + { + if (method.IsConstructor) + return ResolveConstructorSymbol((ConstructorInfo)method); + else + return ResolveMethodSymbol((MethodInfo)method); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected virtual internal ReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + return _context.GetOrCreateConstructorSymbol(ctor); + } + + /// + /// Resolves the symbols for the specified constructors. + /// + /// + /// + protected internal ReflectionConstructorSymbol[] ResolveConstructorSymbols(ConstructorInfo[] ctors) + { + var a = new ReflectionConstructorSymbol[ctors.Length]; + for (int i = 0; i < ctors.Length; i++) + a[i] = ResolveConstructorSymbol(ctors[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected virtual internal ReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + return _context.GetOrCreateMethodSymbol(method); + } + + /// + /// Resolves the symbols for the specified methods. + /// + /// + /// + protected internal ReflectionMethodSymbol[] ResolveMethodSymbols(MethodInfo[] methods) + { + var a = new ReflectionMethodSymbol[methods.Length]; + for (int i = 0; i < methods.Length; i++) + a[i] = ResolveMethodSymbol(methods[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified parameter. + /// + /// + /// + protected virtual internal ReflectionParameterSymbol ResolveParameterSymbol(ParameterInfo parameter) + { + return _context.GetOrCreateParameterSymbol(parameter); + } + + /// + /// Resolves the symbols for the specified parameters. + /// + /// + /// + protected internal ReflectionParameterSymbol[] ResolveParameterSymbols(ParameterInfo[] parameters) + { + var a = new ReflectionParameterSymbol[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + a[i] = ResolveParameterSymbol(parameters[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected virtual internal ReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + return _context.GetOrCreateFieldSymbol(field); + } + + /// + /// Resolves the symbols for the specified fields. + /// + /// + /// + protected internal ReflectionFieldSymbol[] ResolveFieldSymbols(FieldInfo[] fields) + { + var a = new ReflectionFieldSymbol[fields.Length]; + for (int i = 0; i < fields.Length; i++) + a[i] = ResolveFieldSymbol(fields[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected virtual internal ReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + return _context.GetOrCreatePropertySymbol(property); + } + + /// + /// Resolves the symbols for the specified properties. + /// + /// + /// + protected internal ReflectionPropertySymbol[] ResolvePropertySymbols(PropertyInfo[] properties) + { + var a = new ReflectionPropertySymbol[properties.Length]; + for (int i = 0; i < properties.Length; i++) + a[i] = ResolvePropertySymbol(properties[i]); + + return a; + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected virtual internal ReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + return _context.GetOrCreateEventSymbol(@event); + } + + /// + /// Resolves the symbols for the specified events. + /// + /// + /// + protected internal ReflectionEventSymbol[] ResolveEventSymbols(EventInfo[] events) + { + var a = new ReflectionEventSymbol[events.Length]; + for (int i = 0; i < events.Length; i++) + a[i] = ResolveEventSymbol(events[i]); + + return a; + } + + /// + /// Transforms a custom set of custom attribute data records to a symbol record. + /// + /// + /// + protected internal CustomAttributeSymbol[] ResolveCustomAttributes(IList attributes) + { + var a = new CustomAttributeSymbol[attributes.Count]; + for (int i = 0; i < attributes.Count; i++) + a[i] = ResolveCustomAttribute(attributes[i]); + + return a; + } + + /// + /// Transforms a custom attribute data record to a symbol record. + /// + /// + /// + /// + protected internal CustomAttributeSymbol ResolveCustomAttribute(CustomAttributeData customAttributeData) + { + return new CustomAttributeSymbol( + ResolveTypeSymbol(customAttributeData.AttributeType), + ResolveConstructorSymbol(customAttributeData.Constructor), + ResolveCustomAttributeTypedArguments(customAttributeData.ConstructorArguments), + ResolveCustomAttributeNamedArguments(customAttributeData.NamedArguments)); + } + + /// + /// Transforms a list of values into symbols. + /// + /// + /// + ImmutableArray ResolveCustomAttributeTypedArguments(IList args) + { + var a = new CustomAttributeSymbolTypedArgument[args.Count]; + for (int i = 0; i < args.Count; i++) + a[i] = ResolveCustomAttributeTypedArgument(args[i]); + + return a.ToImmutableArray(); + } + + /// + /// Transforms a values into a symbol. + /// + /// + /// + CustomAttributeSymbolTypedArgument ResolveCustomAttributeTypedArgument(CustomAttributeTypedArgument arg) + { + return new CustomAttributeSymbolTypedArgument(ResolveTypeSymbol(arg.ArgumentType), arg.Value); + } + + /// + /// Transforms a list of values into symbols. + /// + /// + /// + ImmutableArray ResolveCustomAttributeNamedArguments(IList args) + { + var a = new CustomAttributeSymbolNamedArgument[args.Count]; + for (int i = 0; i < args.Count; i++) + a[i] = ResolveCustomAttributeNamedArgument(args[i]); + + return ImmutableArray.Create(a); + } + + /// + /// Transforms a values into a symbol. + /// + /// + /// + CustomAttributeSymbolNamedArgument ResolveCustomAttributeNamedArgument(CustomAttributeNamedArgument arg) + { + return new CustomAttributeSymbolNamedArgument(arg.IsField, ResolveMemberSymbol(arg.MemberInfo), arg.MemberName, ResolveCustomAttributeTypedArgument(arg.TypedValue)); + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbolContext.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbolContext.cs new file mode 100644 index 0000000000..b88ecdf06a --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionSymbolContext.cs @@ -0,0 +1,116 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + /// + /// Holds references to symbols derived from System.Reflection. + /// + class ReflectionSymbolContext + { + + readonly ConditionalWeakTable _assemblies = new(); + + /// + /// Initializes a new instance. + /// + public ReflectionSymbolContext() + { + + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionAssemblySymbol GetOrCreateAssemblySymbol(Assembly assembly) + { + return _assemblies.GetValue(assembly, _ => new ReflectionAssemblySymbol(this, _)); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionModuleSymbol GetOrCreateModuleSymbol(Module module) + { + return GetOrCreateAssemblySymbol(module.Assembly).GetOrCreateModuleSymbol(module); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionTypeSymbol GetOrCreateTypeSymbol(Type type) + { + return GetOrCreateModuleSymbol(type.Module).GetOrCreateTypeSymbol(type); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionConstructorSymbol GetOrCreateConstructorSymbol(ConstructorInfo ctor) + { + return GetOrCreateAssemblySymbol(ctor.Module.Assembly).GetOrCreateModuleSymbol(ctor.Module).GetOrCreateTypeSymbol(ctor.DeclaringType!).GetOrCreateConstructorSymbol(ctor); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionMethodSymbol GetOrCreateMethodSymbol(MethodInfo method) + { + return GetOrCreateAssemblySymbol(method.Module.Assembly).GetOrCreateModuleSymbol(method.Module).GetOrCreateTypeSymbol(method.DeclaringType!).GetOrCreateMethodSymbol(method); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionParameterSymbol GetOrCreateParameterSymbol(ParameterInfo parameter) + { + return GetOrCreateAssemblySymbol(parameter.Member.Module.Assembly).GetOrCreateModuleSymbol(parameter.Member.Module).GetOrCreateTypeSymbol(parameter.Member.DeclaringType!).GetOrCreateMethodBaseSymbol((MethodBase)parameter.Member).GetOrCreateParameterSymbol(parameter); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionFieldSymbol GetOrCreateFieldSymbol(FieldInfo field) + { + return GetOrCreateAssemblySymbol(field.Module.Assembly).GetOrCreateModuleSymbol(field.Module).GetOrCreateTypeSymbol(field.DeclaringType!).GetOrCreateFieldSymbol(field); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionPropertySymbol GetOrCreatePropertySymbol(PropertyInfo property) + { + return GetOrCreateAssemblySymbol(property.Module.Assembly).GetOrCreateModuleSymbol(property.Module).GetOrCreateTypeSymbol(property.DeclaringType!).GetOrCreatePropertySymbol(property); + } + + /// + /// Gets or creates a for the specified . + /// + /// + /// + public ReflectionEventSymbol GetOrCreateEventSymbol(EventInfo @event) + { + return GetOrCreateAssemblySymbol(@event.Module.Assembly).GetOrCreateModuleSymbol(@event.Module).GetOrCreateTypeSymbol(@event.DeclaringType!).GetOrCreateEventSymbol(@event); + } + + } + +} diff --git a/src/IKVM.CoreLib/Symbols/Reflection/ReflectionTypeSymbol.cs b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionTypeSymbol.cs new file mode 100644 index 0000000000..df9b1ffe70 --- /dev/null +++ b/src/IKVM.CoreLib/Symbols/Reflection/ReflectionTypeSymbol.cs @@ -0,0 +1,845 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata.Ecma335; +using System.Threading; + +using IKVM.CoreLib.Symbols.IkvmReflection; + +namespace IKVM.CoreLib.Symbols.Reflection +{ + + class ReflectionTypeSymbol : ReflectionMemberSymbol, ITypeSymbol + { + + const BindingFlags DefaultBindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + + readonly Type _type; + + MethodBase[]? _methodsSource; + int _methodsBaseRow; + ReflectionMethodBaseSymbol?[]? _methods; + + FieldInfo[]? _fieldsSource; + int _fieldsBaseRow; + ReflectionFieldSymbol?[]? _fields; + + PropertyInfo[]? _propertiesSource; + int _propertiesBaseRow; + ReflectionPropertySymbol?[]? _properties; + + EventInfo[]? _eventsSource; + int _eventsBaseRow; + ReflectionEventSymbol?[]? _events; + + ReflectionTypeSymbol?[]? _asArray; + ReflectionTypeSymbol? _asSZArray; + ReflectionTypeSymbol? _asPointer; + ReflectionTypeSymbol? _asByRef; + + Type[]? _genericParametersSource; + ReflectionTypeSymbol?[]? _genericParameters; + List<(Type[] Arguments, ReflectionTypeSymbol Symbol)>? _genericTypes; + ReaderWriterLockSlim? _genericTypesLock; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + public ReflectionTypeSymbol(ReflectionSymbolContext context, ReflectionModuleSymbol module, Type type) : + base(context, module, null, type) + { + Debug.Assert(module.ReflectionModule == type.Module); + _type = type ?? throw new ArgumentNullException(nameof(type)); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal ReflectionMethodSymbol GetOrCreateMethodSymbol(MethodInfo method) + { + return (ReflectionMethodSymbol)GetOrCreateMethodBaseSymbol(method); + } + + /// + /// Gets or creates the cached for the type by ctor. + /// + /// + /// + internal ReflectionConstructorSymbol GetOrCreateConstructorSymbol(ConstructorInfo ctor) + { + return (ReflectionConstructorSymbol)GetOrCreateMethodBaseSymbol(ctor); + } + + /// + /// Gets or creates the cached for the type by method. + /// + /// + /// + internal ReflectionMethodBaseSymbol GetOrCreateMethodBaseSymbol(MethodBase method) + { + if (method is null) + throw new ArgumentNullException(nameof(method)); + + Debug.Assert(method.DeclaringType == _type); + + var hnd = MetadataTokens.MethodDefinitionHandle(method.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_methodsSource == null) + { + Interlocked.CompareExchange(ref _methodsSource, _type.GetConstructors(DefaultBindingFlags).Cast().Concat(_type.GetMethods(DefaultBindingFlags)).OrderBy(i => i.MetadataToken).ToArray(), null); + _methodsBaseRow = _methodsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_methodsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_methods == null) + Interlocked.CompareExchange(ref _methods, new ReflectionMethodBaseSymbol?[_methodsSource.Length], null); + + // index of current record is specified row - base + var idx = row - _methodsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _methodsSource.Length); + + // check that our list is long enough to contain the entire table + if (_methods.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _methods[idx]; + if (rec == null) + { + switch (method) + { + case ConstructorInfo c: + Interlocked.CompareExchange(ref rec, new ReflectionConstructorSymbol(Context, ContainingModule, this, c), null); + break; + case MethodInfo m: + Interlocked.CompareExchange(ref rec, new ReflectionMethodSymbol(Context, ContainingModule, this, m), null); + break; + } + } + + // this should never happen + if (rec is not ReflectionMethodBaseSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by field. + /// + /// + /// + /// + internal ReflectionFieldSymbol GetOrCreateFieldSymbol(FieldInfo field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + + Debug.Assert(field.DeclaringType == _type); + + var hnd = MetadataTokens.FieldDefinitionHandle(field.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_fieldsSource == null) + { + Interlocked.CompareExchange(ref _fieldsSource, _type.GetFields(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _fieldsBaseRow = _fieldsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_fieldsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_fields == null) + Interlocked.CompareExchange(ref _fields, new ReflectionFieldSymbol?[_fieldsSource.Length], null); + + // index of current field is specified row - base + var idx = row - _fieldsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _fieldsSource.Length); + + // check that our list is long enough to contain the entire table + if (_fields.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _fields[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionFieldSymbol(Context, this, field), null); + + // this should never happen + if (rec is not ReflectionFieldSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by property. + /// + /// + /// + /// + internal ReflectionPropertySymbol GetOrCreatePropertySymbol(PropertyInfo property) + { + if (property is null) + throw new ArgumentNullException(nameof(property)); + + Debug.Assert(property.DeclaringType == _type); + + var hnd = MetadataTokens.PropertyDefinitionHandle(property.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source table + if (_propertiesSource == null) + { + Interlocked.CompareExchange(ref _propertiesSource, _type.GetProperties(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _propertiesBaseRow = _propertiesSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.MethodDefinitionHandle(_propertiesSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_properties == null) + Interlocked.CompareExchange(ref _properties, new ReflectionPropertySymbol?[_propertiesSource.Length], null); + + // index of current property is specified row - base + var idx = row - _propertiesBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _propertiesSource.Length); + + // check that our list is long enough to contain the entire table + if (_properties.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _properties[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionPropertySymbol(Context, this, property), null); + + // this should never happen + if (rec is not ReflectionPropertySymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the type by event. + /// + /// + /// + /// + internal ReflectionEventSymbol GetOrCreateEventSymbol(EventInfo @event) + { + if (@event is null) + throw new ArgumentNullException(nameof(@event)); + + Debug.Assert(@event.DeclaringType == _type); + + var hnd = MetadataTokens.PropertyDefinitionHandle(@event.MetadataToken); + var row = MetadataTokens.GetRowNumber(hnd); + + // initialize source events + if (_eventsSource == null) + { + Interlocked.CompareExchange(ref _eventsSource, _type.GetEvents(DefaultBindingFlags).OrderBy(i => i.MetadataToken).ToArray(), null); + _eventsBaseRow = _eventsSource.Length != 0 ? MetadataTokens.GetRowNumber(MetadataTokens.EventDefinitionHandle(_eventsSource[0].MetadataToken)) : 0; + } + + // initialize cache table + if (_events == null) + Interlocked.CompareExchange(ref _events, new ReflectionEventSymbol?[_eventsSource.Length], null); + + // index of current event is specified row - base + var idx = row - _eventsBaseRow; + Debug.Assert(idx >= 0); + Debug.Assert(idx < _eventsSource.Length); + + // check that our list is long enough to contain the entire table + if (_events.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _events[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionEventSymbol(Context, this, @event), null); + + // this should never happen + if (rec is not ReflectionEventSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal ReflectionTypeSymbol GetOrCreateGenericParameterSymbol(Type genericTypeParameterType) + { + if (genericTypeParameterType is null) + throw new ArgumentNullException(nameof(genericTypeParameterType)); + + Debug.Assert(genericTypeParameterType.DeclaringType == _type); + + // initialize tables + if (_genericParametersSource == null) + Interlocked.CompareExchange(ref _genericParametersSource, _type.GetGenericArguments(), null); + if (_genericParameters == null) + Interlocked.CompareExchange(ref _genericParameters, new ReflectionTypeSymbol?[_genericParametersSource.Length], null); + + // position of the parameter in the list + var idx = genericTypeParameterType.GenericParameterPosition; + + // check that our list is long enough to contain the entire table + if (_genericParameters.Length < idx) + throw new IndexOutOfRangeException(); + + // if not yet created, create, allow multiple instances, but only one is eventually inserted + ref var rec = ref _genericParameters[idx]; + if (rec == null) + Interlocked.CompareExchange(ref rec, new ReflectionTypeSymbol(Context, ContainingModule, genericTypeParameterType), null); + + // this should never happen + if (rec is not ReflectionTypeSymbol sym) + throw new InvalidOperationException(); + + return sym; + } + + /// + /// Gets or creates the cached for the generic parameter type. + /// + /// + /// + /// + internal ReflectionTypeSymbol GetOrCreateGenericTypeSymbol(Type[] genericTypeArguments) + { + if (genericTypeArguments is null) + throw new ArgumentNullException(nameof(genericTypeArguments)); + + if (_type.IsGenericTypeDefinition == false) + throw new InvalidOperationException(); + + // initialize the available parameters + if (_genericParametersSource == null) + Interlocked.CompareExchange(ref _genericParametersSource, _type.GetGenericArguments(), null); + if (_genericParametersSource.Length != genericTypeArguments.Length) + throw new InvalidOperationException(); + + // initialize generic type map, and lock on it since we're potentially adding items + if (_genericTypes == null) + Interlocked.CompareExchange(ref _genericTypes, [], null); + if (_genericTypesLock == null) + Interlocked.CompareExchange(ref _genericTypesLock, new(), null); + + try + { + _genericTypesLock.EnterUpgradeableReadLock(); + + // find existing entry + foreach (var i in _genericTypes) + if (i.Arguments.SequenceEqual(genericTypeArguments)) + return i.Symbol; + + try + { + _genericTypesLock.EnterWriteLock(); + + // generate new symbol + var sym = new ReflectionTypeSymbol(Context, ContainingModule, _type.MakeGenericType(genericTypeArguments)); + _genericTypes.Add((genericTypeArguments, sym)); + return sym; + } + finally + { + _genericTypesLock.ExitWriteLock(); + } + } + finally + { + _genericTypesLock.ExitUpgradeableReadLock(); + } + } + + /// + /// Resolves the symbol for the specified type. + /// + /// + /// + protected internal override ReflectionTypeSymbol ResolveTypeSymbol(Type type) + { + if (type == _type) + return this; + else + return base.ResolveTypeSymbol(type); + } + + /// + /// Resolves the symbol for the specified constructor. + /// + /// + /// + protected internal override ReflectionConstructorSymbol ResolveConstructorSymbol(ConstructorInfo ctor) + { + if (ctor.DeclaringType == _type) + return GetOrCreateConstructorSymbol(ctor); + else + return base.ResolveConstructorSymbol(ctor); + } + + /// + /// Resolves the symbol for the specified method. + /// + /// + /// + protected internal override ReflectionMethodSymbol ResolveMethodSymbol(MethodInfo method) + { + if (method.DeclaringType == _type) + return GetOrCreateMethodSymbol(method); + else + return base.ResolveMethodSymbol(method); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override ReflectionFieldSymbol ResolveFieldSymbol(FieldInfo field) + { + if (field.DeclaringType == _type) + return GetOrCreateFieldSymbol(field); + else + return base.ResolveFieldSymbol(field); + } + + /// + /// Resolves the symbol for the specified field. + /// + /// + /// + protected internal override ReflectionPropertySymbol ResolvePropertySymbol(PropertyInfo property) + { + if (property.DeclaringType == _type) + return GetOrCreatePropertySymbol(property); + else + return base.ResolvePropertySymbol(property); + } + + /// + /// Resolves the symbol for the specified event. + /// + /// + /// + protected internal override ReflectionEventSymbol ResolveEventSymbol(EventInfo @event) + { + if (@event.DeclaringType == _type) + return GetOrCreateEventSymbol(@event); + else + return base.ResolveEventSymbol(@event); + } + + /// + /// Gets the wrapped . + /// + internal new Type ReflectionObject => _type; + + public IAssemblySymbol Assembly => Context.GetOrCreateAssemblySymbol(_type.Assembly); + + public string? AssemblyQualifiedName => _type.AssemblyQualifiedName; + + public TypeAttributes Attributes => _type.Attributes; + + public ITypeSymbol? BaseType => _type.BaseType != null ? ResolveTypeSymbol(_type.BaseType) : null; + + public bool ContainsGenericParameters => _type.ContainsGenericParameters; + + public IMethodBaseSymbol? DeclaringMethod => _type.DeclaringMethod is MethodInfo m ? ResolveMethodSymbol(m) : null; + + public string? FullName => _type.FullName; + + public GenericParameterAttributes GenericParameterAttributes => _type.GenericParameterAttributes; + + public int GenericParameterPosition => _type.GenericParameterPosition; + + public ITypeSymbol[] GenericTypeArguments => ResolveTypeSymbols(_type.GenericTypeArguments); + + public bool HasElementType => _type.HasElementType; + + public bool IsAbstract => _type.IsAbstract; + + public bool IsArray => _type.IsArray; + + public bool IsAutoLayout => _type.IsAutoLayout; + + public bool IsByRef => _type.IsByRef; + + public bool IsClass => _type.IsClass; + + public bool IsConstructedGenericType => _type.IsConstructedGenericType; + + public bool IsEnum => _type.IsEnum; + + public bool IsExplicitLayout => _type.IsExplicitLayout; + + public bool IsGenericParameter => _type.IsGenericParameter; + + public bool IsGenericType => _type.IsGenericType; + + public bool IsGenericTypeDefinition => _type.IsGenericTypeDefinition; + + public bool IsInterface => _type.IsInterface; + + public bool IsLayoutSequential => _type.IsLayoutSequential; + + public bool IsNested => _type.IsNested; + + public bool IsNestedAssembly => _type.IsNestedAssembly; + + public bool IsNestedFamANDAssem => _type.IsNestedFamANDAssem; + + public bool IsNestedFamORAssem => _type.IsNestedFamORAssem; + + public bool IsNestedFamily => _type.IsNestedFamily; + + public bool IsNestedPrivate => _type.IsNestedPrivate; + + public bool IsNestedPublic => _type.IsNestedPublic; + + public bool IsNotPublic => _type.IsNotPublic; + + public bool IsPointer => _type.IsPointer; + + public bool IsPrimitive => _type.IsPrimitive; + + public bool IsPublic => _type.IsPublic; + + public bool IsSealed => _type.IsSealed; + +#pragma warning disable SYSLIB0050 // Type or member is obsolete + public bool IsSerializable => _type.IsSerializable; +#pragma warning restore SYSLIB0050 // Type or member is obsolete + + public bool IsValueType => _type.IsValueType; + + public bool IsVisible => _type.IsVisible; + + public string? Namespace => _type.Namespace; + + public IConstructorSymbol? TypeInitializer => _type.TypeInitializer is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + + public int GetArrayRank() + { + return _type.GetArrayRank(); + } + + public IConstructorSymbol? GetConstructor(BindingFlags bindingAttr, ITypeSymbol[] types) + { + return _type.GetConstructor(bindingAttr, binder: null, UnpackTypeSymbols(types), modifiers: null) is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + } + + public IConstructorSymbol? GetConstructor(ITypeSymbol[] types) + { + return _type.GetConstructor(UnpackTypeSymbols(types)) is ConstructorInfo ctor ? ResolveConstructorSymbol(ctor) : null; + } + + public IConstructorSymbol[] GetConstructors() + { + return ResolveConstructorSymbols(_type.GetConstructors()); + } + + public IConstructorSymbol[] GetConstructors(BindingFlags bindingAttr) + { + return ResolveConstructorSymbols(_type.GetConstructors(bindingAttr)); + } + + public IMemberSymbol[] GetDefaultMembers() + { + return ResolveMemberSymbols(_type.GetDefaultMembers()); + } + + public ITypeSymbol? GetElementType() + { + return _type.GetElementType() is Type t ? ResolveTypeSymbol(t) : null; + } + + public string? GetEnumName(object value) + { + return _type.GetEnumName(value); + } + + public string[] GetEnumNames() + { + return _type.GetEnumNames(); + } + + public ITypeSymbol GetEnumUnderlyingType() + { + return ResolveTypeSymbol(_type.GetEnumUnderlyingType()); + } + + public Array GetEnumValues() + { + return _type.GetEnumValues(); + } + + public IEventSymbol? GetEvent(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public IEventSymbol? GetEvent(string name) + { + return _type.GetEvent(name) is { } f ? ResolveEventSymbol(f) : null; + } + + public IEventSymbol[] GetEvents() + { + return ResolveEventSymbols(_type.GetEvents()); + } + + public IEventSymbol[] GetEvents(BindingFlags bindingAttr) + { + return ResolveEventSymbols(_type.GetEvents(bindingAttr)); + } + + public IFieldSymbol? GetField(string name) + { + return _type.GetField(name) is FieldInfo f ? ResolveFieldSymbol(f) : null; + } + + public IFieldSymbol? GetField(string name, BindingFlags bindingAttr) + { + return _type.GetField(name, bindingAttr) is FieldInfo f ? ResolveFieldSymbol(f) : null; + } + + public IFieldSymbol[] GetFields() + { + return ResolveFieldSymbols(_type.GetFields()); + } + + public IFieldSymbol[] GetFields(BindingFlags bindingAttr) + { + return ResolveFieldSymbols(_type.GetFields(bindingAttr)); + } + + public ITypeSymbol[] GetGenericArguments() + { + return ResolveTypeSymbols(_type.GetGenericArguments()); + } + + public ITypeSymbol[] GetGenericParameterConstraints() + { + return ResolveTypeSymbols(_type.GetGenericParameterConstraints()); + } + + public ITypeSymbol GetGenericTypeDefinition() + { + return ResolveTypeSymbol(_type.GetGenericTypeDefinition()); + } + + public ITypeSymbol? GetInterface(string name) + { + return _type.GetInterface(name) is { } i ? ResolveTypeSymbol(i) : null; + } + + public ITypeSymbol? GetInterface(string name, bool ignoreCase) + { + return _type.GetInterface(name, ignoreCase) is { } i ? ResolveTypeSymbol(i) : null; + } + + public InterfaceMapping GetInterfaceMap(ITypeSymbol interfaceType) + { + throw new NotImplementedException(); + } + + public ITypeSymbol[] GetInterfaces() + { + return ResolveTypeSymbols(_type.GetInterfaces()); + } + + public IMemberSymbol[] GetMember(string name) + { + return ResolveMemberSymbols(_type.GetMember(name)); + } + + public IMemberSymbol[] GetMember(string name, BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMember(name, bindingAttr)); + } + + public IMemberSymbol[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMember(name, type, bindingAttr)); + } + + public IMemberSymbol[] GetMembers(BindingFlags bindingAttr) + { + return ResolveMemberSymbols(_type.GetMembers(bindingAttr)); + } + + public IMemberSymbol[] GetMembers() + { + return ResolveMemberSymbols(_type.GetMembers()); + } + + public IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr) + { + return _type.GetMethod(name, bindingAttr) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name, ITypeSymbol[] types) + { + return _type.GetMethod(name, UnpackTypeSymbols(types)) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name, BindingFlags bindingAttr, ITypeSymbol[] types) + { + return _type.GetMethod(name, bindingAttr, null, UnpackTypeSymbols(types), null) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol? GetMethod(string name) + { + return _type.GetMethod(name) is { } m ? ResolveMethodSymbol(m) : null; + } + + public IMethodSymbol[] GetMethods(BindingFlags bindingAttr) + { + return ResolveMethodSymbols(_type.GetMethods(bindingAttr)); + } + + public IMethodSymbol[] GetMethods() + { + return ResolveMethodSymbols(_type.GetMethods()); + } + + public ITypeSymbol? GetNestedType(string name) + { + return _type.GetNestedType(name) is Type t ? ResolveTypeSymbol(t) : null; + } + + public ITypeSymbol? GetNestedType(string name, BindingFlags bindingAttr) + { + return _type.GetNestedType(name, bindingAttr) is Type t ? ResolveTypeSymbol(t) : null; + } + + public ITypeSymbol[] GetNestedTypes() + { + return ResolveTypeSymbols(_type.GetNestedTypes()); + } + + public ITypeSymbol[] GetNestedTypes(BindingFlags bindingAttr) + { + return ResolveTypeSymbols(_type.GetNestedTypes(bindingAttr)); + } + + public IPropertySymbol[] GetProperties() + { + return ResolvePropertySymbols(_type.GetProperties()); + } + + public IPropertySymbol[] GetProperties(BindingFlags bindingAttr) + { + return ResolvePropertySymbols(_type.GetProperties(bindingAttr)); + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol[] types) + { + return _type.GetProperty(name, UnpackTypeSymbols(types)) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType, ITypeSymbol[] types) + { + var _returnType = returnType != null ? ((ReflectionTypeSymbol)returnType).ReflectionObject : null; + return _type.GetProperty(name, _returnType, UnpackTypeSymbols(types)) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, BindingFlags bindingAttr) + { + return _type.GetProperty(name, bindingAttr) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name) + { + return _type.GetProperty(name) is { } p ? ResolvePropertySymbol(p) : null; + } + + public IPropertySymbol? GetProperty(string name, ITypeSymbol? returnType) + { + var _returnType = returnType != null ? ((ReflectionTypeSymbol)returnType).ReflectionObject : null; + + return _type.GetProperty(name, _returnType) is { } p ? ResolvePropertySymbol(p) : null; + } + + public bool IsAssignableFrom(ITypeSymbol? c) + { + return _type.IsAssignableFrom(c != null ? ((ReflectionTypeSymbol)c).ReflectionObject : null); + } + + public bool IsEnumDefined(object value) + { + return _type.IsEnumDefined(value); + } + + public bool IsSubclassOf(ITypeSymbol c) + { + return _type.IsSubclassOf(((ReflectionTypeSymbol)c).ReflectionObject); + } + + public ITypeSymbol MakeArrayType() + { + if (_asSZArray == null) + Interlocked.CompareExchange(ref _asSZArray, new ReflectionTypeSymbol(Context, ContainingModule, _type.MakeArrayType()), null); + + return _asSZArray; + } + + public ITypeSymbol MakeArrayType(int rank) + { + if (rank == 1) + return MakeArrayType(); + + if (_asArray == null) + Interlocked.CompareExchange(ref _asArray, new ReflectionTypeSymbol?[32], null); + + ref var asArray = ref _asArray[rank]; + if (asArray == null) + Interlocked.CompareExchange(ref asArray, new ReflectionTypeSymbol(Context, ContainingModule, _type.MakeArrayType(rank)), null); + + return asArray; + } + + public ITypeSymbol MakeByRefType() + { + if (_asByRef == null) + Interlocked.CompareExchange(ref _asByRef, new ReflectionTypeSymbol(Context, ContainingModule, _type.MakeByRefType()), null); + + return _asByRef; + } + + public ITypeSymbol MakeGenericType(params ITypeSymbol[] typeArguments) + { + throw new NotImplementedException(); + } + + public ITypeSymbol MakePointerType() + { + if (_asPointer == null) + Interlocked.CompareExchange(ref _asPointer, new ReflectionTypeSymbol(Context, ContainingModule, _type.MakePointerType()), null); + + return _asPointer; + } + + } + +} diff --git a/src/IKVM.Reflection.Tests/IKVM.Reflection.Tests.csproj b/src/IKVM.Reflection.Tests/IKVM.Reflection.Tests.csproj index 1d174e816f..230f64d71c 100644 --- a/src/IKVM.Reflection.Tests/IKVM.Reflection.Tests.csproj +++ b/src/IKVM.Reflection.Tests/IKVM.Reflection.Tests.csproj @@ -1,6 +1,6 @@  - net472;net6.0;net7.0;net8.0 + net472;net6.0;net8.0 diff --git a/src/IKVM.Reflection/IKVM.Reflection.csproj b/src/IKVM.Reflection/IKVM.Reflection.csproj index 89c0e0f0dd..ce87f7cbca 100644 --- a/src/IKVM.Reflection/IKVM.Reflection.csproj +++ b/src/IKVM.Reflection/IKVM.Reflection.csproj @@ -1,7 +1,7 @@  - net472;net6.0;net7.0;net8.0 + net472;net6.0;net8.0 IKVM implementation of System.Reflection[.Emit] true 11 diff --git a/src/IKVM.Reflection/Universe.cs b/src/IKVM.Reflection/Universe.cs index 37b45b982d..e933bc87af 100644 --- a/src/IKVM.Reflection/Universe.cs +++ b/src/IKVM.Reflection/Universe.cs @@ -603,42 +603,7 @@ Assembly DefaultResolver(string refname, bool throwOnError) if (asm != null) return asm; -#if NETFRAMEWORK - - string fileName; - if (throwOnError) - { - try - { - fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location; - } - catch (System.BadImageFormatException x) - { - throw new BadImageFormatException(x.Message, x); - } - } - else - { - try - { - fileName = System.Reflection.Assembly.ReflectionOnlyLoad(refname).Location; - } - catch (System.BadImageFormatException x) - { - throw new BadImageFormatException(x.Message, x); - } - catch (FileNotFoundException) - { - // we intentionally only swallow the FileNotFoundException, if the file exists but isn't a valid assembly, - // we should throw an exception - return null; - } - } - - return LoadFile(fileName); -#else return null; -#endif } public Type GetType(string assemblyQualifiedTypeName) diff --git a/src/IKVM.Runtime/Annotation.cs b/src/IKVM.Runtime/Annotation.cs index dec264adf4..5ceea4735a 100644 --- a/src/IKVM.Runtime/Annotation.cs +++ b/src/IKVM.Runtime/Annotation.cs @@ -111,7 +111,7 @@ internal static Annotation Load(RuntimeJavaType owner, object[] def) owner.Diagnostics.GenericCompilerWarning($"Unable to load annotation class {annotationClass}"); #if IMPORTER - return new RuntimeManagedByteCodeJavaType.CompiledAnnotation(owner.Context, owner.Context.Resolver.ResolveRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute")); + return new RuntimeManagedByteCodeJavaType.CompiledAnnotation(owner.Context, owner.Context.Resolver.ResolveRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute").AsReflection()); #else return null; #endif diff --git a/src/IKVM.Runtime/AttributeHelper.cs b/src/IKVM.Runtime/AttributeHelper.cs index cbd477d1c5..ea8b43babf 100644 --- a/src/IKVM.Runtime/AttributeHelper.cs +++ b/src/IKVM.Runtime/AttributeHelper.cs @@ -60,27 +60,27 @@ class AttributeHelper #if IMPORTER - CustomAttributeBuilder compilerGeneratedAttribute; - CustomAttributeBuilder ghostInterfaceAttribute; - CustomAttributeBuilder deprecatedAttribute; - CustomAttributeBuilder editorBrowsableNever; - ConstructorInfo implementsAttribute; - ConstructorInfo throwsAttribute; - ConstructorInfo sourceFileAttribute; - ConstructorInfo lineNumberTableAttribute1; - ConstructorInfo lineNumberTableAttribute2; - ConstructorInfo enclosingMethodAttribute; - ConstructorInfo signatureAttribute; - ConstructorInfo methodParametersAttribute; - ConstructorInfo runtimeVisibleTypeAnnotationsAttribute; - ConstructorInfo constantPoolAttribute; - CustomAttributeBuilder paramArrayAttribute; - ConstructorInfo nonNestedInnerClassAttribute; - ConstructorInfo nonNestedOuterClassAttribute; - - Type typeofModifiers; - Type typeofSourceFileAttribute; - Type typeofLineNumberTableAttribute; + CustomAttributeBuilder compilerGeneratedAttribute; + CustomAttributeBuilder ghostInterfaceAttribute; + CustomAttributeBuilder deprecatedAttribute; + CustomAttributeBuilder editorBrowsableNever; + ConstructorInfo implementsAttribute; + ConstructorInfo throwsAttribute; + ConstructorInfo sourceFileAttribute; + ConstructorInfo lineNumberTableAttribute1; + ConstructorInfo lineNumberTableAttribute2; + ConstructorInfo enclosingMethodAttribute; + ConstructorInfo signatureAttribute; + ConstructorInfo methodParametersAttribute; + ConstructorInfo runtimeVisibleTypeAnnotationsAttribute; + ConstructorInfo constantPoolAttribute; + CustomAttributeBuilder paramArrayAttribute; + ConstructorInfo nonNestedInnerClassAttribute; + ConstructorInfo nonNestedOuterClassAttribute; + + Type typeofModifiers; + Type typeofSourceFileAttribute; + Type typeofLineNumberTableAttribute; #endif @@ -113,11 +113,11 @@ class AttributeHelper #if IMPORTER - Type TypeOfModifiers => typeofModifiers ??= LoadType(typeof(Modifiers)); + Type TypeOfModifiers => typeofModifiers ??= LoadType(typeof(Modifiers)); - Type TypeOfSourceFileAttribute => typeofSourceFileAttribute ??= LoadType(typeof(IKVM.Attributes.SourceFileAttribute)); + Type TypeOfSourceFileAttribute => typeofSourceFileAttribute ??= LoadType(typeof(IKVM.Attributes.SourceFileAttribute)); - Type TypeOfLineNumberTableAttribute => typeofLineNumberTableAttribute ??= LoadType(typeof(IKVM.Attributes.LineNumberTableAttribute)); + Type TypeOfLineNumberTableAttribute => typeofLineNumberTableAttribute ??= LoadType(typeof(IKVM.Attributes.LineNumberTableAttribute)); #endif @@ -165,7 +165,7 @@ class AttributeHelper Type TypeOfConstantPoolAttribute => typeofConstantPoolAttribute ??= LoadType(typeof(ConstantPoolAttribute)); - Type TypeOfDebuggableAttribute => typeofDebuggableAttribute ??= context.Resolver.ResolveCoreType(typeof(DebuggableAttribute).FullName); + Type TypeOfDebuggableAttribute => typeofDebuggableAttribute ??= context.Resolver.ResolveCoreType(typeof(DebuggableAttribute).FullName).AsReflection(); CustomAttributeBuilder HideFromJavaAttributeBuilder => hideFromJavaAttribute ??= new CustomAttributeBuilder(TypeOfHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), Array.Empty()); @@ -178,7 +178,7 @@ class AttributeHelper /// Type LoadType(System.Type t) { - return context.Resolver.ResolveRuntimeType(t.FullName); + return context.Resolver.ResolveRuntimeType(t.FullName).AsReflection(); } /// @@ -192,314 +192,314 @@ public AttributeHelper(RuntimeContext context) #if IMPORTER - object ParseValue(RuntimeClassLoader loader, RuntimeJavaType tw, string val) - { - if (tw == context.JavaBase.TypeOfJavaLangString) - { - return val; - } - else if (tw.IsUnloadable) - { - throw new FatalCompilerErrorException(DiagnosticEvent.MapFileTypeNotFound(tw.Name)); - } - else if (tw.TypeAsTBD.IsEnum) - { - return EnumHelper.Parse(context, tw.TypeAsTBD, val); - } - else if (tw.TypeAsTBD == context.Types.Type) - { - var valtw = loader.TryLoadClassByName(val); - if (valtw != null) - return valtw.TypeAsBaseType; - - return context.StaticCompiler.Universe.GetType(val, true); - } - else if (tw == context.PrimitiveJavaTypeFactory.BOOLEAN) - { - return bool.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.BYTE) - { - return (byte)sbyte.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.CHAR) - { - return char.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.SHORT) - { - return short.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.INT) - { - return int.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.FLOAT) - { - return float.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.LONG) - { - return long.Parse(val); - } - else if (tw == context.PrimitiveJavaTypeFactory.DOUBLE) - { - return double.Parse(val); - } - else - { - throw new NotImplementedException(); - } - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, TypeBuilder tb, IKVM.Tools.Importer.MapXml.Attribute attr) - { - tb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, FieldBuilder fb, IKVM.Tools.Importer.MapXml.Attribute attr) - { - fb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, ParameterBuilder pb, IKVM.Tools.Importer.MapXml.Attribute attr) - { - pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, MethodBuilder mb, IKVM.Tools.Importer.MapXml.Attribute attr) - { - mb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, PropertyBuilder pb, IKVM.Tools.Importer.MapXml.Attribute attr) - { - pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - internal void SetCustomAttribute(RuntimeClassLoader loader, AssemblyBuilder ab, IKVM.Tools.Importer.MapXml.Attribute attr) - { - ab.SetCustomAttribute(CreateCustomAttribute(loader, attr)); - } - - void GetAttributeArgsAndTypes(RuntimeClassLoader loader, IKVM.Tools.Importer.MapXml.Attribute attr, out Type[] argTypes, out object[] args) - { - // TODO add error handling - var twargs = loader.ArgJavaTypeListFromSig(attr.Sig, LoadMode.Link); - argTypes = new Type[twargs.Length]; - args = new object[argTypes.Length]; - for (int i = 0; i < twargs.Length; i++) - { - argTypes[i] = twargs[i].TypeAsSignatureType; - RuntimeJavaType tw = twargs[i]; - if (tw == context.JavaBase.TypeOfJavaLangObject) - { - tw = loader.FieldTypeWrapperFromSig(attr.Params[i].Sig, LoadMode.Link); - } - if (tw.IsArray) - { - Array arr = Array.CreateInstance(Type.__GetSystemType(Type.GetTypeCode(tw.ElementTypeWrapper.TypeAsArrayType)), attr.Params[i].Elements.Length); - for (int j = 0; j < arr.Length; j++) - { - arr.SetValue(ParseValue(loader, tw.ElementTypeWrapper, attr.Params[i].Elements[j].Value), j); - } - args[i] = arr; - } - else - { - args[i] = ParseValue(loader, tw, attr.Params[i].Value); - } - } - } - - CustomAttributeBuilder CreateCustomAttribute(RuntimeClassLoader loader, IKVM.Tools.Importer.MapXml.Attribute attr) - { - // TODO add error handling - Type[] argTypes; - object[] args; - GetAttributeArgsAndTypes(loader, attr, out argTypes, out args); - if (attr.Type != null) - { - var t = context.Resolver.ResolveCoreType(attr.Type); - var ci = t.GetConstructor(argTypes); - if (ci == null) - throw new InvalidOperationException($"Constructor missing: {attr.Type}::{attr.Sig}"); - - PropertyInfo[] namedProperties; - object[] propertyValues; - if (attr.Properties != null) - { - namedProperties = new PropertyInfo[attr.Properties.Length]; - propertyValues = new object[attr.Properties.Length]; - for (int i = 0; i < namedProperties.Length; i++) - { - namedProperties[i] = t.GetProperty(attr.Properties[i].Name); - propertyValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Properties[i].Sig, LoadMode.Link), attr.Properties[i].Value); - } - } - else - { - namedProperties = new PropertyInfo[0]; - propertyValues = new object[0]; - } - FieldInfo[] namedFields; - object[] fieldValues; - if (attr.Fields != null) - { - namedFields = new FieldInfo[attr.Fields.Length]; - fieldValues = new object[attr.Fields.Length]; - for (int i = 0; i < namedFields.Length; i++) - { - namedFields[i] = t.GetField(attr.Fields[i].Name); - fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); - } - } - else - { - namedFields = new FieldInfo[0]; - fieldValues = new object[0]; - } - return new CustomAttributeBuilder(ci, args, namedProperties, propertyValues, namedFields, fieldValues); - } - else - { - if (attr.Properties != null) - { - throw new NotImplementedException("Setting property values on Java attributes is not implemented"); - } - RuntimeJavaType t = loader.LoadClassByName(attr.Class); - FieldInfo[] namedFields; - object[] fieldValues; - if (attr.Fields != null) - { - namedFields = new FieldInfo[attr.Fields.Length]; - fieldValues = new object[attr.Fields.Length]; - for (int i = 0; i < namedFields.Length; i++) - { - RuntimeJavaField fw = t.GetFieldWrapper(attr.Fields[i].Name, attr.Fields[i].Sig); - fw.Link(); - namedFields[i] = fw.GetField(); - fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); - } - } - else - { - namedFields = new FieldInfo[0]; - fieldValues = new object[0]; - } - var mw = t.GetMethodWrapper("", attr.Sig, false); - if (mw == null) - { - throw new InvalidOperationException(string.Format("Constructor missing: {0}::{1}", attr.Class, attr.Sig)); - } - mw.Link(); - ConstructorInfo ci = (mw.GetMethod() as ConstructorInfo) ?? ((MethodInfo)mw.GetMethod()).__AsConstructorInfo(); - return new CustomAttributeBuilder(ci, args, namedFields, fieldValues); - } - } - - CustomAttributeBuilder GetEditorBrowsableNever() - { - if (editorBrowsableNever == null) - { - var typeofEditorBrowsableAttribute = context.Resolver.ResolveCoreType(typeof(EditorBrowsableAttribute).FullName); - var typeofEditorBrowsableState = context.Resolver.ResolveCoreType(typeof(EditorBrowsableState).FullName); - var ctor = (ConstructorInfo)typeofEditorBrowsableAttribute.__CreateMissingMethod(ConstructorInfo.ConstructorName, CallingConventions.Standard | CallingConventions.HasThis, null, default, new Type[] { typeofEditorBrowsableState }, null); - editorBrowsableNever = CustomAttributeBuilder.__FromBlob(ctor, new byte[] { 01, 00, 01, 00, 00, 00, 00, 00 }); - } - - return editorBrowsableNever; - } - - internal void SetCompilerGenerated(TypeBuilder tb) - { - compilerGeneratedAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(CompilerGeneratedAttribute).FullName).GetConstructor(Type.EmptyTypes), Array.Empty()); - tb.SetCustomAttribute(compilerGeneratedAttribute); - } - - internal void SetCompilerGenerated(MethodBuilder mb) - { - compilerGeneratedAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(CompilerGeneratedAttribute).FullName).GetConstructor(Type.EmptyTypes), Array.Empty()); - mb.SetCustomAttribute(compilerGeneratedAttribute); - } - - internal void SetEditorBrowsableNever(TypeBuilder tb) - { - tb.SetCustomAttribute(GetEditorBrowsableNever()); - } - - internal void SetEditorBrowsableNever(MethodBuilder mb) - { - mb.SetCustomAttribute(GetEditorBrowsableNever()); - } - - internal void SetEditorBrowsableNever(PropertyBuilder pb) - { - pb.SetCustomAttribute(GetEditorBrowsableNever()); - } - - internal void SetDeprecatedAttribute(MethodBuilder mb) - { - if (deprecatedAttribute == null) - deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); - - mb.SetCustomAttribute(deprecatedAttribute); - } - - internal void SetDeprecatedAttribute(TypeBuilder tb) - { - if (deprecatedAttribute == null) - { - deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); - } - - tb.SetCustomAttribute(deprecatedAttribute); - } - - internal void SetDeprecatedAttribute(FieldBuilder fb) - { - if (deprecatedAttribute == null) - deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); - - fb.SetCustomAttribute(deprecatedAttribute); - } - - internal void SetDeprecatedAttribute(PropertyBuilder pb) - { - if (deprecatedAttribute == null) - { - deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); - } - pb.SetCustomAttribute(deprecatedAttribute); - } - - internal void SetThrowsAttribute(MethodBuilder mb, string[] exceptions) - { - if (exceptions != null && exceptions.Length != 0) - { - throwsAttribute ??= TypeOfThrowsAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(string).FullName).MakeArrayType() }); - exceptions = UnicodeUtil.EscapeInvalidSurrogates(exceptions); - mb.SetCustomAttribute(new CustomAttributeBuilder(throwsAttribute, new object[] { exceptions })); - } - } - - internal void SetGhostInterface(TypeBuilder typeBuilder) - { - ghostInterfaceAttribute ??= new CustomAttributeBuilder(TypeOfGhostInterfaceAttribute.GetConstructor(Type.EmptyTypes), new object[0]); - typeBuilder.SetCustomAttribute(ghostInterfaceAttribute); - } - - internal void SetNonNestedInnerClass(TypeBuilder typeBuilder, string className) - { - nonNestedInnerClassAttribute ??= TypeOfNonNestedInnerClassAttribute.GetConstructor(new Type[] { context.Types.String }); - typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedInnerClassAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); - } - - internal void SetNonNestedOuterClass(TypeBuilder typeBuilder, string className) - { - nonNestedOuterClassAttribute ??= TypeOfNonNestedOuterClassAttribute.GetConstructor(new Type[] { context.Types.String }); - typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedOuterClassAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); - } + object ParseValue(RuntimeClassLoader loader, RuntimeJavaType tw, string val) + { + if (tw == context.JavaBase.TypeOfJavaLangString) + { + return val; + } + else if (tw.IsUnloadable) + { + throw new FatalCompilerErrorException(DiagnosticEvent.MapFileTypeNotFound(tw.Name)); + } + else if (tw.TypeAsTBD.IsEnum) + { + return EnumHelper.Parse(context, tw.TypeAsTBD, val); + } + else if (tw.TypeAsTBD == context.Types.Type) + { + var valtw = loader.TryLoadClassByName(val); + if (valtw != null) + return valtw.TypeAsBaseType; + + return context.StaticCompiler.Universe.GetType(val, true); + } + else if (tw == context.PrimitiveJavaTypeFactory.BOOLEAN) + { + return bool.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.BYTE) + { + return (byte)sbyte.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.CHAR) + { + return char.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.SHORT) + { + return short.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.INT) + { + return int.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.FLOAT) + { + return float.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.LONG) + { + return long.Parse(val); + } + else if (tw == context.PrimitiveJavaTypeFactory.DOUBLE) + { + return double.Parse(val); + } + else + { + throw new NotImplementedException(); + } + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, TypeBuilder tb, IKVM.Tools.Importer.MapXml.Attribute attr) + { + tb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, FieldBuilder fb, IKVM.Tools.Importer.MapXml.Attribute attr) + { + fb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, ParameterBuilder pb, IKVM.Tools.Importer.MapXml.Attribute attr) + { + pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, MethodBuilder mb, IKVM.Tools.Importer.MapXml.Attribute attr) + { + mb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, PropertyBuilder pb, IKVM.Tools.Importer.MapXml.Attribute attr) + { + pb.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + internal void SetCustomAttribute(RuntimeClassLoader loader, AssemblyBuilder ab, IKVM.Tools.Importer.MapXml.Attribute attr) + { + ab.SetCustomAttribute(CreateCustomAttribute(loader, attr)); + } + + void GetAttributeArgsAndTypes(RuntimeClassLoader loader, IKVM.Tools.Importer.MapXml.Attribute attr, out Type[] argTypes, out object[] args) + { + // TODO add error handling + var twargs = loader.ArgJavaTypeListFromSig(attr.Sig, LoadMode.Link); + argTypes = new Type[twargs.Length]; + args = new object[argTypes.Length]; + for (int i = 0; i < twargs.Length; i++) + { + argTypes[i] = twargs[i].TypeAsSignatureType; + RuntimeJavaType tw = twargs[i]; + if (tw == context.JavaBase.TypeOfJavaLangObject) + { + tw = loader.FieldTypeWrapperFromSig(attr.Params[i].Sig, LoadMode.Link); + } + if (tw.IsArray) + { + Array arr = Array.CreateInstance(Type.__GetSystemType(Type.GetTypeCode(tw.ElementTypeWrapper.TypeAsArrayType)), attr.Params[i].Elements.Length); + for (int j = 0; j < arr.Length; j++) + { + arr.SetValue(ParseValue(loader, tw.ElementTypeWrapper, attr.Params[i].Elements[j].Value), j); + } + args[i] = arr; + } + else + { + args[i] = ParseValue(loader, tw, attr.Params[i].Value); + } + } + } + + CustomAttributeBuilder CreateCustomAttribute(RuntimeClassLoader loader, IKVM.Tools.Importer.MapXml.Attribute attr) + { + // TODO add error handling + Type[] argTypes; + object[] args; + GetAttributeArgsAndTypes(loader, attr, out argTypes, out args); + if (attr.Type != null) + { + var t = context.Resolver.ResolveCoreType(attr.Type).AsReflection(); + var ci = t.GetConstructor(argTypes); + if (ci == null) + throw new InvalidOperationException($"Constructor missing: {attr.Type}::{attr.Sig}"); + + PropertyInfo[] namedProperties; + object[] propertyValues; + if (attr.Properties != null) + { + namedProperties = new PropertyInfo[attr.Properties.Length]; + propertyValues = new object[attr.Properties.Length]; + for (int i = 0; i < namedProperties.Length; i++) + { + namedProperties[i] = t.GetProperty(attr.Properties[i].Name); + propertyValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Properties[i].Sig, LoadMode.Link), attr.Properties[i].Value); + } + } + else + { + namedProperties = new PropertyInfo[0]; + propertyValues = new object[0]; + } + FieldInfo[] namedFields; + object[] fieldValues; + if (attr.Fields != null) + { + namedFields = new FieldInfo[attr.Fields.Length]; + fieldValues = new object[attr.Fields.Length]; + for (int i = 0; i < namedFields.Length; i++) + { + namedFields[i] = t.GetField(attr.Fields[i].Name); + fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); + } + } + else + { + namedFields = new FieldInfo[0]; + fieldValues = new object[0]; + } + return new CustomAttributeBuilder(ci, args, namedProperties, propertyValues, namedFields, fieldValues); + } + else + { + if (attr.Properties != null) + { + throw new NotImplementedException("Setting property values on Java attributes is not implemented"); + } + RuntimeJavaType t = loader.LoadClassByName(attr.Class); + FieldInfo[] namedFields; + object[] fieldValues; + if (attr.Fields != null) + { + namedFields = new FieldInfo[attr.Fields.Length]; + fieldValues = new object[attr.Fields.Length]; + for (int i = 0; i < namedFields.Length; i++) + { + RuntimeJavaField fw = t.GetFieldWrapper(attr.Fields[i].Name, attr.Fields[i].Sig); + fw.Link(); + namedFields[i] = fw.GetField(); + fieldValues[i] = ParseValue(loader, loader.FieldTypeWrapperFromSig(attr.Fields[i].Sig, LoadMode.Link), attr.Fields[i].Value); + } + } + else + { + namedFields = new FieldInfo[0]; + fieldValues = new object[0]; + } + var mw = t.GetMethodWrapper("", attr.Sig, false); + if (mw == null) + { + throw new InvalidOperationException(string.Format("Constructor missing: {0}::{1}", attr.Class, attr.Sig)); + } + mw.Link(); + ConstructorInfo ci = (mw.GetMethod() as ConstructorInfo) ?? ((MethodInfo)mw.GetMethod()).__AsConstructorInfo(); + return new CustomAttributeBuilder(ci, args, namedFields, fieldValues); + } + } + + CustomAttributeBuilder GetEditorBrowsableNever() + { + if (editorBrowsableNever == null) + { + var typeofEditorBrowsableAttribute = context.Resolver.ResolveCoreType(typeof(EditorBrowsableAttribute).FullName).AsReflection(); + var typeofEditorBrowsableState = context.Resolver.ResolveCoreType(typeof(EditorBrowsableState).FullName).AsReflection(); + var ctor = (ConstructorInfo)typeofEditorBrowsableAttribute.__CreateMissingMethod(ConstructorInfo.ConstructorName, CallingConventions.Standard | CallingConventions.HasThis, null, default, new Type[] { typeofEditorBrowsableState }, null); + editorBrowsableNever = CustomAttributeBuilder.__FromBlob(ctor, new byte[] { 01, 00, 01, 00, 00, 00, 00, 00 }); + } + + return editorBrowsableNever; + } + + internal void SetCompilerGenerated(TypeBuilder tb) + { + compilerGeneratedAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(CompilerGeneratedAttribute).FullName).AsReflection().GetConstructor(Type.EmptyTypes), Array.Empty()); + tb.SetCustomAttribute(compilerGeneratedAttribute); + } + + internal void SetCompilerGenerated(MethodBuilder mb) + { + compilerGeneratedAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(CompilerGeneratedAttribute).FullName).AsReflection().GetConstructor(Type.EmptyTypes), Array.Empty()); + mb.SetCustomAttribute(compilerGeneratedAttribute); + } + + internal void SetEditorBrowsableNever(TypeBuilder tb) + { + tb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal void SetEditorBrowsableNever(MethodBuilder mb) + { + mb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal void SetEditorBrowsableNever(PropertyBuilder pb) + { + pb.SetCustomAttribute(GetEditorBrowsableNever()); + } + + internal void SetDeprecatedAttribute(MethodBuilder mb) + { + if (deprecatedAttribute == null) + deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor([]).AsReflection(), []); + + mb.SetCustomAttribute(deprecatedAttribute); + } + + internal void SetDeprecatedAttribute(TypeBuilder tb) + { + if (deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor([]).AsReflection(), []); + } + + tb.SetCustomAttribute(deprecatedAttribute); + } + + internal void SetDeprecatedAttribute(FieldBuilder fb) + { + if (deprecatedAttribute == null) + deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor([]).AsReflection(), new object[0]); + + fb.SetCustomAttribute(deprecatedAttribute); + } + + internal void SetDeprecatedAttribute(PropertyBuilder pb) + { + if (deprecatedAttribute == null) + { + deprecatedAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).GetConstructor([]).AsReflection(), new object[0]); + } + pb.SetCustomAttribute(deprecatedAttribute); + } + + internal void SetThrowsAttribute(MethodBuilder mb, string[] exceptions) + { + if (exceptions != null && exceptions.Length != 0) + { + throwsAttribute ??= TypeOfThrowsAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(string).FullName).MakeArrayType().AsReflection() }); + exceptions = UnicodeUtil.EscapeInvalidSurrogates(exceptions); + mb.SetCustomAttribute(new CustomAttributeBuilder(throwsAttribute, new object[] { exceptions })); + } + } + + internal void SetGhostInterface(TypeBuilder typeBuilder) + { + ghostInterfaceAttribute ??= new CustomAttributeBuilder(TypeOfGhostInterfaceAttribute.GetConstructor(Type.EmptyTypes), new object[0]); + typeBuilder.SetCustomAttribute(ghostInterfaceAttribute); + } + + internal void SetNonNestedInnerClass(TypeBuilder typeBuilder, string className) + { + nonNestedInnerClassAttribute ??= TypeOfNonNestedInnerClassAttribute.GetConstructor(new Type[] { context.Types.String }); + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedInnerClassAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); + } + + internal void SetNonNestedOuterClass(TypeBuilder typeBuilder, string className) + { + nonNestedOuterClassAttribute ??= TypeOfNonNestedOuterClassAttribute.GetConstructor(new Type[] { context.Types.String }); + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedOuterClassAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(className) })); + } #endif // IMPORTER @@ -541,10 +541,10 @@ internal void HideFromJava(FieldBuilder fb) #if IMPORTER - internal void HideFromJava(PropertyBuilder pb) - { - pb.SetCustomAttribute(HideFromJavaAttributeBuilder); - } + internal void HideFromJava(PropertyBuilder pb) + { + pb.SetCustomAttribute(HideFromJavaAttributeBuilder); + } #endif @@ -579,15 +579,15 @@ internal HideFromJavaFlags GetHideFromJavaFlags(MemberInfo mi) return ((HideFromJavaAttribute)attr[0]).Flags; #else - var attr = CustomAttributeData.__GetCustomAttributes(mi, TypeOfHideFromJavaAttribute, false); - if (attr.Count == 1) - { - var args = attr[0].ConstructorArguments; - if (args.Count == 1) - return (HideFromJavaFlags)args[0].Value; - - return HideFromJavaFlags.All; - } + var attr = CustomAttributeData.__GetCustomAttributes(mi, TypeOfHideFromJavaAttribute, false); + if (attr.Count == 1) + { + var args = attr[0].ConstructorArguments; + if (args.Count == 1) + return (HideFromJavaFlags)args[0].Value; + + return HideFromJavaFlags.All; + } #endif return HideFromJavaFlags.None; @@ -595,17 +595,17 @@ internal HideFromJavaFlags GetHideFromJavaFlags(MemberInfo mi) #if IMPORTER - internal void SetImplementsAttribute(TypeBuilder typeBuilder, RuntimeJavaType[] ifaceWrappers) - { - var interfaces = new string[ifaceWrappers.Length]; - for (int i = 0; i < interfaces.Length; i++) - interfaces[i] = UnicodeUtil.EscapeInvalidSurrogates(ifaceWrappers[i].Name); + internal void SetImplementsAttribute(TypeBuilder typeBuilder, RuntimeJavaType[] ifaceWrappers) + { + var interfaces = new string[ifaceWrappers.Length]; + for (int i = 0; i < interfaces.Length; i++) + interfaces[i] = UnicodeUtil.EscapeInvalidSurrogates(ifaceWrappers[i].Name); - if (implementsAttribute == null) - implementsAttribute = TypeOfImplementsAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(string).FullName).MakeArrayType() }); + if (implementsAttribute == null) + implementsAttribute = TypeOfImplementsAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(string).FullName).MakeArrayType().AsReflection() }); - typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(implementsAttribute, new object[] { interfaces })); - } + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(implementsAttribute, new object[] { interfaces })); + } #endif @@ -630,17 +630,17 @@ internal ModifiersAttribute GetModifiersAttribute(MemberInfo member) var attr = member.GetCustomAttributes(typeof(ModifiersAttribute), false); return attr.Length == 1 ? (ModifiersAttribute)attr[0] : null; #else - var attr = CustomAttributeData.__GetCustomAttributes(member, TypeOfModifiersAttribute, false); - if (attr.Count == 1) - { - var args = attr[0].ConstructorArguments; - if (args.Count == 2) - return new ModifiersAttribute((Modifiers)args[0].Value, (bool)args[1].Value); + var attr = CustomAttributeData.__GetCustomAttributes(member, TypeOfModifiersAttribute, false); + if (attr.Count == 1) + { + var args = attr[0].ConstructorArguments; + if (args.Count == 2) + return new ModifiersAttribute((Modifiers)args[0].Value, (bool)args[1].Value); - return new ModifiersAttribute((Modifiers)args[0].Value); - } + return new ModifiersAttribute((Modifiers)args[0].Value); + } - return null; + return null; #endif } @@ -702,7 +702,7 @@ internal ExModifiers GetModifiers(MethodBase mb, bool assemblyIsPrivate) } var parameters = mb.GetParameters(); - if (parameters.Length > 0 && parameters[parameters.Length - 1].IsDefined(context.Resolver.ResolveCoreType(typeof(ParamArrayAttribute).FullName), false)) + if (parameters.Length > 0 && parameters[parameters.Length - 1].IsDefined(context.Resolver.ResolveCoreType(typeof(ParamArrayAttribute).FullName).AsReflection(), false)) modifiers |= Modifiers.VarArgs; return new ExModifiers(modifiers, false); @@ -763,171 +763,171 @@ internal void SetDebuggingModes(AssemblyBuilder assemblyBuilder, DebuggableAttri #if IMPORTER - internal void SetModifiers(MethodBuilder mb, Modifiers modifiers, bool isInternal) - { - CustomAttributeBuilder customAttributeBuilder; - if (isInternal) - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); - else - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); - - mb.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetModifiers(FieldBuilder fb, Modifiers modifiers, bool isInternal) - { - CustomAttributeBuilder customAttributeBuilder; - if (isInternal) - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); - else - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); - - fb.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetModifiers(PropertyBuilder pb, Modifiers modifiers, bool isInternal) - { - CustomAttributeBuilder customAttributeBuilder; - if (isInternal) - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); - else - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); - - pb.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetModifiers(TypeBuilder tb, Modifiers modifiers, bool isInternal) - { - CustomAttributeBuilder customAttributeBuilder; - if (isInternal) - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); - else - customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); - - tb.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetNameSig(MethodBuilder mb, string name, string sig) - { - var customAttributeBuilder = new CustomAttributeBuilder(TypeOfNameSigAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String }), new object[] { UnicodeUtil.EscapeInvalidSurrogates(name), UnicodeUtil.EscapeInvalidSurrogates(sig) }); - mb.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetInnerClass(TypeBuilder typeBuilder, string innerClass, Modifiers modifiers) - { - var argTypes = new Type[] { context.Types.String, TypeOfModifiers }; - var args = new object[] { UnicodeUtil.EscapeInvalidSurrogates(innerClass), modifiers }; - var ci = TypeOfInnerClassAttribute.GetConstructor(argTypes); - var customAttributeBuilder = new CustomAttributeBuilder(ci, args); - typeBuilder.SetCustomAttribute(customAttributeBuilder); - } - - internal void SetSourceFile(TypeBuilder typeBuilder, string filename) - { - sourceFileAttribute ??= TypeOfSourceFileAttribute.GetConstructor(new Type[] { context.Types.String }); - typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); - } - - internal void SetSourceFile(ModuleBuilder moduleBuilder, string filename) - { - sourceFileAttribute ??= TypeOfSourceFileAttribute.GetConstructor(new Type[] { context.Types.String }); - moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); - } - - internal void SetLineNumberTable(MethodBuilder mb, IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter writer) - { - object arg; - ConstructorInfo con; - if (writer.Count == 1) - { - lineNumberTableAttribute2 ??= TypeOfLineNumberTableAttribute.GetConstructor(new Type[] { context.Types.UInt16 }); - con = lineNumberTableAttribute2; - arg = (ushort)writer.LineNo; - } - else - { - lineNumberTableAttribute1 ??= TypeOfLineNumberTableAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(byte).FullName).MakeArrayType() }); - con = lineNumberTableAttribute1; - arg = writer.ToArray(); - } - mb.SetCustomAttribute(new CustomAttributeBuilder(con, new object[] { arg })); - } - - internal void SetEnclosingMethodAttribute(TypeBuilder tb, string className, string methodName, string methodSig) - { - if (enclosingMethodAttribute == null) - { - enclosingMethodAttribute = TypeOfEnclosingMethodAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String, context.Types.String }); - } - tb.SetCustomAttribute(new CustomAttributeBuilder(enclosingMethodAttribute, - new object[] { UnicodeUtil.EscapeInvalidSurrogates(className), UnicodeUtil.EscapeInvalidSurrogates(methodName), UnicodeUtil.EscapeInvalidSurrogates(methodSig) })); - } - - internal void SetSignatureAttribute(TypeBuilder tb, string signature) - { - signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); - tb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); - } - - internal void SetSignatureAttribute(FieldBuilder fb, string signature) - { - signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); - fb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); - } - - internal void SetSignatureAttribute(MethodBuilder mb, string signature) - { - signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); - mb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); - } - - internal void SetMethodParametersAttribute(MethodBuilder mb, Modifiers[] modifiers) - { - methodParametersAttribute ??= TypeOfMethodParametersAttribute.GetConstructor(new[] { TypeOfModifiers.MakeArrayType() }); - mb.SetCustomAttribute(new CustomAttributeBuilder(methodParametersAttribute, new[] { modifiers })); - } - - internal void SetRuntimeVisibleTypeAnnotationsAttribute(TypeBuilder tb, ref readonly TypeAnnotationTable table) - { - var builder = new BlobBuilder(); - var encoder = new TypeAnnotationTableEncoder(builder); - table.WriteTo(ref encoder); - - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); - tb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); - } - - internal void SetRuntimeVisibleTypeAnnotationsAttribute(FieldBuilder fb, ref readonly TypeAnnotationTable table) - { - var builder = new BlobBuilder(); - var encoder = new TypeAnnotationTableEncoder(builder); - table.WriteTo(ref encoder); - - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); - fb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); - } - - internal void SetRuntimeVisibleTypeAnnotationsAttribute(MethodBuilder mb, ref readonly TypeAnnotationTable table) - { - var builder = new BlobBuilder(); - var encoder = new TypeAnnotationTableEncoder(builder); - table.WriteTo(ref encoder); - - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); - mb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); - } - - internal void SetConstantPoolAttribute(TypeBuilder tb, object[] constantPool) - { - constantPoolAttribute ??= TypeOfConstantPoolAttribute.GetConstructor(new Type[] { context.Types.Object.MakeArrayType() }); - tb.SetCustomAttribute(new CustomAttributeBuilder(constantPoolAttribute, [constantPool])); - } - - internal void SetParamArrayAttribute(ParameterBuilder pb) - { - paramArrayAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ParamArrayAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); - pb.SetCustomAttribute(paramArrayAttribute); - } + internal void SetModifiers(MethodBuilder mb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); + else + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); + + mb.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetModifiers(FieldBuilder fb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); + else + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); + + fb.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetModifiers(PropertyBuilder pb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); + else + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); + + pb.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetModifiers(TypeBuilder tb, Modifiers modifiers, bool isInternal) + { + CustomAttributeBuilder customAttributeBuilder; + if (isInternal) + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers, context.Types.Boolean }), new object[] { modifiers, isInternal }); + else + customAttributeBuilder = new CustomAttributeBuilder(TypeOfModifiersAttribute.GetConstructor(new Type[] { TypeOfModifiers }), new object[] { modifiers }); + + tb.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetNameSig(MethodBuilder mb, string name, string sig) + { + var customAttributeBuilder = new CustomAttributeBuilder(TypeOfNameSigAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String }), new object[] { UnicodeUtil.EscapeInvalidSurrogates(name), UnicodeUtil.EscapeInvalidSurrogates(sig) }); + mb.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetInnerClass(TypeBuilder typeBuilder, string innerClass, Modifiers modifiers) + { + var argTypes = new Type[] { context.Types.String, TypeOfModifiers }; + var args = new object[] { UnicodeUtil.EscapeInvalidSurrogates(innerClass), modifiers }; + var ci = TypeOfInnerClassAttribute.GetConstructor(argTypes); + var customAttributeBuilder = new CustomAttributeBuilder(ci, args); + typeBuilder.SetCustomAttribute(customAttributeBuilder); + } + + internal void SetSourceFile(TypeBuilder typeBuilder, string filename) + { + sourceFileAttribute ??= TypeOfSourceFileAttribute.GetConstructor(new Type[] { context.Types.String }); + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); + } + + internal void SetSourceFile(ModuleBuilder moduleBuilder, string filename) + { + sourceFileAttribute ??= TypeOfSourceFileAttribute.GetConstructor(new Type[] { context.Types.String }); + moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename })); + } + + internal void SetLineNumberTable(MethodBuilder mb, IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter writer) + { + object arg; + ConstructorInfo con; + if (writer.Count == 1) + { + lineNumberTableAttribute2 ??= TypeOfLineNumberTableAttribute.GetConstructor(new Type[] { context.Types.UInt16 }); + con = lineNumberTableAttribute2; + arg = (ushort)writer.LineNo; + } + else + { + lineNumberTableAttribute1 ??= TypeOfLineNumberTableAttribute.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(byte).FullName).MakeArrayType().AsReflection() }); + con = lineNumberTableAttribute1; + arg = writer.ToArray(); + } + mb.SetCustomAttribute(new CustomAttributeBuilder(con, new object[] { arg })); + } + + internal void SetEnclosingMethodAttribute(TypeBuilder tb, string className, string methodName, string methodSig) + { + if (enclosingMethodAttribute == null) + { + enclosingMethodAttribute = TypeOfEnclosingMethodAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String, context.Types.String }); + } + tb.SetCustomAttribute(new CustomAttributeBuilder(enclosingMethodAttribute, + new object[] { UnicodeUtil.EscapeInvalidSurrogates(className), UnicodeUtil.EscapeInvalidSurrogates(methodName), UnicodeUtil.EscapeInvalidSurrogates(methodSig) })); + } + + internal void SetSignatureAttribute(TypeBuilder tb, string signature) + { + signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); + tb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal void SetSignatureAttribute(FieldBuilder fb, string signature) + { + signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); + fb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal void SetSignatureAttribute(MethodBuilder mb, string signature) + { + signatureAttribute ??= TypeOfSignatureAttribute.GetConstructor(new Type[] { context.Types.String }); + mb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { UnicodeUtil.EscapeInvalidSurrogates(signature) })); + } + + internal void SetMethodParametersAttribute(MethodBuilder mb, Modifiers[] modifiers) + { + methodParametersAttribute ??= TypeOfMethodParametersAttribute.GetConstructor(new[] { TypeOfModifiers.MakeArrayType() }); + mb.SetCustomAttribute(new CustomAttributeBuilder(methodParametersAttribute, new[] { modifiers })); + } + + internal void SetRuntimeVisibleTypeAnnotationsAttribute(TypeBuilder tb, ref readonly TypeAnnotationTable table) + { + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); + + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + tb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); + } + + internal void SetRuntimeVisibleTypeAnnotationsAttribute(FieldBuilder fb, ref readonly TypeAnnotationTable table) + { + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); + + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + fb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); + } + + internal void SetRuntimeVisibleTypeAnnotationsAttribute(MethodBuilder mb, ref readonly TypeAnnotationTable table) + { + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); + + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + mb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); + } + + internal void SetConstantPoolAttribute(TypeBuilder tb, object[] constantPool) + { + constantPoolAttribute ??= TypeOfConstantPoolAttribute.GetConstructor([context.Types.Object.MakeArrayType()]); + tb.SetCustomAttribute(new CustomAttributeBuilder(constantPoolAttribute, [constantPool])); + } + + internal void SetParamArrayAttribute(ParameterBuilder pb) + { + paramArrayAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ParamArrayAttribute).FullName).GetConstructor([]).AsReflection(), []); + pb.SetCustomAttribute(paramArrayAttribute); + } #endif // IMPORTER @@ -937,13 +937,13 @@ internal NameSigAttribute GetNameSig(MemberInfo member) var attr = member.GetCustomAttributes(typeof(NameSigAttribute), false); return attr.Length == 1 ? (NameSigAttribute)attr[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfNameSigAttribute, false)) - { - var args = cad.ConstructorArguments; - return new NameSigAttribute((string)args[0].Value, (string)args[1].Value); - } + foreach (var cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfNameSigAttribute, false)) + { + var args = cad.ConstructorArguments; + return new NameSigAttribute((string)args[0].Value, (string)args[1].Value); + } - return null; + return null; #endif } @@ -963,13 +963,13 @@ internal ImplementsAttribute GetImplements(Type type) var attribs = type.GetCustomAttributes(typeof(ImplementsAttribute), false); return attribs.Length == 1 ? (ImplementsAttribute)attribs[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfImplementsAttribute, false)) - { - var args = cad.ConstructorArguments; - return new ImplementsAttribute(DecodeArray(args[0])); - } + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfImplementsAttribute, false)) + { + var args = cad.ConstructorArguments; + return new ImplementsAttribute(DecodeArray(args[0])); + } - return null; + return null; #endif } @@ -979,24 +979,24 @@ internal ThrowsAttribute GetThrows(MethodBase mb) var attribs = mb.GetCustomAttributes(typeof(ThrowsAttribute), false); return attribs.Length == 1 ? (ThrowsAttribute)attribs[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(mb, TypeOfThrowsAttribute, false)) - { - var args = cad.ConstructorArguments; - if (args[0].ArgumentType == context.Types.String.MakeArrayType()) - { - return new ThrowsAttribute(DecodeArray(args[0])); - } - else if (args[0].ArgumentType == context.Types.Type.MakeArrayType()) - { - return new ThrowsAttribute(DecodeArray(args[0])); - } - else - { - return new ThrowsAttribute((Type)args[0].Value); - } - } - - return null; + foreach (var cad in CustomAttributeData.__GetCustomAttributes(mb, TypeOfThrowsAttribute, false)) + { + var args = cad.ConstructorArguments; + if (args[0].ArgumentType == context.Types.String.MakeArrayType()) + { + return new ThrowsAttribute(DecodeArray(args[0])); + } + else if (args[0].ArgumentType == context.Types.Type.MakeArrayType()) + { + return new ThrowsAttribute(DecodeArray(args[0])); + } + else + { + return new ThrowsAttribute((Type)args[0].Value); + } + } + + return null; #endif } @@ -1010,14 +1010,14 @@ internal string[] GetNonNestedInnerClasses(Type t) return classes; #else - var list = new List(); - foreach (var cad in CustomAttributeData.__GetCustomAttributes(t, TypeOfNonNestedInnerClassAttribute, false)) - { - var args = cad.ConstructorArguments; - list.Add(UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value)); - } - - return list.ToArray(); + var list = new List(); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(t, TypeOfNonNestedInnerClassAttribute, false)) + { + var args = cad.ConstructorArguments; + list.Add(UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value)); + } + + return list.ToArray(); #endif } @@ -1027,12 +1027,12 @@ internal string GetNonNestedOuterClasses(Type t) var attribs = t.GetCustomAttributes(typeof(NonNestedOuterClassAttribute), false); return attribs.Length == 1 ? ((NonNestedOuterClassAttribute)attribs[0]).OuterClassName : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(t, TypeOfNonNestedOuterClassAttribute, false)) - { - var args = cad.ConstructorArguments; - return UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value); - } - return null; + foreach (var cad in CustomAttributeData.__GetCustomAttributes(t, TypeOfNonNestedOuterClassAttribute, false)) + { + var args = cad.ConstructorArguments; + return UnicodeUtil.UnescapeInvalidSurrogates((string)args[0].Value); + } + return null; #endif } @@ -1042,13 +1042,13 @@ internal IKVM.Attributes.SignatureAttribute GetSignature(MemberInfo member) var attribs = member.GetCustomAttributes(typeof(IKVM.Attributes.SignatureAttribute), false); return attribs.Length == 1 ? (IKVM.Attributes.SignatureAttribute)attribs[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfSignatureAttribute, false)) - { - var args = cad.ConstructorArguments; - return new IKVM.Attributes.SignatureAttribute((string)args[0].Value); - } + foreach (var cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfSignatureAttribute, false)) + { + var args = cad.ConstructorArguments; + return new IKVM.Attributes.SignatureAttribute((string)args[0].Value); + } - return null; + return null; #endif } @@ -1058,12 +1058,12 @@ internal IKVM.Attributes.MethodParametersAttribute GetMethodParameters(MethodBas var attribs = method.GetCustomAttributes(typeof(IKVM.Attributes.MethodParametersAttribute), false); return attribs.Length == 1 ? (IKVM.Attributes.MethodParametersAttribute)attribs[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(method, TypeOfMethodParametersAttribute, false)) - { - var args = cad.ConstructorArguments; - return new IKVM.Attributes.MethodParametersAttribute(DecodeArray(args[0])); - } - return null; + foreach (var cad in CustomAttributeData.__GetCustomAttributes(method, TypeOfMethodParametersAttribute, false)) + { + var args = cad.ConstructorArguments; + return new IKVM.Attributes.MethodParametersAttribute(DecodeArray(args[0])); + } + return null; #endif } @@ -1073,10 +1073,10 @@ internal object[] GetConstantPool(Type type) var attribs = type.GetCustomAttributes(typeof(ConstantPoolAttribute), false); return attribs.Length == 1 ? ((ConstantPoolAttribute)attribs[0]).constantPool : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfConstantPoolAttribute, false)) - return ConstantPoolAttribute.Decompress(DecodeArray(cad.ConstructorArguments[0])); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfConstantPoolAttribute, false)) + return ConstantPoolAttribute.Decompress(DecodeArray(cad.ConstructorArguments[0])); - return null; + return null; #endif } @@ -1086,12 +1086,12 @@ internal byte[] GetRuntimeVisibleTypeAnnotations(MemberInfo member) object[] attribs = member.GetCustomAttributes(typeof(IKVM.Attributes.RuntimeVisibleTypeAnnotationsAttribute), false); return attribs.Length == 1 ? ((IKVM.Attributes.RuntimeVisibleTypeAnnotationsAttribute)attribs[0]).data : null; #else - foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfRuntimeVisibleTypeAnnotationsAttribute, false)) - { - return DecodeArray(cad.ConstructorArguments[0]); - } + foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfRuntimeVisibleTypeAnnotationsAttribute, false)) + { + return DecodeArray(cad.ConstructorArguments[0]); + } - return null; + return null; #endif } @@ -1101,12 +1101,12 @@ internal InnerClassAttribute GetInnerClass(Type type) object[] attribs = type.GetCustomAttributes(typeof(InnerClassAttribute), false); return attribs.Length == 1 ? (InnerClassAttribute)attribs[0] : null; #else - foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfInnerClassAttribute, false)) - { - IList args = cad.ConstructorArguments; - return new InnerClassAttribute((string)args[0].Value, (Modifiers)args[1].Value); - } - return null; + foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfInnerClassAttribute, false)) + { + IList args = cad.ConstructorArguments; + return new InnerClassAttribute((string)args[0].Value, (Modifiers)args[1].Value); + } + return null; #endif } @@ -1118,14 +1118,14 @@ internal RemappedInterfaceMethodAttribute[] GetRemappedInterfaceMethods(Type typ Array.Copy(attr, attr1, attr.Length); return attr1; #else - var attrs = new List(); - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfRemappedInterfaceMethodAttribute, false)) - { - var args = cad.ConstructorArguments; - attrs.Add(new RemappedInterfaceMethodAttribute((string)args[0].Value, (string)args[1].Value, DecodeArray(args[2]))); - } - - return attrs.ToArray(); + var attrs = new List(); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfRemappedInterfaceMethodAttribute, false)) + { + var args = cad.ConstructorArguments; + attrs.Add(new RemappedInterfaceMethodAttribute((string)args[0].Value, (string)args[1].Value, DecodeArray(args[2]))); + } + + return attrs.ToArray(); #endif } @@ -1135,13 +1135,13 @@ internal RemappedTypeAttribute GetRemappedType(Type type) var attribs = type.GetCustomAttributes(typeof(RemappedTypeAttribute), false); return attribs.Length == 1 ? (RemappedTypeAttribute)attribs[0] : null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfRemappedTypeAttribute, false)) - { - var args = cad.ConstructorArguments; - return new RemappedTypeAttribute((Type)args[0].Value); - } + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfRemappedTypeAttribute, false)) + { + var args = cad.ConstructorArguments; + return new RemappedTypeAttribute((Type)args[0].Value); + } - return null; + return null; #endif } @@ -1153,14 +1153,14 @@ internal RemappedClassAttribute[] GetRemappedClasses(Assembly coreAssembly) Array.Copy(attr, attr1, attr.Length); return attr1; #else - var attrs = new List(); - foreach (var cad in CustomAttributeData.__GetCustomAttributes(coreAssembly, TypeOfRemappedClassAttribute, false)) - { - var args = cad.ConstructorArguments; - attrs.Add(new RemappedClassAttribute((string)args[0].Value, (Type)args[1].Value)); - } - - return attrs.ToArray(); + var attrs = new List(); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(coreAssembly, TypeOfRemappedClassAttribute, false)) + { + var args = cad.ConstructorArguments; + attrs.Add(new RemappedClassAttribute((string)args[0].Value, (Type)args[1].Value)); + } + + return attrs.ToArray(); #endif } @@ -1173,10 +1173,10 @@ internal string GetAnnotationAttributeType(Type type) return null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfAnnotationAttributeAttribute, false)) - return UnicodeUtil.UnescapeInvalidSurrogates((string)cad.ConstructorArguments[0].Value); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfAnnotationAttributeAttribute, false)) + return UnicodeUtil.UnescapeInvalidSurrogates((string)cad.ConstructorArguments[0].Value); - return null; + return null; #endif } @@ -1185,7 +1185,7 @@ internal AssemblyName[] GetInternalsVisibleToAttributes(Assembly assembly) var list = new List(); foreach (var cad in CustomAttributeData.GetCustomAttributes(assembly)) { - if (cad.Constructor.DeclaringType == context.Resolver.ResolveCoreType(typeof(InternalsVisibleToAttribute).FullName)) + if (cad.Constructor.DeclaringType == context.Resolver.ResolveCoreType(typeof(InternalsVisibleToAttribute).FullName).AsReflection()) { try { @@ -1211,20 +1211,20 @@ internal object[] GetJavaModuleAttributes(Module mod) #if !IMPORTER && !EXPORTER return mod.GetCustomAttributes(TypeOfJavaModuleAttribute, false); #else - List attrs = new List(); - foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(mod, TypeOfJavaModuleAttribute, false)) - { - IList args = cad.ConstructorArguments; - if (args.Count == 0) - { - attrs.Add(new JavaModuleAttribute()); - } - else - { - attrs.Add(new JavaModuleAttribute(DecodeArray(args[0]))); - } - } - return attrs.ToArray(); + List attrs = new List(); + foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(mod, TypeOfJavaModuleAttribute, false)) + { + IList args = cad.ConstructorArguments; + if (args.Count == 0) + { + attrs.Add(new JavaModuleAttribute()); + } + else + { + attrs.Add(new JavaModuleAttribute(DecodeArray(args[0]))); + } + } + return attrs.ToArray(); #endif } @@ -1247,50 +1247,50 @@ internal IKVM.Attributes.EnclosingMethodAttribute GetEnclosingMethodAttribute(Ty return null; #else - foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfEnclosingMethodAttribute, false)) - return new IKVM.Attributes.EnclosingMethodAttribute((string)cad.ConstructorArguments[0].Value, (string)cad.ConstructorArguments[1].Value, (string)cad.ConstructorArguments[2].Value).SetClassName(context, type); + foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfEnclosingMethodAttribute, false)) + return new IKVM.Attributes.EnclosingMethodAttribute((string)cad.ConstructorArguments[0].Value, (string)cad.ConstructorArguments[1].Value, (string)cad.ConstructorArguments[2].Value).SetClassName(context, type); - return null; + return null; #endif } #if IMPORTER - internal void SetRemappedClass(AssemblyBuilder assemblyBuilder, string name, Type shadowType) - { - var remappedClassAttribute = TypeOfRemappedClassAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.Type }); - assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedClassAttribute, new object[] { name, shadowType })); - } - - internal void SetRemappedType(TypeBuilder typeBuilder, Type shadowType) - { - var remappedTypeAttribute = TypeOfRemappedTypeAttribute.GetConstructor(new Type[] { context.Types.Type }); - typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedTypeAttribute, new object[] { shadowType })); - } - - internal void SetRemappedInterfaceMethod(TypeBuilder typeBuilder, string name, string mappedTo, string[] throws) - { - var cab = new CustomAttributeBuilder(TypeOfRemappedInterfaceMethodAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String, context.Types.String.MakeArrayType() }), new object[] { name, mappedTo, throws }); - typeBuilder.SetCustomAttribute(cab); - } - - internal void SetExceptionIsUnsafeForMapping(TypeBuilder typeBuilder) - { - var cab = new CustomAttributeBuilder(TypeOfExceptionIsUnsafeForMappingAttribute.GetConstructor(Type.EmptyTypes), Array.Empty()); - typeBuilder.SetCustomAttribute(cab); - } + internal void SetRemappedClass(AssemblyBuilder assemblyBuilder, string name, Type shadowType) + { + var remappedClassAttribute = TypeOfRemappedClassAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.Type }); + assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedClassAttribute, new object[] { name, shadowType })); + } + + internal void SetRemappedType(TypeBuilder typeBuilder, Type shadowType) + { + var remappedTypeAttribute = TypeOfRemappedTypeAttribute.GetConstructor(new Type[] { context.Types.Type }); + typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedTypeAttribute, new object[] { shadowType })); + } + + internal void SetRemappedInterfaceMethod(TypeBuilder typeBuilder, string name, string mappedTo, string[] throws) + { + var cab = new CustomAttributeBuilder(TypeOfRemappedInterfaceMethodAttribute.GetConstructor(new Type[] { context.Types.String, context.Types.String, context.Types.String.MakeArrayType() }), new object[] { name, mappedTo, throws }); + typeBuilder.SetCustomAttribute(cab); + } + + internal void SetExceptionIsUnsafeForMapping(TypeBuilder typeBuilder) + { + var cab = new CustomAttributeBuilder(TypeOfExceptionIsUnsafeForMappingAttribute.GetConstructor(Type.EmptyTypes), Array.Empty()); + typeBuilder.SetCustomAttribute(cab); + } #endif internal void SetRuntimeCompatibilityAttribute(AssemblyBuilder assemblyBuilder) { - var runtimeCompatibilityAttribute = context.Resolver.ResolveCoreType(typeof(RuntimeCompatibilityAttribute).FullName); + var runtimeCompatibilityAttribute = context.Resolver.ResolveCoreType(typeof(RuntimeCompatibilityAttribute).FullName).AsReflection(); assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(runtimeCompatibilityAttribute.GetConstructor(Type.EmptyTypes), Array.Empty(), new PropertyInfo[] { runtimeCompatibilityAttribute.GetProperty("WrapNonExceptionThrows") }, new object[] { true }, Array.Empty(), Array.Empty())); } internal void SetInternalsVisibleToAttribute(AssemblyBuilder assemblyBuilder, string assemblyName) { - var internalsVisibleToAttribute = context.Resolver.ResolveCoreType(typeof(InternalsVisibleToAttribute).FullName); + var internalsVisibleToAttribute = context.Resolver.ResolveCoreType(typeof(InternalsVisibleToAttribute).FullName).AsReflection(); var cab = new CustomAttributeBuilder(internalsVisibleToAttribute.GetConstructor(new Type[] { context.Types.String }), new object[] { assemblyName }); assemblyBuilder.SetCustomAttribute(cab); } diff --git a/src/IKVM.Runtime/BootstrapClassLoader.cs b/src/IKVM.Runtime/BootstrapClassLoader.cs index 43653d49d3..c847939def 100644 --- a/src/IKVM.Runtime/BootstrapClassLoader.cs +++ b/src/IKVM.Runtime/BootstrapClassLoader.cs @@ -44,7 +44,7 @@ sealed class BootstrapClassLoader : RuntimeAssemblyClassLoader /// Initializes a new instance. /// internal BootstrapClassLoader(RuntimeContext context) : - base(context, context.Resolver.ResolveBaseAssembly(), [typeof(object).Assembly.FullName, typeof(Uri).Assembly.FullName]) + base(context, context.Resolver.ResolveBaseAssembly().AsReflection(), [typeof(object).Assembly.FullName, typeof(Uri).Assembly.FullName]) { #if FIRST_PASS == false && IMPORTER == false && EXPORTER == false RegisterNativeLibrary(LibJava.Instance.Handle); diff --git a/src/IKVM.Runtime/ByteCodeFlowControl.cs b/src/IKVM.Runtime/ByteCodeFlowControl.cs index 2a5eace55d..918ccb0066 100644 --- a/src/IKVM.Runtime/ByteCodeFlowControl.cs +++ b/src/IKVM.Runtime/ByteCodeFlowControl.cs @@ -25,14 +25,14 @@ Jeroen Frijters namespace IKVM.Runtime { - enum ByteCodeFlowControl : byte - { - Next, - Branch, - CondBranch, - Return, - Throw, - Switch, - } + enum ByteCodeFlowControl : byte + { + Next, + Branch, + CondBranch, + Return, + Throw, + Switch, + } } diff --git a/src/IKVM.Runtime/ByteCodeHelperMethods.cs b/src/IKVM.Runtime/ByteCodeHelperMethods.cs index dc8827b82f..666a21a672 100644 --- a/src/IKVM.Runtime/ByteCodeHelperMethods.cs +++ b/src/IKVM.Runtime/ByteCodeHelperMethods.cs @@ -24,6 +24,8 @@ Jeroen Frijters using System; using IKVM.CoreLib.Diagnostics; +using IKVM.CoreLib.Symbols.IkvmReflection; +using IKVM.CoreLib.Symbols.Reflection; #if IMPORTER using IKVM.Reflection; @@ -108,7 +110,11 @@ class ByteCodeHelperMethods /// public ByteCodeHelperMethods(RuntimeContext context) { - var typeofByteCodeHelper = context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper"); +#if IMPORTER || EXPORTER + var typeofByteCodeHelper = ((IkvmReflectionTypeSymbol)context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper")).ReflectionObject; +#else + var typeofByteCodeHelper = ((ReflectionTypeSymbol)context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper")).ReflectionObject; +#endif multianewarray = GetHelper(typeofByteCodeHelper, "multianewarray"); multianewarray_ghost = GetHelper(typeofByteCodeHelper, "multianewarray_ghost"); anewarray_ghost = GetHelper(typeofByteCodeHelper, "anewarray_ghost"); diff --git a/src/IKVM.Runtime/CodeEmitter.cs b/src/IKVM.Runtime/CodeEmitter.cs index 289f66fac7..91a05f0c5b 100644 --- a/src/IKVM.Runtime/CodeEmitter.cs +++ b/src/IKVM.Runtime/CodeEmitter.cs @@ -60,15 +60,15 @@ public CodeEmitterFactory(RuntimeContext context) this.context = context ?? throw new ArgumentNullException(nameof(context)); } - public MethodInfo ObjectToStringMethod => objectToString ??= context.Types.Object.GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + public MethodInfo ObjectToStringMethod => objectToString ??= context.Types.Object.GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, [], null); public MethodInfo VerboseCastFailureMethod => verboseCastFailure ??= JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : context.ByteCodeHelperMethods.VerboseCastFailure; - public MethodInfo MonitorEnterMethod => monitorEnter ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).GetMethod("Enter", BindingFlags.Public | BindingFlags.Static, null, new Type[] { context.Types.Object }, null); + public MethodInfo MonitorEnterMethod => monitorEnter ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).AsReflection().GetMethod("Enter", BindingFlags.Public | BindingFlags.Static, null, [context.Types.Object], null); - public MethodInfo MonitorExitMethod => monitorExit ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).GetMethod("Exit", BindingFlags.Public | BindingFlags.Static, null, new Type[] { context.Types.Object }, null); + public MethodInfo MonitorExitMethod => monitorExit ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).AsReflection().GetMethod("Exit", BindingFlags.Public | BindingFlags.Static, null, [context.Types.Object], null); - public MethodInfo MemoryBarrierMethod => memoryBarrier ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Thread).FullName).GetMethod("MemoryBarrier", Type.EmptyTypes); + public MethodInfo MemoryBarrierMethod => memoryBarrier ??= context.Resolver.ResolveCoreType(typeof(System.Threading.Thread).FullName).GetMethod("MemoryBarrier", []).AsReflection(); public bool ExperimentalOptimizations = JVM.SafeGetEnvironmentVariable("IKVM_EXPERIMENTAL_OPTIMIZATIONS") != null; diff --git a/src/IKVM.Runtime/EnumHelper.cs b/src/IKVM.Runtime/EnumHelper.cs index 0b29602cb7..1e6917c62d 100644 --- a/src/IKVM.Runtime/EnumHelper.cs +++ b/src/IKVM.Runtime/EnumHelper.cs @@ -86,7 +86,7 @@ internal static object OrBoxedIntegrals(RuntimeContext context, object v1, objec else { long v = ((IConvertible)v1).ToInt64(null) | ((IConvertible)v2).ToInt64(null); - switch (Type.GetTypeCode(context.Resolver.ResolveCoreType(v1.GetType().FullName))) + switch (Type.GetTypeCode(context.Resolver.ResolveCoreType(v1.GetType().FullName).AsReflection())) { case TypeCode.SByte: return (sbyte)v; diff --git a/src/IKVM.Runtime/JVM.Internal.cs b/src/IKVM.Runtime/JVM.Internal.cs index 4e6889482d..4d8c83ea92 100644 --- a/src/IKVM.Runtime/JVM.Internal.cs +++ b/src/IKVM.Runtime/JVM.Internal.cs @@ -44,7 +44,7 @@ internal static class Internal static ThreadGroupAccessor threadGroupAccessor; static SystemAccessor systemAccessor; - internal static AccessorCache BaseAccessors => AccessorCache.Get(ref baseAccessors, context.Resolver.ResolveBaseAssembly()); + internal static AccessorCache BaseAccessors => AccessorCache.Get(ref baseAccessors, context.Resolver.ResolveBaseAssembly().AsReflection()); internal static ThreadGroupAccessor ThreadGroupAccessor => BaseAccessors.Get(ref threadGroupAccessor); diff --git a/src/IKVM.Runtime/JVM.Properties.cs b/src/IKVM.Runtime/JVM.Properties.cs index 14bd2a7e9f..3bdd135637 100644 --- a/src/IKVM.Runtime/JVM.Properties.cs +++ b/src/IKVM.Runtime/JVM.Properties.cs @@ -253,35 +253,35 @@ static Dictionary GetInitProperties() static void InitSystemProperties(Dictionary p) { #if FIRST_PASS || IMPORTER || EXPORTER - throw new NotImplementedException(); + throw new NotImplementedException(); #else - p["openjdk.version"] = Constants.openjdk_version; - p["java.vm.name"] = Constants.java_vm_name; - p["java.vm.version"] = Constants.java_vm_version; - p["java.vm.vendor"] = Constants.java_vm_vendor; - p["java.vm.specification.name"] = "Java Virtual Machine Specification"; - p["java.vm.specification.version"] = Constants.java_vm_specification_version; - p["java.vm.specification.vendor"] = Constants.java_vm_specification_vendor; - p["java.vm.info"] = "compiled mode"; - p["java.runtime.name"] = Constants.java_runtime_name; - p["java.runtime.version"] = Constants.java_runtime_version; - - // various directory paths - p["ikvm.home"] = HomePath; - p["java.home"] = HomePath; - p["java.library.path"] = GetLibraryPath(); - p["java.ext.dirs"] = Path.Combine(HomePath, "lib", "ext"); - p["java.endorsed.dirs"] = Path.Combine(HomePath, "lib", "endorsed"); - p["sun.boot.library.path"] = GetBootLibraryPath(); - p["sun.boot.class.path"] = VfsTable.GetAssemblyClassesPath(Vfs.Context, Context.Resolver.ResolveBaseAssembly(), HomePath); - p["sun.cds.enableSharedLookupCache"] = "false"; - - // unlimited direct memory - p["sun.nio.MaxDirectMemorySize"] = "-1"; - - // default to FORK on OSX, instead of posix_spawn with jspawnhelper - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - p["jdk.lang.Process.launchMechanism"] = "FORK"; + p["openjdk.version"] = Constants.openjdk_version; + p["java.vm.name"] = Constants.java_vm_name; + p["java.vm.version"] = Constants.java_vm_version; + p["java.vm.vendor"] = Constants.java_vm_vendor; + p["java.vm.specification.name"] = "Java Virtual Machine Specification"; + p["java.vm.specification.version"] = Constants.java_vm_specification_version; + p["java.vm.specification.vendor"] = Constants.java_vm_specification_vendor; + p["java.vm.info"] = "compiled mode"; + p["java.runtime.name"] = Constants.java_runtime_name; + p["java.runtime.version"] = Constants.java_runtime_version; + + // various directory paths + p["ikvm.home"] = HomePath; + p["java.home"] = HomePath; + p["java.library.path"] = GetLibraryPath(); + p["java.ext.dirs"] = Path.Combine(HomePath, "lib", "ext"); + p["java.endorsed.dirs"] = Path.Combine(HomePath, "lib", "endorsed"); + p["sun.boot.library.path"] = GetBootLibraryPath(); + p["sun.boot.class.path"] = VfsTable.GetAssemblyClassesPath(Vfs.Context, Context.Resolver.ResolveBaseAssembly().AsReflection(), HomePath); + p["sun.cds.enableSharedLookupCache"] = "false"; + + // unlimited direct memory + p["sun.nio.MaxDirectMemorySize"] = "-1"; + + // default to FORK on OSX, instead of posix_spawn with jspawnhelper + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + p["jdk.lang.Process.launchMechanism"] = "FORK"; #if NETFRAMEWORK // read properties from app.config diff --git a/src/IKVM.Runtime/JVM.Resolver.cs b/src/IKVM.Runtime/JVM.Resolver.cs index f8134e9748..b366e9e5a4 100644 --- a/src/IKVM.Runtime/JVM.Resolver.cs +++ b/src/IKVM.Runtime/JVM.Resolver.cs @@ -6,6 +6,9 @@ using System.Reflection; using System.Runtime.CompilerServices; +using IKVM.CoreLib.Symbols; +using IKVM.CoreLib.Symbols.Reflection; + namespace IKVM.Runtime { @@ -17,7 +20,7 @@ static partial class JVM /// /// Provides support for resolving managed types from the current JVM environment. /// - internal class Resolver : IManagedTypeResolver + internal class Resolver : ISymbolResolver { /// @@ -36,42 +39,52 @@ static IEnumerable GetCoreAssemblies() yield return typeof(Environment).Assembly; } - readonly Assembly[] coreAssemblies = GetCoreAssemblies().Distinct().ToArray(); - readonly ConcurrentDictionary typeCache = new(); + readonly static Assembly[] coreAssemblies = GetCoreAssemblies().Distinct().ToArray(); + + readonly ReflectionSymbolContext _context = new(); + readonly IAssemblySymbol[] _coreAssemblies; + readonly ConcurrentDictionary _typeCache = new(); + /// + /// Initializes a new instance. + /// + public Resolver() + { + _coreAssemblies = coreAssemblies.Select(_context.GetOrCreateAssemblySymbol).ToArray(); + } /// - public Assembly ResolveAssembly(string assemblyName) + public IAssemblySymbol ResolveAssembly(string assemblyName) { - return Assembly.Load(assemblyName); + return Assembly.Load(assemblyName) is { } a ? _context.GetOrCreateAssemblySymbol(a) : null; } /// - public Assembly ResolveBaseAssembly() + public IAssemblySymbol ResolveBaseAssembly() { - return typeof(java.lang.Object).Assembly; + return _context.GetOrCreateAssemblySymbol(typeof(java.lang.Object).Assembly); } /// - public Type ResolveCoreType(string typeName) + public ITypeSymbol ResolveCoreType(string typeName) { - return typeCache.GetOrAdd(typeName, ResolveCoreTypeImpl); + return _typeCache.GetOrAdd(typeName, ResolveCoreTypeImpl); } - Type ResolveCoreTypeImpl(string typeName) + ITypeSymbol ResolveCoreTypeImpl(string typeName) { // loop over core assemblies searching for type - foreach (var assembly in coreAssemblies) - if (assembly.GetType(typeName) is Type t) + foreach (var assembly in _coreAssemblies) + if (assembly.GetType(typeName) is ITypeSymbol t) return t; return null; } /// - public Type ResolveRuntimeType(string typeName) + public ITypeSymbol ResolveRuntimeType(string typeName) { - return typeof(Resolver).Assembly.GetType(typeName); + return typeof(Resolver).Assembly.GetType(typeName) is { } t ? _context.GetOrCreateTypeSymbol(t) : null; } } diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs b/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs index 30e0cefa0c..57fbfbd9f0 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/Package.cs @@ -32,7 +32,7 @@ Jeroen Frijters namespace IKVM.Java.Externs.java.lang { - static class Package + static class Package { static Dictionary systemPackages; @@ -48,7 +48,7 @@ static void LazyInitSystemPackages() if (systemPackages == null) { var dict = new Dictionary(); - var path = Path.Combine(VfsTable.GetAssemblyResourcesPath(JVM.Vfs.Context, JVM.Context.Resolver.ResolveBaseAssembly(), JVM.Properties.HomePath), "resources.jar"); + var path = Path.Combine(VfsTable.GetAssemblyResourcesPath(JVM.Vfs.Context, JVM.Context.Resolver.ResolveBaseAssembly().AsReflection(), JVM.Properties.HomePath), "resources.jar"); foreach (var pkgs in JVM.Context.ClassLoaderFactory.GetBootstrapClassLoader().GetPackageInfo()) foreach (var pkg in pkgs.Value) dict[pkg.Replace('.', '/') + "/"] = path; diff --git a/src/IKVM.Runtime/MethodAnalyzer.cs b/src/IKVM.Runtime/MethodAnalyzer.cs index 9af36c6c99..b6a1652c05 100644 --- a/src/IKVM.Runtime/MethodAnalyzer.cs +++ b/src/IKVM.Runtime/MethodAnalyzer.cs @@ -2486,7 +2486,6 @@ private void SetHardError(RuntimeClassLoader classLoader, ref ClassFile.Method.I { string text = string.Format(message, args); #if IMPORTER - Diagnostic msg; switch (hardError) { case HardError.NoClassDefFoundError: diff --git a/src/IKVM.Runtime/MethodHandleUtil.root.cs b/src/IKVM.Runtime/MethodHandleUtil.root.cs index 63a0e8bb8b..40fa2d848d 100644 --- a/src/IKVM.Runtime/MethodHandleUtil.root.cs +++ b/src/IKVM.Runtime/MethodHandleUtil.root.cs @@ -53,29 +53,29 @@ public MethodHandleUtil(RuntimeContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); - typeofMHA = context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHA`8"); + typeofMHA = context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHA`8").AsReflection(); typeofMHV = new Type[] { - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`1"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`2"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`3"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`4"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`5"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`6"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`7"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`8"), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`1").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`2").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`3").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`4").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`5").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`6").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`7").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MHV`8").AsReflection(), }; typeofMH = new Type[] { null, - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`1"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`2"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`3"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`4"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`5"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`6"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`7"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`8"), - context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`9"), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`1").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`2").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`3").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`4").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`5").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`6").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`7").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`8").AsReflection(), + context.Resolver.ResolveRuntimeType("IKVM.Runtime.MH`9").AsReflection(), }; } diff --git a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs index ddf7023129..ef11c41dcd 100644 --- a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs +++ b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs @@ -574,7 +574,7 @@ Assembly LoadAssemblyOrClearName(ref string name, bool exported) try { - return Context.Resolver.ResolveAssembly(name); + return Context.Resolver.ResolveAssembly(name).AsReflection(); } catch { diff --git a/src/IKVM.Runtime/RuntimeAssemblyClassLoaderFactory.cs b/src/IKVM.Runtime/RuntimeAssemblyClassLoaderFactory.cs index 4f219c5f30..6b847c2861 100644 --- a/src/IKVM.Runtime/RuntimeAssemblyClassLoaderFactory.cs +++ b/src/IKVM.Runtime/RuntimeAssemblyClassLoaderFactory.cs @@ -108,9 +108,9 @@ RuntimeAssemblyClassLoader Create(Assembly assembly) return FromAssembly(mainAssembly); } - var baseAssembly = context.Resolver.ResolveBaseAssembly(); + var baseAssembly = context.Resolver.ResolveBaseAssembly().AsReflection(); #if IMPORTER - if (baseAssembly != null && assembly.IsDefined(context.Resolver.ResolveRuntimeType("IKVM.Attributes.RemappedClassAttribute"), false)) + if (baseAssembly != null && assembly.IsDefined(context.Resolver.ResolveRuntimeType("IKVM.Attributes.RemappedClassAttribute").AsReflection(), false)) context.ClassLoaderFactory.LoadRemappedTypes(); #endif diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs index 3631c9d186..7c7c5ebce3 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs @@ -392,7 +392,7 @@ internal Type FinishImpl() #if IMPORTER // see if there exists a "managed JNI" class for this type - var nativeCodeType = context.Resolver.ResolveRuntimeType("IKVM.Java.Externs." + classFile.Name.Replace("$", "+")); + var nativeCodeType = context.Resolver.ResolveRuntimeType("IKVM.Java.Externs." + classFile.Name.Replace("$", "+")).AsReflection(); if (nativeCodeType != null) { if (!m.IsStatic) @@ -1287,7 +1287,7 @@ void GenerateAccessStub(RuntimeJavaField fw, bool type1) // we attach the AccessStub custom modifier because the C# compiler prefers fields without custom modifiers // so if this class defines a field with the same name, that will be preferred over this one by the C# compiler - var fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, null, new Type[] { context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName) }, attribs); + var fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, null, new Type[] { context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName).AsReflection() }, attribs); context.AttributeHelper.HideFromReflection(fb); fb.SetConstant(cjf.GetConstantValue()); } @@ -1307,7 +1307,7 @@ void GenerateAccessStub(RuntimeJavaField fw, bool type1) // we append the IKVM.Attributes.AccessStub type to the modopt array for use in the property accessor method signature // to make sure they never conflict with any user defined methhods - var modopt2 = ArrayUtil.Concat(modopt, context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName)); + var modopt2 = ArrayUtil.Concat(modopt, context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName).AsReflection()); var getter = typeBuilder.DefineMethod("get_" + fw.Name, attribs, CallingConventions.Standard, propType, null, modopt2, Type.EmptyTypes, null, null); context.AttributeHelper.HideFromJava(getter); pb.SetGetMethod(getter); @@ -1404,7 +1404,7 @@ void GenerateAccessStub(int id, RuntimeJavaMethod mw, bool virt, bool type1) } var returnType = mw.ReturnType.TypeAsPublicSignatureType; - var modoptReturnType = ArrayUtil.Concat(wrapper.GetModOpt(mw.ReturnType, true), context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName)); + var modoptReturnType = ArrayUtil.Concat(wrapper.GetModOpt(mw.ReturnType, true), context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName).AsReflection()); string name; if (mw.Name == StringConstants.INIT) @@ -1607,7 +1607,7 @@ internal static class JniProxyBuilder static JniProxyBuilder() { mod = DynamicClassLoader.CreateJniProxyModuleBuilder(); - var cab = new CustomAttributeBuilder(JVM.Context.Resolver.ResolveRuntimeType(typeof(JavaModuleAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); + var cab = new CustomAttributeBuilder(JVM.Context.Resolver.ResolveRuntimeType(typeof(JavaModuleAttribute).FullName).GetConstructor([]).AsReflection(), new object[0]); mod.SetCustomAttribute(cab); } @@ -1663,7 +1663,7 @@ public JniBuilder(RuntimeContext context) this.context = context ?? throw new ArgumentNullException(nameof(context)); } - Type LocalRefStructType => context.Resolver.ResolveRuntimeType("IKVM.Runtime.JNI.JNIFrame"); + Type LocalRefStructType => context.Resolver.ResolveRuntimeType("IKVM.Runtime.JNI.JNIFrame").AsReflection(); MethodInfo JniFuncPtrMethod => LocalRefStructType.GetMethod("GetFuncPtr"); @@ -1675,11 +1675,11 @@ public JniBuilder(RuntimeContext context) MethodInfo UnwrapLocalRefMethod => LocalRefStructType.GetMethod("UnwrapLocalRef"); - MethodInfo WriteLineMethod => context.Resolver.ResolveCoreType(typeof(Console).FullName).GetMethod("WriteLine", new Type[] { context.Types.Object }); + MethodInfo WriteLineMethod => context.Resolver.ResolveCoreType(typeof(Console).FullName).AsReflection().GetMethod("WriteLine", [context.Types.Object]); - MethodInfo MonitorEnterMethod => context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).GetMethod("Enter", new Type[] { context.Types.Object }); + MethodInfo MonitorEnterMethod => context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).AsReflection().GetMethod("Enter", [context.Types.Object]); - MethodInfo MonitorExitMethod => context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).GetMethod("Exit", new Type[] { context.Types.Object }); + MethodInfo MonitorExitMethod => context.Resolver.ResolveCoreType(typeof(System.Threading.Monitor).FullName).AsReflection().GetMethod("Exit", [context.Types.Object]); internal void Generate(RuntimeByteCodeJavaType.FinishContext context, CodeEmitter ilGenerator, RuntimeByteCodeJavaType wrapper, RuntimeJavaMethod mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, RuntimeJavaType[] args, bool thruProxy) { @@ -1910,7 +1910,7 @@ void EmitCallerIDStub(RuntimeJavaMethod mw, string[] parameterNames) } ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Ldc_I4_0); - ilgen.Emit(OpCodes.Newobj, context.Resolver.ResolveCoreType(typeof(StackFrame).FullName).GetConstructor(new Type[] { context.Types.Int32, context.Types.Boolean })); + ilgen.Emit(OpCodes.Newobj, context.Resolver.ResolveCoreType(typeof(StackFrame).FullName).AsReflection().GetConstructor(new Type[] { context.Types.Int32, context.Types.Boolean })); var callerID = context.JavaBase.TypeOfIkvmInternalCallerID.GetMethodWrapper("create", "(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;", false); callerID.Link(); callerID.EmitCall(ilgen); @@ -1943,16 +1943,16 @@ void ImplementInterfaces(RuntimeJavaType[] interfaces, List int // look for "magic" interfaces that imply a .NET interface if (iface.ClassLoader == context.JavaBase.TypeOfJavaLangObject.ClassLoader) { - if (iface.Name == "java.lang.Iterable" && !wrapper.ImplementsInterface(context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName)))) + if (iface.Name == "java.lang.Iterable" && !wrapper.ImplementsInterface(context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName).AsReflection()))) { var enumeratorType = context.ClassLoaderFactory.GetBootstrapClassLoader().TryLoadClassByName("ikvm.lang.IterableEnumerator"); if (enumeratorType != null) { - typeBuilder.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName)); + typeBuilder.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName).AsReflection()); // FXBUG we're using the same method name as the C# compiler here because both the .NET and Mono implementations of Xml serialization depend on this method name - var mb = typeBuilder.DefineMethod("System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerator).FullName), Type.EmptyTypes); + var mb = typeBuilder.DefineMethod("System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerator).FullName).AsReflection(), Type.EmptyTypes); context.AttributeHelper.HideFromJava(mb); - typeBuilder.DefineMethodOverride(mb, context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName).GetMethod("GetEnumerator")); + typeBuilder.DefineMethodOverride(mb, context.Resolver.ResolveCoreType(typeof(System.Collections.IEnumerable).FullName).GetMethod("GetEnumerator").AsReflection()); var ilgen = context.CodeEmitterFactory.Create(mb); ilgen.Emit(OpCodes.Ldarg_0); var mw = enumeratorType.GetMethodWrapper("", "(Ljava.lang.Iterable;)V", false); @@ -2196,14 +2196,14 @@ internal MethodBuilder DefineThreadLocalType() int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count; var tb = typeBuilder.DefineNestedType(NestedTypeName.ThreadLocal + id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType); var fb = tb.DefineField("field", context.Types.Object, FieldAttributes.Private | FieldAttributes.Static); - fb.SetCustomAttribute(new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ThreadStaticAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0])); + fb.SetCustomAttribute(new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ThreadStaticAttribute).FullName).GetConstructor([]).AsReflection(), new object[0])); var mbGet = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, context.Types.Object, Type.EmptyTypes); var ilgen = mbGet.GetILGenerator(); ilgen.Emit(OpCodes.Ldsfld, fb); ilgen.Emit(OpCodes.Ret); - var mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, new Type[] { context.Types.Object }); + var mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, [context.Types.Object]); ilgen = mbSet.GetILGenerator(); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Stsfld, fb); diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs index 0b0231d7ca..7dfb116548 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs @@ -64,11 +64,11 @@ private sealed partial class JavaTypeImpl : DynamicImpl MethodBuilder finalizeMethod; int recursionCount; #if IMPORTER - RuntimeByteCodeJavaType enclosingClassWrapper; - AnnotationBuilder annotationBuilder; - TypeBuilder enumBuilder; - TypeBuilder privateInterfaceMethods; - ConcurrentDictionary nestedTypeNames; // only keys are used, values are always null + RuntimeByteCodeJavaType enclosingClassWrapper; + AnnotationBuilder annotationBuilder; + TypeBuilder enumBuilder; + TypeBuilder privateInterfaceMethods; + ConcurrentDictionary nestedTypeNames; // only keys are used, values are always null #endif internal JavaTypeImpl(RuntimeJavaType host, ClassFile f, RuntimeByteCodeJavaType wrapper) @@ -92,15 +92,15 @@ internal void CreateStep1() if (m.IsClassInitializer) { #if IMPORTER - if (IsSideEffectFreeStaticInitializerOrNoop(m, out var noop)) - { - if (noop) - flags |= MemberFlags.NoOp; - } - else - { - hasclinit = true; - } + if (IsSideEffectFreeStaticInitializerOrNoop(m, out var noop)) + { + if (noop) + flags |= MemberFlags.NoOp; + } + else + { + hasclinit = true; + } #else hasclinit = true; #endif @@ -110,12 +110,12 @@ internal void CreateStep1() flags |= MemberFlags.InternalAccess; #if IMPORTER - if (m.IsCallerSensitive && SupportsCallerID(m)) - flags |= MemberFlags.CallerID; + if (m.IsCallerSensitive && SupportsCallerID(m)) + flags |= MemberFlags.CallerID; - // set as module initializer - if (m.IsModuleInitializer) - flags |= MemberFlags.ModuleInitializer; + // set as module initializer + if (m.IsModuleInitializer) + flags |= MemberFlags.ModuleInitializer; #endif if (wrapper.IsGhost && m.IsVirtual) @@ -190,78 +190,78 @@ internal void CreateStep1() } } #if IMPORTER - wrapper.AddMapXmlFields(ref fields); + wrapper.AddMapXmlFields(ref fields); #endif wrapper.SetFields(fields); } #if IMPORTER - bool SupportsCallerID(ClassFile.Method method) - { - if ((classFile.Name == "sun.reflect.Reflection" && method.Name == "getCallerClass") || (classFile.Name == "java.lang.SecurityManager" && method.Name == "checkMemberAccess")) - { - // ignore CallerSensitive on methods that don't need CallerID parameter - return false; - } - else if (method.IsStatic) - { - return true; - } - else if ((classFile.IsFinal || classFile.Name == "java.lang.Runtime" || classFile.Name == "java.io.ObjectStreamClass") && wrapper.BaseTypeWrapper.GetMethodWrapper(method.Name, method.Signature, true) == null && !HasInterfaceMethod(wrapper, method.Name, method.Signature)) - { - // We only support CallerID instance methods on final or effectively final types, - // because we don't support interface stubs with CallerID. - // We also don't support a CallerID method overriding a method or implementing an interface. - return true; - } - else if (RequiresDynamicReflectionCallerClass(classFile.Name, method.Name, method.Signature)) - { - // We don't support CallerID for virtual methods that can be overridden or implement an interface, - // so these methods will do a dynamic stack walk if when Reflection.getCallerClass() is used. - return false; - } - else - { - // 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.ClassLoader.Diagnostics.CallerSensitiveOnUnsupportedMethod(classFile.Name, method.Name, method.Signature); - return false; - } - } - - static bool HasInterfaceMethod(RuntimeJavaType tw, string name, string signature) - { - for (; tw != null; tw = tw.BaseTypeWrapper) - { - foreach (var iface in tw.Interfaces) - { - if (iface.GetMethodWrapper(name, signature, false) != null) - { - return true; - } - if (HasInterfaceMethod(iface, name, signature)) - { - return true; - } - } - } - - return false; - } + bool SupportsCallerID(ClassFile.Method method) + { + if ((classFile.Name == "sun.reflect.Reflection" && method.Name == "getCallerClass") || (classFile.Name == "java.lang.SecurityManager" && method.Name == "checkMemberAccess")) + { + // ignore CallerSensitive on methods that don't need CallerID parameter + return false; + } + else if (method.IsStatic) + { + return true; + } + else if ((classFile.IsFinal || classFile.Name == "java.lang.Runtime" || classFile.Name == "java.io.ObjectStreamClass") && wrapper.BaseTypeWrapper.GetMethodWrapper(method.Name, method.Signature, true) == null && !HasInterfaceMethod(wrapper, method.Name, method.Signature)) + { + // We only support CallerID instance methods on final or effectively final types, + // because we don't support interface stubs with CallerID. + // We also don't support a CallerID method overriding a method or implementing an interface. + return true; + } + else if (RequiresDynamicReflectionCallerClass(classFile.Name, method.Name, method.Signature)) + { + // We don't support CallerID for virtual methods that can be overridden or implement an interface, + // so these methods will do a dynamic stack walk if when Reflection.getCallerClass() is used. + return false; + } + else + { + // 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.ClassLoader.Diagnostics.CallerSensitiveOnUnsupportedMethod(classFile.Name, method.Name, method.Signature); + return false; + } + } + + static bool HasInterfaceMethod(RuntimeJavaType tw, string name, string signature) + { + for (; tw != null; tw = tw.BaseTypeWrapper) + { + foreach (var iface in tw.Interfaces) + { + if (iface.GetMethodWrapper(name, signature, false) != null) + { + return true; + } + if (HasInterfaceMethod(iface, name, signature)) + { + return true; + } + } + } + + return false; + } #endif internal void CreateStep2() { #if IMPORTER - if (typeBuilder != null) - { - // in the static compiler we need to create the TypeBuilder from outer to inner - // and to avoid having to sort the classes this way, we instead call CreateStep2 - // on demand for outer wrappers and this necessitates us to keep track of - // whether we've already been called - return; - } + if (typeBuilder != null) + { + // in the static compiler we need to create the TypeBuilder from outer to inner + // and to avoid having to sort the classes this way, we instead call CreateStep2 + // on demand for outer wrappers and this necessitates us to keep track of + // whether we've already been called + return; + } #endif // this method is not allowed to throw exceptions (if it does, the runtime will abort) @@ -280,121 +280,121 @@ internal void CreateStep2() typeAttribs |= TypeAttributes.BeforeFieldInit; #if IMPORTER - bool cantNest = false; - bool setModifiers = false; - TypeBuilder enclosing = null; - string enclosingClassName = null; - // we only compile inner classes as nested types in the static compiler, because it has a higher cost - // and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling - // the TypeResolve event very hard) - var outerClass = getOuterClass(); - if (outerClass.outerClass.IsNotNil) - { - enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass); - } - else if (f.EnclosingMethod != null) - { - enclosingClassName = f.EnclosingMethod[0]; - } - - if (enclosingClassName != null) - { - if (!CheckInnerOuterNames(f.Name, enclosingClassName)) - { - wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Incorrect {(outerClass.outerClass.IsNotNil ? "InnerClasses" : "EnclosingMethod")} attribute on {f.Name}"); - } - else - { - try - { - enclosingClassWrapper = wrapper.classLoader.TryLoadClassByName(enclosingClassName) as RuntimeByteCodeJavaType; - } - catch (RetargetableJavaException x) - { - wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Unable to load outer class {enclosingClassName} for inner class {f.Name} ({x.GetType().Name}: {x.Message})"); - } - - if (enclosingClassWrapper != null) - { - // make sure the relationship is reciprocal (otherwise we run the risk of - // baking the outer type before the inner type) and that the inner and outer - // class live in the same class loader (when doing a multi target compilation, - // it is possible to split the two classes across assemblies) - var oimpl = enclosingClassWrapper.impl as JavaTypeImpl; - if (oimpl != null && enclosingClassWrapper.ClassLoader == wrapper.ClassLoader) - { - var outerClassFile = oimpl.classFile; - var outerInnerClasses = outerClassFile.InnerClasses; - if (outerInnerClasses == null) - { - enclosingClassWrapper = null; - } - else - { - var ok = false; - for (int i = 0; i < outerInnerClasses.Length; i++) - { - if (((outerInnerClasses[i].outerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name) || (outerInnerClasses[i].outerClass.IsNil && outerClass.outerClass.IsNil)) && outerInnerClasses[i].innerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name) - { - ok = true; - break; - } - } - - if (!ok) - { - enclosingClassWrapper = null; - } - } - } - else - { - enclosingClassWrapper = null; - } - - if (enclosingClassWrapper != null) - { - enclosingClassWrapper.CreateStep2(); - enclosing = oimpl.typeBuilder; - if (outerClass.outerClass.IsNil) - { - // we need to record that we're not an inner classes, but an enclosed class - typeAttribs |= TypeAttributes.SpecialName; - } - } - else - { - wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Non-reciprocal inner class {f.Name}"); - } - } - } - } - - if (f.IsPublic) - { - if (enclosing != null) - { - if (enclosingClassWrapper.IsPublic) - { - typeAttribs |= TypeAttributes.NestedPublic; - } - else - { - // We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type, - // because that would mean it wouldn't be visible outside the assembly. - cantNest = true; - typeAttribs |= TypeAttributes.Public; - } - } - else - { - typeAttribs |= TypeAttributes.Public; - } - } - else if (enclosing != null) - { - typeAttribs |= TypeAttributes.NestedAssembly; - } + bool cantNest = false; + bool setModifiers = false; + TypeBuilder enclosing = null; + string enclosingClassName = null; + // we only compile inner classes as nested types in the static compiler, because it has a higher cost + // and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling + // the TypeResolve event very hard) + var outerClass = getOuterClass(); + if (outerClass.outerClass.IsNotNil) + { + enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass); + } + else if (f.EnclosingMethod != null) + { + enclosingClassName = f.EnclosingMethod[0]; + } + + if (enclosingClassName != null) + { + if (!CheckInnerOuterNames(f.Name, enclosingClassName)) + { + wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Incorrect {(outerClass.outerClass.IsNotNil ? "InnerClasses" : "EnclosingMethod")} attribute on {f.Name}"); + } + else + { + try + { + enclosingClassWrapper = wrapper.classLoader.TryLoadClassByName(enclosingClassName) as RuntimeByteCodeJavaType; + } + catch (RetargetableJavaException x) + { + wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Unable to load outer class {enclosingClassName} for inner class {f.Name} ({x.GetType().Name}: {x.Message})"); + } + + if (enclosingClassWrapper != null) + { + // make sure the relationship is reciprocal (otherwise we run the risk of + // baking the outer type before the inner type) and that the inner and outer + // class live in the same class loader (when doing a multi target compilation, + // it is possible to split the two classes across assemblies) + var oimpl = enclosingClassWrapper.impl as JavaTypeImpl; + if (oimpl != null && enclosingClassWrapper.ClassLoader == wrapper.ClassLoader) + { + var outerClassFile = oimpl.classFile; + var outerInnerClasses = outerClassFile.InnerClasses; + if (outerInnerClasses == null) + { + enclosingClassWrapper = null; + } + else + { + var ok = false; + for (int i = 0; i < outerInnerClasses.Length; i++) + { + if (((outerInnerClasses[i].outerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name) || (outerInnerClasses[i].outerClass.IsNil && outerClass.outerClass.IsNil)) && outerInnerClasses[i].innerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name) + { + ok = true; + break; + } + } + + if (!ok) + { + enclosingClassWrapper = null; + } + } + } + else + { + enclosingClassWrapper = null; + } + + if (enclosingClassWrapper != null) + { + enclosingClassWrapper.CreateStep2(); + enclosing = oimpl.typeBuilder; + if (outerClass.outerClass.IsNil) + { + // we need to record that we're not an inner classes, but an enclosed class + typeAttribs |= TypeAttributes.SpecialName; + } + } + else + { + wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($"Non-reciprocal inner class {f.Name}"); + } + } + } + } + + if (f.IsPublic) + { + if (enclosing != null) + { + if (enclosingClassWrapper.IsPublic) + { + typeAttribs |= TypeAttributes.NestedPublic; + } + else + { + // We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type, + // because that would mean it wouldn't be visible outside the assembly. + cantNest = true; + typeAttribs |= TypeAttributes.Public; + } + } + else + { + typeAttribs |= TypeAttributes.Public; + } + } + else if (enclosing != null) + { + typeAttribs |= TypeAttributes.NestedAssembly; + } #else // IMPORTER if (f.IsPublic) { @@ -405,34 +405,34 @@ internal void CreateStep2() { typeAttribs |= TypeAttributes.Interface | TypeAttributes.Abstract; #if IMPORTER - // if any "meaningless" bits are set, preserve them - setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; - // by default we assume interfaces are abstract, so in the exceptional case we need a ModifiersAttribute - setModifiers |= (f.Modifiers & Modifiers.Abstract) == 0; - if (enclosing != null && !cantNest) - { - if (wrapper.IsGhost) - { - // TODO this is low priority, since the current Java class library doesn't define any ghost interfaces - // as inner classes - throw new NotImplementedException(); - } - - // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced - // (and broken by J# as well), so we'll just ignore it too. - typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); - } - else - { - if (wrapper.IsGhost) - { - typeBuilder = wrapper.DefineGhostType(mangledTypeName, typeAttribs); - } - else - { - typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); - } - } + // if any "meaningless" bits are set, preserve them + setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; + // by default we assume interfaces are abstract, so in the exceptional case we need a ModifiersAttribute + setModifiers |= (f.Modifiers & Modifiers.Abstract) == 0; + if (enclosing != null && !cantNest) + { + if (wrapper.IsGhost) + { + // TODO this is low priority, since the current Java class library doesn't define any ghost interfaces + // as inner classes + throw new NotImplementedException(); + } + + // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced + // (and broken by J# as well), so we'll just ignore it too. + typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); + } + else + { + if (wrapper.IsGhost) + { + typeBuilder = wrapper.DefineGhostType(mangledTypeName, typeAttribs); + } + else + { + typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); + } + } #else // IMPORTER typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); #endif // IMPORTER @@ -441,17 +441,17 @@ internal void CreateStep2() { typeAttribs |= TypeAttributes.Class; #if IMPORTER - // if any "meaningless" bits are set, preserve them - setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; - // by default we assume ACC_SUPER for classes, so in the exceptional case we need a ModifiersAttribute - setModifiers |= !f.IsSuper; - if (enclosing != null && !cantNest) - { - // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced - // (and broken by J# as well), so we'll just ignore it too. - typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); - } - else + // if any "meaningless" bits are set, preserve them + setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0; + // by default we assume ACC_SUPER for classes, so in the exceptional case we need a ModifiersAttribute + setModifiers |= !f.IsSuper; + if (enclosing != null && !cantNest) + { + // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced + // (and broken by J# as well), so we'll just ignore it too. + typeBuilder = enclosing.DefineNestedType(AllocNestedTypeName(enclosingClassWrapper.Name, f.Name), typeAttribs); + } + else #endif // IMPORTER { typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs); @@ -459,113 +459,113 @@ internal void CreateStep2() } #if IMPORTER - // When we're statically compiling, we associate the typeBuilder with the wrapper. This enables types in referenced assemblies to refer back to - // types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly). - wrapper.Context.ClassLoaderFactory.SetWrapperForType(typeBuilder, wrapper); - - if (outerClass.outerClass.IsNotNil) - { - if (enclosing != null && cantNest) - { - wrapper.Context.AttributeHelper.SetNonNestedInnerClass(enclosing, f.Name); - } - if (enclosing == null || cantNest) - { - wrapper.Context.AttributeHelper.SetNonNestedOuterClass(typeBuilder, enclosingClassName); - } - } - - if (classFile.InnerClasses != null) - { - foreach (var inner in classFile.InnerClasses) - { - var name = classFile.GetConstantPoolClass(inner.innerClass); - var exists = false; - - try - { - exists = wrapper.ClassLoader.TryLoadClassByName(name) != null; - } - catch (RetargetableJavaException) - { - - } - - if (!exists) - { - wrapper.Context.AttributeHelper.SetNonNestedInnerClass(typeBuilder, name); - } - } - } - - if (typeBuilder.FullName != wrapper.Name && wrapper.Name.Replace('$', '+') != typeBuilder.FullName) - { - wrapper.classLoader.AddNameMapping(wrapper.Name, typeBuilder.FullName); - } - - if (f.IsAnnotation && Annotation.HasRetentionPolicyRuntime(f.Annotations)) - { - annotationBuilder = new AnnotationBuilder(wrapper.Context, this, enclosing); - wrapper.SetAnnotation(annotationBuilder); - } - - // For Java 5 Enum types, we generate a nested .NET enum. - // This is primarily to support annotations that take enum parameters. - if (f.IsEnum && f.IsPublic) - { - AddCliEnum(); - } - - AddInnerClassAttribute(enclosing != null, outerClass.innerClass.IsNotNil, mangledTypeName, outerClass.accessFlags); - if (classFile.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(classFile.Annotations)) - { - wrapper.Context.AttributeHelper.SetDeprecatedAttribute(typeBuilder); - } - - if (classFile.GenericSignature != null) - { - wrapper.Context.AttributeHelper.SetSignatureAttribute(typeBuilder, classFile.GenericSignature); - } - if (classFile.EnclosingMethod != null) - { - if (outerClass.outerClass.IsNil && enclosing != null && !cantNest) - { - // we don't need to record the enclosing type, if we're compiling the current type as a nested type because of the EnclosingMethod attribute - wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, null, classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); - } - else - { - wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); - } - } - - if (classFile.RuntimeVisibleTypeAnnotations.Count > 0) - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(typeBuilder, in classFile.RuntimeVisibleTypeAnnotations); - - if (wrapper.classLoader.EmitStackTraceInfo) - { - if (f.SourceFileAttribute != null) - { - if ((enclosingClassWrapper == null && f.SourceFileAttribute == typeBuilder.Name + ".java") - || (enclosingClassWrapper != null && f.SourceFileAttribute == enclosingClassWrapper.sourceFileName)) - { - // we don't need to record the name because it matches our heuristic - } - else - { - wrapper.Context.AttributeHelper.SetSourceFile(typeBuilder, f.SourceFileAttribute); - } - } - else - { - wrapper.Context.AttributeHelper.SetSourceFile(typeBuilder, null); - } - } - // NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types - if (setModifiers || classFile.IsInternal || (classFile.Modifiers & (Modifiers.Synthetic | Modifiers.Annotation | Modifiers.Enum)) != 0) - { - wrapper.Context.AttributeHelper.SetModifiers(typeBuilder, classFile.Modifiers, classFile.IsInternal); - } + // When we're statically compiling, we associate the typeBuilder with the wrapper. This enables types in referenced assemblies to refer back to + // types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly). + wrapper.Context.ClassLoaderFactory.SetWrapperForType(typeBuilder, wrapper); + + if (outerClass.outerClass.IsNotNil) + { + if (enclosing != null && cantNest) + { + wrapper.Context.AttributeHelper.SetNonNestedInnerClass(enclosing, f.Name); + } + if (enclosing == null || cantNest) + { + wrapper.Context.AttributeHelper.SetNonNestedOuterClass(typeBuilder, enclosingClassName); + } + } + + if (classFile.InnerClasses != null) + { + foreach (var inner in classFile.InnerClasses) + { + var name = classFile.GetConstantPoolClass(inner.innerClass); + var exists = false; + + try + { + exists = wrapper.ClassLoader.TryLoadClassByName(name) != null; + } + catch (RetargetableJavaException) + { + + } + + if (!exists) + { + wrapper.Context.AttributeHelper.SetNonNestedInnerClass(typeBuilder, name); + } + } + } + + if (typeBuilder.FullName != wrapper.Name && wrapper.Name.Replace('$', '+') != typeBuilder.FullName) + { + wrapper.classLoader.AddNameMapping(wrapper.Name, typeBuilder.FullName); + } + + if (f.IsAnnotation && Annotation.HasRetentionPolicyRuntime(f.Annotations)) + { + annotationBuilder = new AnnotationBuilder(wrapper.Context, this, enclosing); + wrapper.SetAnnotation(annotationBuilder); + } + + // For Java 5 Enum types, we generate a nested .NET enum. + // This is primarily to support annotations that take enum parameters. + if (f.IsEnum && f.IsPublic) + { + AddCliEnum(); + } + + AddInnerClassAttribute(enclosing != null, outerClass.innerClass.IsNotNil, mangledTypeName, outerClass.accessFlags); + if (classFile.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(classFile.Annotations)) + { + wrapper.Context.AttributeHelper.SetDeprecatedAttribute(typeBuilder); + } + + if (classFile.GenericSignature != null) + { + wrapper.Context.AttributeHelper.SetSignatureAttribute(typeBuilder, classFile.GenericSignature); + } + if (classFile.EnclosingMethod != null) + { + if (outerClass.outerClass.IsNil && enclosing != null && !cantNest) + { + // we don't need to record the enclosing type, if we're compiling the current type as a nested type because of the EnclosingMethod attribute + wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, null, classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); + } + else + { + wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); + } + } + + if (classFile.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(typeBuilder, in classFile.RuntimeVisibleTypeAnnotations); + + if (wrapper.classLoader.EmitStackTraceInfo) + { + if (f.SourceFileAttribute != null) + { + if ((enclosingClassWrapper == null && f.SourceFileAttribute == typeBuilder.Name + ".java") + || (enclosingClassWrapper != null && f.SourceFileAttribute == enclosingClassWrapper.sourceFileName)) + { + // we don't need to record the name because it matches our heuristic + } + else + { + wrapper.Context.AttributeHelper.SetSourceFile(typeBuilder, f.SourceFileAttribute); + } + } + else + { + wrapper.Context.AttributeHelper.SetSourceFile(typeBuilder, null); + } + } + // NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types + if (setModifiers || classFile.IsInternal || (classFile.Modifiers & (Modifiers.Synthetic | Modifiers.Annotation | Modifiers.Enum)) != 0) + { + wrapper.Context.AttributeHelper.SetModifiers(typeBuilder, classFile.Modifiers, classFile.IsInternal); + } #endif // IMPORTER if (hasclinit) { @@ -582,7 +582,7 @@ internal void CreateStep2() } } #if IMPORTER - finally { } + finally { } #else catch (Exception x) { @@ -593,50 +593,50 @@ internal void CreateStep2() #if IMPORTER - private void AddInnerClassAttribute(bool isNestedType, bool isInnerClass, string mangledTypeName, Modifiers innerClassFlags) - { - string name = classFile.Name; - - if (isNestedType) - { - if (name == enclosingClassWrapper.Name + "$" + typeBuilder.Name) - { - name = null; - } - } - else if (name == mangledTypeName) - { - name = null; - } - - if ((isInnerClass && RuntimeManagedByteCodeJavaType.PredictReflectiveModifiers(wrapper) != innerClassFlags) || name != null) - { - // HACK we abuse the InnerClassAttribute to record to real name for non-inner classes as well - wrapper.Context.AttributeHelper.SetInnerClass(typeBuilder, name, isInnerClass ? innerClassFlags : wrapper.Modifiers); - } - } - - private void AddCliEnum() - { - ImportClassLoader ccl = wrapper.classLoader; - string name = "__Enum"; - while (!ccl.ReserveName(classFile.Name + "$" + name)) - { - name += "_"; - } - enumBuilder = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Serializable, wrapper.Context.Types.Enum); - wrapper.Context.AttributeHelper.HideFromJava(enumBuilder); - enumBuilder.DefineField("value__", wrapper.Context.Types.Int32, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); - for (int i = 0; i < classFile.Fields.Length; i++) - { - if (classFile.Fields[i].IsEnum) - { - FieldBuilder fieldBuilder = enumBuilder.DefineField(classFile.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal); - fieldBuilder.SetConstant(i); - } - } - wrapper.SetEnumType(enumBuilder); - } + private void AddInnerClassAttribute(bool isNestedType, bool isInnerClass, string mangledTypeName, Modifiers innerClassFlags) + { + string name = classFile.Name; + + if (isNestedType) + { + if (name == enclosingClassWrapper.Name + "$" + typeBuilder.Name) + { + name = null; + } + } + else if (name == mangledTypeName) + { + name = null; + } + + if ((isInnerClass && RuntimeManagedByteCodeJavaType.PredictReflectiveModifiers(wrapper) != innerClassFlags) || name != null) + { + // HACK we abuse the InnerClassAttribute to record to real name for non-inner classes as well + wrapper.Context.AttributeHelper.SetInnerClass(typeBuilder, name, isInnerClass ? innerClassFlags : wrapper.Modifiers); + } + } + + private void AddCliEnum() + { + ImportClassLoader ccl = wrapper.classLoader; + string name = "__Enum"; + while (!ccl.ReserveName(classFile.Name + "$" + name)) + { + name += "_"; + } + enumBuilder = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Serializable, wrapper.Context.Types.Enum); + wrapper.Context.AttributeHelper.HideFromJava(enumBuilder); + enumBuilder.DefineField("value__", wrapper.Context.Types.Int32, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); + for (int i = 0; i < classFile.Fields.Length; i++) + { + if (classFile.Fields[i].IsEnum) + { + FieldBuilder fieldBuilder = enumBuilder.DefineField(classFile.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal); + fieldBuilder.SetConstant(i); + } + } + wrapper.SetEnumType(enumBuilder); + } #endif void AddClinitTrigger() @@ -686,110 +686,110 @@ private static bool HasStructLayoutAttributeAnnotation(ClassFile c) } #if IMPORTER - private ClassFile.InnerClass getOuterClass() - { - ClassFile.InnerClass[] innerClasses = classFile.InnerClasses; - if (innerClasses != null) - { - for (int j = 0; j < innerClasses.Length; j++) - { - if (innerClasses[j].innerClass.IsNotNil && classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name) - { - return innerClasses[j]; - } - } - } - return new ClassFile.InnerClass(); - } - - private bool IsSideEffectFreeStaticInitializerOrNoop(ClassFile.Method m, out bool noop) - { - if (m.ExceptionTable.Length != 0) - { - noop = false; - return false; - } - noop = true; - for (int i = 0; i < m.Instructions.Length; i++) - { - NormalizedByteCode bc; - while ((bc = m.Instructions[i].NormalizedOpCode) == NormalizedByteCode.__goto) - { - int target = m.Instructions[i].TargetIndex; - if (target <= i) - { - // backward branch means we can't do anything - noop = false; - return false; - } - // we must skip the unused instructions because the "remove assertions" optimization - // uses a goto to remove the (now unused) code - i = target; - } - if (bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic) - { - ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1); - if (fld == null || fld.Class != classFile.Name) - { - noop = false; - return false; - } - // don't allow getstatic to load non-primitive fields, because that would - // cause the verifier to try to load the type - if (bc == NormalizedByteCode.__getstatic && "L[".IndexOf(fld.Signature[0]) != -1) - { - noop = false; - return false; - } - ClassFile.Field field = classFile.GetField(fld.Name, fld.Signature); - if (field == null) - { - noop = false; - return false; - } - if (bc == NormalizedByteCode.__putstatic) - { - if (field.IsProperty && field.PropertySetter != null) - { - noop = false; - return false; - } - } - else if (field.IsProperty && field.PropertyGetter != null) - { - noop = false; - return false; - } - } - else if (ByteCodeMetaData.CanThrowException(bc)) - { - noop = false; - return false; - } - else if (bc == NormalizedByteCode.__aconst_null - || (bc == NormalizedByteCode.__iconst && m.Instructions[i].Arg1 == 0) - || bc == NormalizedByteCode.__return - || bc == NormalizedByteCode.__nop) - { - // valid instructions in a potential noop - } - else - { - noop = false; - } - } - // the method needs to be verifiable to be side effect free, since we already analysed it, - // we know that the verifier won't try to load any types (which isn't allowed at this time) - try - { - wrapper.Context.MethodAnalyzerFactory.Create(null, wrapper, null, classFile, m, wrapper.classLoader); - return true; - } - catch (VerifyError) - { - return false; - } - } + private ClassFile.InnerClass getOuterClass() + { + ClassFile.InnerClass[] innerClasses = classFile.InnerClasses; + if (innerClasses != null) + { + for (int j = 0; j < innerClasses.Length; j++) + { + if (innerClasses[j].innerClass.IsNotNil && classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name) + { + return innerClasses[j]; + } + } + } + return new ClassFile.InnerClass(); + } + + private bool IsSideEffectFreeStaticInitializerOrNoop(ClassFile.Method m, out bool noop) + { + if (m.ExceptionTable.Length != 0) + { + noop = false; + return false; + } + noop = true; + for (int i = 0; i < m.Instructions.Length; i++) + { + NormalizedByteCode bc; + while ((bc = m.Instructions[i].NormalizedOpCode) == NormalizedByteCode.__goto) + { + int target = m.Instructions[i].TargetIndex; + if (target <= i) + { + // backward branch means we can't do anything + noop = false; + return false; + } + // we must skip the unused instructions because the "remove assertions" optimization + // uses a goto to remove the (now unused) code + i = target; + } + if (bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic) + { + ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1); + if (fld == null || fld.Class != classFile.Name) + { + noop = false; + return false; + } + // don't allow getstatic to load non-primitive fields, because that would + // cause the verifier to try to load the type + if (bc == NormalizedByteCode.__getstatic && "L[".IndexOf(fld.Signature[0]) != -1) + { + noop = false; + return false; + } + ClassFile.Field field = classFile.GetField(fld.Name, fld.Signature); + if (field == null) + { + noop = false; + return false; + } + if (bc == NormalizedByteCode.__putstatic) + { + if (field.IsProperty && field.PropertySetter != null) + { + noop = false; + return false; + } + } + else if (field.IsProperty && field.PropertyGetter != null) + { + noop = false; + return false; + } + } + else if (ByteCodeMetaData.CanThrowException(bc)) + { + noop = false; + return false; + } + else if (bc == NormalizedByteCode.__aconst_null + || (bc == NormalizedByteCode.__iconst && m.Instructions[i].Arg1 == 0) + || bc == NormalizedByteCode.__return + || bc == NormalizedByteCode.__nop) + { + // valid instructions in a potential noop + } + else + { + noop = false; + } + } + // the method needs to be verifiable to be side effect free, since we already analysed it, + // we know that the verifier won't try to load any types (which isn't allowed at this time) + try + { + wrapper.Context.MethodAnalyzerFactory.Create(null, wrapper, null, classFile, m, wrapper.classLoader); + return true; + } + catch (VerifyError) + { + return false; + } + } #endif // IMPORTER private RuntimeJavaMethod GetMethodWrapperDuringCtor(RuntimeJavaType lookup, IList methods, string name, string sig) @@ -879,18 +879,18 @@ private void AddDelegateInvokeStubs(RuntimeJavaType tw, ref RuntimeJavaMethod[] } #if IMPORTER - private static bool CheckInnerOuterNames(string inner, string outer) - { - // do some sanity checks on the inner/outer class names - return inner.Length > outer.Length + 1 && inner[outer.Length] == '$' && inner.StartsWith(outer, StringComparison.Ordinal); - } - - private string AllocNestedTypeName(string outer, string inner) - { - Debug.Assert(CheckInnerOuterNames(inner, outer)); - nestedTypeNames ??= new ConcurrentDictionary(); - return DynamicClassLoaderFactory.TypeNameMangleImpl(nestedTypeNames, inner.Substring(outer.Length + 1), null); - } + private static bool CheckInnerOuterNames(string inner, string outer) + { + // do some sanity checks on the inner/outer class names + return inner.Length > outer.Length + 1 && inner[outer.Length] == '$' && inner.StartsWith(outer, StringComparison.Ordinal); + } + + private string AllocNestedTypeName(string outer, string inner) + { + Debug.Assert(CheckInnerOuterNames(inner, outer)); + nestedTypeNames ??= new ConcurrentDictionary(); + return DynamicClassLoaderFactory.TypeNameMangleImpl(nestedTypeNames, inner.Substring(outer.Length + 1), null); + } #endif @@ -922,7 +922,7 @@ private static void CheckLoaderConstraints(RuntimeJavaMethod mw, RuntimeJavaMeth else { #if IMPORTER - StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"", mw.ReturnType, baseMethod.ReturnType, mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"", mw.ReturnType, baseMethod.ReturnType, mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); #else throw new LinkageError("Loader constraints violated"); #endif @@ -945,7 +945,7 @@ private static void CheckLoaderConstraints(RuntimeJavaMethod mw, RuntimeJavaMeth else { #if IMPORTER - StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"", here[i], there[i], mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); + StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"", here[i], there[i], mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name); #else throw new LinkageError("Loader constraints violated"); #endif @@ -975,75 +975,75 @@ internal override FieldInfo LinkField(RuntimeJavaField fw) } int fieldIndex = GetFieldIndex(fw); #if IMPORTER - if (wrapper.ClassLoader.RemoveUnusedFields - && fw.IsPrivate - && fw.IsStatic - && fw.IsFinal - && !fw.IsSerialVersionUID - && classFile.Fields[fieldIndex].Annotations == null - && !classFile.IsReferenced(classFile.Fields[fieldIndex])) - { - // unused, so we skip it - wrapper.ClassLoader.Diagnostics.GenericCompilerInfo($"Unused field {wrapper.Name}::{fw.Name}"); - return null; - } - - // for compatibility with broken Java code that assumes that reflection returns the fields in class declaration - // order, we emit the fields in class declaration order in the .NET metadata (and then when we retrieve them - // using .NET reflection, we sort on metadata token.) - if (fieldIndex > 0) + if (wrapper.ClassLoader.RemoveUnusedFields + && fw.IsPrivate + && fw.IsStatic + && fw.IsFinal + && !fw.IsSerialVersionUID + && classFile.Fields[fieldIndex].Annotations == null + && !classFile.IsReferenced(classFile.Fields[fieldIndex])) + { + // unused, so we skip it + wrapper.ClassLoader.Diagnostics.GenericCompilerInfo($"Unused field {wrapper.Name}::{fw.Name}"); + return null; + } + + // for compatibility with broken Java code that assumes that reflection returns the fields in class declaration + // order, we emit the fields in class declaration order in the .NET metadata (and then when we retrieve them + // using .NET reflection, we sort on metadata token.) + if (fieldIndex > 0) + { + if (!fields[fieldIndex - 1].IsLinked) + { + for (int i = 0; i < fieldIndex; i++) + { + fields[i].Link(); + } + } + } + + if (fieldIndex >= classFile.Fields.Length) + { + // this must be a field defined in map.xml + FieldAttributes fieldAttribs = 0; + if (fw.IsPublic) + { + fieldAttribs |= FieldAttributes.Public; + } + else if (fw.IsProtected) + { + fieldAttribs |= FieldAttributes.FamORAssem; + } + else if (fw.IsPrivate) + { + fieldAttribs |= FieldAttributes.Private; + } + else + { + fieldAttribs |= FieldAttributes.Assembly; + } + if (fw.IsStatic) + { + fieldAttribs |= FieldAttributes.Static; + } + if (fw.IsFinal) + { + fieldAttribs |= FieldAttributes.InitOnly; + } + return DefineField(fw.Name, fw.FieldTypeWrapper, fieldAttribs, fw.IsVolatile); + } +#endif // IMPORTER + FieldBuilder field; + ClassFile.Field fld = classFile.Fields[fieldIndex]; + FieldAttributes attribs = 0; + string realFieldName = UnicodeUtil.EscapeInvalidSurrogates(fld.Name); + if (!ReferenceEquals(realFieldName, fld.Name)) { - if (!fields[fieldIndex - 1].IsLinked) - { - for (int i = 0; i < fieldIndex; i++) - { - fields[i].Link(); - } - } - } - - if (fieldIndex >= classFile.Fields.Length) - { - // this must be a field defined in map.xml - FieldAttributes fieldAttribs = 0; - if (fw.IsPublic) - { - fieldAttribs |= FieldAttributes.Public; - } - else if (fw.IsProtected) - { - fieldAttribs |= FieldAttributes.FamORAssem; - } - else if (fw.IsPrivate) - { - fieldAttribs |= FieldAttributes.Private; - } - else - { - fieldAttribs |= FieldAttributes.Assembly; - } - if (fw.IsStatic) - { - fieldAttribs |= FieldAttributes.Static; - } - if (fw.IsFinal) - { - fieldAttribs |= FieldAttributes.InitOnly; - } - return DefineField(fw.Name, fw.FieldTypeWrapper, fieldAttribs, fw.IsVolatile); - } -#endif // IMPORTER - FieldBuilder field; - ClassFile.Field fld = classFile.Fields[fieldIndex]; - FieldAttributes attribs = 0; - string realFieldName = UnicodeUtil.EscapeInvalidSurrogates(fld.Name); - if (!ReferenceEquals(realFieldName, fld.Name)) - { - attribs |= FieldAttributes.SpecialName; + attribs |= FieldAttributes.SpecialName; } MethodAttributes methodAttribs = MethodAttributes.HideBySig; #if IMPORTER - bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0; + bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0; #endif if (fld.IsPrivate) { @@ -1083,28 +1083,28 @@ internal override FieldInfo LinkField(RuntimeJavaField fw) else { #if IMPORTER - if (wrapper.IsPublic && wrapper.NeedsType2AccessStub(fw)) - { - // this field is going to get a type 2 access stub, so we hide the actual field - attribs &= ~FieldAttributes.FieldAccessMask; - attribs |= FieldAttributes.Assembly; - // instead of adding HideFromJava we rename the field to avoid confusing broken compilers - // see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637 - // additional note: now that we maintain the ordering of the fields, we need to recognize - // these fields so that we know where to insert the corresponding accessor property FieldWrapper. - realFieldName = NamePrefix.Type2AccessStubBackingField + realFieldName; - } - else if (fld.IsFinal) - { - if (wrapper.IsInterface || wrapper.classLoader.StrictFinalFieldSemantics) - { - attribs |= FieldAttributes.InitOnly; - } - else - { - setModifiers = true; - } - } + if (wrapper.IsPublic && wrapper.NeedsType2AccessStub(fw)) + { + // this field is going to get a type 2 access stub, so we hide the actual field + attribs &= ~FieldAttributes.FieldAccessMask; + attribs |= FieldAttributes.Assembly; + // instead of adding HideFromJava we rename the field to avoid confusing broken compilers + // see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637 + // additional note: now that we maintain the ordering of the fields, we need to recognize + // these fields so that we know where to insert the corresponding accessor property FieldWrapper. + realFieldName = NamePrefix.Type2AccessStubBackingField + realFieldName; + } + else if (fld.IsFinal) + { + if (wrapper.IsInterface || wrapper.classLoader.StrictFinalFieldSemantics) + { + attribs |= FieldAttributes.InitOnly; + } + else + { + setModifiers = true; + } + } #else if (fld.IsFinal && wrapper.IsInterface) { @@ -1116,781 +1116,782 @@ internal override FieldInfo LinkField(RuntimeJavaField fw) } if (fld.IsTransient) { - var transientAttrib = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveCoreType(typeof(NonSerializedAttribute).FullName).GetConstructor(Type.EmptyTypes), []); + var transientAttrib = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveCoreType(typeof(NonSerializedAttribute).FullName).GetConstructor([]).AsReflection(), []); field.SetCustomAttribute(transientAttrib); } #if IMPORTER - { - // if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store - // the Java modifiers - if (setModifiers) - wrapper.Context.AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal); + { + // if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store + // the Java modifiers + if (setModifiers) + wrapper.Context.AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal); - if (fld.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(fld.Annotations)) - wrapper.Context.AttributeHelper.SetDeprecatedAttribute(field); + if (fld.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(fld.Annotations)) + wrapper.Context.AttributeHelper.SetDeprecatedAttribute(field); - if (fld.GenericSignature != null) - wrapper.Context.AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature); + if (fld.GenericSignature != null) + wrapper.Context.AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature); - if (fld.RuntimeVisibleTypeAnnotations.Count > 0) - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(field, in fld.RuntimeVisibleTypeAnnotations); - } + if (fld.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(field, in fld.RuntimeVisibleTypeAnnotations); + } #endif return field; } - FieldBuilder DefineField(string name, RuntimeJavaType tw, FieldAttributes attribs, bool isVolatile) - { - var modreq = isVolatile ? [wrapper.Context.Types.IsVolatile] : Type.EmptyTypes; - return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, wrapper.GetModOpt(tw, false), attribs); - } - - internal override void EmitRunClassConstructor(CodeEmitter ilgen) - { - if (clinitMethod != null) - ilgen.Emit(OpCodes.Call, clinitMethod); - } - - internal override DynamicImpl Finish() - { - var baseTypeWrapper = wrapper.BaseTypeWrapper; - if (baseTypeWrapper != null) - { - baseTypeWrapper.Finish(); - baseTypeWrapper.LinkAll(); - } - - // NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that - // causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types. - // The Name in the ResolveEventArgs contains only the nested type name, not the full type name, - // for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only - // receives "MyInnerType" as the name. Since we only compile inner classes as nested types - // when we're statically compiling, we can only run into this bug when we're statically compiling. - // NOTE To work around this bug, we have to make sure that all types that are going to be - // required in finished form, are finished explicitly here. It isn't clear what other types are - // required to be finished. I instrumented a static compilation of classpath.dll and this - // turned up no other cases of the TypeResolve event firing. - foreach (RuntimeJavaType iface in wrapper.interfaces) - { - iface.Finish(); - iface.LinkAll(); - } - - // make sure all classes are loaded, before we start finishing the type. During finishing, we - // may not run any Java code, because that might result in a request to finish the type that we - // are in the process of finishing, and this would be a problem. - // Prevent infinity recursion for broken class loaders by keeping a recursion count and falling - // back to late binding if we recurse more than twice. - var mode = System.Threading.Interlocked.Increment(ref recursionCount) > 2 || (JVM.DisableEagerClassLoading && wrapper.Name != "sun.reflect.misc.Trampoline") - ? LoadMode.ReturnUnloadable - : LoadMode.Link; - try - { - classFile.Link(wrapper, mode); - - for (int i = 0; i < fields.Length; i++) - fields[i].Link(mode); - - for (int i = 0; i < methods.Length; i++) - methods[i].Link(mode); - } - finally - { - System.Threading.Interlocked.Decrement(ref recursionCount); - } - - // this is the correct lock, FinishCore doesn't call any user code and mutates global state, - // so it needs to be protected by a lock. - lock (this) - { - FinishedTypeImpl impl; - try - { - // call FinishCore in the finally to avoid Thread.Abort interrupting the thread - } - finally - { - impl = FinishCore(); - } - return impl; - } - } - - FinishedTypeImpl FinishCore() - { - // it is possible that the loading of the referenced classes triggered a finish of us, - // if that happens, we just return - if (finishedType != null) - return finishedType; - - if (finishInProgress) - throw new InvalidOperationException("Recursive finish attempt for " + wrapper.Name); - - finishInProgress = true; - wrapper.ClassLoader.Diagnostics.GenericCompilerTrace($"Finishing: {wrapper.Name}"); - Profiler.Enter("JavaTypeImpl.Finish.Core"); - - try - { - RuntimeJavaType declaringTypeWrapper = null; - var innerClassesTypeWrappers = Array.Empty(); - - // if we're an inner class, we need to attach an InnerClass attribute - ClassFile.InnerClass[] innerclasses = classFile.InnerClasses; - if (innerclasses != null) - { - // TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here - var wrappers = new List(); - for (int i = 0; i < innerclasses.Length; i++) - { - if (innerclasses[i].innerClass.IsNotNil && innerclasses[i].outerClass.IsNotNil) - { - if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper) - { - wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass)); - } - if (classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper) - { - declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass); - } - } - } - innerClassesTypeWrappers = wrappers.ToArray(); -#if IMPORTER - // before we bake our type, we need to link any inner annotations to allow them to create their attribute type (as a nested type) - foreach (var tw in innerClassesTypeWrappers) - { - var dtw = tw as RuntimeByteCodeJavaType; - if (dtw != null) - { - var impl = dtw.impl as JavaTypeImpl; - if (impl != null) - if (impl.annotationBuilder != null) - impl.annotationBuilder.Link(); - } - } -#endif - } -#if IMPORTER - - if (annotationBuilder != null) - { - var cab = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveRuntimeType(typeof(AnnotationAttributeAttribute).FullName).GetConstructor(new Type[] { wrapper.Context.Types.String }), new object[] { UnicodeUtil.EscapeInvalidSurrogates(annotationBuilder.AttributeTypeName) }); - typeBuilder.SetCustomAttribute(cab); - } - - if (!wrapper.IsInterface && wrapper.IsMapUnsafeException) - { - // mark all exceptions that are unsafe for mapping with a custom attribute, - // so that at runtime we can quickly assertain if an exception type can be - // caught without filtering - wrapper.Context.AttributeHelper.SetExceptionIsUnsafeForMapping(typeBuilder); - } -#endif - - var context = new FinishContext(wrapper.Context, host, classFile, wrapper, typeBuilder); - var type = context.FinishImpl(); - -#if IMPORTER - if (annotationBuilder != null) - { - annotationBuilder.Finish(this); - } - if (enumBuilder != null) - { - enumBuilder.CreateType(); - } - if (privateInterfaceMethods != null) - { - privateInterfaceMethods.CreateType(); - } -#endif - var finishedClinitMethod = (MethodInfo)clinitMethod; -#if !IMPORTER - if (finishedClinitMethod != null) - { - // In dynamic mode, we may need to emit a call to this method from a DynamicMethod which doesn't support calling unfinished methods, - // so we must resolve to the real method here. - finishedClinitMethod = type.GetMethod("__", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - } -#endif - - finishedType = new FinishedTypeImpl(type, innerClassesTypeWrappers, declaringTypeWrapper, wrapper.ReflectiveModifiers, Metadata.Create(classFile), finishedClinitMethod, finalizeMethod, host); - return finishedType; - } -#if !IMPORTER - catch (Exception x) - { - throw new InternalException($"Exception during finishing of: {wrapper.Name}", x); - } -#endif - finally - { - Profiler.Leave("JavaTypeImpl.Finish.Core"); - } - } - -#if IMPORTER - - private bool IsValidAnnotationElementType(string type) - { - if (type[0] == '[') - type = type.Substring(1); - - switch (type) - { - case "Z": - case "B": - case "S": - case "C": - case "I": - case "J": - case "F": - case "D": - case "Ljava.lang.String;": - case "Ljava.lang.Class;": - return true; - } - - if (type.StartsWith("L") && type.EndsWith(";")) - { - try - { - var tw = wrapper.ClassLoader.TryLoadClassByName(type.Substring(1, type.Length - 2)); - if (tw != null) - { - if ((tw.Modifiers & Modifiers.Annotation) != 0) - return true; - - if ((tw.Modifiers & Modifiers.Enum) != 0) - { - var enumType = wrapper.Context.ClassLoaderFactory.GetBootstrapClassLoader().TryLoadClassByName("java.lang.Enum"); - if (enumType != null && tw.IsSubTypeOf(enumType)) - return true; - } - } - } - catch - { - - } - } - - return false; - } - - sealed class AnnotationBuilder : Annotation - { - - readonly RuntimeContext context; - - JavaTypeImpl impl; - TypeBuilder outer; - TypeBuilder annotationTypeBuilder; - TypeBuilder attributeTypeBuilder; - MethodBuilder defineConstructor; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal AnnotationBuilder(RuntimeContext context, JavaTypeImpl o, TypeBuilder outer) - { - this.context = context; - this.impl = o; - this.outer = outer; - } - - internal void Link() - { - if (impl == null) - { - return; - } - JavaTypeImpl o = impl; - impl = null; - - // Make sure the annotation type only has valid methods - for (int i = 0; i < o.methods.Length; i++) - { - if (!o.methods[i].IsStatic) - { - if (!o.methods[i].Signature.StartsWith("()")) - { - return; - } - if (!o.IsValidAnnotationElementType(o.methods[i].Signature.Substring(2))) - { - return; - } - } - } - - // we only set annotationTypeBuilder if we're valid - annotationTypeBuilder = o.typeBuilder; - - var annotationAttributeBaseType = context.ClassLoaderFactory.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); - - // make sure we don't clash with another class name - var ccl = o.wrapper.classLoader; - string name = UnicodeUtil.EscapeInvalidSurrogates(o.classFile.Name); - while (!ccl.ReserveName(name + "Attribute")) - { - name += "_"; - } - - var typeAttributes = TypeAttributes.Class | TypeAttributes.Sealed; - if (o.enclosingClassWrapper != null) - { - if (o.wrapper.IsPublic) - { - typeAttributes |= TypeAttributes.NestedPublic; - } - else - { - typeAttributes |= TypeAttributes.NestedAssembly; - } - attributeTypeBuilder = outer.DefineNestedType(o.AllocNestedTypeName(o.enclosingClassWrapper.Name, name + "Attribute"), typeAttributes, annotationAttributeBaseType.TypeAsBaseType); - } - else - { - if (o.wrapper.IsPublic) - { - typeAttributes |= TypeAttributes.Public; - } - else - { - typeAttributes |= TypeAttributes.NotPublic; - } - attributeTypeBuilder = o.wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType); - } - if (o.wrapper.IsPublic) - { - // In the Java world, the class appears as a non-public proxy class - context.AttributeHelper.SetModifiers(attributeTypeBuilder, Modifiers.Final, false); - } - - // NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world - int dotindex = o.classFile.Name.LastIndexOf('.') + 1; - context.AttributeHelper.SetInnerClass(attributeTypeBuilder, o.classFile.Name.Substring(0, dotindex) + "$Proxy" + o.classFile.Name.Substring(dotindex), Modifiers.Final); - attributeTypeBuilder.AddInterfaceImplementation(o.typeBuilder); - context.AttributeHelper.SetImplementsAttribute(attributeTypeBuilder, new RuntimeJavaType[] { o.wrapper }); - - if (o.classFile.Annotations != null) - { - CustomAttributeBuilder attributeUsageAttribute = null; - bool hasAttributeUsageAttribute = false; - foreach (object[] def in o.classFile.Annotations) - { - if (def[1].Equals("Ljava/lang/annotation/Target;") && !hasAttributeUsageAttribute) - { - for (int i = 2; i < def.Length; i += 2) - { - if (def[i].Equals("value")) - { - object[] val = def[i + 1] as object[]; - if (val != null - && val.Length > 0 - && val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY)) - { - AttributeTargets targets = 0; - for (int j = 1; j < val.Length; j++) - { - object[] eval = val[j] as object[]; - if (eval != null - && eval.Length == 3 - && eval[0].Equals(AnnotationDefaultAttribute.TAG_ENUM) - && eval[1].Equals("Ljava/lang/annotation/ElementType;")) - { - switch ((string)eval[2]) - { - case "ANNOTATION_TYPE": - targets |= AttributeTargets.Interface; - break; - case "CONSTRUCTOR": - targets |= AttributeTargets.Constructor; - break; - case "FIELD": - targets |= AttributeTargets.Field; - break; - case "LOCAL_VARIABLE": - break; - case "METHOD": - targets |= AttributeTargets.Method; - break; - case "PACKAGE": - targets |= AttributeTargets.Interface; - break; - case "PARAMETER": - targets |= AttributeTargets.Parameter; - break; - case "TYPE": - targets |= AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum; - break; - } - } - } - attributeUsageAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(AttributeUsageAttribute).FullName).GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(AttributeTargets).FullName) }), new object[] { targets }); - } - } - } - } - else - { - // apply any .NET custom attributes that are on the annotation to the custom attribute we synthesize - // (for example, to allow AttributeUsageAttribute to be overridden) - Annotation annotation = Annotation.Load(o.wrapper, def); - if (annotation != null && annotation.IsCustomAttribute) - { - annotation.Apply(o.wrapper.ClassLoader, attributeTypeBuilder, def); - } - if (def[1].Equals("Lcli/System/AttributeUsageAttribute$Annotation;")) - { - hasAttributeUsageAttribute = true; - } - } - } - if (attributeUsageAttribute != null && !hasAttributeUsageAttribute) - { - attributeTypeBuilder.SetCustomAttribute(attributeUsageAttribute); - } - } - - defineConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { context.Resolver.ResolveCoreType(typeof(object).FullName).MakeArrayType() }); - context.AttributeHelper.SetEditorBrowsableNever(defineConstructor); - } + FieldBuilder DefineField(string name, RuntimeJavaType tw, FieldAttributes attribs, bool isVolatile) + { + var modreq = isVolatile ? [wrapper.Context.Types.IsVolatile] : Type.EmptyTypes; + return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, wrapper.GetModOpt(tw, false), attribs); + } + + internal override void EmitRunClassConstructor(CodeEmitter ilgen) + { + if (clinitMethod != null) + ilgen.Emit(OpCodes.Call, clinitMethod); + } - private static Type TypeWrapperToAnnotationParameterType(RuntimeJavaType tw) + internal override DynamicImpl Finish() + { + var baseTypeWrapper = wrapper.BaseTypeWrapper; + if (baseTypeWrapper != null) { - bool isArray = false; - if (tw.IsArray) - { - isArray = true; - tw = tw.ElementTypeWrapper; - } - if (tw.Annotation != null) - { - // we don't support Annotation args - return null; - } - else - { - Type argType; - if (tw == tw.Context.JavaBase.TypeOfJavaLangClass) - { - argType = tw.Context.Types.Type; - } - else if (tw.EnumType != null) // is it a Java enum? - { - argType = tw.EnumType; - } - else if (IsDotNetEnum(tw)) - { - argType = tw.DeclaringTypeWrapper.TypeAsSignatureType; - } - else - { - argType = tw.TypeAsSignatureType; - } - if (isArray) - { - argType = RuntimeArrayJavaType.MakeArrayType(argType, 1); - } - return argType; - } + baseTypeWrapper.Finish(); + baseTypeWrapper.LinkAll(); } - private static bool IsDotNetEnum(RuntimeJavaType tw) + // NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that + // causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types. + // The Name in the ResolveEventArgs contains only the nested type name, not the full type name, + // for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only + // receives "MyInnerType" as the name. Since we only compile inner classes as nested types + // when we're statically compiling, we can only run into this bug when we're statically compiling. + // NOTE To work around this bug, we have to make sure that all types that are going to be + // required in finished form, are finished explicitly here. It isn't clear what other types are + // required to be finished. I instrumented a static compilation of classpath.dll and this + // turned up no other cases of the TypeResolve event firing. + foreach (RuntimeJavaType iface in wrapper.interfaces) { - return tw.IsFakeNestedType && (tw.Modifiers & Modifiers.Enum) != 0; + iface.Finish(); + iface.LinkAll(); } - internal string AttributeTypeName + // make sure all classes are loaded, before we start finishing the type. During finishing, we + // may not run any Java code, because that might result in a request to finish the type that we + // are in the process of finishing, and this would be a problem. + // Prevent infinity recursion for broken class loaders by keeping a recursion count and falling + // back to late binding if we recurse more than twice. + var mode = System.Threading.Interlocked.Increment(ref recursionCount) > 2 || (JVM.DisableEagerClassLoading && wrapper.Name != "sun.reflect.misc.Trampoline") + ? LoadMode.ReturnUnloadable + : LoadMode.Link; + try { - get - { - Link(); - if (attributeTypeBuilder != null) - { - return attributeTypeBuilder.FullName; - } - return null; - } + classFile.Link(wrapper, mode); + + for (int i = 0; i < fields.Length; i++) + fields[i].Link(mode); + + for (int i = 0; i < methods.Length; i++) + methods[i].Link(mode); + } + finally + { + System.Threading.Interlocked.Decrement(ref recursionCount); } - private static void EmitSetValueCall(RuntimeJavaType annotationAttributeBaseType, CodeEmitter ilgen, string name, RuntimeJavaType tw, int argIndex) + // this is the correct lock, FinishCore doesn't call any user code and mutates global state, + // so it needs to be protected by a lock. + lock (this) { - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Ldstr, name); - ilgen.EmitLdarg(argIndex); - if (tw.TypeAsSignatureType.IsValueType) - { - ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType); - } - else if (tw.EnumType != null) // is it a Java enum? + FinishedTypeImpl impl; + try { - ilgen.Emit(OpCodes.Box, tw.EnumType); + // call FinishCore in the finally to avoid Thread.Abort interrupting the thread } - else if (IsDotNetEnum(tw)) + finally { - ilgen.Emit(OpCodes.Box, tw.DeclaringTypeWrapper.TypeAsSignatureType); + impl = FinishCore(); } - var setValueMethod = annotationAttributeBaseType.GetMethodWrapper("setValue", "(Ljava.lang.String;Ljava.lang.Object;)V", false); - setValueMethod.Link(); - setValueMethod.EmitCall(ilgen); + return impl; } + } - internal void Finish(JavaTypeImpl o) - { - Link(); - if (annotationTypeBuilder == null) - { - // not a valid annotation type - return; - } - RuntimeJavaType annotationAttributeBaseType = context.ClassLoaderFactory.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); - annotationAttributeBaseType.Finish(); + FinishedTypeImpl FinishCore() + { + // it is possible that the loading of the referenced classes triggered a finish of us, + // if that happens, we just return + if (finishedType != null) + return finishedType; - int requiredArgCount = 0; - int valueArg = -1; - bool unsupported = false; - for (int i = 0; i < o.methods.Length; i++) - { - if (!o.methods[i].IsStatic) - { - if (valueArg == -1 && o.methods[i].Name == "value") - { - valueArg = i; - } - if (o.classFile.Methods[i].AnnotationDefault == null) - { - if (TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType) == null) - { - unsupported = true; - break; - } - requiredArgCount++; - } - } - } + if (finishInProgress) + throw new InvalidOperationException("Recursive finish attempt for " + wrapper.Name); - MethodBuilder defaultConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, unsupported || requiredArgCount > 0 ? MethodAttributes.Private : MethodAttributes.Public, Type.EmptyTypes); - CodeEmitter ilgen; + finishInProgress = true; + wrapper.ClassLoader.Diagnostics.GenericCompilerTrace($"Finishing: {wrapper.Name}"); + Profiler.Enter("JavaTypeImpl.Finish.Core"); - if (!unsupported) - { - if (requiredArgCount > 0) - { - Type[] args = new Type[requiredArgCount]; - for (int i = 0, j = 0; i < o.methods.Length; i++) - { - if (!o.methods[i].IsStatic) - { - if (o.classFile.Methods[i].AnnotationDefault == null) - { - args[j++] = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); - } - } - } - MethodBuilder reqArgConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, args); - context.AttributeHelper.HideFromJava(reqArgConstructor); - ilgen = context.CodeEmitterFactory.Create(reqArgConstructor); - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Call, defaultConstructor); - for (int i = 0, j = 0; i < o.methods.Length; i++) - { - if (!o.methods[i].IsStatic) - { - if (o.classFile.Methods[i].AnnotationDefault == null) - { - reqArgConstructor.DefineParameter(++j, ParameterAttributes.None, o.methods[i].Name); - EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, j); - } - } - } - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - } - else if (valueArg != -1) - { - // We don't have any required parameters, but we do have an optional "value" parameter, - // so we create an additional constructor (the default constructor will be public in this case) - // that accepts the value parameter. - Type argType = TypeWrapperToAnnotationParameterType(o.methods[valueArg].ReturnType); - if (argType != null) - { - MethodBuilder cb = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { argType }); - context.AttributeHelper.HideFromJava(cb); - cb.DefineParameter(1, ParameterAttributes.None, "value"); - ilgen = context.CodeEmitterFactory.Create(cb); - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Call, defaultConstructor); - EmitSetValueCall(annotationAttributeBaseType, ilgen, "value", o.methods[valueArg].ReturnType, 1); - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - } - } - } + try + { + RuntimeJavaType declaringTypeWrapper = null; + var innerClassesTypeWrappers = Array.Empty(); - ilgen = context.CodeEmitterFactory.Create(defaultConstructor); - ilgen.Emit(OpCodes.Ldarg_0); - o.wrapper.EmitClassLiteral(ilgen); - annotationAttributeBaseType.GetMethodWrapper("", "(Ljava.lang.Class;)V", false).EmitCall(ilgen); - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - - ilgen = context.CodeEmitterFactory.Create(defineConstructor); - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Call, defaultConstructor); - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Ldarg_1); - annotationAttributeBaseType.GetMethodWrapper("setDefinition", "([Ljava.lang.Object;)V", false).EmitCall(ilgen); - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - - var getValueMethod = annotationAttributeBaseType.GetMethodWrapper("getValue", "(Ljava.lang.String;)Ljava.lang.Object;", false); - var getByteValueMethod = annotationAttributeBaseType.GetMethodWrapper("getByteValue", "(Ljava.lang.String;)B", false); - var getBooleanValueMethod = annotationAttributeBaseType.GetMethodWrapper("getBooleanValue", "(Ljava.lang.String;)Z", false); - var getCharValueMethod = annotationAttributeBaseType.GetMethodWrapper("getCharValue", "(Ljava.lang.String;)C", false); - var getShortValueMethod = annotationAttributeBaseType.GetMethodWrapper("getShortValue", "(Ljava.lang.String;)S", false); - var getIntValueMethod = annotationAttributeBaseType.GetMethodWrapper("getIntValue", "(Ljava.lang.String;)I", false); - var getFloatValueMethod = annotationAttributeBaseType.GetMethodWrapper("getFloatValue", "(Ljava.lang.String;)F", false); - var getLongValueMethod = annotationAttributeBaseType.GetMethodWrapper("getLongValue", "(Ljava.lang.String;)J", false); - var getDoubleValueMethod = annotationAttributeBaseType.GetMethodWrapper("getDoubleValue", "(Ljava.lang.String;)D", false); - for (int i = 0; i < o.methods.Length; i++) + // if we're an inner class, we need to attach an InnerClass attribute + ClassFile.InnerClass[] innerclasses = classFile.InnerClasses; + if (innerclasses != null) { - // skip and non-virtual interface methods introduced in Java 8 - if (o.methods[i].IsVirtual) + // TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here + var wrappers = new List(); + for (int i = 0; i < innerclasses.Length; i++) { - MethodBuilder mb = o.methods[i].GetDefineMethodHelper().DefineMethod(o.wrapper, attributeTypeBuilder, o.methods[i].Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); - attributeTypeBuilder.DefineMethodOverride(mb, (MethodInfo)o.methods[i].GetMethod()); - ilgen = context.CodeEmitterFactory.Create(mb); - ilgen.Emit(OpCodes.Ldarg_0); - ilgen.Emit(OpCodes.Ldstr, o.methods[i].Name); - if (o.methods[i].ReturnType.IsPrimitive) + if (innerclasses[i].innerClass.IsNotNil && innerclasses[i].outerClass.IsNotNil) { - if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.BYTE) - { - getByteValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.BOOLEAN) - { - getBooleanValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.CHAR) - { - getCharValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.SHORT) - { - getShortValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.INT) - { - getIntValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.FLOAT) - { - getFloatValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.LONG) - { - getLongValueMethod.EmitCall(ilgen); - } - else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.DOUBLE) - { - getDoubleValueMethod.EmitCall(ilgen); - } - else + if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper) { - throw new InvalidOperationException(); + wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass)); } - } - else - { - getValueMethod.EmitCall(ilgen); - o.methods[i].ReturnType.EmitCheckcast(ilgen); - } - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - - if (o.classFile.Methods[i].AnnotationDefault != null - && !(o.methods[i].Name == "value" && requiredArgCount == 0)) - { - // now add a .NET property for this annotation optional parameter - Type argType = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); - if (argType != null) + if (classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper) { - PropertyBuilder pb = attributeTypeBuilder.DefineProperty(o.methods[i].Name, PropertyAttributes.None, argType, Type.EmptyTypes); - context.AttributeHelper.HideFromJava(pb); - MethodBuilder setter = attributeTypeBuilder.DefineMethod("set_" + o.methods[i].Name, MethodAttributes.Public, context.Types.Void, new Type[] { argType }); - context.AttributeHelper.HideFromJava(setter); - pb.SetSetMethod(setter); - ilgen = context.CodeEmitterFactory.Create(setter); - EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, 1); - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - MethodBuilder getter = attributeTypeBuilder.DefineMethod("get_" + o.methods[i].Name, MethodAttributes.Public, argType, Type.EmptyTypes); - context.AttributeHelper.HideFromJava(getter); - pb.SetGetMethod(getter); - // TODO implement the getter method - ilgen = context.CodeEmitterFactory.Create(getter); - ilgen.ThrowException(context.Resolver.ResolveCoreType(typeof(NotImplementedException).FullName)); - ilgen.DoEmit(); + declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass); } } } + innerClassesTypeWrappers = wrappers.ToArray(); +#if IMPORTER + // before we bake our type, we need to link any inner annotations to allow them to create their attribute type (as a nested type) + foreach (var tw in innerClassesTypeWrappers) + { + var dtw = tw as RuntimeByteCodeJavaType; + if (dtw != null) + { + var impl = dtw.impl as JavaTypeImpl; + if (impl != null) + if (impl.annotationBuilder != null) + impl.annotationBuilder.Link(); + } + } +#endif } - attributeTypeBuilder.CreateType(); - } +#if IMPORTER - private CustomAttributeBuilder MakeCustomAttributeBuilder(RuntimeClassLoader loader, object annotation) - { - Link(); - ConstructorInfo ctor = defineConstructor != null - ? defineConstructor.__AsConstructorInfo() - : context.Resolver.ResolveRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute").GetConstructor(new Type[] { context.Types.Object.MakeArrayType() }); - return new CustomAttributeBuilder(ctor, new object[] { AnnotationDefaultAttribute.Escape(QualifyClassNames(loader, annotation)) }); - } + if (annotationBuilder != null) + { + var cab = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveRuntimeType(typeof(AnnotationAttributeAttribute).FullName).AsReflection().GetConstructor(new Type[] { wrapper.Context.Types.String }), new object[] { UnicodeUtil.EscapeInvalidSurrogates(annotationBuilder.AttributeTypeName) }); + typeBuilder.SetCustomAttribute(cab); + } + + if (!wrapper.IsInterface && wrapper.IsMapUnsafeException) + { + // mark all exceptions that are unsafe for mapping with a custom attribute, + // so that at runtime we can quickly assertain if an exception type can be + // caught without filtering + wrapper.Context.AttributeHelper.SetExceptionIsUnsafeForMapping(typeBuilder); + } +#endif - internal override void Apply(RuntimeClassLoader loader, TypeBuilder tb, object annotation) - { - tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); - } + var context = new FinishContext(wrapper.Context, host, classFile, wrapper, typeBuilder); + var type = context.FinishImpl(); - internal override void Apply(RuntimeClassLoader loader, MethodBuilder mb, object annotation) - { - mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); - } +#if IMPORTER + if (annotationBuilder != null) + { + annotationBuilder.Finish(this); + } + if (enumBuilder != null) + { + enumBuilder.CreateType(); + } + if (privateInterfaceMethods != null) + { + privateInterfaceMethods.CreateType(); + } +#endif + var finishedClinitMethod = (MethodInfo)clinitMethod; +#if !IMPORTER + if (finishedClinitMethod != null) + { + // In dynamic mode, we may need to emit a call to this method from a DynamicMethod which doesn't support calling unfinished methods, + // so we must resolve to the real method here. + finishedClinitMethod = type.GetMethod("__", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } +#endif - internal override void Apply(RuntimeClassLoader loader, FieldBuilder fb, object annotation) - { - fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + finishedType = new FinishedTypeImpl(type, innerClassesTypeWrappers, declaringTypeWrapper, wrapper.ReflectiveModifiers, Metadata.Create(classFile), finishedClinitMethod, finalizeMethod, host); + return finishedType; } - - internal override void Apply(RuntimeClassLoader loader, ParameterBuilder pb, object annotation) +#if !IMPORTER + catch (Exception x) { - pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + throw new InternalException($"Exception during finishing of: {wrapper.Name}", x); } - - internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, object annotation) +#endif + finally { - ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + Profiler.Leave("JavaTypeImpl.Finish.Core"); } + } - internal override void Apply(RuntimeClassLoader loader, PropertyBuilder pb, object annotation) - { - pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); - } +#if IMPORTER - internal override bool IsCustomAttribute - { - get { return false; } - } - } + private bool IsValidAnnotationElementType(string type) + { + if (type[0] == '[') + type = type.Substring(1); + + switch (type) + { + case "Z": + case "B": + case "S": + case "C": + case "I": + case "J": + case "F": + case "D": + case "Ljava.lang.String;": + case "Ljava.lang.Class;": + return true; + } + + if (type.StartsWith("L") && type.EndsWith(";")) + { + try + { + var tw = wrapper.ClassLoader.TryLoadClassByName(type.Substring(1, type.Length - 2)); + if (tw != null) + { + if ((tw.Modifiers & Modifiers.Annotation) != 0) + return true; + + if ((tw.Modifiers & Modifiers.Enum) != 0) + { + var enumType = wrapper.Context.ClassLoaderFactory.GetBootstrapClassLoader().TryLoadClassByName("java.lang.Enum"); + if (enumType != null && tw.IsSubTypeOf(enumType)) + return true; + } + } + } + catch + { + + } + } + + return false; + } + + sealed class AnnotationBuilder : Annotation + { + + readonly RuntimeContext context; + + JavaTypeImpl impl; + TypeBuilder outer; + TypeBuilder annotationTypeBuilder; + TypeBuilder attributeTypeBuilder; + MethodBuilder defineConstructor; + + /// + /// Initializes a new instance. + /// + /// + /// + /// + internal AnnotationBuilder(RuntimeContext context, JavaTypeImpl o, TypeBuilder outer) + { + this.context = context; + this.impl = o; + this.outer = outer; + } + + internal void Link() + { + if (impl == null) + { + return; + } + JavaTypeImpl o = impl; + impl = null; + + // Make sure the annotation type only has valid methods + for (int i = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (!o.methods[i].Signature.StartsWith("()")) + { + return; + } + if (!o.IsValidAnnotationElementType(o.methods[i].Signature.Substring(2))) + { + return; + } + } + } + + // we only set annotationTypeBuilder if we're valid + annotationTypeBuilder = o.typeBuilder; + + var annotationAttributeBaseType = context.ClassLoaderFactory.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); + + // make sure we don't clash with another class name + var ccl = o.wrapper.classLoader; + string name = UnicodeUtil.EscapeInvalidSurrogates(o.classFile.Name); + while (!ccl.ReserveName(name + "Attribute")) + { + name += "_"; + } + + var typeAttributes = TypeAttributes.Class | TypeAttributes.Sealed; + if (o.enclosingClassWrapper != null) + { + if (o.wrapper.IsPublic) + { + typeAttributes |= TypeAttributes.NestedPublic; + } + else + { + typeAttributes |= TypeAttributes.NestedAssembly; + } + attributeTypeBuilder = outer.DefineNestedType(o.AllocNestedTypeName(o.enclosingClassWrapper.Name, name + "Attribute"), typeAttributes, annotationAttributeBaseType.TypeAsBaseType); + } + else + { + if (o.wrapper.IsPublic) + { + typeAttributes |= TypeAttributes.Public; + } + else + { + typeAttributes |= TypeAttributes.NotPublic; + } + attributeTypeBuilder = o.wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType); + } + if (o.wrapper.IsPublic) + { + // In the Java world, the class appears as a non-public proxy class + context.AttributeHelper.SetModifiers(attributeTypeBuilder, Modifiers.Final, false); + } + + // NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world + int dotindex = o.classFile.Name.LastIndexOf('.') + 1; + context.AttributeHelper.SetInnerClass(attributeTypeBuilder, o.classFile.Name.Substring(0, dotindex) + "$Proxy" + o.classFile.Name.Substring(dotindex), Modifiers.Final); + attributeTypeBuilder.AddInterfaceImplementation(o.typeBuilder); + context.AttributeHelper.SetImplementsAttribute(attributeTypeBuilder, new RuntimeJavaType[] { o.wrapper }); + + if (o.classFile.Annotations != null) + { + CustomAttributeBuilder attributeUsageAttribute = null; + bool hasAttributeUsageAttribute = false; + foreach (object[] def in o.classFile.Annotations) + { + if (def[1].Equals("Ljava/lang/annotation/Target;") && !hasAttributeUsageAttribute) + { + for (int i = 2; i < def.Length; i += 2) + { + if (def[i].Equals("value")) + { + object[] val = def[i + 1] as object[]; + if (val != null + && val.Length > 0 + && val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY)) + { + AttributeTargets targets = 0; + for (int j = 1; j < val.Length; j++) + { + object[] eval = val[j] as object[]; + if (eval != null + && eval.Length == 3 + && eval[0].Equals(AnnotationDefaultAttribute.TAG_ENUM) + && eval[1].Equals("Ljava/lang/annotation/ElementType;")) + { + switch ((string)eval[2]) + { + case "ANNOTATION_TYPE": + targets |= AttributeTargets.Interface; + break; + case "CONSTRUCTOR": + targets |= AttributeTargets.Constructor; + break; + case "FIELD": + targets |= AttributeTargets.Field; + break; + case "LOCAL_VARIABLE": + break; + case "METHOD": + targets |= AttributeTargets.Method; + break; + case "PACKAGE": + targets |= AttributeTargets.Interface; + break; + case "PARAMETER": + targets |= AttributeTargets.Parameter; + break; + case "TYPE": + targets |= AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum; + break; + } + } + } + + attributeUsageAttribute = new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(AttributeUsageAttribute).FullName).GetConstructor([context.Resolver.ResolveCoreType(typeof(AttributeTargets).FullName)]).AsReflection(), [targets]); + } + } + } + } + else + { + // apply any .NET custom attributes that are on the annotation to the custom attribute we synthesize + // (for example, to allow AttributeUsageAttribute to be overridden) + Annotation annotation = Annotation.Load(o.wrapper, def); + if (annotation != null && annotation.IsCustomAttribute) + { + annotation.Apply(o.wrapper.ClassLoader, attributeTypeBuilder, def); + } + if (def[1].Equals("Lcli/System/AttributeUsageAttribute$Annotation;")) + { + hasAttributeUsageAttribute = true; + } + } + } + if (attributeUsageAttribute != null && !hasAttributeUsageAttribute) + { + attributeTypeBuilder.SetCustomAttribute(attributeUsageAttribute); + } + } + + defineConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { context.Resolver.ResolveCoreType(typeof(object).FullName).MakeArrayType().AsReflection() }); + context.AttributeHelper.SetEditorBrowsableNever(defineConstructor); + } + + private static Type TypeWrapperToAnnotationParameterType(RuntimeJavaType tw) + { + bool isArray = false; + if (tw.IsArray) + { + isArray = true; + tw = tw.ElementTypeWrapper; + } + if (tw.Annotation != null) + { + // we don't support Annotation args + return null; + } + else + { + Type argType; + if (tw == tw.Context.JavaBase.TypeOfJavaLangClass) + { + argType = tw.Context.Types.Type; + } + else if (tw.EnumType != null) // is it a Java enum? + { + argType = tw.EnumType; + } + else if (IsDotNetEnum(tw)) + { + argType = tw.DeclaringTypeWrapper.TypeAsSignatureType; + } + else + { + argType = tw.TypeAsSignatureType; + } + if (isArray) + { + argType = RuntimeArrayJavaType.MakeArrayType(argType, 1); + } + return argType; + } + } + + private static bool IsDotNetEnum(RuntimeJavaType tw) + { + return tw.IsFakeNestedType && (tw.Modifiers & Modifiers.Enum) != 0; + } + + internal string AttributeTypeName + { + get + { + Link(); + if (attributeTypeBuilder != null) + { + return attributeTypeBuilder.FullName; + } + return null; + } + } + + private static void EmitSetValueCall(RuntimeJavaType annotationAttributeBaseType, CodeEmitter ilgen, string name, RuntimeJavaType tw, int argIndex) + { + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldstr, name); + ilgen.EmitLdarg(argIndex); + if (tw.TypeAsSignatureType.IsValueType) + { + ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType); + } + else if (tw.EnumType != null) // is it a Java enum? + { + ilgen.Emit(OpCodes.Box, tw.EnumType); + } + else if (IsDotNetEnum(tw)) + { + ilgen.Emit(OpCodes.Box, tw.DeclaringTypeWrapper.TypeAsSignatureType); + } + var setValueMethod = annotationAttributeBaseType.GetMethodWrapper("setValue", "(Ljava.lang.String;Ljava.lang.Object;)V", false); + setValueMethod.Link(); + setValueMethod.EmitCall(ilgen); + } + + internal void Finish(JavaTypeImpl o) + { + Link(); + if (annotationTypeBuilder == null) + { + // not a valid annotation type + return; + } + RuntimeJavaType annotationAttributeBaseType = context.ClassLoaderFactory.LoadClassCritical("ikvm.internal.AnnotationAttributeBase"); + annotationAttributeBaseType.Finish(); + + int requiredArgCount = 0; + int valueArg = -1; + bool unsupported = false; + for (int i = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (valueArg == -1 && o.methods[i].Name == "value") + { + valueArg = i; + } + if (o.classFile.Methods[i].AnnotationDefault == null) + { + if (TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType) == null) + { + unsupported = true; + break; + } + requiredArgCount++; + } + } + } + + MethodBuilder defaultConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, unsupported || requiredArgCount > 0 ? MethodAttributes.Private : MethodAttributes.Public, Type.EmptyTypes); + CodeEmitter ilgen; + + if (!unsupported) + { + if (requiredArgCount > 0) + { + Type[] args = new Type[requiredArgCount]; + for (int i = 0, j = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (o.classFile.Methods[i].AnnotationDefault == null) + { + args[j++] = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); + } + } + } + MethodBuilder reqArgConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, args); + context.AttributeHelper.HideFromJava(reqArgConstructor); + ilgen = context.CodeEmitterFactory.Create(reqArgConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + for (int i = 0, j = 0; i < o.methods.Length; i++) + { + if (!o.methods[i].IsStatic) + { + if (o.classFile.Methods[i].AnnotationDefault == null) + { + reqArgConstructor.DefineParameter(++j, ParameterAttributes.None, o.methods[i].Name); + EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, j); + } + } + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + else if (valueArg != -1) + { + // We don't have any required parameters, but we do have an optional "value" parameter, + // so we create an additional constructor (the default constructor will be public in this case) + // that accepts the value parameter. + Type argType = TypeWrapperToAnnotationParameterType(o.methods[valueArg].ReturnType); + if (argType != null) + { + MethodBuilder cb = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { argType }); + context.AttributeHelper.HideFromJava(cb); + cb.DefineParameter(1, ParameterAttributes.None, "value"); + ilgen = context.CodeEmitterFactory.Create(cb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + EmitSetValueCall(annotationAttributeBaseType, ilgen, "value", o.methods[valueArg].ReturnType, 1); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + } + } + + ilgen = context.CodeEmitterFactory.Create(defaultConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + o.wrapper.EmitClassLiteral(ilgen); + annotationAttributeBaseType.GetMethodWrapper("", "(Ljava.lang.Class;)V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + ilgen = context.CodeEmitterFactory.Create(defineConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Call, defaultConstructor); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldarg_1); + annotationAttributeBaseType.GetMethodWrapper("setDefinition", "([Ljava.lang.Object;)V", false).EmitCall(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + var getValueMethod = annotationAttributeBaseType.GetMethodWrapper("getValue", "(Ljava.lang.String;)Ljava.lang.Object;", false); + var getByteValueMethod = annotationAttributeBaseType.GetMethodWrapper("getByteValue", "(Ljava.lang.String;)B", false); + var getBooleanValueMethod = annotationAttributeBaseType.GetMethodWrapper("getBooleanValue", "(Ljava.lang.String;)Z", false); + var getCharValueMethod = annotationAttributeBaseType.GetMethodWrapper("getCharValue", "(Ljava.lang.String;)C", false); + var getShortValueMethod = annotationAttributeBaseType.GetMethodWrapper("getShortValue", "(Ljava.lang.String;)S", false); + var getIntValueMethod = annotationAttributeBaseType.GetMethodWrapper("getIntValue", "(Ljava.lang.String;)I", false); + var getFloatValueMethod = annotationAttributeBaseType.GetMethodWrapper("getFloatValue", "(Ljava.lang.String;)F", false); + var getLongValueMethod = annotationAttributeBaseType.GetMethodWrapper("getLongValue", "(Ljava.lang.String;)J", false); + var getDoubleValueMethod = annotationAttributeBaseType.GetMethodWrapper("getDoubleValue", "(Ljava.lang.String;)D", false); + for (int i = 0; i < o.methods.Length; i++) + { + // skip and non-virtual interface methods introduced in Java 8 + if (o.methods[i].IsVirtual) + { + MethodBuilder mb = o.methods[i].GetDefineMethodHelper().DefineMethod(o.wrapper, attributeTypeBuilder, o.methods[i].Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); + attributeTypeBuilder.DefineMethodOverride(mb, (MethodInfo)o.methods[i].GetMethod()); + ilgen = context.CodeEmitterFactory.Create(mb); + ilgen.Emit(OpCodes.Ldarg_0); + ilgen.Emit(OpCodes.Ldstr, o.methods[i].Name); + if (o.methods[i].ReturnType.IsPrimitive) + { + if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.BYTE) + { + getByteValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.BOOLEAN) + { + getBooleanValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.CHAR) + { + getCharValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.SHORT) + { + getShortValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.INT) + { + getIntValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.FLOAT) + { + getFloatValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.LONG) + { + getLongValueMethod.EmitCall(ilgen); + } + else if (o.methods[i].ReturnType == context.PrimitiveJavaTypeFactory.DOUBLE) + { + getDoubleValueMethod.EmitCall(ilgen); + } + else + { + throw new InvalidOperationException(); + } + } + else + { + getValueMethod.EmitCall(ilgen); + o.methods[i].ReturnType.EmitCheckcast(ilgen); + } + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + + if (o.classFile.Methods[i].AnnotationDefault != null + && !(o.methods[i].Name == "value" && requiredArgCount == 0)) + { + // now add a .NET property for this annotation optional parameter + Type argType = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType); + if (argType != null) + { + PropertyBuilder pb = attributeTypeBuilder.DefineProperty(o.methods[i].Name, PropertyAttributes.None, argType, Type.EmptyTypes); + context.AttributeHelper.HideFromJava(pb); + MethodBuilder setter = attributeTypeBuilder.DefineMethod("set_" + o.methods[i].Name, MethodAttributes.Public, context.Types.Void, new Type[] { argType }); + context.AttributeHelper.HideFromJava(setter); + pb.SetSetMethod(setter); + ilgen = context.CodeEmitterFactory.Create(setter); + EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, 1); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + MethodBuilder getter = attributeTypeBuilder.DefineMethod("get_" + o.methods[i].Name, MethodAttributes.Public, argType, Type.EmptyTypes); + context.AttributeHelper.HideFromJava(getter); + pb.SetGetMethod(getter); + // TODO implement the getter method + ilgen = context.CodeEmitterFactory.Create(getter); + ilgen.ThrowException(context.Resolver.ResolveCoreType(typeof(NotImplementedException).FullName).AsReflection()); + ilgen.DoEmit(); + } + } + } + } + attributeTypeBuilder.CreateType(); + } + + private CustomAttributeBuilder MakeCustomAttributeBuilder(RuntimeClassLoader loader, object annotation) + { + Link(); + ConstructorInfo ctor = defineConstructor != null + ? defineConstructor.__AsConstructorInfo() + : context.Resolver.ResolveRuntimeType("IKVM.Attributes.DynamicAnnotationAttribute").AsReflection().GetConstructor(new Type[] { context.Types.Object.MakeArrayType() }); + return new CustomAttributeBuilder(ctor, new object[] { AnnotationDefaultAttribute.Escape(QualifyClassNames(loader, annotation)) }); + } + + internal override void Apply(RuntimeClassLoader loader, TypeBuilder tb, object annotation) + { + tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(RuntimeClassLoader loader, MethodBuilder mb, object annotation) + { + mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(RuntimeClassLoader loader, FieldBuilder fb, object annotation) + { + fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(RuntimeClassLoader loader, ParameterBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, object annotation) + { + ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override void Apply(RuntimeClassLoader loader, PropertyBuilder pb, object annotation) + { + pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + } + + internal override bool IsCustomAttribute + { + get { return false; } + } + } #endif // IMPORTER internal override RuntimeJavaType[] InnerClasses @@ -2454,11 +2455,11 @@ internal override MethodBase LinkMethod(RuntimeJavaMethod mw) wrapper.EmitLevel4Warning(mmw.IsConflictError ? HardError.IncompatibleClassChangeError : HardError.AbstractMethodError, message); } #if IMPORTER - if (wrapper.IsInterface && !mmw.IsAbstract) - { - // even though we're not visible to reflection we need to record the fact that we have a default implementation - wrapper.Context.AttributeHelper.SetModifiers(mb, mmw.Modifiers, false); - } + if (wrapper.IsInterface && !mmw.IsAbstract) + { + // even though we're not visible to reflection we need to record the fact that we have a default implementation + wrapper.Context.AttributeHelper.SetModifiers(mb, mmw.Modifiers, false); + } #endif return mb; } @@ -2501,50 +2502,50 @@ internal override MethodBase LinkMethod(RuntimeJavaMethod mw) methods[index].SetDeclaredExceptions(exceptions); #if IMPORTER - wrapper.Context.AttributeHelper.SetThrowsAttribute(method, exceptions); - - if (setModifiers || m.IsInternal || (m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0) - wrapper.Context.AttributeHelper.SetModifiers(method, m.Modifiers, m.IsInternal); - - // synthetic and bridge methods should not be visible to the user and set as compiler generated - if ((m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic && !IsAccessBridge(classFile, m)) - { - wrapper.Context.AttributeHelper.SetCompilerGenerated(method); - wrapper.Context.AttributeHelper.SetEditorBrowsableNever(method); - } - - // ensure deprecated attribute appears on method if obsolete not specified - if (m.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(m.Annotations)) - { - wrapper.Context.AttributeHelper.SetDeprecatedAttribute(method); - } - - // apply .NET attribute to record Java generic signature - if (m.GenericSignature != null) - { - wrapper.Context.AttributeHelper.SetSignatureAttribute(method, m.GenericSignature); - } - - if (wrapper.ClassLoader.NoParameterReflection) - { - // ignore MethodParameters (except to extract parameter names) - } - else if (m.MalformedMethodParameters) - { - wrapper.Context.AttributeHelper.SetMethodParametersAttribute(method, null); - } - else if (m.MethodParameters != null) - { - var modifiers = new Modifiers[m.MethodParameters.Length]; - for (int i = 0; i < modifiers.Length; i++) - modifiers[i] = (Modifiers)m.MethodParameters[i].accessFlags; - - wrapper.Context.AttributeHelper.SetMethodParametersAttribute(method, modifiers); - } - - // copy runtime visible annotations as attributes - if (m.RuntimeVisibleTypeAnnotations.Count > 0) - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(method, in m.RuntimeVisibleTypeAnnotations); + wrapper.Context.AttributeHelper.SetThrowsAttribute(method, exceptions); + + if (setModifiers || m.IsInternal || (m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0) + wrapper.Context.AttributeHelper.SetModifiers(method, m.Modifiers, m.IsInternal); + + // synthetic and bridge methods should not be visible to the user and set as compiler generated + if ((m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic && !IsAccessBridge(classFile, m)) + { + wrapper.Context.AttributeHelper.SetCompilerGenerated(method); + wrapper.Context.AttributeHelper.SetEditorBrowsableNever(method); + } + + // ensure deprecated attribute appears on method if obsolete not specified + if (m.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(m.Annotations)) + { + wrapper.Context.AttributeHelper.SetDeprecatedAttribute(method); + } + + // apply .NET attribute to record Java generic signature + if (m.GenericSignature != null) + { + wrapper.Context.AttributeHelper.SetSignatureAttribute(method, m.GenericSignature); + } + + if (wrapper.ClassLoader.NoParameterReflection) + { + // ignore MethodParameters (except to extract parameter names) + } + else if (m.MalformedMethodParameters) + { + wrapper.Context.AttributeHelper.SetMethodParametersAttribute(method, null); + } + else if (m.MethodParameters != null) + { + var modifiers = new Modifiers[m.MethodParameters.Length]; + for (int i = 0; i < modifiers.Length; i++) + modifiers[i] = (Modifiers)m.MethodParameters[i].accessFlags; + + wrapper.Context.AttributeHelper.SetMethodParametersAttribute(method, modifiers); + } + + // copy runtime visible annotations as attributes + if (m.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(method, in m.RuntimeVisibleTypeAnnotations); #else // IMPORTER @@ -2662,20 +2663,20 @@ MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifier attribs |= MethodAttributes.SpecialName; } #if IMPORTER - if ((m.Modifiers & Modifiers.Bridge) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic) - { - string sigbase = m.Signature.Substring(0, m.Signature.LastIndexOf(')') + 1); - foreach (var mw in methods) - { - if (mw.Name == m.Name && mw.Signature.StartsWith(sigbase) && mw.Signature != m.Signature) - { - // To prevent bridge methods with covariant return types from confusing - // other .NET compilers (like C#), we rename the bridge method. - name = NamePrefix.Bridge + name; - break; - } - } - } + if ((m.Modifiers & Modifiers.Bridge) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic) + { + string sigbase = m.Signature.Substring(0, m.Signature.LastIndexOf(')') + 1); + foreach (var mw in methods) + { + if (mw.Name == m.Name && mw.Signature.StartsWith(sigbase) && mw.Signature != m.Signature) + { + // To prevent bridge methods with covariant return types from confusing + // other .NET compilers (like C#), we rename the bridge method. + name = NamePrefix.Bridge + name; + break; + } + } + } #endif if ((attribs & MethodAttributes.Virtual) != 0 && !classFile.IsInterface) { @@ -2708,7 +2709,7 @@ MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifier } MethodBuilder mb = null; #if IMPORTER - mb = wrapper.DefineGhostMethod(typeBuilder, name, attribs, methods[index]); + mb = wrapper.DefineGhostMethod(typeBuilder, name, attribs, methods[index]); #endif if (mb == null) { @@ -2783,7 +2784,7 @@ MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifier tb, NamePrefix.PrivateInterfaceInstanceMethod + name, attribs | MethodAttributes.Static | MethodAttributes.SpecialName, typeBuilder, false); #if IMPORTER - wrapper.Context.AttributeHelper.SetNameSig(mb, m.Name, m.Signature); + wrapper.Context.AttributeHelper.SetNameSig(mb, m.Name, m.Signature); #endif } setModifiers = true; @@ -2857,12 +2858,12 @@ MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifier ilgen.DoEmit(); } #if IMPORTER - if (classFile.Methods[index].AnnotationDefault != null) - { - CustomAttributeBuilder cab = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveRuntimeType("IKVM.Attributes.AnnotationDefaultAttribute").GetConstructor(new Type[] { wrapper.Context.Types.Object }), new object[] { AnnotationDefaultAttribute.Escape(classFile.Methods[index].AnnotationDefault) }); - mb.SetCustomAttribute(cab); - } -#endif + if (classFile.Methods[index].AnnotationDefault != null) + { + var cab = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveRuntimeType("IKVM.Attributes.AnnotationDefaultAttribute").AsReflection().GetConstructor([wrapper.Context.Types.Object]), [AnnotationDefaultAttribute.Escape(classFile.Methods[index].AnnotationDefault)]); + mb.SetCustomAttribute(cab); + } +#endif } // method is a synchronized method @@ -2919,28 +2920,28 @@ private static MethodAttributes GetMethodAccess(RuntimeJavaMethod mw) } #if IMPORTER - // The classic example of an access bridge is StringBuilder.length(), the JDK 6 compiler - // generates this to work around a reflection problem (which otherwise wouldn't surface the - // length() method, because it is defined in the non-public base class AbstractStringBuilder.) - private static bool IsAccessBridge(ClassFile classFile, ClassFile.Method m) - { - // HACK this is a pretty gross hack - // We look at the method body to figure out if the bridge method calls another method with the exact - // same name/signature and if that is the case, we assume that it is an access bridge. - // This code is based on the javac algorithm in addBridgeIfNeeded(...) in com/sun/tools/javac/comp/TransTypes.java. - if ((m.Modifiers & (Modifiers.Abstract | Modifiers.Native | Modifiers.Public | Modifiers.Bridge)) == (Modifiers.Public | Modifiers.Bridge)) - { - foreach (ClassFile.Method.Instruction instr in m.Instructions) - { - if (instr.NormalizedOpCode == NormalizedByteCode.__invokespecial) - { - ClassFile.ConstantPoolItemMI cpi = classFile.SafeGetMethodref(instr.Arg1); - return cpi != null && cpi.Name == m.Name && cpi.Signature == m.Signature; - } - } - } - return false; - } + // The classic example of an access bridge is StringBuilder.length(), the JDK 6 compiler + // generates this to work around a reflection problem (which otherwise wouldn't surface the + // length() method, because it is defined in the non-public base class AbstractStringBuilder.) + private static bool IsAccessBridge(ClassFile classFile, ClassFile.Method m) + { + // HACK this is a pretty gross hack + // We look at the method body to figure out if the bridge method calls another method with the exact + // same name/signature and if that is the case, we assume that it is an access bridge. + // This code is based on the javac algorithm in addBridgeIfNeeded(...) in com/sun/tools/javac/comp/TransTypes.java. + if ((m.Modifiers & (Modifiers.Abstract | Modifiers.Native | Modifiers.Public | Modifiers.Bridge)) == (Modifiers.Public | Modifiers.Bridge)) + { + foreach (ClassFile.Method.Instruction instr in m.Instructions) + { + if (instr.NormalizedOpCode == NormalizedByteCode.__invokespecial) + { + ClassFile.ConstantPoolItemMI cpi = classFile.SafeGetMethodref(instr.Arg1); + return cpi != null && cpi.Name == m.Name && cpi.Signature == m.Signature; + } + } + } + return false; + } #endif // IMPORTER internal override Type Type diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs index cf74aa77da..35bf3c4ed3 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.cs @@ -670,7 +670,7 @@ private bool IsPInvokeMethod(ClassFile.Method m) { foreach (IKVM.Tools.Importer.MapXml.Attribute attr in method.Attributes) { - if (Context.StaticCompiler.GetType(classLoader, attr.Type) == Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.DllImportAttribute).FullName)) + if (Context.StaticCompiler.GetType(classLoader, attr.Type) == Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.DllImportAttribute).FullName).AsReflection()) { return true; } diff --git a/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs b/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs index e9e48b2b72..1a0eb7c92d 100644 --- a/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs +++ b/src/IKVM.Runtime/RuntimeClassLoaderFactory.cs @@ -99,7 +99,7 @@ internal void SetBootstrapClassLoader(RuntimeClassLoader bootstrapClassLoader) internal void LoadRemappedTypes() { // if we're compiling the base assembly, we won't be able to resolve one - var baseAssembly = context.Resolver.ResolveBaseAssembly(); + var baseAssembly = context.Resolver.ResolveBaseAssembly().AsReflection(); if (baseAssembly != null && remappedTypes.Count == 0) { var remapped = context.AttributeHelper.GetRemappedClasses(baseAssembly); diff --git a/src/IKVM.Runtime/RuntimeContext.cs b/src/IKVM.Runtime/RuntimeContext.cs index 87e62e6288..e2d770865c 100644 --- a/src/IKVM.Runtime/RuntimeContext.cs +++ b/src/IKVM.Runtime/RuntimeContext.cs @@ -2,6 +2,8 @@ using System.Collections.Concurrent; using IKVM.CoreLib.Diagnostics; +using IKVM.CoreLib.Symbols; + #if IMPORTER @@ -27,7 +29,7 @@ class RuntimeContext readonly RuntimeContextOptions options; readonly IDiagnosticHandler diagnostics; - readonly IManagedTypeResolver resolver; + readonly ISymbolResolver resolver; readonly bool bootstrap; readonly ConcurrentDictionary singletons = new(); @@ -79,7 +81,7 @@ class RuntimeContext /// /// /// - public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, IManagedTypeResolver resolver, bool bootstrap, StaticCompiler staticCompiler) + public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, ISymbolResolver resolver, bool bootstrap, StaticCompiler staticCompiler) { this.options = options ?? throw new ArgumentNullException(nameof(options)); this.diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); @@ -90,14 +92,14 @@ public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnost #else - /// - /// Initializes a new instance. - /// - /// - /// - /// - /// - public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, IManagedTypeResolver resolver, bool bootstrap) + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + public RuntimeContext(RuntimeContextOptions options, IDiagnosticHandler diagnostics, ISymbolResolver resolver, bool bootstrap) { this.options = options ?? throw new ArgumentNullException(nameof(options)); this.diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); @@ -141,10 +143,10 @@ T GetOrCreateSingleton(ref T value, Func create) /// public RuntimeContextOptions Options => options; - /// - /// Gets the associated with this instance of the runtime. - /// - public IManagedTypeResolver Resolver => resolver; + /// + /// Gets the associated with this instance of the runtime. + /// + public ISymbolResolver Resolver => resolver; /// /// Gets whether or not the runtime is running in bootstrap mode; that is, we are compiling the Java base assembly itself. diff --git a/src/IKVM.Runtime/RuntimeJavaType.cs b/src/IKVM.Runtime/RuntimeJavaType.cs index ecfad5c401..e16b878896 100644 --- a/src/IKVM.Runtime/RuntimeJavaType.cs +++ b/src/IKVM.Runtime/RuntimeJavaType.cs @@ -125,7 +125,7 @@ internal void EmitClassLiteral(CodeEmitter ilgen) } else { - var classLiteralType = Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ClassLiteral`1").MakeGenericType(type); + var classLiteralType = Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ClassLiteral`1").AsReflection().MakeGenericType(type); ilgen.Emit(OpCodes.Call, classLiteralType.GetProperty("Value").GetMethod); } } @@ -156,11 +156,11 @@ bool IsForbiddenTypeParameterType(Type type) // these are the types that may not be used as a type argument when instantiating a generic type return type == context.Types.Void #if NETFRAMEWORK - || type == context.Resolver.ResolveCoreType(typeof(ArgIterator).FullName) + || type == context.Resolver.ResolveCoreType(typeof(ArgIterator).FullName).AsReflection() #endif - || type == context.Resolver.ResolveCoreType(typeof(RuntimeArgumentHandle).FullName) - || type == context.Resolver.ResolveCoreType(typeof(TypedReference).FullName) - || type.ContainsGenericParameters + || type == context.Resolver.ResolveCoreType(typeof(RuntimeArgumentHandle).FullName).AsReflection() + || type == context.Resolver.ResolveCoreType(typeof(TypedReference).FullName).AsReflection() + || type.ContainsGenericParameters || type.IsByRef; } @@ -1619,7 +1619,7 @@ internal RuntimeJavaType GetPublicBaseTypeWrapper() // return the constructor used for automagic .NET serialization internal virtual MethodBase GetSerializationConstructor() { - return TypeAsBaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.SerializationInfo).FullName), context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.StreamingContext).FullName) }, null); + return TypeAsBaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(System.Runtime.Serialization.StreamingContext).FullName).AsReflection()], null); } internal virtual MethodBase GetBaseSerializationConstructor() diff --git a/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs b/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs index abdef21b8d..82ee77df55 100644 --- a/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs +++ b/src/IKVM.Runtime/RuntimeManagedByteCodeJavaType.cs @@ -946,7 +946,7 @@ static RuntimeJavaType TypeWrapperFromModOpt(RuntimeContext context, Type[] modo RuntimeJavaType tw = null; foreach (var type in modopt) { - if (type == context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName)) + if (type == context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName).AsReflection()) { // ignore } @@ -1191,7 +1191,7 @@ internal sealed class CompiledAnnotation : Annotation internal CompiledAnnotation(RuntimeContext context, Type type) { this.context = context ?? throw new ArgumentNullException(nameof(context)); - constructor = type.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(object).FullName).MakeArrayType() }); + constructor = type.GetConstructor(new Type[] { context.Resolver.ResolveCoreType(typeof(object).FullName).MakeArrayType().AsReflection() }); } private CustomAttributeBuilder MakeCustomAttributeBuilder(RuntimeClassLoader loader, object annotation) diff --git a/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs b/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs index 4bce53d8eb..9bd4613d3c 100644 --- a/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs +++ b/src/IKVM.Runtime/RuntimeManagedJavaType.AttributeAnnotationJavaType.cs @@ -239,7 +239,7 @@ static RuntimeJavaType MapType(RuntimeContext context, Type type, bool isArray) { if (tw is EnumEnumJavaType) { - if (!isArray && type.IsDefined(context.Resolver.ResolveCoreType(typeof(FlagsAttribute).FullName), false)) + if (!isArray && type.IsDefined(context.Resolver.ResolveCoreType(typeof(FlagsAttribute).FullName).AsReflection(), false)) { return tw.MakeArrayType(1); } @@ -413,9 +413,9 @@ AttributeUsageAttribute GetAttributeUsage() bool inherited = true; foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(attributeType)) { - if (cad.Constructor.DeclaringType == Context.Resolver.ResolveCoreType(typeof(AttributeUsageAttribute).FullName)) + if (cad.Constructor.DeclaringType == Context.Resolver.ResolveCoreType(typeof(AttributeUsageAttribute).FullName).AsReflection()) { - if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == Context.Resolver.ResolveCoreType(typeof(AttributeTargets).FullName)) + if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == Context.Resolver.ResolveCoreType(typeof(AttributeTargets).FullName).AsReflection()) { validOn = (AttributeTargets)cad.ConstructorArguments[0].Value; } @@ -540,7 +540,7 @@ CustomAttributeBuilder MakeCustomAttributeBuilder(RuntimeClassLoader loader, obj internal override void Apply(RuntimeClassLoader loader, TypeBuilder tb, object annotation) { - if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.StructLayoutAttribute).FullName) && tb.BaseType != loader.Context.Types.Object) + if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.StructLayoutAttribute).FullName).AsReflection() && tb.BaseType != loader.Context.Types.Object) { // we have to handle this explicitly, because if we apply an illegal StructLayoutAttribute, // TypeBuilder.CreateType() will later on throw an exception. @@ -569,7 +569,7 @@ internal override void Apply(RuntimeClassLoader loader, ParameterBuilder pb, obj { // TODO with the current custom attribute annotation restrictions it is impossible to use this CA, // but if we make it possible, we should also implement it here - if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.DefaultParameterValueAttribute).FullName)) + if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.InteropServices.DefaultParameterValueAttribute).FullName).AsReflection()) throw new NotImplementedException(); else pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); @@ -578,11 +578,11 @@ internal override void Apply(RuntimeClassLoader loader, ParameterBuilder pb, obj internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, object annotation) { #if IMPORTER - if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute).FullName)) + if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute).FullName).AsReflection()) { ab.__AddTypeForwarder((Type)ConvertValue(loader, loader.Context.Types.Type, ((object[])annotation)[3])); } - else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyVersionAttribute).FullName)) + else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyVersionAttribute).FullName).AsReflection()) { string str = (string)ConvertValue(loader, loader.Context.Types.String, ((object[])annotation)[3]); Version version; @@ -595,7 +595,7 @@ internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, obje loader.Diagnostics.InvalidCustomAttribute(type.FullName, "The version '" + str + "' is invalid."); } } - else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyCultureAttribute).FullName)) + else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyCultureAttribute).FullName).AsReflection()) { string str = (string)ConvertValue(loader, loader.Context.Types.String, ((object[])annotation)[3]); if (str != "") @@ -603,18 +603,18 @@ internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, obje ab.__SetAssemblyCulture(str); } } - else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyDelaySignAttribute).FullName) - || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyFileAttribute).FullName) - || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyNameAttribute).FullName)) + else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyDelaySignAttribute).FullName).AsReflection() + || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyFileAttribute).FullName).AsReflection() + || type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyKeyNameAttribute).FullName).AsReflection()) { loader.Diagnostics.IgnoredCustomAttribute(type.FullName, "Please use the corresponding compiler switch."); } - else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyAlgorithmIdAttribute).FullName)) + else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyAlgorithmIdAttribute).FullName).AsReflection()) { // this attribute is currently not exposed as an annotation and isn't very interesting throw new NotImplementedException(); } - else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyFlagsAttribute).FullName)) + else if (type == loader.Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyFlagsAttribute).FullName).AsReflection()) { // this attribute is currently not exposed as an annotation and isn't very interesting throw new NotImplementedException(); @@ -624,7 +624,7 @@ internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab, obje ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); } #else - ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); + ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation)); #endif } diff --git a/src/IKVM.Runtime/RuntimeManagedJavaType.EnumEnumJavaType.cs b/src/IKVM.Runtime/RuntimeManagedJavaType.EnumEnumJavaType.cs index 95830d7a77..f709eb7aac 100644 --- a/src/IKVM.Runtime/RuntimeManagedJavaType.EnumEnumJavaType.cs +++ b/src/IKVM.Runtime/RuntimeManagedJavaType.EnumEnumJavaType.cs @@ -120,7 +120,7 @@ internal override void SetValue(object obj, object value) #if EMITTERS protected override void EmitGetImpl(CodeEmitter ilgen) { - var typeofByteCodeHelper = DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper"); + var typeofByteCodeHelper = DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper").AsReflection(); ilgen.Emit(OpCodes.Ldstr, Name); ilgen.Emit(OpCodes.Call, typeofByteCodeHelper.GetMethod("GetDotNetEnumField").MakeGenericMethod(DeclaringType.TypeAsBaseType)); } diff --git a/src/IKVM.Runtime/RuntimeSimpleJavaField.cs b/src/IKVM.Runtime/RuntimeSimpleJavaField.cs index 939b274266..b2f055afc0 100644 --- a/src/IKVM.Runtime/RuntimeSimpleJavaField.cs +++ b/src/IKVM.Runtime/RuntimeSimpleJavaField.cs @@ -134,7 +134,7 @@ protected override void EmitUnsafeGetImpl(CodeEmitter il) if (IsFinal) { il.Emit(OpCodes.Ldsflda, fi); - il.Emit(OpCodes.Call, DeclaringType.Context.Resolver.ResolveRuntimeType(typeof(RuntimeSimpleJavaField).FullName).GetMethod(nameof(UnsafeGetImplByRefNoInline), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(fi.FieldType)); + il.Emit(OpCodes.Call, DeclaringType.Context.Resolver.ResolveRuntimeType(typeof(RuntimeSimpleJavaField).FullName).AsReflection().GetMethod(nameof(UnsafeGetImplByRefNoInline), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(fi.FieldType)); } else { diff --git a/src/IKVM.Runtime/Serialization.cs b/src/IKVM.Runtime/Serialization.cs index b0a6d3d0d3..bf40867722 100644 --- a/src/IKVM.Runtime/Serialization.cs +++ b/src/IKVM.Runtime/Serialization.cs @@ -59,13 +59,13 @@ public Serialization(RuntimeContext context) this.context = context ?? throw new ArgumentNullException(nameof(context)); } - CustomAttributeBuilder SerializableAttribute => serializableAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SerializableAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); + CustomAttributeBuilder SerializableAttribute => serializableAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SerializableAttribute).FullName).GetConstructor([]).AsReflection(), []); - CustomAttributeBuilder SecurityCriticalAttribute => securityCriticalAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SecurityCriticalAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); + CustomAttributeBuilder SecurityCriticalAttribute => securityCriticalAttribute ??= new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SecurityCriticalAttribute).FullName).GetConstructor([]).AsReflection(), []); - RuntimeJavaType TypeOfISerializable => typeOfISerializable ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName)); + RuntimeJavaType TypeOfISerializable => typeOfISerializable ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).AsReflection()); - RuntimeJavaType TypeOfIObjectReference => typeofIObjectreference ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName)); + RuntimeJavaType TypeOfIObjectReference => typeofIObjectreference ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection()); RuntimeJavaType TypeOfExternalizable => typeOfExternalizable ??= context.ClassLoaderFactory.LoadClassCritical("java.io.Externalizable"); @@ -172,11 +172,11 @@ internal void AddGetObjectData(TypeBuilder tb) var attr = tb.IsSealed ? MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final : MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; - tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName)); - var getObjectData = tb.DefineMethod(name, attr, null, new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName) }); + tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).AsReflection()); + var getObjectData = tb.DefineMethod(name, attr, null, new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() }); getObjectData.SetCustomAttribute(SecurityCriticalAttribute); context.AttributeHelper.HideFromJava(getObjectData); - tb.DefineMethodOverride(getObjectData, context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).GetMethod("GetObjectData")); + tb.DefineMethodOverride(getObjectData, context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).GetMethod("GetObjectData").AsReflection()); CodeEmitter ilgen = context.CodeEmitterFactory.Create(getObjectData); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); @@ -190,7 +190,7 @@ internal void AddGetObjectData(TypeBuilder tb) MethodBuilder AddConstructor(TypeBuilder tb, RuntimeJavaMethod defaultConstructor, MethodBase serializationConstructor, bool callReadObject) { - MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Family, new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName) }); + MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Family, new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() }); context.AttributeHelper.HideFromJava(ctor); CodeEmitter ilgen = context.CodeEmitterFactory.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); @@ -223,11 +223,11 @@ void AddReadResolve(RuntimeByteCodeJavaType wrapper, TypeBuilder tb) var mw = wrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", false); if (mw != null && !wrapper.IsSubTypeOf(TypeOfIObjectReference)) { - tb.AddInterfaceImplementation(wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName)); - var getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, wrapper.Context.Types.Object, new Type[] { wrapper.Context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName) }); + tb.AddInterfaceImplementation(wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection()); + var getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, wrapper.Context.Types.Object, new Type[] { wrapper.Context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() }); getRealObject.SetCustomAttribute(SecurityCriticalAttribute); wrapper.Context.AttributeHelper.HideFromJava(getRealObject); - tb.DefineMethodOverride(getRealObject, wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod("GetRealObject")); + tb.DefineMethodOverride(getRealObject, wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod("GetRealObject").AsReflection()); var ilgen = context.CodeEmitterFactory.Create(getRealObject); mw.Link(); if (!wrapper.IsFinal) @@ -252,11 +252,11 @@ void AddReadResolve(RuntimeByteCodeJavaType wrapper, TypeBuilder tb) void RemoveReadResolve(TypeBuilder tb) { - tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName)); - MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, context.Types.Object, new Type[] { context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName) }); + tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection()); + MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, context.Types.Object, [context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection()]); getRealObject.SetCustomAttribute(SecurityCriticalAttribute); context.AttributeHelper.HideFromJava(getRealObject); - tb.DefineMethodOverride(getRealObject, context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod("GetRealObject")); + tb.DefineMethodOverride(getRealObject, context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod("GetRealObject").AsReflection()); CodeEmitter ilgen = context.CodeEmitterFactory.Create(getRealObject); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ret); diff --git a/src/IKVM.Runtime/StubGen/StubGenerator.cs b/src/IKVM.Runtime/StubGen/StubGenerator.cs index bb91ff5a47..6c8911eb05 100644 --- a/src/IKVM.Runtime/StubGen/StubGenerator.cs +++ b/src/IKVM.Runtime/StubGen/StubGenerator.cs @@ -222,7 +222,7 @@ void AddRuntimeVisibleAnnotationsAttribute(ClassFileBuilder builder, RuntimeJava /// void AddDeprecatedAttribute(ClassFileBuilder builder, RuntimeJavaType type) { - if (type.TypeAsBaseType.IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName), false)) + if (type.TypeAsBaseType.IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).AsReflection(), false)) builder.Attributes.Deprecated(); } @@ -414,7 +414,7 @@ void AddDeprecatedAttribute(ClassFileBuilder builder, RuntimeJavaType type, Runt // HACK the instancehelper methods are marked as Obsolete (to direct people toward the ikvm.extensions methods instead) // but in the Java world most of them are not deprecated (and to keep the Japi results clean we need to reflect this) // the Java deprecated methods actually have two Obsolete attributes - if (methodBase.IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName), false) && (!methodBase.Name.StartsWith("instancehelper_") || methodBase.DeclaringType.FullName != "java.lang.String" || GetObsoleteCount(methodBase) == 2)) + if (methodBase.IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).AsReflection(), false) && (!methodBase.Name.StartsWith("instancehelper_") || methodBase.DeclaringType.FullName != "java.lang.String" || GetObsoleteCount(methodBase) == 2)) attributes.Deprecated(); } @@ -541,7 +541,7 @@ void AddSignatureAttribute(ClassFileBuilder builder, RuntimeJavaType type, Runti void AddDeprecatedAttribute(ClassFileBuilder builder, RuntimeJavaType type, RuntimeJavaField field, AttributeTableBuilder attributes) { // .NET ObsoleteAttribute translates to Deprecated attribute - if (field.GetField() != null && field.GetField().IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName), false)) + if (field.GetField() != null && field.GetField().IsDefined(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).AsReflection(), false)) attributes.Deprecated(); } @@ -1167,7 +1167,7 @@ object[] UnpackArray(IList list) int GetObsoleteCount(MethodBase mb) { #if EXPORTER - return mb.__GetCustomAttributes(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName), false).Count; + return mb.__GetCustomAttributes(context.Resolver.ResolveCoreType(typeof(ObsoleteAttribute).FullName).AsReflection(), false).Count; #else return mb.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length; #endif @@ -1176,7 +1176,7 @@ int GetObsoleteCount(MethodBase mb) CustomAttributeData GetAnnotationDefault(MethodBase mb) { #if EXPORTER - var attr = CustomAttributeData.__GetCustomAttributes(mb, context.Resolver.ResolveRuntimeType(typeof(Attributes.AnnotationDefaultAttribute).FullName), false); + var attr = CustomAttributeData.__GetCustomAttributes(mb, context.Resolver.ResolveRuntimeType(typeof(Attributes.AnnotationDefaultAttribute).FullName).AsReflection(), false); return attr.Count == 1 ? attr[0] : null; #else foreach (var cad in CustomAttributeData.GetCustomAttributes(mb)) diff --git a/src/IKVM.Runtime/SymbolExtensions.cs b/src/IKVM.Runtime/SymbolExtensions.cs new file mode 100644 index 0000000000..d49d1486e9 --- /dev/null +++ b/src/IKVM.Runtime/SymbolExtensions.cs @@ -0,0 +1,95 @@ +using System; + +using IKVM.CoreLib.Symbols; +using IKVM.CoreLib.Symbols.Reflection; +using IKVM.CoreLib.Symbols.IkvmReflection; + +#if IMPORTER || EXPORTER +using IKVM.Reflection; + +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +#endif + +namespace IKVM.Runtime +{ + + static class SymbolExtensions + { + + public static Assembly AsReflection(this IAssemblySymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionAssemblySymbol)symbol).ReflectionObject; +#else + return ((ReflectionAssemblySymbol)symbol).ReflectionObject; +#endif + } + + public static Type AsReflection(this ITypeSymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionTypeSymbol)symbol).ReflectionObject; +#else + return ((ReflectionTypeSymbol)symbol).ReflectionObject; +#endif + } + + public static ConstructorInfo AsReflection(this IConstructorSymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionConstructorSymbol)symbol).ReflectionObject; +#else + return ((ReflectionConstructorSymbol)symbol).ReflectionObject; +#endif + } + + public static MethodInfo AsReflection(this IMethodSymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionMethodSymbol)symbol).ReflectionObject; +#else + return ((ReflectionMethodSymbol)symbol).ReflectionObject; +#endif + } + + public static FieldInfo AsReflection(this IFieldSymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionFieldSymbol)symbol).ReflectionObject; +#else + return ((ReflectionFieldSymbol)symbol).ReflectionObject; +#endif + } + + public static PropertyInfo AsReflection(this IPropertySymbol symbol) + { + if (symbol == null) + return null; + +#if IMPORTER || EXPORTER + return ((IkvmReflectionPropertySymbol)symbol).ReflectionObject; +#else + return ((ReflectionPropertySymbol)symbol).ReflectionObject; +#endif + } + + } + +} diff --git a/src/IKVM.Runtime/Types.cs b/src/IKVM.Runtime/Types.cs index 7477db06d0..e085932131 100644 --- a/src/IKVM.Runtime/Types.cs +++ b/src/IKVM.Runtime/Types.cs @@ -85,7 +85,7 @@ public Types(RuntimeContext context) /// Type Import(System.Type type) { - return context.Resolver.ResolveCoreType(type.FullName); + return context.Resolver.ResolveCoreType(type.FullName).AsReflection(); } public Type Object => typeOfObject ??= Import(typeof(System.Object)); diff --git a/src/IKVM.Runtime/atomic.cs b/src/IKVM.Runtime/atomic.cs index 3c631b1610..d200ca7211 100644 --- a/src/IKVM.Runtime/atomic.cs +++ b/src/IKVM.Runtime/atomic.cs @@ -150,8 +150,8 @@ public InterlockedMethods(RuntimeContext context) { this.context = context; - var type = context.Resolver.ResolveCoreType(typeof(System.Threading.Interlocked).FullName); - AddInt32 = type.GetMethod("Add", new Type[] { context.Types.Int32.MakeByRefType(), context.Types.Int32 }); + var type = context.Resolver.ResolveCoreType(typeof(System.Threading.Interlocked).FullName).AsReflection(); + AddInt32 = type.GetMethod("Add", [context.Types.Int32.MakeByRefType(), context.Types.Int32]); CompareExchangeInt32 = type.GetMethod("CompareExchange", new Type[] { context.Types.Int32.MakeByRefType(), context.Types.Int32, context.Types.Int32 }); CompareExchangeInt64 = type.GetMethod("CompareExchange", new Type[] { context.Types.Int64.MakeByRefType(), context.Types.Int64, context.Types.Int64 }); foreach (MethodInfo m in type.GetMethods()) diff --git a/src/IKVM.Runtime/compiler.cs b/src/IKVM.Runtime/compiler.cs index 98591bf474..9efe8b7346 100644 --- a/src/IKVM.Runtime/compiler.cs +++ b/src/IKVM.Runtime/compiler.cs @@ -120,11 +120,11 @@ public CompilerFactory(RuntimeContext context, bool bootstrap) public MethodInfo SuppressFillInStackTraceMethod => suppressFillInStackTraceMethod ??= bootstrap ? (MethodInfo)Throwable.GetMethodWrapper("__", "()V", false).GetMethod() : Throwable.TypeAsBaseType.GetMethod("__", Type.EmptyTypes); - public MethodInfo GetTypeFromHandleMethod => getTypeFromHandleMethod ??= context.Types.Type.GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public, null, new Type[] { context.Types.RuntimeTypeHandle }, null); + public MethodInfo GetTypeFromHandleMethod => getTypeFromHandleMethod ??= context.Types.Type.GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public, null, [context.Types.RuntimeTypeHandle], null); public MethodInfo GetTypeMethod => getTypeMethod ??= context.Types.Object.GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); - public MethodInfo KeepAliveMethod => keepAliveMethod ??= context.Resolver.ResolveCoreType(typeof(GC).FullName).GetMethod("KeepAlive", BindingFlags.Static | BindingFlags.Public, null, new Type[] { context.Types.Object }, null); + public MethodInfo KeepAliveMethod => keepAliveMethod ??= context.Resolver.ResolveCoreType(typeof(GC).FullName).AsReflection().GetMethod("KeepAlive", BindingFlags.Static | BindingFlags.Public, null, [context.Types.Object], null); public RuntimeJavaMethod GetClassFromTypeHandle => getClassFromTypeHandle ??= context.ClassLoaderFactory.LoadClassCritical("ikvm.runtime.Util").GetMethodWrapper("getClassFromTypeHandle", "(Lcli.System.RuntimeTypeHandle;)Ljava.lang.Class;", false); @@ -1745,7 +1745,7 @@ void Compile(Block block, int startIndex) } case NormalizedByteCode.__multianewarray: { - var localArray = ilGenerator.UnsafeAllocTempLocal(finish.Context.Resolver.ResolveCoreType(typeof(int).FullName).MakeArrayType()); + var localArray = ilGenerator.UnsafeAllocTempLocal(finish.Context.Resolver.ResolveCoreType(typeof(int).FullName).MakeArrayType().AsReflection()); var localInt = ilGenerator.UnsafeAllocTempLocal(finish.Context.Types.Int32); ilGenerator.EmitLdc_I4(instr.Arg2); ilGenerator.Emit(OpCodes.Newarr, finish.Context.Types.Int32); @@ -2725,7 +2725,7 @@ static class InvokeDynamicBuilder internal static void Emit(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType) { - var typeofOpenIndyCallSite = compiler.finish.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.IndyCallSite`1"); + var typeofOpenIndyCallSite = compiler.finish.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.IndyCallSite`1").AsReflection(); var methodLookup = compiler.finish.Context.ClassLoaderFactory.LoadClassCritical("java.lang.invoke.MethodHandles").GetMethodWrapper("lookup", "()Ljava.lang.invoke.MethodHandles$Lookup;", false); methodLookup.Link(); @@ -3461,7 +3461,7 @@ internal static void EmitLinkToCall(RuntimeContext context, CodeEmitter ilgen, R context.MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType); FromBasic(retType, ilgen); #else - throw new InvalidOperationException(); + throw new InvalidOperationException(); #endif } @@ -3533,7 +3533,7 @@ private void EmitInvoke(CodeEmitter ilgen) Type delegateType = compiler.finish.Context.MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType()); MethodInfo mi = ilgen.Context.ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(delegateType); - var typeofInvokeCache = compiler.finish.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.InvokeCache`1"); + var typeofInvokeCache = compiler.finish.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.InvokeCache`1").AsReflection(); FieldBuilder fb = compiler.finish.DefineMethodHandleInvokeCacheField(typeofInvokeCache.MakeGenericType(delegateType)); ilgen.Emit(OpCodes.Ldloc, temps[0]); if (HasUnloadable(cpi.GetArgTypes(), cpi.GetRetType())) diff --git a/src/IKVM.Runtime/intrinsics.cs b/src/IKVM.Runtime/intrinsics.cs index c6bc71a856..fab8a4e379 100644 --- a/src/IKVM.Runtime/intrinsics.cs +++ b/src/IKVM.Runtime/intrinsics.cs @@ -228,25 +228,25 @@ private static bool IsSafeForGetClassOptimization(RuntimeJavaType tw) private static bool Float_floatToRawIntBits(EmitIntrinsicContext eic) { - EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.FloatConverter"), "ToInt"); + EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.FloatConverter").AsReflection(), "ToInt"); return true; } private static bool Float_intBitsToFloat(EmitIntrinsicContext eic) { - EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.FloatConverter"), "ToFloat"); + EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.FloatConverter").AsReflection(), "ToFloat"); return true; } private static bool Double_doubleToRawLongBits(EmitIntrinsicContext eic) { - EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.DoubleConverter"), "ToLong"); + EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.DoubleConverter").AsReflection(), "ToLong"); return true; } static bool Double_longBitsToDouble(EmitIntrinsicContext eic) { - EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.DoubleConverter"), "ToDouble"); + EmitConversion(eic.Emitter, eic.Method.DeclaringType.Context.Resolver.ResolveRuntimeType("IKVM.Runtime.DoubleConverter").AsReflection(), "ToDouble"); return true; } diff --git a/src/IKVM.Tools.Exporter/FakeTypes.cs b/src/IKVM.Tools.Exporter/FakeTypes.cs index 7a18a5b9da..1cd9d3de55 100644 --- a/src/IKVM.Tools.Exporter/FakeTypes.cs +++ b/src/IKVM.Tools.Exporter/FakeTypes.cs @@ -44,7 +44,7 @@ class FakeTypes public FakeTypes(RuntimeContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); - genericType = context.Resolver.ResolveRuntimeType("IKVM.Runtime.ValueObject`1"); + genericType = context.Resolver.ResolveRuntimeType("IKVM.Runtime.ValueObject`1").AsReflection(); } internal Type GetAttributeType(Type type) diff --git a/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj b/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj index 27009d9583..00fd909a0f 100644 --- a/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj +++ b/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj @@ -93,7 +93,7 @@ - + diff --git a/src/IKVM.Tools.Exporter/ManagedTypeResolver.cs b/src/IKVM.Tools.Exporter/ManagedTypeResolver.cs index 054e1d80b4..d1f2ac4699 100644 --- a/src/IKVM.Tools.Exporter/ManagedTypeResolver.cs +++ b/src/IKVM.Tools.Exporter/ManagedTypeResolver.cs @@ -1,73 +1,75 @@ using System; +using IKVM.CoreLib.Symbols; +using IKVM.CoreLib.Symbols.IkvmReflection; using IKVM.Reflection; -using IKVM.Runtime; using Type = IKVM.Reflection.Type; namespace IKVM.Tools.Exporter { - class ManagedTypeResolver : IManagedTypeResolver - { + class ManagedTypeResolver : ISymbolResolver + { - readonly StaticCompiler compiler; - readonly Assembly baseAssembly; + readonly StaticCompiler compiler; + readonly Assembly baseAssembly; + readonly IkvmReflectionSymbolContext context = new(); - /// - /// Initializes a new instance. - /// - /// - /// - public ManagedTypeResolver(StaticCompiler compiler, Assembly baseAssembly) - { - this.compiler = compiler ?? throw new ArgumentNullException(nameof(compiler)); - this.baseAssembly = baseAssembly; - } + /// + /// Initializes a new instance. + /// + /// + /// + public ManagedTypeResolver(StaticCompiler compiler, Assembly baseAssembly) + { + this.compiler = compiler ?? throw new ArgumentNullException(nameof(compiler)); + this.baseAssembly = baseAssembly; + } - /// - /// Attempts to resolve the base Java assembly. - /// - /// - public Assembly ResolveBaseAssembly() - { - return baseAssembly; - } + /// + /// Attempts to resolve the base Java assembly. + /// + /// + public IAssemblySymbol ResolveBaseAssembly() + { + return baseAssembly != null ? context.GetOrCreateAssemblySymbol(baseAssembly) : null; + } - /// - /// Attempts to resolve an assembly from one of the assembly sources. - /// - /// - /// - public Assembly ResolveAssembly(string assemblyName) - { - return compiler.Load(assemblyName); - } + /// + /// Attempts to resolve an assembly from one of the assembly sources. + /// + /// + /// + public IAssemblySymbol ResolveAssembly(string assemblyName) + { + return compiler.Load(assemblyName) is { } a ? context.GetOrCreateAssemblySymbol(a) : null; + } - /// - /// Attempts to resolve a type from one of the assembly sources. - /// - /// - /// - public Type ResolveCoreType(string typeName) - { - foreach (var assembly in compiler.Universe.GetAssemblies()) - if (assembly.GetType(typeName) is Type t) - return t; + /// + /// Attempts to resolve a type from one of the assembly sources. + /// + /// + /// + public ITypeSymbol ResolveCoreType(string typeName) + { + foreach (var assembly in compiler.Universe.GetAssemblies()) + if (assembly.GetType(typeName) is Type t) + return context.GetOrCreateTypeSymbol(t); - return null; - } + return null; + } - /// - /// Attempts to resolve a type from the IKVM runtime assembly. - /// - /// - /// - public Type ResolveRuntimeType(string typeName) - { - return compiler.GetRuntimeType(typeName); - } + /// + /// Attempts to resolve a type from the IKVM runtime assembly. + /// + /// + /// + public ITypeSymbol ResolveRuntimeType(string typeName) + { + return compiler.GetRuntimeType(typeName) is { } t ? context.GetOrCreateTypeSymbol(t) : null; + } - } + } } diff --git a/src/IKVM.Tools.Exporter/RuntimeBootstrapClassLoader.cs b/src/IKVM.Tools.Exporter/RuntimeBootstrapClassLoader.cs index 21cf1d0d51..12948e0eea 100644 --- a/src/IKVM.Tools.Exporter/RuntimeBootstrapClassLoader.cs +++ b/src/IKVM.Tools.Exporter/RuntimeBootstrapClassLoader.cs @@ -39,14 +39,14 @@ internal RuntimeBootstrapClassLoader(RuntimeContext context) : base(context, CodeGenOptions.None, null) { var javaLangObject = new RuntimeStubJavaType(context, Modifiers.Public, "java.lang.Object", null, true); - SetRemappedType(Context.Resolver.ResolveCoreType(typeof(object).FullName), javaLangObject); - SetRemappedType(Context.Resolver.ResolveCoreType(typeof(string).FullName), new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Final, "java.lang.String", javaLangObject, true)); - SetRemappedType(Context.Resolver.ResolveCoreType(typeof(Exception).FullName), new RuntimeStubJavaType(context, Modifiers.Public, "java.lang.Throwable", javaLangObject, true)); - SetRemappedType(Context.Resolver.ResolveCoreType(typeof(IComparable).FullName), new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.Comparable", null, true)); - + SetRemappedType(Context.Resolver.ResolveCoreType(typeof(object).FullName).AsReflection(), javaLangObject); + SetRemappedType(Context.Resolver.ResolveCoreType(typeof(string).FullName).AsReflection(), new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Final, "java.lang.String", javaLangObject, true)); + SetRemappedType(Context.Resolver.ResolveCoreType(typeof(Exception).FullName).AsReflection(), new RuntimeStubJavaType(context, Modifiers.Public, "java.lang.Throwable", javaLangObject, true)); + SetRemappedType(Context.Resolver.ResolveCoreType(typeof(IComparable).FullName).AsReflection(), new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.Comparable", null, true)); + var autoCloseable = new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.AutoCloseable", null, true); - autoCloseable.SetMethods(new [] { new RuntimeSimpleCallJavaMethod(autoCloseable, "close", "()V", Context.Resolver.ResolveCoreType(typeof(IDisposable).FullName).GetMethod("Dispose"), context.PrimitiveJavaTypeFactory.VOID, Array.Empty(), Modifiers.Public | Modifiers.Abstract, MemberFlags.None, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt) }); - SetRemappedType(Context.Resolver.ResolveCoreType(typeof(IDisposable).FullName), autoCloseable); + autoCloseable.SetMethods(new[] { new RuntimeSimpleCallJavaMethod(autoCloseable, "close", "()V", Context.Resolver.ResolveCoreType(typeof(IDisposable).FullName).GetMethod("Dispose").AsReflection(), context.PrimitiveJavaTypeFactory.VOID, Array.Empty(), Modifiers.Public | Modifiers.Abstract, MemberFlags.None, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt) }); + SetRemappedType(Context.Resolver.ResolveCoreType(typeof(IDisposable).FullName).AsReflection(), autoCloseable); RegisterInitiatingLoader(new RuntimeStubJavaType(context, Modifiers.Public, "java.lang.Enum", javaLangObject, false)); RegisterInitiatingLoader(new RuntimeStubJavaType(context, Modifiers.Public | Modifiers.Abstract | Modifiers.Interface, "java.lang.annotation.Annotation", null, false)); diff --git a/src/IKVM.Tools.Importer/ImportClassLoader.cs b/src/IKVM.Tools.Importer/ImportClassLoader.cs index b1797c5cf4..d3251bd5fc 100644 --- a/src/IKVM.Tools.Importer/ImportClassLoader.cs +++ b/src/IKVM.Tools.Importer/ImportClassLoader.cs @@ -547,13 +547,13 @@ void SetMain(RuntimeJavaType type, PEFileKinds target, IDictionary 0) { - var environmentType = Context.Resolver.ResolveCoreType(typeof(Environment).FullName); - var environmentExpandMethod = environmentType.GetMethod(nameof(Environment.ExpandEnvironmentVariables), new[] { Context.Types.String }); - var dictionaryType = Context.Resolver.ResolveCoreType(typeof(Dictionary<,>).FullName).MakeGenericType(Context.Types.String, Context.Types.String); - var dictionaryAddMethod = dictionaryType.GetMethod("Add", new[] { Context.Types.String, Context.Types.String }); + var environmentType = Context.Resolver.ResolveCoreType(typeof(Environment).FullName).AsReflection(); + var environmentExpandMethod = environmentType.GetMethod(nameof(Environment.ExpandEnvironmentVariables), [Context.Types.String]); + var dictionaryType = Context.Resolver.ResolveCoreType(typeof(Dictionary<,>).FullName).AsReflection().MakeGenericType(Context.Types.String, Context.Types.String); + var dictionaryAddMethod = dictionaryType.GetMethod("Add", [Context.Types.String, Context.Types.String]); ilgen.EmitLdc_I4(properties.Count); - ilgen.Emit(OpCodes.Newobj, dictionaryType.GetConstructor(new[] { Context.Types.Int32 })); + ilgen.Emit(OpCodes.Newobj, dictionaryType.GetConstructor([Context.Types.Int32])); foreach (var kvp in properties) { @@ -575,7 +575,7 @@ void SetMain(RuntimeJavaType type, PEFileKinds target, IDictionary remappedType if (hasfail) { ilgen.MarkLabel(fail); - ilgen.ThrowException(Context.Resolver.ResolveCoreType(typeof(InvalidCastException).FullName)); + ilgen.ThrowException(Context.Resolver.ResolveCoreType(typeof(InvalidCastException).FullName).AsReflection()); } ilgen.DoEmit(); @@ -2277,7 +2277,7 @@ internal void Emit(MapXml.CodeGenContext context, CodeEmitter ilgen) for (int i = 0; i < map.Length; i++) { ilgen.Emit(OpCodes.Dup); - ilgen.Emit(OpCodes.Ldtoken, rcontext.Resolver.ResolveCoreType(map[i].Source)); + ilgen.Emit(OpCodes.Ldtoken, rcontext.Resolver.ResolveCoreType(map[i].Source).AsReflection()); ilgen.Emit(OpCodes.Call, rcontext.CompilerFactory.GetTypeFromHandleMethod); ilgen.Emit(OpCodes.Ceq); var label = ilgen.DefineLabel(); @@ -2858,8 +2858,8 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, IDiag if (options.bootstrap == false) { - allReferencesAreStrongNamed &= IsSigned(context.Resolver.ResolveBaseAssembly()); - loader.AddReference(context.AssemblyClassLoaderFactory.FromAssembly(context.Resolver.ResolveBaseAssembly())); + allReferencesAreStrongNamed &= IsSigned(context.Resolver.ResolveBaseAssembly().AsReflection()); + loader.AddReference(context.AssemblyClassLoaderFactory.FromAssembly(context.Resolver.ResolveBaseAssembly().AsReflection())); } if ((options.keyPair != null || options.publicKey != null) && !allReferencesAreStrongNamed) @@ -2875,7 +2875,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, IDiag if (options.bootstrap == false) { loader.fakeTypes = context.FakeTypes; - loader.fakeTypes.Load(context.Resolver.ResolveBaseAssembly()); + loader.fakeTypes.Load(context.Resolver.ResolveBaseAssembly().AsReflection()); } return 0; @@ -2883,7 +2883,7 @@ static int CreateCompiler(RuntimeContext context, StaticCompiler compiler, IDiag static bool IsBaseAssembly(RuntimeContext context, Assembly asm) { - return asm.IsDefined(context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.RemappedClassAttribute).FullName), false); + return asm.IsDefined(context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.RemappedClassAttribute).FullName).AsReflection(), false); } private static Assembly LoadReferencedAssembly(StaticCompiler compiler, string r) @@ -3014,7 +3014,7 @@ int CompilePass3() _ => throw new NotImplementedException(), }; - SetMain(wrapper, state.target, state.props, state.noglobbing, apartmentAttributeType); + SetMain(wrapper, state.target, state.props, state.noglobbing, apartmentAttributeType.AsReflection()); } // complete map @@ -3045,7 +3045,7 @@ int CompilePass3() // configure Win32 file version if (state.fileversion != null) { - var filever = new CustomAttributeBuilder(Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyFileVersionAttribute).FullName).GetConstructor(new Type[] { Context.Types.String }), new object[] { state.fileversion }); + var filever = new CustomAttributeBuilder(Context.Resolver.ResolveCoreType(typeof(System.Reflection.AssemblyFileVersionAttribute).FullName).AsReflection().GetConstructor([Context.Types.String]), [state.fileversion]); assemblyBuilder.SetCustomAttribute(filever); } @@ -3090,7 +3090,7 @@ int CompilePass3() throw new FatalCompilerErrorException(DiagnosticEvent.ClassLoaderConstructorMissing()); // 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); + var ci = Context.Resolver.ResolveRuntimeType(typeof(CustomAssemblyClassLoaderAttribute).FullName).AsReflection().GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { Context.Types.Type }, null); assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(ci, new object[] { classLoaderType.TypeAsTBD })); // the class loader type defines a module initialize method, ensure we call it upon module load @@ -3100,9 +3100,9 @@ int CompilePass3() moduleInitBuilders.Add((mb, il) => { il.Emit(OpCodes.Ldtoken, mb); - il.Emit(OpCodes.Call, Context.Resolver.ResolveCoreType(typeof(System.Reflection.MethodBase).FullName).GetMethod("GetMethodFromHandle", new[] { Context.Resolver.ResolveCoreType(typeof(RuntimeMethodHandle).FullName) })); - il.Emit(OpCodes.Callvirt, Context.Resolver.ResolveCoreType(typeof(System.Reflection.MemberInfo).FullName).GetProperty("Module").GetGetMethod()); - il.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper").GetMethod("InitializeModule")); + il.Emit(OpCodes.Call, Context.Resolver.ResolveCoreType(typeof(System.Reflection.MethodBase).FullName).GetMethod("GetMethodFromHandle", new[] { Context.Resolver.ResolveCoreType(typeof(RuntimeMethodHandle).FullName) }).AsReflection()); + il.Emit(OpCodes.Callvirt, Context.Resolver.ResolveCoreType(typeof(System.Reflection.MemberInfo).FullName).GetProperty("Module").GetGetMethod().AsReflection()); + il.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType("IKVM.Runtime.ByteCodeHelper").GetMethod("InitializeModule").AsReflection()); }); } } diff --git a/src/IKVM.Tools.Importer/ImportContext.cs b/src/IKVM.Tools.Importer/ImportContext.cs index 0bb36283f2..1ef1ea8e7a 100644 --- a/src/IKVM.Tools.Importer/ImportContext.cs +++ b/src/IKVM.Tools.Importer/ImportContext.cs @@ -31,6 +31,7 @@ Jeroen Frijters using IKVM.ByteCode; using IKVM.CoreLib.Diagnostics; +using IKVM.CoreLib.Symbols; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -184,14 +185,14 @@ static int Compile(ImportOptions options) var services = new ServiceCollection(); services.AddToolsDiagnostics(); services.AddSingleton(p => GetDiagnostics(p, rootTarget, options.Log)); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); using var provider = services.BuildServiceProvider(); var diagnostics = provider.GetRequiredService(); var compiler = provider.GetRequiredService(); var targets = new List(); - var context = new RuntimeContext(new RuntimeContextOptions(), diagnostics, provider.GetRequiredService(), options.Bootstrap, compiler); + var context = new RuntimeContext(new RuntimeContextOptions(), diagnostics, provider.GetRequiredService(), options.Bootstrap, compiler); compiler.rootTarget = rootTarget; var importer = new ImportContext(); diff --git a/src/IKVM.Tools.Importer/ManagedResolver.cs b/src/IKVM.Tools.Importer/ManagedResolver.cs index 496205ff9e..2b6ec0e4e6 100644 --- a/src/IKVM.Tools.Importer/ManagedResolver.cs +++ b/src/IKVM.Tools.Importer/ManagedResolver.cs @@ -23,17 +23,19 @@ Jeroen Frijters */ using System; -using IKVM.Reflection; -using IKVM.Runtime; +using IKVM.CoreLib.Symbols; +using IKVM.CoreLib.Symbols.IkvmReflection; using Type = IKVM.Reflection.Type; namespace IKVM.Tools.Importer { - class ManagedResolver : IManagedTypeResolver + + class ManagedResolver : ISymbolResolver { readonly StaticCompiler compiler; + readonly IkvmReflectionSymbolContext context = new(); /// /// Initializes a new instance. @@ -44,28 +46,28 @@ public ManagedResolver(StaticCompiler compiler) this.compiler = compiler ?? throw new ArgumentNullException(nameof(compiler)); } - public Assembly ResolveBaseAssembly() + public IAssemblySymbol ResolveBaseAssembly() { - return compiler.baseAssembly; + return compiler.baseAssembly != null ? context.GetOrCreateAssemblySymbol(compiler.baseAssembly) : null; } - public Assembly ResolveAssembly(string assemblyName) + public IAssemblySymbol ResolveAssembly(string assemblyName) { - return compiler.Universe.Load(assemblyName); + return compiler.Universe.Load(assemblyName) is { } a ? context.GetOrCreateAssemblySymbol(a) : null; } - public Type ResolveCoreType(string typeName) + public ITypeSymbol ResolveCoreType(string typeName) { foreach (var assembly in compiler.Universe.GetAssemblies()) if (assembly.GetType(typeName) is Type t) - return t; + return context.GetOrCreateTypeSymbol(t); return null; } - public Type ResolveRuntimeType(string typeName) + public ITypeSymbol ResolveRuntimeType(string typeName) { - return compiler.GetRuntimeType(typeName); + return compiler.GetRuntimeType(typeName) is { } t ? context.GetOrCreateTypeSymbol(t) : null; } } diff --git a/src/IKVM.Tools.Importer/MapXml/Call.cs b/src/IKVM.Tools.Importer/MapXml/Call.cs index 6771ddd455..f0f135ef52 100644 --- a/src/IKVM.Tools.Importer/MapXml/Call.cs +++ b/src/IKVM.Tools.Importer/MapXml/Call.cs @@ -100,8 +100,9 @@ internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen if (Name == ".ctor") { Debug.Assert(Class == null && Type != null); - Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); - ConstructorInfo ci = context.ClassLoader.Context.Resolver.ResolveCoreType(Type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); + + var argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); + var ci = context.ClassLoader.Context.Resolver.ResolveCoreType(Type).AsReflection().GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); if (ci == null) { throw new InvalidOperationException("Missing .ctor: " + Type + "..ctor" + Sig); @@ -195,17 +196,17 @@ internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen argTypes = new Type[types.Length]; for (int i = 0; i < types.Length; i++) { - argTypes[i] = context.ClassLoader.Context.Resolver.ResolveCoreType(types[i]); + argTypes[i] = context.ClassLoader.Context.Resolver.ResolveCoreType(types[i]).AsReflection(); } } - Type ti = context.ClassLoader.Context.Resolver.ResolveCoreType(Type); + var ti = context.ClassLoader.Context.Resolver.ResolveCoreType(Type).AsReflection(); if (ti == null) { throw new InvalidOperationException("Missing type: " + Type); } - MethodInfo mi = ti.GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); + var mi = ti.GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); if (mi == null) { var ta = argTypes.Select(i => i.AssemblyQualifiedName).ToArray(); diff --git a/src/IKVM.Tools.Importer/MapXml/Redirect.cs b/src/IKVM.Tools.Importer/MapXml/Redirect.cs index cdfea759d3..57951eaef6 100644 --- a/src/IKVM.Tools.Importer/MapXml/Redirect.cs +++ b/src/IKVM.Tools.Importer/MapXml/Redirect.cs @@ -85,7 +85,7 @@ internal void Emit(RuntimeClassLoader loader, CodeEmitter ilgen) // HACK if the class name contains a comma, we assume it is a .NET type if (Type != null) { - var type = loader.Context.Resolver.ResolveCoreType(Type); + var type = loader.Context.Resolver.ResolveCoreType(Type).AsReflection(); var mi = type.GetMethod(Name, redirParamTypes); if (mi == null) { diff --git a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs index b30c549e16..37c22bb2a1 100644 --- a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs +++ b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs @@ -828,7 +828,7 @@ protected override void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldtoken, typeBuilder); ilgen.Emit(OpCodes.Ldarg_1); - ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static)); + ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).AsReflection().GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static)); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); @@ -881,7 +881,7 @@ protected override void FinishGhost(TypeBuilder typeBuilder, RuntimeJavaMethod[] ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldtoken, typeBuilder); ilgen.Emit(OpCodes.Ldarg_1); - ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static)); + ilgen.Emit(OpCodes.Call, Context.Resolver.ResolveRuntimeType(typeof(IKVM.Runtime.GhostTag).FullName).AsReflection().GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static)); ilgen.MarkLabel(end); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); diff --git a/src/dist-tests/dist-tests.csproj b/src/dist-tests/dist-tests.csproj index 019371a15d..00db3fc0c7 100644 --- a/src/dist-tests/dist-tests.csproj +++ b/src/dist-tests/dist-tests.csproj @@ -9,8 +9,10 @@ - + + + diff --git a/src/ikvmc/Properties/launchSettings.json b/src/ikvmc/Properties/launchSettings.json index b3249c1914..31d9cf8012 100644 --- a/src/ikvmc/Properties/launchSettings.json +++ b/src/ikvmc/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "ikvmc": { "commandName": "Project", - "commandLineArgs": "@C:\\Users\\jhaltom\\AppData\\Local\\Temp\\31187b7c-3061-4bf2-96d0-c1cb9fa41ecb\\helloworld\\ikvmc.rsp" + "commandLineArgs": "@D:\\ikvm\\src\\IKVM.Java\\obj\\Debug\\net8.0\\IKVM.Java.ikvmc.rsp" } } }