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); }
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); }
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); }
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)); } }