| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.core.tests.compiler.regression; |
| |
| import java.io.File; |
| import java.util.Map; |
| |
| import junit.framework.Test; |
| |
| import org.eclipse.jdt.core.ToolFactory; |
| import org.eclipse.jdt.core.tests.util.Util; |
| import org.eclipse.jdt.core.util.ClassFileBytesDisassembler; |
| import org.eclipse.jdt.internal.compiler.Compiler; |
| import org.eclipse.jdt.internal.compiler.env.INameEnvironment; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies; |
| |
| @SuppressWarnings({ "rawtypes" }) |
| public class EnclosingMethodAttributeTest extends AbstractComparableTest { |
| public EnclosingMethodAttributeTest(String name) { |
| super(name); |
| } |
| |
| // Static initializer to specify tests subset using TESTS_* static variables |
| // All specified tests which does not belong to the class are skipped... |
| static { |
| // TESTS_NAMES = new String[] { "test127" }; |
| // TESTS_NUMBERS = new int[] { 4 }; |
| // TESTS_RANGE = new int[] { 169, 180 }; |
| } |
| |
| public static Test suite() { |
| return buildComparableTestSuite(testClass()); |
| } |
| |
| public static Class testClass() { |
| return EnclosingMethodAttributeTest.class; |
| } |
| |
| public void test001() throws Exception { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "public class X {\n" + |
| "public static void main(String[] args) throws Exception {\n" + |
| " class MyLocal$A {\n" + |
| " class Member {\n" + |
| " }\n" + |
| " };\n" + |
| " System.out.print(MyLocal$A.Member.class.getEnclosingMethod() != null);\n" + |
| " System.out.print(MyLocal$A.Member.class.getEnclosingConstructor() != null);\n" + |
| "\n" + |
| " System.out.print(MyLocal$A.class.getEnclosingMethod()!= null);\n" + |
| " System.out.print(MyLocal$A.class.getEnclosingConstructor() != null); \n" + |
| " \n" + |
| " System.out.print(X.class.getEnclosingMethod() != null);\n" + |
| " System.out.print(X.class.getEnclosingConstructor() != null); \n" + |
| "}\n" + |
| "public Object foo() {\n" + |
| " return new Object() {};\n" + |
| "}\n" + |
| "}" |
| }, |
| "falsefalsetruefalsefalsefalse"); |
| |
| ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); |
| byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X$1.class")); |
| String actualOutput = |
| disassembler.disassemble( |
| classFileBytes, |
| "\n", |
| ClassFileBytesDisassembler.DETAILED); |
| |
| String expectedOutput = " Enclosing Method: #22 #24 X.foo()Ljava/lang/Object;\n"; |
| |
| int index = actualOutput.indexOf(expectedOutput); |
| if (index == -1 || expectedOutput.length() == 0) { |
| System.out.println(Util.displayString(actualOutput, 2)); |
| } |
| if (index == -1) { |
| assertEquals("Wrong contents", expectedOutput, actualOutput); |
| } |
| } |
| |
| public void test002() throws Exception { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "public class X {\n" + |
| "public static void main(String[] args) throws Exception {\n" + |
| " class MyLocal$A {\n" + |
| " class Member {\n" + |
| " public Object foo() {\n" + |
| " return new Object() {};\n" + |
| " }\n" + |
| " }\n" + |
| " };\n" + |
| " System.out.print(MyLocal$A.Member.class.getEnclosingMethod() != null);\n" + |
| " System.out.print(MyLocal$A.Member.class.getEnclosingConstructor() != null);\n" + |
| "\n" + |
| " System.out.print(MyLocal$A.class.getEnclosingMethod()!= null);\n" + |
| " System.out.print(MyLocal$A.class.getEnclosingConstructor() != null); \n" + |
| " \n" + |
| " System.out.print(X.class.getEnclosingMethod() != null);\n" + |
| " System.out.print(X.class.getEnclosingConstructor() != null); \n" + |
| "}\n" + |
| "}" |
| }, |
| "falsefalsetruefalsefalsefalse"); |
| |
| ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); |
| byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator + "X$1MyLocal$A$Member$1.class")); |
| String actualOutput = |
| disassembler.disassemble( |
| classFileBytes, |
| "\n", |
| ClassFileBytesDisassembler.DETAILED); |
| |
| String expectedOutput = " Enclosing Method: #22 #24 X$1MyLocal$A$Member.foo()Ljava/lang/Object;\n"; |
| |
| int index = actualOutput.indexOf(expectedOutput); |
| if (index == -1 || expectedOutput.length() == 0) { |
| System.out.println(Util.displayString(actualOutput, 2)); |
| } |
| if (index == -1) { |
| assertEquals("Wrong contents", expectedOutput, actualOutput); |
| } |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=162356 |
| public void test003() throws Exception { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.lang.reflect.*;\n" + |
| "public class X {\n" + |
| " public void test() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {\n" + |
| " class LocalClass {\n" + |
| " public void method() {\n" + |
| " }\n" + |
| " };\n" + |
| " LocalClass localClass = new LocalClass();\n" + |
| " Class cc = localClass.getClass();\n" + |
| " System.out.println(\"enclosing class = \" + cc.getEnclosingClass());\n" + |
| " System.out.println(\"enclosing method = \" + cc.getEnclosingMethod());\n" + |
| " }\n" + |
| " public static void main(String args[]) {\n" + |
| " X t = new X();\n" + |
| " try {\n" + |
| " t.test();\n" + |
| " } catch (Exception e) {\n" + |
| " e.printStackTrace();\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "enclosing class = class X\n" + |
| "enclosing method = public void X.test() throws java.lang.NoSuchMethodException,java.lang.IllegalAccessException,java.lang.reflect.InvocationTargetException"); |
| |
| INameEnvironment nameEnvironment = getNameEnvironment(new String[]{}, null); |
| nameEnvironment.findType(new char[][] {new char[0], "X$1LocalClass".toCharArray()}); |
| ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); |
| byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator + "X$1LocalClass.class")); |
| String actualOutput = |
| disassembler.disassemble( |
| classFileBytes, |
| "\n", |
| ClassFileBytesDisassembler.DETAILED); |
| |
| String expectedOutput = |
| " Inner classes:\n" + |
| " [inner class info: #1 X$1LocalClass, outer class info: #0\n" + |
| " inner name: #28 LocalClass, accessflags: 0 default]\n"; |
| |
| // check inner classes info |
| int index = actualOutput.indexOf(expectedOutput); |
| if (index == -1 || expectedOutput.length() == 0) { |
| System.out.println(Util.displayString(actualOutput, 2)); |
| } |
| if (index == -1) { |
| assertEquals("Wrong contents", expectedOutput, actualOutput); |
| } |
| |
| expectedOutput = |
| " Enclosing Method: #23 #25 X.test()V\n"; |
| |
| // check enclosing method |
| index = actualOutput.indexOf(expectedOutput); |
| if (index == -1 || expectedOutput.length() == 0) { |
| System.out.println(Util.displayString(actualOutput, 2)); |
| } |
| if (index == -1) { |
| assertEquals("Wrong contents", expectedOutput, actualOutput); |
| } |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=288920 |
| public void test004() throws Exception { |
| this.runConformTest( |
| new String[] { |
| "X.java", |
| "import java.lang.reflect.*;\n" + |
| "interface I<E> {\n" + |
| " public String run();\n" + |
| "}\n" + |
| "public class X {\n" + |
| " public Object test(String s, int i) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {\n" + |
| " return (new I<String>() {" + |
| " public String run() {\n" + |
| " return \"SUCCESS\";\n" + |
| " }\n" + |
| " }).run();\n" + |
| " }\n" + |
| " public static void main(String args[]) {\n" + |
| " X t = new X();\n" + |
| " try {\n" + |
| " System.out.println(t.test(\"\", 0));\n" + |
| " } catch (Exception e) {\n" + |
| " e.printStackTrace();\n" + |
| " }\n" + |
| " }\n" + |
| "}" |
| }, |
| "SUCCESS"); |
| |
| Requestor requestor = |
| new Requestor( |
| true, |
| null, |
| false, /* show category */ |
| false /* show warning token*/); |
| requestor.outputPath = OUTPUT_DIR.endsWith(File.separator) ? OUTPUT_DIR : OUTPUT_DIR + File.separator; |
| // WORK should not have to test a constant? |
| |
| Map<String, String> options = getCompilerOptions(); |
| CompilerOptions compilerOptions = new CompilerOptions(options); |
| compilerOptions.performMethodsFullRecovery = true; |
| compilerOptions.performStatementsRecovery = true; |
| INameEnvironment nameEnvironment = getNameEnvironment(new String[]{}, null); |
| Compiler batchCompiler = |
| new Compiler( |
| nameEnvironment, |
| getErrorHandlingPolicy(), |
| compilerOptions, |
| requestor, |
| getProblemFactory()); |
| //{ObjectTeams: avoid exceptions: |
| try (Config config = Dependencies.setup(batchCompiler, batchCompiler.parser, batchCompiler.lookupEnvironment, true, false)) |
| { |
| // orig: |
| ReferenceBinding binaryType = batchCompiler.lookupEnvironment.askForType(new char[][] {new char[0], "X$1".toCharArray()}, batchCompiler.lookupEnvironment.UnNamedModule); |
| assertNotNull("Should not be null", binaryType); |
| // :giro |
| } |
| // SH} |
| } |
| } |