예제 #1
0
 public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
 {
     if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation)
     {
         SetState(context.Resolve(identifierExpression), VariableState.Used);
     }
 }
예제 #2
0
        public static IType GuessType(BaseRefactoringContext context, AstNode expr)
        {
            if (expr is SimpleType && expr.Role == Roles.TypeArgument)
            {
                if (expr.Parent is MemberReferenceExpression || expr.Parent is IdentifierExpression)
                {
                    var rr             = context.Resolve(expr.Parent);
                    var argumentNumber = expr.Parent.GetChildrenByRole(Roles.TypeArgument).TakeWhile(c => c != expr).Count();

                    var mgrr = rr as MethodGroupResolveResult;
                    if (mgrr != null && mgrr.Methods.Any() && mgrr.Methods.First().TypeArguments.Count > argumentNumber)
                    {
                        return(mgrr.Methods.First().TypeParameters[argumentNumber]);
                    }
                }
                else if (expr.Parent is MemberType || expr.Parent is SimpleType)
                {
                    var rr             = context.Resolve(expr.Parent);
                    var argumentNumber = expr.Parent.GetChildrenByRole(Roles.TypeArgument).TakeWhile(c => c != expr).Count();
                    var mgrr           = rr as TypeResolveResult;
                    if (mgrr != null && mgrr.Type.TypeParameterCount > argumentNumber)
                    {
                        return(mgrr.Type.GetDefinition().TypeParameters[argumentNumber]);
                    }
                }
            }

            var type          = GetValidTypes(context.Resolver, expr).ToArray();
            var typeInference = new TypeInference(context.Compilation);

            typeInference.Algorithm = TypeInferenceAlgorithm.Improved;
            var inferedType = typeInference.FindTypeInBounds(type, emptyTypes);

            return(inferedType);
        }
            Func <Expression, bool> GetChecker(Expression expression, IList <IdentifierExpression> identifiers)
            {
                // TODO: This only works for simple cases.
                IList <IMember>   members;
                IList <IVariable> locals;
                var identifierResolveResults = identifiers.Select(identifier => context.Resolve(identifier)).ToList();

                SplitResolveResults(identifierResolveResults, out members, out locals);

                if (expression is InvocationExpression || expression is ObjectCreateExpression)
                {
                    return(node => {
                        if (node is InvocationExpression || node is ObjectCreateExpression)
                        {
                            // We don't know what these might do, so assume it will change the initializer
                            return true;
                        }
                        var binaryOperator = node as BinaryOperatorExpression;
                        if (binaryOperator != null)
                        {
                            var resolveResult = context.Resolve(binaryOperator) as OperatorResolveResult;
                            if (resolveResult == null)
                            {
                                return false;
                            }
                            // Built-in operators are ok, user defined ones not so much
                            return resolveResult.UserDefinedOperatorMethod != null;
                        }
                        return IsConflictingAssignment(node, identifiers, members, locals);
                    });
                }
                else if (expression is IdentifierExpression)
                {
                    var initializerDependsOnMembers       = identifierResolveResults.Any(result => result is MemberResolveResult);
                    var initializerDependsOnReferenceType = identifierResolveResults.Any(result => result.Type.IsReferenceType == true);
                    return(node => {
                        if ((node is InvocationExpression || node is ObjectCreateExpression) &&
                            (initializerDependsOnMembers || initializerDependsOnReferenceType))
                        {
                            // Anything can happen...
                            return true;
                        }
                        var binaryOperator = node as BinaryOperatorExpression;
                        if (binaryOperator != null)
                        {
                            var resolveResult = context.Resolve(binaryOperator) as OperatorResolveResult;
                            if (resolveResult == null)
                            {
                                return false;
                            }
                            return resolveResult.UserDefinedOperatorMethod != null;
                        }
                        return IsConflictingAssignment(node, identifiers, members, locals);
                    });
                }

                return(node => false);
            }
예제 #4
0
            public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
            {
                base.VisitMemberReferenceExpression(memberReferenceExpression);
                var targetMember = context.Resolve(memberReferenceExpression) as MemberResolveResult;

                if (targetMember != null && targetMember.IsVirtualCall && targetMember.TargetResult is ThisResolveResult)
                {
                    CreateIssue(memberReferenceExpression);
                }
            }
예제 #5
0
            bool CheckExceptionType(ObjectCreateExpression objectCreateExpression, out Expression paramNode, out Expression altParam, out bool canAddParameterName)
            {
                paramNode           = null;
                altParam            = null;
                canAddParameterName = false;
                var rr = context.Resolve(objectCreateExpression.Type) as TypeResolveResult;

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

                var type = rr.Type;

                if (type.Name == typeof(ArgumentException).Name && type.Namespace == typeof(ArgumentException).Namespace)
                {
                    if (objectCreateExpression.Arguments.Count >= 2)
                    {
                        altParam  = objectCreateExpression.Arguments.ElementAt(0);
                        paramNode = objectCreateExpression.Arguments.ElementAt(1);
                    }
                    return(paramNode != null);
                }
                if (type.Name == typeof(ArgumentNullException).Name && type.Namespace == typeof(ArgumentNullException).Namespace ||
                    type.Name == typeof(ArgumentOutOfRangeException).Name && type.Namespace == typeof(ArgumentOutOfRangeException).Namespace ||
                    type.Name == typeof(DuplicateWaitObjectException).Name && type.Namespace == typeof(DuplicateWaitObjectException).Namespace)
                {
                    canAddParameterName = objectCreateExpression.Arguments.Count == 1;
                    if (objectCreateExpression.Arguments.Count >= 1)
                    {
                        paramNode = objectCreateExpression.Arguments.FirstOrDefault();
                        if (objectCreateExpression.Arguments.Count == 2)
                        {
                            altParam = objectCreateExpression.Arguments.ElementAt(1);
                            if (!context.Resolve(altParam).Type.IsKnownType(KnownTypeCode.String))
                            {
                                paramNode = null;
                            }
                        }
                        if (objectCreateExpression.Arguments.Count == 3)
                        {
                            altParam = objectCreateExpression.Arguments.ElementAt(2);
                        }
                    }
                    return(paramNode != null);
                }
                return(false);
            }
예제 #6
0
        public override void VisitAttribute(Attribute attribute)
        {
            base.VisitAttribute(attribute);
            if (suppressMessageCheckId == null)
            {
                return;
            }
            var resolveResult = ctx.Resolve(attribute);

            if (resolveResult.Type.Name == "SuppressMessageAttribute" && resolveResult.Type.Namespace == "System.Diagnostics.CodeAnalysis")
            {
                if (attribute.Arguments.Count < 2)
                {
                    return;
                }
                var category = attribute.Arguments.First() as PrimitiveExpression;
                if (category == null || category.Value.ToString() != suppressMessageCategory)
                {
                    return;
                }
                var checkId = attribute.Arguments.Skip(1).First() as PrimitiveExpression;
                if (checkId == null || checkId.Value.ToString() != suppressMessageCheckId)
                {
                    return;
                }
                suppressedRegions.Add(attribute.Parent.Parent.Region);
            }
        }
예제 #7
0
        static CodeAction CreateAction(BaseRefactoringContext context, Match match, bool negateMatch, BinaryOperatorExpression node)
        {
            var target = match.Get <Expression>("target").Single();
            var expr   = match.Get <Expression>("expr").Single();

            if (!expr.DescendantsAndSelf.All(x => !(x is BinaryOperatorExpression) || ((BinaryOperatorExpression)x).Operator == BinaryOperatorType.BitwiseOr) &&
                !expr.DescendantsAndSelf.All(x => !(x is BinaryOperatorExpression) || ((BinaryOperatorExpression)x).Operator == BinaryOperatorType.BitwiseAnd))
            {
                return(null);
            }
            var rr = context.Resolve(target);

            if (rr.Type.Kind != ICSharpCode.NRefactory.TypeSystem.TypeKind.Enum)
            {
                return(null);
            }

            return(new CodeAction(
                       context.TranslateString("Replace with 'Enum.HasFlag'"),
                       script => {
                Expression newExpr = BuildHasFlagExpression(target, expr);
                if (negateMatch)
                {
                    newExpr = new UnaryOperatorExpression(UnaryOperatorType.Not, newExpr);
                }
                script.Replace(node, newExpr);
            },
                       node.OperatorToken));
        }
예제 #8
0
        internal static Expression GetSwitchExpression(BaseRefactoringContext context, Expression expr)
        {
            var binaryOp = expr as BinaryOperatorExpression;

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

            if (binaryOp.Operator == BinaryOperatorType.ConditionalOr)
            {
                return(GetSwitchExpression(context, binaryOp.Left));
            }

            if (binaryOp.Operator == BinaryOperatorType.Equality)
            {
                Expression switchExpr = null;
                if (IsConstantExpression(context, binaryOp.Right))
                {
                    switchExpr = binaryOp.Left;
                }
                if (IsConstantExpression(context, binaryOp.Left))
                {
                    switchExpr = binaryOp.Right;
                }
                if (switchExpr != null && IsValidSwitchType(context.Resolve(switchExpr).Type))
                {
                    return(switchExpr);
                }
            }

            return(null);
        }
        public static bool LambdaTypeCanBeInferred(BaseRefactoringContext ctx, Expression expression, List <ParameterDeclaration> parameters)
        {
            var validTypes = TypeGuessing.GetValidTypes(ctx.Resolver, expression).ToList();

            foreach (var type in validTypes)
            {
                if (type.Kind != TypeKind.Delegate)
                {
                    continue;
                }
                var invokeMethod = type.GetDelegateInvokeMethod();
                if (invokeMethod == null || invokeMethod.Parameters.Count != parameters.Count)
                {
                    continue;
                }
                for (int p = 0; p < invokeMethod.Parameters.Count; p++)
                {
                    var resolvedArgument = ctx.Resolve(parameters[p].Type);
                    if (!invokeMethod.Parameters [p].Type.Equals(resolvedArgument.Type))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
예제 #10
0
        internal static IField ScanSetter(BaseRefactoringContext context, PropertyDeclaration propertyDeclaration)
        {
            if (propertyDeclaration.Setter.Body.Statements.Count != 1)
            {
                return(null);
            }
            var setAssignment = propertyDeclaration.Setter.Body.Statements.First() as ExpressionStatement;
            var assignment    = setAssignment != null ? setAssignment.Expression as AssignmentExpression : null;

            if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign)
            {
                return(null);
            }
            var idExpr = assignment.Right as IdentifierExpression;

            if (idExpr == null || idExpr.Identifier != "value")
            {
                return(null);
            }
            if (!IsPossibleExpression(assignment.Left))
            {
                return(null);
            }
            var result = context.Resolve(assignment.Left);

            if (result == null || !(result is MemberResolveResult))
            {
                return(null);
            }
            return(((MemberResolveResult)result).Member as IField);
        }
예제 #11
0
 static bool IsConstantExpression(BaseRefactoringContext context, Expression expr)
 {
     if (expr is PrimitiveExpression || expr is NullReferenceExpression)
     {
         return(true);
     }
     return(context.Resolve(expr).IsCompileTimeConstant);
 }
예제 #12
0
        protected static bool HidesMember(BaseRefactoringContext ctx, AstNode node, string variableName, out IMember member)
        {
            MemberCollectionService mcs = (MemberCollectionService)ctx.GetService(typeof(MemberCollectionService));

            if (mcs == null)
            {
                lock (ctx) {
                    if ((mcs = (MemberCollectionService)ctx.GetService(typeof(MemberCollectionService))) == null)
                    {
                        mcs = new MemberCollectionService();
                        ctx.Services.AddService(typeof(MemberCollectionService), mcs);
                    }
                }
            }

            var typeDecl = node.GetParent <TypeDeclaration>();

            member = null;
            if (typeDecl == null)
            {
                return(false);
            }
            var entityDecl          = node.GetParent <EntityDeclaration>();
            var memberResolveResult = ctx.Resolve(entityDecl) as MemberResolveResult;

            if (memberResolveResult == null)
            {
                return(false);
            }
            var typeResolveResult = ctx.Resolve(typeDecl) as TypeResolveResult;

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

            var sourceMember = memberResolveResult.Member;

            member = mcs.GetMembers(typeResolveResult.Type, variableName).FirstOrDefault(m2 => IsAccessible(sourceMember, m2));
            return(member != null);
        }
예제 #13
0
        internal static IType GetRequestedReturnType(BaseRefactoringContext ctx, AstNode returnStatement, out AstNode entityNode)
        {
            entityNode = returnStatement.GetParent(p => p is LambdaExpression || p is AnonymousMethodExpression || !(p is Accessor) && p is EntityDeclaration);
            if (entityNode == null)
            {
                return(SpecialType.UnknownType);
            }
            if (entityNode is EntityDeclaration)
            {
                var rr = ctx.Resolve(entityNode) as MemberResolveResult;
                if (rr == null)
                {
                    return(SpecialType.UnknownType);
                }
                if (((EntityDeclaration)entityNode).HasModifier(Modifiers.Async))
                {
                    return(TaskType.UnpackTask(ctx.Compilation, rr.Member.ReturnType));
                }
                return(rr.Member.ReturnType);
            }
            bool isAsync = false;

            if (entityNode is LambdaExpression)
            {
                isAsync = ((LambdaExpression)entityNode).IsAsync;
            }
            if (entityNode is AnonymousMethodExpression)
            {
                isAsync = ((AnonymousMethodExpression)entityNode).IsAsync;
            }
            foreach (var type in TypeGuessing.GetValidTypes(ctx.Resolver, entityNode))
            {
                if (type.Kind != TypeKind.Delegate)
                {
                    continue;
                }
                var invoke = type.GetDelegateInvokeMethod();
                if (invoke != null)
                {
                    return(isAsync ? TaskType.UnpackTask(ctx.Compilation, invoke.ReturnType) : invoke.ReturnType);
                }
            }
            return(SpecialType.UnknownType);
        }
예제 #14
0
        public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
        {
            var resolveResult = context.Resolve(identifierExpression);

            if (resolveResult is MemberResolveResult)
            {
                var memberResult = (MemberResolveResult)resolveResult;
                if (!memberResult.Member.IsStatic)
                {
                    UsesNonStaticMember = true;
                }
            }
            else if (resolveResult is MethodGroupResolveResult)
            {
                var methodGroupResolveResult = (MethodGroupResolveResult)resolveResult;
                if (methodGroupResolveResult.Methods.Any(m => !m.IsStatic))
                {
                    UsesNonStaticMember = true;
                }
            }
        }
예제 #15
0
        internal static IField ScanGetter(BaseRefactoringContext context, PropertyDeclaration propertyDeclaration)
        {
            if (propertyDeclaration.Getter.Body.Statements.Count != 1)
            {
                return(null);
            }
            var returnStatement = propertyDeclaration.Getter.Body.Statements.First() as ReturnStatement;

            if (returnStatement == null)
            {
                return(null);
            }
            if (!IsPossibleExpression(returnStatement.Expression))
            {
                return(null);
            }
            var result = context.Resolve(returnStatement.Expression);

            if (result == null || !(result is MemberResolveResult))
            {
                return(null);
            }
            return(((MemberResolveResult)result).Member as IField);
        }
예제 #16
0
                bool CheckRecursion(AstNode node)
                {
                    if (member == null)
                    {
                        return(false);
                    }

                    var resolveResult = ctx.Resolve(node);

                    //We'll ignore Method groups here
                    //If the invocation expressions will be dealt with later anyway
                    //and properties are never in "method groups".
                    var memberResolveResult = resolveResult as MemberResolveResult;

                    if (memberResolveResult == null || memberResolveResult.Member != this.member)
                    {
                        return(false);
                    }

                    //Now check for virtuals
                    if (memberResolveResult.Member.IsVirtual && !memberResolveResult.Member.DeclaringTypeDefinition.IsSealed)
                    {
                        return(false);
                    }

                    var parentAssignment = node.Parent as AssignmentExpression;

                    if (parentAssignment != null)
                    {
                        if (accessorRole == CustomEventDeclaration.AddKeywordRole)
                        {
                            return(parentAssignment.Operator == AssignmentOperatorType.Add);
                        }
                        if (accessorRole == CustomEventDeclaration.RemoveKeywordRole)
                        {
                            return(parentAssignment.Operator == AssignmentOperatorType.Subtract);
                        }
                        if (accessorRole == PropertyDeclaration.GetKeywordRole)
                        {
                            return(parentAssignment.Operator != AssignmentOperatorType.Assign);
                        }

                        return(true);
                    }

                    var parentUnaryOperation = node.Parent as UnaryOperatorExpression;

                    if (parentUnaryOperation != null)
                    {
                        var operatorType = parentUnaryOperation.Operator;
                        if (operatorType == UnaryOperatorType.Increment ||
                            operatorType == UnaryOperatorType.Decrement ||
                            operatorType == UnaryOperatorType.PostIncrement ||
                            operatorType == UnaryOperatorType.PostDecrement)
                        {
                            return(true);
                        }
                    }

                    return(accessorRole == null || accessorRole == PropertyDeclaration.GetKeywordRole);
                }
예제 #17
0
            public override void VisitInvocationExpression(InvocationExpression invocationExpression)
            {
                base.VisitInvocationExpression(invocationExpression);

                // Speed up the inspector by discarding some invocations early
                var hasEligibleArgument = invocationExpression.Arguments.Any(argument => {
                    var primitiveArg = argument as PrimitiveExpression;
                    return(primitiveArg != null && primitiveArg.Value is string);
                });

                if (!hasEligibleArgument)
                {
                    return;
                }

                var invocationResolveResult = context.Resolve(invocationExpression) as AlInvocationResolveResult;

                if (invocationResolveResult == null)
                {
                    return;
                }
                Expression         formatArgument;
                IList <Expression> formatArguments;

                if (!FormatStringHelper.TryGetFormattingParameters(invocationResolveResult, invocationExpression,
                                                                   out formatArgument, out formatArguments, null))
                {
                    return;
                }
                var primitiveArgument = formatArgument as PrimitiveExpression;

                if (primitiveArgument == null || !(primitiveArgument.Value is string))
                {
                    return;
                }
                var format        = (string)primitiveArgument.Value;
                var parsingResult = context.ParseFormatString(format);

                CheckSegments(parsingResult.Segments, formatArgument.StartLocation, formatArguments, invocationExpression);

                var argUsed = new HashSet <int> ();

                foreach (var item in parsingResult.Segments)
                {
                    var fi = item as FormatItem;
                    if (fi == null)
                    {
                        continue;
                    }
                    argUsed.Add(fi.Index);
                }
                for (int i = 0; i < formatArguments.Count; i++)
                {
                    if (!argUsed.Contains(i))
                    {
                        AddIssue(new CodeIssue(formatArguments[i], ctx.TranslateString("Argument is not used in format string"))
                        {
                            IssueMarker = IssueMarker.GrayOut
                        });
                    }
                }
            }
예제 #18
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));
        }