aoqi@0: /* aoqi@0: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 8005085 8005681 8008769 8010015 aoqi@0: * @summary Check (repeating)type annotations on lambda usage. aoqi@0: * @run main CombinationsTargetTest3 aoqi@0: */ aoqi@0: aoqi@0: import com.sun.tools.classfile.*; aoqi@0: import java.io.File; aoqi@0: import java.util.Vector; aoqi@0: aoqi@0: public class CombinationsTargetTest3 extends ClassfileTestHelper { aoqi@0: aoqi@0: // Helps identify test case in event of failure. aoqi@0: int testcount = 0; aoqi@0: aoqi@0: // Known failure cases due to open bugs. aoqi@0: Vector skippedTests = new Vector<>(); aoqi@0: void printSkips() { aoqi@0: if(!skippedTests.isEmpty()) { aoqi@0: println(skippedTests.size() + " tests were skipped:"); aoqi@0: for(String t : skippedTests) aoqi@0: println(" " + t); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Test case descriptions and expected annotation counts. aoqi@0: enum srce { aoqi@0: src1("type annotations on lambda expression as method arg.",4,0), aoqi@0: src2("type annotations on new in single line lambda expression",2,0), aoqi@0: src3("type annotations in lambda expression code block",4,0), aoqi@0: src4("type annotations in code block with recursion,cast",2,0), aoqi@0: src5("type annotations in lambda expression code block",4,0), aoqi@0: src6("type annotations on type parm in method reference",4,0), aoqi@0: src7("type annotations on inner class field of lambda expression",2,2), aoqi@0: src8("type annotations in inner class of lambda expression",4,2), aoqi@0: src9("type annotations on static method of interface",4,2); aoqi@0: aoqi@0: String description; aoqi@0: // Expected annotation counts are same for Vis or Invis, but which one aoqi@0: // depends on retention type. aoqi@0: Integer[] exp = { 0, 0 }; aoqi@0: aoqi@0: // If class to test is inner class, this may be set in SourceString() aoqi@0: String innerClassname = null ; aoqi@0: aoqi@0: // If class to test is not main or inner class; set in sourceString() aoqi@0: String altClassName = null; aoqi@0: aoqi@0: srce(String desc, int e1, int e2) { aoqi@0: description = this + ": " +desc; aoqi@0: exp[0]=e1; aoqi@0: exp[1]=e2; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Check for RuntimeInvisible or RuntimeVisible annotations. aoqi@0: String[] RType={"CLASS", "RUNTIME"}; aoqi@0: aoqi@0: // This can be a compile only test. aoqi@0: static boolean compileonly=false; aoqi@0: aoqi@0: // Collect failure for end of test report() aoqi@0: Vector vFailures = new Vector<>(); aoqi@0: aoqi@0: // pass/fail determined after all tests have run. aoqi@0: void report() { aoqi@0: if(vFailures.isEmpty()) { aoqi@0: printSkips(); aoqi@0: println("PASS"); aoqi@0: } else { aoqi@0: System.err.println("FAILED: There were failures:"); aoqi@0: for(String f : vFailures) aoqi@0: System.err.println(f); aoqi@0: throw new RuntimeException("There were failures. See test log."); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static void main(String[] args) throws Exception { aoqi@0: if(args.length>0 && args[0].compareTo("compileonly")==0) aoqi@0: compileonly=true; aoqi@0: new CombinationsTargetTest3().run(); aoqi@0: } aoqi@0: aoqi@0: void run() throws Exception { aoqi@0: // Determines which repeat and order in source(ABMix). aoqi@0: Boolean As= false, BDs=true, ABMix=false; aoqi@0: int testrun=0; aoqi@0: // A repeats and/or B/D repeats, ABMix for order of As and Bs. aoqi@0: Boolean [][] bRepeat = new Boolean[][]{{false,false,false}, //no repeats aoqi@0: {true,false,false}, //repeat @A aoqi@0: {false,true,false}, //repeat @B aoqi@0: {true,true,false}, //repeat both aoqi@0: {false,false,true} //repeat mix aoqi@0: }; aoqi@0: // Added ElementType's. All set; not permuted (so far) for this test aoqi@0: String et = "TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE"; aoqi@0: aoqi@0: // test loop aoqi@0: for(Boolean[] bCombo : bRepeat) { aoqi@0: As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2]; aoqi@0: for(srce src : srce.values()) aoqi@0: for( String rtype : RType ) { aoqi@0: switch( rtype ) { aoqi@0: case "RUNTIME": aoqi@0: test(0,src.exp[0],0,src.exp[1],As, BDs, ABMix, aoqi@0: "RUNTIME", et, ++testrun, src); aoqi@0: break; aoqi@0: case "CLASS": aoqi@0: test(src.exp[0],0,src.exp[1],0,As, BDs, ABMix, aoqi@0: "CLASS", et, ++testrun, src); aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: report(); aoqi@0: } aoqi@0: aoqi@0: // Filter out skipped cases, compile, pass class file to test method, aoqi@0: // count annotations and asses results. aoqi@0: public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats, aoqi@0: Boolean BDrepeats, Boolean ABmix, String rtn, String et2, aoqi@0: Integer N, srce source) throws Exception { aoqi@0: ++testcount; aoqi@0: expected_tvisibles = tvis; aoqi@0: expected_tinvisibles = tinv; aoqi@0: expected_visibles = vis; aoqi@0: expected_invisibles = inv; aoqi@0: File testFile = null; aoqi@0: String tname="Test" + N.toString(); aoqi@0: String testDef = "Test " + testcount + " parameters: tinv=" + tinv + aoqi@0: ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis + aoqi@0: ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats + aoqi@0: ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " + aoqi@0: et2 + ", src=" + source; aoqi@0: aoqi@0: // Skip failing cases with bug ID's aoqi@0: if ((source.equals(srce.src2) || source.equals(srce.src4) || aoqi@0: source.equals(srce.src5)) && aoqi@0: (ABmix || (Arepeats && BDrepeats))) { aoqi@0: skippedTests.add(testDef + aoqi@0: "\n--8005681 repeated type-annotations on new/cast/array in" + aoqi@0: " inner class in lambda expression."); aoqi@0: return; aoqi@0: }//8008769 Repeated type-annotations on type parm of local variable aoqi@0: else if (source.equals(srce.src6) && aoqi@0: (ABmix || (Arepeats && BDrepeats))) { aoqi@0: skippedTests.add(testDef + "\n--8008769 Repeated " + aoqi@0: "type-annotations on type parm of local variable"); aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: println(testDef); aoqi@0: // Create test source and File. aoqi@0: String sourceString = sourceString(tname, rtn, et2, Arepeats, aoqi@0: BDrepeats, ABmix, source); aoqi@0: testFile = writeTestFile(tname+".java", sourceString); aoqi@0: // Compile test source and read classfile. aoqi@0: File classFile = null; aoqi@0: try { aoqi@0: classFile = compile(testFile); aoqi@0: System.out.println("pass compile: " + tname + ".java"); aoqi@0: } catch (Error err) { aoqi@0: System.err.println("fail compile. Source:\n" + sourceString); aoqi@0: throw err; aoqi@0: } aoqi@0: if(!compileonly) { aoqi@0: //check if innerClassname is set aoqi@0: String classdir = classFile.getAbsolutePath(); aoqi@0: if(source.innerClassname != null) { aoqi@0: StringBuffer sb = new StringBuffer(classdir); aoqi@0: classFile=new File(sb.insert(sb.lastIndexOf(".class"), aoqi@0: source.innerClassname).toString()); aoqi@0: source.innerClassname=null; aoqi@0: } else if (source.altClassName != null) { aoqi@0: classdir = classdir.substring(0,classdir.lastIndexOf("Test")); aoqi@0: classFile=new File(classdir.concat(source.altClassName)); aoqi@0: source.innerClassname=null; aoqi@0: } aoqi@0: ClassFile cf = ClassFile.read(classFile); aoqi@0: aoqi@0: println("Testing classfile: " + cf.getName()); aoqi@0: //Test class,fields and method counts. aoqi@0: test(cf); aoqi@0: aoqi@0: for (Field f : cf.fields) { aoqi@0: test(cf, f); aoqi@0: test(cf, f, true); aoqi@0: } aoqi@0: for (Method m: cf.methods) { aoqi@0: test(cf, m); aoqi@0: test(cf, m, true); aoqi@0: } aoqi@0: aoqi@0: countAnnotations(); // sets errors=0 before counting. aoqi@0: if (errors > 0) { aoqi@0: System.err.println( testDef ); aoqi@0: System.err.println( "Source:\n" + sourceString ); aoqi@0: vFailures.add(testDef); aoqi@0: } aoqi@0: } aoqi@0: if(errors==0) println("Pass"); println(""); aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Source definitions for test cases. aoqi@0: * To add a test: aoqi@0: * Add enum to srce(near top of file) with expected annotation counts. aoqi@0: * Add source defintion below. aoqi@0: */ aoqi@0: String sourceString(String testname, String retentn, String annot2, aoqi@0: Boolean Arepeats, Boolean BDrepeats, Boolean ABmix, aoqi@0: srce src) { aoqi@0: aoqi@0: String As = "@A", Bs = "@B", Ds = "@D"; aoqi@0: if(Arepeats) As = "@A @A"; aoqi@0: if(BDrepeats) { aoqi@0: Bs = "@B @B"; aoqi@0: Ds = "@D @D"; aoqi@0: } aoqi@0: if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; } aoqi@0: aoqi@0: // Source to check for TYPE_USE and TYPE_PARAMETER annotations. aoqi@0: // Source base (annotations) is same for all test cases. aoqi@0: String source = new String(); aoqi@0: String imports = new String("import java.lang.annotation.*; \n" + aoqi@0: "import static java.lang.annotation.RetentionPolicy.*; \n" + aoqi@0: "import static java.lang.annotation.ElementType.*; \n" + aoqi@0: "import java.util.List; \n" + aoqi@0: "import java.util.ArrayList;\n\n"); aoqi@0: aoqi@0: String sourceBase = new String( aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( AC.class ) @interface A { }\n" + aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface AC { A[] value(); } \n" + aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( BC.class ) @interface B { }\n" + aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface BC { B[] value(); } \n" + aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @Repeatable(DC.class) @interface D { }\n" + aoqi@0: "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @interface DC { D[] value(); }"); aoqi@0: aoqi@0: // Test case sources with sample generated source aoqi@0: switch(src) { aoqi@0: case src1: //(repeating) type annotations on lambda expressions. aoqi@0: /* aoqi@0: * class Test1 { aoqi@0: * Test1(){} aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * void meth( MapFun mf ) { aoqi@0: * assert( mf.m("four") == 4); aoqi@0: * } aoqi@0: * void test(Integer i) { aoqi@0: * // lambda expression as method arg aoqi@0: * meth( (@A @B String s) -> { @A @B Integer len = s.length(); return len; } ); aoqi@0: * }} aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class " + testname + " {\n" + aoqi@0: " " + testname +"(){} \n" + aoqi@0: " interface MapFun { R m( T n); }\n\n" + aoqi@0: " void meth( MapFun mf ) {\n" + aoqi@0: " assert( mf.m(\"four\") == 4);\n" + aoqi@0: " }\n\n" + aoqi@0: " void test(Integer i) {\n" + aoqi@0: " // lambda expression as method arg\n" + aoqi@0: " meth( (_As_ _Bs_ String s) -> { _As_ _Bs_ Integer len = s.length(); return len; } );\n" + aoqi@0: "}}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: break; aoqi@0: case src2: //(repeating) type annotations on new in single line lambda expression. aoqi@0: /* aoqi@0: * //case2: (repeating) type annotations on new in single lambda expressions. aoqi@0: * class Test2{ aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * MapFun its; aoqi@0: * void test(Integer i) { aoqi@0: * its = a -> "~"+new @A @B Integer(a).toString()+"~"; aoqi@0: * System.out.println("in: " + i + " out: " + its.m(i)); aoqi@0: * }} aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class " + testname + "{\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun its;\n" + aoqi@0: " void test(Integer i) {\n" + aoqi@0: " its = a -> \"~\"+new _As_ _Bs_ Integer(a).toString()+\"~\";\n" + aoqi@0: " System.out.println(\"in: \" + i + \" out: \" + its.m(i));\n" + aoqi@0: " }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: break; aoqi@0: case src3: //(repeating) type annotations in lambda expression code block. aoqi@0: /* aoqi@0: * class Test183{ aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * MapFun, String> iLs; aoqi@0: * void testm(Integer i) { aoqi@0: * iLs = l -> { @A @B @A @B String ret = new String(); aoqi@0: * for( @A @B @A @B Integer i2 : l) aoqi@0: * ret=ret.concat(i2.toString() + " "); aoqi@0: * return ret; }; aoqi@0: * List li = new ArrayList<>(); aoqi@0: * for(int j=0; j { R m( T n); }\n" + aoqi@0: " MapFun, String> iLs;\n" + aoqi@0: " void testm(Integer i) {\n" + aoqi@0: " iLs = l -> { _As_ _Bs_ String ret = new String();\n" + aoqi@0: " for( _As_ _Bs_ Integer i2 : l)\n" + aoqi@0: " ret=ret.concat(i2.toString() + \" \");\n" + aoqi@0: " return ret; };\n" + aoqi@0: " List li = new ArrayList<>();\n" + aoqi@0: " for(int j=0; j { R m( T n); } aoqi@0: * MapFun nf; aoqi@0: * void testm(Integer i) { aoqi@0: * nf = j -> { return j == 1 ? 1.0 : (@A @B @A @B Double)(nf.m(j-1) * j); }; aoqi@0: * System.out.println( "nf.m(" + i + "): " + nf.m(i)); aoqi@0: * } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun nf;\n" + aoqi@0: " void testm(Integer i) {\n" + aoqi@0: " nf = j -> { return j == 1 ? 1.0 : (_As_ _Bs_ Double)(nf.m(j-1) * j); };\n" + aoqi@0: " System.out.println( \"nf.m(\" + i + \"): \" + nf.m(i));\n" + aoqi@0: " }\n" + aoqi@0: " public static void main(String... args) {new " + testname + "().testm(5); }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: break; aoqi@0: case src5: //(repeating) type annotations in lambda expression code block. aoqi@0: /* aoqi@0: * class Test180 { aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * MapFun> iLi; aoqi@0: * void test(Integer i) { aoqi@0: * // type parameter use. aoqi@0: * iLi = n -> { List<@A @B @A @B Integer> LI = new ArrayList<@A @B @A @B Integer>(n); aoqi@0: * for(int nn = n; nn >=0; nn--) LI.add(nn); aoqi@0: * return LI; }; aoqi@0: * List li = iLi.m(i); aoqi@0: * for(Integer k : li) System.out.print(k); aoqi@0: * } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun> iLi;\n" + aoqi@0: " void test(Integer i) {\n" + aoqi@0: " // type parameter use.\n" + aoqi@0: " iLi = n -> { List<_As_ _Bs_ Integer> LI = new ArrayList<_As_ _Bs_ Integer>(n);\n" + aoqi@0: " for(int nn = n; nn >=0; nn--) LI.add(nn);\n" + aoqi@0: " return LI; };\n" + aoqi@0: " List li = iLi.m(i);\n" + aoqi@0: " for(Integer k : li) System.out.print(k);\n" + aoqi@0: "}\n" + aoqi@0: " public static void main(String... args) {new " + testname + "().test(5); }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) + aoqi@0: "\n"; aoqi@0: break; aoqi@0: case src6: //(repeating) type annotations on type parm in method reference. aoqi@0: /* aoqi@0: * class Test240{ aoqi@0: * interface PrintString { void print(String s); } aoqi@0: * public void printArray(Object[] oa, PrintString ps) { aoqi@0: * for(Object o : oa ) ps.print(o.toString()); aoqi@0: * } aoqi@0: * public void test() { aoqi@0: * Integer[] intarray = {1,2,3,4,5}; aoqi@0: * printArray(intarray, @A @B @A @B TPrint::<@A @B @A @B String>print); aoqi@0: * } aoqi@0: * } aoqi@0: * class TPrint { aoqi@0: * public static void print(T t) { System.out.println( t.toString()); } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface PrintString { void print(String s); }\n" + aoqi@0: " public void printArray(Object[] oa, PrintString ps) {\n" + aoqi@0: " for(Object o : oa ) ps.print(o.toString());\n" + aoqi@0: " }\n" + aoqi@0: " public void test() {\n" + aoqi@0: " Integer[] intarray = {1,2,3,4,5};\n" + aoqi@0: " printArray(intarray, _As_ _Bs_ TPrint::<_As_ _Bs_ String>print);\n" + aoqi@0: " }\n" + aoqi@0: " public static void main(String... args) {new " + testname + "().test(); }\n" + aoqi@0: "}\n\n" + aoqi@0: "class TPrint {\n" + aoqi@0: " public static void print(T t) { System.out.println( t.toString()); }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: break; aoqi@0: case src7: //(repeating)type annotations in inner class of lambda expression. aoqi@0: /* aoqi@0: * class Test2{ aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * MapFun,String> cs; aoqi@0: * void test() { aoqi@0: * cs = c -> { aoqi@0: * class innerClass { aoqi@0: * @A @B Class icc = null; aoqi@0: * String getString() { return icc.toString(); } aoqi@0: * } aoqi@0: * return new innerClass().getString(); aoqi@0: * }; aoqi@0: * System.out.println("cs.m : " + cs.m(Integer.class)); aoqi@0: * } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun,String> cs;\n" + aoqi@0: " void test() {\n" + aoqi@0: " cs = c -> {\n" + aoqi@0: " class innerClass {\n" + aoqi@0: " _As_ _Bs_ Class icc = null;\n" + aoqi@0: " innerClass(Class _c) { icc = _c; }\n" + aoqi@0: " String getString() { return icc.toString(); }\n" + aoqi@0: " }\n" + aoqi@0: " return new innerClass(c).getString();\n" + aoqi@0: " };\n" + aoqi@0: " System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" + aoqi@0: " }\n" + aoqi@0: "\n" + aoqi@0: " public static void main(String... args) {new " + testname + "().test(); }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: src.innerClassname="$1innerClass"; aoqi@0: break; aoqi@0: case src8: //(repeating)type annotations in inner class of lambda expression. aoqi@0: /* aoqi@0: * class Test2{ aoqi@0: * interface MapFun { R m( T n); } aoqi@0: * MapFun,String> cs; aoqi@0: * void test() { aoqi@0: * cs = c -> { aoqi@0: * class innerClass { aoqi@0: * Class icc; aoqi@0: * innerClass(@A @B Class _c) { icc = _c; } aoqi@0: * @A @B String getString() { return icc.toString(); } aoqi@0: * } aoqi@0: * return new innerClass(c).getString(); aoqi@0: * }; aoqi@0: * System.out.println("cs.m : " + cs.m(Integer.class)); aoqi@0: * } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun,String> cs;\n" + aoqi@0: " void test() {\n" + aoqi@0: " cs = c -> {\n" + aoqi@0: " class innerClass {\n" + aoqi@0: " Class icc;\n" + aoqi@0: " innerClass(_As_ _Bs_ Class _c) { icc = _c; }\n" + aoqi@0: " _As_ _Bs_ String getString() { return icc.toString(); }\n" + aoqi@0: " }\n" + aoqi@0: " return new innerClass(c).getString();\n" + aoqi@0: " };\n" + aoqi@0: " System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" + aoqi@0: " }\n" + aoqi@0: "\n" + aoqi@0: " public static void main(String... args) {new " + testname + "().test(); }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: src.innerClassname="$1innerClass"; aoqi@0: break; aoqi@0: case src9: //(repeating)type annotations on static method of interface aoqi@0: /* aoqi@0: * class Test90{ aoqi@0: * interface I { aoqi@0: * static @A @B @A @B String m() { @A @B @A @B String ret = "I.m"; return ret; } aoqi@0: * } aoqi@0: * } aoqi@0: */ aoqi@0: source = new String( source + aoqi@0: "// " + src.description + "\n" + aoqi@0: "class "+ testname + "{\n" + aoqi@0: " interface I { \n" + aoqi@0: " static _As_ _Bs_ String m() { _As_ _Bs_ String ret = \"I.m\"; return ret; }\n" + aoqi@0: " }\n" + aoqi@0: "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + aoqi@0: "\n"; aoqi@0: src.innerClassname="$I"; aoqi@0: break; aoqi@0: } aoqi@0: return imports + source; aoqi@0: } aoqi@0: }