2 * Copyright(c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
23 using static Mono.Cecil.Cil.Instruction;
24 using static Mono.Cecil.Cil.OpCodes;
26 using Tizen.NUI.Xaml.Build.Tasks;
28 using Tizen.NUI.Binding;
31 namespace Tizen.NUI.Xaml.Core.XamlC
33 class RDSourceTypeConverter : ICompiledTypeConverter
35 public IEnumerable<Instruction> ConvertFromString(string value, ILContext context, BaseNode node)
37 var module = context.Module;
39 EmbeddedResource matchedResource = null;
41 foreach (var resource in module.Resources.OfType<EmbeddedResource>())
43 if (resource.Name.StartsWith(context.EmbeddedResourceNameSpace) && resource.Name.EndsWith(value))
45 matchedResource = resource;
50 if (null == matchedResource)
52 foreach (var resource in module.Resources.OfType<EmbeddedResource>())
54 if (resource.Name.EndsWith(value))
56 matchedResource = resource;
62 if (null != matchedResource)
65 if (matchedResource.IsResourceDictionaryXaml(module, out classname))
67 int lastIndex = classname.LastIndexOf('.');
68 var realClassName = classname.Substring(lastIndex + 1);
69 var typeref = XmlTypeExtensions.GetTypeReference(realClassName, module, node, XmlTypeExtensions.ModeOfGetType.Both);
71 var typeName = matchedResource.Name.Replace('.', '_');
72 var typeDefOfGetResource = module.Types.FirstOrDefault(type => type.FullName == "GetResource." + typeName);
73 if (null != typeDefOfGetResource)
75 module.Types.Remove(typeDefOfGetResource);
76 typeDefOfGetResource = null;
79 if (null == typeDefOfGetResource)
81 typeDefOfGetResource = new TypeDefinition("GetResource", typeName, TypeAttributes.NotPublic);
82 typeDefOfGetResource.BaseType = typeref;
83 module.Types.Add(typeDefOfGetResource);
85 typeDefOfGetResource.AddDefaultConstructor(typeref);
88 var methodName = "GetResource";
89 var methodOfGetResource = typeDefOfGetResource.Methods.FirstOrDefault(m => m.Name == methodName);
91 if (null == methodOfGetResource)
93 methodOfGetResource = new MethodDefinition(methodName, MethodAttributes.Public, typeref);
94 typeDefOfGetResource.Methods.Add(methodOfGetResource);
97 var constructor = typeDefOfGetResource.Methods.FirstOrDefault(m => m.IsConstructor);
99 if (null != constructor)
101 constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Ldarg_0));
102 constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Call, methodOfGetResource));
103 constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Pop));
106 var rootnode = XamlTask.ParseXaml(matchedResource.GetResourceStream(), typeref);
109 TryCoreCompile(methodOfGetResource, rootnode, context.EmbeddedResourceNameSpace, out exception);
111 yield return Create(Newobj, constructor);
116 internal static string GetPathForType(ModuleDefinition module, TypeReference type)
118 foreach (var ca in type.Module.GetCustomAttributes())
120 if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference((XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "XamlResourceIdAttribute"))))
122 if (!TypeRefComparer.Default.Equals(ca.ConstructorArguments[2].Value as TypeReference, type))
124 return ca.ConstructorArguments[1].Value as string;
129 private bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string resourceName, out Exception exception)
133 var body = new MethodBody(initComp);
134 var module = body.Method.Module;
135 var type = initComp.DeclaringType;
137 body.InitLocals = true;
138 var il = body.GetILProcessor();
139 il.Emit(OpCodes.Ldarg_0);
140 var resourcePath = GetPathForType(module, type);
144 List<Instruction> insOfAddEvent = new List<Instruction>();
146 var visitorContext = new ILContext(il, body, insOfAddEvent, module, resourceName);
148 rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
149 rootnode.Accept(new Tizen.NUI.Xaml.Build.Tasks.ExpandMarkupsVisitor(visitorContext), null);
150 rootnode.Accept(new PruneIgnoredNodesVisitor(), null);
151 rootnode.Accept(new CreateObjectVisitor(visitorContext), null);
153 rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null);
154 rootnode.Accept(new SetFieldVisitor(visitorContext), null);
155 rootnode.Accept(new SetResourcesVisitor(visitorContext), null);
156 rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null);
159 initComp.Body = body;
165 XamlParseException xamlParseException = e as XamlParseException;
166 if (null != xamlParseException)
168 XamlParseException ret = new XamlParseException(xamlParseException.Message, xamlParseException.XmlInfo, xamlParseException.InnerException);