Browse Source

Add support for resolving "operator true".

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
46254b3b0d
  1. 21
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  2. 6
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  3. 6
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs
  4. 32
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs

21
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -2095,6 +2095,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2095,6 +2095,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region ResolveConditional
/// <summary>
/// Converts the input to <c>bool</c> using the rules for boolean expressions.
/// That is, <c>operator true</c> is used if a regular conversion to <c>bool</c> is not possible.
/// </summary>
public ResolveResult ResolveCondition(ResolveResult input)
{
if (input == null)
throw new ArgumentNullException("input");
IType boolean = compilation.FindType(KnownTypeCode.Boolean);
Conversion c = conversions.ImplicitConversion(input, boolean);
if (!c.IsValid) {
var opTrue = input.Type.GetMethods(m => m.IsOperator && m.Name == "op_True").FirstOrDefault();
if (opTrue != null) {
c = Conversion.UserDefinedImplicitConversion(opTrue, false);
}
}
return Convert(input, boolean, c);
}
public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression)
{
// C# 4.0 spec §7.14: Conditional operator
@ -2131,7 +2150,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2131,7 +2150,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else {
return ErrorResult;
}
isValid &= TryConvert(ref condition, compilation.FindType(KnownTypeCode.Boolean));
condition = ResolveCondition(condition);
if (isValid) {
if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) {
bool? val = condition.ConstantValue as bool?;

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

@ -2604,7 +2604,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2604,7 +2604,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled) {
for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) {
if (child.Role == AstNode.Roles.Condition) {
ResolveAndProcessConversion((Expression)child, resolver.Compilation.FindType(KnownTypeCode.Boolean));
Expression condition = (Expression)child;
ResolveResult conditionRR = Resolve(condition);
ResolveResult convertedRR = resolver.ResolveCondition(conditionRR);
if (convertedRR != conditionRR)
ProcessConversionResult(condition, convertedRR as ConversionResolveResult);
} else {
Scan(child);
}

6
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs

@ -64,5 +64,11 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers @@ -64,5 +64,11 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
Assert.AreEqual("MyObject", ((SimpleType)od.ReturnType).Identifier);
Assert.AreEqual("op_UnaryPlus", od.Name);
}
[Test, Ignore("Parser crash")]
public void InvalidOperatorTrueDeclaration()
{
ParseUtilCSharp.ParseTypeMember<OperatorDeclaration>("public static implicit operator true(MyBool b) {}", expectErrors: true);
}
}
}

32
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs

@ -165,5 +165,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -165,5 +165,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
AssertType(typeof(StringComparison), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(StringComparison)), MakeConstant(0)));
}
[Test]
public void TypeWithImplicitConversionToBool()
{
string program = @"struct MyBool {
public static implicit operator bool(MyBool b) {}
void Test() {
var x = $this$ ? 1 : 0;
}
}";
Assert.AreEqual("System.Boolean", GetExpectedType(program).ReflectionName);
Conversion c = GetConversion(program);
Assert.IsTrue(c.IsValid);
Assert.IsTrue(c.IsUserDefined);
Assert.AreEqual("op_Implicit", c.Method.Name);
}
[Test]
public void TypeWithOperatorTrue()
{
string program = @"struct MyBool {
public static bool operator true(MyBool b) {}
void Test() {
var x = $this$ ? 1 : 0;
}
}";
Assert.AreEqual("System.Boolean", GetExpectedType(program).ReflectionName);
Conversion c = GetConversion(program);
Assert.IsTrue(c.IsValid);
Assert.IsTrue(c.IsUserDefined);
Assert.AreEqual("op_True", c.Method.Name);
}
}
}

Loading…
Cancel
Save