Browse Source

Merge branch 'master' into gsoc-fixes

newNRvisualizers
Simon Lindgren 14 years ago
parent
commit
af16dc305c
  1. 8
      ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  2. 1
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs
  3. 35
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs
  4. 15
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  5. 5
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  6. 20
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertAsToCastAction.cs
  7. 23
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertCastToAsAction.cs
  8. 7
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertLambdaToAnonymousDelegateAction.cs
  9. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs
  10. 18
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs
  11. 9
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs
  12. 13
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/PutInsideUsingAction.cs
  13. 11
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SplitDeclarationAndAssignmentAction.cs
  14. 9
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/CastExpressionOfIncompatibleTypeIssue.cs
  15. 8
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionIsAlwaysOfProvidedTypeIssue.cs
  16. 13
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantArrayInitializerCommaIssue.cs
  17. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantFieldInitializerIssue.cs
  18. 64
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantWhereWithPredicateIssue.cs
  19. 16
      ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs
  20. 39
      ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs
  21. 15
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  22. 3
      ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
  23. 6
      ICSharpCode.NRefactory.Demo/CSDemo.cs
  24. 42
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertAsToCastTests.cs
  25. 30
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertCastToAsTests.cs
  26. 22
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertLamdaToAnonymousDelegateTests.cs
  27. 21
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs
  28. 23
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateOverloadWithoutParameterTests.cs
  29. 55
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementAbstractMembersTest.cs
  30. 24
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/PutInsideUsingTests.cs
  31. 2
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs
  32. 16
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/CastExpressionOfIncompatibleTypeIssueTests.cs
  33. 53
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantArrayInitializerCommaIssueTests.cs
  34. 44
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs
  35. 70
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantWhereWithPredicateIssueTests.cs
  36. 50
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  37. 23
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs
  38. 1
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  39. 5
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  40. 8
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  41. 1
      ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs
  42. 14
      ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs
  43. 21
      ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs
  44. 1
      ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs
  45. 13
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs

8
ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs

@ -405,7 +405,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -405,7 +405,9 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
public override ControlFlowNode VisitIfElseStatement(IfElseStatement ifElseStatement, ControlFlowNode data)
{
bool? cond = builder.EvaluateCondition(ifElseStatement.Condition);
bool? cond = ifElseStatement.Condition.IsNull ? true : builder.EvaluateCondition(ifElseStatement.Condition);
if (ifElseStatement.TrueStatement.IsNull)
return data;
ControlFlowNode trueBegin = builder.CreateStartNode(ifElseStatement.TrueStatement);
if (cond != false)
Connect(data, trueBegin, ControlFlowEdgeType.ConditionTrue);
@ -535,7 +537,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -535,7 +537,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Connect(data, conditionNode);
bool? cond = builder.EvaluateCondition(whileStatement.Condition);
bool? cond = whileStatement.Condition.IsNull ? true : builder.EvaluateCondition(whileStatement.Condition);
ControlFlowNode bodyStart = builder.CreateStartNode(whileStatement.EmbeddedStatement);
if (cond != false)
Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue);
@ -563,7 +565,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -563,7 +565,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
ControlFlowNode bodyEnd = doWhileStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart);
Connect(bodyEnd, conditionNode);
bool? cond = builder.EvaluateCondition(doWhileStatement.Condition);
bool? cond = doWhileStatement.Condition.IsNull ? true : builder.EvaluateCondition(doWhileStatement.Condition);
if (cond != false)
Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue);
if (cond != true)

1
ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs

@ -80,6 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,6 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp
public AnonymousMethodExpression (BlockStatement body, IEnumerable<ParameterDeclaration> parameters = null)
{
if (parameters != null) {
hasParameterList = true;
foreach (var parameter in parameters) {
AddChild (parameter, Roles.Parameter);
}

35
ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs

@ -43,9 +43,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -43,9 +43,14 @@ namespace ICSharpCode.NRefactory.CSharp
}
string literalValue;
TextLocation? endLocation;
public override TextLocation EndLocation {
get {
return new TextLocation (StartLocation.Line, StartLocation.Column + literalValue.Length);
if (!endLocation.HasValue) {
endLocation = value is string ? AdvanceLocation (StartLocation, literalValue) :
new TextLocation (StartLocation.Line, StartLocation.Column + literalValue.Length);
}
return endLocation.Value;
}
}
@ -103,6 +108,34 @@ namespace ICSharpCode.NRefactory.CSharp @@ -103,6 +108,34 @@ namespace ICSharpCode.NRefactory.CSharp
return visitor.VisitPrimitiveExpression (this, data);
}
unsafe static TextLocation AdvanceLocation(TextLocation startLocation, string str)
{
int line = startLocation.Line;
int col = startLocation.Column;
fixed (char* start = str) {
char* p = start;
char* endPtr = start + str.Length;
while (p < endPtr) {
switch (*p) {
case '\r':
char* nextp = p + 1;
if (nextp < endPtr && *nextp == '\n')
p++;
goto case '\n';
case '\n':
line++;
col = 1;
break;
default:
col++;
break;
}
p++;
}
}
return new TextLocation (line, col);
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
PrimitiveExpression o = other as PrimitiveExpression;

15
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -2295,11 +2295,18 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2295,11 +2295,18 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null;
}
var lookup = new MemberLookup(
ctx.CurrentTypeDefinition,
Compilation.MainAssembly
);
if (resolveResult is NamespaceResolveResult) {
var nr = (NamespaceResolveResult)resolveResult;
var namespaceContents = new CompletionDataWrapper(this);
foreach (var cl in nr.Namespace.Types) {
if (!lookup.IsAccessible(cl, false))
continue;
IType addType = typePred != null ? typePred(cl) : cl;
if (addType != null)
namespaceContents.AddType(addType, addType.Name);
@ -2320,12 +2327,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2320,12 +2327,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var result = new CompletionDataWrapper(this);
bool includeStaticMembers = false;
var lookup = new MemberLookup(
ctx.CurrentTypeDefinition,
Compilation.MainAssembly
);
if (resolveResult is LocalResolveResult) {
if (resolvedNode is IdentifierExpression) {
var mrr = (LocalResolveResult)resolveResult;
@ -2461,6 +2462,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2461,6 +2462,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} else {
foreach (var meths in state.GetExtensionMethods (type)) {
foreach (var m in meths) {
if (!lookup.IsAccessible(m, isProtectedAllowed))
continue;
result.AddMember(m);
}
}

5
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -42,10 +42,12 @@ @@ -42,10 +42,12 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<DebugSymbols>false</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'net_4_5_Debug' ">
<Optimize>False</Optimize>
@ -56,6 +58,7 @@ @@ -56,6 +58,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'net_4_5_Release' ">
<Optimize>True</Optimize>
@ -66,6 +69,7 @@ @@ -66,6 +69,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<DebugSymbols>false</DebugSymbols>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@ -498,6 +502,7 @@ @@ -498,6 +502,7 @@
<Compile Include="Refactoring\CodeActions\ConvertLambdaToAnonymousDelegateAction.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

20
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertAsToCastAction.cs

@ -32,13 +32,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -32,13 +32,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
[ContextAction("Convert 'as' to cast.", Description = "Convert 'as' to cast.")]
public class ConvertAsToCastAction : SpecializedCodeAction <AsExpression>
{
static InsertParenthesesVisitor insertParentheses = new InsertParenthesesVisitor ();
protected override CodeAction GetAction (RefactoringContext context, AsExpression node)
{
if (!node.AsToken.Contains (context.Location))
return null;
return new CodeAction (context.TranslateString ("Convert 'as' to cast"),
script => script.Replace (node, new CastExpression (node.Type.Clone (), node.Expression.Clone ())));
return new CodeAction (context.TranslateString ("Convert 'as' to cast"), script => {
var castExpr = new CastExpression (node.Type.Clone (), node.Expression.Clone ());
var parenthesizedExpr = node.Parent as ParenthesizedExpression;
if (parenthesizedExpr != null && parenthesizedExpr.Parent is Expression) {
// clone parent expression and replace the ParenthesizedExpression with castExpr to remove
// parentheses, then insert parentheses if necessary
var parentExpr = (Expression)parenthesizedExpr.Parent.Clone ();
parentExpr.GetNodeContaining (parenthesizedExpr.StartLocation, parenthesizedExpr.EndLocation)
.ReplaceWith (castExpr);
parentExpr.AcceptVisitor (insertParentheses);
script.Replace (parenthesizedExpr.Parent, parentExpr);
} else {
castExpr.AcceptVisitor (insertParentheses);
script.Replace (node, castExpr);
}
});
}
}
}

23
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertCastToAsAction.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
[ContextAction ("Convert cast to 'as'.", Description = "Convert cast to 'as'.")]
public class ConvertCastToAsAction : SpecializedCodeAction<CastExpression>
{
static InsertParenthesesVisitor insertParentheses = new InsertParenthesesVisitor ();
protected override CodeAction GetAction (RefactoringContext context, CastExpression node)
{
if (node.Expression.Contains (context.Location))
@ -42,10 +42,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -42,10 +42,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// only works on reference and nullable types
var type = context.ResolveType (node.Type);
var typeDef = type.GetDefinition ();
if (type.IsReferenceType == true || (typeDef != null && typeDef.KnownTypeCode == KnownTypeCode.NullableOfT))
return new CodeAction (context.TranslateString ("Convert cast to 'as'"), script =>
script.Replace (node, new AsExpression (node.Expression.Clone (), node.Type.Clone ())));
var isNullable = typeDef != null && typeDef.KnownTypeCode == KnownTypeCode.NullableOfT;
if (type.IsReferenceType == true || isNullable) {
return new CodeAction (context.TranslateString ("Convert cast to 'as'"), script => {
var asExpr = new AsExpression (node.Expression.Clone (), node.Type.Clone ());
// if parent is an expression, clone parent and replace the case expression with asExpr,
// so that we can inset parentheses
var parentExpr = node.Parent.Clone () as Expression;
if (parentExpr != null) {
var castExpr = parentExpr.GetNodeContaining (node.StartLocation, node.EndLocation);
castExpr.ReplaceWith (asExpr);
parentExpr.AcceptVisitor (insertParentheses);
script.Replace (node.Parent, parentExpr);
} else {
script.Replace (node, asExpr);
}
});
}
return null;
}
}

7
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertLambdaToAnonymousDelegateAction.cs

@ -56,7 +56,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -56,7 +56,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
};
}
var method = new AnonymousMethodExpression (newBody, GetParameters(lambdaResolveResult.Parameters, context));
method.HasParameterList = true;
script.Replace(node, method);
});
}
@ -64,6 +63,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -64,6 +63,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IEnumerable<ParameterDeclaration> GetParameters(IList<IParameter> parameters, RefactoringContext context)
{
if (parameters == null || parameters.Count == 0)
return null;
var result = new List<ParameterDeclaration> ();
foreach (var parameter in parameters) {
var type = context.CreateShortType(parameter.Type);
var name = parameter.Name;
@ -72,8 +74,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -72,8 +74,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
modifier |= ParameterModifier.Ref;
if (parameter.IsOut)
modifier |= ParameterModifier.Out;
yield return new ParameterDeclaration(type, name, modifier);
result.Add (new ParameterDeclaration(type, name, modifier));
}
return result;
}
}
}

2
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
result = new TypeDeclaration() { Name = className };
var entity = simpleType.GetParent<EntityDeclaration>();
if (entity != null)
result.Modifiers |= entity.Modifiers & ~Modifiers.Internal;
result.Modifiers |= entity.Modifiers & Modifiers.Public;
return result;
}

18
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs

@ -66,15 +66,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -66,15 +66,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Expression argExpr;
if (node.ParameterModifier == ParameterModifier.Ref) {
body.Add (new VariableDeclarationStatement (node.Type.Clone (), node.Name, defaultExpr));
argExpr = new DirectionExpression (FieldDirection.Ref, new IdentifierExpression (node.Name));
argExpr = GetArgumentExpression (node);
} else if (node.ParameterModifier == ParameterModifier.Out) {
body.Add (new VariableDeclarationStatement (node.Type.Clone (), node.Name));
argExpr = new DirectionExpression (FieldDirection.Out, new IdentifierExpression (node.Name));
argExpr = GetArgumentExpression (node);
} else {
argExpr = defaultExpr;
}
body.Add (new InvocationExpression (new IdentifierExpression (methodDecl.Name),
methodDecl.Parameters.Select (param => param == node ? argExpr : new IdentifierExpression (param.Name))));
methodDecl.Parameters.Select (param => param == node ? argExpr : GetArgumentExpression(param))));
var decl = (MethodDeclaration)methodDecl.Clone ();
decl.Parameters.Remove (decl.Parameters.First (param => param.Name == node.Name));
@ -87,6 +87,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -87,6 +87,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
});
}
static Expression GetArgumentExpression(ParameterDeclaration parameter)
{
var identifierExpr = new IdentifierExpression(parameter.Name);
switch (parameter.ParameterModifier) {
case ParameterModifier.Out:
return new DirectionExpression (FieldDirection.Out, identifierExpr);
case ParameterModifier.Ref:
return new DirectionExpression (FieldDirection.Ref, identifierExpr);
}
return identifierExpr;
}
static Expression GetDefaultValueExpression (RefactoringContext context, AstType astType)
{
var type = context.ResolveType (astType);

9
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs

@ -93,6 +93,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -93,6 +93,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
var builder = context.CreateTypeSytemAstBuilder();
builder.GenerateBody = true;
builder.ShowModifiers = false;
builder.ShowAccessibility = true;
builder.ShowConstantValues = !explicitImplementation;
builder.ShowTypeParameterConstraints = !explicitImplementation;
builder.UseCustomEvents = explicitImplementation;
@ -100,8 +102,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -100,8 +102,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (explicitImplementation) {
decl.Modifiers = Modifiers.None;
decl.AddChild(builder.ConvertType(member.DeclaringType), EntityDeclaration.PrivateImplementationTypeRole);
} else if (member.DeclaringType.Kind == TypeKind.Interface) {
decl.Modifiers |= Modifiers.Public;
} else {
decl.Modifiers = Modifiers.Public;
// Remove 'internal' modifier from 'protected internal' members if the override is in a different assembly than the member
if (!member.ParentAssembly.InternalsVisibleTo(context.Compilation.MainAssembly)) {
decl.Modifiers &= ~Modifiers.Internal;
}
}
return decl;
}

13
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/PutInsideUsingAction.cs

@ -29,6 +29,7 @@ using System.Linq; @@ -29,6 +29,7 @@ using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -99,6 +100,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -99,6 +100,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
foreach (var decl in variableToMoveOutside)
script.InsertBefore (variableDecl, decl);
if (body.Statements.Count > 0) {
var lastStatement = body.Statements.Last ();
if (IsDisposeInvocation (resolveResult.Variable.Name, lastStatement))
lastStatement.Remove ();
}
var usingStatement = new UsingStatement
{
ResourceAcquisition = new VariableDeclarationStatement (variableDecl.Type.Clone (), node.Name,
@ -143,5 +149,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -143,5 +149,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}, context.CancellationToken);
return lastReference;
}
static bool IsDisposeInvocation (string variableName, Statement statement)
{
var memberReferenceExpr = new MemberReferenceExpression (new IdentifierExpression (variableName), "Dispose");
var pattern = new ExpressionStatement (new InvocationExpression (memberReferenceExpr));
return pattern.Match (statement).Success;
}
}
}

11
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/SplitDeclarationAndAssignmentAction.cs

@ -28,6 +28,7 @@ using System.Linq; @@ -28,6 +28,7 @@ using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using System.Threading;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -65,10 +66,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -65,10 +66,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
var result = context.GetNode<VariableDeclarationStatement> ();
if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Variables.First ().NameToken.Contains (context.Location.Line, context.Location.Column)) {
resolvedType = result.Type.Clone ();
// resolvedType = context.Resolve (result.Variables.First ().Initializer).Type.ConvertToAstType ();
// if (resolvedType == null)
// return null;
var type = context.Resolve(result.Variables.First ().Initializer).Type;
if (type.Equals(SpecialType.NullType) || type.Equals(SpecialType.UnknownType)) {
resolvedType = new PrimitiveType ("object");
} else {
resolvedType = context.CreateShortType (type);
}
return result;
}
resolvedType = null;

9
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/CastExpressionOfIncompatibleTypeIssue.cs

@ -26,6 +26,8 @@ @@ -26,6 +26,8 @@
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -43,9 +45,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -43,9 +45,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
readonly CSharpConversions conversion;
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
conversion = new CSharpConversions(ctx.Compilation);
}
public override void VisitCastExpression (CastExpression castExpression)
@ -66,8 +71,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -66,8 +71,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
void VisitTypeCastExpression (Expression expression, IType exprType, IType castToType)
{
if (TypeCompatibilityHelper.CheckTypeCompatibility (exprType, castToType) ==
TypeCompatibilityHelper.TypeCompatiblity.NeverOfProvidedType)
var foundConversion = conversion.ExplicitConversion(exprType, castToType);
if (foundConversion == Conversion.None)
AddIssue (expression, ctx.TranslateString ("Type cast expression of incompatible type"));
}
}

8
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionIsAlwaysOfProvidedTypeIssue.cs

@ -25,6 +25,8 @@ @@ -25,6 +25,8 @@
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -42,9 +44,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -42,9 +44,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
static CSharpConversions conversion;
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
conversion = new CSharpConversions(ctx.Compilation);
}
public override void VisitIsExpression (IsExpression isExpression)
@ -54,8 +58,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -54,8 +58,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var type = ctx.Resolve (isExpression.Expression).Type;
var providedType = ctx.ResolveType (isExpression.Type);
if (TypeCompatibilityHelper.CheckTypeCompatibility (type, providedType) !=
TypeCompatibilityHelper.TypeCompatiblity.AlwaysOfProvidedType)
var foundConversion = conversion.ImplicitConversion(type, providedType);
if (foundConversion == Conversion.None)
return;
var action = new CodeAction (ctx.TranslateString ("Compare with 'null'"),

13
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantArrayInitializerCommaIssue.cs

@ -57,7 +57,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -57,7 +57,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var commaToken = arrayInitializerExpression.RBraceToken.PrevSibling as CSharpTokenNode;
if (commaToken == null || commaToken.GetText () != ",")
return;
AddIssue (commaToken, ctx.TranslateString ("Remove redundant comma in array initializer"),
string initializerType;
if (arrayInitializerExpression.Parent is ObjectCreateExpression) {
if (arrayInitializerExpression.Elements.FirstOrNullObject () is NamedExpression) {
initializerType = "object";
} else {
initializerType = "collection";
}
} else {
initializerType = "array";
}
AddIssue (commaToken,
ctx.TranslateString (string.Format("Remove redundant comma in {0} initializer", initializerType)),
script => script.Remove (commaToken));
}
}

2
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantFieldInitializerIssue.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!defaultValueExpr.Match (variable.Initializer).Success)
continue;
AddIssue (variable, ctx.TranslateString ("Remove redundant field initializer"),
AddIssue (variable.Initializer, ctx.TranslateString ("Remove redundant field initializer"),
script => script.Replace (variable, new VariableInitializer (variable.Name)));
}
}

64
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantWhereWithPredicateIssue.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[IssueDescription("Any() should be used with predicate and Where() removed",
Description= "Detects redundant Where() with predicate calls followed by Any().",
Category = IssueCategories.CodeQualityIssues,
Severity = Severity.Hint)]
public class RedundantWhereWithPredicateIssue : ICodeIssueProvider
{
static readonly AstNode pattern =
new InvocationExpression (
new MemberReferenceExpression (
new NamedNode ("whereInvoke",
new InvocationExpression (
new MemberReferenceExpression (new AnyNode ("target"), "Where"),
new AnyNode ())),
"Any"));
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor(context).GetIssues();
}
class GatherVisitor : GatherVisitorBase
{
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
{
}
public override void VisitInvocationExpression (InvocationExpression anyInvoke)
{
base.VisitInvocationExpression (anyInvoke);
var match = pattern.Match (anyInvoke);
if (!match.Success)
return;
var anyResolve = ctx.Resolve (anyInvoke) as InvocationResolveResult;
if (anyResolve == null || anyResolve.Member.FullName != "System.Linq.Enumerable.Any")
return;
var whereInvoke = match.Get<InvocationExpression> ("whereInvoke").Single ();
var whereResolve = ctx.Resolve (whereInvoke) as InvocationResolveResult;
if (whereResolve == null || whereResolve.Member.FullName != "System.Linq.Enumerable.Where")
return;
if (whereResolve.Member.Parameters.Count != 2)
return;
var predResolve = whereResolve.Member.Parameters [1];
if (predResolve.Type.TypeParameterCount != 2)
return;
AddIssue (anyInvoke, "Redundant Where() call with predicate followed by Any()", script => {
var arg = whereInvoke.Arguments.Single ().Clone ();
var target = match.Get<Expression> ("target").Single ().Clone ();
script.Replace (anyInvoke, new InvocationExpression (new MemberReferenceExpression (target, "Any"), arg));
});
}
}
}
}

16
ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -461,7 +461,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -461,7 +461,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
EntityDeclaration ConvertTypeDefinition(ITypeDefinition typeDefinition)
{
Modifiers modifiers = ModifierFromAccessibility(typeDefinition.Accessibility);
Modifiers modifiers = Modifiers.None;
if (this.ShowAccessibility) {
modifiers |= ModifierFromAccessibility(typeDefinition.Accessibility);
}
if (this.ShowModifiers) {
if (typeDefinition.IsStatic) {
modifiers |= Modifiers.Static;
@ -598,7 +601,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -598,7 +601,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (accessor == null)
return Accessor.Null;
Accessor decl = new Accessor();
if (accessor.Accessibility != ownerAccessibility)
if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility)
decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility);
decl.Body = GenerateBodyBlock();
return decl;
@ -716,10 +719,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -716,10 +719,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
#endregion
#region Convert Modifiers
Modifiers ModifierFromAccessibility(Accessibility accessibility)
static Modifiers ModifierFromAccessibility(Accessibility accessibility)
{
if (!this.ShowAccessibility)
return Modifiers.None;
switch (accessibility) {
case Accessibility.Private:
return Modifiers.Private;
@ -740,7 +741,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -740,7 +741,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Modifiers GetMemberModifiers(IMember member)
{
bool isInterfaceMember = member.DeclaringType.Kind == TypeKind.Interface;
Modifiers m = isInterfaceMember ? Modifiers.None : ModifierFromAccessibility(member.Accessibility);
Modifiers m = Modifiers.None;
if (this.ShowAccessibility && !isInterfaceMember) {
m |= ModifierFromAccessibility(member.Accessibility);
}
if (this.ShowModifiers) {
if (member.IsStatic) {
m |= Modifiers.Static;

39
ICSharpCode.NRefactory.CSharp/Refactoring/VariableReferenceGraph.cs

@ -28,6 +28,7 @@ using System.Collections.Generic; @@ -28,6 +28,7 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Threading;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -80,6 +81,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -80,6 +81,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return cfgVrNodeBuilder.Build (cfg [0], references, refStatements, context.Resolver);
}
public static VariableReferenceNode Build (Statement statement, ISet<AstNode> references,
ISet<Statement> refStatements, CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken))
{
var cfg = cfgBuilder.BuildControlFlowGraph (statement, resolver, cancellationToken);
return cfgVrNodeBuilder.Build (cfg [0], references, refStatements, resolver);
}
class GetExpressionsVisitor : DepthFirstAstVisitor<IEnumerable<Expression>>
{
@ -153,6 +161,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -153,6 +161,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
yield return yieldReturnStatement.Expression;
}
public override IEnumerable<Expression> VisitBlockStatement(BlockStatement blockStatement)
{
yield break;
}
}
class CfgVariableReferenceNodeBuilder
@ -216,16 +228,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -216,16 +228,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
nodeDict [cfNode] = node;
if (IsValidControlFlowNode (cfNode) && refStatements.Contains (cfNode.NextStatement))
if (IsValidControlFlowNode (cfNode) && refStatements.Contains (cfNode.NextStatement)) {
node = GetStatementEndNode (node, cfNode.NextStatement);
}
if (cfNode.Outgoing.Count == 1) {
cfNode = cfNode.Outgoing [0].To;
} else {
foreach (var e in cfNode.Outgoing)
foreach (var e in cfNode.Outgoing) {
node.AddNextNode (AddNode (e.To));
}
break;
}
// Hack for handling try ... catch ... finally.
var tryc = cfNode.NextStatement as TryCatchStatement;
if (tryc != null) {
VariableReferenceNode outNode = null;
foreach (var n in tryc.CatchClauses) {
var catchNode = VariableReferenceGraphBuilder.Build(n.Body, references, refStatements, this.resolver);
(outNode ?? node).AddNextNode (catchNode);
outNode = catchNode;
}
if (!tryc.FinallyBlock.IsNull) {
var finallyNode = VariableReferenceGraphBuilder.Build(tryc.FinallyBlock, references, refStatements, this.resolver);
(outNode ?? node).AddNextNode (finallyNode);
outNode = finallyNode;
}
if (outNode != null) {
nodeDict [cfNode] = outNode;
return outNode;
}
}
}
return nodeDict [startNode];
}
@ -282,7 +316,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -282,7 +316,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
#region Skipped Expressions
public override void VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression)
{
}

15
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -3257,13 +3257,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -3257,13 +3257,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
AstType outermostType = type;
while (outermostType.Parent is AstType)
outermostType = (AstType)outermostType.Parent;
NameLookupMode lookupMode = NameLookupMode.Type;
if (outermostType.Parent is UsingDeclaration || outermostType.Parent is UsingAliasDeclaration) {
lookupMode = NameLookupMode.TypeInUsingDeclaration;
} else if (outermostType.Parent is TypeDeclaration && outermostType.Role == Roles.BaseType) {
lookupMode = NameLookupMode.BaseTypeReference;
}
return lookupMode;
return NameLookupMode.TypeInUsingDeclaration;
} else if (outermostType.Role == Roles.BaseType) {
// Use BaseTypeReference for a type's base type, and for a constraint on a type.
// Do not use it for a constraint on a method.
if (outermostType.Parent is TypeDeclaration || (outermostType.Parent is Constraint && outermostType.Parent.Parent is TypeDeclaration))
return NameLookupMode.BaseTypeReference;
}
return NameLookupMode.Type;
}
ResolveResult IAstVisitor<ResolveResult>.VisitMemberType(MemberType memberType)

3
ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs

@ -515,7 +515,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -515,7 +515,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
continue;
}
}
tp.Constraints.Add(type.ToTypeReference());
var lookupMode = (ownerType == EntityType.TypeDefinition) ? NameLookupMode.BaseTypeReference : NameLookupMode.Type;
tp.Constraints.Add(type.ToTypeReference(lookupMode));
}
break;
}

6
ICSharpCode.NRefactory.Demo/CSDemo.cs

@ -65,7 +65,11 @@ namespace ICSharpCode.NRefactory.Demo @@ -65,7 +65,11 @@ namespace ICSharpCode.NRefactory.Demo
void CSharpParseButtonClick(object sender, EventArgs e)
{
syntaxTree = new CSharpParser().Parse(csharpCodeTextBox.Text, "demo.cs");
var parser = new CSharpParser();
syntaxTree = parser.Parse(csharpCodeTextBox.Text, "demo.cs");
if (parser.HasErrors) {
MessageBox.Show(string.Join(Environment.NewLine, parser.Errors.Select(err => err.Message)));
}
csharpTreeView.Nodes.Clear();
foreach (var element in syntaxTree.Children) {
csharpTreeView.Nodes.Add(MakeTreeNode(element));

42
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertAsToCastTests.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
public class ConvertAsToCastTests : ContextActionTestBase
{
[Test]
public void Test()
public void Test ()
{
Test<ConvertAsToCastAction> (@"
using System;
@ -54,5 +54,45 @@ class TestClass @@ -54,5 +54,45 @@ class TestClass
}
}");
}
[Test]
public void TestRemoveParentheses ()
{
string input = @"
class TestClass {
void TestMethod (object o)
{
var b = 1 + (o $as TestClass);
}
}";
string output = @"
class TestClass {
void TestMethod (object o)
{
var b = 1 + (TestClass)o;
}
}";
Test<ConvertAsToCastAction> (input, output);
}
[Test]
public void TestInsertParentheses ()
{
string input = @"
class TestClass {
void TestMethod (object o)
{
var b = 1 + o $as TestClass;
}
}";
string output = @"
class TestClass {
void TestMethod (object o)
{
var b = (TestClass)(1 + o);
}
}";
Test<ConvertAsToCastAction> (input, output);
}
}
}

30
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertCastToAsTests.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
[TestFixture]
public class ConvertCastToAsTests : ContextActionTestBase
{
void TestType(string type)
void TestType (string type)
{
string input = @"
using System;
@ -56,19 +56,19 @@ class TestClass @@ -56,19 +56,19 @@ class TestClass
}
[Test]
public void Test()
public void Test ()
{
TestType ("Exception");
}
[Test]
public void TestNullable()
public void TestNullable ()
{
TestType ("int?");
}
[Test]
public void TestNonReferenceType()
public void TestNonReferenceType ()
{
TestWrongContext<ConvertCastToAsAction> (@"
using System;
@ -76,9 +76,29 @@ class TestClass @@ -76,9 +76,29 @@ class TestClass
{
void Test (object a)
{
var b = (int)$a;
var b = ($int)a;
}
}");
}
[Test]
public void TestInsertParentheses ()
{
string input = @"
class TestClass {
void TestMethod (object o)
{
var b = 1 + ($TestClass)o;
}
}";
string output = @"
class TestClass {
void TestMethod (object o)
{
var b = 1 + (o as TestClass);
}
}";
Test<ConvertCastToAsAction> (input, output);
}
}
}

22
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertLamdaToAnonymousDelegateTests.cs

@ -72,6 +72,28 @@ class A @@ -72,6 +72,28 @@ class A
System.Console.WriteLine (i1);
};
}
}");
}
[Test]
public void ParameterLessLambdaTest ()
{
Test<ConvertLambdaToAnonymousDelegateAction>(@"
class A
{
void F ()
{
System.Action = ()$ => { System.Console.WriteLine (); };
}
}", @"
class A
{
void F ()
{
System.Action = delegate {
System.Console.WriteLine ();
};
}
}");
}
}

21
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs

@ -301,5 +301,26 @@ class TestClass @@ -301,5 +301,26 @@ class TestClass
");
}
[Test()]
public void TestModifierBug ()
{
Test<CreateClassDeclarationAction> (
@"
class TestClass
{
private readonly $Foo _foo;
}
", @"
class Foo
{
}
class TestClass
{
private readonly Foo _foo;
}
");
}
}
}

23
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateOverloadWithoutParameterTests.cs

@ -203,6 +203,29 @@ class Test : ITest @@ -203,6 +203,29 @@ class Test : ITest
void ITest.Test (int a, int $b)
{
}
}");
}
[Test]
public void TestGenereatedCall ()
{
Test<CreateOverloadWithoutParameterAction> (
@"class Test
{
void TestMethod (ref int $i, ref int j, out int k)
{
}
}",
@"class Test
{
void TestMethod (ref int j, out int k)
{
int i = 0;
TestMethod (ref i, ref j, out k);
}
void TestMethod (ref int i, ref int j, out int k)
{
}
}");
}
}

55
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementAbstractMembersTest.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// ImplementAbstractMembersTest.cs
//
// Author:
@ -58,6 +58,59 @@ class Foo : Simple @@ -58,6 +58,59 @@ class Foo : Simple
");
}
[Test()]
public void TestProtectedMembers()
{
Test<ImplementAbstractMembersAction>(@"abstract class Simple {
protected abstract string ServiceName { get; }
}
class Foo : $Simple
{
}
", @"abstract class Simple {
protected abstract string ServiceName { get; }
}
class Foo : Simple
{
#region implemented abstract members of Simple
protected override string ServiceName {
get {
throw new System.NotImplementedException ();
}
}
#endregion
}
");
}
[Test()]
public void TestProtectedInternalMembers()
{
Test<ImplementAbstractMembersAction>(@"abstract class Simple {
protected internal abstract string ServiceName { get; }
}
class Foo : $Simple
{
}
", @"abstract class Simple {
protected internal abstract string ServiceName { get; }
}
class Foo : Simple
{
#region implemented abstract members of Simple
protected internal override string ServiceName {
get {
throw new System.NotImplementedException ();
}
}
#endregion
}
");
}
}
}

24
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/PutInsideUsingTests.cs

@ -185,6 +185,30 @@ class TestClass @@ -185,6 +185,30 @@ class TestClass
}
a++;
}
}");
}
[Test]
public void TestRemoveDisposeInvocation ()
{
Test<PutInsideUsingAction> (@"
class TestClass
{
void TestMethod ()
{
System.IDisposable obj $= null;
obj.Method ();
obj.Dispose();
}
}", @"
class TestClass
{
void TestMethod ()
{
using (System.IDisposable obj = null) {
obj.Method ();
}
}
}");
}
}

2
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"{" + Environment.NewLine +
" void Test ()" + Environment.NewLine +
" {" + Environment.NewLine +
" var aVar;" + Environment.NewLine +
" TestClass aVar;" + Environment.NewLine +
" aVar = this;" + Environment.NewLine +
" }" + Environment.NewLine +
"}", result);

16
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/CastExpressionOfIncompatibleTypeIssueTests.cs

@ -46,5 +46,21 @@ class TestClass @@ -46,5 +46,21 @@ class TestClass
}";
Test<CastExpressionOfIncompatibleTypeIssue> (input, 2);
}
[Test]
public void TestCompatibleTypes ()
{
var input = @"
class TestClass
{
void TestMethod ()
{
var x1 = (int)123;
var x2 = (int)System.ConsoleKey.A;
}
}";
Test<CastExpressionOfIncompatibleTypeIssue> (input, 0);
}
}
}

53
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantArrayInitializerCommaIssueTests.cs

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp.CodeActions;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using NUnit.Framework;
@ -53,5 +54,57 @@ class TestClass @@ -53,5 +54,57 @@ class TestClass
}";
Test<RedundantArrayInitializerCommaIssue> (input, 1, output);
}
[Test]
public void TestArrayInitializerDescription ()
{
var input = @"
class TestClass
{
void TestMethod ()
{
var a = new int[] { 1, 2, };
}
}";
TestRefactoringContext ctx;
var issues = GetIssues (new RedundantArrayInitializerCommaIssue (), input, out ctx);
Assert.AreEqual (issues.Count, 1);
Assert.AreEqual (issues [0].Description, "Remove redundant comma in array initializer");
}
[Test]
public void TestObjectInitializerDescription ()
{
var input = @"
class TestClass
{
int Prop { get; set; }
void TestMethod ()
{
var a = new TestClass { Prop = 1, };
}
}";
TestRefactoringContext ctx;
var issues = GetIssues (new RedundantArrayInitializerCommaIssue (), input, out ctx);
Assert.AreEqual (issues.Count, 1);
Assert.AreEqual (issues [0].Description, "Remove redundant comma in object initializer");
}
[Test]
public void TestCollectionInitializerDescrition ()
{
var input = @"
class TestClass
{
void TestMethod ()
{
var a = new TestClass { 1, };
}
}";
TestRefactoringContext ctx;
var issues = GetIssues (new RedundantArrayInitializerCommaIssue (), input, out ctx);
Assert.AreEqual (issues.Count, 1);
Assert.AreEqual (issues [0].Description, "Remove redundant comma in collection initializer");
}
}
}

44
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantAssignmentIssueTests.cs

@ -290,5 +290,49 @@ class TestClass @@ -290,5 +290,49 @@ class TestClass
}";
Test<RedundantAssignmentIssue> (input, 0);
}
[Test]
public void TestAssignmentInTryCatch ()
{
var input = @"using System;
class TestClass
{
void TestMethod ()
{
var a = new TestClass ();
try {
a = null;
} catch (Exception) {
if (a != null) {
a.TestMethod ();
}
}
}
}";
Test<RedundantAssignmentIssue> (input, 0);
}
[Test]
public void TestAssignmentInTryCatchFinally ()
{
var input = @"
class TestClass
{
void TestMethod ()
{
var a = new TestClass ();
try {
a = null;
} finally {
if (a != null) {
a.TestMethod ();
}
}
}
}";
Test<RedundantAssignmentIssue> (input, 0);
}
}
}

70
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantWhereWithPredicateIssueTests.cs

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
using System;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.CodeActions;
namespace ICSharpCode.NRefactory.CSharp.CodeIssues
{
[TestFixture]
public class RedundantWhereWithPredicateIssueTests : InspectionActionTestBase
{
[Test]
public void TestWhereAnyCase1 ()
{
var input = @"using System.Linq;
public class CSharpDemo {
public void Bla () {
int[] arr;
var bla = arr.Where (x => x < 4).Any ();
}
}";
TestRefactoringContext context;
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context);
Assert.AreEqual (1, issues.Count);
CheckFix (context, issues, @"using System.Linq;
public class CSharpDemo {
public void Bla () {
int[] arr;
var bla = arr.Any (x => x < 4);
}
}");
}
[Test]
public void TestWhereAnyWrongWhere1 ()
{
var input = @"using System.Linq;
public class CSharpDemo {
public void Bla () {
int[] arr;
var bla = arr.Where ((x, i) => x + i < 4).Any ();
}
}";
TestRefactoringContext context;
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context);
Assert.AreEqual (0, issues.Count);
}
[Test]
public void TestWhereAnyWrongWhere2 ()
{
var input = @"using System;
using System.Linq;
public class X
{
X Where (Func<int,int> f) { return null; }
bool Any () { return false; }
public void Bla () {
X ex = null;
var bla = ex.Where (x => x + 1).Any ();
}
}";
TestRefactoringContext context;
var issues = GetIssues (new RedundantWhereWithPredicateIssue (), input, out context);
Assert.AreEqual (0, issues.Count);
}
}
}

50
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -1015,5 +1015,55 @@ namespace foo { @@ -1015,5 +1015,55 @@ namespace foo {
Assert.AreEqual("foo.Foo", result.Type.FullName);
}
[Test]
public void BaseTypeReference_refers_to_outer_type()
{
string program = @"class B {}
class A : $B$ {
class B {}
}";
var result = Resolve<TypeResolveResult>(program);
Assert.IsFalse(result.IsError);
Assert.AreEqual("B", result.Type.FullName);
// also check if the reference in the type system is correct
var a = ((ITypeDefinition)result.Type).Compilation.RootNamespace.GetTypeDefinition("A", 0);
Assert.AreEqual("B", a.DirectBaseTypes.Single().FullName);
}
[Test]
public void Class_constraint_refers_to_outer_type()
{
string program = @"class B {}
class A<T> where T : $B$ {
class B {}
}";
var result = Resolve<TypeResolveResult>(program);
Assert.IsFalse(result.IsError);
Assert.AreEqual("B", result.Type.FullName);
// also check if the reference in the type system is correct
var a = ((ITypeDefinition)result.Type).Compilation.RootNamespace.GetTypeDefinition("A", 1);
Assert.AreEqual("B", a.TypeParameters.Single().DirectBaseTypes.Single().FullName);
}
[Test]
public void Method_constraint_refers_to_inner_type()
{
string program = @"class B {}
class A {
void M<T>() where T : $B$ {}
class B {}
}";
var result = Resolve<TypeResolveResult>(program);
Assert.IsFalse(result.IsError);
Assert.AreEqual("A.B", result.Type.FullName);
// also check if the reference in the type system is correct
var a = ((ITypeDefinition)result.Type).Compilation.RootNamespace.GetTypeDefinition("A", 0);
var method = a.Methods.Single(m => m.Name == "M");
Assert.AreEqual("A.B", method.TypeParameters.Single().DirectBaseTypes.Single().FullName);
}
}
}

23
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs

@ -179,5 +179,28 @@ class Foo { @@ -179,5 +179,28 @@ class Foo {
}
}"));
}
[Test]
public void TestBug6758()
{
var rr = ResolveAtLocation<TypeResolveResult>(
@"using System;
namespace TestCrash
{
class A
{
}
class B<T> : T where T: $A
{
}
}
");
Assert.AreEqual("A", rr.Type.Name);
}
}
}

1
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -359,6 +359,7 @@ @@ -359,6 +359,7 @@
<Compile Include="CSharp\CodeActions\ConvertLamdaToAnonymousDelegateTests.cs" />
<Compile Include="CSharp\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterionTests.cs" />
<Compile Include="CSharp\CodeActions\CreateBackingStoreTests.cs" />
<Compile Include="CSharp\CodeIssues\RedundantWhereWithPredicateIssueTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">

5
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -327,4 +327,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -327,4 +327,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
get { return 0; }
}
}
public class ClassWithMethodThatHasNullableDefaultParameter {
public void Foo (int? bar = 42) { }
}
}

8
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -1200,5 +1200,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1200,5 +1200,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
var indexer = type.GetProperties(p => p.IsIndexer).Single();
Assert.AreEqual("Foo", indexer.Name);
}
[Test]
public void TestNullableDefaultParameter()
{
ITypeDefinition type = GetTypeDefinition(typeof(ClassWithMethodThatHasNullableDefaultParameter));
var method = type.GetMethods ().Single (m => m.Name == "Foo");
Assert.AreEqual(42, method.Parameters.Single ().ConstantValue);
}
}
}

1
ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs

@ -1963,6 +1963,7 @@ namespace ICSharpCode.NRefactory.VB @@ -1963,6 +1963,7 @@ namespace ICSharpCode.NRefactory.VB
WriteKeyword("For");
WriteKeyword("Each");
forEachStatement.Variable.AcceptVisitor(this, data);
Space();
WriteKeyword("In");
forEachStatement.InExpression.AcceptVisitor(this, data);
NewLine();

14
ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs

@ -671,6 +671,12 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -671,6 +671,12 @@ namespace ICSharpCode.NRefactory.VB.Visitors
((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Dereference" };
((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
break;
case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Await:
expr = new UnaryOperatorExpression() {
Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data),
Operator = UnaryOperatorType.Await
};
break;
default:
throw new Exception("Invalid value for UnaryOperatorType");
}
@ -1912,14 +1918,14 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -1912,14 +1918,14 @@ namespace ICSharpCode.NRefactory.VB.Visitors
throw new NotImplementedException();
}
public AstNode VisitCompilationUnit(CSharp.CompilationUnit compilationUnit, object data)
public AstNode VisitSyntaxTree(CSharp.SyntaxTree syntaxTree, object data)
{
var unit = new CompilationUnit();
foreach (var node in compilationUnit.Children)
foreach (var node in syntaxTree.Children)
unit.AddChild(node.AcceptVisitor(this, null), CompilationUnit.MemberRole);
return EndNode(compilationUnit, unit);
return EndNode(syntaxTree, unit);
}
public AstNode VisitSimpleType(CSharp.SimpleType simpleType, object data)
@ -2134,6 +2140,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors @@ -2134,6 +2140,8 @@ namespace ICSharpCode.NRefactory.VB.Visitors
mod |= Modifiers.Override;
if ((modifier & CSharp.Modifiers.Virtual) == CSharp.Modifiers.Virtual)
mod |= Modifiers.Overridable;
if ((modifier & CSharp.Modifiers.Async) == CSharp.Modifiers.Async)
mod |= Modifiers.Async;
return mod;
}

21
ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs

@ -259,13 +259,30 @@ namespace ICSharpCode.NRefactory.Documentation @@ -259,13 +259,30 @@ namespace ICSharpCode.NRefactory.Documentation
int pos = linePosMapper.GetPositionForLine(reader.LineNumber) + Math.Max(reader.LinePosition - 2, 0);
string memberAttr = reader.GetAttribute("name");
if (memberAttr != null)
indexList.Add(new IndexEntry(memberAttr.GetHashCode(), pos));
indexList.Add(new IndexEntry(GetHashCode(memberAttr), pos));
reader.Skip();
}
break;
}
}
}
/// <summary>
/// Hash algorithm used for the index.
/// This is a custom implementation so that old index files work correctly
/// even when the .NET string.GetHashCode implementation changes
/// (e.g. due to .NET 4.5 hash randomization)
/// </summary>
static int GetHashCode(string key)
{
unchecked {
int h = 0;
foreach (char c in key) {
h = (h << 5) - h + c;
}
return h;
}
}
#endregion
#region GetDocumentation
@ -277,7 +294,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -277,7 +294,7 @@ namespace ICSharpCode.NRefactory.Documentation
if (key == null)
throw new ArgumentNullException("key");
int hashcode = key.GetHashCode();
int hashcode = GetHashCode(key);
// index is sorted, so we can use binary search
int m = Array.BinarySearch(index, new IndexEntry(hashcode, 0));
if (m < 0)

1
ICSharpCode.NRefactory/Semantics/ConversionResolveResult.cs

@ -63,5 +63,6 @@ namespace ICSharpCode.NRefactory.Semantics @@ -63,5 +63,6 @@ namespace ICSharpCode.NRefactory.Semantics
{
return new [] { Input };
}
}
}

13
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs

@ -235,12 +235,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -235,12 +235,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public object ConstantValue {
get {
ResolveResult rr = LazyInit.VolatileRead(ref this.resolvedDefaultValue);
if (rr != null) {
return rr.ConstantValue;
} else {
if (rr == null) {
rr = defaultValue.Resolve(context);
return LazyInit.GetOrSet(ref this.resolvedDefaultValue, rr).ConstantValue;
LazyInit.GetOrSet(ref this.resolvedDefaultValue, rr);
}
if (rr is ConversionResolveResult) {
var crr = (ConversionResolveResult)rr;
if (crr.Conversion.IsNullableConversion)
return crr.Input.ConstantValue;
}
return rr.ConstantValue;
}
}

Loading…
Cancel
Save