/// <summary> /// Computes a single TypeParameterSubstitution so that for all types <c>t</c>: /// <c>t.AcceptVisitor(Compose(g, f)) equals t.AcceptVisitor(f).AcceptVisitor(g)</c> /// </summary> /// <remarks>If you consider type parameter substitution to be a function, this is function composition.</remarks> public static TypeParameterSubstitution Compose(TypeParameterSubstitution g, TypeParameterSubstitution f) { if (g == null) return f; if (f == null || (f.classTypeArguments == null && f.methodTypeArguments == null)) return g; // The composition is a copy of 'f', with 'g' applied on the array elements. // If 'f' has a null list (keeps type parameters unmodified), we have to treat it as // the identity function, and thus use the list from 'g'. var classTypeArguments = f.classTypeArguments != null ? GetComposedTypeArguments(f.classTypeArguments, g) : g.classTypeArguments; var methodTypeArguments = f.methodTypeArguments != null ? GetComposedTypeArguments(f.methodTypeArguments, g) : g.methodTypeArguments; return new TypeParameterSubstitution(classTypeArguments, methodTypeArguments); }
static IList<IType> GetComposedTypeArguments(IList<IType> input, TypeParameterSubstitution substitution) { IType[] result = new IType[input.Count]; for (int i = 0; i < result.Length; i++) { result[i] = input[i].AcceptVisitor(substitution); } return result; }
IMember IMember.Specialize(TypeParameterSubstitution substitution) { return Specialize(substitution); }
IEnumerable<TreeNode> LazyEvaluateIEnumerableOfT(ParameterizedType targetType, Value value) { var enumerableType = targetType.Compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); var enumeratorType = targetType.Compilation.FindType(KnownTypeCode.IEnumeratorOfT).GetDefinition(); var substitution = new TypeParameterSubstitution(targetType.TypeArguments, EmptyList<IType>.Instance); IMethod getEnumerator = enumerableType.GetMethods(m => m.Name == "GetEnumerator", GetMemberOptions.IgnoreInheritedMembers) .First(m => m.ReturnType.GetDefinition().Equals(enumeratorType)) .Specialize(substitution); IMethod moveNext = enumeratorType.GetMethods(m => m.Name == "MoveNext").First(); IProperty current = enumeratorType.GetProperties(p => p.Name == "Current").First(); Value enumerator; GetValueException lastError; enumerator = EvaluateOrError(() => Debugger.Value.InvokeMethod(WindowsDebugger.EvalThread, value, getEnumerator), out lastError); if (lastError != null) { yield return new TreeNode(null, "(error)", lastError.Message, string.Empty, null); yield break; } int currentIndex = -1; var moveNextResult = EvaluateOrError(() => Debugger.Value.InvokeMethod(WindowsDebugger.EvalThread, enumerator, moveNext), out lastError); while (lastError == null && (bool)moveNextResult.PrimitiveValue) { currentIndex++; var currentValue = EvaluateOrError(() => enumerator.GetPropertyValue(WindowsDebugger.EvalThread, current), out lastError); yield return new ValueNode(ClassBrowserIconService.Field, "[" + currentIndex + "]", () => currentValue); moveNextResult = EvaluateOrError(() => Debugger.Value.InvokeMethod(WindowsDebugger.EvalThread, enumerator, moveNext), out lastError); } if (lastError != null) { yield return new TreeNode(null, "(error)", lastError.Message, string.Empty, null); yield break; } if (currentIndex < 0) yield return new TreeNode("(empty)", null); }
public IMethod Specialize(TypeParameterSubstitution substitution) { return new ReducedExtensionMethod((IMethod)baseMethod.Specialize(substitution)); }