public override void VisitIdentifierExpression(IdentifierExpression identifierExpression) { if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation) { SetState(context.Resolve(identifierExpression), VariableState.Used); } }
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); }
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); } }
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); }
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); } }
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)); }
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); }
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); }
static bool IsConstantExpression(BaseRefactoringContext context, Expression expr) { if (expr is PrimitiveExpression || expr is NullReferenceExpression) { return(true); } return(context.Resolve(expr).IsCompileTimeConstant); }
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); }
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); }
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; } } }
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); }
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); }
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 }); } } }
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)); }