public NRefactoryCodeAction(string id, string title, ICSharpCode.NRefactory.PlayScript.Refactoring.CodeAction act) { this.IdString = id; this.Title = title; this.act = act; this.DocumentRegion = new Mono.TextEditor.DocumentRegion(act.Start, act.End); }
public override void VisitConditionalExpression (ConditionalExpression conditionalExpression) { base.VisitConditionalExpression (conditionalExpression); if (!conditionalExpression.TrueExpression.Match (conditionalExpression.FalseExpression).Success) return; var action = new CodeAction (ctx.TranslateString ("Replace '?:' with branch"), script => script.Replace (conditionalExpression, conditionalExpression.TrueExpression.Clone ())); AddIssue (conditionalExpression, ctx.TranslateString ("'?:' expression has identical true and false branches"), new [] { action }); }
public override void VisitIsExpression (IsExpression isExpression) { base.VisitIsExpression (isExpression); var type = ctx.Resolve (isExpression.Expression).Type; var providedType = ctx.ResolveType (isExpression.Type); // var foundConversion = conversions.ImplicitConversion(type, providedType); if (!IsValidReferenceOrBoxingConversion(type, providedType)) return; var action = new CodeAction (ctx.TranslateString ("Compare with 'null'"), scrpit => scrpit.Replace (isExpression, new BinaryOperatorExpression ( isExpression.Expression.Clone (), BinaryOperatorType.InEquality, new PrimitiveExpression (null)))); AddIssue (isExpression, ctx.TranslateString ("Given expression is always of the provided type. " + "Consider comparing with 'null' instead"), new [] { action }); }
public override void VisitCatchClause(CatchClause catchClause) { base.VisitCatchClause(catchClause); var exceptionResolveResult = ctx.Resolve(catchClause.VariableNameToken) as LocalResolveResult; if (exceptionResolveResult == null) return; var catchVisitor = new CatchClauseVisitor(ctx, exceptionResolveResult.Variable); catchClause.Body.AcceptVisitor(catchVisitor); foreach (var throwStatement in catchVisitor.OffendingThrows) { var localThrowStatement = throwStatement; var title = ctx.TranslateString("The exception is rethrown with explicit usage of the variable"); var action = new CodeAction(ctx.TranslateString("Change to 'throw;'"), script => { script.Replace(localThrowStatement, new ThrowStatement()); }); AddIssue(localThrowStatement, title, action); } }
void AddIssuesForClauses(List<CatchClause> redundantCatchClauses) { var allCatchClausesMessage = ctx.TranslateString("Remove all '{0}' redundant catches"); var removeAllRedundantClausesAction = new CodeAction(allCatchClausesMessage, script => { foreach (var redundantCatchClause in redundantCatchClauses) { script.Remove(redundantCatchClause); } }); var singleCatchClauseMessage = ctx.TranslateString("Remove redundant catch clause"); var redundantCatchClauseMessage = ctx.TranslateString("A catch clause containing a single empty throw statement is redundant."); foreach (var redundantCatchClause in redundantCatchClauses) { var closureLocalCatchClause = redundantCatchClause; var removeRedundantClauseAction = new CodeAction(singleCatchClauseMessage, script => { script.Remove(closureLocalCatchClause); }); var actions = new List<CodeAction>(); actions.Add(removeRedundantClauseAction); if (redundantCatchClauses.Count > 1) { actions.Add(removeAllRedundantClausesAction); } AddIssue(closureLocalCatchClause, redundantCatchClauseMessage, actions); } }
public override void VisitInvocationExpression (InvocationExpression invocationExpression) { base.VisitInvocationExpression (invocationExpression); // Quickly determine if this invocation is eligible to speed up the inspector var nameToken = invocationExpression.Target.GetChildByRole(Roles.Identifier); if (nameToken.Name != "ReferenceEquals") return; var resolveResult = ctx.Resolve (invocationExpression) as InvocationResolveResult; if (resolveResult == null || resolveResult.Member.DeclaringTypeDefinition == null || resolveResult.Member.DeclaringTypeDefinition.KnownTypeCode != KnownTypeCode.Object || resolveResult.Member.Name != "ReferenceEquals" || invocationExpression.Arguments.All(arg => ctx.Resolve(arg).Type.IsReferenceType ?? true)) return; var action = new CodeAction (ctx.TranslateString ("Use Equals()"), script => script.Replace (invocationExpression.Target, new MemberReferenceExpression ( new TypeReferenceExpression (new PrimitiveType ("object")), "Equals"))); AddIssue (invocationExpression, ctx.TranslateString ("'Object.ReferenceEquals' is always false because it is called with value type"), new [] { action }); }
bool AddStatement(Statement statement) { if (reachability.IsReachable (statement)) return false; if (collectedStatements.Contains (statement)) return true; var prevEnd = statement.GetPrevNode ().EndLocation; // group multiple continuous statements into one issue var start = statement.StartLocation; collectedStatements.Add (statement); visitor.unreachableNodes.Add (statement); while (statement.NextSibling is Statement) { statement = (Statement)statement.NextSibling; collectedStatements.Add (statement); visitor.unreachableNodes.Add (statement); } var end = statement.EndLocation; var removeAction = new CodeAction (visitor.ctx.TranslateString ("Remove unreachable code"), script => { var startOffset = script.GetCurrentOffset (prevEnd); var endOffset = script.GetCurrentOffset (end); script.RemoveText (startOffset, endOffset - startOffset); }); var commentAction = new CodeAction (visitor.ctx.TranslateString ("Comment unreachable code"), script => { var startOffset = script.GetCurrentOffset (prevEnd); script.InsertText (startOffset, Environment.NewLine + "/*"); var endOffset = script.GetCurrentOffset (end); script.InsertText (endOffset, Environment.NewLine + "*/"); }); var actions = new [] { removeAction, commentAction }; visitor.AddIssue (start, end, visitor.ctx.TranslateString ("Code is unreachable"), actions); return true; }
/// <summary> /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.PlayScript.Refactoring.CodeIssue"/> class. /// </summary> /// <param name='description'> /// The desription of the issue. /// </param> /// <param name='start'> /// The issue start location. /// </param> /// <param name='end'> /// the issue end location. /// </param> /// <param name='action'> /// A potential solution for the issue. /// </param> public CodeIssue(string description, TextLocation start, TextLocation end, CodeAction action) : this (description, start, end, action != null ? new [] { action } : null) { }
public NRefactoryCodeAction (string id, string title, ICSharpCode.NRefactory.PlayScript.Refactoring.CodeAction act) { this.IdString = id; this.Title = title; this.act = act; }
void CheckMethodCall <T> (T node, IEnumerable <Expression> args, Func <T, IEnumerable <Expression>, T> generateReplacement) where T : AstNode { // The first two checks are unnecessary, but eliminates the majority of calls early, // improving performance. var arguments = args.ToArray(); if (arguments.Length == 0) { return; } var lastArg = arguments[arguments.Length - 1]; if (!(lastArg is PrimitiveExpression || lastArg is NamedArgumentExpression)) { return; } var invocationResolveResult = ctx.Resolve(node) as CSharpInvocationResolveResult; if (invocationResolveResult == null) { return; } string actionMessage = ctx.TranslateString("Remove redundant arguments"); var redundantArguments = GetRedundantArguments(arguments, invocationResolveResult); var action = new CodeAction(actionMessage, script => { var newArgumentList = arguments .Where(arg => !redundantArguments.Contains(arg)) .Select(arg => arg.Clone()); var newInvocation = generateReplacement(node, newArgumentList); script.Replace(node, newInvocation); }); var issueMessage = ctx.TranslateString("Argument is identical to the default value"); var lastPositionalArgument = redundantArguments.FirstOrDefault(expression => !(expression is NamedArgumentExpression)); foreach (var argument in redundantArguments) { var localArgument = argument; var actions = new List <CodeAction>(); actions.Add(action); if (localArgument is NamedArgumentExpression || localArgument == lastPositionalArgument) { var title = ctx.TranslateString("Remove this argument"); actions.Add(new CodeAction(title, script => { var newArgumentList = arguments .Where(arg => arg != localArgument) .Select(arg => arg.Clone()); var newInvocation = generateReplacement(node, newArgumentList); script.Replace(node, newInvocation); })); } else { var title = ctx.TranslateString("Remove this and the following positional arguments"); actions.Add(new CodeAction(title, script => { var newArgumentList = arguments .Where(arg => arg.StartLocation < localArgument.StartLocation && !(arg is NamedArgumentExpression)) .Select(arg => arg.Clone()); var newInvocation = generateReplacement(node, newArgumentList); script.Replace(node, newInvocation); })); } AddIssue(localArgument, issueMessage, actions); } }
protected void AddIssue(TextLocation start, TextLocation end, string title, CodeAction fix) { FoundIssues.Add(new CodeIssue (title, start, end, fix)); }
protected void AddIssue(AstNode node, string title, CodeAction fix) { FoundIssues.Add(new CodeIssue(title, node.StartLocation, node.EndLocation, fix)); }
void AddIssueForTryCatchStatement(TryCatchStatement tryCatchStatement) { var lastCatch = tryCatchStatement.CatchClauses.LastOrNullObject(); if (lastCatch.IsNull) return; var removeTryCatchMessage = ctx.TranslateString("Remove try statement"); var removeTryStatementAction = new CodeAction(removeTryCatchMessage, script => { var statements = tryCatchStatement.TryBlock.Statements; if (statements.Count == 1 || tryCatchStatement.Parent is BlockStatement) { foreach (var statement in statements) { script.InsertAfter(tryCatchStatement.PrevSibling, statement.Clone()); } script.Remove(tryCatchStatement); } else { var blockStatement = new BlockStatement(); foreach (var statement in statements) { blockStatement.Statements.Add(statement.Clone()); } script.Replace(tryCatchStatement, blockStatement); } // The replace and insert script functions does not format these things well on their own script.FormatText(tryCatchStatement.Parent); }); var fixes = new [] { removeTryStatementAction }; AddIssue(tryCatchStatement.TryBlock.EndLocation, lastCatch.EndLocation, removeTryCatchMessage, fixes); }
void CheckCondition (Expression condition) { if (condition is PrimitiveExpression) return; var resolveResult = ctx.Resolve (condition); if (!(resolveResult.IsCompileTimeConstant && resolveResult.ConstantValue is bool)) return; var value = (bool)resolveResult.ConstantValue; var conditionalExpr = condition.Parent as ConditionalExpression; var ifElseStatement = condition.Parent as IfElseStatement; var valueStr = value.ToString ().ToLower (); CodeAction action; if (conditionalExpr != null) { var replaceExpr = value ? conditionalExpr.TrueExpression : conditionalExpr.FalseExpression; action = new CodeAction ( string.Format (ctx.TranslateString ("Replace '?:' with '{0}' branch"), valueStr), script => script.Replace (conditionalExpr, replaceExpr.Clone ())); } else if (ifElseStatement != null) { action = new CodeAction ( string.Format (ctx.TranslateString ("Replace 'if' with '{0}' branch"), valueStr), script => { var statement = value ? ifElseStatement.TrueStatement : ifElseStatement.FalseStatement; var blockStatement = statement as BlockStatement; if (statement.IsNull || (blockStatement != null && blockStatement.Statements.Count == 0)) { script.Remove (ifElseStatement); return; } TextLocation start, end; if (blockStatement != null) { start = blockStatement.Statements.FirstOrNullObject ().StartLocation; end = blockStatement.Statements.LastOrNullObject ().EndLocation; } else { start = statement.StartLocation; end = statement.EndLocation; } RemoveText (script, ifElseStatement.StartLocation, start); RemoveText (script, end, ifElseStatement.EndLocation); script.FormatText (ifElseStatement.Parent); }); } else { action = new CodeAction ( string.Format (ctx.TranslateString ("Replace expression with '{0}'"), valueStr), script => script.Replace (condition, new PrimitiveExpression (value))); } AddIssue (condition, string.Format (ctx.TranslateString ("Condition is always '{0}'"), valueStr), new [] { action }); }
public NRefactoryCodeAction(string id, string title, ICSharpCode.NRefactory.PlayScript.Refactoring.CodeAction act) { this.IdString = id; this.Title = title; this.act = act; }