/// <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);
		}
示例#4
0
		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));
		}