5 changed files with 130 additions and 18 deletions
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using ICSharpCode.NRefactory.CSharp; |
||||
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
using CSharpBinding.Parser; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
[ContextAction("Add range check for parameter", Description = "Adds a parameter range check.")] |
||||
public class ParamRangeCheckContextAction : ContextAction |
||||
{ |
||||
public override async Task<bool> IsAvailableAsync(EditorRefactoringContext context, System.Threading.CancellationToken cancellationToken) |
||||
{ |
||||
SyntaxTree st = await context.GetSyntaxTreeAsync().ConfigureAwait(false); |
||||
Identifier identifier = (Identifier) st.GetNodeAt(context.CaretLocation, node => node.Role == Roles.Identifier); |
||||
if (identifier == null) |
||||
return false; |
||||
ParameterDeclaration parameterDeclaration = identifier.Parent as ParameterDeclaration; |
||||
if (parameterDeclaration == null) |
||||
return false; |
||||
ICompilation compilation = await context.GetCompilationAsync().ConfigureAwait(false); |
||||
ITypeReference typeRef = parameterDeclaration.Type.ToTypeReference(); |
||||
if (typeRef == null) |
||||
return false; |
||||
IType type = typeRef.Resolve(compilation); |
||||
if (type == null) |
||||
return false; |
||||
return type.HasRange(); |
||||
} |
||||
|
||||
public override void Execute(EditorRefactoringContext context) |
||||
{ |
||||
CSharpFullParseInformation parseInformation = context.GetParseInformation() as CSharpFullParseInformation; |
||||
if (parseInformation != null) { |
||||
SyntaxTree st = parseInformation.SyntaxTree; |
||||
Identifier identifier = (Identifier) st.GetNodeAt(context.CaretLocation, node => node.Role == Roles.Identifier); |
||||
if (identifier == null) |
||||
return; |
||||
ParameterDeclaration parameterDeclaration = identifier.Parent as ParameterDeclaration; |
||||
if (parameterDeclaration == null) |
||||
return; |
||||
|
||||
AstNode grandparent = identifier.Parent.Parent; |
||||
if ((grandparent is MethodDeclaration) || (grandparent is ConstructorDeclaration)) { |
||||
// Range check condition
|
||||
var rangeCheck = new IfElseStatement( |
||||
new BinaryOperatorExpression( |
||||
new BinaryOperatorExpression(new IdentifierExpression(identifier.Name), BinaryOperatorType.LessThan, new IdentifierExpression("lower")), |
||||
BinaryOperatorType.ConditionalOr, |
||||
new BinaryOperatorExpression(new IdentifierExpression(identifier.Name), BinaryOperatorType.GreaterThan, new IdentifierExpression("upper")) |
||||
), |
||||
new ThrowStatement( |
||||
new ObjectCreateExpression( |
||||
new SimpleType("ArgumentOutOfRangeException"), |
||||
new List<Expression>() { new PrimitiveExpression(identifier.Name, '"' + identifier.Name + '"'), new IdentifierExpression(identifier.Name), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Add, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Add, new IdentifierExpression("upper")))) } |
||||
) |
||||
) |
||||
); |
||||
|
||||
// Add range check as first statement in method's/constructor's body
|
||||
var refactoringContext = SDRefactoringContext.Create(context.Editor, CancellationToken.None); |
||||
using (Script script = refactoringContext.StartScript()) { |
||||
if (grandparent is MethodDeclaration) { |
||||
var methodDeclaration = (MethodDeclaration) grandparent; |
||||
script.AddTo(methodDeclaration.Body, rangeCheck); |
||||
} else if (grandparent is ConstructorDeclaration) { |
||||
var ctorDeclaration = (ConstructorDeclaration) grandparent; |
||||
script.AddTo(ctorDeclaration.Body, rangeCheck); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public override string DisplayName { |
||||
get { |
||||
return "Add range check for parameter"; |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue