/// <summary>Initializes a new instance of the <see cref="DataModelType"/> class.</summary> /// <param name="summaryText">The summary text to emit for this type declaration.</param> /// <param name="remarksText">The remarks text to emit for this type declaration.</param> /// <param name="g4Name">Declaring name in the G4 file.</param> /// <param name="cSharpName">Name of the type in C#.</param> /// <param name="members">The members of this type, if any.</param> /// <param name="toStringEntries"> /// Records describing the "ToString" override to generate for this type. /// </param> /// <param name="baseType">Type of the base.</param> /// <param name="kind">The kind of type this is.</param> public DataModelType( bool rootObject, string summaryText, string remarksText, string g4Name, string cSharpName, string interfaceName, ImmutableArray <DataModelMember> members, ImmutableArray <string> serializedValues, ImmutableArray <string> G4DeclaredValues, ImmutableArray <ToStringEntry> toStringEntries, string baseType, DataModelTypeKind kind ) { this.RootObject = rootObject; this.SummaryText = summaryText; this.RemarksText = remarksText; this.G4DeclaredName = g4Name; this.CSharpName = cSharpName; this.InterfaceName = interfaceName; this.Members = members; this.SerializedValues = serializedValues; this.G4DeclaredValues = G4DeclaredValues; this.ToStringEntries = toStringEntries; this.Base = baseType; this.Kind = kind; }
private static DataModelType CreateBuiltin(string g4Name, string cSharpName, DataModelTypeKind kind) { return(new DataModelType( false, null, null, g4Name, cSharpName, null, ImmutableArray <DataModelMember> .Empty, ImmutableArray <string> .Empty, ImmutableArray <string> .Empty, ImmutableArray <ToStringEntry> .Empty, null, kind )); }
private void WriteToStringEntryRecursive(ToStringEntry toStringEntry, DataModelTypeKind memberTypeKind, string sourceVariable, int ranksRemaining) { if (ranksRemaining == 0) { switch (memberTypeKind) { case DataModelTypeKind.Leaf: case DataModelTypeKind.Base: case DataModelTypeKind.BuiltInUri: case DataModelTypeKind.BuiltInVersion: _codeWriter.WriteLine("sb.Append({0} == null ? \"{1}(null)\" : {0}.ToString());", sourceVariable, toStringEntry.Variable.CSharpName); break; case DataModelTypeKind.BuiltInString: _codeWriter.WriteLine("sb.Append({0} == null ? \"{1}(null)\" : {0});", sourceVariable, toStringEntry.Variable.CSharpName); break; case DataModelTypeKind.BuiltInNumber: case DataModelTypeKind.BuiltInBoolean: _codeWriter.WriteLine("sb.Append({0}.ToString(CultureInfo.InvariantCulture));", sourceVariable); break; case DataModelTypeKind.BuiltInDictionary: string value = _valueNamer.MakeName(); _codeWriter.OpenBrace("if (this.{0} == null)", toStringEntry.Variable.CSharpName); _codeWriter.WriteLine("sb.Append(\"{0}(null)\");", toStringEntry.Variable.CSharpName); _codeWriter.CloseBrace(); _codeWriter.OpenBrace("else"); _codeWriter.WriteLine("sb.Append('{');"); _codeWriter.OpenBrace("using (var {0} = this.{1}.GetEnumerator())", value, toStringEntry.Variable.CSharpName); _codeWriter.OpenBrace("if ({0}.MoveNext())", value); _codeWriter.WriteLine("sb.Append(\"{{\" + {0}.Current.Key + \", \" + {0}.Current.Value + \"}}\");", value); _codeWriter.OpenBrace("while ({0}.MoveNext())", value); _codeWriter.WriteLine("sb.Append(\", {{\" + {0}.Current.Key + \", \" + {0}.Current.Value + \"}}\");", value); _codeWriter.CloseBrace(); // while _codeWriter.CloseBrace(); // if _codeWriter.CloseBrace(); // using _codeWriter.WriteLine("sb.Append('}');"); _codeWriter.CloseBrace(); // else break; default: Debug.Fail("Bad DataModelTypeKind " + _writtenType.Kind); break; } } else { string indexVariable = _indexNamer.MakeName(); string valueVariable = _valueNamer.MakeName(); string skipDelimiterLabel = _labelNamer.MakeName(); string loopHeadLabel = _labelNamer.MakeName(); // This code makes the: // Write(0) // for (i = 1 -> N) { // Delimeter(); // Write(i); // } // pattern; the "goto" mess is to avoid n^2 code size explosion due to repeating the "Write" call. // (If this were not generated code it would make sense to stamp out separate functions) // // if (source.Count != 0) { // int index = 0; // goto skipDelimeter; // loopHead: // WriteDelimeter(); // skipDelimeter: // Write(); // ++index; // if (index < source.Count) { // goto loopHead; // } // } // _codeWriter.OpenBrace("if ({0}.Count != 0)", sourceVariable); _codeWriter.WriteLine("int {0} = 0;", indexVariable); _codeWriter.WriteLine("goto {0};", skipDelimiterLabel); _codeWriter.WriteLine(loopHeadLabel + ":"); this.WriteLiteralTextAppend(toStringEntry.Text ?? ", "); _codeWriter.WriteLine(skipDelimiterLabel + ":"); _codeWriter.WriteLine("var {0} = {1}[{2}];", valueVariable, sourceVariable, indexVariable); this.WriteToStringEntryRecursive(toStringEntry, memberTypeKind, valueVariable, ranksRemaining - 1); _codeWriter.WriteLine("++{0};", indexVariable); _codeWriter.OpenBrace("if ({0} < {1}.Count)", indexVariable, sourceVariable); _codeWriter.WriteLine("goto {0};", loopHeadLabel); _codeWriter.CloseBrace(); // if (index < source.Count) _codeWriter.CloseBrace(); // if (count != 0) _codeWriter.WriteLine(); } }
private void WriteEqualsForMember(DataModelMember member) { DataModelTypeKind typeKind = _model.GetTypeForMember(member).Kind; string sourceVariable = "this." + member.CSharpName; string otherVariable = "other." + member.CSharpName; for (int idx = 0; idx < member.Rank; ++idx) { _codeWriter.OpenBrace("if (!global::System.Object.ReferenceEquals({0}, {1}))", sourceVariable, otherVariable); _codeWriter.OpenBrace("if ({0} == null || {1} == null)", sourceVariable, otherVariable); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); // null check _codeWriter.WriteLine(); _codeWriter.OpenBrace("if ({0}.Count != {1}.Count)", sourceVariable, otherVariable); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); // different lengths check _codeWriter.WriteLine(); string max = _maxNamer.MakeName(); string index = _indexNamer.MakeName(); _codeWriter.WriteLine("int {0} = {1}.Count;", max, sourceVariable); _codeWriter.OpenBrace("for (int {0} = 0; {0} < {1}; ++{0})", index, max); string newSource = _valueNamer.MakeName(); string newOther = _valueNamer.MakeName(); _codeWriter.WriteLine("var {0} = {1}[{2}];", newSource, sourceVariable, index); _codeWriter.WriteLine("var {0} = {1}[{2}];", newOther, otherVariable, index); sourceVariable = newSource; otherVariable = newOther; } switch (typeKind) { case DataModelTypeKind.Base: case DataModelTypeKind.Leaf: _codeWriter.OpenBrace("if (!global::System.Object.Equals({0}, {1}))", sourceVariable, otherVariable); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); break; case DataModelTypeKind.BuiltInString: case DataModelTypeKind.BuiltInNumber: case DataModelTypeKind.BuiltInBoolean: case DataModelTypeKind.BuiltInUri: case DataModelTypeKind.Enum: case DataModelTypeKind.BuiltInVersion: _codeWriter.OpenBrace("if ({0} != {1})", sourceVariable, otherVariable); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); break; case DataModelTypeKind.BuiltInDictionary: string sourceKvp = _valueNamer.MakeName(); string otherVal = _valueNamer.MakeName(); _codeWriter.OpenBrace("if (!global::System.Object.ReferenceEquals({0}, {1}))", sourceVariable, otherVariable); _codeWriter.OpenBrace("if ({0} == null || {1} == null || {0}.Count != {1}.Count)", sourceVariable, otherVariable); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); _codeWriter.OpenBrace("foreach (var {0} in {1})", sourceKvp, sourceVariable); _codeWriter.WriteLine("string " + otherVal + ";"); _codeWriter.OpenBrace("if (!{0}.TryGetValue({1}.Key, out {2}) || !global::System.Object.Equals({1}.Value, {2}))", otherVariable, sourceKvp, otherVal); _codeWriter.WriteLine("return false;"); _codeWriter.CloseBrace(); // if _codeWriter.CloseBrace(); // foreach _codeWriter.CloseBrace(); // if (!referenceequals) break; default: Debug.Fail("Unrecognized DataModelTypeKind"); throw new InvalidOperationException(); } for (int idx = 0; idx < member.Rank; ++idx) { _codeWriter.CloseBrace(); // for _codeWriter.CloseBrace(); // ReferenceEquals } _codeWriter.WriteLine(); }
private void WriteGetHashCodeMember(DataModelMember member) { DataModelType memberType = _model.GetTypeForMember(member); DataModelTypeKind typeKind = memberType.Kind; string sourceVariable = "this." + member.CSharpName; int additionalCloseBraces = 0; // (rank - 1) * 2 OpenBrace calls for (int idx = 1; idx < member.Rank; ++idx) { string nextVariable = _valueNamer.MakeName(); _codeWriter.OpenBrace("if ({0} != null)", sourceVariable); _codeWriter.OpenBrace("foreach (var {0} in {1})", nextVariable, sourceVariable); _codeWriter.WriteLine("result = result * {0};", MultiplicativeConstant); _codeWriter.OpenBrace("if ({0} != null)", nextVariable); sourceVariable = nextVariable; ++additionalCloseBraces; } // rank != 0 ? 1 : 0 OpenBrace calls if (member.Rank != 0) { string nextVariable = _valueNamer.MakeName(); _codeWriter.OpenBrace("if ({0} != null)", sourceVariable); _codeWriter.OpenBrace("foreach (var {0} in {1})", nextVariable, sourceVariable); _codeWriter.WriteLine("result = result * {0};", MultiplicativeConstant); sourceVariable = nextVariable; ++additionalCloseBraces; } // rank if (memberType.IsNullable) { _codeWriter.OpenBrace("if ({0} != null)", sourceVariable); } switch (typeKind) { case DataModelTypeKind.Base: case DataModelTypeKind.Leaf: case DataModelTypeKind.BuiltInString: case DataModelTypeKind.BuiltInUri: case DataModelTypeKind.BuiltInVersion: _codeWriter.WriteLine("result = (result * {1}) + {0}.GetHashCode();", sourceVariable, MultiplicativeConstant); break; case DataModelTypeKind.BuiltInNumber: case DataModelTypeKind.Enum: _codeWriter.WriteLine("result = (result * {1}) + (int){0};", sourceVariable, MultiplicativeConstant); break; case DataModelTypeKind.BuiltInBoolean: _codeWriter.OpenBrace("if (" + sourceVariable + ")"); _codeWriter.WriteLine("result = (result * " + MultiplicativeConstant + ") + 1;"); _codeWriter.CloseBrace(); break; case DataModelTypeKind.BuiltInDictionary: string xorTempVal = _xorNamer.MakeName(); string iterVal = _valueNamer.MakeName(); _codeWriter.WriteLine("// Use xor for dictionaries to be order-independent"); _codeWriter.WriteLine("int {0} = 0;", xorTempVal); _codeWriter.OpenBrace("foreach (var {0} in {1})", iterVal, sourceVariable); _codeWriter.WriteLine("{0} ^= ({1}.Key ?? String.Empty).GetHashCode();", xorTempVal, iterVal); _codeWriter.WriteLine("{0} ^= ({1}.Value ?? String.Empty).GetHashCode();", xorTempVal, iterVal); _codeWriter.CloseBrace(); // foreach _codeWriter.WriteLine(); _codeWriter.WriteLine("result = (result * {1}) + {0};", xorTempVal, MultiplicativeConstant); break; default: Debug.Fail("Unrecognized DataModelTypeKind"); break; } int closeBraces; if (member.Rank == 0) { closeBraces = 0; } else { closeBraces = (member.Rank - 1) * 2 + 1; } if (memberType.IsNullable) { ++closeBraces; } closeBraces += additionalCloseBraces; for (int idx = 0; idx < closeBraces; ++idx) { _codeWriter.CloseBrace(); } }