public StatSubtypeDefinition(StatTypeDefinition type, string name) { Type = type; Name = name; Fields = new Dictionary <string, StatField>(); SubObjects = new Dictionary <string, StatSubtypeDefinition>(); }
private StatSubtypeDefinition FindSubtype(StatTypeDefinition type, string declarationName, StatDeclaration declaration) { if (type.SubtypeProperty == null) { return(type.Subtypes.Values.First()); } if (declaration.Properties.TryGetValue(type.SubtypeProperty, out object subtypeName)) { var name = (string)subtypeName; if (type.Subtypes.TryGetValue(name, out StatSubtypeDefinition subtype)) { return(subtype); } else { Context.LogError(DiagnosticCode.StatSubtypeMissing, $"Stat declaration '{declarationName}' references unknown subtype '{name}'", declaration.Location.FileName, declaration.Location.StartLine); return(null); } } else { Context.LogError(DiagnosticCode.StatSubtypeMissing, $"Stat declaration '{declarationName}' is missing subtype property '{type.SubtypeProperty}'", declaration.Location.FileName, declaration.Location.StartLine); return(null); } }
public Dictionary <string, StatDeclaration> ResolveBaseClasses(StatTypeDefinition definition, Dictionary <string, StatDeclaration> declarations) { var mappings = new List <BaseClassMapping>(); var resolved = new Dictionary <string, StatDeclaration>(); foreach (var declaration in declarations) { var succeeded = ResolveBaseClass(definition, declaration.Value, declarations, out StatDeclaration baseClass); if (succeeded && baseClass != null) { mappings.Add(new BaseClassMapping { Declaration = declaration.Value, BaseClass = baseClass }); } if (succeeded || AllowMappingErrors) { resolved.Add(declaration.Key, declaration.Value); } } PropagateInheritedProperties(mappings); return(resolved); }
public bool ResolveBaseClass( StatTypeDefinition definition, StatDeclaration declaration, Dictionary <string, StatDeclaration> declarations, out StatDeclaration baseClassDeclaration) { var props = declaration.Properties; var name = (string)props[definition.NameProperty]; if (definition.BaseClassProperty != null && props.ContainsKey(definition.BaseClassProperty)) { var baseClass = (string)props[definition.BaseClassProperty]; if (declarations.TryGetValue(baseClass, out StatDeclaration baseDeclaration)) { baseClassDeclaration = baseDeclaration; return(true); } else { Context.LogError(DiagnosticCode.StatBaseClassNotKnown, $"Stat declaration '{name}' references nonexistent base class '{baseClass}'", declaration.Location.FileName, declaration.Location.StartLine, name); baseClassDeclaration = null; return(false); } } baseClassDeclaration = null; return(true); }
private void AddSubtype(StatTypeDefinition definition, string subtypeName, IEnumerable <XElement> fields) { var subtype = new StatSubtypeDefinition(definition, subtypeName); foreach (var field in fields) { AddField(definition, subtype, field); } definition.Subtypes.Add(subtypeName, subtype); }
private void AddDefinition(XElement defn) { var name = defn.Attribute("name").Value; var parentName = defn.Attribute("export_type")?.Value ?? name; if (!Definitions.TryGetValue(parentName, out StatTypeDefinition definition)) { var subtypeProperty = defn.Attribute("subtype_property")?.Value ?? null; definition = new StatTypeDefinition(parentName, subtypeProperty); Definitions.Add(parentName, definition); } var fields = defn.Element("field_definitions").Elements("field_definition"); AddSubtype(definition, name, fields); }
private void AddField(StatTypeDefinition definition, StatSubtypeDefinition subtype, XElement field) { if (field.Attribute("export_name").Value == "") { return; } var fieldName = field.Attribute("export_name").Value; var typeName = field.Attribute("type").Value; StatEnumeration enumeration = null; List <StatReferenceConstraint> referenceConstraints = null; switch (typeName) { case "Enumeration": case "EnumerationList": var enumName = field.Attribute("enumeration_type_name").Value; enumeration = Enumerations[enumName]; break; case "Name": if (definition.NameProperty == null) { definition.NameProperty = fieldName; } else if (definition.NameProperty != fieldName) { throw new Exception($"Conflicting Name property for type '{definition.Name}': First seen using '{definition.NameProperty}', now seen using '{fieldName}'."); } break; case "BaseClass": if (definition.BaseClassProperty == null) { definition.BaseClassProperty = fieldName; } else if (definition.BaseClassProperty != fieldName) { throw new Exception($"Conflicting BaseClass for type '{definition.Name}': First seen using '{definition.BaseClassProperty}', now seen using '{fieldName}'."); } break; case "StatReference": case "StatReferences": referenceConstraints = new List <StatReferenceConstraint>(); var descriptions = field.Element("stat_descriptions"); if (descriptions == null) { throw new Exception("Field of type 'StatReference' must have a list of stat types in the <stat_descriptions> node"); } var descs = descriptions.Elements("description"); foreach (var desc in descs) { var constraint = new StatReferenceConstraint { StatType = desc.Attribute("stat_type").Value, StatSubtype = desc.Attribute("stat_subtype")?.Value ?? null }; referenceConstraints.Add(constraint); } break; case "Boolean": case "Integer": case "Float": case "String": case "TranslatedString": case "RootTemplate": case "Comment": case "Color": case "Requirements": case "Properties": case "Conditions": case "Passthrough": case "UUID": break; default: throw new Exception($"Unsupported stat field type: '{typeName}'"); } var statField = new StatField { Name = fieldName, Type = typeName, EnumType = enumeration, ReferenceTypes = referenceConstraints }; subtype.Fields.Add(fieldName, statField); if (typeName == "TranslatedString") { var translatedKeyRefField = new StatField { Name = fieldName + "Ref", Type = typeName, EnumType = enumeration }; subtype.Fields.Add(fieldName + "Ref", translatedKeyRefField); } }