test/tools/javac/lambda/TestInvokeDynamic.java

Tue, 14 May 2013 11:11:09 -0700

author
rfield
date
Tue, 14 May 2013 11:11:09 -0700
changeset 1752
c09b7234cded
parent 1676
e9d986381414
child 1774
37295244f534
permissions
-rw-r--r--

8012556: Implement lambda methods on interfaces as static
8006140: Javac NPE compiling Lambda expression on initialization expression of static field in interface
Summary: Lambdas occurring in static contexts or those not needing instance information should be generated into static methods. This has long been the case for classes. However, as a work-around to the lack of support for statics on interfaces, interface lambda methods have been generated into default methods. For lambdas in interface static contexts (fields and static methods) this causes an NPE in javac because there is no 'this'. MethodHandles now support static methods on interfaces. This changeset allows lambda methods to be generated as static interface methods. An existing bug in Hotspot (8013875) is exposed in a test when the "-esa" flag is used. This test and another test that already exposed this bug have been marked with @ignore.
Reviewed-by: mcimadamore

mcimadamore@1336 1 /*
vromero@1482 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1336 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1336 4 *
mcimadamore@1336 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1336 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1336 7 * published by the Free Software Foundation.
mcimadamore@1336 8 *
mcimadamore@1336 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1336 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1336 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1336 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1336 13 * accompanied this code).
mcimadamore@1336 14 *
mcimadamore@1336 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1336 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1336 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1336 18 *
mcimadamore@1336 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1336 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1336 21 * questions.
mcimadamore@1336 22 */
mcimadamore@1336 23
mcimadamore@1336 24 /*
mcimadamore@1336 25 * @test
mcimadamore@1336 26 * @bug 7194586
mcimadamore@1676 27 * @bug 8003280 8006694 8010404
mcimadamore@1415 28 * @summary Add lambda tests
mcimadamore@1415 29 * Add back-end support for invokedynamic
vromero@1520 30 * temporarily workaround combo tests are causing time out in several platforms
vromero@1482 31 * @library ../lib
vromero@1482 32 * @build JavacTestingAbstractThreadedTest
vromero@1520 33 * @run main/othervm TestInvokeDynamic
mcimadamore@1336 34 */
mcimadamore@1336 35
vromero@1520 36 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
vromero@1520 37 // see JDK-8006746
vromero@1520 38
mcimadamore@1336 39 import com.sun.source.tree.MethodInvocationTree;
mcimadamore@1336 40 import com.sun.source.tree.MethodTree;
mcimadamore@1336 41 import com.sun.source.util.TaskEvent;
mcimadamore@1336 42 import com.sun.source.util.TaskListener;
mcimadamore@1336 43 import com.sun.source.util.TreeScanner;
mcimadamore@1336 44
mcimadamore@1336 45 import com.sun.tools.classfile.Attribute;
mcimadamore@1336 46 import com.sun.tools.classfile.BootstrapMethods_attribute;
mcimadamore@1336 47 import com.sun.tools.classfile.ClassFile;
mcimadamore@1336 48 import com.sun.tools.classfile.Code_attribute;
mcimadamore@1336 49 import com.sun.tools.classfile.ConstantPool.*;
mcimadamore@1336 50 import com.sun.tools.classfile.Instruction;
mcimadamore@1676 51 import com.sun.tools.classfile.LineNumberTable_attribute;
mcimadamore@1336 52 import com.sun.tools.classfile.Method;
mcimadamore@1336 53
mcimadamore@1336 54 import com.sun.tools.javac.api.JavacTaskImpl;
mcimadamore@1336 55 import com.sun.tools.javac.code.Symbol;
mcimadamore@1336 56 import com.sun.tools.javac.code.Symbol.MethodSymbol;
mcimadamore@1336 57 import com.sun.tools.javac.code.Symtab;
vromero@1452 58 import com.sun.tools.javac.code.Types;
mcimadamore@1336 59 import com.sun.tools.javac.jvm.Pool;
mcimadamore@1336 60 import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
mcimadamore@1336 61 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
mcimadamore@1336 62 import com.sun.tools.javac.tree.JCTree.JCIdent;
mcimadamore@1336 63 import com.sun.tools.javac.util.Context;
mcimadamore@1336 64 import com.sun.tools.javac.util.Names;
mcimadamore@1336 65
mcimadamore@1336 66 import java.io.File;
mcimadamore@1336 67 import java.net.URI;
mcimadamore@1336 68 import java.util.ArrayList;
mcimadamore@1336 69 import java.util.Arrays;
mcimadamore@1336 70 import java.util.Locale;
mcimadamore@1336 71
mcimadamore@1336 72 import javax.tools.Diagnostic;
mcimadamore@1336 73 import javax.tools.JavaFileObject;
mcimadamore@1336 74 import javax.tools.SimpleJavaFileObject;
mcimadamore@1336 75
mcimadamore@1336 76 import static com.sun.tools.javac.jvm.ClassFile.*;
mcimadamore@1336 77
vromero@1482 78 public class TestInvokeDynamic
vromero@1482 79 extends JavacTestingAbstractThreadedTest
vromero@1482 80 implements Runnable {
mcimadamore@1336 81
mcimadamore@1336 82 enum StaticArgumentKind {
mcimadamore@1336 83 STRING("Hello!", "String", "Ljava/lang/String;") {
mcimadamore@1336 84 @Override
mcimadamore@1336 85 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 86 return (cpInfo instanceof CONSTANT_String_info) &&
vromero@1482 87 ((CONSTANT_String_info)cpInfo).getString()
vromero@1482 88 .equals(value);
mcimadamore@1336 89 }
mcimadamore@1336 90 },
mcimadamore@1336 91 CLASS(null, "Class<?>", "Ljava/lang/Class;") {
mcimadamore@1336 92 @Override
mcimadamore@1336 93 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 94 return (cpInfo instanceof CONSTANT_Class_info) &&
vromero@1482 95 ((CONSTANT_Class_info)cpInfo).getName()
vromero@1482 96 .equals("java/lang/String");
mcimadamore@1336 97 }
mcimadamore@1336 98 },
mcimadamore@1336 99 INTEGER(1, "int", "I") {
mcimadamore@1336 100 @Override
mcimadamore@1336 101 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 102 return (cpInfo instanceof CONSTANT_Integer_info) &&
vromero@1482 103 ((CONSTANT_Integer_info)cpInfo).value ==
vromero@1482 104 ((Integer)value).intValue();
mcimadamore@1336 105 }
mcimadamore@1336 106 },
mcimadamore@1336 107 LONG(1L, "long", "J") {
mcimadamore@1336 108 @Override
mcimadamore@1336 109 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 110 return (cpInfo instanceof CONSTANT_Long_info) &&
vromero@1482 111 ((CONSTANT_Long_info)cpInfo).value ==
vromero@1482 112 ((Long)value).longValue();
mcimadamore@1336 113 }
mcimadamore@1336 114 },
mcimadamore@1336 115 FLOAT(1.0f, "float", "F") {
mcimadamore@1336 116 @Override
mcimadamore@1336 117 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 118 return (cpInfo instanceof CONSTANT_Float_info) &&
vromero@1482 119 ((CONSTANT_Float_info)cpInfo).value ==
vromero@1482 120 ((Float)value).floatValue();
mcimadamore@1336 121 }
mcimadamore@1336 122 },
mcimadamore@1336 123 DOUBLE(1.0, "double","D") {
mcimadamore@1336 124 @Override
mcimadamore@1336 125 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 126 return (cpInfo instanceof CONSTANT_Double_info) &&
vromero@1482 127 ((CONSTANT_Double_info)cpInfo).value ==
vromero@1482 128 ((Double)value).doubleValue();
mcimadamore@1336 129 }
mcimadamore@1336 130 },
mcimadamore@1336 131 METHOD_HANDLE(null, "MethodHandle", "Ljava/lang/invoke/MethodHandle;") {
mcimadamore@1336 132 @Override
mcimadamore@1336 133 boolean check(CPInfo cpInfo) throws Exception {
vromero@1482 134 if (!(cpInfo instanceof CONSTANT_MethodHandle_info))
vromero@1482 135 return false;
vromero@1482 136 CONSTANT_MethodHandle_info handleInfo =
vromero@1482 137 (CONSTANT_MethodHandle_info)cpInfo;
mcimadamore@1336 138 return handleInfo.getCPRefInfo().getClassName().equals("Array") &&
mcimadamore@1336 139 handleInfo.reference_kind == RefKind.REF_invokeVirtual &&
vromero@1482 140 handleInfo.getCPRefInfo()
vromero@1482 141 .getNameAndTypeInfo().getName().equals("clone") &&
vromero@1482 142 handleInfo.getCPRefInfo()
vromero@1482 143 .getNameAndTypeInfo().getType().equals("()Ljava/lang/Object;");
mcimadamore@1336 144 }
mcimadamore@1336 145 },
mcimadamore@1336 146 METHOD_TYPE(null, "MethodType", "Ljava/lang/invoke/MethodType;") {
mcimadamore@1336 147 @Override
mcimadamore@1336 148 boolean check(CPInfo cpInfo) throws Exception {
mcimadamore@1336 149 return (cpInfo instanceof CONSTANT_MethodType_info) &&
vromero@1482 150 ((CONSTANT_MethodType_info)cpInfo).getType()
vromero@1482 151 .equals("()Ljava/lang/Object;");
mcimadamore@1336 152 }
mcimadamore@1336 153 };
mcimadamore@1336 154
mcimadamore@1336 155 Object value;
mcimadamore@1336 156 String sourceTypeStr;
mcimadamore@1336 157 String bytecodeTypeStr;
mcimadamore@1336 158
vromero@1482 159 StaticArgumentKind(Object value, String sourceTypeStr,
vromero@1482 160 String bytecodeTypeStr) {
mcimadamore@1336 161 this.value = value;
mcimadamore@1336 162 this.sourceTypeStr = sourceTypeStr;
mcimadamore@1336 163 this.bytecodeTypeStr = bytecodeTypeStr;
mcimadamore@1336 164 }
mcimadamore@1336 165
mcimadamore@1336 166 abstract boolean check(CPInfo cpInfo) throws Exception;
mcimadamore@1336 167
vromero@1452 168 Object getValue(Symtab syms, Names names, Types types) {
mcimadamore@1336 169 switch (this) {
mcimadamore@1336 170 case STRING:
mcimadamore@1336 171 case INTEGER:
mcimadamore@1336 172 case LONG:
mcimadamore@1336 173 case FLOAT:
mcimadamore@1336 174 case DOUBLE:
mcimadamore@1336 175 return value;
mcimadamore@1336 176 case CLASS:
mcimadamore@1336 177 return syms.stringType.tsym;
mcimadamore@1336 178 case METHOD_HANDLE:
vromero@1482 179 return new Pool.MethodHandle(REF_invokeVirtual,
vromero@1482 180 syms.arrayCloneMethod, types);
mcimadamore@1336 181 case METHOD_TYPE:
mcimadamore@1336 182 return syms.arrayCloneMethod.type;
mcimadamore@1336 183 default:
mcimadamore@1336 184 throw new AssertionError();
mcimadamore@1336 185 }
mcimadamore@1336 186 }
mcimadamore@1336 187 }
mcimadamore@1336 188
mcimadamore@1336 189 enum StaticArgumentsArity {
mcimadamore@1336 190 ZERO(0),
mcimadamore@1336 191 ONE(1),
mcimadamore@1336 192 TWO(2),
mcimadamore@1336 193 THREE(3);
mcimadamore@1336 194
mcimadamore@1336 195 int arity;
mcimadamore@1336 196
mcimadamore@1336 197 StaticArgumentsArity(int arity) {
mcimadamore@1336 198 this.arity = arity;
mcimadamore@1336 199 }
mcimadamore@1336 200 }
mcimadamore@1336 201
mcimadamore@1336 202 public static void main(String... args) throws Exception {
mcimadamore@1336 203 for (StaticArgumentsArity arity : StaticArgumentsArity.values()) {
mcimadamore@1336 204 if (arity.arity == 0) {
vromero@1482 205 pool.execute(new TestInvokeDynamic(arity));
mcimadamore@1336 206 } else {
mcimadamore@1336 207 for (StaticArgumentKind sak1 : StaticArgumentKind.values()) {
mcimadamore@1336 208 if (arity.arity == 1) {
vromero@1482 209 pool.execute(new TestInvokeDynamic(arity, sak1));
mcimadamore@1336 210 } else {
mcimadamore@1336 211 for (StaticArgumentKind sak2 : StaticArgumentKind.values()) {
mcimadamore@1336 212 if (arity.arity == 2) {
vromero@1482 213 pool.execute(new TestInvokeDynamic(arity, sak1, sak2));
mcimadamore@1336 214 } else {
mcimadamore@1336 215 for (StaticArgumentKind sak3 : StaticArgumentKind.values()) {
vromero@1482 216 pool.execute(
vromero@1482 217 new TestInvokeDynamic(arity, sak1, sak2, sak3));
mcimadamore@1336 218 }
mcimadamore@1336 219 }
mcimadamore@1336 220 }
mcimadamore@1336 221 }
mcimadamore@1336 222 }
mcimadamore@1336 223 }
mcimadamore@1336 224 }
mcimadamore@1336 225
vromero@1482 226 checkAfterExec();
mcimadamore@1336 227 }
mcimadamore@1336 228
mcimadamore@1336 229 StaticArgumentsArity arity;
mcimadamore@1336 230 StaticArgumentKind[] saks;
mcimadamore@1336 231 DiagChecker dc;
mcimadamore@1336 232
mcimadamore@1336 233 TestInvokeDynamic(StaticArgumentsArity arity, StaticArgumentKind... saks) {
mcimadamore@1336 234 this.arity = arity;
mcimadamore@1336 235 this.saks = saks;
mcimadamore@1336 236 dc = new DiagChecker();
mcimadamore@1336 237 }
mcimadamore@1336 238
vromero@1482 239 public void run() {
vromero@1482 240 int id = checkCount.incrementAndGet();
vromero@1482 241 JavaSource source = new JavaSource(id);
vromero@1482 242 JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
mcimadamore@1676 243 Arrays.asList("-g"), null, Arrays.asList(source));
mcimadamore@1336 244 Context context = ct.getContext();
mcimadamore@1336 245 Symtab syms = Symtab.instance(context);
mcimadamore@1336 246 Names names = Names.instance(context);
vromero@1452 247 Types types = Types.instance(context);
vromero@1452 248 ct.addTaskListener(new Indifier(syms, names, types));
mcimadamore@1336 249 try {
mcimadamore@1336 250 ct.generate();
mcimadamore@1336 251 } catch (Throwable t) {
mcimadamore@1336 252 t.printStackTrace();
vromero@1482 253 throw new AssertionError(
vromero@1482 254 String.format("Error thrown when compiling following code\n%s",
vromero@1482 255 source.source));
mcimadamore@1336 256 }
mcimadamore@1336 257 if (dc.diagFound) {
vromero@1482 258 throw new AssertionError(
vromero@1482 259 String.format("Diags found when compiling following code\n%s\n\n%s",
vromero@1482 260 source.source, dc.printDiags()));
mcimadamore@1336 261 }
vromero@1482 262 verifyBytecode(id);
mcimadamore@1336 263 }
mcimadamore@1336 264
vromero@1482 265 void verifyBytecode(int id) {
vromero@1482 266 File compiledTest = new File(String.format("Test%d.class", id));
mcimadamore@1336 267 try {
mcimadamore@1336 268 ClassFile cf = ClassFile.read(compiledTest);
mcimadamore@1336 269 Method testMethod = null;
mcimadamore@1336 270 for (Method m : cf.methods) {
mcimadamore@1336 271 if (m.getName(cf.constant_pool).equals("test")) {
mcimadamore@1336 272 testMethod = m;
mcimadamore@1336 273 break;
mcimadamore@1336 274 }
mcimadamore@1336 275 }
mcimadamore@1336 276 if (testMethod == null) {
mcimadamore@1336 277 throw new Error("Test method not found");
mcimadamore@1336 278 }
vromero@1482 279 Code_attribute ea =
vromero@1482 280 (Code_attribute)testMethod.attributes.get(Attribute.Code);
mcimadamore@1336 281 if (testMethod == null) {
mcimadamore@1336 282 throw new Error("Code attribute for test() method not found");
mcimadamore@1336 283 }
mcimadamore@1336 284
mcimadamore@1336 285 int bsmIdx = -1;
mcimadamore@1336 286
mcimadamore@1336 287 for (Instruction i : ea.getInstructions()) {
mcimadamore@1336 288 if (i.getMnemonic().equals("invokedynamic")) {
mcimadamore@1336 289 CONSTANT_InvokeDynamic_info indyInfo =
vromero@1482 290 (CONSTANT_InvokeDynamic_info)cf
vromero@1482 291 .constant_pool.get(i.getShort(1));
mcimadamore@1336 292 bsmIdx = indyInfo.bootstrap_method_attr_index;
mcimadamore@1336 293 if (!indyInfo.getNameAndTypeInfo().getType().equals("()V")) {
vromero@1482 294 throw new
vromero@1482 295 AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
mcimadamore@1336 296 }
mcimadamore@1336 297 }
mcimadamore@1336 298 }
mcimadamore@1336 299 if (bsmIdx == -1) {
mcimadamore@1336 300 throw new Error("Missing invokedynamic in generated code");
mcimadamore@1336 301 }
mcimadamore@1336 302
vromero@1482 303 BootstrapMethods_attribute bsm_attr =
vromero@1482 304 (BootstrapMethods_attribute)cf
vromero@1482 305 .getAttribute(Attribute.BootstrapMethods);
mcimadamore@1336 306 if (bsm_attr.bootstrap_method_specifiers.length != 1) {
vromero@1482 307 throw new Error("Bad number of method specifiers " +
vromero@1482 308 "in BootstrapMethods attribute");
mcimadamore@1336 309 }
mcimadamore@1336 310 BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec =
mcimadamore@1336 311 bsm_attr.bootstrap_method_specifiers[0];
mcimadamore@1336 312
mcimadamore@1336 313 if (bsm_spec.bootstrap_arguments.length != arity.arity) {
vromero@1482 314 throw new Error("Bad number of static invokedynamic args " +
vromero@1482 315 "in BootstrapMethod attribute");
mcimadamore@1336 316 }
mcimadamore@1336 317
mcimadamore@1336 318 int count = 0;
mcimadamore@1336 319 for (StaticArgumentKind sak : saks) {
vromero@1482 320 if (!sak.check(cf.constant_pool
vromero@1482 321 .get(bsm_spec.bootstrap_arguments[count]))) {
mcimadamore@1336 322 throw new Error("Bad static argument value " + sak);
mcimadamore@1336 323 }
mcimadamore@1336 324 count++;
mcimadamore@1336 325 }
mcimadamore@1336 326
mcimadamore@1336 327 CONSTANT_MethodHandle_info bsm_handle =
vromero@1482 328 (CONSTANT_MethodHandle_info)cf.constant_pool
vromero@1482 329 .get(bsm_spec.bootstrap_method_ref);
mcimadamore@1336 330
mcimadamore@1336 331 if (bsm_handle.reference_kind != RefKind.REF_invokeStatic) {
mcimadamore@1336 332 throw new Error("Bad kind on boostrap method handle");
mcimadamore@1336 333 }
mcimadamore@1336 334
mcimadamore@1336 335 CONSTANT_Methodref_info bsm_ref =
vromero@1482 336 (CONSTANT_Methodref_info)cf.constant_pool
vromero@1482 337 .get(bsm_handle.reference_index);
mcimadamore@1336 338
mcimadamore@1336 339 if (!bsm_ref.getClassInfo().getName().equals("Bootstrap")) {
mcimadamore@1336 340 throw new Error("Bad owner of boostrap method");
mcimadamore@1336 341 }
mcimadamore@1336 342
mcimadamore@1336 343 if (!bsm_ref.getNameAndTypeInfo().getName().equals("bsm")) {
mcimadamore@1336 344 throw new Error("Bad boostrap method name");
mcimadamore@1336 345 }
mcimadamore@1336 346
vromero@1482 347 if (!bsm_ref.getNameAndTypeInfo()
vromero@1482 348 .getType().equals(asBSMSignatureString())) {
vromero@1482 349 throw new Error("Bad boostrap method type" +
vromero@1482 350 bsm_ref.getNameAndTypeInfo().getType() + " " +
vromero@1482 351 asBSMSignatureString());
mcimadamore@1336 352 }
mcimadamore@1676 353
mcimadamore@1676 354 LineNumberTable_attribute lnt =
mcimadamore@1676 355 (LineNumberTable_attribute)ea.attributes.get(Attribute.LineNumberTable);
mcimadamore@1676 356
mcimadamore@1676 357 if (lnt == null) {
mcimadamore@1676 358 throw new Error("No LineNumberTable attribute");
mcimadamore@1676 359 }
mcimadamore@1676 360 if (lnt.line_number_table_length != 2) {
mcimadamore@1676 361 throw new Error("Wrong number of entries in LineNumberTable");
mcimadamore@1676 362 }
mcimadamore@1336 363 } catch (Exception e) {
mcimadamore@1336 364 e.printStackTrace();
mcimadamore@1336 365 throw new Error("error reading " + compiledTest +": " + e);
mcimadamore@1336 366 }
mcimadamore@1336 367 }
mcimadamore@1336 368
mcimadamore@1336 369 String asBSMSignatureString() {
mcimadamore@1336 370 StringBuilder buf = new StringBuilder();
mcimadamore@1336 371 buf.append("(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;");
mcimadamore@1336 372 for (StaticArgumentKind sak : saks) {
mcimadamore@1336 373 buf.append(sak.bytecodeTypeStr);
mcimadamore@1336 374 }
mcimadamore@1336 375 buf.append(")Ljava/lang/invoke/CallSite;");
mcimadamore@1336 376 return buf.toString();
mcimadamore@1336 377 }
mcimadamore@1336 378
mcimadamore@1336 379 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1336 380
mcimadamore@1336 381 static final String source_template = "import java.lang.invoke.*;\n" +
mcimadamore@1336 382 "class Bootstrap {\n" +
vromero@1482 383 " public static CallSite bsm(MethodHandles.Lookup lookup, " +
vromero@1482 384 "String name, MethodType methodType #SARGS) {\n" +
mcimadamore@1336 385 " return null;\n" +
mcimadamore@1336 386 " }\n" +
mcimadamore@1336 387 "}\n" +
vromero@1482 388 "class Test#ID {\n" +
mcimadamore@1336 389 " void m() { }\n" +
mcimadamore@1676 390 " void test() {\n" +
mcimadamore@1676 391 " Object o = this; // marker statement \n" +
mcimadamore@1676 392 " m();\n" +
mcimadamore@1676 393 " }\n" +
mcimadamore@1336 394 "}";
mcimadamore@1336 395
mcimadamore@1336 396 String source;
mcimadamore@1336 397
vromero@1482 398 JavaSource(int id) {
mcimadamore@1336 399 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
vromero@1482 400 source = source_template.replace("#SARGS", asSignatureString())
vromero@1482 401 .replace("#ID", String.valueOf(id));
mcimadamore@1336 402 }
mcimadamore@1336 403
mcimadamore@1336 404 @Override
mcimadamore@1336 405 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1336 406 return source;
mcimadamore@1336 407 }
mcimadamore@1336 408
mcimadamore@1336 409 String asSignatureString() {
mcimadamore@1336 410 int count = 0;
mcimadamore@1336 411 StringBuilder buf = new StringBuilder();
mcimadamore@1336 412 for (StaticArgumentKind sak : saks) {
mcimadamore@1336 413 buf.append(",");
mcimadamore@1336 414 buf.append(sak.sourceTypeStr);
mcimadamore@1336 415 buf.append(' ');
mcimadamore@1336 416 buf.append(String.format("x%d", count++));
mcimadamore@1336 417 }
mcimadamore@1336 418 return buf.toString();
mcimadamore@1336 419 }
mcimadamore@1336 420 }
mcimadamore@1336 421
mcimadamore@1336 422 class Indifier extends TreeScanner<Void, Void> implements TaskListener {
mcimadamore@1336 423
mcimadamore@1336 424 MethodSymbol bsm;
mcimadamore@1336 425 Symtab syms;
mcimadamore@1336 426 Names names;
vromero@1452 427 Types types;
mcimadamore@1336 428
vromero@1452 429 Indifier(Symtab syms, Names names, Types types) {
mcimadamore@1336 430 this.syms = syms;
mcimadamore@1336 431 this.names = names;
vromero@1452 432 this.types = types;
mcimadamore@1336 433 }
mcimadamore@1336 434
mcimadamore@1336 435 @Override
mcimadamore@1336 436 public void started(TaskEvent e) {
mcimadamore@1336 437 //do nothing
mcimadamore@1336 438 }
mcimadamore@1336 439
mcimadamore@1336 440 @Override
mcimadamore@1336 441 public void finished(TaskEvent e) {
mcimadamore@1336 442 if (e.getKind() == TaskEvent.Kind.ANALYZE) {
mcimadamore@1336 443 scan(e.getCompilationUnit(), null);
mcimadamore@1336 444 }
mcimadamore@1336 445 }
mcimadamore@1336 446
mcimadamore@1336 447 @Override
mcimadamore@1336 448 public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
mcimadamore@1336 449 super.visitMethodInvocation(node, p);
mcimadamore@1336 450 JCMethodInvocation apply = (JCMethodInvocation)node;
mcimadamore@1336 451 JCIdent ident = (JCIdent)apply.meth;
mcimadamore@1336 452 Symbol oldSym = ident.sym;
mcimadamore@1336 453 if (!oldSym.isConstructor()) {
mcimadamore@1336 454 Object[] staticArgs = new Object[arity.arity];
mcimadamore@1336 455 for (int i = 0; i < arity.arity ; i++) {
vromero@1452 456 staticArgs[i] = saks[i].getValue(syms, names, types);
mcimadamore@1336 457 }
vromero@1482 458 ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
vromero@1482 459 oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
mcimadamore@1336 460 }
mcimadamore@1336 461 return null;
mcimadamore@1336 462 }
mcimadamore@1336 463
mcimadamore@1336 464 @Override
mcimadamore@1336 465 public Void visitMethod(MethodTree node, Void p) {
mcimadamore@1336 466 super.visitMethod(node, p);
mcimadamore@1336 467 if (node.getName().toString().equals("bsm")) {
mcimadamore@1336 468 bsm = ((JCMethodDecl)node).sym;
mcimadamore@1336 469 }
mcimadamore@1336 470 return null;
mcimadamore@1336 471 }
mcimadamore@1336 472 }
mcimadamore@1336 473
vromero@1482 474 static class DiagChecker
vromero@1482 475 implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1336 476
mcimadamore@1336 477 boolean diagFound;
mcimadamore@1336 478 ArrayList<String> diags = new ArrayList<>();
mcimadamore@1336 479
mcimadamore@1336 480 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1336 481 diags.add(diagnostic.getMessage(Locale.getDefault()));
mcimadamore@1336 482 diagFound = true;
mcimadamore@1336 483 }
mcimadamore@1336 484
mcimadamore@1336 485 String printDiags() {
mcimadamore@1336 486 StringBuilder buf = new StringBuilder();
mcimadamore@1336 487 for (String s : diags) {
mcimadamore@1336 488 buf.append(s);
mcimadamore@1336 489 buf.append("\n");
mcimadamore@1336 490 }
mcimadamore@1336 491 return buf.toString();
mcimadamore@1336 492 }
mcimadamore@1336 493 }
vromero@1482 494
mcimadamore@1336 495 }

mercurial