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;
19 using System.Reflection;
25 namespace Tizen.NUI.EXaml.Build.Tasks
27 internal class EXamlContext
29 public EXamlContext(TypeDefinition type, ModuleDefinition module, FieldDefinition parentContextValues = null)
31 Values = new Dictionary<INode, object>();
32 Variables = new Dictionary<IElementNode, VariableDefinition>();
33 Scopes = new Dictionary<INode, Tuple<VariableDefinition, IList<string>>>();
34 TypeExtensions = new Dictionary<INode, TypeReference>();
35 ParentContextValues = parentContextValues;
40 public Dictionary<INode, object> Values { get; private set; }
42 public Dictionary<IElementNode, VariableDefinition> Variables { get; private set; }
44 public Dictionary<INode, Tuple<VariableDefinition, IList<string>>> Scopes { get; private set; }
46 public Dictionary<INode, TypeReference> TypeExtensions { get; }
48 public FieldDefinition ParentContextValues { get; private set; }
50 public object Root { get; set; } //FieldDefinition or VariableDefinition
52 public INode RootNode { get; set; }
54 public TypeDefinition Type { get; set; }
56 public ModuleDefinition Module { get; private set; }
58 public List<EXamlOperation> eXamlOperations = new List<EXamlOperation>();
60 private string GetAssemblyName(AssemblyDefinition assembly)
62 string assemblyName = "";
63 if (assembly.FullName.StartsWith("Tizen.NUI.XamlBuild"))
65 assemblyName = "Tizen.NUI";
69 assemblyName = assembly.FullName;
71 if (assemblyName.EndsWith(".dll"))
73 assemblyName = assemblyName.Substring(0, assemblyName.Length - ".dll".Length);
75 else if (assemblyName.EndsWith(".exe"))
77 assemblyName = assemblyName.Substring(0, assemblyName.Length - ".exe".Length);
81 int firstIndex = assemblyName.IndexOf(',');
82 assemblyName = assemblyName.Substring(0, firstIndex);
85 if ("Tizen.NUI.Xaml" == assemblyName)
87 assemblyName = "Tizen.NUI";
91 return assemblyName + ", ";
94 private string GetAssemblyName(Assembly assembly)
96 string assemblyName = "";
97 if (assembly.FullName == typeof(EXamlOperation).Assembly.FullName)
99 assemblyName = "Tizen.NUI";
103 assemblyName = assembly.FullName;
105 if (assemblyName.Substring(assemblyName.Length - ".dll".Length) == ".dll")
107 assemblyName = assemblyName.Substring(0, assemblyName.Length - ".dll".Length);
109 else if (assemblyName.Substring(assemblyName.Length - ".exe".Length) == ".exe")
111 assemblyName = assemblyName.Substring(0, assemblyName.Length - ".exe".Length);
114 if ("Tizen.NUI.Xaml" == assemblyName)
116 assemblyName = "Tizen.NUI";
120 return assemblyName + ", ";
123 private List<string> definedAssemblies
126 } = new List<string>();
128 private List<TypeData> definedTypes
131 } = new List<TypeData>();
133 internal EXamlDefinitionList<PropertyDefinition> definedProperties
136 } = new EXamlDefinitionList<PropertyDefinition>();
138 internal EXamlDefinitionList<EventDefinition> definedEvents
141 } = new EXamlDefinitionList<EventDefinition>();
143 internal List<IMemberDefinition> definedBindableProperties
146 } = new List<IMemberDefinition>();
148 internal EXamlDefinitionList<MethodDefinition> definedMethods
151 } = new EXamlDefinitionList<MethodDefinition>();
153 #region Data of CreateObject
154 internal List<EXamlCreateObject> eXamlCreateObjects
157 } = new List<EXamlCreateObject>();
159 internal Dictionary<(TypeReference, MemberReference), EXamlCreateObject> StaticInstances
162 } = new Dictionary<(TypeReference, MemberReference), EXamlCreateObject>();
165 #region Data of AddObject
166 internal List<EXamlAddObject> eXamlAddObjectList
169 } = new List<EXamlAddObject>();
173 internal Dictionary<TypeDefinition, EXamlCreateObject> typeToInstance
176 } = new Dictionary<TypeDefinition, EXamlCreateObject>();
179 #region Data of AddEvent
180 internal List<EXamlAddEvent> eXamlAddEventList
183 } = new List<EXamlAddEvent>();
186 #region Data of Register XName
187 internal Dictionary<string, object> xNameToInstance
190 } = new Dictionary<string, object>();
192 internal object GetObjectByXName(string xName)
195 xNameToInstance.TryGetValue(xName, out ret);
200 #region Data of Add Resource to Dictionary
201 internal Dictionary<string, object> resourceDictionary
204 } = new Dictionary<string, object>();
207 #region Data of Get object by property
208 internal List<EXamlGetObjectByProperty> objectsAccordingToProperty = new List<EXamlGetObjectByProperty>();
210 private int GetIndex(EXamlGetObjectByProperty eXamlObjectFromProperty)
212 return objectsAccordingToProperty.IndexOf(eXamlObjectFromProperty);
216 public string GenerateEXamlString()
222 foreach (var examlOp in eXamlCreateObjects)
226 examlOp.Index = objectIndex++;
230 foreach (var examlOp in eXamlCreateObjects)
234 GatherType(examlOp.Type);
236 foreach (var property in examlOp.PropertyList)
238 GatherType(property.Item1);
240 definedProperties.Add(property.Item1, property.Item2);
242 if (true == property.Item1.Resolve()?.IsEnum)
244 GatherType(property.Item1.Resolve());
248 foreach (var eventDef in examlOp.EventList)
250 GatherType(eventDef.Item1);
252 definedEvents.Add(eventDef.Item1, eventDef.Item2);
255 foreach (var property in examlOp.BindableProperties)
257 if (!definedBindableProperties.Contains(property))
259 definedBindableProperties.Add(property);
262 var typeDef = property.DeclaringType;
263 if (-1 == GetTypeIndex(typeDef))
265 GatherType(property.DeclaringType);
269 foreach (var param in examlOp.paramsList)
271 if (null != param && param.GetType().IsEnum)
273 GatherType(param.GetType());
277 if (null != examlOp.XFactoryMethod)
279 GatherMethod((examlOp.XFactoryMethod.DeclaringType, examlOp.XFactoryMethod));
284 foreach (var op in eXamlAddObjectList)
286 if (op.Parent.IsValid && (!(op.Child is EXamlCreateObject eXamlCreateObject) || eXamlCreateObject.IsValid))
288 GatherMethod((op.Method.DeclaringType, op.Method));
292 foreach (var op in eXamlAddEventList)
294 if (op.Instance.IsValid)
296 GatherMethod((op.Value.DeclaringType, op.Value));
300 foreach (var ass in definedAssemblies)
302 ret += String.Format("({0} ({1}))\n",
303 GetValueString((int)EXamlOperationType.GatherAssembly),
304 GetValueString(ass));
307 foreach (var type in definedTypes)
309 ret += String.Format("({0} {1})\n",
310 GetValueString((int)EXamlOperationType.GatherType),
311 type.ConvertToString(definedAssemblies, definedTypes));
314 foreach (var property in definedProperties)
316 var typeDef = property.Item1;
317 int typeIndex = GetTypeIndex(typeDef);
318 ret += String.Format("({0} ({1} {2}))\n",
319 GetValueString((int)EXamlOperationType.GatherProperty),
320 GetValueString(typeIndex),
321 GetValueString(property.Item2.Name));
324 foreach (var eventDef in definedEvents)
326 var typeDef = eventDef.Item1;
327 int typeIndex = GetTypeIndex(typeDef);
328 ret += String.Format("({0} ({1} {2}))\n",
329 GetValueString((int)EXamlOperationType.GatherEvent),
330 GetValueString(typeIndex),
331 GetValueString(eventDef.Item2.Name));
334 foreach (var method in definedMethods)
336 var typeDef = method.Item1;
337 int typeIndex = GetTypeIndex(typeDef);
339 string strForParam = "(";
340 foreach (var param in method.Item2.Parameters)
342 int paramTypeIndex = GetTypeIndex(param.ParameterType);
344 if (-1 == paramTypeIndex)
346 throw new Exception($"Can't find index of param type {param.ParameterType.FullName}");
349 strForParam += GetValueString(paramTypeIndex) + " ";
353 ret += String.Format("({0} ({1} {2} {3}))\n",
354 GetValueString((int)EXamlOperationType.GatherMethod),
355 GetValueString(typeIndex),
356 GetValueString(method.Item2.Name),
360 foreach (var property in definedBindableProperties)
362 var typeDef = property.DeclaringType;
363 int typeIndex = GetTypeIndex(typeDef);
364 ret += String.Format("({0} ({1} {2}))\n",
365 GetValueString((int)EXamlOperationType.GatherBindableProperty),
366 GetValueString(typeIndex),
367 GetValueString(property.Name));
370 foreach (var op in eXamlOperations)
375 if (0 < longStrings.Length)
377 ret += String.Format("({0} ({1}))\n",
378 GetValueString((int)EXamlOperationType.GetLongString),
379 GetValueString(longStrings));
385 private void GatherType(TypeReference typeRef)
387 if (-1 == GetTypeIndex(typeRef))
389 var assemblyName = GetAssemblyName(typeRef.Resolve().Module.Assembly);
390 if (!definedAssemblies.Contains(assemblyName))
392 definedAssemblies.Add(assemblyName);
395 var typeData = new TypeData(typeRef, GetAssemblyName(typeRef.Resolve().Module.Assembly));
397 if (typeRef is GenericInstanceType genericType)
399 foreach (var type in genericType.GenericArguments)
404 definedTypes.Add(typeData);
408 private void GatherType(Type type)
410 var assemblyName = GetAssemblyName(type.Assembly);
411 if (!definedAssemblies.Contains(assemblyName))
413 definedAssemblies.Add(assemblyName);
416 if (-1 == GetTypeIndex(type))
418 definedTypes.Add(new TypeData(type, GetAssemblyName(type.Assembly)));
422 private void GatherMethod((TypeReference, MethodDefinition) methodInfo)
424 GatherType(methodInfo.Item1);
426 foreach (var param in methodInfo.Item2.Parameters)
428 GatherType(param.ParameterType);
431 definedMethods.Add(methodInfo.Item1, methodInfo.Item2);
434 private int GetTypeIndex(TypeData typeData)
436 if (null != typeData.TypeReference)
438 return GetTypeIndex(typeData.TypeReference);
441 if (null != typeData.Type)
443 return GetTypeIndex(typeData.Type);
449 internal int GetTypeIndex(TypeReference typeReference)
451 for (int i = 0; i < definedTypes.Count; i++)
453 if (EXamlUtility.IsSameTypeReference(typeReference, definedTypes[i].TypeReference))
460 switch (typeReference.FullName)
477 case "System.UInt16":
480 case "System.UInt32":
483 case "System.UInt64":
486 case "System.Boolean":
489 case "System.String":
492 case "System.Object":
498 case "System.Decimal":
501 case "System.Single":
504 case "System.Double":
507 case "System.TimeSpan":
518 internal static int GetTypeIndex(TypeData type, List<TypeData> definedTypes)
520 for (int i = 0; i < definedTypes.Count; i++)
522 if (EXamlUtility.IsSameTypeReference(type.TypeReference, definedTypes[i].TypeReference))
529 switch (type.TypeReference.FullName)
546 case "System.UInt16":
549 case "System.UInt32":
552 case "System.UInt64":
555 case "System.Boolean":
558 case "System.String":
561 case "System.Object":
567 case "System.Decimal":
570 case "System.Single":
573 case "System.Double":
576 case "System.TimeSpan":
587 private int GetTypeIndex(Type type)
589 for (int i = 0; i < definedTypes.Count; i++)
591 if (type == definedTypes[i].Type)
600 internal (int, int) GetLongStringIndexs(string longString)
602 if (longStringToIndexPair.ContainsKey(longString))
604 return longStringToIndexPair[longString];
608 var indexPair = (longStrings.Length, 0);
609 longStrings += longString;
610 indexPair.Item2 = longStrings.Length - 1;
612 longStringToIndexPair.Add(longString, indexPair);
617 private string longStrings = "";
618 private Dictionary<string, (int, int)> longStringToIndexPair = new Dictionary<string, (int, int)>();
620 internal string GetValueString(object valueObject)
622 //Fang: How to deal the Enum
625 if (System.Type.Missing == valueObject)
629 else if (null == valueObject)
633 else if (valueObject is List<object> listObjects)
637 foreach (var obj in listObjects)
639 ret += GetValueString(obj);
648 var paramType = valueObject.GetType();
650 string signBegin = "a", signEnd = "a";
653 if (valueObject is EXamlCreateObject)
655 signBegin = signEnd = "a";
656 value = (valueObject as EXamlCreateObject).Index.ToString();
658 else if (valueObject is EXamlGetObjectByProperty)
660 return GetValueString(GetIndex(valueObject as EXamlGetObjectByProperty));
662 else if (paramType == typeof(string) || paramType == typeof(Uri))
664 signBegin = signEnd = "\"";
665 value = valueObject.ToString();
667 else if (paramType == typeof(char))
669 signBegin = signEnd = "\'";
670 value = valueObject.ToString();
672 else if (paramType == typeof(SByte))
674 signBegin = signEnd = "b";
675 value = valueObject.ToString();
677 else if (paramType == typeof(Int16))
679 signBegin = signEnd = "c";
680 value = valueObject.ToString();
682 else if (paramType == typeof(Int32))
684 signBegin = signEnd = "d";
685 value = valueObject.ToString();
687 else if (paramType == typeof(Int64))
689 signBegin = signEnd = "e";
690 value = valueObject.ToString();
692 else if (paramType == typeof(Byte))
694 signBegin = signEnd = "f";
695 value = valueObject.ToString();
697 else if (paramType == typeof(UInt16))
699 signBegin = signEnd = "g";
700 value = valueObject.ToString();
702 else if (paramType == typeof(UInt32))
704 signBegin = signEnd = "h";
705 value = valueObject.ToString();
707 else if (paramType == typeof(UInt64))
709 signBegin = signEnd = "i";
710 value = valueObject.ToString();
712 else if (paramType == typeof(Single))
714 signBegin = signEnd = "j";
715 value = valueObject.ToString();
717 else if (paramType == typeof(Double))
719 signBegin = signEnd = "k";
720 value = valueObject.ToString();
722 else if (paramType == typeof(TimeSpan))
724 signBegin = signEnd = "l";
725 value = valueObject.ToString();
727 else if (paramType == typeof(Boolean))
729 signBegin = signEnd = "m";
730 value = valueObject.ToString();
732 else if (paramType == typeof(decimal))
734 signBegin = signEnd = "n";
735 value = valueObject.ToString();
737 else if (paramType.IsEnum)
740 int typeIndex = GetTypeIndex(paramType);
741 value = String.Format("d{0}d \"{1}\"", typeIndex, valueObject.ToString());
744 else if (valueObject is EXamlValueConverterFromString)
748 value = (valueObject as EXamlValueConverterFromString).GetString();
751 ret += String.Format("{0}{1}{2} ", signBegin, value, signEnd);
758 internal class TypeData
760 internal TypeData(Type type, string assemblyName)
763 AssemblyName = assemblyName;
767 FullName = type.FullName.Replace('/', '+');
771 FullName = type.FullName;
775 internal TypeData(TypeReference typeReference, string assemblyName)
777 TypeReference = typeReference;
779 AssemblyName = assemblyName;
781 if (typeReference is GenericInstanceType genericType)
783 GenericArgumentTypes = new List<TypeData>();
784 foreach (var type in genericType.GenericArguments)
786 GenericArgumentTypes.Add(new TypeData(type, AssemblyName));
788 FullName = typeReference.Resolve().FullName;
792 FullName = typeReference.FullName;
795 if (typeReference.IsNested)
797 FullName = FullName.Replace('/', '+');
801 public string ConvertToString(List<string> definedAssemblies, List<TypeData> typeDatas)
804 int assemblyIndex = definedAssemblies.IndexOf(AssemblyName);
806 if (null == GenericArgumentTypes)
808 ret += String.Format("(d{0}d \"{1}\")", assemblyIndex, FullName);
812 string strForGenericTypes = "(";
814 foreach (var type in GenericArgumentTypes)
816 strForGenericTypes += "d" + EXamlContext.GetTypeIndex(type, typeDatas) + "d ";
819 strForGenericTypes += ")";
821 ret += String.Format("(d{0}d \"{1}\" {2})", assemblyIndex, FullName, strForGenericTypes);
827 internal TypeReference TypeReference
837 internal string AssemblyName
842 internal string FullName
847 internal List<TypeData> GenericArgumentTypes