PageRenderTime 36ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/project/core/Config/preprocessor/ElementProcessors/ForProcessor.cs

https://github.com/psgirard/CruiseControl.NET
C# | 85 lines | 66 code | 6 blank | 13 comment | 3 complexity | 638aba0025a147c5ab9fbdadac47d846 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Xml.Linq;
  6. namespace ThoughtWorks.CruiseControl.Core.Config.Preprocessor.ElementProcessors
  7. {
  8. /// <summary>
  9. /// Processor for the "for" looping element
  10. /// </summary>
  11. internal class ForProcessor : ElementProcessor
  12. {
  13. public ForProcessor(PreprocessorEnvironment env)
  14. : base(env._Settings.Namespace.GetName("for"), env)
  15. {
  16. }
  17. public override IEnumerable< XNode > Process(XNode node)
  18. {
  19. XElement element = _AssumeElement( node );
  20. Validation.RequireAttributes( element, AttrName.CounterName, AttrName.InitExpr,
  21. AttrName.TestExpr, AttrName.CountExpr );
  22. // Get the attributes representing the counter name, initialization expression, termination test
  23. // expression, and counter-increment expression. General, this translates to a traditional C-style
  24. // for-loop semantics: for( counter_name = init_expr; test_expr; count_expr );
  25. string counter_name =
  26. _ProcessText( element.GetAttributeValue( AttrName.CounterName ) ).GetTextValue();
  27. string init_expr =
  28. _ProcessText( element.GetAttributeValue( AttrName.InitExpr ) ).GetTextValue();
  29. string test_expr = element.GetAttributeValue( AttrName.TestExpr );
  30. string count_expr = element.GetAttributeValue( AttrName.CountExpr );
  31. var generated_nodes = new List< XNode >();
  32. string current_expr = init_expr;
  33. int count = _ExprAsInt( current_expr );
  34. bool run = true;
  35. while ( run )
  36. {
  37. /* Necessary due to "modified closure" lambda interaction rules */
  38. int count1 = count;
  39. XNode[] nodes = _Env.Call( () =>
  40. {
  41. // Define the counter value in the environment
  42. _Env.DefineTextSymbol( counter_name,
  43. count1.ToString(
  44. NumberFormatInfo.
  45. InvariantInfo ) );
  46. // Test for loop termination condition
  47. if (
  48. !_Env.EvalBool(
  49. _ProcessText( test_expr ).GetTextValue() ) )
  50. {
  51. /* terminate */
  52. run = false;
  53. return new XNode[] {};
  54. }
  55. // Evaluate the count expression (must be done in the current environment stack frame)
  56. count1 =
  57. _ExprAsInt(
  58. _ProcessText( count_expr ).GetTextValue() );
  59. // Process the loop body
  60. return _ProcessNodes( element.Nodes() ).ToArray();
  61. } );
  62. /* Necessary due to "modified closure" lambda interaction rules */
  63. count = count1;
  64. generated_nodes.AddRange( nodes );
  65. }
  66. return generated_nodes;
  67. }
  68. private int _ExprAsInt(string expr)
  69. {
  70. int val;
  71. if ( !Int32.TryParse( _Env.EvalExprAsString( expr ), out val ) )
  72. {
  73. throw new InvalidCastException(
  74. String.Format( CultureInfo.CurrentCulture, "Expression '{0}' does not evaluate to an integer", expr ) );
  75. }
  76. return val;
  77. }
  78. }
  79. }