private static void WriteVisitMember(CodeWriter codeWriter, DataModel model, DataModelMember member) { DataModelType memberType = model.GetTypeForMember(member); switch (memberType.Kind) { case DataModelTypeKind.BuiltInNumber: case DataModelTypeKind.BuiltInString: case DataModelTypeKind.BuiltInDictionary: case DataModelTypeKind.BuiltInBoolean: case DataModelTypeKind.BuiltInUri: case DataModelTypeKind.BuiltInVersion: case DataModelTypeKind.Enum: // Don't visit builtins; overrides would inspect those directly. return; case DataModelTypeKind.Leaf: case DataModelTypeKind.Base: // Visit this member break; case DataModelTypeKind.Default: default: Debug.Fail("Unexpected DataModelTypeKind"); return; } var valueNamer = new LocalVariableNamer("value"); string sourceVariable = "node." + member.CSharpName; for (int idx = 0; idx < member.Rank; ++idx) { string valueName = valueNamer.MakeName(); codeWriter.OpenBrace("if ({0} != null)", sourceVariable); codeWriter.OpenBrace("foreach (var {0} in {1})", valueName, sourceVariable); sourceVariable = valueName; } codeWriter.WriteLine("this.VisitNullChecked({0});", sourceVariable); if (member.Rank == 0) { return; } for (int idx = 0; idx < member.Rank; ++idx) { codeWriter.CloseBrace(); // if (source != null) codeWriter.CloseBrace(); // foreach } codeWriter.WriteLine(); }
private static void WriteInitForMember(CodeWriter codeWriter, DataModel model, DataModelMember member, LocalVariableNamer destNamer, LocalVariableNamer valueNamer) { DataModelType memberType = model.GetTypeForMember(member); if (memberType.IsNullable) { codeWriter.OpenBrace("if ({0} != null)", member.ArgumentName); } if (member.Rank == 0) { codeWriter.WriteLine("this." + member.CSharpName + " = " + GetCopyCreationExpression(memberType, member.ArgumentName) + ";"); } else { string[] destinations = new string[member.Rank]; string source = member.ArgumentName; for (int idx = 0; idx < destinations.Length; ++idx) { string currentDest = destNamer.MakeName(); destinations[idx] = currentDest; StringBuilder sb = new StringBuilder(); sb.Append("var ").Append(currentDest).Append(" = new List<"); AppendRankedTypeName(sb, "IList", memberType.CSharpName, member.Rank - idx - 1); sb.Append(">();"); codeWriter.WriteLineConsume(sb); codeWriter.OpenBrace("if ({0} != null)", source); string value = valueNamer.MakeName(); codeWriter.OpenBrace("foreach (var {0} in {1})", value, source); source = value; } string lastDestination = destinations[destinations.Length - 1]; if (memberType.IsNullable) { codeWriter.OpenBrace("if ({0} == null)", source); codeWriter.WriteLine(lastDestination + ".Add(null);"); codeWriter.CloseBrace(); codeWriter.OpenBrace("else"); } codeWriter.WriteLine(lastDestination + ".Add(" + GetCopyCreationExpression(memberType, source) + ");"); if (memberType.IsNullable) { codeWriter.CloseBrace(); } codeWriter.CloseBrace(); // foreach codeWriter.CloseBrace(); // if (source != null) codeWriter.WriteLine(); for (int idx = 1; idx < destinations.Length; ++idx) { codeWriter.WriteLine("{0}.Add({1});", destinations[member.Rank - idx - 1], destinations[member.Rank - idx]); codeWriter.CloseBrace(); // foreach codeWriter.CloseBrace(); // if (source != null) codeWriter.WriteLine(); } codeWriter.WriteLine("this.{0} = {1};", member.CSharpName, destinations[0]); } if (memberType.IsNullable) { codeWriter.CloseBrace(); } }
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(); } }