private void AppendTupleElements( StringBuilder builder, Type type, int cardinality, ReadOnlyCollection <byte> dynamicFlags, ref int dynamicFlagIndex, ReadOnlyCollection <string> tupleElementNames, ref int tupleElementIndex, bool escapeKeywordIdentifiers, out bool sawInvalidIdentifier) { sawInvalidIdentifier = false; int nameIndex = tupleElementIndex; tupleElementIndex += cardinality; builder.Append('('); bool any = false; while (true) { var typeArguments = type.GetGenericArguments(); int nTypeArgs = typeArguments.Length; Debug.Assert(nTypeArgs > 0); Debug.Assert(nTypeArgs <= TypeHelpers.TupleFieldRestPosition); int nFields = Math.Min(nTypeArgs, TypeHelpers.TupleFieldRestPosition - 1); for (int i = 0; i < nFields; i++) { if (any) { builder.Append(", "); } bool sawSingleInvalidIdentifier; var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, nameIndex); nameIndex++; AppendTupleElement( builder, typeArguments[i], name, dynamicFlags, ref dynamicFlagIndex, tupleElementNames, ref tupleElementIndex, escapeKeywordIdentifiers, sawInvalidIdentifier: out sawSingleInvalidIdentifier); sawInvalidIdentifier |= sawSingleInvalidIdentifier; any = true; } if (nTypeArgs < TypeHelpers.TupleFieldRestPosition) { break; } Debug.Assert(!DynamicFlagsCustomTypeInfo.GetFlag(dynamicFlags, dynamicFlagIndex)); dynamicFlagIndex++; type = typeArguments[nTypeArgs - 1]; } builder.Append(')'); }
private static Fields GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality, bool useRawView) { Debug.Assert(declaringTypeAndInfo.Type.GetTupleCardinalityIfAny() == cardinality); var appDomain = declaringTypeAndInfo.ClrType.AppDomain; var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaringTypeAndInfo); var tupleElementNames = customTypeInfoMap.TupleElementNames; var builder = ArrayBuilder <Field> .GetInstance(); Field parent = null; int offset = 0; bool includeRawView = false; while (true) { var declaringType = declaringTypeAndInfo.Type; int n = Math.Min(cardinality, TypeHelpers.TupleFieldRestPosition - 1); for (int index = 0; index < n; index++) { var fieldName = TypeHelpers.GetTupleFieldName(index); var field = declaringType.GetTupleField(fieldName); if (field == null) { // Ignore missing fields. continue; } var fieldTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, field, customTypeInfoMap); if (!useRawView) { var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index); if (name != null) { includeRawView = true; builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent, isRest: false)); continue; } } builder.Add(new Field( declaringTypeAndInfo, fieldTypeAndInfo, field, (offset == 0) ? fieldName : TypeHelpers.GetTupleFieldName(offset + index), parent, isRest: false)); } cardinality -= n; if (cardinality == 0) { break; } var rest = declaringType.GetTupleField(TypeHelpers.TupleFieldRestName); if (rest == null) { // Ignore remaining fields. break; } var restTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, rest, customTypeInfoMap); var restField = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent, isRest: true); if (useRawView) { builder.Add(restField); break; } includeRawView = true; parent = restField; declaringTypeAndInfo = restTypeAndInfo; offset += TypeHelpers.TupleFieldRestPosition - 1; } return(new Fields(builder.ToImmutableAndFree(), includeRawView)); }
private static ReadOnlyCollection <Field> GetFields(TypeAndCustomInfo declaringTypeAndInfo, int cardinality) { Debug.Assert(declaringTypeAndInfo.Type.GetTupleCardinalityIfAny() == cardinality); var appDomain = declaringTypeAndInfo.ClrType.AppDomain; var customTypeInfoMap = CustomTypeInfoTypeArgumentMap.Create(declaringTypeAndInfo); var tupleElementNames = customTypeInfoMap.TupleElementNames; var builder = ArrayBuilder <Field> .GetInstance(); Field parent = null; int offset = 0; while (true) { var declaringType = declaringTypeAndInfo.Type; int n = Math.Min(cardinality, TypeHelpers.TupleFieldRestPosition - 1); for (int index = 0; index < n; index++) { var fieldName = TypeHelpers.GetTupleFieldName(index); var field = declaringType.GetTupleField(fieldName); if (field == null) { // Ignore missing fields. continue; } var fieldTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, field, customTypeInfoMap); var name = CustomTypeInfo.GetTupleElementNameIfAny(tupleElementNames, offset + index); if (name != null) { builder.Add(new Field(declaringTypeAndInfo, fieldTypeAndInfo, field, name, parent)); } builder.Add(new Field( declaringTypeAndInfo, fieldTypeAndInfo, field, (offset == 0) ? fieldName : TypeHelpers.GetTupleFieldName(offset + index), parent)); } cardinality -= n; if (cardinality == 0) { break; } var rest = declaringType.GetTupleField(TypeHelpers.TupleFieldRestName); if (rest == null) { // Ignore remaining fields. break; } var restTypeAndInfo = GetTupleFieldTypeAndInfo(appDomain, rest, customTypeInfoMap); parent = new Field(declaringTypeAndInfo, restTypeAndInfo, rest, TypeHelpers.TupleFieldRestName, parent); declaringTypeAndInfo = restTypeAndInfo; offset += TypeHelpers.TupleFieldRestPosition - 1; } // If there were any nested ValueTuples, // add the Rest field of the outermost. if (parent != null) { while (parent.Parent != null) { parent = parent.Parent; } builder.Add(parent); } return(builder.ToImmutableAndFree()); }