private static void PopulateClass(TypeSafeDataUnit dataUnit, CodeTypeDeclaration container) { foreach (var nestedUnit in dataUnit.NestedUnits) { string className; if (!CompilerUtil.GetSafeNameAndVerifyNotDuplicate(nestedUnit.ClassName, container, out className)) { continue; } if (className == container.Name) { TSLog.LogWarning(LogCategory.Compile, Strings.Warning_NameCannotBeSameAsParent); className = "_" + className; // Check for duplicates again after having added the '_' if (!CompilerUtil.GetSafeNameAndVerifyNotDuplicate(className, container, out className)) { continue; } } var nestedContainer = CompilerUtil.CreateStaticType(className); PopulateClass(nestedUnit, nestedContainer); container.Members.Add(nestedContainer); } PopulateClassMembers(dataUnit, container); }
private static void WriteResourceProperty(CodeTypeDeclaration type, ResourceDefinition rd, int index) { string name; if (!CompilerUtil.GetSafeNameAndVerifyNotDuplicate(rd.Name, type, out name)) { return; } var resourceType = GetResourceType(rd.Type); var attributes = MemberAttributes.Static; if (rd.Type.IsNotPublic) { attributes |= MemberAttributes.Assembly; } else { attributes |= MemberAttributes.Public; } // Create a property to access the array var propertyExpression = new CodeMemberProperty { Name = name, Type = resourceType, HasSet = false, HasGet = true, Attributes = attributes, GetStatements = { new CodeMethodReturnStatement(new CodeCastExpression(resourceType, new CodeArrayIndexerExpression( new CodeVariableReferenceExpression(CollectionMemberName), new CodePrimitiveExpression(index)))) } }; type.Members.Add(propertyExpression); }
private static void PopulateClassMembers(TypeSafeDataUnit unit, CodeTypeDeclaration container) { // Create the list type that is used to store the internal array (not used when All list is disabled) var valueListType = new CodeTypeReference(typeof(IList <>)) { TypeArguments = { unit.DataType } }; // Set up the default type for members var dataType = new CodeTypeReference(unit.DataType); // Use global references CompilerUtil.SetTypeGlobalReference(dataType); CompilerUtil.SetTypeGlobalReference(valueListType); // Expression to make the internal list (not used when All list is disabled) var arrayExpression = new CodeArrayCreateExpression(dataType); //TSLog.Log(LogCategory.Trace, $"[DataUnitCompiler] Populating {container.Name}"); foreach (var c in unit.Data) { // Can't override type if using the All property method (since can't store non-compatible types in the list) if (unit.EnableAllProperty && c.OverrideType != null) { throw new InvalidOperationException("Cannot override type when using All list."); } var name = c.PropertyName; string memberName; if ( !CompilerUtil.GetSafeNameAndVerifyNotDuplicate(name, container, out memberName, !c.OverrideRestrictedNames)) { continue; } // Create the expression to initialize this member var entryExpression = GetCreateExpression(c, c.OverrideType != null ? c.OverrideType : unit.DataType); var isObsolete = !string.IsNullOrEmpty(c.ObsoleteWarning); //TSLog.Log(LogCategory.Trace, $"[DataUnitCompiler] Member (name={memberName}, isObsolete={isObsolete})"); // Exclude obsolete members from the _all array if (unit.EnableAllProperty && !isObsolete) { // Add the initializer expression to the internal _all array arrayExpression.Initializers.Add(entryExpression); } CodeTypeMember member; // Create a field if one of the following criteria matches: // - Entry is a primitive or string. We duplicate the data (include in _all array and const field) so that const uses are faster // - All property is disabled, so we don't have an internal _all array to access // - Entry has an obsolete warning and so isn't included in the internal _all array. if (!unit.EnableAllProperty || unit.DataType.IsPrimitive || unit.DataType == typeof(string) || isObsolete) { //TSLog.Log(LogCategory.Trace, $"[DataUnitCompiler] Member handled as field"); var entryTypeReference = dataType; var attributes = MemberAttributes.Public; if (c.OverrideType != null) { entryTypeReference = new CodeTypeReference(c.OverrideType); } if (CompilerUtil.IsPrimitiveType(unit.DataType)) { attributes |= MemberAttributes.Const; } else { attributes |= MemberAttributes.Static; entryTypeReference = new CodeTypeReference("readonly global::" + entryTypeReference.BaseType); } // Duplicate data and create a field for data entry member = new CodeMemberField { Name = memberName, Type = entryTypeReference, Attributes = attributes, InitExpression = entryExpression }; if (isObsolete) { //TSLog.Log(LogCategory.Trace, $"[DataUnitCompiler] Adding obsolete warning: {c.ObsoleteWarning}"); member.CustomAttributes.Add(CompilerUtil.GetObsoleteAttribute(c.ObsoleteWarning, false)); } } else { //TSLog.Log(LogCategory.Trace, $"[DataUnitCompiler] Member handled as property"); // Otherwise create a property getter to access the internal _all array element member = new CodeMemberProperty { Name = memberName, Type = dataType, HasSet = false, HasGet = true, Attributes = MemberAttributes.Static | MemberAttributes.Public, GetStatements = { new CodeMethodReturnStatement(new CodeArrayIndexerExpression( new CodeVariableReferenceExpression("__all"), new CodePrimitiveExpression(arrayExpression.Initializers.Count - 1))) } }; } container.Members.Add(member); } if (unit.EnableAllProperty) { var all = new CodeMemberField(valueListType, "__all") { InitExpression = new CodeObjectCreateExpression( new CodeTypeReference(typeof(ReadOnlyCollection <>), CodeTypeReferenceOptions.GlobalReference) { TypeArguments = { dataType } }, arrayExpression), Attributes = MemberAttributes.Private | MemberAttributes.Static }; container.Members.Add(all); var allPublic = new CodeMemberProperty { Name = "All", Type = valueListType, GetStatements = { new CodeMethodReturnStatement(new CodeFieldReferenceExpression { FieldName = "__all" }) }, HasGet = true, Attributes = MemberAttributes.Public | MemberAttributes.Static }; container.Members.Add(allPublic); } }