blob: 9254c0bbf29be308f9466462b3b5c8338bad974d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 461250 - ArrayIndexOutOfBoundsException in SourceTypeBinding.fields
* Carmi Grushko - Bug 465048 - Binding is null for class literals in synchronized blocks
*******************************************************************************/
package org.eclipse.jdt.core.tests.dom;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.FileASTRequestor;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest;
@SuppressWarnings({ "rawtypes" })
public class StandAloneASTParserTest extends AbstractRegressionTest {
public StandAloneASTParserTest(String name) {
super(name);
}
private static final int AST_JLS_LATEST = AST.JLS9;
public ASTNode runConversion(
int astLevel,
String source,
boolean resolveBindings,
boolean statementsRecovery,
boolean bindingsRecovery,
String unitName) {
ASTParser parser = ASTParser.newParser(astLevel);
parser.setSource(source.toCharArray());
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(resolveBindings);
parser.setStatementsRecovery(statementsRecovery);
parser.setBindingsRecovery(bindingsRecovery);
parser.setCompilerOptions(getCompilerOptions());
parser.setUnitName(unitName);
return parser.createAST(null);
}
public void test1() {
String contents =
"package p;\n" +
"public class X {\n" +
" public int i;\n" +
" public static void main(String[] args) {\n" +
" int length = args.length;\n" +
" System.out.println(length);\n" +
" }\n" +
"}";
ASTNode node = runConversion(AST_JLS_LATEST, contents, true, true, true, "p/X.java");
assertTrue("Should be a compilation unit", node instanceof CompilationUnit);
CompilationUnit unit = (CompilationUnit) node;
List types = unit.types();
TypeDeclaration typeDeclaration = (TypeDeclaration) types.get(0);
ITypeBinding binding = typeDeclaration.resolveBinding();
assertNotNull("No binding", binding);
assertNull("Got a java element", binding.getJavaElement());
assertEquals("Wrong name", "p.X", binding.getQualifiedName());
MethodDeclaration methodDeclaration = (MethodDeclaration) typeDeclaration.bodyDeclarations().get(1);
IMethodBinding methodBinding = methodDeclaration.resolveBinding();
assertNotNull("No binding", methodBinding);
assertNull("Got a java element", methodBinding.getJavaElement());
Block body = methodDeclaration.getBody();
VariableDeclarationStatement statement = (VariableDeclarationStatement) body.statements().get(0);
VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
IVariableBinding variableBinding = fragment.resolveBinding();
assertNotNull("No binding", variableBinding);
assertNull("Got a java element", variableBinding.getJavaElement());
ExpressionStatement statement2 = (ExpressionStatement) body.statements().get(1);
Expression expression = statement2.getExpression();
MethodInvocation invocation = (MethodInvocation) expression;
Expression expression2 = invocation.getExpression();
assertNotNull("No binding", expression2.resolveTypeBinding());
FieldDeclaration fieldDeclaration = (FieldDeclaration) typeDeclaration.bodyDeclarations().get(0);
VariableDeclarationFragment fragment2 = (VariableDeclarationFragment) fieldDeclaration.fragments().get(0);
IVariableBinding variableBinding2 = fragment2.resolveBinding();
assertNotNull("No binding", variableBinding2);
assertNull("Got a java element", variableBinding2.getJavaElement());
}
public void test2() {
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(getCompilerOptions());
final String key = "Ljava/lang/String;";
final IBinding[] bindings = new IBinding[1];
FileASTRequestor requestor = new FileASTRequestor() {
public void acceptBinding(String bindingKey, IBinding binding) {
if (key.equals(bindingKey)) {
bindings[0] = binding;
}
}
};
parser.createASTs(new String[] {}, null, new String[] {key}, requestor, null);
assertNotNull("No binding", bindings[0]);
assertEquals("Wrong type of binding", IBinding.TYPE, bindings[0].getKind());
ITypeBinding typeBinding = (ITypeBinding) bindings[0];
assertEquals("Wrong binding", "java.lang.String", typeBinding.getQualifiedName());
assertNull("No java element", typeBinding.getJavaElement());
}
public void test3() throws IOException {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(getCompilerOptions());
final String key = "Lp/X;";
final IBinding[] bindings = new IBinding[1];
String contents =
"package p;\n" +
"public class X extends Y {\n" +
" public int i;\n" +
" public static void main(String[] args) {\n" +
" int length = args.length;\n" +
" System.out.println(length);\n" +
" }\n" +
"}";
File packageDir = new File(rootDir, "p");
packageDir.mkdir();
File file = new File(packageDir, "X.java");
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"package p;\n" +
"public class Y {}";
File fileY = new File(packageDir, "Y.java");
Writer writer2 = null;
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} finally {
if (writer2 != null) {
try {
writer2.close();
} catch(IOException e) {
// ignore
}
}
}
try {
final String canonicalPath = file.getCanonicalPath();
final CompilationUnit[] units = new CompilationUnit[1];
FileASTRequestor requestor = new FileASTRequestor() {
public void acceptBinding(String bindingKey, IBinding binding) {
if (key.equals(bindingKey)) {
bindings[0] = binding;
}
}
public void acceptAST(String sourceFilePath, CompilationUnit ast) {
if (canonicalPath.equals(sourceFilePath)) {
units[0] = ast;
}
}
};
parser.setEnvironment(null, new String[] { rootDir.getCanonicalPath() }, null, true);
parser.createASTs(new String[] {canonicalPath}, null, new String[] {key}, requestor, null);
assertNotNull("No binding", bindings[0]);
assertEquals("Wrong type of binding", IBinding.TYPE, bindings[0].getKind());
ITypeBinding typeBinding = (ITypeBinding) bindings[0];
assertEquals("Wrong binding", "p.X", typeBinding.getQualifiedName());
assertNull("No java element", typeBinding.getJavaElement());
assertNotNull("No ast", units[0]);
assertEquals("No problem", 0, units[0].getProblems().length);
} finally {
file.delete();
fileY.delete();
}
}
public void test4() {
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
try {
parser.setEnvironment(null, null, new String[] {"UTF-8"}, true);
assertTrue("Should have failed", false);
} catch(IllegalArgumentException e) {
// ignore
}
}
public void test5() {
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
try {
parser.setEnvironment(null, new String[] {}, new String[] {"UTF-8"}, true);
assertTrue("Should have failed", false);
} catch(IllegalArgumentException e) {
// ignore
}
}
public void test6() throws IOException {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(getCompilerOptions());
final String key = "Lp/X;";
final IBinding[] bindings = new IBinding[2];
String contents =
"package p;\n" +
"public class X extends Y {\n" +
" public int i;\n" +
" public static void main(String[] args) {\n" +
" int length = args.length;\n" +
" System.out.println(length);\n" +
" }\n" +
"}";
File packageDir = new File(rootDir, "p");
packageDir.mkdir();
File file = new File(packageDir, "X.java");
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"package p;\n" +
"public class Y {}";
File fileY = new File(packageDir, "Y.java");
Writer writer2 = null;
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} finally {
if (writer2 != null) {
try {
writer2.close();
} catch(IOException e) {
// ignore
}
}
}
try {
final String canonicalPath = file.getCanonicalPath();
final CompilationUnit[] units = new CompilationUnit[1];
FileASTRequestor requestor = new FileASTRequestor() {
public void acceptBinding(String bindingKey, IBinding binding) {
if (key.equals(bindingKey)) {
bindings[0] = binding;
IBinding[] temp = createBindings(new String[] {"Ljava/lang/Object;"});
for (int i = 0; i < temp.length; ++i) {
bindings[i + 1] = temp[i];
}
}
}
public void acceptAST(String sourceFilePath, CompilationUnit ast) {
if (canonicalPath.equals(sourceFilePath)) {
units[0] = ast;
}
}
};
parser.setEnvironment(null, new String[] { rootDir.getCanonicalPath() }, null, true);
parser.createASTs(new String[] {canonicalPath}, null, new String[] {key}, requestor, null);
assertNotNull("No binding", bindings[0]);
assertEquals("Wrong type of binding", IBinding.TYPE, bindings[0].getKind());
ITypeBinding typeBinding = (ITypeBinding) bindings[0];
assertEquals("Wrong binding", "p.X", typeBinding.getQualifiedName());
assertNull("No java element", typeBinding.getJavaElement());
IPackageBinding packageBinding = typeBinding.getPackage();
assertNull("No java element", packageBinding.getJavaElement());
assertNotNull("No ast", units[0]);
assertEquals("No problem", 0, units[0].getProblems().length);
assertNotNull("No binding", bindings[1]);
assertEquals("Wrong type of binding", IBinding.TYPE, bindings[1].getKind());
typeBinding = (ITypeBinding) bindings[1];
assertEquals("Wrong binding", "java.lang.Object", typeBinding.getQualifiedName());
} finally {
file.delete();
fileY.delete();
}
}
/**
* @deprecated
* @throws IOException
*/
public void testBug415066_001() throws IOException {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(getCompilerOptions());
final String key = "Lp/C;";
final IBinding[] bindings = new IBinding[2];
String contents =
"package p;\n" +
"public class A{}\n" +
"class B{}";
File packageDir = new File(rootDir, "p");
packageDir.mkdir();
File file = new File(packageDir, "A.java");
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"package p;\n" +
"public class C extends B {}";
File fileY = new File(packageDir, "C.java");
Writer writer2 = null;
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} finally {
if (writer2 != null) {
try {
writer2.close();
} catch(IOException e) {
// ignore
}
}
}
try {
final String canonicalPath = fileY.getCanonicalPath();
final CompilationUnit[] units = new CompilationUnit[1];
FileASTRequestor requestor = new FileASTRequestor() {
public void acceptBinding(String bindingKey, IBinding binding) {
if (key.equals(bindingKey)) {
bindings[0] = binding;
IBinding[] temp = createBindings(new String[] {"Lp/C;"});
for (int i = 0; i < temp.length; ++i) {
bindings[i + 1] = temp[i];
}
}
}
public void acceptAST(String sourceFilePath, CompilationUnit ast) {
if (canonicalPath.equals(sourceFilePath)) {
units[0] = ast;
}
}
};
parser.setEnvironment(null, new String[] { rootDir.getCanonicalPath() }, null, true);
org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.MAX_AT_ONCE = 0;
parser.createASTs(new String[] {canonicalPath}, null, new String[] {key}, requestor, null);
assertNotNull("No ast", units[0]);
assertEquals("No problem", 0, units[0].getProblems().length);
} finally {
file.delete();
fileY.delete();
}
}
/**
* Negative test case
* @deprecated
* @throws IOException
*/
public void testBug415066_002() throws IOException {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setEnvironment(null, null, null, true);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(getCompilerOptions());
final String key = "Lp/C;";
final IBinding[] bindings = new IBinding[2];
String contents =
"package p;\n" +
"public class A{}\n" +
"class B{}";
File packageDir = new File(rootDir, "p");
packageDir.mkdir();
File file = new File(packageDir, "A.java");
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"package q;\n" +
"import p.*;\n" +
"public class C extends B {}";
File fileY = new File(packageDir, "C.java");
Writer writer2 = null;
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} finally {
if (writer2 != null) {
try {
writer2.close();
} catch(IOException e) {
// ignore
}
}
}
try {
final String canonicalPath = fileY.getCanonicalPath();
final CompilationUnit[] units = new CompilationUnit[1];
FileASTRequestor requestor = new FileASTRequestor() {
public void acceptBinding(String bindingKey, IBinding binding) {
if (key.equals(bindingKey)) {
bindings[0] = binding;
IBinding[] temp = createBindings(new String[] {"Lq/C;"});
for (int i = 0; i < temp.length; ++i) {
bindings[i + 1] = temp[i];
}
}
}
public void acceptAST(String sourceFilePath, CompilationUnit ast) {
if (canonicalPath.equals(sourceFilePath)) {
units[0] = ast;
}
}
};
parser.setEnvironment(null, new String[] { rootDir.getCanonicalPath() }, null, true);
parser.createASTs(new String[] {canonicalPath}, null, new String[] {key}, requestor, null);
assertNotNull("No ast", units[0]);
IProblem[] problems = units[0].getProblems();
assertEquals("No problem", 1, problems.length);
assertEquals("Pb(3) The type B is not visible", problems[0].toString());
} finally {
file.delete();
fileY.delete();
}
}
public void test7() throws IOException {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
String contents =
"enum X {\n" +
" /** */\n" +
" FOO\n" +
"}";
File file = new File(rootDir, "X.java");
Writer writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"package p;\n" +
"class Y {}";
File packageDir = new File(rootDir, "p");
packageDir.mkdir();
File fileY = new File(packageDir, "Y.java");
Writer writer2 = null;
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} finally {
if (writer2 != null) {
try {
writer2.close();
} catch(IOException e) {
// ignore
}
}
}
try {
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setCompilerOptions(JavaCore.getOptions());
parser.createASTs(
new String[] { file.getCanonicalPath(), fileY.getCanonicalPath() },
null,
new String[] {},
new FileASTRequestor() {},
null);
} finally {
file.delete();
fileY.delete();
}
}
public void testBug461250() {
String source =
"class QH<T> implements QR.Q {\n" +
" QR.Q q;\n" +
" @V(v = A, d = \"\") Map p;\n" +
"}\n";
Map<String, String> options = JavaCore.getOptions();
JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
ASTParser parser = ASTParser.newParser(AST_JLS_LATEST);
parser.setCompilerOptions(options);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(source.toCharArray());
parser.setResolveBindings(true);
String[] emptyStringArray = new String[0];
parser.setEnvironment(emptyStringArray, emptyStringArray, emptyStringArray, true /* includeRunningVMBootclasspath */);
parser.setUnitName("dontCare");
ASTNode ast = parser.createAST(null);
assertTrue("should have parsed a CUD", ast instanceof CompilationUnit);
}
public void testBug465048() {
String source =
"class A {\n" +
" void f(OtherClass otherClass) {\n" +
" synchronized (otherClass) {\n" +
" Class c = InnerClass.class;\n" + // Line = 4
" }\n" +
" }\n" +
" class InnerClass { }\n" +
"}\n";
Map<String, String> options = JavaCore.getOptions();
JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
ASTParser parser = ASTParser.newParser(AST.JLS9);
parser.setCompilerOptions(options);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(source.toCharArray());
parser.setResolveBindings(true);
String[] emptyStringArray = new String[0];
parser.setEnvironment(emptyStringArray, emptyStringArray, emptyStringArray,
true /* includeRunningVMBootclasspath */);
parser.setUnitName("dontCare");
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
SimpleName innerClassLiteral = (SimpleName) NodeFinder.perform(cu, cu.getPosition(4, 16), 1 /* length */);
ITypeBinding innerClassBinding = (ITypeBinding) innerClassLiteral.resolveBinding();
assertEquals("InnerClass", innerClassBinding.getName());
}
/**
* Verifies that ASTParser doesn't throw an IllegalArgumentException when given
* this valid input.
*/
public void testBug480545() {
String input = "class Test2 { void f(Test2... xs) {} }";
ASTParser parser = ASTParser.newParser(AST.JLS9);
parser.setSource(input.toCharArray());
Map<String, String> options = JavaCore.getOptions();
JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
parser.setCompilerOptions(options);
assertNotNull(parser.createAST(null));
}
public void testBug493336_001() {
String input = "public class X implements á¼³ {\n" +
" public static final class if {\n"+
" public static final if ËŠ = new if(null, null, null, null);\n"+
" }\n" +
"}";
ASTParser parser = ASTParser.newParser(AST.JLS9);
parser.setSource(input.toCharArray());
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setEnvironment(null, new String[] {null}, null, true);
Hashtable<String, String> options1 = JavaCore.getDefaultOptions();
options1.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
options1.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
options1.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
parser.setCompilerOptions(options1);
assertNotNull(parser.createAST(null));
}
public void testBug526996_001() {
File rootDir = new File(System.getProperty("java.io.tmpdir"));
String contents =
"public class X {\n" +
" public X() {\n" +
" this.f16132b =\n" +
"/*\n" +
" at jadx.api.JavaClass.decompile(JavaClass.java:62)\n" +
"*/\n" +
"\n" +
" /* JADX WARNING: inconsistent code. */\n" +
" /* Code decompiled incorrectly, please refer to instructions dump. */\n" +
" public final C1984r m22030a() {\n" +
" }\n" +
" }\n" +
"\n";
File file = new File(rootDir, "X.java");
Writer writer = null;
try {
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(contents);
} catch (IOException e1) {
// ignore
}
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
// ignore
}
}
}
String contents2 =
"public class Y {\n" +
"\n" +
" /* JADX WARNING: inconsistent code. */\n" +
" protected void finalize() {\n" +
" for (i =\n" +
"/*\n" +
" at jadx.core.codegen.InsnGen.makeInsn(InsnGen.java:220)\n" +
"*/\n" +
" public void close() { }\n" +
" }\n" ;
File fileY = new File(rootDir, "Y.java");
Writer writer2 = null;
try {
try {
writer2 = new BufferedWriter(new FileWriter(fileY));
writer2.write(contents2);
} catch (IOException e) {
// ignore
}
} finally {
try {
if (writer2 != null) writer2.close();
} catch(IOException e) {
// ignore
}
}
try {
final FileASTRequestor astRequestor = new FileASTRequestor() {
@Override
public void acceptAST(String sourceFilePath, CompilationUnit ast) {
super.acceptAST(sourceFilePath, ast);
System.out.println(sourceFilePath);
}
};
ASTParser parser = ASTParser.newParser(AST.JLS9);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
parser.setBindingsRecovery(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setEnvironment(new String[0], new String[] { rootDir.getAbsolutePath() }, null, true);
String[] files = null;
try {
files = new String[] {file.getCanonicalPath(), fileY.getCanonicalPath()};
System.out.println("Building...");
parser.createASTs(files,
null,
new String[0],
astRequestor,
null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} finally {
file.delete();
fileY.delete();
}
}
}