Browse Source

Introduced ParamRangeCheckContextAction.

addin-manager-package-subdirectories
Andreas Weizel 12 years ago
parent
commit
a2e20fdeb3
  1. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 89
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/ParamRangeCheckContextAction.cs
  4. 20
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/PropertyOrFieldWrapper.cs
  5. 37
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/RefactoringExtensions.cs

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -316,6 +316,7 @@ @@ -316,6 +316,7 @@
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeywordAction" />
<Class class="CSharpBinding.Refactoring.MoveTypeToFileContextAction" />
<Class class="CSharpBinding.Refactoring.RenameFileToMatchTypeNameContextAction" />
<Class class="CSharpBinding.Refactoring.ParamRangeCheckContextAction" />
</Path>
<Path name = "/SharpDevelop/Workbench/DisplayBindings">

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -110,6 +110,7 @@ @@ -110,6 +110,7 @@
<Compile Include="Src\Refactoring\IssueOptionsViewModel.cs" />
<Compile Include="Src\Refactoring\MoveTypeToFileContextAction.cs" />
<Compile Include="Src\Refactoring\Options.cs" />
<Compile Include="Src\Refactoring\ParamRangeCheckContextAction.cs" />
<Compile Include="Src\Refactoring\RefactoringExtensions.cs" />
<Compile Include="Src\Refactoring\OverrideEqualsGetHashCodeMethodsDialog.xaml.cs">
<DependentUpon>OverrideEqualsGetHashCodeMethodsDialog.xaml</DependentUpon>

89
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/ParamRangeCheckContextAction.cs

@ -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";
}
}
}
}

20
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/PropertyOrFieldWrapper.cs

@ -75,16 +75,13 @@ namespace CSharpBinding.Refactoring @@ -75,16 +75,13 @@ namespace CSharpBinding.Refactoring
public bool IsNullable {
get {
// true = reference, null = generic or unknown
return Member.ReturnType.IsReferenceType != false
|| (Member.ReturnType.FullName == "System.Nullable");
return Member.ReturnType.IsNullable();
}
}
public bool HasRange {
get {
return IsTypeWithRange(Member.ReturnType) ||
(Member.ReturnType.FullName == "System.Nullable")
&& IsTypeWithRange(Member.ReturnType.TypeArguments.First());
return Member.ReturnType.HasRange();
}
}
@ -104,19 +101,6 @@ namespace CSharpBinding.Refactoring @@ -104,19 +101,6 @@ namespace CSharpBinding.Refactoring
}
}
bool IsTypeWithRange(IType type)
{
string crtType = type.FullName;
return crtType == "System.Int32" ||
crtType == "System.Int16" ||
crtType == "System.Int64" ||
crtType == "System.Single" ||
crtType == "System.Double" ||
crtType == "System.UInt16" ||
crtType == "System.UInt32" ||
crtType == "System.UInt64";
}
static string ToParameterName(string memberName)
{
if (string.IsNullOrEmpty(memberName))

37
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/RefactoringExtensions.cs

@ -46,6 +46,43 @@ namespace CSharpBinding.Refactoring @@ -46,6 +46,43 @@ namespace CSharpBinding.Refactoring
return false;
}
/// <summary>
/// Checks whether a type is nullable.
/// </summary>
/// <param name="type">Checked type</param>
/// <returns>True if nullable, false otherwise.</returns>
public static bool IsNullable(this IType type)
{
// true = reference, null = generic or unknown
return type.IsReferenceType != false
|| (type.FullName == "System.Nullable");
}
/// <summary>
/// Checks whether a type has a range.
/// </summary>
/// <param name="type">Checked type</param>
/// <returns>True if type has range, false otherwise.</returns>
public static bool HasRange(this IType type)
{
return IsTypeWithRange(type) ||
(type.FullName == "System.Nullable")
&& IsTypeWithRange(type.TypeArguments.First());
}
static bool IsTypeWithRange(IType type)
{
string crtType = type.FullName;
return crtType == "System.Int32" ||
crtType == "System.Int16" ||
crtType == "System.Int64" ||
crtType == "System.Single" ||
crtType == "System.Double" ||
crtType == "System.UInt16" ||
crtType == "System.UInt32" ||
crtType == "System.UInt64";
}
/// <summary>
/// Retrieves the declaration for the specified entity.
/// Returns null if the entity is not defined in C# source code.

Loading…
Cancel
Save