You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
7.5 KiB
201 lines
7.5 KiB
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using ICSharpCode.NRefactory.Semantics; |
|
using NUnit.Framework; |
|
|
|
namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
{ |
|
// assign short name to the fake reflection type |
|
using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; |
|
|
|
[TestFixture] |
|
public class ConditionalOperatorTests : ResolverTestBase |
|
{ |
|
CSharpResolver resolver; |
|
|
|
public override void SetUp() |
|
{ |
|
base.SetUp(); |
|
resolver = new CSharpResolver(compilation); |
|
} |
|
|
|
void TestOperator(ResolveResult condition, ResolveResult trueExpr, ResolveResult falseExpr, |
|
Conversion conditionConv, Conversion trueConv, Conversion falseConv, |
|
Type expectedResultType) |
|
{ |
|
var corr = (OperatorResolveResult)resolver.ResolveConditional(condition, trueExpr, falseExpr); |
|
AssertType(expectedResultType, corr); |
|
AssertConversion(corr.Operands[0], condition, conditionConv, "Condition Conversion"); |
|
AssertConversion(corr.Operands[1], trueExpr, trueConv, "True Conversion"); |
|
AssertConversion(corr.Operands[2], falseExpr, falseConv, "False Conversion"); |
|
} |
|
|
|
[Test] |
|
public void PickMoreGeneralOfTheTypes() |
|
{ |
|
TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeResult(typeof(object)), |
|
Conversion.IdentityConversion, Conversion.ImplicitReferenceConversion, Conversion.IdentityConversion, |
|
typeof(object)); |
|
|
|
TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(int)), MakeResult(typeof(long)), |
|
Conversion.IdentityConversion, Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, |
|
typeof(long)); |
|
} |
|
|
|
[Test] |
|
public void StringAndNull() |
|
{ |
|
ResolveResult condition = MakeResult(typeof(bool)); |
|
ResolveResult trueExpr = MakeResult(typeof(string)); |
|
var result = (OperatorResolveResult)resolver.ResolveConditional( |
|
condition, trueExpr, MakeConstant(null)); |
|
AssertType(typeof(string), result); |
|
AssertConversion(result.Operands[0], condition, Conversion.IdentityConversion, "Condition Conversion"); |
|
AssertConversion(result.Operands[1], trueExpr, Conversion.IdentityConversion, "True Conversion"); |
|
Assert.IsTrue(result.Operands[2].IsCompileTimeConstant); |
|
Assert.IsNull(result.Operands[2].ConstantValue); |
|
Assert.AreEqual("System.String", result.Operands[2].Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void NullAndString() |
|
{ |
|
ResolveResult condition = MakeResult(typeof(bool)); |
|
ResolveResult falseExpr = MakeResult(typeof(string)); |
|
var result = (OperatorResolveResult)resolver.ResolveConditional( |
|
condition, MakeConstant(null), falseExpr); |
|
AssertType(typeof(string), result); |
|
AssertConversion(result.Operands[0], condition, Conversion.IdentityConversion, "Condition Conversion"); |
|
Assert.IsTrue(result.Operands[1].IsCompileTimeConstant); |
|
Assert.IsNull(result.Operands[1].ConstantValue); |
|
Assert.AreEqual("System.String", result.Operands[1].Type.FullName); |
|
AssertConversion(result.Operands[2], falseExpr, Conversion.IdentityConversion, "False Conversion"); |
|
} |
|
|
|
[Test] |
|
public void DynamicInArguments() |
|
{ |
|
TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(dynamic)), MakeResult(typeof(double)), |
|
Conversion.IdentityConversion, Conversion.IdentityConversion, Conversion.BoxingConversion, |
|
typeof(dynamic)); |
|
|
|
TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(double)), MakeResult(typeof(dynamic)), |
|
Conversion.IdentityConversion, Conversion.BoxingConversion, Conversion.IdentityConversion, |
|
typeof(dynamic)); |
|
} |
|
|
|
[Test] |
|
public void DynamicInCondition() |
|
{ |
|
TestOperator(MakeResult(typeof(dynamic)), MakeResult(typeof(float)), MakeResult(typeof(double)), |
|
Conversion.ImplicitDynamicConversion, Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, |
|
typeof(double)); |
|
} |
|
|
|
[Test] |
|
public void AllDynamic() |
|
{ |
|
TestOperator(MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), |
|
Conversion.ImplicitDynamicConversion, Conversion.IdentityConversion, Conversion.IdentityConversion, |
|
typeof(dynamic)); |
|
} |
|
|
|
[Test] |
|
public void ListOfDynamicAndListOfObject() |
|
{ |
|
AssertError(typeof(List<object>), resolver.ResolveConditional( |
|
MakeResult(typeof(bool)), MakeResult(typeof(List<object>)), MakeResult(typeof(List<dynamic>)))); |
|
|
|
AssertError(typeof(List<dynamic>), resolver.ResolveConditional( |
|
MakeResult(typeof(bool)), MakeResult(typeof(List<dynamic>)), MakeResult(typeof(List<object>)))); |
|
} |
|
|
|
[Test] |
|
public void Constant() |
|
{ |
|
AssertConstant(1L, resolver.ResolveConditional( |
|
MakeConstant(true), MakeConstant(1), MakeConstant(2L))); |
|
|
|
AssertConstant(2L, resolver.ResolveConditional( |
|
MakeConstant(false), MakeConstant(1), MakeConstant(2L))); |
|
} |
|
|
|
[Test] |
|
public void NotConstantIfFalsePortionNotConstant() |
|
{ |
|
AssertType(typeof(long), resolver.ResolveConditional( |
|
MakeConstant(true), MakeConstant(1), MakeResult(typeof(long)))); |
|
} |
|
|
|
[Test] |
|
public void ByteAndZeroLiteral() |
|
{ |
|
AssertType(typeof(int), resolver.ResolveConditional( |
|
MakeResult(typeof(bool)), MakeResult(typeof(byte)), MakeConstant(0))); |
|
} |
|
|
|
[Test] |
|
public void ByteAndUShort() |
|
{ |
|
AssertType(typeof(ushort), resolver.ResolveConditional( |
|
MakeResult(typeof(bool)), MakeResult(typeof(byte)), MakeResult(typeof(ushort)))); |
|
} |
|
|
|
[Test] |
|
public void EnumAndZeroLiteral() |
|
{ |
|
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); |
|
} |
|
} |
|
}
|
|
|