set flag OurSyncCollections. !include once #1034831 // Gazelle 22 Function Include for Testing svoid test_leftArrowScript_classDefs() { temp LASMultiClassLoader cl = new(mc()); test_leftArrowScript_classDefs(cl); } svoid test_leftArrowScript_classDefs(LASMultiClassLoader cl) { var test = new TestFunctionValues(l1 leftArrowVerbose); // define a class with two fields S classPrefix = "scriptClasses."; embedded O runScript(S code) { new GazelleV_LeftArrowScriptParser parser; enableScaffolding(parser); parser.classDefPrefix(classPrefix); parser.lasClassLoader(cl); ret leftArrowVerbose(parser, code); } S classSrc = [[ class MyClass { a: String b: String } ]], src = classSrc; Class c = cast runScript(src); assertStartsWith(print(c.getName()), classPrefix + "MyClass" + "_"); // compile same source again - make sure we get the same class object assertSame(c, runScript(src)); assertEqualsVerbose("Number of fields", 2, l(getDeclaredFields_cached(c))); assertEqualsVerbose("Type of a", S.class, getField(c, "a").getType()); assertEqualsVerbose("Type of b", S.class, getField(c, "b").getType()); // Make sure a change in the class definition gives us a new class name Class c2 = cast runScript([[ class MyClass { a: String c: String } ]]); print(className(c2)); assertNotSame(c, c2); // Make sure a change in the methods also gives us a new class name S classSrc2 = [[ class MyClass { def bla { "x" } } ]]; c = (Class) runScript(classSrc2); assertSame(c, runScript(classSrc2)); c2 = (Class) runScript([[ class MyClass { def bla { "y" } } ]]); assertNotSame(c, c2); // Now let's try and use a script-defined class src = classSrc + [[ x <- new MyClass y <- new MyClass x a <- "yo" y a <- "oy" x a ]]; assertEqualsVerbose("yo", runScript(src)); // Using the class in a function src = classSrc + [[ def bla { x <- new MyClass x a <- "yo" x a } bla ]]; assertEqualsVerbose("yo", runScript(src)); // Now for defining some methods (yay!) src = [[ class MyClass2 { def method1 { "I'm here" } def method2 a { reversed a } } x <- new MyClass2 pair (x method1) (x method2 "sey") ]]; assertEqualsVerbose(pair("I'm here", "yes"), runScript(src)); // accessing instance fields src = [[ class MyClass3 { a: String def getA { this a } // requiring the this keyword for now def setA a { this a <- a } def aLength { (this a) length } } x <- new MyClass3 x setA "abc" assertEquals (x aLength) 3 x getA ]]; assertEqualsVerbose("abc", runScript(src)); // fully qualified type classSrc = [[ class MyClass4 { a: java.util.List } ]]; c = (Class) runScript(classSrc); assertEqualsVerbose(fieldType(c, "a"), L.class); // type with type parameter classSrc = [[ class MyClass5 { a: L } ]]; c = (Class) runScript(classSrc); assertEqualsVerbose("Raw type of L field", fieldType(c, "a"), L.class); assertEqualsVerbose("Generic type of L field", genericFieldType(c, "a"), new ParameterizedTypeImpl(null, L, S)); // primitive type classSrc = [[ class MyClass6 { x: int } ]]; c = (Class) runScript(classSrc); assertEqualsVerbose(fieldType(c, "x"), int.class); classSrc = [[ class ToString { def toString : S { "It's me, George!" } } new ToString ]]; assertEqualsVerbose("It's me, George!", str(runScript(classSrc))); // primitive array classSrc = [[ class MyClass7 { x: int[] } ]]; c = (Class) runScript(classSrc); assertEqualsVerbose(fieldType(c, "x"), int[].class); // define class implementing interface classSrc = [[ class Bla is IF0 { def get { "hello" } } new Bla ]]; IF0 o = cast runScript(classSrc); assertEqualsVerbose("hello", o!); // call function on class defined inline assertEqualsVerbose(Class.class, runScript([[ _getClass2 class A { } ]])); // constructor (dev.) assertEqualsVerbose(5, runScript([[ class MyClass8 { x: int ctor { this x <- 5 } } new MyClass8, x ]]); }