Browse Source

Fix ExpressionOfCompatibleTypeCastIssue: assigning a literal 0 to an enum-type variable is valid

pull/45/merge
Daniel Grunwald 13 years ago
parent
commit
1e1ed360aa
  1. 4
      ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs
  2. 49
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs
  3. 40
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs

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

@ -361,8 +361,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -361,8 +361,8 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
protected override ControlFlowNode VisitChildren(AstNode node, ControlFlowNode data)
{
// We have overrides for all possible expressions and should visit expressions only.
throw new NotImplementedException();
// We have overrides for all possible statements and should visit statements only.
throw new NotSupportedException();
}
public override ControlFlowNode VisitBlockStatement(BlockStatement blockStatement, ControlFlowNode data)

49
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs

@ -58,35 +58,44 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -58,35 +58,44 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
base.VisitAssignmentExpression(assignmentExpression);
if (assignmentExpression.Operator != AssignmentOperatorType.Assign)
return;
var rightExpressionType = ctx.Resolve(assignmentExpression.Right).Type;
var leftExpressionType = ctx.Resolve(assignmentExpression.Left).Type;
VisitTypeCastExpression(assignmentExpression, rightExpressionType, leftExpressionType);
var variableType = ctx.Resolve(assignmentExpression.Left).Type;
VisitTypeCastExpression(variableType, assignmentExpression.Right);
}
public override void VisitVariableInitializer(VariableInitializer variableInitializer)
{
base.VisitVariableInitializer(variableInitializer);
if (!variableInitializer.Initializer.IsNull) {
var variableType = ctx.Resolve(variableInitializer).Type;
VisitTypeCastExpression(variableType, variableInitializer.Initializer);
}
}
private AstType CreateShortType(AstNode node, IType fullType)
{
var builder = ctx.CreateTypeSytemAstBuilder(node);
return builder.ConvertType(fullType);
}
void VisitTypeCastExpression(AssignmentExpression expression, IType exprType, IType castToType)
void VisitTypeCastExpression(IType variableType, Expression expression)
{
if (exprType.Kind == TypeKind.Unknown || castToType.Kind == TypeKind.Unknown)
return;
var foundConversion = conversion.ExplicitConversion(exprType, castToType);
if (foundConversion == Conversion.None)
return;
if (!foundConversion.IsExplicit)
return;
var implicitConversion = conversion.ImplicitConversion(exprType, castToType);
if (implicitConversion != Conversion.None)
return;
AddIssue(expression, string.Format(ctx.TranslateString("Cast to '{0}'"), castToType.Name),
if (variableType.Kind == TypeKind.Unknown)
return; // ignore error if the variable type is unknown
if (ctx.GetConversion(expression).IsValid)
return; // don't complain if the code is valid
var rr = ctx.Resolve(expression);
if (rr.Type.Kind == TypeKind.Unknown)
return; // ignore error if expression type is unknown
var foundConversion = conversion.ExplicitConversion(rr, variableType);
if (!foundConversion.IsValid)
return; // there's an error, but we can't fix it by introducing a cast
AddIssue(expression, string.Format(ctx.TranslateString("Cast to '{0}'"), variableType.Name),
script => {
var right = expression.Right.Clone();
var castRight = right.CastTo(CreateShortType(expression, castToType));
script.Replace(expression.Right, castRight);
var right = expression.Clone();
var castRight = right.CastTo(CreateShortType(expression, variableType));
script.Replace(expression, castRight);
});
}
}

40
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs

@ -31,6 +31,31 @@ enum Enum{ }; @@ -31,6 +31,31 @@ enum Enum{ };
}";
Test<ExpressionOfCompatibleTypeCastIssue>(input, output);
}
[Test]
public void TestConversionInInitializer()
{
var input = @"
class TestClass
{
enum Enum{ };
void TestMethod (Enum i)
{
int x = i;
}
}";
var output = @"
class TestClass
{
enum Enum{ };
void TestMethod (Enum i)
{
int x = (int)i;
}
}";
Test<ExpressionOfCompatibleTypeCastIssue>(input, output);
}
[Test]
public void TestClassConversion()
{
@ -155,6 +180,21 @@ class TestClass @@ -155,6 +180,21 @@ class TestClass
Point p;
p = new Vector ();
}
}";
Test<ExpressionOfCompatibleTypeCastIssue>(input, 0);
}
[Test]
public void TestAssignZeroToEnum()
{
var input = @"using System;
class TestClass
{
void TestMethod ()
{
StringComparison c = 0;
c = 0;
}
}";
Test<ExpressionOfCompatibleTypeCastIssue>(input, 0);
}

Loading…
Cancel
Save