mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
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.
516 lines
24 KiB
516 lines
24 KiB
using CodingSeb.ExpressionEvaluator; |
|
using CppSharp.AST; |
|
using CppSharp.Generators.CSharp; |
|
using CppSharp.Passes; |
|
using NUnit.Framework; |
|
using System.Collections; |
|
using System.Linq; |
|
|
|
namespace CppSharp.Generator.Tests.Passes |
|
{ |
|
[TestFixture] |
|
public class TestPasses : ASTTestFixture |
|
{ |
|
[SetUp] |
|
public void Setup() |
|
{ |
|
ParseLibrary("Passes.h"); |
|
passBuilder = new PassBuilder<TranslationUnitPass>(Driver.Context); |
|
} |
|
|
|
[TearDown] |
|
public void TearDown() |
|
{ |
|
Driver.Dispose(); |
|
} |
|
|
|
[Test] |
|
public void TestExtractInterfacePass() |
|
{ |
|
var c = AstContext.Class("TestExtractInterfacePass"); |
|
|
|
Assert.IsNull(c.GetInterface()); |
|
|
|
passBuilder.AddPass(new ExtractInterfacePass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.IsNotNull(c.GetInterface()); |
|
Assert.AreEqual("ITestExtractInterfacePass", c.GetInterface().Name); |
|
} |
|
|
|
[Test] |
|
public void TestCheckEnumsPass() |
|
{ |
|
var @enum = AstContext.Enum("FlagEnum"); |
|
var enum2 = AstContext.Enum("FlagEnum2"); |
|
var boolClassEnum = AstContext.Enum("BoolEnum"); |
|
var ucharClassEnum = AstContext.Enum("UCharEnum"); |
|
|
|
Assert.IsFalse(@enum.IsFlags); |
|
Assert.IsFalse(enum2.IsFlags); |
|
Assert.IsFalse(boolClassEnum.IsFlags); |
|
Assert.IsFalse(ucharClassEnum.IsFlags); |
|
|
|
Assert.IsTrue(boolClassEnum.BuiltinType.Type == PrimitiveType.Bool); |
|
Assert.IsTrue(ucharClassEnum.BuiltinType.Type == PrimitiveType.UChar); |
|
|
|
passBuilder.AddPass(new CheckEnumsPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.IsTrue(@enum.IsFlags); |
|
Assert.IsFalse(enum2.IsFlags); |
|
Assert.IsFalse(boolClassEnum.IsFlags); |
|
Assert.IsTrue(ucharClassEnum.IsFlags); |
|
|
|
Assert.IsTrue(boolClassEnum.BuiltinType.Type != PrimitiveType.Bool, "C# does not support Bool enums"); |
|
Assert.IsTrue(ucharClassEnum.BuiltinType.Type == PrimitiveType.UChar); |
|
} |
|
|
|
[Test] |
|
public void TestCheckStaticClassPass() |
|
{ |
|
var staticClass = AstContext.Class("TestCheckStaticClass"); |
|
var staticStruct = AstContext.Class("TestCheckStaticStruct"); |
|
var staticClassDeletedCtor = AstContext.Class("TestCheckStaticClassDeleted"); |
|
var nonStaticClass = AstContext.Class("TestCheckNonStaticClass"); |
|
var nonStaticEmptyClass = AstContext.Class("TestCommentsPass"); |
|
|
|
Assert.IsFalse(staticClass.IsStatic); |
|
Assert.IsFalse(staticStruct.IsStatic); |
|
Assert.IsFalse(staticClassDeletedCtor.IsStatic); |
|
Assert.IsFalse(nonStaticClass.IsStatic); |
|
Assert.IsFalse(nonStaticEmptyClass.IsStatic); |
|
|
|
passBuilder.AddPass(new CheckStaticClassPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.IsTrue(staticClass.IsStatic, "`TestCheckStaticClass` should be static"); |
|
Assert.IsTrue(staticStruct.IsStatic, "`TestCheckStaticStruct` should be static"); |
|
Assert.IsTrue(staticClassDeletedCtor.IsStatic, "`TestCheckStaticClassDeleted` should be static"); |
|
|
|
Assert.IsFalse(nonStaticClass.IsStatic, "`TestCheckNonStaticClass` should NOT be static, since it has a private data field with default ctor"); |
|
Assert.IsFalse(nonStaticEmptyClass.IsStatic, "`TestCommentsPass` should NOT be static, since it doesn't have any static declarations"); |
|
} |
|
|
|
[Test] |
|
public void TestFunctionToInstancePass() |
|
{ |
|
var c = AstContext.Class("Foo"); |
|
|
|
Assert.IsNull(c.Method("Start")); |
|
|
|
passBuilder.AddPass(new FunctionToInstanceMethodPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.IsNotNull(c.Method("Start")); |
|
} |
|
|
|
[Test] |
|
public void TestFunctionToStaticPass() |
|
{ |
|
var c = AstContext.Class("Foo"); |
|
|
|
Assert.IsTrue(AstContext.Function("FooStart").IsGenerated); |
|
Assert.IsNull(c.Method("Start")); |
|
|
|
passBuilder.AddPass(new FunctionToStaticMethodPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.IsFalse(AstContext.Function("FooStart").IsGenerated); |
|
Assert.IsNotNull(c.Method("Start")); |
|
} |
|
|
|
[Test] |
|
public void TestCleanCommentsPass() |
|
{ |
|
var c = AstContext.Class("TestCommentsPass"); |
|
var c2 = AstContext.Class("TestCommentsPass2"); |
|
|
|
passBuilder.AddPass(new CleanCommentsPass()); |
|
passBuilder.RunPasses(pass => pass.VisitDeclaration(c)); |
|
passBuilder.RunPasses(pass => pass.VisitClassDecl(c2)); |
|
|
|
var para = (ParagraphComment)c.Comment.FullComment.Blocks[0]; |
|
var textGenerator = new TextGenerator(); |
|
textGenerator.Print(para, CommentKind.BCPLSlash); |
|
|
|
Assert.That(textGenerator.StringBuilder.ToString().Trim(), |
|
Is.EqualTo("/// <summary>A simple test.</summary>")); |
|
|
|
var textGenerator2 = new TextGenerator(); |
|
textGenerator2.Print(c2.Methods[0].Comment.FullComment, CommentKind.BCPLSlash); |
|
|
|
Assert.That(textGenerator2.StringBuilder.ToString().Trim(), |
|
Is.EqualTo( |
|
"/// <summary>Gets a value</summary>\n" + |
|
"/// <returns>One</returns>" |
|
)); |
|
|
|
var textGenerator3 = new TextGenerator(); |
|
textGenerator3.Print(c2.Methods[1].Comment.FullComment, CommentKind.BCPLSlash); |
|
|
|
Assert.That(textGenerator3.StringBuilder.ToString().Trim(), |
|
Is.EqualTo( |
|
"/// <summary>Sets a value. Get it with <see cref=\"GetValueWithComment\"/></summary>\n" + |
|
"/// <param name=\"value\">The value to set</param>\n" + |
|
"/// <returns>The parameter (typeof<float>)</returns>" |
|
)); |
|
} |
|
|
|
[Test] |
|
public void TestCaseRenamePass() |
|
{ |
|
Type.TypePrinterDelegate += TypePrinterDelegate; |
|
|
|
var c = AstContext.Class("TestRename"); |
|
|
|
passBuilder.AddPass(new FieldToPropertyPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
var method = c.Method("lowerCaseMethod"); |
|
var property = c.Properties.Find(p => p.Name == "lowerCaseField"); |
|
|
|
passBuilder.RenameDeclsUpperCase(RenameTargets.Any); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.That(method.Name, Is.EqualTo("LowerCaseMethod")); |
|
Assert.That(property.Name, Is.EqualTo("LowerCaseField")); |
|
|
|
Type.TypePrinterDelegate -= TypePrinterDelegate; |
|
} |
|
|
|
[Test] |
|
public void TestCleanEnumItemNames() |
|
{ |
|
AstContext.GenerateEnumFromMacros("TestEnumItemName", "TEST_ENUM_ITEM_NAME_(.*)"); |
|
|
|
var @enum = AstContext.Enum("TestEnumItemName"); |
|
Assert.IsNotNull(@enum); |
|
|
|
// Testing the values read for the enum |
|
Assert.AreEqual(3, @enum.Items[0].Value); // Decimal literal |
|
Assert.AreEqual(0, @enum.Items[1].Value); // Hex literal |
|
Assert.AreEqual(1, @enum.Items[2].Value); // Hex literal with suffix |
|
Assert.AreEqual(2, @enum.Items[3].Value); // Enum item |
|
|
|
passBuilder.RemovePrefix("TEST_ENUM_ITEM_NAME_", RenameTargets.EnumItem); |
|
passBuilder.AddPass(new CleanInvalidDeclNamesPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
Assert.That(@enum.Items[1].Name, Is.EqualTo("_0")); |
|
} |
|
|
|
[Test] |
|
public void TestEnumBaseTypesFromMacroValues() |
|
{ |
|
AstContext.GenerateEnumFromMacros("TestEnumMaxSbyte", "TEST_ENUM_MAX_SBYTE"); |
|
var @enum = AstContext.Enum("TestEnumMaxSbyte"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(sbyte.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxByte", "TEST_ENUM_MAX_BYTE"); |
|
@enum = AstContext.Enum("TestEnumMaxByte"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(byte.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxShort", "TEST_ENUM_MAX_SHORT"); |
|
@enum = AstContext.Enum("TestEnumMaxShort"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(short.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.Short, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxUshort", "TEST_ENUM_MAX_USHORT"); |
|
@enum = AstContext.Enum("TestEnumMaxUshort"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(ushort.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.UShort, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxInt", "TEST_ENUM_MAX_INT"); |
|
@enum = AstContext.Enum("TestEnumMaxInt"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(int.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.Int, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxLong", "TEST_ENUM_MAX_LONG"); |
|
@enum = AstContext.Enum("TestEnumMaxLong"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(long.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxUint", "TEST_ENUM_MAX_UINT"); |
|
@enum = AstContext.Enum("TestEnumMaxUint"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(uint.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.UInt, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMaxUlong", "TEST_ENUM_MAX_ULONG"); |
|
@enum = AstContext.Enum("TestEnumMaxUlong"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(ulong.MaxValue, @enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.ULongLong, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMinInt", "TEST_ENUM_MIN_INT"); |
|
@enum = AstContext.Enum("TestEnumMinInt"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(int.MinValue, (long)@enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.Int, @enum.BuiltinType.Type); |
|
|
|
AstContext.GenerateEnumFromMacros("TestEnumMinLong", "TEST_ENUM_MIN_LONG"); |
|
@enum = AstContext.Enum("TestEnumMinLong"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(long.MinValue, (long)@enum.Items[0].Value); |
|
Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
|
} |
|
|
|
// These tests have nothing to do with testing passes except that the expression evaluator |
|
// is only used by GenerateEnumFromMacros. Add a separate TestFixture? |
|
static ExprEvalTestParams[] TestExpressionEvaluatorTestCases = |
|
{ |
|
new ExprEvalTestParams("2147483647", int.MaxValue), |
|
new ExprEvalTestParams("-2147483648", int.MinValue), |
|
new ExprEvalTestParams("4294967295", uint.MaxValue), |
|
new ExprEvalTestParams("9223372036854775807", long.MaxValue), |
|
new ExprEvalTestParams("-9223372036854775808", long.MinValue), |
|
new ExprEvalTestParams("18446744073709551615", ulong.MaxValue), |
|
|
|
// Must use "L" suffix here or the expression evaluator will overflow with no warning. Note |
|
// that it won't compile in C# without it. |
|
new ExprEvalTestParams("-2147483648L - 1", -2147483648L - 1), |
|
|
|
// Note that the dynamic subsystem used by the expression evaluator types this result as |
|
// long, but the compiler types the expression a uint. Adding the casts to dynamic in |
|
// the expressions below matches the result of the expression evaluator. Not sure we |
|
// care that they're different. |
|
new ExprEvalTestParams("2147483648 + 5", (dynamic)2147483648 + (dynamic)5), |
|
new ExprEvalTestParams("5 + 2147483648", (dynamic)5 + (dynamic)2147483648), |
|
|
|
new ExprEvalTestParams("0x2A828670572C << 1", 0x2A828670572C << 1), |
|
new ExprEvalTestParams("-0xFC84D76B0482", -0xFC84D76B0482), |
|
new ExprEvalTestParams("27 - 9223372036854775807", 27 - 9223372036854775807), |
|
new ExprEvalTestParams("9223372036854775807", 9223372036854775807), |
|
new ExprEvalTestParams("18446744073709551615", 18446744073709551615), |
|
new ExprEvalTestParams("1 << 5", 1 << 5), |
|
new ExprEvalTestParams("1 << 32", 1 << 32), |
|
new ExprEvalTestParams("1L << 32", 1L << 32), |
|
new ExprEvalTestParams("5u", 5u), |
|
new ExprEvalTestParams("5ul", 5ul), |
|
new ExprEvalTestParams("\"This is\" + \" a string expression\"", "This is" + " a string expression"), |
|
new ExprEvalTestParams("(17 - 48 + 80 * 81 - 88) + (74 + 79 - 50) - ((76 - 51 - 88 + (9 + 98 - 47)))", (17 - 48 + 80 * 81 - 88) + (74 + 79 - 50) - ((76 - 51 - 88 + (9 + 98 - 47)))), |
|
new ExprEvalTestParams("3.14159265", 3.14159265), |
|
new ExprEvalTestParams("16 - 47 * (75 / 91) + 44", 16 - 47 * (75 / 91) + 44), // Does C# truncate the same way? |
|
new ExprEvalTestParams("16 - 47 * (75d / 91d) + 44", 16 - 47 * (75d / 91d) + 44), |
|
new ExprEvalTestParams("69d / 5 - 48 - 47 / (82d - 71 + 2 + 6 / 39d) - 56", 69d / 5 - 48 - 47 / (82d - 71 + 2 + 6 / 39d) - 56), |
|
new ExprEvalTestParams("55.59m", 55.59m), |
|
new ExprEvalTestParams("55.59m + 23", 55.59m + 23), |
|
new ExprEvalTestParams("'A'", 'A'), |
|
new ExprEvalTestParams("'A'+'B'", 'A' + 'B'), |
|
new ExprEvalTestParams("(int)'A'", (int)'A'), |
|
|
|
// C++ specific sufixes not supported. C++ octal not supported. |
|
//new EETestParams("5ll", 5L), |
|
//new EETestParams("5ull", 5UL), |
|
//new EETestParams("016", 8 + 6), |
|
|
|
new ExprEvalTestParams("V1 | V2", 3, ("V1", 1), ("V2", 2)), |
|
new ExprEvalTestParams("TRUE && FALSE", false, ("TRUE", true), ("FALSE", false)), |
|
}; |
|
|
|
class ExprEvalTestParams |
|
{ |
|
public readonly string Expression; |
|
public readonly object ExpectedResult; |
|
public readonly (string Name, object Value)[] Symbols; |
|
public ExprEvalTestParams(string expression, object expectedResult, params (string Name, object Value)[] symbols) |
|
{ |
|
Expression = expression; |
|
ExpectedResult = expectedResult; |
|
Symbols = symbols; |
|
} |
|
} |
|
|
|
static IEnumerable GetExpressionEvaluatorTestCases() |
|
{ |
|
var testNumber = 100; |
|
foreach (var tc in TestExpressionEvaluatorTestCases) |
|
{ |
|
// "testNumber" is just used to cause the test runner to show the tests in the order |
|
// we've listed them which is simply a development time convenience. |
|
yield return new TestCaseData(testNumber++, tc.Expression, tc.ExpectedResult, tc.Symbols); |
|
} |
|
} |
|
|
|
[TestCaseSource(nameof(GetExpressionEvaluatorTestCases))] |
|
public void TestExpressionEvaluator(int testNumber, string expression, object expectedResult, (string SymbolName, object SymbolValue)[] symbols) |
|
{ |
|
var evaluator = symbols == null || symbols.Length == 0 |
|
? new ExpressionEvaluator() |
|
: new ExpressionEvaluator(symbols.ToDictionary(s => s.SymbolName, s => s.SymbolValue)); |
|
|
|
var result = evaluator.Evaluate(expression); |
|
Assert.AreEqual(expectedResult, result); |
|
Assert.AreEqual(expectedResult.GetType(), result.GetType()); |
|
} |
|
|
|
[Test] |
|
public void TestEnumsWithBitwiseExpressionMacroValues() |
|
{ |
|
var @enum = AstContext.GenerateEnumFromMacros("TestBitwiseShift", "TEST_BITWISE_SHIFT_(.*)"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
|
Assert.AreEqual(0x2A828670572C << 1, (long)@enum.Items[0].Value); |
|
|
|
@enum = AstContext.GenerateEnumFromMacros("TestNegativeHex", "TEST_NEGATIVE_HEX_(.*)"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(PrimitiveType.LongLong, @enum.BuiltinType.Type); |
|
Assert.AreEqual(-0xFC84D76B0482, (long)@enum.Items[0].Value); |
|
|
|
@enum = AstContext.GenerateEnumFromMacros("TestBitwiseOr", "TEST_BITWISE_OR_1"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
|
Assert.AreEqual(0x7F | 0x80, @enum.Items[0].Value); |
|
|
|
@enum = AstContext.GenerateEnumFromMacros("TestBitwiseAnd", "TEST_BITWISE_AND_(.*)"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
|
Assert.AreEqual(0x7F & 0xFF, @enum.Items[0].Value); |
|
Assert.AreEqual(0x73 & -1, @enum.Items[1].Value); |
|
Assert.AreEqual(0x42 & ~0x2, @enum.Items[2].Value); |
|
|
|
@enum = AstContext.GenerateEnumFromMacros("TestBitwiseXor", "TEST_BITWISE_XOR_(.*)"); |
|
Assert.IsNotNull(@enum); |
|
Assert.AreEqual(PrimitiveType.UChar, @enum.BuiltinType.Type); |
|
Assert.AreEqual(0x7F ^ 0x03, @enum.Items[0].Value); |
|
} |
|
|
|
[Test] |
|
public void TestUnnamedEnumSupport() |
|
{ |
|
passBuilder.AddPass(new CleanInvalidDeclNamesPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
var unnamedEnum1 = AstContext.FindEnum("Unnamed_Enum_1").Single(); |
|
var unnamedEnum2 = AstContext.FindEnum("Unnamed_Enum_2").Single(); |
|
Assert.IsNotNull(unnamedEnum1); |
|
Assert.IsNotNull(unnamedEnum2); |
|
|
|
Assert.AreEqual(2, unnamedEnum1.Items.Count); |
|
Assert.AreEqual(2, unnamedEnum2.Items.Count); |
|
|
|
Assert.AreEqual(1, unnamedEnum1.Items[0].Value); |
|
Assert.AreEqual(2, unnamedEnum1.Items[1].Value); |
|
Assert.AreEqual(3, unnamedEnum2.Items[0].Value); |
|
Assert.AreEqual(4, unnamedEnum2.Items[1].Value); |
|
} |
|
|
|
[Test, Ignore("Nameless enums are no longer uniquely named.")] |
|
public void TestUniqueNamesAcrossTranslationUnits() |
|
{ |
|
passBuilder.AddPass(new CleanInvalidDeclNamesPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
var unnamedEnum1 = AstContext.GetEnumWithMatchingItem("UnnamedEnumA1"); |
|
var unnamedEnum2 = AstContext.GetEnumWithMatchingItem("UnnamedEnumB1"); |
|
Assert.IsNotNull(unnamedEnum1); |
|
Assert.IsNotNull(unnamedEnum2); |
|
|
|
Assert.AreNotEqual(unnamedEnum1.Name, unnamedEnum2.Name); |
|
} |
|
|
|
[Test] |
|
public void TestSkippedPrivateMethod() |
|
{ |
|
AstContext.IgnoreClassMethodWithName("Foo", "toIgnore"); |
|
Assert.That(AstContext.FindClass("Foo").First().Methods.Find( |
|
m => m.Name == "toIgnore"), Is.Null); |
|
} |
|
|
|
[Test] |
|
public void TestSetPropertyAsReadOnly() |
|
{ |
|
const string className = "TestReadOnlyProperties"; |
|
passBuilder.AddPass(new FieldToPropertyPass()); |
|
passBuilder.AddPass(new GetterSetterToPropertyPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
AstContext.SetPropertyAsReadOnly(className, "readOnlyProperty"); |
|
Assert.IsFalse(AstContext.FindClass(className).First().Properties.Find( |
|
m => m.Name == "readOnlyProperty").HasSetter); |
|
AstContext.SetPropertyAsReadOnly(className, "readOnlyPropertyMethod"); |
|
Assert.IsFalse(AstContext.FindClass(className).First().Properties.Find( |
|
m => m.Name == "readOnlyPropertyMethod").HasSetter); |
|
} |
|
|
|
[Test] |
|
public void TestCheckAmbiguousFunctionsPass() |
|
{ |
|
passBuilder.AddPass(new CheckAmbiguousFunctions()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
var @class = AstContext.FindClass("TestCheckAmbiguousFunctionsPass").FirstOrDefault(); |
|
Assert.IsNotNull(@class); |
|
var overloads = @class.Methods.Where(m => m.Name == "Method"); |
|
var constMethod = overloads |
|
.FirstOrDefault(m => m.IsConst && m.Parameters.Count == 0); |
|
var nonConstMethod = overloads |
|
.FirstOrDefault(m => !m.IsConst && m.Parameters.Count == 0); |
|
Assert.IsNotNull(constMethod); |
|
Assert.IsNotNull(nonConstMethod); |
|
Assert.IsTrue(constMethod.GenerationKind == GenerationKind.None); |
|
Assert.IsTrue(nonConstMethod.GenerationKind == GenerationKind.Generate); |
|
var constMethodWithParam = overloads |
|
.FirstOrDefault(m => m.IsConst && m.Parameters.Count == 1); |
|
var nonConstMethodWithParam = overloads |
|
.FirstOrDefault(m => !m.IsConst && m.Parameters.Count == 1); |
|
Assert.IsNotNull(constMethodWithParam); |
|
Assert.IsNotNull(nonConstMethodWithParam); |
|
Assert.IsTrue(constMethodWithParam.GenerationKind == GenerationKind.None); |
|
Assert.IsTrue(nonConstMethodWithParam.GenerationKind == GenerationKind.Generate); |
|
} |
|
|
|
[Test] |
|
public void TestSetMethodAsInternal() |
|
{ |
|
var c = AstContext.Class("TestMethodAsInternal"); |
|
var method = c.Method("beInternal"); |
|
Assert.AreEqual(method.Access, AccessSpecifier.Public); |
|
passBuilder.AddPass(new CheckMacroPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
Assert.AreEqual(method.Access, AccessSpecifier.Internal); |
|
} |
|
|
|
private string TypePrinterDelegate(Type type) |
|
{ |
|
return type.Visit(new CSharpTypePrinter(Driver.Context)).Type; |
|
} |
|
|
|
[Test] |
|
public void TestAbstractOperator() |
|
{ |
|
passBuilder.AddPass(new ValidateOperatorsPass()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
var @class = AstContext.FindDecl<Class>("ClassWithAbstractOperator").First(); |
|
Assert.AreEqual(@class.Operators.First().GenerationKind, GenerationKind.None); |
|
} |
|
|
|
[Test] |
|
public void TestFlattenAnonymousTypesToFields() |
|
{ |
|
passBuilder.AddPass(new FlattenAnonymousTypesToFields()); |
|
passBuilder.RunPasses(pass => pass.VisitASTContext(AstContext)); |
|
|
|
var @class = AstContext.FindDecl<Class>("TestFlattenAnonymousTypesToFields").First(); |
|
|
|
/* TODO: Enable this test and fix the parsing bug |
|
var @public = @class.Fields.Where(f => f.Name == "Public").FirstOrDefault(); |
|
Assert.IsNotNull(@public); |
|
Assert.AreEqual(AccessSpecifier.Public, @public.Access); */ |
|
|
|
var @protected = @class.Fields.Find(f => f.Name == "Protected"); |
|
Assert.IsNotNull(@protected); |
|
Assert.AreEqual(AccessSpecifier.Protected, @protected.Access); |
|
} |
|
|
|
private PassBuilder<TranslationUnitPass> passBuilder; |
|
} |
|
}
|
|
|