blob: 7c4952b32a58c0fdf24a5f46688e094f22bc87b3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2020 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.ui.tests.core;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Hashtable;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.eclipse.jdt.testplugin.JavaProjectHelper;
import org.eclipse.jdt.testplugin.TestOptions;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Assignment;
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.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup;
import org.eclipse.jdt.internal.ui.JavaPlugin;
public class PartialASTTest extends CoreTests {
@Rule
public ProjectTestSetup pts= new ProjectTestSetup();
private IJavaProject fJProject1;
private IPackageFragmentRoot fSourceFolder;
@Before
public void setUp() throws Exception {
Hashtable<String, String> options= TestOptions.getDefaultOptions();
options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4");
JavaCore.setOptions(options);
IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
store.setValue(PreferenceConstants.CODEGEN_ADD_COMMENTS, false);
fJProject1= pts.getProject();
fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src");
}
@After
public void tearDown() throws Exception {
JavaProjectHelper.clear(fJProject1, pts.getDefaultClasspath());
}
@Test
public void testPartialCU1() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("public class E {\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
String statement= "fField1 = fField2;";
int offset= existing.indexOf(statement);
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("public class E {\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
offset= expected.indexOf(statement);
ASTNode node= NodeFinder.perform(astRoot, offset, statement.length());
Assignment assignment= (Assignment) ((ExpressionStatement) node).getExpression();
Expression e1= assignment.getLeftHandSide();
Expression e2= assignment.getRightHandSide();
assertNotNull(e1.resolveTypeBinding());
assertNotNull(e2.resolveTypeBinding());
assertTrue(((SimpleName) e1).resolveBinding() instanceof IVariableBinding);
assertTrue(((SimpleName) e2).resolveBinding() instanceof IVariableBinding);
assertAllBindings(astRoot);
}
private void assertAllBindings(CompilationUnit astRoot) {
List<AbstractTypeDeclaration> list= astRoot.types();
for (AbstractTypeDeclaration element : list) {
TypeDeclaration decl= (TypeDeclaration) element;
assertNotNull(decl.resolveBinding());
if (!decl.isInterface() && decl.getSuperclassType() != null) {
assertNotNull(decl.getSuperclassType().resolveBinding());
}
List<Type> interfaces= decl.superInterfaceTypes();
for (Type interface1 : interfaces) {
assertNotNull(interface1.resolveBinding());
}
for (MethodDeclaration meth : decl.getMethods()) {
assertNotNull(meth.resolveBinding());
List<SingleVariableDeclaration> params= meth.parameters();
for (SingleVariableDeclaration arg : params) {
assertNotNull(arg.resolveBinding());
}
if (!meth.isConstructor()) {
assertNotNull(meth.getReturnType2().resolveBinding());
}
}
}
}
@Test
public void testPartialCU2() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" public int local(int i) {\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
int offset= existing.indexOf("fField1 = fField2;");
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
assertAllBindings(astRoot);
}
@Test
public void testPartialCU3() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.Serializable;\n");
buf.append("public class E {\n");
buf.append(" private class EInner implements Serializable {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
int offset= existing.indexOf("return 1;");
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.Serializable;\n");
buf.append("public class E {\n");
buf.append(" private class EInner implements Serializable {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() {\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
assertAllBindings(astRoot);
}
@Test
public void testPartialCU4() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" return 0;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
int offset= existing.indexOf("return 0;");
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" return 0;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" }\n");
buf.append(" public int foo1(int i) {\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
assertAllBindings(astRoot);
}
@Test
public void testPartialCUPositionNotInMethod1() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" return 0;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo2(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
int offset= existing.indexOf("private int fField1;");
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" public int inner(int i) {\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" }\n");
buf.append(" public int foo2(int i) {\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
assertAllBindings(astRoot);
}
@Test
public void testPartialCUPositionNotInMethod2() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" {\n");
buf.append(" System.out.println();\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" fField1 = fField2;\n");
buf.append(" if (fField1 == 0) {\n");
buf.append(" fField2++;\n");
buf.append(" }\n");
buf.append(" EInner inner = new EInner();\n");
buf.append(" }\n");
buf.append(" public int foo2(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" private int fField3;\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String existing= buf.toString();
ICompilationUnit cu= pack1.createCompilationUnit("E.java", existing, false, null);
int offset= existing.indexOf("private int fField3;");
CompilationUnit astRoot= getPartialCompilationUnit(cu, offset);
String string= ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null);
buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("import java.util.Vector;\n");
buf.append("import java.io.IOException;\n");
buf.append("import java.text.ParseException;\n");
buf.append("public class E {\n");
buf.append(" private class EInner {\n");
buf.append(" {\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" private int fField1;\n");
buf.append(" private int fField2;\n");
buf.append(" public void foo1() throws IOException, ParseException {\n");
buf.append(" }\n");
buf.append(" public int foo2(int i) {\n");
buf.append(" private class Local {\n");
buf.append(" private int fField3;\n");
buf.append(" public int local(int i) {\n");
buf.append(" return 1;\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" Local local = new Local();\n");
buf.append(" return i;\n");
buf.append(" }\n");
buf.append("}");
String expected= buf.toString();
assertEqualString(string, expected);
assertAllBindings(astRoot);
}
private CompilationUnit getPartialCompilationUnit(ICompilationUnit cu, int offset) {
ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
p.setSource(cu);
p.setFocalPosition(offset);
p.setResolveBindings(true);
return (CompilationUnit) p.createAST(null);
}
/*
private static class PartialVisitor extends ASTVisitor {
private int fOffset;
public PartialVisitor(int offset) {
fOffset= offset;
}
public boolean visit(Block node) {
ASTNode parent= node.getParent();
if (parent instanceof MethodDeclaration || parent instanceof Initializer) {
int start= node.getStartPosition();
int end= start + node.getLength();
if (start <= fOffset && fOffset < end) {
return true;
}
node.statements().clear();
return false;
}
return true;
}
}*/
}