public NRefactoryCodeAction (string id, string title, ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction act)
		{
			this.IdString = id;
			this.Title = title;
			this.act = act;
			this.DocumentRegion = new Mono.TextEditor.DocumentRegion (act.Start, act.End);
		}
Beispiel #2
0
 public NRefactoryCodeAction(string id, string title, ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction act)
 {
     this.IdString       = id;
     this.Title          = title;
     this.act            = act;
     this.DocumentRegion = new Mono.TextEditor.DocumentRegion(act.Start, act.End);
 }
		public NRefactoryCodeAction (string id, string title, CodeAction act, object siblingKey = null)
		{
			this.IdString = id;
			this.Title = title;
			this.act = act;
			this.SiblingKey = siblingKey;
			this.Severity = act.Severity;
			this.DocumentRegion = new Mono.TextEditor.DocumentRegion (act.Start, act.End);
		}
Beispiel #4
0
 public NRefactoryCodeAction(string id, string title, ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction act, object siblingKey = null)
 {
     this.IdString       = id;
     this.Title          = title;
     this.act            = act;
     this.SiblingKey     = siblingKey;
     this.Severity       = act.Severity;
     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 CSharpContextActionWrapper(IContextActionProvider provider, CodeAction codeAction,
		                                  Func<SDRefactoringContext, CodeAction> getUpdatedCodeAction)
		{
			if (provider == null)
				throw new ArgumentNullException("provider");
			if (codeAction == null)
				throw new ArgumentNullException("codeAction");
			if (getUpdatedCodeAction == null)
				throw new ArgumentNullException("getUpdatedCodeAction");
			this.provider = provider;
			this.description = codeAction.Description;
			this.getUpdatedCodeAction = getUpdatedCodeAction;
			// Don't maintain a reference to 'action', it indirectly references the compilation etc.
		}
			public override void VisitIsExpression (IsExpression isExpression)
			{
				base.VisitIsExpression (isExpression);

				var type = ctx.Resolve (isExpression.Expression).Type;
				var providedType = ctx.ResolveType (isExpression.Type);

				if (type.GetAllBaseTypes ().All (t => !t.Equals (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 VisitInvocationExpression (InvocationExpression invocationExpression)
			{
				base.VisitInvocationExpression (invocationExpression);

				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 });
			}
			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, new [] { 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 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 });
            }
Beispiel #12
0
			IContextAction Wrap(CodeAction actionToWrap, int index)
			{
				// Take care not to capture 'actionToWrap' in the lambda
				string actionDescription = actionToWrap.Description;
				return new CSharpContextActionWrapper(
					manager, actionToWrap,
					context => {
						// Look up the new issue position
						int newStart = InspectedVersion.MoveOffsetTo(context.Version, StartOffset, AnchorMovementType.Default);
						int newEnd = InspectedVersion.MoveOffsetTo(context.Version, EndOffset, AnchorMovementType.Default);
						// If the length changed, don't bother looking up the issue again
						if (newEnd - newStart != EndOffset - StartOffset)
							return null;
						// Now rediscover this issue in the new context
						var issue = this.Provider.GetIssues(context).FirstOrDefault(
							i => context.GetOffset(i.Start) == newStart && context.GetOffset(i.End) == newEnd && i.Description == this.Description);
						if (issue == null)
							return null;
						// Now look up the action within that issue:
						if (index < issue.Actions.Count && issue.Actions[index].Description == actionDescription)
							return issue.Actions[index];
						else
							return null;
					});
			}
Beispiel #13
0
 public NRefactoryCodeAction(string id, string title, ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction act)
 {
     this.IdString = id;
     this.Title    = title;
     this.act      = act;
 }
		public NRefactoryCodeAction (string id, string title, ICSharpCode.NRefactory.CSharp.Refactoring.CodeAction act)
		{
			this.IdString = id;
			this.Title = title;
			this.act = act;
		}
Beispiel #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.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)
 {
 }
			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);
			}
Beispiel #17
0
			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 });
			}
			IContextAction Wrap(CodeAction actionToWrap, int index)
			{
				// Take care not to capture 'actionToWrap' in the lambda
				string description = actionToWrap.Description;
				return new CSharpContextActionWrapper(
					this, actionToWrap,
					context => {
						var actions = codeActionProvider.GetActions(context).ToList();
						if (index < actions.Count) {
							var action = actions[index];
							if (action.Description == description)
								return action;
						}
						return null;
					});
			}
 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));
 }
Beispiel #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.CSharp.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)
 {
 }
Beispiel #22
0
				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;
				}