7426f3b2956cac9247876694726eab50b49d3e36
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.XamlBuild / src / public / EXamlBuild / EXamlContext.cs
1 /*
2  * Copyright(c) 2022 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 using System;
18 using System.Collections.Generic;
19 using System.Reflection;
20 using Mono.Cecil;
21 using Mono.Cecil.Cil;
22
23 using Tizen.NUI.Xaml;
24
25 namespace Tizen.NUI.EXaml.Build.Tasks
26 {
27     internal class EXamlContext
28     {
29         public EXamlContext(TypeDefinition type, ModuleDefinition module, FieldDefinition parentContextValues = null)
30         {
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;
36             Type = type;
37             Module = module;
38         }
39
40         public Dictionary<INode, object> Values { get; private set; }
41
42         public Dictionary<IElementNode, VariableDefinition> Variables { get; private set; }
43
44         public Dictionary<INode, Tuple<VariableDefinition, IList<string>>> Scopes { get; private set; }
45
46         public Dictionary<INode, TypeReference> TypeExtensions { get; }
47
48         public FieldDefinition ParentContextValues { get; private set; }
49
50         public object Root { get; set; } //FieldDefinition or VariableDefinition
51
52         public INode RootNode { get; set; }
53
54         public TypeDefinition Type { get; set; }
55
56         public ModuleDefinition Module { get; private set; }
57
58         public List<EXamlOperation> eXamlOperations = new List<EXamlOperation>();
59
60         private string GetAssemblyName(AssemblyDefinition assembly)
61         {
62             string assemblyName = "";
63             if (assembly.FullName.StartsWith("Tizen.NUI.XamlBuild"))
64             {
65                 assemblyName = "Tizen.NUI";
66             }
67             else
68             {
69                 assemblyName = assembly.FullName;
70
71                 if (assemblyName.EndsWith(".dll"))
72                 {
73                     assemblyName = assemblyName.Substring(0, assemblyName.Length - ".dll".Length);
74                 }
75                 else if (assemblyName.EndsWith(".exe"))
76                 {
77                     assemblyName = assemblyName.Substring(0, assemblyName.Length - ".exe".Length);
78                 }
79                 else
80                 {
81                     int firstIndex = assemblyName.IndexOf(',');
82                     assemblyName = assemblyName.Substring(0, firstIndex);
83                 }
84
85                 if ("Tizen.NUI.Xaml" == assemblyName)
86                 {
87                     assemblyName = "Tizen.NUI";
88                 }
89             }
90
91             return assemblyName + ", ";
92         }
93
94         private string GetAssemblyName(Assembly assembly)
95         {
96             string assemblyName = "";
97             if (assembly.FullName == typeof(EXamlOperation).Assembly.FullName)
98             {
99                 assemblyName = "Tizen.NUI";
100             }
101             else
102             {
103                 assemblyName = assembly.FullName;
104
105                 if (assemblyName.Substring(assemblyName.Length - ".dll".Length) == ".dll")
106                 {
107                     assemblyName = assemblyName.Substring(0, assemblyName.Length - ".dll".Length);
108                 }
109                 else if (assemblyName.Substring(assemblyName.Length - ".exe".Length) == ".exe")
110                 {
111                     assemblyName = assemblyName.Substring(0, assemblyName.Length - ".exe".Length);
112                 }
113
114                 if ("Tizen.NUI.Xaml" == assemblyName)
115                 {
116                     assemblyName = "Tizen.NUI";
117                 }
118             }
119
120             return assemblyName + ", ";
121         }
122
123         private List<string> definedAssemblies
124         {
125             get;
126         } = new List<string>();
127
128         private List<TypeData> definedTypes
129         {
130             get;
131         } = new List<TypeData>();
132
133         internal EXamlDefinitionList<PropertyDefinition> definedProperties
134         {
135             get;
136         } = new EXamlDefinitionList<PropertyDefinition>();
137
138         internal EXamlDefinitionList<EventDefinition> definedEvents
139         {
140             get;
141         } = new EXamlDefinitionList<EventDefinition>();
142
143         internal List<IMemberDefinition> definedBindableProperties
144         {
145             get;
146         } = new List<IMemberDefinition>();
147
148         internal EXamlDefinitionList<MethodDefinition> definedMethods
149         {
150             get;
151         } = new EXamlDefinitionList<MethodDefinition>();
152
153         #region Data of CreateObject
154         internal List<EXamlCreateObject> eXamlCreateObjects
155         {
156             get;
157         } = new List<EXamlCreateObject>();
158
159         internal Dictionary<(TypeReference, MemberReference), EXamlCreateObject> StaticInstances
160         {
161             get;
162         } = new Dictionary<(TypeReference, MemberReference), EXamlCreateObject>();
163         #endregion
164
165         #region Data of AddObject
166         internal List<EXamlAddObject> eXamlAddObjectList
167         {
168             get;
169         } = new List<EXamlAddObject>();
170         #endregion
171
172         #region ConvertValue
173         internal Dictionary<TypeDefinition, EXamlCreateObject> typeToInstance
174         {
175             get;
176         } = new Dictionary<TypeDefinition, EXamlCreateObject>();
177         #endregion
178
179         #region Data of AddEvent
180         internal List<EXamlAddEvent> eXamlAddEventList
181         {
182             get;
183         } = new List<EXamlAddEvent>();
184         #endregion
185
186         #region Data of Register XName
187         internal Dictionary<string, object> xNameToInstance
188         {
189             get;
190         } = new Dictionary<string, object>();
191
192         internal object GetObjectByXName(string xName)
193         {
194             object ret = null;
195             xNameToInstance.TryGetValue(xName, out ret);
196             return ret;
197         }
198         #endregion
199
200         #region Data of Add Resource to Dictionary
201         internal Dictionary<string, object> resourceDictionary
202         {
203             get;
204         } = new Dictionary<string, object>();
205         #endregion
206
207         #region Data of Get object by property
208         internal List<EXamlGetObjectByProperty> objectsAccordingToProperty = new List<EXamlGetObjectByProperty>();
209
210         private int GetIndex(EXamlGetObjectByProperty eXamlObjectFromProperty)
211         {
212             return objectsAccordingToProperty.IndexOf(eXamlObjectFromProperty);
213         }
214         #endregion
215
216         public string GenerateEXamlString()
217         {
218             string ret = "";
219
220             int objectIndex = 0;
221
222             foreach (var examlOp in eXamlCreateObjects)
223             {
224                 if (examlOp.IsValid)
225                 {
226                     examlOp.Index = objectIndex++;
227                 }
228             }
229
230             foreach (var examlOp in eXamlCreateObjects)
231             {
232                 if (examlOp.IsValid)
233                 {
234                     GatherType(examlOp.Type);
235
236                     foreach (var property in examlOp.PropertyList)
237                     {
238                         GatherType(property.Item1);
239
240                         definedProperties.Add(property.Item1, property.Item2);
241
242                         if (true == property.Item1.Resolve()?.IsEnum)
243                         {
244                             GatherType(property.Item1.Resolve());
245                         }
246                     }
247
248                     foreach (var eventDef in examlOp.EventList)
249                     {
250                         GatherType(eventDef.Item1);
251
252                         definedEvents.Add(eventDef.Item1, eventDef.Item2);
253                     }
254
255                     foreach (var property in examlOp.BindableProperties)
256                     {
257                         if (!definedBindableProperties.Contains(property))
258                         {
259                             definedBindableProperties.Add(property);
260                         }
261
262                         var typeDef = property.DeclaringType;
263                         if (-1 == GetTypeIndex(typeDef))
264                         {
265                             GatherType(property.DeclaringType);
266                         }
267                     }
268
269                     foreach (var param in examlOp.paramsList)
270                     {
271                         if (null != param && param.GetType().IsEnum)
272                         {
273                             GatherType(param.GetType());
274                         }
275                     }
276
277                     if (null != examlOp.XFactoryMethod)
278                     {
279                         GatherMethod((examlOp.XFactoryMethod.DeclaringType, examlOp.XFactoryMethod));
280                     }
281                 }
282             }
283
284             foreach (var op in eXamlAddObjectList)
285             {
286                 if (op.Parent.IsValid && (!(op.Child is EXamlCreateObject eXamlCreateObject) || eXamlCreateObject.IsValid))
287                 {
288                     GatherMethod((op.Method.DeclaringType, op.Method));
289                 }
290             }
291
292             foreach (var op in eXamlAddEventList)
293             {
294                 if (op.Instance.IsValid)
295                 {
296                     GatherMethod((op.Value.DeclaringType, op.Value));
297                 }
298             }
299
300             foreach (var ass in definedAssemblies)
301             {
302                 ret += String.Format("({0} ({1}))\n",
303                                 GetValueString((int)EXamlOperationType.GatherAssembly),
304                                 GetValueString(ass));
305             }
306
307             foreach (var type in definedTypes)
308             {
309                 ret += String.Format("({0} {1})\n",
310                                 GetValueString((int)EXamlOperationType.GatherType),
311                                 type.ConvertToString(definedAssemblies, definedTypes));
312             }
313
314             foreach (var property in definedProperties)
315             {
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));
322             }
323
324             foreach (var eventDef in definedEvents)
325             {
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));
332             }
333
334             foreach (var method in definedMethods)
335             {
336                 var typeDef = method.Item1;
337                 int typeIndex = GetTypeIndex(typeDef);
338
339                 string strForParam = "(";
340                 foreach (var param in method.Item2.Parameters)
341                 {
342                     int paramTypeIndex = GetTypeIndex(param.ParameterType);
343
344                     if (-1 == paramTypeIndex)
345                     {
346                         throw new Exception($"Can't find index of param type {param.ParameterType.FullName}");
347                     }
348
349                     strForParam += GetValueString(paramTypeIndex) + " ";
350                 }
351                 strForParam += ")";
352
353                 ret += String.Format("({0} ({1} {2} {3}))\n",
354                                 GetValueString((int)EXamlOperationType.GatherMethod),
355                                 GetValueString(typeIndex),
356                                 GetValueString(method.Item2.Name),
357                                 strForParam);
358             }
359
360             foreach (var property in definedBindableProperties)
361             {
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));
368             }
369
370             foreach (var op in eXamlOperations)
371             {
372                 ret += op.Write();
373             }
374
375             if (0 < longStrings.Length)
376             {
377                 ret += String.Format("({0} ({1}))\n",
378                                 GetValueString((int)EXamlOperationType.GetLongString),
379                                 GetValueString(longStrings));
380             }
381
382             return ret;
383         }
384
385         private void GatherType(TypeReference typeRef)
386         {
387             if (-1 == GetTypeIndex(typeRef))
388             {
389                 var assemblyName = GetAssemblyName(typeRef.Resolve().Module.Assembly);
390                 if (!definedAssemblies.Contains(assemblyName))
391                 {
392                     definedAssemblies.Add(assemblyName);
393                 }
394
395                 var typeData = new TypeData(typeRef, GetAssemblyName(typeRef.Resolve().Module.Assembly));
396
397                 if (typeRef is GenericInstanceType genericType)
398                 {
399                     foreach (var type in genericType.GenericArguments)
400                     {
401                         GatherType(type);
402                     }
403                 }
404                 definedTypes.Add(typeData);
405             }
406         }
407
408         private void GatherType(Type type)
409         {
410             var assemblyName = GetAssemblyName(type.Assembly);
411             if (!definedAssemblies.Contains(assemblyName))
412             {
413                 definedAssemblies.Add(assemblyName);
414             }
415
416             if (-1 == GetTypeIndex(type))
417             {
418                 definedTypes.Add(new TypeData(type, GetAssemblyName(type.Assembly)));
419             }
420         }
421
422         private void GatherMethod((TypeReference, MethodDefinition) methodInfo)
423         {
424             GatherType(methodInfo.Item1);
425
426             foreach (var param in methodInfo.Item2.Parameters)
427             {
428                 GatherType(param.ParameterType);
429             }
430
431             definedMethods.Add(methodInfo.Item1, methodInfo.Item2);
432         }
433
434         private int GetTypeIndex(TypeData typeData)
435         {
436             if (null != typeData.TypeReference)
437             {
438                 return GetTypeIndex(typeData.TypeReference);
439             }
440
441             if (null != typeData.Type)
442             {
443                 return GetTypeIndex(typeData.Type);
444             }
445
446             return -1;
447         }
448
449         internal int GetTypeIndex(TypeReference typeReference)
450         {
451             for (int i = 0; i < definedTypes.Count; i++)
452             {
453                 if (EXamlUtility.IsSameTypeReference(typeReference, definedTypes[i].TypeReference))
454                 {
455                     return i;
456                 }
457             }
458
459             int ret = -1;
460             switch (typeReference.FullName)
461             {
462                 case "System.SByte":
463                     ret = -2;
464                     break;
465                 case "System.Int16":
466                     ret = -3;
467                     break;
468                 case "System.Int32":
469                     ret = -4;
470                     break;
471                 case "System.Int64":
472                     ret = -5;
473                     break;
474                 case "System.Byte":
475                     ret = -6;
476                     break;
477                 case "System.UInt16":
478                     ret = -7;
479                     break;
480                 case "System.UInt32":
481                     ret = -8;
482                     break;
483                 case "System.UInt64":
484                     ret = -9;
485                     break;
486                 case "System.Boolean":
487                     ret = -10;
488                     break;
489                 case "System.String":
490                     ret = -11;
491                     break;
492                 case "System.Object":
493                     ret = -12;
494                     break;
495                 case "System.Char":
496                     ret = -13;
497                     break;
498                 case "System.Decimal":
499                     ret = -14;
500                     break;
501                 case "System.Single":
502                     ret = -15;
503                     break;
504                 case "System.Double":
505                     ret = -16;
506                     break;
507                 case "System.TimeSpan":
508                     ret = -17;
509                     break;
510                 case "System.Uri":
511                     ret = -18;
512                     break;
513             }
514
515             return ret;
516         }
517
518         internal static int GetTypeIndex(TypeData type, List<TypeData> definedTypes)
519         {
520             for (int i = 0; i < definedTypes.Count; i++)
521             {
522                 if (EXamlUtility.IsSameTypeReference(type.TypeReference, definedTypes[i].TypeReference))
523                 {
524                     return i;
525                 }
526             }
527
528             int ret = -1;
529             switch (type.TypeReference.FullName)
530             {
531                 case "System.SByte":
532                     ret = -2;
533                     break;
534                 case "System.Int16":
535                     ret = -3;
536                     break;
537                 case "System.Int32":
538                     ret = -4;
539                     break;
540                 case "System.Int64":
541                     ret = -5;
542                     break;
543                 case "System.Byte":
544                     ret = -6;
545                     break;
546                 case "System.UInt16":
547                     ret = -7;
548                     break;
549                 case "System.UInt32":
550                     ret = -8;
551                     break;
552                 case "System.UInt64":
553                     ret = -9;
554                     break;
555                 case "System.Boolean":
556                     ret = -10;
557                     break;
558                 case "System.String":
559                     ret = -11;
560                     break;
561                 case "System.Object":
562                     ret = -12;
563                     break;
564                 case "System.Char":
565                     ret = -13;
566                     break;
567                 case "System.Decimal":
568                     ret = -14;
569                     break;
570                 case "System.Single":
571                     ret = -15;
572                     break;
573                 case "System.Double":
574                     ret = -16;
575                     break;
576                 case "System.TimeSpan":
577                     ret = -17;
578                     break;
579                 case "System.Uri":
580                     ret = -18;
581                     break;
582             }
583
584             return ret;
585         }
586
587         private int GetTypeIndex(Type type)
588         {
589             for (int i = 0; i < definedTypes.Count; i++)
590             {
591                 if (type == definedTypes[i].Type)
592                 {
593                     return i;
594                 }
595             }
596
597             return -1;
598         }
599
600         internal (int, int) GetLongStringIndexs(string longString)
601         {
602             if (longStringToIndexPair.ContainsKey(longString))
603             {
604                 return longStringToIndexPair[longString];
605             }
606             else
607             {
608                 var indexPair = (longStrings.Length, 0);
609                 longStrings += longString;
610                 indexPair.Item2 = longStrings.Length - 1;
611
612                 longStringToIndexPair.Add(longString, indexPair);
613                 return indexPair;
614             }
615         }
616
617         private string longStrings = "";
618         private Dictionary<string, (int, int)> longStringToIndexPair = new Dictionary<string, (int, int)>();
619
620         internal string GetValueString(object valueObject)
621         {
622             //Fang: How to deal the Enum
623             string ret = "";
624
625             if (System.Type.Missing == valueObject)
626             {
627                 ret += "yy ";
628             }
629             else if (null == valueObject)
630             {
631                 ret += "zz ";
632             }
633             else if (valueObject is List<object> listObjects)
634             {
635                 ret += "(";
636
637                 foreach (var obj in listObjects)
638                 {
639                     ret += GetValueString(obj);
640                     ret += " ";
641                 }
642
643                 ret += ")";
644             }
645             else
646             {
647                 //Fang
648                 var paramType = valueObject.GetType();
649
650                 string signBegin = "a", signEnd = "a";
651                 string value = "";
652
653                 if (valueObject is EXamlCreateObject)
654                 {
655                     signBegin = signEnd = "a";
656                     value = (valueObject as EXamlCreateObject).Index.ToString();
657                 }
658                 else if (valueObject is EXamlGetObjectByProperty)
659                 {
660                     return GetValueString(GetIndex(valueObject as EXamlGetObjectByProperty));
661                 }
662                 else if (paramType == typeof(string) || paramType == typeof(Uri))
663                 {
664                     signBegin = signEnd = "\"";
665                     value = valueObject.ToString();
666                 }
667                 else if (paramType == typeof(char))
668                 {
669                     signBegin = signEnd = "\'";
670                     value = valueObject.ToString();
671                 }
672                 else if (paramType == typeof(SByte))
673                 {
674                     signBegin = signEnd = "b";
675                     value = valueObject.ToString();
676                 }
677                 else if (paramType == typeof(Int16))
678                 {
679                     signBegin = signEnd = "c";
680                     value = valueObject.ToString();
681                 }
682                 else if (paramType == typeof(Int32))
683                 {
684                     signBegin = signEnd = "d";
685                     value = valueObject.ToString();
686                 }
687                 else if (paramType == typeof(Int64))
688                 {
689                     signBegin = signEnd = "e";
690                     value = valueObject.ToString();
691                 }
692                 else if (paramType == typeof(Byte))
693                 {
694                     signBegin = signEnd = "f";
695                     value = valueObject.ToString();
696                 }
697                 else if (paramType == typeof(UInt16))
698                 {
699                     signBegin = signEnd = "g";
700                     value = valueObject.ToString();
701                 }
702                 else if (paramType == typeof(UInt32))
703                 {
704                     signBegin = signEnd = "h";
705                     value = valueObject.ToString();
706                 }
707                 else if (paramType == typeof(UInt64))
708                 {
709                     signBegin = signEnd = "i";
710                     value = valueObject.ToString();
711                 }
712                 else if (paramType == typeof(Single))
713                 {
714                     signBegin = signEnd = "j";
715                     value = valueObject.ToString();
716                 }
717                 else if (paramType == typeof(Double))
718                 {
719                     signBegin = signEnd = "k";
720                     value = valueObject.ToString();
721                 }
722                 else if (paramType == typeof(TimeSpan))
723                 {
724                     signBegin = signEnd = "l";
725                     value = valueObject.ToString();
726                 }
727                 else if (paramType == typeof(Boolean))
728                 {
729                     signBegin = signEnd = "m";
730                     value = valueObject.ToString();
731                 }
732                 else if (paramType == typeof(decimal))
733                 {
734                     signBegin = signEnd = "n";
735                     value = valueObject.ToString();
736                 }
737                 else if (paramType.IsEnum)
738                 {
739                     signBegin = "o(";
740                     int typeIndex = GetTypeIndex(paramType);
741                     value = String.Format("d{0}d \"{1}\"", typeIndex, valueObject.ToString());
742                     signEnd = ")o";
743                 }
744                 else if (valueObject is EXamlValueConverterFromString)
745                 {
746                     signBegin = "q(";
747                     signEnd = ")q";
748                     value = (valueObject as EXamlValueConverterFromString).GetString();
749                 }
750
751                 ret += String.Format("{0}{1}{2} ", signBegin, value, signEnd);
752             }
753
754             return ret;
755         }
756     }
757
758     internal class TypeData
759     {
760         internal TypeData(Type type, string assemblyName)
761         {
762             Type = type;
763             AssemblyName = assemblyName;
764
765             if (type.IsNested)
766             {
767                 FullName = type.FullName.Replace('/', '+');
768             }
769             else
770             {
771                 FullName = type.FullName;
772             }
773         }
774
775         internal TypeData(TypeReference typeReference, string assemblyName)
776         {
777             TypeReference = typeReference;
778
779             AssemblyName = assemblyName;
780
781             if (typeReference is GenericInstanceType genericType)
782             {
783                 GenericArgumentTypes = new List<TypeData>();
784                 foreach (var type in genericType.GenericArguments)
785                 {
786                     GenericArgumentTypes.Add(new TypeData(type, AssemblyName));
787                 }
788                 FullName = typeReference.Resolve().FullName;
789             }
790             else
791             {
792                 FullName = typeReference.FullName;
793             }
794
795             if (typeReference.IsNested)
796             {
797                 FullName = FullName.Replace('/', '+');
798             }
799         }
800
801         public string ConvertToString(List<string> definedAssemblies, List<TypeData> typeDatas)
802         {
803             string ret = "";
804             int assemblyIndex = definedAssemblies.IndexOf(AssemblyName);
805
806             if (null == GenericArgumentTypes)
807             {
808                 ret += String.Format("(d{0}d \"{1}\")", assemblyIndex, FullName);
809             }
810             else
811             {
812                 string strForGenericTypes = "(";
813
814                 foreach (var type in GenericArgumentTypes)
815                 {
816                     strForGenericTypes += "d" + EXamlContext.GetTypeIndex(type, typeDatas) + "d ";
817                 }
818
819                 strForGenericTypes += ")";
820
821                 ret += String.Format("(d{0}d \"{1}\" {2})", assemblyIndex, FullName, strForGenericTypes);
822             }
823
824             return ret;
825         }
826
827         internal TypeReference TypeReference
828         {
829             get;
830         }
831
832         internal Type Type
833         {
834             get;
835         }
836
837         internal string AssemblyName
838         {
839             get;
840         }
841
842         internal string FullName
843         {
844             get;
845         }
846
847         internal List<TypeData> GenericArgumentTypes
848         {
849             get;
850         }
851     }
852 }
853