// called by Expression<T>.Accept internal Expression <T> Rewrite <T>(Expression <T> lambda) { VerifyTemps(); // Lambda starts with an empty stack var body = RewriteExpressionFreeTemps(lambda.Body, _startingStack); _lambdaRewrite = body.Action; VerifyTemps(); if (body.Action != RewriteAction.None) { // Create a new scope for temps // (none of these will be hoisted so there is no closure impact) var newBody = body.Node; if (_tm.Temps.Count > 0) { newBody = Expression.Block(_tm.Temps, newBody); } // Clone the lambda, replacing the body & variables return(new Expression <T>(newBody, lambda.Name, lambda.TailCall, lambda.Parameters)); } return(lambda); }
// Block private Result RewriteBlockExpression(Expression expr, Stack stack) { BlockExpression node = (BlockExpression)expr; int count = node.ExpressionCount; RewriteAction action = RewriteAction.None; Expression[] clone = null; for (int i = 0; i < count; i++) { Expression expression = node.GetExpression(i); // All statements within the block execute at the // same stack state. Result rewritten = RewriteExpression(expression, stack); action |= rewritten.Action; if (clone == null && rewritten.Action != RewriteAction.None) { clone = Clone(node.Expressions, i); } if (clone != null) { clone[i] = rewritten.Node; } } if (action != RewriteAction.None) { // okay to wrap since we know no one can mutate the clone array expr = node.Rewrite(null, clone); } return(new Result(action, expr)); }
private Result RewriteThrowUnaryExpression(Expression expr, Stack stack) { var node = (UnaryExpression)expr; // Throw statement itself does not care about the stack // but it will empty the stack and it may cause stack imbalance // it so we need to restore stack after unconditional throw to make JIT happy // this has an effect of executing Throw on an empty stack. Result value = RewriteExpressionFreeTemps(node.Operand, Stack.Empty); RewriteAction action = value.Action; if (stack != Stack.Empty) { action = RewriteAction.SpillStack; } if (action != RewriteAction.None) { expr = new UnaryExpression(ExpressionType.Throw, value.Node, node.Type, null); } return(new Result(action, expr)); }
// Called by Expression<T>.Accept(StackSpiller). internal Expression <T> Rewrite <T>(Expression <T> lambda) { VerifyTemps(); // Lambda starts with an empty stack. Result body = RewriteExpressionFreeTemps(lambda.Body, _startingStack); _lambdaRewrite = body.Action; VerifyTemps(); if (body.Action != RewriteAction.None) { // Create a new scope for temps. // Note that none of these will be hoisted so there is no closure impact. Expression newBody = body.Node; if (_tm.Temps.Count > 0) { newBody = Expression.Block(_tm.Temps, new TrueReadOnlyCollection <Expression>(newBody)); } // Clone the lambda, replacing the body & variables. return(Expression <T> .Create(newBody, lambda.Name, lambda.TailCall, new ParameterList(lambda))); } return(lambda); }
// BinaryExpression: AndAlso, OrElse private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack) { BinaryExpression node = (BinaryExpression)expr; // Left expression runs on a stack as left by parent Result left = RewriteExpression(node.Left, stack); // ... and so does the right one Result right = RewriteExpression(node.Right, stack); //conversion is a lambda. stack state will be ignored. Result conversion = RewriteExpression(node.Conversion, stack); RewriteAction action = left.Action | right.Action | conversion.Action; if (action != RewriteAction.None) { expr = BinaryExpression.Create( node.NodeType, left.Node, right.Node, node.Type, node.Method, (LambdaExpression)conversion.Node ); } return(new Result(action, expr)); }
// BinaryExpression: AndAlso, OrElse private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack) { var node = (BinaryExpression)expr; // Left expression runs on a stack as left by parent Result left = RewriteExpression(node.Left, stack); // ... and so does the right one Result right = RewriteExpression(node.Right, stack); //conversion is a lambda. stack state will be ignored. Result conversion = RewriteExpression(node.Conversion, stack); RewriteAction action = left.Action | right.Action | conversion.Action; if (action != RewriteAction.None) { // We don't have to worry about byref parameters here, because the // factory doesn't allow it (it requires identical parameters and // return type from the AndAlso/OrElse method) expr = BinaryExpression.Create( node.NodeType, left.Node, right.Node, node.Type, node.Method, (LambdaExpression)conversion.Node ); } return(new Result(action, expr)); }
private Result RewriteMemberInitExpression(Expression expr, Stack stack) { var node = (MemberInitExpression)expr; // Constructor runs on initial stack. Result result = RewriteExpression(node.NewExpression, stack); Expression rewrittenNew = result.Node; RewriteAction action = result.Action; ReadOnlyCollection <MemberBinding> bindings = node.Bindings; BindingRewriter[] bindingRewriters = new BindingRewriter[bindings.Count]; for (int i = 0; i < bindings.Count; i++) { MemberBinding binding = bindings[i]; // Bindings run on non-empty stack (the object instance is on it). BindingRewriter rewriter = BindingRewriter.Create(binding, this, Stack.NonEmpty); bindingRewriters[i] = rewriter; action |= rewriter.Action; } switch (action) { case RewriteAction.None: break; case RewriteAction.Copy: MemberBinding[] newBindings = new MemberBinding[bindings.Count]; for (int i = 0; i < bindings.Count; i++) { newBindings[i] = bindingRewriters[i].AsBinding(); } expr = new MemberInitExpression((NewExpression)rewrittenNew, new TrueReadOnlyCollection <MemberBinding>(newBindings)); break; case RewriteAction.SpillStack: RequireNotRefInstance(node.NewExpression); ParameterExpression tempNew = MakeTemp(rewrittenNew.Type); Expression[] comma = new Expression[bindings.Count + 2]; comma[0] = new AssignBinaryExpression(tempNew, rewrittenNew); for (int i = 0; i < bindings.Count; i++) { BindingRewriter cr = bindingRewriters[i]; Expression initExpr = cr.AsExpression(tempNew); comma[i + 1] = initExpr; } comma[bindings.Count + 1] = tempNew; expr = MakeBlock(comma); break; default: throw ContractUtils.Unreachable; } return(new Result(action, expr)); }
public void Execute_WithNullContext_Throws() { // Arrange RewriteAction action = new RewriteAction("/", RewriteProcessing.RestartProcessing); IRewriteContext context = null; // Act/Assert ExceptionAssert.Throws <ArgumentNullException>(() => action.Execute(context)); }
public void Execute_WithNullContext_Throws() { // Arrange RewriteAction action = new RewriteAction("/", RewriteProcessing.RestartProcessing); IRewriteContext context = null; // Act/Assert ExceptionAssert.Throws<ArgumentNullException>(() => action.Execute(context)); }
public RewriteAttribute(string typeName = null, string targetName = null, RewriteAction action = RewriteAction.None, string newName = null, string oldName = null, StubAction stubAction = StubAction.UseOld, string contentHandler = null) { this.typeName = typeName; this.targetName = targetName; this.action = action; this.newName = newName; this.oldName = oldName; this.stubAction = stubAction; this.contentHandler = contentHandler; }
public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri_CodedRule(string conditionInputPattern, string expectedResult, int uriMatchPart) { // arrange var inputParser = new InputParser(); var ruleBuilder = new UrlRewriteRuleBuilder { Name = "test", Global = false }; ruleBuilder.AddUrlMatch(".*"); var condition = new UriMatchCondition( inputParser, "{REQUEST_URI}", conditionInputPattern, (UriMatchPart)uriMatchPart, ignoreCase: true, negate: false); ruleBuilder.ConfigureConditionBehavior(LogicalGrouping.MatchAll, trackAllCaptures: true); ruleBuilder.AddUrlCondition(condition); var action = new RewriteAction( RuleResult.SkipRemainingRules, inputParser.ParseInputString(@"http://www.test.com{C:1}", (UriMatchPart)uriMatchPart), queryStringAppend: false); ruleBuilder.AddUrlAction(action); var options = new RewriteOptions().Add(ruleBuilder.Build()); using var host = new HostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseTestServer() .Configure(app => { app.UseRewriter(options); app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl())); }); }).Build(); await host.StartAsync(); var server = host.GetTestServer(); // act var response = await server.CreateClient().GetStringAsync("http://localhost/foo/bar"); // assert Assert.Equal(expectedResult, response); }
// RewriteMemberInitExpression private Result RewriteMemberInitExpression(Expression expr, Stack stack) { MemberInitExpression node = (MemberInitExpression)expr; //ctor runs on original stack Result result = RewriteExpression(node.NewExpression, stack); Expression rewrittenNew = result.Node; RewriteAction action = result.Action; ReadOnlyCollection <MemberBinding> bindings = node.Bindings; BindingRewriter[] bindingRewriters = new BindingRewriter[bindings.Count]; for (int i = 0; i < bindings.Count; i++) { MemberBinding binding = bindings[i]; //bindings run on nonempty stack BindingRewriter rewriter = BindingRewriter.Create(binding, this, Stack.NonEmpty); bindingRewriters[i] = rewriter; action |= rewriter.Action; } switch (action) { case RewriteAction.None: break; case RewriteAction.Copy: MemberBinding[] newBindings = new MemberBinding[bindings.Count]; for (int i = 0; i < bindings.Count; i++) { newBindings[i] = bindingRewriters[i].AsBinding(); } expr = Expression.MemberInit((NewExpression)rewrittenNew, new ReadOnlyCollection <MemberBinding>(newBindings)); break; case RewriteAction.SpillStack: ParameterExpression tempNew = MakeTemp(rewrittenNew.Type); Expression[] comma = new Expression[bindings.Count + 2]; comma[0] = Expression.Assign(tempNew, rewrittenNew); for (int i = 0; i < bindings.Count; i++) { BindingRewriter cr = bindingRewriters[i]; Expression initExpr = cr.AsExpression(tempNew); comma[i + 1] = initExpr; } comma[bindings.Count + 1] = tempNew; expr = Expression.Block(comma); break; default: throw Assert.Unreachable; } return(new Result(action, expr)); }
public void TestSerializeRewriteCodeFolder() { var rc = new RewriteCodeFolder(".", "*.cs"); var text = rc.SerializeMe(); var newClass = RewriteAction.UnSerializeMe(text) as RewriteCodeFolder; Assert.IsNotNull(newClass); //File.WriteAllText("a.txt", text); //Process.Start("notepad.exe", "a.txt"); Assert.AreEqual(rc.FolderName, newClass.FolderName); }
public void IsMatch_WhenNoConditions_ReturnsTrue() { // Arrange RewriteAction action = new RewriteAction("/", RewriteProcessing.RestartProcessing); IRewriteContext context = new MockRewriteContext(); // Act bool match = action.IsMatch(context); // Assert Assert.IsTrue(match); }
private static Result RewriteLambdaExpression(Expression expr) { var node = (LambdaExpression)expr; // Call back into the rewriter expr = AnalyzeLambda(node); // If the lambda gets rewritten, we don't need to spill the stack, // but we do need to rebuild the tree above us so it includes the new node. RewriteAction action = (expr == node) ? RewriteAction.None : RewriteAction.Copy; return(new Result(action, expr)); }
public void TestSerializeRewriteCodeFolderFormatter() { var rc = new RewriteCodeFolder(".", "*.cs"); rc.Formatter.FormatterFirstLine = "System.Console.WriteLine('andrei ignat')"; var text = rc.SerializeMe(); var newClass = RewriteAction.UnSerializeMe(text) as RewriteCodeFolder; Assert.IsNotNull(newClass); //File.WriteAllText("a.txt", text); //Process.Start("notepad.exe", "a.txt"); rc.Formatter.FormatterFirstLine.ShouldBe(newClass.Formatter.FormatterFirstLine); }
public void IsMatch_WhenSingleConditionDoesNotMatch_ReturnsFalse() { // Arrange RewriteAction action = new RewriteAction("/", RewriteProcessing.RestartProcessing); IRewriteContext context = new MockRewriteContext(); action.Conditions.Add(new MockRewriteCondition(false)); // Act bool match = action.IsMatch(context); // Assert Assert.IsFalse(match); }
public void TestSerializeRewriteCodeFile() { #region arrange var rc = new RewriteCodeFile("andrei.cs"); #endregion #region act var text = rc.SerializeMe(); var newClass = RewriteAction.UnSerializeMe(text) as RewriteCodeFile; #endregion #region assert Assert.IsNotNull(newClass); Assert.AreEqual(rc.FileName, newClass.FileName); #endregion }
// DebugInfoExpression private Result RewriteDebugInfoExpression(Expression expr, Stack stack) { var node = (DebugInfoExpression)expr; Result body = RewriteExpression(node.Expression, stack); RewriteAction action = body.Action; if (action != RewriteAction.None) { expr = new DebugInfoExpression(body.Node, node.Document, node.StartLine, node.StartColumn, node.EndLine, node.EndColumn); } return(new Result(action, expr)); }
public void IsMatch_WhenMultipleMatchingConditions_ReturnsTrue() { // Arrange RewriteAction action = new RewriteAction("/", RewriteProcessing.RestartProcessing); IRewriteContext context = new MockRewriteContext(); action.Conditions.Add(new MockRewriteCondition(true)); action.Conditions.Add(new MockRewriteCondition(true)); // Act bool match = action.IsMatch(context); // Assert Assert.IsTrue(match); }
private int OnExecute() { Console.WriteLine($"processing files accordingly to settings from {Name}"); var i = new Interpret(); var text = i.InterpretText(File.ReadAllText(Name)); var rewrite = RewriteAction.UnSerializeMe(text); rewrite.Rewrite(); return(0); //for (var i = 0; i < Count; i++) //{ // Console.WriteLine($"Hello {Name}!"); //} //return 0; }
// SwitchStatement private Result RewriteSwitchExpression(Expression expr, Stack stack) { SwitchExpression node = (SwitchExpression)expr; // The switch statement test is emitted on the stack in current state Result test = RewriteExpressionFreeTemps(node.Test, stack); RewriteAction action = test.Action; ReadOnlyCollection <SwitchCase> cases = node.SwitchCases; SwitchCase[] clone = null; for (int i = 0; i < cases.Count; i++) { SwitchCase @case = cases[i]; // And all the cases also run on the same stack level. Result body = RewriteExpression(@case.Body, stack); action |= body.Action; if (body.Action != RewriteAction.None) { @case = new SwitchCase(@case.IsDefault, @case.Value, body.Node); if (clone == null) { clone = Clone(cases, i); } } if (clone != null) { clone[i] = @case; } } if (action != RewriteAction.None) { if (clone != null) { // okay to wrap because we aren't modifying the array cases = new ReadOnlyCollection <SwitchCase>(clone); } expr = new SwitchExpression(test.Node, node.BreakLabel, cases); } return(new Result(action, expr)); }
public void Execute_SetsLocation_ReturnsCorrectValue() { // Arrange string location = "/NewLocation"; RewriteProcessing processing = RewriteProcessing.RestartProcessing; RewriteAction action = new RewriteAction(location, processing); action.Conditions.Add(new MockRewriteCondition(true)); IRewriteContext context = new MockRewriteContext(); // Act RewriteProcessing result = action.Execute(context); // Assert Assert.AreEqual(processing, result); Assert.AreEqual(location, context.Location); }
// BinaryExpression: AndAlso, OrElse private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack) { BinaryExpression node = (BinaryExpression)expr; // Left expression runs on a stack as left by parent Result left = RewriteExpression(node.Left, stack); // ... and so does the right one Result right = RewriteExpression(node.Right, stack); //conversion is a lambda. stack state will be ignored. Result conversion = RewriteExpression(node.Conversion, stack); RewriteAction action = left.Action | right.Action | conversion.Action; if (action != RewriteAction.None) { // We don't have to worry about byref parameters here, because the // factory doesn't allow it (it requires identical parameters and // return type from the AndAlso/OrElse method) expr = BinaryExpressionStubs.Create( node.NodeType, left.Node, right.Node, node.Type, node.Method, (LambdaExpression)conversion.Node ); #if !LINQ /* * CONSIDER: Move logic to reduce logical binary nodes from the Reducer to the stack spiller. * * switch (expr.NodeType) * { * case ExpressionType.AndAlso: * case ExpressionType.OrElse: * expr = Microsoft.CSharp.Expressions.Compiler.Reducer.ReduceLogical((BinaryExpression)expr); * break; * case ExpressionType.Coalesce: * expr = Microsoft.CSharp.Expressions.Compiler.Reducer.ReduceCoalesce((BinaryExpression)expr); * break; * } */ #endif } return(new Result(action, expr)); }
/// <summary> /// Adds a child <paramref name="expression" /> to the rewriter, causing /// it to be rewritten using the parent stack spiller, and the evaluation /// stack state and rewrite action to be updated accordingly. /// </summary> /// <param name="expression">The child expression to add.</param> internal void Add(Expression expression) { Debug.Assert(!_done); var exp = _self.RewriteExpression(expression, _stack); Action |= exp.Action; _stack = Stack.NonEmpty; if (exp.Action == RewriteAction.SpillStack) { _lastSpillIndex = _expressionsCount; } // Track items in case we need to copy or spill stack. _expressions[_expressionsCount++] = exp.Node; }
internal void Add(Expression node) { Debug.Assert(!_done); if (node == null) { _expressions[_expressionsCount++] = null; return; } Result exp = _self.RewriteExpression(node, _stack); _action |= exp.Action; _stack = Stack.NonEmpty; // track items in case we need to copy or spill stack _expressions[_expressionsCount++] = exp.Node; }
/// <summary> /// Parses the node. /// </summary> /// <param name="node">The node to parse.</param> /// <param name="config">The rewriter configuration.</param> /// <returns>The parsed action, or null if no action parsed.</returns> public override IRewriteAction Parse(XmlNode node, object config) { if (node == null) { throw new ArgumentNullException("node"); } if (config == null) { throw new ArgumentNullException("config"); } XmlNode toNode = node.Attributes[Constants.AttrTo]; if (toNode.Value == null) { throw new ConfigurationErrorsException(MessageProvider.FormatString(Message.AttributeRequired, Constants.AttrTo), node); } XmlNode processingNode = node.Attributes[Constants.AttrProcessing]; var processing = RewriteProcessing.ContinueProcessing; if (processingNode != null) { if (processingNode.Value == Constants.AttrValueRestart) { processing = RewriteProcessing.RestartProcessing; } else if (processingNode.Value == Constants.AttrValueStop) { processing = RewriteProcessing.StopProcessing; } else if (processingNode.Value != Constants.AttrValueContinue) { throw new ConfigurationErrorsException(MessageProvider.FormatString(Message.ValueOfProcessingAttribute, processingNode.Value, Constants.AttrValueContinue, Constants.AttrValueRestart, Constants.AttrValueStop), node); } } var action = new RewriteAction(toNode.Value, processing); this.ParseConditions(node, action.Conditions, false, config); return(action); }
// ConditionalExpression private Result RewriteConditionalExpression(Expression expr, Stack stack) { ConditionalExpression node = (ConditionalExpression)expr; // Test executes at the stack as left by parent Result test = RewriteExpression(node.Test, stack); // The test is popped by conditional jump so branches execute // at the stack as left by parent too. Result ifTrue = RewriteExpression(node.IfTrue, stack); Result ifFalse = RewriteExpression(node.IfFalse, stack); RewriteAction action = test.Action | ifTrue.Action | ifFalse.Action; if (action != RewriteAction.None) { expr = Expression.Condition(test.Node, ifTrue.Node, ifFalse.Node, node.Type); } return(new Result(action, expr)); }
private static Result RewriteLambdaExpression(Expression expr, Stack stack) { #if LINQ LambdaExpression node = (LambdaExpression)expr; // Call back into the rewriter expr = AnalyzeLambda(node); // If the lambda gets rewritten, we don't need to spill the stack, // but we do need to rebuild the tree above us so it includes the new node. RewriteAction action = (expr == node) ? RewriteAction.None : RewriteAction.Copy; return(new Result(action, expr)); #else // NB: We're only spilling for await sites (unlike LINQ where the whole tree is analyzed recursively). // Nested async lambdas will be reduced prior to spilling, so we don't have to recurse here. We // don't care about nested synchronous lambdas because those don't have await sites. return(new Result(RewriteAction.None, expr)); #endif }
/// <summary> /// Parses the node. /// </summary> /// <param name="node">The node to parse.</param> /// <param name="config">The rewriter configuration.</param> /// <returns>The parsed action, or null if no action parsed.</returns> public override IRewriteAction Parse(XmlNode node, IRewriterConfiguration config) { if (node == null) { throw new ArgumentNullException("node"); } if (config == null) { throw new ArgumentNullException("config"); } var to = node.GetRequiredAttribute(Constants.AttrTo, true); var processing = ParseProcessing(node); var action = new RewriteAction(to, processing); ParseConditions(node, action.Conditions, false, config); return(action); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); Swagger.Builder(app); app.UseRouting(); RewriteAction.DefaultUrl(app); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
/// <summary> /// Parses the node. /// </summary> /// <param name="node">The node to parse.</param> /// <param name="config">The rewriter configuration.</param> /// <returns>The parsed action, or null if no action parsed.</returns> public override IRewriteAction Parse(XmlNode node, RewriterConfiguration config) { if (node == null) { throw new ArgumentNullException("node"); } if (config == null) { throw new ArgumentNullException("config"); } string to = node.GetRequiredAttribute(Constants.AttrTo, true); XmlNode processingNode = node.Attributes[Constants.AttrProcessing]; RewriteProcessing processing = RewriteProcessing.ContinueProcessing; if (processingNode != null) { if (processingNode.Value == Constants.AttrValueRestart) { processing = RewriteProcessing.RestartProcessing; } else if (processingNode.Value == Constants.AttrValueStop) { processing = RewriteProcessing.StopProcessing; } else if (processingNode.Value != Constants.AttrValueContinue) { throw new ConfigurationErrorsException(MessageProvider.FormatString(Message.ValueOfProcessingAttribute, processingNode.Value, Constants.AttrValueContinue, Constants.AttrValueRestart, Constants.AttrValueStop), node); } } RewriteAction action = new RewriteAction(to, processing); ParseConditions(node, action.Conditions, false, config); return(action); }
/// <summary> /// Adds a child <paramref name="expression"/> to the rewriter, causing /// it to be rewritten using the parent stack spiller, and the evaluation /// stack state and rewrite action to be updated accordingly. /// </summary> /// <param name="expression">The child expression to add.</param> internal void Add(Expression expression) { Debug.Assert(!_done); if (expression == null) { _expressions[_expressionsCount++] = null; return; } Result exp = _self.RewriteExpression(expression, _stack); _action |= exp.Action; _stack = Stack.NonEmpty; if (exp.Action == RewriteAction.SpillStack) { _lastSpillIndex = _expressionsCount; } // Track items in case we need to copy or spill stack. _expressions[_expressionsCount++] = exp.Node; }