예제 #1
0
 /// <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
                ));
 }
예제 #3
0
        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();
            }
        }