FieldInfoLookUp GenerateFieldInfos(TypeReference typeRef)
        {
            var lookup = new FieldInfoLookUp()
            {
                Index = m_FieldGenInfos.Count(),
                Count = 0
            };

            if (!m_FieldInfoMap.ContainsKey(typeRef))
            {
                var resolver = TypeResolver.For(typeRef);
                var typeDef  = typeRef.Resolve();

                // Push the component into the fieldInfoTypeList
                m_FieldTypes.Add(typeRef);
                foreach (var field in typeDef.Fields)
                {
                    if (field.IsStatic)
                    {
                        continue;
                    }

                    var fieldType          = resolver.ResolveFieldType(field);
                    var sanitizedFieldName = SanitizeFieldName(field.Name);

                    var fieldInfo = new FieldGenInfo
                    {
                        Offset    = TypeUtils.GetFieldOffset(field.Name, typeRef, ArchBits),
                        FieldName = sanitizedFieldName,
                        FieldType = fieldType
                    };

                    m_FieldGenInfos.Add(fieldInfo);
                    m_FieldTypes.Add(fieldType);
                    m_FieldNames.Add(sanitizedFieldName);
                    lookup.Count++;
                }
                m_FieldInfoMap.Add(typeRef, lookup);

                // Now that we have added info for the top-level, recurse until all nested fields have fieldInfo
                foreach (var field in typeDef.Fields)
                {
                    if (field.IsStatic)
                    {
                        continue;
                    }

                    var fieldType = resolver.ResolveFieldType(field);
                    GenerateFieldInfos(fieldType);
                }
            }

            return(lookup);
        }
예제 #2
0
        private static string GetParseAttributeAction(FieldGenInfo field)
        {
            var readCommand = field.m_field.Type.Name switch
            {
                "String" => "value.ToString()",
                "Byte" => "StrReader.ParseByte(value)",
                "Int32" => "StrReader.ParseInt(value)",
                "UInt32" => "StrReader.ParseUInt(value)",
                "Double" => "StrReader.ParseDouble(value)",
                "Boolean" => "StrReader.InterpretBool(value)",
                _ => throw new NotImplementedException($"no attribute reader for {field.m_field.Type.Name}")
            };

            return(readCommand);
        }
예제 #3
0
        private static string GetPutAttributeAction(FieldGenInfo field)
        {
            var writerAction = field.m_field.Type.Name switch
            {
                "String" => $"buffer.PutAttribute(\"{field.m_xmlName}\", {field.m_field.Name});",
                "Byte" => $"buffer.PutAttributeByte(\"{field.m_xmlName}\", {field.m_field.Name});",
                "Int32" => $"buffer.PutAttributeInt(\"{field.m_xmlName}\", {field.m_field.Name});",
                "UInt32" => $"buffer.PutAttributeUInt(\"{field.m_xmlName}\", {field.m_field.Name});",
                "Double" => $"buffer.PutAttributeDouble(\"{field.m_xmlName}\", {field.m_field.Name});",
                "Boolean" => $"buffer.PutAttributeBoolean(\"{field.m_xmlName}\", {field.m_field.Name});",
                _ => throw new Exception($"no attribute writer for type {field.m_field.Type.Name}")
            };

            return(writerAction);
        }
예제 #4
0
        public void ExecuteInternal(GeneratorExecutionContext context)
        {
            if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
            {
                return;
            }

            var compilation = context.Compilation;

            var bodyAttributeSymbol        = compilation.GetTypeByMetadataName("StackXML.XmlBody");
            var fieldAttributeSymbol       = compilation.GetTypeByMetadataName("StackXML.XmlField");
            var classAttributeSymbol       = compilation.GetTypeByMetadataName("StackXML.XmlCls");
            var splitStringAttributeSymbol = compilation.GetTypeByMetadataName("StackXML.XmlSplitStr");

            var classes = new Dictionary <INamedTypeSymbol, ClassGenInfo>(SymbolEqualityComparer.Default);

            foreach (var @class in receiver.m_candidateClasses)
            {
                var model  = compilation.GetSemanticModel(@class.SyntaxTree);
                var symbol = model.GetDeclaredSymbol(@class);

                if (symbol == null)
                {
                    continue;
                }

                var classAttr = symbol.GetAttributes().SingleOrDefault(ad =>
                                                                       ad.AttributeClass != null &&
                                                                       ad.AttributeClass.Equals(classAttributeSymbol, SymbolEqualityComparer.Default));

                if (classAttr == null)
                {
                    continue;
                }
                var xmlName = classAttr.ConstructorArguments[0].Value.ToString();

                var classGenInfo = new ClassGenInfo(symbol);
                classGenInfo.m_className = xmlName;
                classes[symbol]          = classGenInfo;
            }

            foreach (var field in receiver.m_candidateFields)
            {
                var model = compilation.GetSemanticModel(field.SyntaxTree);
                foreach (var variable in field.Declaration.Variables)
                {
                    var fieldSymbol = ModelExtensions.GetDeclaredSymbol(model, variable) as IFieldSymbol;
                    if (fieldSymbol == null)
                    {
                        continue;
                    }

                    var fieldAttr = fieldSymbol.GetAttributes().SingleOrDefault(ad => ad.AttributeClass.Equals(fieldAttributeSymbol, SymbolEqualityComparer.Default));
                    var bodyAttr  = fieldSymbol.GetAttributes().SingleOrDefault(ad => ad.AttributeClass.Equals(bodyAttributeSymbol, SymbolEqualityComparer.Default));
                    var splitAttr = fieldSymbol.GetAttributes().SingleOrDefault(ad => ad.AttributeClass.Equals(splitStringAttributeSymbol, SymbolEqualityComparer.Default));

                    if (fieldAttr == null && bodyAttr == null)
                    {
                        continue;
                    }

                    if (!classes.TryGetValue(fieldSymbol.ContainingType, out var classInfo))
                    {
                        classInfo = new ClassGenInfo(fieldSymbol.ContainingType);
                        classes[fieldSymbol.ContainingType] = classInfo;
                    }

                    var fieldInfo = new FieldGenInfo(fieldSymbol);
                    if (fieldAttr != null)
                    {
                        fieldInfo.m_xmlName = fieldAttr.ConstructorArguments[0].Value.ToString();
                        classInfo.m_fields.Add(fieldInfo);
                    }
                    if (bodyAttr != null)
                    {
                        fieldInfo.m_xmlName = bodyAttr.ConstructorArguments[0].Value?.ToString();
                        classInfo.m_bodies.Add(fieldInfo);
                    }
                    if (splitAttr != null)
                    {
                        fieldInfo.m_splitChar = (char)splitAttr.ConstructorArguments[0].Value;
                    }
                }
            }

            foreach (KeyValuePair <INamedTypeSymbol, ClassGenInfo> info in classes)
            {
                var classSource = ProcessClass(info.Value, classes);
                if (classSource == null)
                {
                    continue;
                }
                context.AddSource($"{nameof(XmlGenerator)}_{info.Value.m_symbol}.cs", SourceText.From(classSource, Encoding.UTF8));
            }
        }