Beispiel #1
0
        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();
        }
Beispiel #2
0
        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();
            }
        }
Beispiel #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();
            }
        }