|
|
@ -1,7 +1,7 @@ |
|
|
using System; |
|
|
using System; |
|
|
|
|
|
using System.Collections.Generic; |
|
|
using System.IO; |
|
|
using System.IO; |
|
|
using System.Linq; |
|
|
using System.Linq; |
|
|
using System.Reflection; |
|
|
|
|
|
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions; |
|
|
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions; |
|
|
using Microsoft.Build.Framework; |
|
|
using Microsoft.Build.Framework; |
|
|
using Mono.Cecil; |
|
|
using Mono.Cecil; |
|
|
@ -21,6 +21,8 @@ namespace Avalonia.Build.Tasks |
|
|
{ |
|
|
{ |
|
|
public static partial class XamlCompilerTaskExecutor |
|
|
public static partial class XamlCompilerTaskExecutor |
|
|
{ |
|
|
{ |
|
|
|
|
|
private const string CompiledAvaloniaXamlNamespace = "CompiledAvaloniaXaml"; |
|
|
|
|
|
|
|
|
static bool CheckXamlName(IResource r) => r.Name.ToLowerInvariant().EndsWith(".xaml") |
|
|
static bool CheckXamlName(IResource r) => r.Name.ToLowerInvariant().EndsWith(".xaml") |
|
|
|| r.Name.ToLowerInvariant().EndsWith(".paml") |
|
|
|| r.Name.ToLowerInvariant().EndsWith(".paml") |
|
|
|| r.Name.ToLowerInvariant().EndsWith(".axaml"); |
|
|
|| r.Name.ToLowerInvariant().EndsWith(".axaml"); |
|
|
@ -37,43 +39,58 @@ namespace Avalonia.Build.Tasks |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static CompileResult Compile(IBuildEngine engine, string input, string[] references, |
|
|
public static CompileResult Compile(IBuildEngine engine, |
|
|
string projectDirectory, |
|
|
string input, string output, |
|
|
string output, bool verifyIl, bool defaultCompileBindings, MessageImportance logImportance, string strongNameKey, |
|
|
string refInput, string refOutput, |
|
|
|
|
|
string[] references, string projectDirectory, |
|
|
|
|
|
bool verifyIl, bool defaultCompileBindings, MessageImportance logImportance, string strongNameKey, |
|
|
bool skipXamlCompilation) |
|
|
bool skipXamlCompilation) |
|
|
{ |
|
|
{ |
|
|
return Compile(engine, input, references, projectDirectory, output, verifyIl, defaultCompileBindings, logImportance, strongNameKey, skipXamlCompilation, debuggerLaunch:false); |
|
|
return Compile(engine, input, output, refInput, refOutput, references, projectDirectory, verifyIl, defaultCompileBindings, logImportance, strongNameKey, skipXamlCompilation, debuggerLaunch:false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
internal static CompileResult Compile(IBuildEngine engine, string input, string[] references, |
|
|
internal static CompileResult Compile(IBuildEngine engine, |
|
|
string projectDirectory, |
|
|
string input, string output, |
|
|
string output, bool verifyIl, bool defaultCompileBindings, MessageImportance logImportance, string strongNameKey, bool skipXamlCompilation, bool debuggerLaunch) |
|
|
string refInput, string refOutput, |
|
|
|
|
|
string[] references, string projectDirectory, |
|
|
|
|
|
bool verifyIl, bool defaultCompileBindings, MessageImportance logImportance, string strongNameKey, bool skipXamlCompilation, bool debuggerLaunch) |
|
|
{ |
|
|
{ |
|
|
try |
|
|
try |
|
|
{ |
|
|
{ |
|
|
var typeSystem = new CecilTypeSystem( |
|
|
references = references.Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll")).ToArray(); |
|
|
references.Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll")), |
|
|
var typeSystem = new CecilTypeSystem(references, input); |
|
|
input); |
|
|
var refTypeSystem = !string.IsNullOrWhiteSpace(refInput) && File.Exists(refInput) ? new CecilTypeSystem(references, refInput) : null; |
|
|
|
|
|
|
|
|
var asm = typeSystem.TargetAssemblyDefinition; |
|
|
var asm = typeSystem.TargetAssemblyDefinition; |
|
|
|
|
|
var refAsm = refTypeSystem?.TargetAssemblyDefinition; |
|
|
if (!skipXamlCompilation) |
|
|
if (!skipXamlCompilation) |
|
|
{ |
|
|
{ |
|
|
var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, defaultCompileBindings, |
|
|
var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, defaultCompileBindings, logImportance, debuggerLaunch); |
|
|
logImportance, debuggerLaunch); |
|
|
if (compileRes == null) |
|
|
if (compileRes == null) |
|
|
return new CompileResult(true); |
|
|
return new CompileResult(true); |
|
|
if (compileRes == false) |
|
|
if (compileRes == false) |
|
|
return new CompileResult(false); |
|
|
return new CompileResult(false); |
|
|
|
|
|
} |
|
|
if (refTypeSystem is not null) |
|
|
|
|
|
{ |
|
|
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols }; |
|
|
var refCompileRes = CompileCoreForRefAssembly(engine, typeSystem, refTypeSystem); |
|
|
if (!string.IsNullOrWhiteSpace(strongNameKey)) |
|
|
if (refCompileRes == false) |
|
|
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); |
|
|
return new CompileResult(false); |
|
|
|
|
|
} |
|
|
asm.Write(output, writerParameters); |
|
|
} |
|
|
|
|
|
|
|
|
return new CompileResult(true, true); |
|
|
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols }; |
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(strongNameKey)) |
|
|
|
|
|
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); |
|
|
|
|
|
|
|
|
|
|
|
asm.Write(output, writerParameters); |
|
|
|
|
|
|
|
|
|
|
|
var refWriterParameters = new WriterParameters { WriteSymbols = false }; |
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(strongNameKey)) |
|
|
|
|
|
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); |
|
|
|
|
|
refAsm?.Write(refOutput, refWriterParameters); |
|
|
|
|
|
|
|
|
|
|
|
return new CompileResult(true, true); |
|
|
} |
|
|
} |
|
|
catch (Exception ex) |
|
|
catch (Exception ex) |
|
|
{ |
|
|
{ |
|
|
@ -122,6 +139,7 @@ namespace Avalonia.Build.Tasks |
|
|
if (avares.Resources.Count(CheckXamlName) == 0) |
|
|
if (avares.Resources.Count(CheckXamlName) == 0) |
|
|
// Nothing to do
|
|
|
// Nothing to do
|
|
|
return null; |
|
|
return null; |
|
|
|
|
|
|
|
|
if (typeSystem.FindType("System.Reflection.AssemblyMetadataAttribute") is {} asmMetadata) |
|
|
if (typeSystem.FindType("System.Reflection.AssemblyMetadataAttribute") is {} asmMetadata) |
|
|
{ |
|
|
{ |
|
|
var ctor = asm.MainModule.ImportReference(typeSystem.GetTypeReference(asmMetadata).Resolve() |
|
|
var ctor = asm.MainModule.ImportReference(typeSystem.GetTypeReference(asmMetadata).Resolve() |
|
|
@ -131,14 +149,14 @@ namespace Avalonia.Build.Tasks |
|
|
var arg2 = new CustomAttributeArgument(strType, defaultCompileBindings.ToString()); |
|
|
var arg2 = new CustomAttributeArgument(strType, defaultCompileBindings.ToString()); |
|
|
asm.CustomAttributes.Add(new CustomAttribute(ctor) { ConstructorArguments = { arg1, arg2 } }); |
|
|
asm.CustomAttributes.Add(new CustomAttribute(ctor) { ConstructorArguments = { arg1, arg2 } }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers", |
|
|
var clrPropertiesDef = new TypeDefinition(CompiledAvaloniaXamlNamespace, "XamlIlHelpers", |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
asm.MainModule.Types.Add(clrPropertiesDef); |
|
|
asm.MainModule.Types.Add(clrPropertiesDef); |
|
|
var indexerAccessorClosure = new TypeDefinition("CompiledAvaloniaXaml", "!IndexerAccessorFactoryClosure", |
|
|
var indexerAccessorClosure = new TypeDefinition(CompiledAvaloniaXamlNamespace, "!IndexerAccessorFactoryClosure", |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
asm.MainModule.Types.Add(indexerAccessorClosure); |
|
|
asm.MainModule.Types.Add(indexerAccessorClosure); |
|
|
var trampolineBuilder = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlTrampolines", |
|
|
var trampolineBuilder = new TypeDefinition(CompiledAvaloniaXamlNamespace, "XamlIlTrampolines", |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
asm.MainModule.Types.Add(trampolineBuilder); |
|
|
asm.MainModule.Types.Add(trampolineBuilder); |
|
|
|
|
|
|
|
|
@ -154,7 +172,7 @@ namespace Avalonia.Build.Tasks |
|
|
new DeterministicIdGenerator()); |
|
|
new DeterministicIdGenerator()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var contextDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlContext", |
|
|
var contextDef = new TypeDefinition(CompiledAvaloniaXamlNamespace, "XamlIlContext", |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
asm.MainModule.Types.Add(contextDef); |
|
|
asm.MainModule.Types.Add(contextDef); |
|
|
|
|
|
|
|
|
@ -175,8 +193,8 @@ namespace Avalonia.Build.Tasks |
|
|
typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods |
|
|
typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods |
|
|
.First(x => x.Name == "CreateRootServiceProviderV2")); |
|
|
.First(x => x.Name == "CreateRootServiceProviderV2")); |
|
|
|
|
|
|
|
|
var loaderDispatcherDef = new TypeDefinition("CompiledAvaloniaXaml", "!XamlLoader", |
|
|
var loaderDispatcherDef = new TypeDefinition(CompiledAvaloniaXamlNamespace, "!XamlLoader", |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class | TypeAttributes.Public, asm.MainModule.TypeSystem.Object); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor) |
|
|
loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor) |
|
|
@ -204,8 +222,8 @@ namespace Avalonia.Build.Tasks |
|
|
|
|
|
|
|
|
bool CompileGroup(IResourceGroup group) |
|
|
bool CompileGroup(IResourceGroup group) |
|
|
{ |
|
|
{ |
|
|
var typeDef = new TypeDefinition("CompiledAvaloniaXaml", "!"+ group.Name, |
|
|
var typeDef = new TypeDefinition(CompiledAvaloniaXamlNamespace, "!"+ group.Name, |
|
|
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); |
|
|
TypeAttributes.Class | TypeAttributes.Public, asm.MainModule.TypeSystem.Object); |
|
|
|
|
|
|
|
|
typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor) |
|
|
typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor) |
|
|
{ |
|
|
{ |
|
|
@ -213,7 +231,9 @@ namespace Avalonia.Build.Tasks |
|
|
}); |
|
|
}); |
|
|
asm.MainModule.Types.Add(typeDef); |
|
|
asm.MainModule.Types.Add(typeDef); |
|
|
var builder = typeSystem.CreateTypeBuilder(typeDef); |
|
|
var builder = typeSystem.CreateTypeBuilder(typeDef); |
|
|
|
|
|
|
|
|
|
|
|
var populateMethodsToTransform = new List<(MethodDefinition populateMethod, string resourceFilePath)>(); |
|
|
|
|
|
|
|
|
foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x=>x.FilePath.ToLowerInvariant())) |
|
|
foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x=>x.FilePath.ToLowerInvariant())) |
|
|
{ |
|
|
{ |
|
|
try |
|
|
try |
|
|
@ -279,13 +299,24 @@ namespace Avalonia.Build.Tasks |
|
|
populateBuilder.DefineDelegateSubType(closureName, false, returnType, parameterTypes), |
|
|
populateBuilder.DefineDelegateSubType(closureName, false, returnType, parameterTypes), |
|
|
res.Uri, res |
|
|
res.Uri, res |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve() |
|
|
|
|
|
.Methods.First(m => m.Name == populateName); |
|
|
|
|
|
|
|
|
|
|
|
// Include populate method and all nested methods/closures used in the populate method,
|
|
|
|
|
|
// So we can replace style/resource includes in all of them.
|
|
|
|
|
|
populateMethodsToTransform.Add((compiledPopulateMethod, res.FilePath)); |
|
|
|
|
|
populateMethodsToTransform.AddRange(compiledPopulateMethod.Body.Instructions |
|
|
|
|
|
.Where(b => b.OpCode == OpCodes.Call || b.OpCode == OpCodes.Callvirt || b.OpCode == OpCodes.Ldftn) |
|
|
|
|
|
.Select(b => b.Operand) |
|
|
|
|
|
.OfType<MethodReference>() |
|
|
|
|
|
.Where(m => compiledPopulateMethod.DeclaringType.NestedTypes.Contains(m.DeclaringType)) |
|
|
|
|
|
.Select(m => m.Resolve()) |
|
|
|
|
|
.Where(m => m.HasBody) |
|
|
|
|
|
.Select(m => (m, res.FilePath))); |
|
|
|
|
|
|
|
|
if (classTypeDefinition != null) |
|
|
if (classTypeDefinition != null) |
|
|
{ |
|
|
{ |
|
|
var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve() |
|
|
|
|
|
.Methods.First(m => m.Name == populateName); |
|
|
|
|
|
|
|
|
|
|
|
var designLoaderFieldType = typeSystem |
|
|
var designLoaderFieldType = typeSystem |
|
|
.GetType("System.Action`1") |
|
|
.GetType("System.Action`1") |
|
|
.MakeGenericType(typeSystem.GetType("System.Object")); |
|
|
.MakeGenericType(typeSystem.GetType("System.Object")); |
|
|
@ -435,8 +466,94 @@ namespace Avalonia.Build.Tasks |
|
|
} |
|
|
} |
|
|
res.Remove(); |
|
|
res.Remove(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var (populateMethod, resourceFilePath) in populateMethodsToTransform) |
|
|
|
|
|
{ |
|
|
|
|
|
foreach (var instruction in populateMethod.Body.Instructions.ToArray()) |
|
|
|
|
|
{ |
|
|
|
|
|
const string resolveStyleIncludeName = "ResolveStyleInclude"; |
|
|
|
|
|
const string resolveResourceInclude = "ResolveResourceInclude"; |
|
|
|
|
|
if (instruction.OpCode == OpCodes.Call |
|
|
|
|
|
&& instruction.Operand is MethodReference |
|
|
|
|
|
{ |
|
|
|
|
|
Name: resolveStyleIncludeName or resolveResourceInclude, |
|
|
|
|
|
DeclaringType: { Name: "XamlIlRuntimeHelpers" } |
|
|
|
|
|
}) |
|
|
|
|
|
{ |
|
|
|
|
|
int lineNumber = 0, linePosition = 0; |
|
|
|
|
|
bool instructionsModified = false; |
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
|
|
|
var assetSource = (string)instruction.Previous.Previous.Previous.Operand; |
|
|
|
|
|
lineNumber = Convert.ToInt32(instruction.Previous.Previous.Operand); |
|
|
|
|
|
linePosition = Convert.ToInt32(instruction.Previous.Operand); |
|
|
|
|
|
|
|
|
|
|
|
var index = populateMethod.Body.Instructions.IndexOf(instruction); |
|
|
|
|
|
|
|
|
|
|
|
assetSource = assetSource.Replace("avares://", ""); |
|
|
|
|
|
|
|
|
|
|
|
var assemblyNameSeparator = assetSource.IndexOf('/'); |
|
|
|
|
|
var fileNameSeparator = assetSource.LastIndexOf('/'); |
|
|
|
|
|
if (assemblyNameSeparator < 0 || fileNameSeparator < 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new InvalidProgramException( |
|
|
|
|
|
$"Invalid asset source \"{assetSource}\". It must contain assembly name and relative path."); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var assetAssemblyName = assetSource.Substring(0, assemblyNameSeparator); |
|
|
|
|
|
var assetAssembly = typeSystem.FindAssembly(assetAssemblyName) |
|
|
|
|
|
?? throw new InvalidProgramException($"Unable to resolve assembly \"{assetAssemblyName}\""); |
|
|
|
|
|
|
|
|
|
|
|
var fileName = Path.GetFileNameWithoutExtension(assetSource.Replace('/', '.')); |
|
|
|
|
|
if (assetAssembly.FindType(fileName) is { } type |
|
|
|
|
|
&& type.FindConstructor() is { } ctor) |
|
|
|
|
|
{ |
|
|
|
|
|
var ctorMethod = |
|
|
|
|
|
asm.MainModule.ImportReference(typeSystem.GetMethodReference(ctor)); |
|
|
|
|
|
instructionsModified = true; |
|
|
|
|
|
populateMethod.Body.Instructions[index - 3] = Instruction.Create(OpCodes.Nop); |
|
|
|
|
|
populateMethod.Body.Instructions[index - 2] = Instruction.Create(OpCodes.Nop); |
|
|
|
|
|
populateMethod.Body.Instructions[index - 1] = Instruction.Create(OpCodes.Nop); |
|
|
|
|
|
populateMethod.Body.Instructions[index] = Instruction.Create(OpCodes.Newobj, ctorMethod); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
var resources = assetAssembly.FindType("CompiledAvaloniaXaml.!AvaloniaResources") |
|
|
|
|
|
?? throw new InvalidOperationException($"Unable to resolve \"!AvaloniaResources\" type on \"{assetAssemblyName}\" assembly"); |
|
|
|
|
|
|
|
|
|
|
|
var relativeName = "Build:" + assetSource.Substring(assemblyNameSeparator); |
|
|
|
|
|
var buildMethod = resources.FindMethod(m => m.Name == relativeName) |
|
|
|
|
|
?? throw new InvalidOperationException($"Unable to resolve build method \"{relativeName}\" resource on the \"{assetAssemblyName}\" assembly"); |
|
|
|
|
|
|
|
|
|
|
|
var methodReference = asm.MainModule.ImportReference(typeSystem.GetMethodReference(buildMethod)); |
|
|
|
|
|
instructionsModified = true; |
|
|
|
|
|
populateMethod.Body.Instructions[index - 3] = Instruction.Create(OpCodes.Nop); |
|
|
|
|
|
populateMethod.Body.Instructions[index - 2] = Instruction.Create(OpCodes.Nop); |
|
|
|
|
|
populateMethod.Body.Instructions[index - 1] = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod); |
|
|
|
|
|
populateMethod.Body.Instructions[index] = Instruction.Create(OpCodes.Call, methodReference); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception e) |
|
|
|
|
|
{ |
|
|
|
|
|
if (instructionsModified) |
|
|
|
|
|
{ |
|
|
|
|
|
engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", resourceFilePath, |
|
|
|
|
|
lineNumber, linePosition, lineNumber, linePosition, |
|
|
|
|
|
e.Message, "", "Avalonia")); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
engine.LogWarningEvent(new BuildWarningEventArgs("Avalonia", "XAMLIL", |
|
|
|
|
|
resourceFilePath, |
|
|
|
|
|
lineNumber, linePosition, lineNumber, linePosition, |
|
|
|
|
|
e.Message, "", "Avalonia")); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Technically that's a hack, but it fixes corert incompatibility caused by deterministic builds
|
|
|
// Technically that's a hack, but it fixes corert incompatibility caused by deterministic builds
|
|
|
int dupeCounter = 1; |
|
|
int dupeCounter = 1; |
|
|
foreach (var grp in typeDef.NestedTypes.GroupBy(x => x.Name)) |
|
|
foreach (var grp in typeDef.NestedTypes.GroupBy(x => x.Name)) |
|
|
@ -463,6 +580,55 @@ namespace Avalonia.Build.Tasks |
|
|
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); |
|
|
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool? CompileCoreForRefAssembly( |
|
|
|
|
|
IBuildEngine engine, CecilTypeSystem sourceTypeSystem, CecilTypeSystem refTypeSystem) |
|
|
|
|
|
{ |
|
|
|
|
|
var asm = refTypeSystem.TargetAssemblyDefinition; |
|
|
|
|
|
|
|
|
|
|
|
var compiledTypes = sourceTypeSystem.TargetAssemblyDefinition.MainModule.Types |
|
|
|
|
|
.Where(t => t.Namespace.StartsWith(CompiledAvaloniaXamlNamespace) && t.IsPublic).ToArray(); |
|
|
|
|
|
if (compiledTypes.Length == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
|
|
|
foreach (var ogType in compiledTypes) |
|
|
|
|
|
{ |
|
|
|
|
|
var wrappedOgType = sourceTypeSystem.TargetAssembly.FindType(ogType.FullName); |
|
|
|
|
|
|
|
|
|
|
|
var clrPropertiesDef = new TypeDefinition(ogType.Namespace, ogType.Name, |
|
|
|
|
|
TypeAttributes.Class | TypeAttributes.Public, asm.MainModule.TypeSystem.Object); |
|
|
|
|
|
asm.MainModule.Types.Add(clrPropertiesDef); |
|
|
|
|
|
foreach (var attribute in ogType.CustomAttributes) |
|
|
|
|
|
{ |
|
|
|
|
|
var method = asm.MainModule.ImportReference(attribute.Constructor); |
|
|
|
|
|
clrPropertiesDef.CustomAttributes.Add(new CustomAttribute(method, attribute.GetBlob())); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var typeBuilder = refTypeSystem.CreateTypeBuilder(clrPropertiesDef); |
|
|
|
|
|
foreach (var ogMethod in wrappedOgType.Methods.Where(m => m.IsPublic && m.IsStatic)) |
|
|
|
|
|
{ |
|
|
|
|
|
var method = typeBuilder.DefineMethod(ogMethod.ReturnType, ogMethod.Parameters, ogMethod.Name, |
|
|
|
|
|
ogMethod.IsPublic, ogMethod.IsStatic, false); |
|
|
|
|
|
method.Generator.Ldnull(); |
|
|
|
|
|
method.Generator.Throw(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
typeBuilder.CreateType(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch (Exception e) |
|
|
|
|
|
{ |
|
|
|
|
|
engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", "", |
|
|
|
|
|
0, 0, 0, 0, |
|
|
|
|
|
e.Message, "", "Avalonia")); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|