From 1e1ed360aa1656f0ba063e946df541eafb144171 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 1 Jun 2013 21:34:26 +0200 Subject: [PATCH] Fix ExpressionOfCompatibleTypeCastIssue: assigning a literal 0 to an enum-type variable is valid --- .../Analysis/ControlFlow.cs | 4 +- .../ExpressionOfCompatibleTypeCastIssue.cs | 49 +++++++++++-------- ...xpressionOfCompatibleTypeCastIssueTests.cs | 40 +++++++++++++++ 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs index d52f6964da..2d3895b1e9 100644 --- a/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs @@ -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) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs index e828ebbb9a..7173be843a 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ExpressionOfCompatibleTypeCastIssue.cs @@ -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); }); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs index 6af34c8099..b5c248f6bf 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionOfCompatibleTypeCastIssueTests.cs @@ -31,6 +31,31 @@ enum Enum{ }; }"; Test(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(input, output); + } + [Test] public void TestClassConversion() { @@ -155,6 +180,21 @@ class TestClass Point p; p = new Vector (); } +}"; + Test(input, 0); + } + + [Test] + public void TestAssignZeroToEnum() + { + var input = @"using System; +class TestClass +{ + void TestMethod () + { + StringComparison c = 0; + c = 0; + } }"; Test(input, 0); }