test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest3.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     1 /*
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 8005085 8005681 8008769 8010015
    27  * @summary Check (repeating)type annotations on lambda usage.
    28  * @run main CombinationsTargetTest3
    29  */
    31 import com.sun.tools.classfile.*;
    32 import java.io.File;
    33 import java.util.Vector;
    35 public class CombinationsTargetTest3 extends ClassfileTestHelper {
    37     // Helps identify test case in event of failure.
    38     int testcount = 0;
    40     // Known failure cases due to open bugs.
    41     Vector<String> skippedTests = new Vector<>();
    42     void printSkips() {
    43         if(!skippedTests.isEmpty()) {
    44             println(skippedTests.size() + " tests were skipped:");
    45             for(String t : skippedTests)
    46                 println("    " + t);
    47         }
    48     }
    50     // Test case descriptions and expected annotation counts.
    51     enum srce  {
    52         src1("type annotations on lambda expression as method arg.",4,0),
    53         src2("type annotations on new in single line lambda expression",2,0),
    54         src3("type annotations in lambda expression code block",4,0),
    55         src4("type annotations in code block with recursion,cast",2,0),
    56         src5("type annotations in lambda expression code block",4,0),
    57         src6("type annotations on type parm in method reference",4,0),
    58         src7("type annotations on inner class field of lambda expression",2,2),
    59         src8("type annotations in inner class of lambda expression",4,2),
    60         src9("type annotations on static method of interface",4,2);
    62         String description;
    63         // Expected annotation counts are same for Vis or Invis, but which one
    64         // depends on retention type.
    65         Integer[] exp = { 0, 0 };
    67         // If class to test is inner class, this may be set in SourceString()
    68         String innerClassname = null ;
    70         // If class to test is not main or inner class; set in sourceString()
    71         String altClassName = null;
    73         srce(String desc, int e1, int e2) {
    74             description = this + ": " +desc;
    75             exp[0]=e1;
    76             exp[1]=e2;
    77         }
    78     }
    80     // Check for RuntimeInvisible or RuntimeVisible annotations.
    81     String[] RType={"CLASS", "RUNTIME"};
    83     // This can be a compile only test.
    84     static boolean compileonly=false;
    86     // Collect failure for end of test report()
    87     Vector<String> vFailures = new Vector<>();
    89     // pass/fail determined after all tests have run.
    90     void report() {
    91         if(vFailures.isEmpty()) {
    92             printSkips();
    93             println("PASS");
    94         } else {
    95            System.err.println("FAILED: There were failures:");
    96            for(String f : vFailures)
    97                System.err.println(f);
    98            throw new RuntimeException("There were failures. See test log.");
    99         }
   100     }
   102     public static void main(String[] args) throws Exception {
   103         if(args.length>0 && args[0].compareTo("compileonly")==0)
   104             compileonly=true;
   105         new CombinationsTargetTest3().run();
   106     }
   108     void run() throws Exception {
   109         // Determines which repeat and order in source(ABMix).
   110         Boolean As= false, BDs=true, ABMix=false;
   111         int testrun=0;
   112         // A repeats and/or B/D repeats, ABMix for order of As and Bs.
   113         Boolean [][] bRepeat = new Boolean[][]{{false,false,false}, //no repeats
   114                                                {true,false,false}, //repeat @A
   115                                                {false,true,false}, //repeat @B
   116                                                {true,true,false},  //repeat both
   117                                                {false,false,true}  //repeat mix
   118         };
   119         // Added ElementType's. All set; not permuted (so far) for this test
   120         String et = "TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE";
   122         // test loop
   123         for(Boolean[] bCombo : bRepeat) {
   124             As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
   125             for(srce src : srce.values())
   126                 for( String rtype : RType ) {
   127                    switch( rtype ) {
   128                        case "RUNTIME":
   129                            test(0,src.exp[0],0,src.exp[1],As, BDs, ABMix,
   130                                 "RUNTIME", et, ++testrun, src);
   131                            break;
   132                        case "CLASS":
   133                            test(src.exp[0],0,src.exp[1],0,As, BDs, ABMix,
   134                                 "CLASS", et, ++testrun, src);
   135                            break;
   136                 }
   137             }
   138         }
   139         report();
   140     }
   142     // Filter out skipped cases, compile, pass class file to test method,
   143     // count annotations and asses results.
   144     public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
   145                      Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
   146                      Integer N, srce source) throws Exception {
   147         ++testcount;
   148         expected_tvisibles = tvis;
   149         expected_tinvisibles = tinv;
   150         expected_visibles = vis;
   151         expected_invisibles = inv;
   152         File testFile = null;
   153         String tname="Test" + N.toString();
   154         String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
   155                 ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
   156                 ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
   157                 ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
   158                 et2 + ", src=" + source;
   160         // Skip failing cases with bug ID's
   161         if ((source.equals(srce.src2) || source.equals(srce.src4) ||
   162             source.equals(srce.src5)) &&
   163             (ABmix || (Arepeats && BDrepeats))) {
   164                 skippedTests.add(testDef +
   165                   "\n--8005681 repeated type-annotations on new/cast/array in" +
   166                   " inner class in lambda expression.");
   167             return;
   168         }//8008769 Repeated type-annotations on type parm of local variable
   169          else if (source.equals(srce.src6) &&
   170                    (ABmix || (Arepeats && BDrepeats))) {
   171             skippedTests.add(testDef +  "\n--8008769 Repeated " +
   172                              "type-annotations on type parm of local variable");
   173             return;
   174         }
   176         println(testDef);
   177         // Create test source and File.
   178         String sourceString = sourceString(tname, rtn, et2, Arepeats,
   179                                            BDrepeats, ABmix, source);
   180         testFile = writeTestFile(tname+".java", sourceString);
   181         // Compile test source and read classfile.
   182         File classFile = null;
   183         try {
   184             classFile = compile(testFile);
   185             System.out.println("pass compile: " + tname + ".java");
   186         } catch (Error err) {
   187             System.err.println("fail compile. Source:\n" + sourceString);
   188             throw err;
   189         }
   190         if(!compileonly) {
   191             //check if innerClassname is set
   192             String classdir = classFile.getAbsolutePath();
   193             if(source.innerClassname != null) {
   194                 StringBuffer sb = new StringBuffer(classdir);
   195                 classFile=new File(sb.insert(sb.lastIndexOf(".class"),
   196                                    source.innerClassname).toString());
   197                 source.innerClassname=null;
   198             } else if (source.altClassName != null) {
   199                 classdir = classdir.substring(0,classdir.lastIndexOf("Test"));
   200                 classFile=new File(classdir.concat(source.altClassName));
   201                 source.innerClassname=null;
   202             }
   203             ClassFile cf = ClassFile.read(classFile);
   205             println("Testing classfile: " + cf.getName());
   206             //Test class,fields and method counts.
   207             test(cf);
   209             for (Field f : cf.fields) {
   210                 test(cf, f);
   211                 test(cf, f, true);
   212             }
   213             for (Method m: cf.methods) {
   214                 test(cf, m);
   215                 test(cf, m, true);
   216             }
   218             countAnnotations(); // sets errors=0 before counting.
   219             if (errors > 0) {
   220                 System.err.println( testDef );
   221                 System.err.println( "Source:\n" + sourceString );
   222                 vFailures.add(testDef);
   223             }
   224         }
   225         if(errors==0) println("Pass"); println("");
   226     }
   228     /*
   229      * Source definitions for test cases.
   230      * To add a test:
   231      *   Add enum to srce(near top of file) with expected annotation counts.
   232      *   Add source defintion below.
   233      */
   234     String sourceString(String testname, String retentn, String annot2,
   235                         Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
   236                         srce src) {
   238         String As = "@A", Bs = "@B", Ds = "@D";
   239         if(Arepeats) As = "@A @A";
   240         if(BDrepeats) {
   241             Bs = "@B @B";
   242             Ds = "@D @D";
   243         }
   244         if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
   246         // Source to check for TYPE_USE and TYPE_PARAMETER annotations.
   247         // Source base (annotations) is same for all test cases.
   248         String source = new String();
   249         String imports = new String("import java.lang.annotation.*; \n" +
   250             "import static java.lang.annotation.RetentionPolicy.*; \n" +
   251             "import static java.lang.annotation.ElementType.*; \n" +
   252             "import java.util.List; \n" +
   253             "import java.util.ArrayList;\n\n");
   255             String sourceBase = new String(
   256             "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( AC.class ) @interface A { }\n" +
   257             "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface AC { A[] value(); } \n" +
   258             "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( BC.class ) @interface B { }\n" +
   259             "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface BC { B[] value(); } \n" +
   260             "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @Repeatable(DC.class) @interface D { }\n" +
   261             "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @interface DC { D[] value(); }");
   263         // Test case sources with sample generated source
   264         switch(src) {
   265             case src1: //(repeating) type annotations on lambda expressions.
   266                 /*
   267                  * class Test1 {
   268                  * Test1(){}
   269                  * interface MapFun<T,R> {  R m( T n); }
   270                  * void meth( MapFun<String,Integer> mf ) {
   271                  *     assert( mf.m("four") == 4);
   272                  * }
   273                  * void test(Integer i) {
   274                  *     // lambda expression as method arg
   275                  *     meth( (@A @B String s) -> { @A @B Integer len = s.length(); return len; } );
   276                  * }}
   277                  */
   278                 source = new String( source +
   279                 "// " + src.description + "\n" +
   280                 "class " + testname + " {\n" +
   281                 "  " + testname +"(){} \n" +
   282                 "  interface MapFun<T,R> {  R m( T n); }\n\n" +
   283                 "  void meth( MapFun<String,Integer> mf ) {\n" +
   284                 "    assert( mf.m(\"four\") == 4);\n" +
   285                 "  }\n\n" +
   286                 "  void test(Integer i) {\n" +
   287                 "    // lambda expression as method arg\n" +
   288                 "    meth( (_As_ _Bs_ String s) -> { _As_ _Bs_ Integer len = s.length(); return len; } );\n" +
   289                 "}}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   290                 "\n";
   291                 break;
   292             case src2: //(repeating) type annotations on new in single line lambda expression.
   293                 /*
   294                  * //case2: (repeating) type annotations on new in single lambda expressions.
   295                  * class Test2{
   296                  *   interface MapFun<T, R> {  R m( T n); }
   297                  *   MapFun<Integer, String> its;
   298                  * void test(Integer i) {
   299                  *   its = a -> "~"+new @A @B Integer(a).toString()+"~";
   300                  *   System.out.println("in: " + i + " out: " + its.m(i));
   301                  * }}
   302                  */
   303                 source = new String( source +
   304                 "// " + src.description + "\n" +
   305                 "class " + testname + "{\n" +
   306                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   307                 "  MapFun<Integer, String> its;\n" +
   308                 "  void test(Integer i) {\n" +
   309                 "    its = a -> \"~\"+new _As_ _Bs_ Integer(a).toString()+\"~\";\n" +
   310                 "    System.out.println(\"in: \" + i + \" out: \" + its.m(i));\n" +
   311                 "  }\n" +
   312                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   313                 "\n";
   314             break;
   315             case src3: //(repeating) type annotations in lambda expression code block.
   316                 /*
   317                  * class Test183{
   318                  *   interface MapFun<T, R> {  R m( T n); }
   319                  *   MapFun<List<Integer>, String> iLs;
   320                  *   void testm(Integer i) {
   321                  *       iLs = l -> { @A @B @A @B String ret = new String();
   322                  *                    for( @A @B @A @B Integer i2 : l)
   323                  *                        ret=ret.concat(i2.toString() + " ");
   324                  *                    return ret; };
   325                  *   List<Integer> li = new ArrayList<>();
   326                  *   for(int j=0; j<i; j++) li.add(j);
   327                  *   System.out.println(iLs.m(li) );
   328                  * }}
   329                  */
   330                 source = new String( source +
   331                 "// " + src.description + "\n" +
   332                 "class "+ testname + "{\n" +
   333                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   334                 "  MapFun<List<Integer>, String> iLs;\n" +
   335                 "  void testm(Integer i) {\n" +
   336                 "    iLs = l -> { _As_ _Bs_ String ret = new String();\n" +
   337                 "                 for( _As_ _Bs_ Integer i2 : l)\n" +
   338                 "                   ret=ret.concat(i2.toString() + \" \");\n" +
   339                 "                 return ret; };\n" +
   340                 "  List<Integer> li = new ArrayList<>();\n" +
   341                 "  for(int j=0; j<i; j++) li.add(j);\n" +
   342                 "  System.out.println(iLs.m(li) );\n" +
   343                 "}\n" +
   344                 "\n" +
   345                 "    public static void main(String... args) {new " + testname + "().testm(5); }\n" +
   346                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   347                 "\n";
   348             break;
   349             case src4: //(repeating) type annotations in code block with recursion,cast
   350                 /*
   351                  * class Test194{
   352                  *   interface MapFun<T, R> {  R m( T n); }
   353                  *   MapFun<Integer, Double>  nf;
   354                  *   void testm(Integer i) {
   355                  *       nf = j -> { return j == 1 ? 1.0 : (@A @B @A @B  Double)(nf.m(j-1) * j); };
   356                  *       System.out.println( "nf.m(" + i + "): " + nf.m(i));
   357                  *   }
   358                  * }
   359                  */
   360                 source = new String( source +
   361                 "// " + src.description + "\n" +
   362                 "class "+ testname + "{\n" +
   363                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   364                 "  MapFun<Integer, Double>  nf;\n" +
   365                 "  void testm(Integer i) {\n" +
   366                 "    nf = j -> { return j == 1 ? 1.0 : (_As_ _Bs_  Double)(nf.m(j-1) * j); };\n" +
   367                 "    System.out.println( \"nf.m(\" + i + \"): \" + nf.m(i));\n" +
   368                 "  }\n" +
   369                 "  public static void main(String... args) {new " + testname + "().testm(5); }\n" +
   370                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   371                 "\n";
   372             break;
   373             case src5: //(repeating) type annotations in lambda expression code block.
   374                    /*
   375                     * class Test180 {
   376                     *   interface MapFun<T, R> {  R m( T n); }
   377                     *   MapFun<Integer,List<Integer>> iLi;
   378                     *   void test(Integer i) {
   379                     *     // type parameter use.
   380                     *     iLi = n -> { List<@A @B @A @B Integer> LI = new ArrayList<@A @B @A @B Integer>(n);
   381                     *                  for(int nn = n; nn >=0; nn--) LI.add(nn);
   382                     *                  return LI; };
   383                     *     List<Integer> li = iLi.m(i);
   384                     *     for(Integer k : li) System.out.print(k);
   385                     *   }
   386                     * }
   387                     */
   388                 source = new String( source +
   389                 "// " + src.description + "\n" +
   390                 "class "+ testname + "{\n" +
   391                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   392                 "  MapFun<Integer,List<Integer>> iLi;\n" +
   393                 "  void test(Integer i) {\n" +
   394                 "    // type parameter use.\n" +
   395                 "    iLi = n -> { List<_As_ _Bs_ Integer> LI = new ArrayList<_As_ _Bs_ Integer>(n);\n" +
   396                 "                 for(int nn = n; nn >=0; nn--) LI.add(nn);\n" +
   397                 "                 return LI; };\n" +
   398                 "    List<Integer> li = iLi.m(i);\n" +
   399                 "    for(Integer k : li) System.out.print(k);\n" +
   400                 "}\n" +
   401                 "  public static void main(String... args) {new " + testname + "().test(5); }\n" +
   402                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
   403                 "\n";
   404             break;
   405             case src6: //(repeating) type annotations on type parm in method reference.
   406                 /*
   407                  * class Test240{
   408                  *   interface PrintString { void print(String s); }
   409                  *   public void printArray(Object[] oa, PrintString ps) {
   410                  *       for(Object o : oa ) ps.print(o.toString());
   411                  *   }
   412                  *   public void test() {
   413                  *       Integer[] intarray = {1,2,3,4,5};
   414                  *       printArray(intarray, @A @B @A @B TPrint::<@A @B @A @B String>print);
   415                  *   }
   416                  * }
   417                  * class TPrint {
   418                  *    public static <T> void print(T t) { System.out.println( t.toString()); }
   419                  * }
   420                  */
   421                 source = new String( source +
   422                 "// " + src.description + "\n" +
   423                 "class "+ testname + "{\n" +
   424                 "  interface PrintString { void print(String s); }\n" +
   425                 "  public void printArray(Object[] oa, PrintString ps) {\n" +
   426                 "      for(Object o : oa ) ps.print(o.toString());\n" +
   427                 "  }\n" +
   428                 "  public void test() {\n" +
   429                 "    Integer[] intarray = {1,2,3,4,5};\n" +
   430                 "    printArray(intarray, _As_ _Bs_ TPrint::<_As_ _Bs_ String>print);\n" +
   431                 "  }\n" +
   432                 "  public static void main(String... args) {new " + testname + "().test(); }\n" +
   433                 "}\n\n" +
   434                 "class TPrint {\n" +
   435                 "  public static <T> void print(T t) { System.out.println( t.toString()); }\n" +
   436                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   437                 "\n";
   438             break;
   439             case src7: //(repeating)type annotations in inner class of lambda expression.
   440                 /*
   441                  * class Test2{
   442                  *   interface MapFun<T, R> {  R m( T n); }
   443                  *   MapFun<Class<?>,String> cs;
   444                  *   void test() {
   445                  *     cs = c -> {
   446                  *         class innerClass   {
   447                  *           @A @B Class<?> icc = null;
   448                  *           String getString() { return icc.toString(); }
   449                  *         }
   450                  *         return new innerClass().getString();
   451                  *     };
   452                  *     System.out.println("cs.m : " + cs.m(Integer.class));
   453                  *   }
   454                  * }
   455                  */
   456                 source = new String( source +
   457                 "// " + src.description + "\n" +
   458                 "class "+ testname + "{\n" +
   459                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   460                 "  MapFun<Class<?>,String> cs;\n" +
   461                 "  void test() {\n" +
   462                 "    cs = c -> {\n" +
   463                 "        class innerClass   {\n" +
   464                 "          _As_ _Bs_ Class<?> icc = null;\n" +
   465                 "          innerClass(Class<?> _c) { icc = _c; }\n" +
   466                 "          String getString() { return icc.toString(); }\n" +
   467                 "        }\n" +
   468                 "        return new innerClass(c).getString();\n" +
   469                 "    };\n" +
   470                 "    System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
   471                 "  }\n" +
   472                 "\n" +
   473                 "    public static void main(String... args) {new " + testname + "().test(); }\n" +
   474                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   475                 "\n";
   476                 src.innerClassname="$1innerClass";
   477             break;
   478             case src8: //(repeating)type annotations in inner class of lambda expression.
   479                 /*
   480                  * class Test2{
   481                  *   interface MapFun<T, R> {  R m( T n); }
   482                  *   MapFun<Class<?>,String> cs;
   483                  *   void test() {
   484                  *     cs = c -> {
   485                  *         class innerClass   {
   486                  *             Class<?> icc;
   487                  *             innerClass(@A @B Class<?> _c) { icc = _c; }
   488                  *             @A @B String getString() { return icc.toString(); }
   489                  *         }
   490                  *         return new innerClass(c).getString();
   491                  *     };
   492                  *     System.out.println("cs.m : " + cs.m(Integer.class));
   493                  *   }
   494                  * }
   495                  */
   496                 source = new String( source +
   497                 "// " + src.description + "\n" +
   498                 "class "+ testname + "{\n" +
   499                 "  interface MapFun<T, R> {  R m( T n); }\n" +
   500                 "  MapFun<Class<?>,String> cs;\n" +
   501                 "  void test() {\n" +
   502                 "    cs = c -> {\n" +
   503                 "        class innerClass {\n" +
   504                 "            Class<?> icc;\n" +
   505                 "            innerClass(_As_ _Bs_ Class<?> _c) { icc = _c; }\n" +
   506                 "            _As_ _Bs_ String getString() { return icc.toString(); }\n" +
   507                 "        }\n" +
   508                 "        return new innerClass(c).getString();\n" +
   509                 "    };\n" +
   510                 "    System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
   511                 "  }\n" +
   512                 "\n" +
   513                 "    public static void main(String... args) {new " + testname + "().test(); }\n" +
   514                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   515                 "\n";
   516                 src.innerClassname="$1innerClass";
   517             break;
   518             case src9: //(repeating)type annotations on static method of interface
   519                 /*
   520                  *  class Test90{
   521                  *    interface I  {
   522                  *      static @A @B @A @B String m() { @A @B @A @B String ret = "I.m"; return ret; }
   523                  *    }
   524                  *  }
   525                  */
   526                 source = new String( source +
   527                 "// " + src.description + "\n" +
   528                 "class "+ testname + "{\n" +
   529                 "  interface I  { \n" +
   530                 "    static _As_ _Bs_ String m() { _As_ _Bs_ String ret = \"I.m\"; return ret; }\n" +
   531                 "  }\n" +
   532                 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
   533                 "\n";
   534                 src.innerClassname="$I";
   535             break;
   536         }
   537         return imports + source;
   538     }
   539 }

mercurial