PageRenderTime 128ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListInitExpression.cs

https://github.com/iainlane/mono
C# | 237 lines | 110 code | 22 blank | 105 comment | 15 complexity | 53168dd9ec9c62026f220ab0244e9bc5 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using System.Diagnostics;
  19. using System.Dynamic.Utils;
  20. using System.Reflection;
  21. using System.Runtime.CompilerServices;
  22. #if SILVERLIGHT
  23. using System.Core;
  24. #endif
  25. #if CLR2
  26. namespace Microsoft.Scripting.Ast {
  27. #else
  28. namespace System.Linq.Expressions {
  29. #endif
  30. /// <summary>
  31. /// Represents a constructor call that has a collection initializer.
  32. /// </summary>
  33. /// <remarks>
  34. /// Use the <see cref="M:ListInit"/> factory methods to create a ListInitExpression.
  35. /// The value of the NodeType property of a ListInitExpression is ListInit.
  36. /// </remarks>
  37. #if !SILVERLIGHT
  38. [DebuggerTypeProxy(typeof(Expression.ListInitExpressionProxy))]
  39. #endif
  40. public sealed class ListInitExpression : Expression {
  41. private readonly NewExpression _newExpression;
  42. private readonly ReadOnlyCollection<ElementInit> _initializers;
  43. internal ListInitExpression(NewExpression newExpression, ReadOnlyCollection<ElementInit> initializers) {
  44. _newExpression = newExpression;
  45. _initializers = initializers;
  46. }
  47. /// <summary>
  48. /// Returns the node type of this <see cref="Expression"/>. (Inherited from <see cref="Expression" />.)
  49. /// </summary>
  50. /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
  51. public sealed override ExpressionType NodeType {
  52. get { return ExpressionType.ListInit; }
  53. }
  54. /// <summary>
  55. /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
  56. /// </summary>
  57. /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
  58. public sealed override Type Type {
  59. get { return _newExpression.Type; }
  60. }
  61. /// <summary>
  62. /// Gets a value that indicates whether the expression tree node can be reduced.
  63. /// </summary>
  64. public override bool CanReduce {
  65. get {
  66. return true;
  67. }
  68. }
  69. /// <summary>
  70. /// Gets the expression that contains a call to the constructor of a collection type.
  71. /// </summary>
  72. public NewExpression NewExpression {
  73. get { return _newExpression; }
  74. }
  75. /// <summary>
  76. /// Gets the element initializers that are used to initialize a collection.
  77. /// </summary>
  78. public ReadOnlyCollection<ElementInit> Initializers {
  79. get { return _initializers; }
  80. }
  81. /// <summary>
  82. /// Dispatches to the specific visit method for this node type.
  83. /// </summary>
  84. protected internal override Expression Accept(ExpressionVisitor visitor) {
  85. return visitor.VisitListInit(this);
  86. }
  87. /// <summary>
  88. /// Reduces the binary expression node to a simpler expression.
  89. /// If CanReduce returns true, this should return a valid expression.
  90. /// This method is allowed to return another node which itself
  91. /// must be reduced.
  92. /// </summary>
  93. /// <returns>The reduced expression.</returns>
  94. public override Expression Reduce() {
  95. return MemberInitExpression.ReduceListInit(_newExpression, _initializers, true);
  96. }
  97. /// <summary>
  98. /// Creates a new expression that is like this one, but using the
  99. /// supplied children. If all of the children are the same, it will
  100. /// return this expression.
  101. /// </summary>
  102. /// <param name="newExpression">The <see cref="NewExpression" /> property of the result.</param>
  103. /// <param name="initializers">The <see cref="Initializers" /> property of the result.</param>
  104. /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
  105. public ListInitExpression Update(NewExpression newExpression, IEnumerable<ElementInit> initializers) {
  106. if (newExpression == NewExpression && initializers == Initializers) {
  107. return this;
  108. }
  109. return Expression.ListInit(newExpression, initializers);
  110. }
  111. }
  112. public partial class Expression {
  113. /// <summary>
  114. /// Creates a <see cref="ListInitExpression"/> that uses a method named "Add" to add elements to a collection.
  115. /// </summary>
  116. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  117. /// <param name="initializers">An array of <see cref="Expression"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
  118. /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
  119. public static ListInitExpression ListInit(NewExpression newExpression, params Expression[] initializers) {
  120. ContractUtils.RequiresNotNull(newExpression, "newExpression");
  121. ContractUtils.RequiresNotNull(initializers, "initializers");
  122. return ListInit(newExpression, initializers as IEnumerable<Expression>);
  123. }
  124. /// <summary>
  125. /// Creates a <see cref="ListInitExpression"/> that uses a method named "Add" to add elements to a collection.
  126. /// </summary>
  127. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  128. /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
  129. /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
  130. public static ListInitExpression ListInit(NewExpression newExpression, IEnumerable<Expression> initializers) {
  131. ContractUtils.RequiresNotNull(newExpression, "newExpression");
  132. ContractUtils.RequiresNotNull(initializers, "initializers");
  133. var initializerlist = initializers.ToReadOnly();
  134. if (initializerlist.Count == 0) {
  135. throw Error.ListInitializerWithZeroMembers();
  136. }
  137. MethodInfo addMethod = FindMethod(newExpression.Type, "Add", null, new Expression[] { initializerlist[0] }, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  138. return ListInit(newExpression, addMethod, initializers);
  139. }
  140. /// <summary>
  141. /// Creates a <see cref="ListInitExpression"/> that uses a specified method to add elements to a collection.
  142. /// </summary>
  143. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  144. /// <param name="addMethod">A <see cref="MethodInfo"/> that represents an instance method named "Add" (case insensitive), that adds an element to a collection. </param>
  145. /// <param name="initializers">An array of <see cref="Expression"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
  146. /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
  147. public static ListInitExpression ListInit(NewExpression newExpression, MethodInfo addMethod, params Expression[] initializers) {
  148. if (addMethod == null) {
  149. return ListInit(newExpression, initializers as IEnumerable<Expression>);
  150. }
  151. ContractUtils.RequiresNotNull(newExpression, "newExpression");
  152. ContractUtils.RequiresNotNull(initializers, "initializers");
  153. return ListInit(newExpression, addMethod, initializers as IEnumerable<Expression>);
  154. }
  155. /// <summary>
  156. /// Creates a <see cref="ListInitExpression"/> that uses a specified method to add elements to a collection.
  157. /// </summary>
  158. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  159. /// <param name="addMethod">A <see cref="MethodInfo"/> that represents an instance method named "Add" (case insensitive), that adds an element to a collection. </param>
  160. /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="Expression"/> objects to use to populate the Initializers collection.</param>
  161. /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
  162. public static ListInitExpression ListInit(NewExpression newExpression, MethodInfo addMethod, IEnumerable<Expression> initializers) {
  163. if (addMethod == null) {
  164. return ListInit(newExpression, initializers);
  165. }
  166. ContractUtils.RequiresNotNull(newExpression, "newExpression");
  167. ContractUtils.RequiresNotNull(initializers, "initializers");
  168. var initializerlist = initializers.ToReadOnly();
  169. if (initializerlist.Count == 0) {
  170. throw Error.ListInitializerWithZeroMembers();
  171. }
  172. ElementInit[] initList = new ElementInit[initializerlist.Count];
  173. for (int i = 0; i < initializerlist.Count; i++) {
  174. initList[i] = ElementInit(addMethod, initializerlist[i]);
  175. }
  176. return ListInit(newExpression, new TrueReadOnlyCollection<ElementInit>(initList));
  177. }
  178. /// <summary>
  179. /// Creates a <see cref="ListInitExpression"/> that uses specified <see cref="M:ElementInit"/> objects to initialize a collection.
  180. /// </summary>
  181. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  182. /// <param name="initializers">An array that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
  183. /// <returns>
  184. /// A <see cref="ListInitExpression"/> that has the <see cref="P:Expressions.NodeType"/> property equal to ListInit
  185. /// and the <see cref="P:ListInitExpression.NewExpression"/> and <see cref="P:ListInitExpression.Initializers"/> properties set to the specified values.
  186. /// </returns>
  187. /// <remarks>
  188. /// The <see cref="P:Expressions.Type"/> property of <paramref name="newExpression"/> must represent a type that implements <see cref="System.Collections.IEnumerable"/>.
  189. /// The <see cref="P:Expressions.Type"/> property of the resulting <see cref="ListInitExpression"/> is equal to newExpression.Type.
  190. /// </remarks>
  191. public static ListInitExpression ListInit(NewExpression newExpression, params ElementInit[] initializers) {
  192. return ListInit(newExpression, (IEnumerable<ElementInit>)initializers);
  193. }
  194. /// <summary>
  195. /// Creates a <see cref="ListInitExpression"/> that uses specified <see cref="M:ElementInit"/> objects to initialize a collection.
  196. /// </summary>
  197. /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
  198. /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
  199. /// <returns>An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</returns>
  200. /// <remarks>
  201. /// The <see cref="P:Expressions.Type"/> property of <paramref name="newExpression"/> must represent a type that implements <see cref="System.Collections.IEnumerable"/>.
  202. /// The <see cref="P:Expressions.Type"/> property of the resulting <see cref="ListInitExpression"/> is equal to newExpression.Type.
  203. /// </remarks>
  204. public static ListInitExpression ListInit(NewExpression newExpression, IEnumerable<ElementInit> initializers) {
  205. ContractUtils.RequiresNotNull(newExpression, "newExpression");
  206. ContractUtils.RequiresNotNull(initializers, "initializers");
  207. var initializerlist = initializers.ToReadOnly();
  208. if (initializerlist.Count == 0) {
  209. throw Error.ListInitializerWithZeroMembers();
  210. }
  211. ValidateListInitArgs(newExpression.Type, initializerlist);
  212. return new ListInitExpression(newExpression, initializerlist);
  213. }
  214. }
  215. }