Example #1
0
		public override bool DoMatch(INode other, Match match)
		{
			var last = match.Get (referencedGroupName).Last ();
			if (last == null && other == null)
				return true;
			return last.IsMatch(other);
		}
		public override bool DoMatch(INode other, Match match)
		{
			CSharp.IdentifierExpression ident = other as CSharp.IdentifierExpression;
			if (ident == null || ident.TypeArguments.Any())
				return false;
			CSharp.AstNode referenced = (CSharp.AstNode)match.Get(referencedGroupName).Last();
			if (referenced == null)
				return false;
			return ident.Identifier == referenced.GetChildByRole(CSharp.AstNode.Roles.Identifier).Name;
		}
Example #3
0
        Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool?isChecked = null)
        {
            if (invocation.Arguments.Count < 2)
            {
                return(NotSupported(invocation));
            }

            Expression left = Convert(invocation.Arguments.ElementAt(0));

            if (left == null)
            {
                return(null);
            }
            Expression right = Convert(invocation.Arguments.ElementAt(1));

            if (right == null)
            {
                return(null);
            }

            BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right);

            if (isChecked != null)
            {
                boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
            }

            switch (invocation.Arguments.Count)
            {
            case 2:
                return(boe);

            case 3:
                Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2));
                if (m.Success)
                {
                    return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>()));
                }
                else
                {
                    return(null);
                }

            case 4:
                if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2)))
                {
                    return(null);
                }
                m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3));
                if (m.Success)
                {
                    return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>()));
                }
                else
                {
                    return(null);
                }

            default:
                return(NotSupported(invocation));
            }
        }
Example #4
0
        Expression ConvertNewObject(InvocationExpression invocation)
        {
            if (invocation.Arguments.Count < 1 || invocation.Arguments.Count > 3)
            {
                return(NotSupported(invocation));
            }

            Match m = newObjectCtorPattern.Match(invocation.Arguments.First());

            if (!m.Success)
            {
                return(NotSupported(invocation));
            }

            IMethod ctor = m.Get <AstNode>("ctor").Single().Annotation <IMethod>();

            if (ctor == null)
            {
                return(null);
            }

            AstType       declaringTypeNode;
            ITypeDefOrRef declaringType;

            if (m.Has("declaringType"))
            {
                declaringTypeNode = m.Get <AstType>("declaringType").Single().Clone();
                declaringType     = declaringTypeNode.Annotation <ITypeDefOrRef>();
            }
            else
            {
                declaringTypeNode = AstBuilder.ConvertType(ctor.DeclaringType);
                declaringType     = ctor.DeclaringType;
            }
            if (declaringTypeNode == null)
            {
                return(null);
            }

            ObjectCreateExpression oce = new ObjectCreateExpression(declaringTypeNode);

            if (invocation.Arguments.Count >= 2)
            {
                IList <Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAtOrDefault(1));
                if (arguments == null)
                {
                    return(null);
                }
                oce.Arguments.AddRange(arguments);
            }
            if (invocation.Arguments.Count >= 3 && declaringType.IsAnonymousType())
            {
                MethodDef resolvedCtor = ctor.ResolveMethodDef();
                if (resolvedCtor == null || resolvedCtor.Parameters.Count != oce.Arguments.Count)
                {
                    return(null);
                }
                AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
                var arguments = oce.Arguments.ToArray();
                if (AstMethodBodyBuilder.CanInferAnonymousTypePropertyNamesFromArguments(arguments, resolvedCtor.Parameters))
                {
                    oce.Arguments.MoveTo(atce.Initializers);
                }
                else
                {
                    for (int i = 0; i < resolvedCtor.Parameters.Count; i++)
                    {
                        atce.Initializers.Add(
                            new NamedExpression {
                            Name       = resolvedCtor.Parameters[i].Name,
                            Expression = arguments[i].Detach()
                        });
                    }
                }
                return(atce);
            }

            return(oce);
        }
Example #5
0
        static CodeAction HandleNegatedCase(BaseRefactoringContext ctx, IfElseStatement ifElseStatement, Match match, out IsExpression isExpression, out int foundCastCount)
        {
            foundCastCount = 0;
            var outerIs = match.Get <Expression>("isExpression").Single();

            isExpression = AlUtil.GetInnerMostExpression(outerIs) as IsExpression;
            var obj        = AlUtil.GetInnerMostExpression(isExpression.Expression);
            var castToType = isExpression.Type;

            var cast = new Choice {
                PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastTo(castToType.Clone())),
                PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastAs(castToType.Clone()))
            };

            var rr = ctx.Resolve(castToType);

            if (rr == null || rr.IsError || rr.Type.IsReferenceType == false)
            {
                return(null);
            }
            var foundCasts = ifElseStatement.GetParent <BlockStatement>().DescendantNodes(n => n.StartLocation >= ifElseStatement.StartLocation && !cast.IsMatch(n)).Where(n => cast.IsMatch(n)).ToList();

            foundCastCount = foundCasts.Count;

            return(new CodeAction(ctx.TranslateString("Use 'as' and check for null"), script => {
                var varName = ctx.GetNameProposal(CreateMethodDeclarationAction.GuessNameFromType(rr.Type), ifElseStatement.StartLocation);
                var varDec = new VariableDeclarationStatement(new PrimitiveType("var"), varName, new AsExpression(obj.Clone(), castToType.Clone()));
                var binaryOperatorIdentifier = new IdentifierExpression(varName);
                var binaryOperatorExpression = new BinaryOperatorExpression(binaryOperatorIdentifier, BinaryOperatorType.Equality, new NullReferenceExpression());
                var linkedNodes = new List <AstNode>();
                linkedNodes.Add(varDec.Variables.First().NameToken);
                linkedNodes.Add(binaryOperatorIdentifier);
                if (IsEmbeddedStatement(ifElseStatement))
                {
                    var block = new BlockStatement();
                    block.Add(varDec);
                    var newIf = (IfElseStatement)ifElseStatement.Clone();
                    newIf.Condition = binaryOperatorExpression;
                    foreach (var node in newIf.DescendantNodesAndSelf(n => !cast.IsMatch(n)).Where(n => cast.IsMatch(n)))
                    {
                        var id = new IdentifierExpression(varName);
                        linkedNodes.Add(id);
                        node.ReplaceWith(id);
                    }
                    block.Add(newIf);
                    script.Replace(ifElseStatement, block);
                }
                else
                {
                    script.InsertBefore(ifElseStatement, varDec);
                    script.Replace(ifElseStatement.Condition, binaryOperatorExpression);
                    foreach (var c in foundCasts)
                    {
                        var id = new IdentifierExpression(varName);
                        linkedNodes.Add(id);
                        script.Replace(c, id);
                    }
                }
                script.Link(linkedNodes);
            }, isExpression.IsToken));
        }
Example #6
0
        Expression ConvertCall(InvocationExpression invocation)
        {
            if (invocation.Arguments.Count < 2)
            {
                return(NotSupported(invocation));
            }

            Expression target;
            int        firstArgumentPosition;

            Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(0));

            if (m.Success)
            {
                target = null;
                firstArgumentPosition = 1;
            }
            else
            {
                m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
                if (!m.Success)
                {
                    return(NotSupported(invocation));
                }
                target = invocation.Arguments.ElementAt(0);
                firstArgumentPosition = 2;
            }

            IMethod mr = m.Get <AstNode>("method").Single().Annotation <IMethod>();

            if (mr == null)
            {
                return(null);
            }

            Expression convertedTarget;

            if (target == null || target is NullReferenceExpression)
            {
                // static method
                if (m.Has("declaringType"))
                {
                    convertedTarget = new TypeReferenceExpression(m.Get <AstType>("declaringType").Single().Clone());
                }
                else
                {
                    convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType));
                }
            }
            else
            {
                convertedTarget = Convert(target);
                if (convertedTarget == null)
                {
                    return(null);
                }
            }

            MemberReferenceExpression mre = convertedTarget.Member(mr.Name);
            var gim = mr as MethodSpec;

            if (gim != null)
            {
                foreach (var tr in gim.GenericInstMethodSig.GenericArguments)
                {
                    mre.TypeArguments.Add(AstBuilder.ConvertType(tr));
                }
            }
            IList <Expression> arguments = null;

            if (invocation.Arguments.Count == firstArgumentPosition + 1)
            {
                Expression argumentArray = invocation.Arguments.ElementAt(firstArgumentPosition);
                arguments = ConvertExpressionsArray(argumentArray);
            }
            if (arguments == null)
            {
                arguments = new List <Expression>();
                foreach (Expression argument in invocation.Arguments.Skip(firstArgumentPosition))
                {
                    Expression convertedArgument = Convert(argument);
                    if (convertedArgument == null)
                    {
                        return(null);
                    }
                    arguments.Add(convertedArgument);
                }
            }
            var methodDef = mr.ResolveMethodDef();

            if (methodDef != null && methodDef.IsGetter)
            {
                PropertyDef indexer = AstMethodBodyBuilder.GetIndexer(methodDef);
                if (indexer != null)
                {
                    return(new IndexerExpression(mre.Target.Detach(), arguments).WithAnnotation(indexer));
                }
            }
            return(new InvocationExpression(mre, arguments).WithAnnotation(mr));
        }
Example #7
0
            bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
            {
                if (!IsTransparentIdentifier(fromClause.Identifier))
                {
                    return(false);
                }
                Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

                if (!match.Success)
                {
                    return(false);
                }
                QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
                NamedExpression   nae1         = match.Get <NamedExpression>("nae1").SingleOrDefault();
                NamedExpression   nae2         = match.Get <NamedExpression>("nae2").SingleOrDefault();

                if (nae1 != null && nae1.Name != ((IdentifierExpression)nae1.Expression).Identifier)
                {
                    return(false);
                }
                Expression           nae2Expr      = match.Get <Expression>("nae2Expr").Single();
                IdentifierExpression nae2IdentExpr = nae2Expr as IdentifierExpression;

                if (nae2IdentExpr != null && (nae2 == null || nae2.Name == nae2IdentExpr.Identifier))
                {
                    // from * in (from x in ... select new { x = x, y = y }) ...
                    // =>
                    // from x in ... ...
                    fromClause.Remove();
                    selectClause.Remove();
                    // Move clauses from innerQuery to query
                    QueryClause insertionPos = null;
                    foreach (var clause in innerQuery.Clauses)
                    {
                        query.Clauses.InsertAfter(insertionPos, insertionPos = Detach(clause));
                    }
                }
                else
                {
                    // from * in (from x in ... select new { x = x, y = expr }) ...
                    // =>
                    // from x in ... let y = expr ...
                    fromClause.Remove();
                    selectClause.Remove();
                    // Move clauses from innerQuery to query
                    QueryClause insertionPos = null;
                    foreach (var clause in innerQuery.Clauses)
                    {
                        query.Clauses.InsertAfter(insertionPos, insertionPos = Detach(clause));
                    }
                    string ident;
                    if (nae2 != null)
                    {
                        ident = nae2.Name;
                    }
                    else if (nae2Expr is MemberReferenceExpression)
                    {
                        ident = ((MemberReferenceExpression)nae2Expr).MemberName;
                    }
                    else
                    {
                        throw new InvalidOperationException("Could not infer name from initializer in AnonymousTypeCreateExpression");
                    }
                    query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                        Identifier = ident, Expression = Detach(nae2Expr)
                    });
                }
                return(true);
            }
        // Module defining this command


        // Optional custom code for this activity


        /// <summary>
        /// Returns a configured instance of System.Management.Automation.PowerShell, pre-populated with the command to run.
        /// </summary>
        /// <param name="context">The NativeActivityContext for the currently running activity.</param>
        /// <returns>A populated instance of System.Management.Automation.PowerShell</returns>
        /// <remarks>The infrastructure takes responsibility for closing and disposing the PowerShell instance returned.</remarks>
        protected override ActivityImplementationContext GetPowerShell(NativeActivityContext context)
        {
            System.Management.Automation.PowerShell invoker       = global::System.Management.Automation.PowerShell.Create();
            System.Management.Automation.PowerShell targetCommand = invoker.AddCommand(PSCommandName);

            // Initialize the arguments

            if (InputObject.Expression != null)
            {
                targetCommand.AddParameter("InputObject", InputObject.Get(context));
            }

            if (FilterScript.Expression != null)
            {
                targetCommand.AddParameter("FilterScript", FilterScript.Get(context));
            }

            if (Property.Expression != null)
            {
                targetCommand.AddParameter("Property", Property.Get(context));
            }

            if (Value.Expression != null)
            {
                targetCommand.AddParameter("Value", Value.Get(context));
            }

            if (EQ.Expression != null)
            {
                targetCommand.AddParameter("EQ", EQ.Get(context));
            }

            if (CEQ.Expression != null)
            {
                targetCommand.AddParameter("CEQ", CEQ.Get(context));
            }

            if (NE.Expression != null)
            {
                targetCommand.AddParameter("NE", NE.Get(context));
            }

            if (CNE.Expression != null)
            {
                targetCommand.AddParameter("CNE", CNE.Get(context));
            }

            if (GT.Expression != null)
            {
                targetCommand.AddParameter("GT", GT.Get(context));
            }

            if (CGT.Expression != null)
            {
                targetCommand.AddParameter("CGT", CGT.Get(context));
            }

            if (LT.Expression != null)
            {
                targetCommand.AddParameter("LT", LT.Get(context));
            }

            if (CLT.Expression != null)
            {
                targetCommand.AddParameter("CLT", CLT.Get(context));
            }

            if (GE.Expression != null)
            {
                targetCommand.AddParameter("GE", GE.Get(context));
            }

            if (CGE.Expression != null)
            {
                targetCommand.AddParameter("CGE", CGE.Get(context));
            }

            if (LE.Expression != null)
            {
                targetCommand.AddParameter("LE", LE.Get(context));
            }

            if (CLE.Expression != null)
            {
                targetCommand.AddParameter("CLE", CLE.Get(context));
            }

            if (Like.Expression != null)
            {
                targetCommand.AddParameter("Like", Like.Get(context));
            }

            if (CLike.Expression != null)
            {
                targetCommand.AddParameter("CLike", CLike.Get(context));
            }

            if (NotLike.Expression != null)
            {
                targetCommand.AddParameter("NotLike", NotLike.Get(context));
            }

            if (CNotLike.Expression != null)
            {
                targetCommand.AddParameter("CNotLike", CNotLike.Get(context));
            }

            if (Match.Expression != null)
            {
                targetCommand.AddParameter("Match", Match.Get(context));
            }

            if (CMatch.Expression != null)
            {
                targetCommand.AddParameter("CMatch", CMatch.Get(context));
            }

            if (NotMatch.Expression != null)
            {
                targetCommand.AddParameter("NotMatch", NotMatch.Get(context));
            }

            if (CNotMatch.Expression != null)
            {
                targetCommand.AddParameter("CNotMatch", CNotMatch.Get(context));
            }

            if (Contains.Expression != null)
            {
                targetCommand.AddParameter("Contains", Contains.Get(context));
            }

            if (CContains.Expression != null)
            {
                targetCommand.AddParameter("CContains", CContains.Get(context));
            }

            if (NotContains.Expression != null)
            {
                targetCommand.AddParameter("NotContains", NotContains.Get(context));
            }

            if (CNotContains.Expression != null)
            {
                targetCommand.AddParameter("CNotContains", CNotContains.Get(context));
            }

            if (In.Expression != null)
            {
                targetCommand.AddParameter("In", In.Get(context));
            }

            if (CIn.Expression != null)
            {
                targetCommand.AddParameter("CIn", CIn.Get(context));
            }

            if (NotIn.Expression != null)
            {
                targetCommand.AddParameter("NotIn", NotIn.Get(context));
            }

            if (CNotIn.Expression != null)
            {
                targetCommand.AddParameter("CNotIn", CNotIn.Get(context));
            }

            if (Is.Expression != null)
            {
                targetCommand.AddParameter("Is", Is.Get(context));
            }

            if (IsNot.Expression != null)
            {
                targetCommand.AddParameter("IsNot", IsNot.Get(context));
            }


            return(new ActivityImplementationContext()
            {
                PowerShellInstance = invoker
            });
        }
Example #9
0
 void AddMatch(BinaryOperatorExpression binaryOperatorExpression, Match match, bool negateAny)
 {
     AddIssue(new CodeIssue(
                  binaryOperatorExpression,
                  ctx.TranslateString("Use 'Any()' for increased performance."),
                  negateAny ? ctx.TranslateString("Replace with call to '!Any()'") : ctx.TranslateString("Replace with call to 'Any()'"),
                  script => {
         Expression expr = new InvocationExpression(new MemberReferenceExpression(match.Get <Expression>("expr").First().Clone(), "Any"));
         if (negateAny)
         {
             expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
         }
         script.Replace(binaryOperatorExpression, expr);
     }
                  ));
 }
        internal void HandleInstanceFieldInitializers(IEnumerable <AstNode> members)
        {
            var instanceCtors = members.OfType <ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
            var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray();

            if (instanceCtorsNotChainingWithThis.Length > 0)
            {
                var ctorMethodDef = instanceCtorsNotChainingWithThis[0].GetSymbol() as IMethod;
                if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsReferenceType == false)
                {
                    return;
                }

                bool ctorIsUnsafe = instanceCtorsNotChainingWithThis.All(c => c.HasModifier(Modifiers.Unsafe));

                // Recognize field or property initializers:
                // Translate first statement in all ctors (if all ctors have the same statement) into an initializer.
                bool allSame;
                do
                {
                    Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
                    if (!m.Success)
                    {
                        break;
                    }
                    IMember fieldOrPropertyOrEvent = (m.Get <AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition;
                    if (!(fieldOrPropertyOrEvent is IField) && !(fieldOrPropertyOrEvent is IProperty) && !(fieldOrPropertyOrEvent is IEvent))
                    {
                        break;
                    }
                    var fieldOrPropertyOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrPropertyOrEvent) as EntityDeclaration;
                    // Cannot transform if member is not found or if it is a custom event.
                    if (fieldOrPropertyOrEventDecl == null || fieldOrPropertyOrEventDecl is CustomEventDeclaration)
                    {
                        break;
                    }
                    Expression initializer = m.Get <Expression>("initializer").Single();
                    // 'this'/'base' cannot be used in initializers
                    if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression))
                    {
                        break;
                    }

                    allSame = true;
                    for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++)
                    {
                        var otherMatch = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault());
                        if (!otherMatch.Success)
                        {
                            allSame = false;
                            break;
                        }
                        var otherMember = (otherMatch.Get <AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition;
                        if (!otherMember.Equals(fieldOrPropertyOrEvent))
                        {
                            allSame = false;
                        }
                        if (!initializer.IsMatch(otherMatch.Get <AstNode>("initializer").Single()))
                        {
                            allSame = false;
                        }
                    }
                    if (allSame)
                    {
                        foreach (var ctor in instanceCtorsNotChainingWithThis)
                        {
                            ctor.Body.First().Remove();
                        }
                        if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(initializer))
                        {
                            fieldOrPropertyOrEventDecl.Modifiers |= Modifiers.Unsafe;
                        }
                        if (fieldOrPropertyOrEventDecl is PropertyDeclaration pd)
                        {
                            pd.Initializer = initializer.Detach();
                        }
                        else
                        {
                            fieldOrPropertyOrEventDecl.GetChildrenByRole(Roles.Variable).Single().Initializer = initializer.Detach();
                        }
                    }
                } while (allSame);
            }
        }
Example #11
0
        bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, Dictionary <string, object> letClauses)
        {
            if (!IsTransparentIdentifier(fromClause.Identifier))
            {
                return(false);
            }
            QuerySelectClause selectClause = innerQuery.Clauses.Last() as QuerySelectClause;
            Match             match        = selectTransparentIdentifierPattern.Match(selectClause);

            if (!match.Success)
            {
                return(false);
            }

            // from * in (from x in ... select new { members of anonymous type }) ...
            // =>
            // from x in ... { let x = ... } ...
            fromClause.Remove();
            selectClause.Remove();
            // Move clauses from innerQuery to query
            QueryClause insertionPos = null;

            foreach (var clause in innerQuery.Clauses)
            {
                query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
            }

            foreach (var expr in match.Get <Expression>("expr"))
            {
                switch (expr)
                {
                case IdentifierExpression identifier:
                    letClauses[identifier.Identifier] = identifier.Annotation <ILVariableResolveResult>();
                    break;

                case MemberReferenceExpression member:
                    AddQueryLetClause(member.MemberName, member);
                    break;

                case NamedExpression namedExpression:
                    if (namedExpression.Expression is IdentifierExpression identifierExpression && namedExpression.Name == identifierExpression.Identifier)
                    {
                        letClauses[namedExpression.Name] = identifierExpression.Annotation <ILVariableResolveResult>();
                        continue;
                    }
                    AddQueryLetClause(namedExpression.Name, namedExpression.Expression);
                    break;
                }
            }
            return(true);

            void AddQueryLetClause(string name, Expression expression)
            {
                QueryLetClause letClause = new QueryLetClause {
                    Identifier = name, Expression = expression.Detach()
                };
                var annotation = new LetIdentifierAnnotation();

                letClause.AddAnnotation(annotation);
                letClauses[name] = annotation;
                query.Clauses.InsertAfter(insertionPos, letClause);
            }
        }
Example #12
0
        public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
        {
            Match m = doWhilePattern.Match(whileLoop);

            if (m.Success)
            {
                DoWhileStatement doLoop = new DoWhileStatement();
                doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get <Expression>("condition").Single().Detach());
                //doLoop.Condition.AcceptVisitor(new PushNegation(), null);
                BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
                block.Statements.Last().Remove();                 // remove if statement
                doLoop.EmbeddedStatement = block.Detach();
                doLoop.CopyAnnotationsFrom(whileLoop);
                whileLoop.ReplaceWith(doLoop);

                // we may have to extract variable definitions out of the loop if they were used in the condition:
                foreach (var varDecl in block.Statements.OfType <VariableDeclarationStatement>())
                {
                    VariableInitializer v = varDecl.Variables.Single();
                    if (doLoop.Condition.DescendantsAndSelf.OfType <IdentifierExpression>().Any(i => i.Identifier == v.Name))
                    {
                        AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
                        // move annotations from v to assign:
                        assign.CopyAnnotationsFrom(v);
                        v.RemoveAnnotations <object>();
                        // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
                        varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
                        varDecl.RemoveAnnotations <object>();

                        // insert the varDecl above the do-while loop:
                        doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
                    }
                }
                return(doLoop);
            }
            return(null);
        }
Example #13
0
        public string CombineQuery(AstNode node, AstNode rootQuery = null)
        {
            if (rootQuery == null)
            {
                rootQuery = node;
            }

            QueryExpression query = node as QueryExpression;

            if (query != null)
            {
                string continuationIdentifier = null;

                foreach (var clause in query.Clauses)
                {
                    var continuation = clause as QueryContinuationClause;
                    if (continuation != null)
                    {
                        CombineQuery(continuation.PrecedingQuery);
                    }

                    var from = clause as QueryFromClause;
                    if (from != null)
                    {
                        continuationIdentifier = CombineQuery(from.Expression, rootQuery);
                    }
                }

                QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
                QueryExpression innerQuery = fromClause.Expression as QueryExpression;
                if (innerQuery != null)
                {
                    continuationIdentifier = continuationIdentifier ?? ((QueryFromClause)innerQuery.Clauses.First()).Identifier;

                    string transparentIdentifier;
                    if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, continuationIdentifier, out transparentIdentifier))
                    {
                        RemoveTransparentIdentifierReferences(rootQuery, transparentIdentifier);
                    }
                    else if (fromClause.Type.IsNull)
                    {
                        QueryContinuationClause continuation = new QueryContinuationClause();
                        continuation.PrecedingQuery = innerQuery.Detach();
                        continuation.Identifier     = fromClause.Identifier;
                        fromClause.ReplaceWith(continuation);
                    }

                    return(transparentIdentifier);
                }
                else
                {
                    Match m = castPattern.Match(fromClause.Expression);
                    if (m.Success)
                    {
                        fromClause.Type       = m.Get <AstType>("targetType").Single().Detach();
                        fromClause.Expression = m.Get <Expression>("inExpr").Single().Detach();
                    }
                }
            }

            return(null);
        }
Example #14
0
        bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, string continuationIdentifier, out string transparentIdentifier)
        {
            transparentIdentifier = fromClause.Identifier;

            Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

            if (!match.Success)
            {
                return(false);
            }
            QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
            Expression        nae1         = match.Get <Expression>("nae1").SingleOrDefault();
            string            nae1Name     = ExtractExpressionName(ref nae1);

            if (nae1Name == null)
            {
                return(false);
            }

            Expression nae2     = match.Get <Expression>("nae2").SingleOrDefault();
            string     nae2Name = ExtractExpressionName(ref nae2);

            if (nae1Name == null)
            {
                return(false);
            }

            bool introduceLetClause = true;
            var  nae1Identifier     = nae1 as IdentifierExpression;
            var  nae2Identifier     = nae2 as IdentifierExpression;

            if (nae1Identifier != null && nae2Identifier != null && nae1Identifier.Identifier == nae1Name && nae2Identifier.Identifier == nae2Name)
            {
                introduceLetClause = false;
            }

            if (nae1Name != continuationIdentifier)
            {
                if (nae2Name == continuationIdentifier)
                {
                    //Members are in reversed order
                    string     tempName = nae1Name;
                    Expression tempNae  = nae1;

                    nae1Name = nae2Name;
                    nae1     = nae2;
                    nae2Name = tempName;
                    nae2     = tempNae;
                }
                else
                {
                    return(false);
                }
            }

            if (introduceLetClause && innerQuery.Clauses.OfType <QueryFromClause>().Any(from => from.Identifier == nae2Name))
            {
                return(false);
            }
            if (introduceLetClause && innerQuery.Clauses.OfType <QueryJoinClause>().Any(join => join.JoinIdentifier == nae2Name))
            {
                return(false);
            }

            // from * in (from x in ... select new { x = x, y = expr }) ...
            // =>
            // from x in ... let y = expr ...
            fromClause.Remove();
            selectClause.Remove();
            // Move clauses from innerQuery to query
            QueryClause insertionPos = null;

            foreach (var clause in innerQuery.Clauses)
            {
                query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
            }
            if (introduceLetClause)
            {
                query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                    Identifier = nae2Name, Expression = nae2.Detach()
                });
            }
            return(true);
        }
Example #15
0
        public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
        {
            var instanceCtors = typeDeclaration.Members.OfType <ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
            var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => thisCallPattern.Match(ctor.Body.Statements.FirstOrDefault()) == null).ToArray();

            if (instanceCtorsNotChainingWithThis.Length > 0 && typeDeclaration.ClassType == NRefactory.TypeSystem.ClassType.Class)
            {
                // Recognize field initializers:
                // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer.
                bool allSame;
                do
                {
                    Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
                    if (m == null)
                    {
                        break;
                    }

                    FieldDefinition fieldDef = m.Get("fieldAccess").Single().Annotation <FieldReference>().ResolveWithinSameModule();
                    if (fieldDef == null)
                    {
                        break;
                    }
                    AttributedNode fieldOrEventDecl = typeDeclaration.Members.FirstOrDefault(f => f.Annotation <FieldDefinition>() == fieldDef);
                    if (fieldOrEventDecl == null)
                    {
                        break;
                    }

                    allSame = true;
                    for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++)
                    {
                        if (instanceCtors[0].Body.First().Match(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()) == null)
                        {
                            allSame = false;
                        }
                    }
                    if (allSame)
                    {
                        foreach (var ctor in instanceCtorsNotChainingWithThis)
                        {
                            ctor.Body.First().Remove();
                        }
                        fieldOrEventDecl.GetChildrenByRole(AstNode.Roles.Variable).Single().Initializer = m.Get <Expression>("initializer").Single().Detach();
                    }
                } while (allSame);
            }

            // Now convert base constructor calls to initializers:
            base.VisitTypeDeclaration(typeDeclaration, data);

            // Remove single empty constructor:
            if (instanceCtors.Length == 1)
            {
                ConstructorDeclaration emptyCtor = new ConstructorDeclaration();
                emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public);
                emptyCtor.Body      = new BlockStatement();
                if (emptyCtor.Match(instanceCtors[0]) != null)
                {
                    instanceCtors[0].Remove();
                }
            }

            // Convert static constructor into field initializers if the class is BeforeFieldInit
            var staticCtor = typeDeclaration.Members.OfType <ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);

            if (staticCtor != null)
            {
                TypeDefinition typeDef = typeDeclaration.Annotation <TypeDefinition>();
                if (typeDef != null && typeDef.IsBeforeFieldInit)
                {
                    while (true)
                    {
                        ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
                        if (es == null)
                        {
                            break;
                        }
                        AssignmentExpression assignment = es.Expression as AssignmentExpression;
                        if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign)
                        {
                            break;
                        }
                        FieldDefinition fieldDef = assignment.Left.Annotation <FieldReference>().ResolveWithinSameModule();
                        if (fieldDef == null || !fieldDef.IsStatic)
                        {
                            break;
                        }
                        FieldDeclaration fieldDecl = typeDeclaration.Members.OfType <FieldDeclaration>().FirstOrDefault(f => f.Annotation <FieldDefinition>() == fieldDef);
                        if (fieldDecl == null)
                        {
                            break;
                        }
                        fieldDecl.Variables.Single().Initializer = assignment.Right.Detach();
                        es.Remove();
                    }
                    if (staticCtor.Body.Statements.Count == 0)
                    {
                        staticCtor.Remove();
                    }
                }
            }
            return(null);
        }
Example #16
0
        ArrayInitializerExpression ConvertMemberBindings(Expression elementsArray)
        {
            Match m = memberBindingArrayPattern.Match(elementsArray);

            if (!m.Success)
            {
                return(null);
            }
            ArrayInitializerExpression result = new ArrayInitializerExpression();

            foreach (var binding in m.Get <Expression>("binding"))
            {
                InvocationExpression bindingInvocation = binding as InvocationExpression;
                if (bindingInvocation == null || bindingInvocation.Arguments.Count != 2)
                {
                    return(null);
                }
                MemberReferenceExpression bindingMRE = bindingInvocation.Target as MemberReferenceExpression;
                if (bindingMRE == null || !expressionTypeReference.IsMatch(bindingMRE.Target))
                {
                    return(null);
                }

                Expression bindingTarget = bindingInvocation.Arguments.ElementAt(0);
                Expression bindingValue  = bindingInvocation.Arguments.ElementAt(1);

                string memberName;
                Match  m2 = getMethodFromHandlePattern.Match(bindingTarget);
                if (m2.Success)
                {
                    IMethod setter = m2.Get <AstNode>("method").Single().Annotation <IMethod>();
                    if (setter == null)
                    {
                        return(null);
                    }
                    memberName = GetPropertyName(setter);
                }
                else
                {
                    return(null);
                }

                Expression convertedValue;
                switch (bindingMRE.MemberName)
                {
                case "Bind":
                    convertedValue = Convert(bindingValue);
                    break;

                case "MemberBind":
                    convertedValue = ConvertMemberBindings(bindingValue);
                    break;

                case "ListBind":
                    convertedValue = ConvertElementInit(bindingValue);
                    break;

                default:
                    return(null);
                }
                if (convertedValue == null)
                {
                    return(null);
                }
                result.Elements.Add(new NamedExpression(memberName, convertedValue));
            }
            return(result);
        }
        void HandleInstanceFieldInitializers(IEnumerable <AstNode> members)
        {
            var instanceCtors = members.OfType <ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
            var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray();

            if (instanceCtorsNotChainingWithThis.Length > 0)
            {
                MethodDef ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation <MethodDef>();
                if (ctorMethodDef != null && DnlibExtensions.IsValueType(ctorMethodDef.DeclaringType))
                {
                    return;
                }

                // Recognize field initializers:
                // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer.
                bool allSame;
                do
                {
                    Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
                    if (!m.Success)
                    {
                        break;
                    }

                    FieldDef fieldDef = m.Get <AstNode>("fieldAccess").Single().Annotation <IField>().ResolveFieldWithinSameModule();
                    if (fieldDef == null)
                    {
                        break;
                    }
                    AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation <FieldDef>() == fieldDef);
                    if (fieldOrEventDecl == null)
                    {
                        break;
                    }
                    Expression initializer = m.Get <Expression>("initializer").Single();
                    // 'this'/'base' cannot be used in field initializers
                    if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression))
                    {
                        break;
                    }

                    allSame = true;
                    for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++)
                    {
                        if (!instanceCtors[0].Body.First().IsMatch(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()))
                        {
                            allSame = false;
                            break;
                        }
                    }
                    if (allSame)
                    {
                        var ctorIlRanges = new List <Tuple <MemberMapping, List <ILRange> > >(instanceCtorsNotChainingWithThis.Length);
                        for (int i = 0; i < instanceCtorsNotChainingWithThis.Length; i++)
                        {
                            var ctor = instanceCtorsNotChainingWithThis[i];
                            var stmt = ctor.Body.First();
                            stmt.Remove();
                            var mm = ctor.Annotation <MemberMapping>() ?? ctor.Body.Annotation <MemberMapping>();
                            Debug.Assert(mm != null);
                            if (mm != null)
                            {
                                ctorIlRanges.Add(Tuple.Create(mm, stmt.GetAllRecursiveILRanges()));
                            }
                        }
                        var varInit = fieldOrEventDecl.GetChildrenByRole(Roles.Variable).Single();
                        initializer.Remove();
                        initializer.RemoveAllILRangesRecursive();
                        varInit.Initializer = initializer;
                        fieldOrEventDecl.AddAnnotation(ctorIlRanges);
                    }
                } while (allSame);
            }
        }
Example #18
0
        public override object VisitBlockStatement(BlockStatement blockStatement, object data)
        {
            int numberOfVariablesOutsideBlock = currentlyUsedVariableNames.Count;

            base.VisitBlockStatement(blockStatement, data);
            foreach (ExpressionStatement stmt in blockStatement.Statements.OfType <ExpressionStatement>().ToArray())
            {
                Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt);
                if (!displayClassAssignmentMatch.Success)
                {
                    continue;
                }

                ILVariable variable = displayClassAssignmentMatch.Get <AstNode>("variable").Single().Annotation <ILVariable>();
                if (variable == null)
                {
                    continue;
                }
                TypeDef type = variable.Type.ToTypeDefOrRef().ResolveWithinSameModule();
                if (!IsPotentialClosure(context, type))
                {
                    continue;
                }
                if (displayClassAssignmentMatch.Get <AstType>("type").Single().Annotation <ITypeDefOrRef>().ResolveWithinSameModule() != type)
                {
                    continue;
                }

                // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses:
                bool ok = true;
                foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>())
                {
                    if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single())
                    {
                        if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation <IField>() != null && identExpr.Parent.Annotation <IField>().IsField))
                        {
                            ok = false;
                        }
                    }
                }
                if (!ok)
                {
                    continue;
                }
                Dictionary <IField, AstNode> dict = new Dictionary <IField, AstNode>();

                // Delete the variable declaration statement:
                VariableDeclarationStatement displayClassVarDecl = PatternStatementTransform.FindVariableDeclaration(stmt, variable.Name);
                if (displayClassVarDecl != null)
                {
                    displayClassVarDecl.Remove();                    //TODO: Save ILRanges
                }
                // Delete the assignment statement:
                AstNode cur = stmt.NextSibling;
                stmt.Remove();                //TODO: Save ILRanges

                // Delete any following statements as long as they assign parameters to the display class
                BlockStatement    rootBlock            = blockStatement.Ancestors.OfType <BlockStatement>().LastOrDefault() ?? blockStatement;
                List <ILVariable> parameterOccurrances = rootBlock.Descendants.OfType <IdentifierExpression>()
                                                         .Select(n => n.Annotation <ILVariable>()).Where(p => p != null && p.IsParameter).ToList();
                AstNode next;
                for (; cur != null; cur = next)
                {
                    next = cur.NextSibling;

                    // Test for the pattern:
                    // "variableName.MemberName = right;"
                    ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement(
                        new AssignmentExpression(
                            new NamedNode("left", new MemberReferenceExpression {
                        Target     = IdentifierExpression.Create(variable.Name, variable.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local),
                        MemberName = Pattern.AnyString
                    }),
                            new AnyNode("right")
                            )
                        );
                    Match m = closureFieldAssignmentPattern.Match(cur);
                    if (m.Success)
                    {
                        FieldDef fieldDef    = m.Get <MemberReferenceExpression>("left").Single().Annotation <IField>().ResolveFieldWithinSameModule();
                        AstNode  right       = m.Get <AstNode>("right").Single();
                        bool     isParameter = false;
                        bool     isDisplayClassParentPointerAssignment = false;
                        if (right is ThisReferenceExpression)
                        {
                            isParameter = true;
                        }
                        else if (right is IdentifierExpression)
                        {
                            // handle parameters only if the whole method contains no other occurrence except for 'right'
                            ILVariable v = right.Annotation <ILVariable>();
                            isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1;
                            if (!isParameter && IsPotentialClosure(context, v.Type.ToTypeDefOrRef().ResolveWithinSameModule()))
                            {
                                // parent display class within the same method
                                // (closure2.localsX = closure1;)
                                isDisplayClassParentPointerAssignment = true;
                            }
                        }
                        else if (right is MemberReferenceExpression)
                        {
                            // copy of parent display class reference from an outer lambda
                            // closure2.localsX = this.localsY
                            MemberReferenceExpression mre = m.Get <MemberReferenceExpression>("right").Single();
                            do
                            {
                                // descend into the targets of the mre as long as the field types are closures
                                FieldDef fieldDef2 = mre.Annotation <FieldDef>().ResolveFieldWithinSameModule();
                                if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ToTypeDefOrRef().ResolveWithinSameModule()))
                                {
                                    break;
                                }
                                // if we finally get to a this reference, it's copying a display class parent pointer
                                if (mre.Target is ThisReferenceExpression)
                                {
                                    isDisplayClassParentPointerAssignment = true;
                                }
                                mre = mre.Target as MemberReferenceExpression;
                            } while (mre != null);
                        }
                        if (isParameter || isDisplayClassParentPointerAssignment)
                        {
                            if (fieldDef != null)
                            {
                                dict[fieldDef] = right;
                            }
                            cur.Remove();                            //TODO: Save ILRanges
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                // Now create variables for all fields of the display class (except for those that we already handled as parameters)
                List <Tuple <AstType, ILVariable> > variablesToDeclare = new List <Tuple <AstType, ILVariable> >();
                foreach (FieldDef field in type.Fields)
                {
                    if (field.IsStatic)
                    {
                        continue;                         // skip static fields
                    }
                    if (dict.ContainsKey(field))          // skip field if it already was handled as parameter
                    {
                        continue;
                    }
                    string capturedVariableName = field.Name;
                    if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10)
                    {
                        capturedVariableName = capturedVariableName.Substring(10);
                    }
                    EnsureVariableNameIsAvailable(blockStatement, capturedVariableName);
                    currentlyUsedVariableNames.Add(capturedVariableName);
                    ILVariable ilVar = new ILVariable
                    {
                        GeneratedByDecompiler = true,
                        Name = capturedVariableName,
                        Type = field.FieldType,
                    };
                    variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, stringBuilder, field), ilVar));
                    dict[field] = IdentifierExpression.Create(capturedVariableName, TextTokenKind.Local).WithAnnotation(ilVar);
                }

                // Now figure out where the closure was accessed and use the simpler replacement expression there:
                foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>())
                {
                    if (identExpr.Identifier == variable.Name)
                    {
                        MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent;
                        AstNode replacement;
                        var     fieldDef = mre.Annotation <IField>().ResolveFieldWithinSameModule();
                        if (fieldDef != null && dict.TryGetValue(fieldDef, out replacement))
                        {
                            var newReplacement = replacement.Clone();
                            newReplacement.AddAnnotation(mre.GetAllRecursiveILRanges());
                            mre.ReplaceWith(newReplacement);
                        }
                    }
                }
                // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
                Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
                foreach (var tuple in variablesToDeclare)
                {
                    var newVarDecl = new VariableDeclarationStatement(tuple.Item2.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local, tuple.Item1, tuple.Item2.Name);
                    newVarDecl.Variables.Single().AddAnnotation(CapturedVariableAnnotation.Instance);
                    newVarDecl.Variables.Single().AddAnnotation(tuple.Item2);
                    blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
                }
            }
            currentlyUsedVariableNames.RemoveRange(numberOfVariablesOutsideBlock, currentlyUsedVariableNames.Count - numberOfVariablesOutsideBlock);
            return(null);
        }
Example #19
0
		public override bool DoMatch(INode other, Match match)
		{
			return match.Get(referencedGroupName).Last().IsMatch(other);
		}
Example #20
0
 public static Pair GetPair(this Match source, int first) =>
 new Pair(source.Get(first).AsInt(), source.Get(first + 1).AsInt());
Example #21
0
 public static Field MakeField(Match m) => new Field(m.Get(1), m.GetPair(2), m.GetPair(4));
Example #22
0
        private QueryExpression DecompileQuery(InvocationExpression invocation)
        {
            if (invocation == null)
            {
                return(null);
            }
            MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;

            if (mre == null)
            {
                return(null);
            }

            switch (mre.MemberName)
            {
            case "Select":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression body;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
                {
                    QueryExpression query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = parameterName, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = body.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "Cast":
            {
                if (invocation.Arguments.Count == 0 && mre.TypeArguments.Count == 1)
                {
                    var typeArgument = mre.TypeArguments.First();

                    QueryExpression query   = new QueryExpression();
                    string          varName = GenerateVariableName();
                    query.Clauses.Add(new QueryFromClause
                        {
                            Identifier = varName,
                            Expression = ExtractQuery(mre),
                            Type       = typeArgument.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "GroupBy":
            {
                if (invocation.Arguments.Count == 2)
                {
                    string     parameterName1, parameterName2;
                    Expression keySelector, elementSelector;
                    if (MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName1, out keySelector) &&
                        MatchSimpleLambda(invocation.Arguments.ElementAt(1), out parameterName2, out elementSelector) &&
                        parameterName1 == parameterName2)
                    {
                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName1, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(new QueryGroupClause {
                                Projection = elementSelector.Detach(), Key = keySelector.Detach()
                            });
                        return(query);
                    }
                }
                else if (invocation.Arguments.Count == 1)
                {
                    string     parameterName;
                    Expression keySelector;
                    if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out keySelector))
                    {
                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(new QueryGroupClause
                            {
                                Projection = new IdentifierExpression(parameterName),
                                Key        = keySelector.Detach()
                            });
                        return(query);
                    }
                }
                return(null);
            }

            case "SelectMany":
            {
                if (invocation.Arguments.Count != 2)
                {
                    return(null);
                }
                string     parameterName;
                Expression collectionSelector;
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName, out collectionSelector))
                {
                    return(null);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression;
                if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression)
                {
                    ParameterDeclaration p1    = lambda.Parameters.ElementAt(0);
                    ParameterDeclaration p2    = lambda.Parameters.ElementAt(1);
                    QueryExpression      query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = p1.Name, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = p2.Name, Expression = collectionSelector.Detach()
                        });
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = ((Expression)lambda.Body).Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "Where":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression body;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
                {
                    QueryExpression query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = parameterName, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QueryWhereClause {
                            Condition = body.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "OrderBy":
            case "OrderByDescending":
            case "ThenBy":
            case "ThenByDescending":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression orderExpression;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out orderExpression))
                {
                    if (ValidateThenByChain(invocation, parameterName))
                    {
                        QueryOrderClause     orderClause = new QueryOrderClause();
                        InvocationExpression tmp         = invocation;
                        while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending")
                        {
                            // insert new ordering at beginning
                            orderClause.Orderings.InsertAfter(
                                null, new QueryOrdering
                                {
                                    Expression = orderExpression.Detach(),
                                    Direction  = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
                                });

                            tmp = (InvocationExpression)mre.Target;
                            mre = (MemberReferenceExpression)tmp.Target;
                            MatchSimpleLambda(tmp.Arguments.Single(), out parameterName, out orderExpression);
                        }
                        // insert new ordering at beginning
                        orderClause.Orderings.InsertAfter(
                            null, new QueryOrdering
                            {
                                Expression = orderExpression.Detach(),
                                Direction  = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
                            });

                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(orderClause);
                        return(query);
                    }
                }
                return(null);
            }

            case "Join":
            case "GroupJoin":
            {
                if (invocation.Arguments.Count != 4)
                {
                    return(null);
                }
                Expression source1 = mre.Target;
                Expression source2 = invocation.Arguments.ElementAt(0);
                string     elementName1, elementName2;
                Expression key1, key2;
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(1), out elementName1, out key1))
                {
                    return(null);
                }
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(2), out elementName2, out key2))
                {
                    return(null);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression;
                if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression)
                {
                    ParameterDeclaration p1    = lambda.Parameters.ElementAt(0);
                    ParameterDeclaration p2    = lambda.Parameters.ElementAt(1);
                    QueryExpression      query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = elementName1, Expression = source1.Detach()
                        });
                    QueryJoinClause joinClause = new QueryJoinClause();

                    joinClause.JoinIdentifier = elementName2;                                        // join elementName2
                    joinClause.InExpression   = source2.Detach();                                    // in source2

                    Match castMatch = castPattern.Match(source2);
                    if (castMatch.Success)
                    {
                        Expression target = castMatch.Get <Expression>("inExpr").Single().Detach();
                        joinClause.Type         = castMatch.Get <AstType>("targetType").Single().Detach();
                        joinClause.InExpression = target;
                    }

                    joinClause.OnExpression     = key1.Detach();                                     // on key1
                    joinClause.EqualsExpression = key2.Detach();                                     // equals key2
                    if (mre.MemberName == "GroupJoin")
                    {
                        joinClause.IntoIdentifier = p2.Name;                                         // into p2.Name
                    }
                    query.Clauses.Add(joinClause);
                    Expression resultExpr = ((Expression)lambda.Body).Detach();
                    if (p1.Name != elementName1)
                    {
                        foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p1.Name))
                        {
                            identifier.Name = elementName1;
                        }
                    }
                    if (p2.Name != elementName2 && mre.MemberName != "GroupJoin")
                    {
                        foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p2.Name))
                        {
                            identifier.Name = elementName2;
                        }
                    }
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = resultExpr
                        });
                    return(query);
                }
                return(null);
            }

            default:
                return(null);
            }
        }
Example #23
0
 void AddIssue(AstNode invocationExpression, Match match, bool negate = false)
 {
     AddIssue(new CodeIssue(
                  invocationExpression,
                  ctx.TranslateString("Use 'is' operator"),
                  ctx.TranslateString("Replace with 'is' operator"),
                  s => {
         Expression expression = new IsExpression(CSharpUtil.AddParensForUnaryExpressionIfRequired(match.Get <Expression>("object").Single().Clone()), match.Get <AstType>("Type").Single().Clone());
         if (negate)
         {
             expression = new UnaryOperatorExpression(UnaryOperatorType.Not, new ParenthesizedExpression(expression));
         }
         s.Replace(invocationExpression, expression);
     }
                  ));
 }
Example #24
0
        public override object VisitBlockStatement(BlockStatement blockStatement, object data)
        {
            base.VisitBlockStatement(blockStatement, data);
            foreach (ExpressionStatement stmt in blockStatement.Statements.OfType <ExpressionStatement>().ToArray())
            {
                Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt);
                if (displayClassAssignmentMatch == null)
                {
                    continue;
                }

                ILVariable variable = displayClassAssignmentMatch.Get("variable").Single().Annotation <ILVariable>();
                if (variable == null)
                {
                    continue;
                }
                TypeDefinition type = variable.Type.ResolveWithinSameModule();
                if (!IsPotentialClosure(context, type))
                {
                    continue;
                }
                if (displayClassAssignmentMatch.Get("type").Single().Annotation <TypeReference>().ResolveWithinSameModule() != type)
                {
                    continue;
                }

                // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses:
                bool ok = true;
                foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>())
                {
                    if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single())
                    {
                        if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation <FieldReference>() != null))
                        {
                            ok = false;
                        }
                    }
                }
                if (!ok)
                {
                    continue;
                }
                Dictionary <FieldReference, AstNode> dict = new Dictionary <FieldReference, AstNode>();
                // Delete the variable declaration statement:
                AstNode cur = stmt.NextSibling;
                stmt.Remove();
                if (blockStatement.Parent.NodeType == NodeType.Member || blockStatement.Parent is Accessor)
                {
                    // Delete any following statements as long as they assign parameters to the display class
                    // Do parameter handling only for closures created in the top scope (direct child of method/accessor)
                    List <ILVariable> parameterOccurrances = blockStatement.Descendants.OfType <IdentifierExpression>()
                                                             .Select(n => n.Annotation <ILVariable>()).Where(p => p != null && p.IsParameter).ToList();
                    AstNode next;
                    for (; cur != null; cur = next)
                    {
                        next = cur.NextSibling;

                        // Test for the pattern:
                        // "variableName.MemberName = right;"
                        ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement(
                            new AssignmentExpression(
                                new NamedNode("left", new MemberReferenceExpression {
                            Target = new IdentifierExpression(variable.Name)
                        }),
                                new AnyNode("right")
                                )
                            );
                        Match m = closureFieldAssignmentPattern.Match(cur);
                        if (m != null)
                        {
                            AstNode right       = m.Get("right").Single();
                            bool    isParameter = false;
                            if (right is ThisReferenceExpression)
                            {
                                isParameter = true;
                            }
                            else if (right is IdentifierExpression)
                            {
                                // handle parameters only if the whole method contains no other occurrance except for 'right'
                                ILVariable param = right.Annotation <ILVariable>();
                                isParameter = param.IsParameter && parameterOccurrances.Count(c => c == param) == 1;
                            }
                            if (isParameter)
                            {
                                dict[m.Get <MemberReferenceExpression>("left").Single().Annotation <FieldReference>().ResolveWithinSameModule()] = right;
                                cur.Remove();
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                // Now create variables for all fields of the display class (except for those that we already handled as parameters)
                List <Tuple <AstType, string> > variablesToDeclare = new List <Tuple <AstType, string> >();
                foreach (FieldDefinition field in type.Fields)
                {
                    if (dict.ContainsKey(field))
                    {
                        continue;
                    }
                    variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), field.Name));
                    dict[field] = new IdentifierExpression(field.Name);
                }

                // Now figure out where the closure was accessed and use the simpler replacement expression there:
                foreach (var identExpr in blockStatement.Descendants.OfType <IdentifierExpression>())
                {
                    if (identExpr.Identifier == variable.Name)
                    {
                        MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent;
                        AstNode replacement;
                        if (dict.TryGetValue(mre.Annotation <FieldReference>().ResolveWithinSameModule(), out replacement))
                        {
                            mre.ReplaceWith(replacement.Clone());
                        }
                    }
                }
                // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
                Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
                foreach (var tuple in variablesToDeclare)
                {
                    var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2);
                    newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
                    blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
                }
            }
            return(null);
        }
Example #25
0
 public static ShipAction ToData(Match m) =>
 new ShipAction(m.Get(1)[0], m.Get(2).AsInt());