blob: 33d3114fb2b62bde7ea6127238b6b610936e8f12 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 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
* Technical University Berlin - adapted for Object Teams
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import junit.framework.Test;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CompilationParticipant;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.ReconcileContext;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
public class ReconcilerTests extends ModifyingResourceTests {
protected ICompilationUnit workingCopy;
protected ProblemRequestor problemRequestor;
/* A problem requestor that auto-cancels on first problem */
static class CancelingProblemRequestor extends ProblemRequestor {
IProgressMonitor progressMonitor = new IProgressMonitor() {
boolean isCanceled = false;
public void beginTask(String name, int totalWork) {}
public void done() {}
public void internalWorked(double work) {}
public boolean isCanceled() {
return this.isCanceled;
}
public void setCanceled(boolean value) {
this.isCanceled = value;
}
public void setTaskName(String name) {}
public void subTask(String name) {}
public void worked(int work) {}
};
boolean isCanceling = false;
public void acceptProblem(IProblem problem) {
if (this.isCanceling) this.progressMonitor.setCanceled(true); // auto-cancel on first problem
super.acceptProblem(problem);
}
}
static class ReconcileParticipant extends CompilationParticipant {
IJavaElementDelta delta;
org.eclipse.jdt.core.dom.CompilationUnit ast;
ReconcileParticipant() {
TestCompilationParticipant.PARTICIPANT = this;
}
public boolean isActive(IJavaProject project) {
return true;
}
public void reconcile(ReconcileContext context) {
this.delta = context.getDelta();
try {
this.ast = context.getAST3();
} catch (JavaModelException e) {
assertNull("Unexpected exception", e);
}
}
}
static class ReconcileParticipant2 extends CompilationParticipant {
IJavaElementDelta delta;
org.eclipse.jdt.core.dom.CompilationUnit ast;
ReconcileParticipant2() {
TestCompilationParticipant.PARTICIPANT = this;
}
public boolean isActive(IJavaProject project) {
return true;
}
public void reconcile(ReconcileContext context) {
this.delta = context.getDelta();
try {
this.ast = context.getAST3();
assertTrue("Context should have statement recovery enabled", (context.getReconcileFlags() & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
assertTrue("Context should have ignore method body enabled", (context.getReconcileFlags() & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
} catch (JavaModelException e) {
assertNull("Unexpected exception", e);
}
}
}
static class ReconcileParticipant3 extends CompilationParticipant {
IJavaElementDelta delta;
org.eclipse.jdt.core.dom.CompilationUnit ast;
ReconcileParticipant3() {
TestCompilationParticipant.PARTICIPANT = this;
}
public boolean isActive(IJavaProject project) {
return true;
}
public void reconcile(ReconcileContext context) {
this.delta = context.getDelta();
try {
this.ast = context.getAST3();
assertFalse("Context should have statement recovery enabled", (context.getReconcileFlags() & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
assertTrue("Context should have ignore method body enabled", (context.getReconcileFlags() & ICompilationUnit.IGNORE_METHOD_BODIES) != 0);
} catch (JavaModelException e) {
assertNull("Unexpected exception", e);
}
}
}
/**
*/
public ReconcilerTests(String name) {
super(name);
}
// Use this static initializer to specify subset for tests
// All specified tests which do not belong to the class are skipped...
static {
// JavaModelManager.VERBOSE = true;
// org.eclipse.jdt.internal.core.search.BasicSearchEngine.VERBOSE = true;
// TESTS_PREFIX = "testIgnoreIfBetterNonAccessibleRule";
// TESTS_NAMES = new String[] { "testIgnoreMethodBodies1", "testIgnoreMethodBodies2" };
// TESTS_NUMBERS = new int[] { 118823 };
// TESTS_RANGE = new int[] { 16, -1 };
}
public static Test suite() {
return buildModelTestSuite(ReconcilerTests.class);
}
protected void assertProblems(String message, String expected) {
assertProblems(message, expected, this.problemRequestor);
}
protected void assertProblemsInclude(String message, String expected) {
String actual = org.eclipse.jdt.core.tests.util.Util.convertToIndependantLineDelimiter(this.problemRequestor.problems.toString());
String independantExpectedString = org.eclipse.jdt.core.tests.util.Util.convertToIndependantLineDelimiter(expected);
if (actual.indexOf(independantExpectedString) == -1){
System.out.println(org.eclipse.jdt.core.tests.util.Util.displayString(actual, this.tabs));
assertEquals(
message,
independantExpectedString,
actual);
}
}
// Expect no error as soon as indexing is finished
protected void assertNoProblem(char[] source, ICompilationUnit unit) throws InterruptedException, JavaModelException {
IndexManager indexManager = JavaModelManager.getIndexManager();
if (this.problemRequestor.problemCount > 0) {
// If errors then wait for indexes to finish
while (indexManager.awaitingJobsCount() > 0) {
Thread.sleep(100);
}
// Reconcile again to see if error goes away
this.problemRequestor.initialize(source);
unit.getBuffer().setContents(source); // need to set contents again to be sure that following reconcile will be really done
unit.reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
if (this.problemRequestor.problemCount > 0) {
assertEquals("Working copy should NOT have any problem!", "", this.problemRequestor.problems.toString());
}
}
}
protected void addClasspathEntries(IClasspathEntry[] entries, boolean enableForbiddenReferences) throws JavaModelException {
IJavaProject project = getJavaProject("Reconciler");
IClasspathEntry[] oldClasspath = project.getRawClasspath();
int oldLength = oldClasspath.length;
int length = entries.length;
IClasspathEntry[] newClasspath = new IClasspathEntry[oldLength+length];
System.arraycopy(oldClasspath, 0, newClasspath, 0, oldLength);
System.arraycopy(entries, 0, newClasspath, oldLength, length);
project.setRawClasspath(newClasspath, null);
if (enableForbiddenReferences) {
project.setOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, JavaCore.ERROR);
}
}
protected void removeClasspathEntries(IClasspathEntry[] entries) throws JavaModelException {
IJavaProject project = getJavaProject("Reconciler");
IClasspathEntry[] oldClasspath = project.getRawClasspath();
int oldLength = oldClasspath.length;
int length = entries.length;
IClasspathEntry[] newClasspath = new IClasspathEntry[oldLength-length];
System.arraycopy(oldClasspath, 0, newClasspath, 0, oldLength-length);
project.setRawClasspath(newClasspath, null);
}
/**
* Setup for the next test.
*/
public void setUp() throws Exception {
super.setUp();
this.problemRequestor = new ProblemRequestor();
this.wcOwner = new WorkingCopyOwner() {
public IProblemRequestor getProblemRequestor(ICompilationUnit unit) {
return ReconcilerTests.this.problemRequestor;
}
};
this.workingCopy = getCompilationUnit("Reconciler/src/p1/X.java").getWorkingCopy(this.wcOwner, null);
this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray());
startDeltas();
}
public void setUpSuite() throws Exception {
super.setUpSuite();
// Create project with 1.4 compliance
IJavaProject project14 = createJavaProject("Reconciler", new String[] {"src"}, new String[] {"JCL_LIB"}, "bin");
createFolder("/Reconciler/src/p1");
createFolder("/Reconciler/src/p2");
createFile(
"/Reconciler/src/p1/X.java",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
project14.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_4);
project14.setOption(JavaCore.COMPILER_PB_UNUSED_LOCAL, JavaCore.IGNORE);
project14.setOption(JavaCore.COMPILER_PB_INVALID_JAVADOC, JavaCore.WARNING);
// Create project with 1.5 compliance
IJavaProject project15 = createJavaProject("Reconciler15", new String[] {"src"}, new String[] {"JCL15_LIB"}, "bin", "1.5");
addLibrary(
project15,
"lib15.jar",
"lib15src.zip",
new String[] {
"java/util/List.java",
"package java.util;\n" +
"public class List<T> {\n" +
"}",
"java/util/Stack.java",
"package java.util;\n" +
"public class Stack<T> {\n" +
"}",
"java/util/Map.java",
"package java.util;\n" +
"public interface Map<K,V> {\n" +
"}",
"java/lang/annotation/Annotation.java",
"package java.lang.annotation;\n" +
"public interface Annotation {\n" +
"}",
"java/lang/Deprecated.java",
"package java.lang;\n" +
"public @interface Deprecated {\n" +
"}",
"java/lang/SuppressWarnings.java",
"package java.lang;\n" +
"public @interface SuppressWarnings {\n" +
" String[] value();\n" +
"}"
},
JavaCore.VERSION_1_5
);
project15.setOption(JavaCore.COMPILER_PB_UNUSED_LOCAL, JavaCore.IGNORE);
project15.setOption(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE, JavaCore.IGNORE);
}
private void setUp15WorkingCopy() throws JavaModelException {
setUp15WorkingCopy("Reconciler15/src/p1/X.java", this.wcOwner);
}
private void setUp15WorkingCopy(String path, WorkingCopyOwner owner) throws JavaModelException {
String contents = this.workingCopy.getSource();
setUpWorkingCopy(path, contents, owner);
}
private void setUpWorkingCopy(String path, String contents) throws JavaModelException {
setUpWorkingCopy(path, contents, this.wcOwner);
}
private void setUpWorkingCopy(String path, String contents, WorkingCopyOwner owner) throws JavaModelException {
this.workingCopy.discardWorkingCopy();
this.workingCopy = getCompilationUnit(path).getWorkingCopy(owner, null);
assertEquals("Invalid problem requestor!", this.problemRequestor, this.wcOwner.getProblemRequestor(this.workingCopy));
setWorkingCopyContents(contents);
this.workingCopy.makeConsistent(null);
}
void setWorkingCopyContents(String contents) throws JavaModelException {
this.workingCopy.getBuffer().setContents(contents);
this.problemRequestor.initialize(contents.toCharArray());
}
/**
* Cleanup after the previous test.
*/
public void tearDown() throws Exception {
TestCompilationParticipant.PARTICIPANT = null;
if (this.workingCopy != null) {
this.workingCopy.discardWorkingCopy();
}
stopDeltas();
super.tearDown();
}
public void tearDownSuite() throws Exception {
deleteProject("Reconciler");
deleteProject("Reconciler15");
super.tearDownSuite();
}
/*
* Ensures that no problem is created for a reference to a type that is included in a prereq project.
*/
public void testAccessRestriction() throws CoreException {
try {
createJavaProject("P1", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[0], null, null, new boolean[0], "bin", null, new String[][] {{"**/X.java"}}, null, "1.4");
createFolder("/P1/src/p");
createFile("/P1/src/p/X.java", "package p; public class X {}");
createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
setUpWorkingCopy("/P2/src/Y.java", "public class Y extends p.X {}");
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/*
* Ensures that no problem is created for a reference to a binary type that is included in a prereq project.
* (regression test for bug 82542 Internal error during AST creation)
*/
public void testAccessRestriction2() throws CoreException, IOException {
try {
IJavaProject project = createJavaProject("P1");
addLibrary(
project,
"lib.jar",
"libsrc.zip",
new String[] {
"p/X.java",
"package p;\n" +
"public class X {\n" +
"}",
},
null/*no non-Java resources*/,
new String[] {
"**/*"
},
null,
"1.4"
);
createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
setUpWorkingCopy("/P2/src/Y.java", "public class Y extends p.X {}");
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/*
* Ensures that no problem is created for a reference to a type that is included and not exported in a prereq project
* but with combineAccessRestriction flag set to false.
*/
public void testAccessRestriction3() throws CoreException {
try {
createJavaProject("P1");
createFolder("/P1/p");
createFile("/P1/p/X.java", "package p; public class X {}");
createJavaProject("P2", new String[] {}, new String[] {}, null, null, new String[] {"/P1"}, null, null, new boolean[] {true}, "", null, null, null, "1.4");
createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, false/*don't combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4", false/*don't import*/);
setUpWorkingCopy("/P3/src/Y.java", "public class Y extends p.X {}");
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteProjects(new String[] {"P1", "P2", "P3" });
}
}
/*
* Ensures that a problem is created for a reference to a type that is included and not exported in a prereq project
* but with combineAccessRestriction flag set to true.
*/
public void testAccessRestriction4() throws CoreException {
try {
createJavaProject("P1");
createFolder("/P1/p");
createFile("/P1/p/X.java", "package p; public class X {}");
createJavaProject("P2", new String[] {}, new String[] {}, null, null, new String[] {"/P1"}, null, null, new boolean[] {true}, "", null, null, null, "1.4");
createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, true/*combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4", false/*don't import*/);
setUpWorkingCopy("/P3/src/Y.java", "public class Y extends p.X {}");
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /P3/src/Y.java (at line 1)\n" +
" public class Y extends p.X {}\n" +
" ^^^\n" +
"Access restriction: The type X is not accessible due to restriction on required project P1\n" +
"----------\n"
);
} finally {
deleteProjects(new String[] {"P1", "P2", "P3" });
}
}
/*
* Ensures that a problem is created for a reference to a type that is no longer accessible in a prereq project.
* (regression test for bug 91498 Reconcile still sees old access rules)
*/
public void testAccessRestriction5() throws CoreException {
try {
createJavaProject("P1");
createFolder("/P1/p");
createFile("/P1/p/X.java", "package p; public class X {}");
IJavaProject p2 = createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, "bin");
IClasspathEntry[] classpath = p2.getRawClasspath();
int length = classpath.length;
System.arraycopy(classpath, 0, classpath = new IClasspathEntry[length+1], 0, length);
classpath[length] = createSourceEntry("P2", "/P1", "+**/p/|-**/*");
p2.setRawClasspath(classpath, null);
setUpWorkingCopy("/P2/src/Y.java", "public class Y extends p.X {}");
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
// remove accessible rule
System.arraycopy(classpath, 0, classpath = new IClasspathEntry[length+1], 0, length);
classpath[length] = createSourceEntry("P2", "/P1", "-**/*");
p2.setRawClasspath(classpath, null);
this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force problem detection*/, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /P2/src/Y.java (at line 1)\n" +
" public class Y extends p.X {}\n" +
" ^^^\n" +
"Access restriction: The type X is not accessible due to restriction on required project P1\n" +
"----------\n"
);
} finally {
deleteProjects(new String[] {"P1", "P2"});
}
}
/**
* Ensures that the reconciler handles duplicate members correctly.
*/
public void testAddDuplicateMember() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()#2[+]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a field and a constructor.
*/
public void testAddFieldAndConstructor() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" int i;\n" +
" X(int i) {\n" +
" this.i = i;\n" +
" }\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" X(int)[+]: {}\n" +
" i[+]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a field and a constructor.
*/
public void testAddImports() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"import java.lang.reflect.*;\n" +
"import java.util.Vector;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"<import container>[*]: {CHILDREN | FINE GRAINED}\n" +
" import java.lang.reflect.*[+]: {}\n" +
" import java.util.Vector[+]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a method.
*/
public void testAddMethod1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
" public void bar() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a portion of a new method.
*/
public void testAddPartialMethod1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void some()\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" some()[+]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a portion of a new method. Ensures that when a
* second part is added to the new method no structural changes are recognized.
*/
public void testAddPartialMethod1and2() throws JavaModelException {
// Add partial method before foo
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void some()\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// Add { on partial method
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void some() {\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"[Working copy] X.java[*]: {CONTENT | FINE GRAINED}"
);
}
/*
* Ensures that the delta is correct when adding an annotation
*/
public void testAnnotations1() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {ANNOTATIONS}\n" +
" @MyAnnot[+]: {}"
);
}
/*
* Ensures that the delta is correct when removing an annotation
*/
public void testAnnotations2() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {ANNOTATIONS}\n" +
" @MyAnnot[-]: {}"
);
}
/*
* Ensures that the delta is correct when changing an annotation
*/
public void testAnnotations3() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot(x=1)\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot(y=1)\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {ANNOTATIONS}\n" +
" @MyAnnot[*]: {CONTENT}"
);
}
/*
* Ensures that the delta is correct when changing an annotation
*/
public void testAnnotations4() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot(x=1)\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" @MyAnnot(x=2)\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {ANNOTATIONS}\n" +
" @MyAnnot[*]: {CONTENT}"
);
}
/*
* Ensures that no error is reported if an annotation type's cu starts with a slash
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=214450 )
*/
public void testAnnotations5() throws JavaModelException {
ICompilationUnit annotation = null;
try {
setUp15WorkingCopy();
annotation = getWorkingCopy(
"Reconciler15/src/p1/MyAnnot2.java",
"/* test */\n" +
"package p1;\n" +
"public @interface MyAnnot2 {\n" +
" String bar();\n" +
"}",
this.wcOwner);
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" @MyAnnot2(bar=\"a\")\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (annotation != null)
annotation.discardWorkingCopy();
}
}
/*
* Ensures that the AST broadcasted during a reconcile operation is correct.
* (case of a working copy being reconciled with changes, creating AST and no problem detection)
*/
public void testBroadcastAST1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(AST.JLS3, false/*don't force problem detection*/, null/*primary owner*/, null/*no progress*/);
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}\n",
this.deltaListener.getCompilationUnitAST(this.workingCopy));
}
/*
* Ensures that the AST broadcasted during a reconcile operation is correct.
* (case of a working copy being reconciled with NO changes, creating AST and forcing problem detection)
*/
public void testBroadcastAST2() throws JavaModelException {
this.workingCopy.reconcile(AST.JLS3, true/*force problem detection*/, null/*primary owner*/, null/*no progress*/);
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo(){\n" +
" }\n" +
"}\n",
this.deltaListener.getCompilationUnitAST(this.workingCopy));
}
/*
* Ensures that no AST is broadcasted during a reconcile operation if the working copy being reconciled
* has NO changes and NO problem detection is requested)
*/
public void testBroadcastAST3() throws JavaModelException {
this.workingCopy.reconcile(AST.JLS3, false/*don't force problem detection*/, null/*primary owner*/, null/*no progress*/);
assertASTNodeEquals(
"Unexpected ast",
"null",
this.deltaListener.getCompilationUnitAST(this.workingCopy));
}
/*
* Ensures that the AST broadcasted during a reconcile operation is correct.
* (case of a working copy being reconciled twice in a batch operation)
*/
public void testBroadcastAST4() throws CoreException {
JavaCore.run(
new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
ReconcilerTests.this.workingCopy.reconcile(AST.JLS3, true/*force problem detection*/, null/*primary owner*/, monitor);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}");
ReconcilerTests.this.workingCopy.reconcile(AST.JLS3, false/*don't force problem detection*/, null/*primary owner*/, monitor);
}
},
null/*no progress*/);
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}\n",
this.deltaListener.getCompilationUnitAST(this.workingCopy));
}
/*
* Ensures that the AST broadcasted doesn't have a type root that is caching its contents
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=222213 )
*/
public void testBroadcastAST5() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(AST.JLS3, false/*don't force problem detection*/, null/*primary owner*/, null/*no progress*/);
org.eclipse.jdt.core.dom.CompilationUnit compilationUnit = this.deltaListener.getCompilationUnitAST(this.workingCopy);
String newContents =
"package p1;\n" +
"public class X {\n" +
"}";
setWorkingCopyContents(newContents);
org.eclipse.jdt.internal.compiler.env.ICompilationUnit compilerCU = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnit.getTypeRoot();
assertSourceEquals("Unexpected contents", newContents, new String(compilerCU.getContents()));
}
/*
* Ensures that reconciling a subclass doesn't close the buffer while resolving its superclass.
* (regression test for bug 62854 refactoring does not trigger reconcile)
*/
public void testBufferOpenAfterReconcile() throws CoreException {
try {
createFile(
"/Reconciler/src/p1/Super.java",
"package p1;\n" +
"public class Super {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X extends Super {\n" +
" public void foo() {\n" +
" }\n" +
"}");
IBuffer buffer = this.workingCopy.getBuffer();
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertTrue("Buffer should still be open", !buffer.isClosed());
} finally {
deleteFile("/Reconciler/src/p1/Super.java");
}
}
/*
* Ensures that reconciling with a closed buffer reports an error
* (regression test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=138882 )
*/
public void testBufferClosed1() throws CoreException {
this.wcOwner = new WorkingCopyOwner() {
public IBuffer createBuffer(ICompilationUnit copy) {
return new TestBuffer(copy);
}
public IProblemRequestor getProblemRequestor(ICompilationUnit unit) {
return ReconcilerTests.this.problemRequestor;
}
};
setUpWorkingCopy(
"Reconciler/src/p1/X.java",
"package p1;\n" +
"public class X {\n" +
" void foo(String s) {\n" +
" }\n" +
"}"
);
// simulate buffer being closed
((TestBuffer) this.workingCopy.getBuffer()).contents = null;
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblemsInclude(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 1)\n" +
" package p1;\n" +
" ^\n" +
"Cannot read the source from /Reconciler/src/p1/X.java due to internal exception java.io.IOException:Buffer is closed\n" +
"----------\n"
);
}
/*
* Ensures that reconciling with a closed buffer reports an error
* (regression test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=138882 )
*/
public void testBufferClosed2() throws CoreException {
this.wcOwner = new WorkingCopyOwner() {
public IBuffer createBuffer(ICompilationUnit copy) {
return new TestBuffer(copy);
}
public IProblemRequestor getProblemRequestor(ICompilationUnit unit) {
return ReconcilerTests.this.problemRequestor;
}
};
setUpWorkingCopy(
"Reconciler/src/p1/X.java",
"package p1;\n" +
"public class X {\n" +
" void foo(String s) {\n" +
" }\n" +
"}"
);
// make the working copy not consistent
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
"}"
);
// simulate buffer being closed
((TestBuffer) this.workingCopy.getBuffer()).contents = null;
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblemsInclude(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 1)\n" +
" package p1;\n" +
" ^\n" +
"Cannot read the source from /Reconciler/src/p1/X.java due to internal exception java.io.IOException:Buffer is closed\n" +
"----------\n"
);
}
/**
* Ensure an OperationCanceledException is correcly thrown when progress monitor is canceled
* @deprecated using deprecated code
*/
public void testCancel() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" void foo(String s) {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
// count the number of time isCanceled() is called when converting this source unit
CancelCounter counter = new CancelCounter();
this.workingCopy.reconcile(AST.JLS2, true, null, counter);
// throw an OperatonCanceledException at each point isCanceled() is called
for (int i = 0; i < counter.count; i++) {
boolean gotException = false;
try {
this.workingCopy.reconcile(AST.JLS2, true, null, new Canceler(i));
} catch (OperationCanceledException e) {
gotException = true;
}
assertTrue("Should get an OperationCanceledException (" + i + ")", gotException);
}
// last should not throw an OperationCanceledException
this.workingCopy.reconcile(AST.JLS2, true, null, new Canceler(counter.count));
}
/**
* Ensures that the delta is correct when adding a category
*/
public void testCategories1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat1\n" +
" */\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {CATEGORIES}"
);
}
/**
* Ensures that the delta is correct when removing a category
*/
public void testCategories2() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat1\n" +
" */\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {CATEGORIES}"
);
}
/**
* Ensures that the delta is correct when changing a category
*/
public void testCategories3() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat1\n" +
" */\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat2\n" +
" */\n" +
" public void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {CATEGORIES}"
);
}
/*
* Ensures that the delta is correct when adding a category to a second field
* (regression test for bug 125675 @category not reflected in outliner in live fashion)
*/
public void testCategories4() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat1\n" +
" */\n" +
" int f1;\n" +
" int f2;\n" +
"}"
);
this.workingCopy.makeConsistent(null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" /**\n" +
" * @category cat1\n" +
" */\n" +
" int f1;\n" +
" /**\n" +
" * @category cat2\n" +
" */\n" +
" int f2;\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" f2[*]: {CATEGORIES}"
);
}
/*
* Ensures that changing the source level to make a type valid doesn't report an error any longer
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568 )
*/
public void testChangeSourceLevel1() throws Exception {
try {
IJavaProject p = createJavaProject("P1", new String[] {"src"}, new String[] {"JCL15_LIB", "/P1/lib.jar"}, "bin", "1.5");
Util.createJar(new String[] {
"p/enum/X.java",
"package p.enum;\n" +
"public class X{\n" +
"}"
},
p.getProject().getLocation().append("lib.jar").toOSString(),
"1.3");
refresh(p);
setUpWorkingCopy(
"/P1/src/p1/X.java",
"package p1;\n" +
"public class X {\n" +
" p.enum.X field;\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
/* At this point, the following error is reported:
"----------\n" +
"1. ERROR in /P1/src/p1/X.java (at line 3)\n" +
" p.enum.X field;\n" +
" ^^^^\n" +
"Syntax error on token \"enum\", Identifier expected\n" +
"----------\n"
*/
this.problemRequestor.reset();
p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_3);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force problem detection*/, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /P1/src/p1/X.java (at line 3)\n" +
" p.enum.X field;\n" +
" ^^^^\n" +
"\'enum\' should not be used as an identifier, since it is a reserved keyword from source level 1.5 on\n" +
"----------\n"
);
} finally {
deleteProject("P1");
}
}
/*
* Ensures that changing the source level to make a type valid doesn't report an error any longer
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568 )
*/
public void testChangeSourceLevel2() throws Exception {
Hashtable defaultOptions = null;
try {
defaultOptions = JavaCore.getOptions();
Hashtable newOptions = new Hashtable();
newOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
JavaCore.setOptions(newOptions);
IJavaProject p = createJavaProject("P1", new String[] {"src"}, new String[] {"JCL15_LIB", "/P1/lib.jar"}, "bin");
Util.createJar(new String[] {
"p/enum/X.java",
"package p.enum;\n" +
"public class X{\n" +
"}"
},
p.getProject().getLocation().append("lib.jar").toOSString(),
"1.3");
refresh(p);
setUpWorkingCopy(
"/P1/src/p1/X.java",
"package p1;\n" +
"public class X {\n" +
" p.enum.X field;\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
/* At this point, the following error is reported:
"----------\n" +
"1. ERROR in /P1/src/p1/X.java (at line 3)\n" +
" p.enum.X field;\n" +
" ^^^^\n" +
"Syntax error on token \"enum\", Identifier expected\n" +
"----------\n"
*/
this.problemRequestor.reset();
newOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_3);
JavaCore.setOptions(newOptions);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force problem detection*/, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /P1/src/p1/X.java (at line 3)\n" +
" p.enum.X field;\n" +
" ^^^^\n" +
"\'enum\' should not be used as an identifier, since it is a reserved keyword from source level 1.5 on\n" +
"----------\n"
);
} finally {
deleteProject("P1");
if (defaultOptions != null)
JavaCore.setOptions(defaultOptions);
}
}
/*
* Ensures that changing a binary folder used as class folder in 2 projects doesn't cause the old binary to be seen
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=210746 )
*/
public void testChangeClassFolder() throws CoreException {
try {
createJavaProject("P1", new String[] {"src"}, new String[] {"JCL_LIB"}, "bin");
createFolder("/P1/src/p");
createFile(
"/P1/src/p/X.java",
"package p;\n" +
"public class X {\n" +
"}"
);
getProject("P1").build(IncrementalProjectBuilder.FULL_BUILD, null);
createJavaProject("P2", new String[0], new String[] {"/P1/bin"}, "bin");
createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB", "/P1/bin"}, "bin");
setUpWorkingCopy(
"/P3/src/q/Y.java",
"package q;\n" +
"import p.X;\n" +
"public class Y {\n" +
" void foo(X x) {\n" +
" }\n"+
"}"
);
editFile(
"/P1/src/p/X.java",
"package p;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
"}"
);
getProject("P1").build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
setWorkingCopyContents(
"package q;\n" +
"import p.X;\n" +
"public class Y {\n" +
" void foo(X x) {\n" +
" x.bar();\n" +
" }\n"+
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteProjects(new String[] {"P1", "P2", "P3"});
}
}
/*
* Ensures that changing and external jar and refreshing takes the change into account
* (regression test for bug 134110 [regression] Does not pick-up interface changes from classes in the build path)
*/
public void testChangeExternalJar() throws CoreException, IOException {
IJavaProject project = getJavaProject("Reconciler");
String jarPath = getExternalPath() + "lib.jar";
try {
createJar(new String[] {
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public void foo() {\n" +
" }\n" +
"}"
}, jarPath);
addLibraryEntry(project, jarPath, false);
// force Y.class file to be cached during resolution
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.Y {\n" +
" public void bar() {\n" +
" foo();\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// change jar and refresh
createJar(new String[] {
"p/Y.java",
"package p;\n" +
"public class Y {\n" +
" public void foo(String s) {\n" +
" }\n" +
"}"
}, jarPath);
getJavaModel().refreshExternalArchives(null,null);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.Y {\n" +
" public void bar() {\n" +
" foo(\"a\");\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
removeClasspathEntry(project, new Path(jarPath));
deleteResource(new File(jarPath));
}
}
/**
* @bug 162621: [model][delta] Validation errors do not clear after replacing jar file
* @test Ensures that changing an internal jar and refreshing takes the change into account
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=162621"
*/
public void testChangeInternalJar() throws CoreException, IOException {
IJavaProject project = getJavaProject("Reconciler");
String jarName = "b162621.jar";
try {
String[] pathAndContents = new String[] {
"test/before/Foo.java",
"package test.before;\n" +
"public class Foo {\n" +
"}\n"
};
addLibrary(project, jarName, "b162621_src.zip", pathAndContents, JavaCore.VERSION_1_4);
// Wait a little bit to be sure file system is aware of zip file creation
try {
Thread.sleep(1000);
}
catch (InterruptedException ie) {
// skip
}
// Set working copy content with no error
setUpWorkingCopy("/Reconciler/src/test/Test.java",
"package test;\n" +
"import test.before.Foo;\n" +
"public class Test {\n" +
" Foo f;\n" +
"}\n"
);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
// Update working copy with Jar expected changes
String contents = "package test;\n" +
"import test.after.Foo;\n" +
"public class Test {\n" +
" Foo f;\n" +
"}\n";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblems(
"Wrong expected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/test/Test.java (at line 2)\n" +
" import test.after.Foo;\n" +
" ^^^^^^^^^^\n" +
"The import test.after cannot be resolved\n" +
"----------\n" +
"2. ERROR in /Reconciler/src/test/Test.java (at line 4)\n" +
" Foo f;\n" +
" ^^^\n" +
"Foo cannot be resolved to a type\n" +
"----------\n"
);
// change jar and refresh
String projectLocation = project.getProject().getLocation().toOSString();
String jarPath = projectLocation + File.separator + jarName;
createJar(new String[] {
"test/after/Foo.java",
"package test.after;\n" +
"public class Foo {\n" +
"}\n"
}, jarPath);
project.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
try {
Thread.sleep(1000);
}
catch (InterruptedException ie) {
// skip
}
// Verify that error is gone
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
removeClasspathEntry(project, new Path(jarName));
deleteResource(new File(jarName));
}
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of a method's type parameter change.
*/
public void testChangeMethodTypeParameters() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public <T> void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {CONTENT}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of a type's type parameter change.
*/
public void testChangeTypeTypeParameters() throws JavaModelException {
setUp15WorkingCopy();
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X <T> {\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CONTENT}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of a method visibility change.
*/
public void testChangeMethodVisibility() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" private void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {MODIFIERS CHANGED}"
);
}
/**
* Ensures that the correct delta is reported when closing the working copy and modifying its buffer.
*/
public void testCloseWorkingCopy() throws JavaModelException {
IBuffer buffer = this.workingCopy.getBuffer();
this.workingCopy.close();
buffer.setContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
" public void bar() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}"
);
}
/**
* Ensures that a reference to a constant with type mismatch doesn't show an error.
* (regression test for bug 17104 Compiler does not complain but "Quick Fix" ??? complains)
*/
public void testConstantReference() throws CoreException {
try {
createFile(
"/Reconciler/src/p1/OS.java",
"package p1;\n" +
"public class OS {\n" +
" public static final int CONST = 23 * 1024;\n" +
"}");
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public short c;\n" +
" public static void main(String[] arguments) {\n" +
" short c = 1;\n" +
" switch (c) {\n" +
" case OS.CONST: return;\n" +
" }\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteFile("/Reconciler/src/p1/OS.java");
}
}
/*
* Ensures that the source type converter doesn't throw an OutOfMemoryError if converting a generic type with a primitive type array as argument
* (regression test for bug 135296 opening a special java file results in an "out of memory" message)
*/
public void testConvertPrimitiveTypeArrayTypeArgument() throws CoreException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"Reconciler15/src/Y.java",
"public class Y {\n" +
" void foo(Z<int[]> z) {}\n" +
"}\n" +
"class Z<E> {\n" +
"}",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/X.java", this.wcOwner);
setWorkingCopyContents(
"public class X {\n" +
" void bar(Y y) {\n" +
" y.foo(new Z<int[]>());\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of a method being deleted.
*/
public void testDeleteMethod1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[-]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of two methods being deleted.
*/
public void testDeleteTwoMethods() throws JavaModelException {
// create 2 methods
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
" public void bar() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// delete the 2 methods
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[-]: {}\n" +
" foo()[-]: {}"
);
}
/*
* Ensures that excluded part of prereq project are not visible
*/
public void testExcludePartOfAnotherProject1() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P", "-**/internal/"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P");
createFolder("/P/p/internal");
createFile(
"/P/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 2)\n" +
" public class X extends p.internal.Y {\n" +
" ^^^^^^^^^^^^\n" +
"Access restriction: The type Y is not accessible due to restriction on required project P\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProject("P");
}
}
/*
* Ensures that packages that are not in excluded part of prereq project are visible
*/
public void testExcludePartOfAnotherProject2() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P", "-**/internal/"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P");
createFolder("/P/p/api");
createFile(
"/P/p/api/Y.java",
"package p.api;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.api.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProject("P");
}
}
/*
* Ensures that an external working copy can be reconciled with no error.
*/
public void testExternal1() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
this.problemRequestor = new ProblemRequestor();
IClasspathEntry[] classpath = new IClasspathEntry[] {JavaCore.newLibraryEntry(getExternalJCLPath(), null, null)};
this.workingCopy = newExternalWorkingCopy("External.java", classpath, this.problemRequestor,
"public class External {\n"+
" String foo(){\n"+
" return \"\";\n" +
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null/*no owner*/, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
}
/*
* Ensures that an external working copy with a container classpath entry can be reconciled with no exception.
* (regression test for bug 148970 Exceptions opening external Java file)
*/
public void testExternal2() throws CoreException {
class LogListener implements ILogListener {
IStatus loggedStatus;
public void logging(IStatus status, String plugin) {
this.loggedStatus = status;
}
}
LogListener listener = new LogListener();
try {
Platform.addLogListener(listener);
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
this.problemRequestor = new ProblemRequestor();
ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {" ", getExternalJCLPathString()}));
IClasspathEntry[] classpath = new IClasspathEntry[] {
JavaCore.newContainerEntry(new Path("org.eclipse.jdt.core.tests.model.TEST_CONTAINER"))
};
this.workingCopy = newExternalWorkingCopy("External.java", classpath, this.problemRequestor,
"public class External {\n"+
" String foo(){\n"+
" return \"\";\n" +
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null/*no owner*/, null);
assertEquals("Should not get any exception in log", null, listener.loggedStatus);
} finally {
Platform.removeLogListener(listener);
}
}
/*
* Ensures that an error is detected after refreshing external archives used by
* an external working copy.
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=216772 )
*/
public void testExternal3() throws Exception {
try {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
this.problemRequestor = new ProblemRequestor();
createJar(new String[] {
"p/Lib.java",
"package p;\n" +
"public class Lib {\n" +
"}"
}, getExternalResourcePath("lib.jar"));
IClasspathEntry[] classpath = new IClasspathEntry[] {
JavaCore.newLibraryEntry(getExternalJCLPath(), null, null),
JavaCore.newLibraryEntry(new Path(getExternalResourcePath("lib.jar")), null, null)
};
this.workingCopy = newExternalWorkingCopy("External.java", classpath, this.problemRequestor,
"public class External {\n"+
" p.Lib field;\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null/*no owner*/, null);
createJar(new String[] {
"p/Lib2.java",
"package p;\n" +
"public class Lib2 {\n" +
"}"
}, getExternalResourcePath("lib.jar"));
getJavaModel().refreshExternalArchives(null, null);
this.problemRequestor.reset();
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force problem detection*/, null/*no owner*/, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in / /External.java\n" +
"p.Lib cannot be resolved to a type\n" +
"----------\n"
);
} finally {
deleteExternalResource("lib.jar");
}
}
/*
* Ensures that included part of prereq project are visible
*/
public void testIncludePartOfAnotherProject1() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P", "+**/api/"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P");
createFolder("/P/p/api");
createFile(
"/P/p/api/Y.java",
"package p.api;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.api.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProject("P");
}
}
/*
* Ensures that packages that are not in included part of prereq project are not visible
*/
public void testIncludePartOfAnotherProject2() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P", "+**/api/|-**"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P");
createFolder("/P/p/internal");
createFile(
"/P/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 2)\n" +
" public class X extends p.internal.Y {\n" +
" ^^^^^^^^^^^^\n" +
"Access restriction: The type Y is not accessible due to restriction on required project P\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProject("P");
}
}
/**
* Start with no imports, add an import, and then append to the import name.
*/
public void testGrowImports() throws JavaModelException {
// no imports
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// add an import
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"<import container>[+]: {}"
);
// append to import name
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2\n" +
"public class X {\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"<import container>[*]: {CHILDREN | FINE GRAINED}\n" +
" import p2[+]: {}\n" +
" import p[-]: {}"
);
}
/*
* Ensures that a type matching a ignore-if-better non-accessible rule is further found when accessible
* on another classpath entry.
* (regression test for bug 98127 Access restrictions started showing up after switching to bundle)
*/
public void testIgnoreIfBetterNonAccessibleRule1() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P1", "?**/internal/", "/P2", "+**/internal/Y"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P1");
createFolder("/P1/p/internal");
createFile(
"/P1/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
createJavaProject("P2");
createFolder("/P2/p/internal");
createFile(
"/P2/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProjects(new String[] {"P1", "P2"});
}
}
/*
* Ensures that a type matching a ignore-if-better non-accessible rule is further found when accessible
* on another classpath entry.
* (regression test for bug 98127 Access restrictions started showing up after switching to bundle)
*/
public void testIgnoreIfBetterNonAccessibleRule2() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P1", "?**/internal/", "/P2", "~**/internal/Y"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P1");
createFolder("/P1/p/internal");
createFile(
"/P1/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
createJavaProject("P2");
createFolder("/P2/p/internal");
createFile(
"/P2/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler/src/p1/X.java (at line 2)\n" +
" public class X extends p.internal.Y {\n" +
" ^^^^^^^^^^^^\n" +
"Discouraged access: The type Y is not accessible due to restriction on required project P2\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProjects(new String[] {"P1", "P2"});
}
}
/*
* Ensures that a type matching a ignore-if-better non-accessible rule is further found non-accessible
* on another classpath entry.
* (regression test for bug 98127 Access restrictions started showing up after switching to bundle)
*/
public void testIgnoreIfBetterNonAccessibleRule3() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P1", "?**/internal/", "/P2", "-**/internal/Y"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P1");
createFolder("/P1/p/internal");
createFile(
"/P1/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
createJavaProject("P2");
createFolder("/P2/p/internal");
createFile(
"/P2/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 2)\n" +
" public class X extends p.internal.Y {\n" +
" ^^^^^^^^^^^^\n" +
"Access restriction: The type Y is not accessible due to restriction on required project P1\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProjects(new String[] {"P1", "P2"});
}
}
/*
* Ensures that a type matching a ignore-if-better non-accessible rule is found non-accessible
* if no other classpath entry matches it.
* (regression test for bug 98127 Access restrictions started showing up after switching to bundle)
*/
public void testIgnoreIfBetterNonAccessibleRule4() throws CoreException {
IClasspathEntry[] newEntries = createClasspath("Reconciler", new String[] {"/P1", "?**/internal/"});
try {
addClasspathEntries(newEntries, true);
createJavaProject("P1");
createFolder("/P1/p/internal");
createFile(
"/P1/p/internal/Y.java",
"package p.internal;\n" +
"public class Y {\n" +
"}"
);
setWorkingCopyContents(
"package p1;\n" +
"public class X extends p.internal.Y {\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 2)\n" +
" public class X extends p.internal.Y {\n" +
" ^^^^^^^^^^^^\n" +
"Access restriction: The type Y is not accessible due to restriction on required project P1\n" +
"----------\n"
);
} finally {
removeClasspathEntries(newEntries);
deleteProjects(new String[] {"P1"});
}
}
/**
* Introduces a syntax error in the modifiers of a method.
*/
public void testMethodWithError01() throws CoreException {
// Introduce syntax error
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public.void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta after syntax error",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {MODIFIERS CHANGED}"
);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" public.void foo() {\n" +
" ^\n" +
"Syntax error on token \".\", delete this token\n" +
"----------\n"
);
// Fix the syntax error
clearDeltas();
String contents =
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
"}";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta after fixing syntax error",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {MODIFIERS CHANGED}"
);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler/src/p1/X.java (at line 2)\n" +
" import p2.*;\n" +
" ^^\n" +
"The import p2 is never used\n" +
"----------\n"
);
}
/**
* Test reconcile force flag
*/
public void testMethodWithError02() throws CoreException {
String contents =
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public.void foo() {\n" +
" }\n" +
"}";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// use force flag to refresh problems
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" public.void foo() {\n" +
" ^\n" +
"Syntax error on token \".\", delete this token\n" +
"----------\n"
);
}
/**
* Test reconcile force flag off
*/
public void testMethodWithError03() throws CoreException {
String contents =
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public.void foo() {\n" +
" }\n" +
"}";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// reconcile with force flag turned off
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
""
);
}
/**
* Test reconcile force flag + cancel
*/
public void testMethodWithError04() throws CoreException {
CancelingProblemRequestor myPbRequestor = new CancelingProblemRequestor();
this.workingCopy.discardWorkingCopy();
ICompilationUnit x = getCompilationUnit("Reconciler", "src", "p1", "X.java");
this.problemRequestor = myPbRequestor;
this.workingCopy = x.getWorkingCopy(this.wcOwner, null);
String contents =
"package p1;\n" +
"public class X {\n" +
" Zork f; \n"+
" void foo(Zork z){\n"+
" }\n"+
"} \n";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
// use force flag to refresh problems
myPbRequestor.isCanceling = true;
myPbRequestor.initialize(contents.toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, myPbRequestor.progressMonitor);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 3)\n" +
" Zork f; \n" +
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n"
);
}
/**
* Test reconcile force flag off
*/
public void testMethodWithError05() throws CoreException {
try {
createFolder("/Reconciler/src/tests");
String contents =
"package tests; \n"+
"abstract class AbstractSearchableSource extends AbstractSource implements SearchableSource { \n"+
" abstract int indexOfImpl(long value); \n"+
" public final int indexOf(long value) { \n"+
" return indexOfImpl(value); \n"+
" } \n"+
"} \n";
createFile(
"/Reconciler/src/tests/AbstractSearchableSource.java",
contents);
createFile(
"/Reconciler/src/tests/Source.java",
"package tests; \n"+
"interface Source { \n"+
" long getValue(int index); \n"+
" int size(); \n"+
"} \n");
createFile(
"/Reconciler/src/tests/AbstractSource.java",
"package tests; \n"+
"abstract class AbstractSource implements Source { \n"+
" AbstractSource() { \n"+
" } \n"+
" void invalidate() { \n"+
" } \n"+
" abstract long getValueImpl(int index); \n"+
" abstract int sizeImpl(); \n"+
" public final long getValue(int index) { \n"+
" return 0; \n"+
" } \n"+
" public final int size() { \n"+
" return 0; \n"+
" } \n"+
"} \n");
createFile(
"/Reconciler/src/tests/SearchableSource.java",
"package tests; \n"+
"interface SearchableSource extends Source { \n"+
" int indexOf(long value); \n"+
"} \n");
ICompilationUnit compilationUnit = getCompilationUnit("Reconciler", "src", "tests", "AbstractSearchableSource.java");
ProblemRequestor pbReq = new ProblemRequestor();
WorkingCopyOwner owner = newWorkingCopyOwner(pbReq);
ICompilationUnit wc = compilationUnit.getWorkingCopy(owner, null);
pbReq.initialize(contents.toCharArray());
startDeltas();
wc.reconcile(ICompilationUnit.NO_AST, true, null, null);
String actual = pbReq.problems.toString();
String expected =
"----------\n" +
"----------\n";
if (!expected.equals(actual)){
System.out.println(Util.displayString(actual, 2));
}
assertEquals(
"unexpected errors",
expected,
actual);
} finally {
deleteFile("/Reconciler/src/tests/AbstractSearchableSource.java");
deleteFile("/Reconciler/src/tests/SearchableSource.java");
deleteFile("/Reconciler/src/tests/Source.java");
deleteFile("/Reconciler/src/tests/AbstractSource.java");
deleteFolder("/Reconciler/src/tests");
}
}
/*
* Test that the creation of a working copy detects errors
* (regression test for bug 33757 Problem not detected when opening a working copy)
*/
public void testMethodWithError06() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
try {
String contents =
"package p1;\n" +
"public class Y {\n" +
" public.void foo() {\n" +
" }\n" +
"}";
createFile(
"/Reconciler/src/p1/Y.java",
contents
);
this.problemRequestor = new ProblemRequestor();
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy = getCompilationUnit("Reconciler/src/p1/Y.java").getWorkingCopy(this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/Y.java (at line 3)\n" +
" public.void foo() {\n" +
" ^\n" +
"Syntax error on token \".\", delete this token\n" +
"----------\n"
);
} finally {
deleteFile("/Reconciler/src/p1/Y.java");
}
}
/*
* Test that the opening of a working copy detects errors
* (regression test for bug 33757 Problem not detected when opening a working copy)
*/
public void testMethodWithError07() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
try {
String contents =
"package p1;\n" +
"public class Y {\n" +
" public.void foo() {\n" +
" }\n" +
"}";
createFile(
"/Reconciler/src/p1/Y.java",
contents
);
this.problemRequestor = new ProblemRequestor();
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy = getCompilationUnit("Reconciler/src/p1/Y.java").getWorkingCopy(this.wcOwner, null);
// Close working copy
JavaModelManager.getJavaModelManager().removeInfoAndChildren((CompilationUnit)this.workingCopy); // use a back door as working copies cannot be closed
// Reopen should detect syntax error
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.open(null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/Y.java (at line 3)\n" +
" public.void foo() {\n" +
" ^\n" +
"Syntax error on token \".\", delete this token\n" +
"----------\n"
);
} finally {
deleteFile("/Reconciler/src/p1/Y.java");
}
}
/*
* Test that the units with similar names aren't presenting each other errors
* (regression test for bug 39475)
*/
public void testMethodWithError08() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
try {
createFile(
"/Reconciler/src/p1/X01.java",
"package p1;\n" +
"public abstract class X01 {\n" +
" public abstract void bar(); \n"+
" public abstract void foo(Zork z); \n"+
"}"
);
String contents =
"package p2;\n" +
"public class X01 extends p1.X01 {\n" +
" public void bar(){} \n"+
"}";
createFile(
"/Reconciler/src/p2/X01.java",
contents
);
this.problemRequestor = new ProblemRequestor();
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy = getCompilationUnit("Reconciler/src/p2/X01.java").getWorkingCopy(this.wcOwner, null);
// Close working copy
JavaModelManager.getJavaModelManager().removeInfoAndChildren((CompilationUnit)this.workingCopy); // use a back door as working copies cannot be closed
// Reopen should detect syntax error
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.open(null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p2/X01.java (at line 2)\n" +
" public class X01 extends p1.X01 {\n" +
" ^^^\n" +
"The type X01 must implement the inherited abstract method X01.foo(Zork)\n" +
"----------\n"
);
} finally {
deleteFile("/Reconciler/src/p1/X01.java");
deleteFile("/Reconciler/src/p2/X01.java");
}
}
/*
* Scenario of reconciling using a working copy owner
*/
public void testMethodWithError09() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
workingCopy1 = getCompilationUnit("/Reconciler/src/p1/X1.java").getWorkingCopy(this.wcOwner, null);
workingCopy1.getBuffer().setContents(
"package p1;\n" +
"public abstract class X1 {\n" +
" public abstract void bar(); \n"+
"}"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler/src/p/X.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package p;\n" +
"public class X extends p1.X1 {\n" +
" public void bar(){} \n"+
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n" // shouldn't report problem against p.X
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
}
}
/*
* Scenario of reconciling using a working copy owner (68557)
*/
public void testMethodWithError10() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
createFolder("/Reconciler15/src/test/cheetah");
workingCopy1 = getCompilationUnit("/Reconciler15/src/test/cheetah/NestedGenerics.java").getWorkingCopy(this.wcOwner, null);
workingCopy1.getBuffer().setContents(
"package test.cheetah;\n"+
"import java.util.List;\n"+
"import java.util.Stack;\n"+
"public class NestedGenerics {\n"+
" Stack< List<Object>> stack = new Stack< List<Object> >();\n"+
"}\n"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler15/src/test/cheetah/NestedGenericsTest.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package test.cheetah;\n"+
"import java.util.Stack;\n"+
"public class NestedGenericsTest {\n"+
" void test() { \n"+
" Stack s = new NestedGenerics().stack; \n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
deleteFolder("/Reconciler15/src/test");
}
}
/*
* Scenario of reconciling using a working copy owner (68557)
*/
public void testMethodWithError11() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
createFolder("/Reconciler15/src/test/cheetah");
workingCopy1 = getCompilationUnit("/Reconciler15/src/test/cheetah/NestedGenerics.java").getWorkingCopy(this.wcOwner, null);
workingCopy1.getBuffer().setContents(
"package test.cheetah;\n"+
"import java.util.*;\n"+
"public class NestedGenerics {\n"+
" Map<List<Object>,String> map = null;\n"+
" Stack<List<Object>> stack2 = null;\n"+
" Map<List<Object>,List<Object>> map3 = null;\n"+
"}\n"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler15/src/test/cheetah/NestedGenericsTest.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package test.cheetah;\n"+
"import java.util.*;\n"+
"public class NestedGenericsTest {\n"+
" void test() { \n"+
" Map m = new NestedGenerics().map; \n"+
" Stack s2 = new NestedGenerics().stack2; \n"+
" Map m3 = new NestedGenerics().map3; \n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
deleteFolder("/Reconciler15/src/test");
}
}
/*
* Scenario of reconciling using a working copy owner (68557 variation with wildcards)
*/
public void testMethodWithError12() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
createFolder("/Reconciler15/src/test/cheetah");
workingCopy1 = getCompilationUnit("/Reconciler15/src/test/cheetah/NestedGenerics.java").getWorkingCopy(this.wcOwner, null);
workingCopy1.getBuffer().setContents(
"package test.cheetah;\n"+
"import java.util.*;\n"+
"public class NestedGenerics {\n"+
" Map<List<?>,? super String> map = null;\n"+
" Stack<List<? extends Object>> stack2 = null;\n"+
" Map<List<Object[]>,List<Object>[]> map3 = null;\n"+
"}\n"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler15/src/test/cheetah/NestedGenericsTest.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package test.cheetah;\n"+
"import java.util.*;\n"+
"public class NestedGenericsTest {\n"+
" void test() { \n"+
" Map m = new NestedGenerics().map; \n"+
" Stack s2 = new NestedGenerics().stack2; \n"+
" Map m3 = new NestedGenerics().map3; \n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
deleteFolder("/Reconciler15/src/test");
}
}
/*
* Scenario of reconciling using a working copy owner (68730)
*/
public void testMethodWithError13() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
this.problemRequestor = null;
try {
workingCopy1 = getCompilationUnit("/Reconciler15/src/test/X.java").getWorkingCopy(this.wcOwner, null);
createFolder("/Reconciler15/src/test");
workingCopy1.getBuffer().setContents(
"package test;\n"+
"public class X <T extends String, U> {\n"+
" <Y1> void bar(Y1[] y) {}\n"+
" void bar2(Y<E3[]>[] ye[]) {}\n"+
" void foo(java.util.Map<Object[],String>.MapEntry<p.K<T>[],? super q.r.V8> m){}\n"+
" Class<? extends Object> getClass0() {}\n"+
" <E extends String> void pair (X<? extends E, U> e, T t){}\n"+
"}\n"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler15/src/test/Y.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package test;\n"+
"public class Y {\n"+
" void foo(){\n"+
" X someX = new X();\n"+
" someX.bar(null);\n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler15/src/test/Y.java (at line 5)\n" +
" someX.bar(null);\n" +
" ^^^^^^^^^^^^^^^\n" +
"Type safety: The method bar(Object[]) belongs to the raw type X. References to generic type X<T,U> should be parameterized\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
deleteFolder("/Reconciler15/src/test");
}
}
/*
* Scenario of reconciling using a working copy owner (66424)
*/
public void testMethodWithError14() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
workingCopy1 = getCompilationUnit("/Reconciler15/src/test/X.java").getWorkingCopy(this.wcOwner, null);
createFolder("/Reconciler15/src/test");
workingCopy1.getBuffer().setContents(
"package test;\n"+
"public class X <T> {\n"+
" <U> void bar(U u) {}\n"+
"}\n"
);
workingCopy1.makeConsistent(null);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler15/src/test/Y.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package test;\n"+
"public class Y {\n"+
" void foo(){\n"+
" X someX = new X();\n"+
" someX.bar();\n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler15/src/test/Y.java (at line 5)\n" +
" someX.bar();\n" +
" ^^^\n" +
"The method bar(Object) in the type X is not applicable for the arguments ()\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
deleteFolder("/Reconciler15/src/test");
}
}
/**
* Ensures that the reconciler handles member move correctly.
*/
public void testMoveMember() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" }\n" +
" public void bar() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
clearDeltas();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
" public void foo() {\n" +
" }\n" +
"}");
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[*]: {REORDERED}\n" +
" foo()[*]: {REORDERED}"
);
}
/**
* Ensures that the reconciler does nothing when the source
* to reconcile with is the same as the current contents.
*/
public void testNoChanges1() throws JavaModelException {
setWorkingCopyContents(this.workingCopy.getSource());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"[Working copy] X.java[*]: {CONTENT | FINE GRAINED}"
);
}
/**
* Ensures that the reconciler does nothing when the source
* to reconcile with has the same structure as the current contents.
*/
public void testNoChanges2() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"[Working copy] X.java[*]: {CONTENT | FINE GRAINED}"
);
}
/*
* Ensures that the problem requestor is not called when the source
* to reconcile is the same as the current contents,
* no ast is requested, no problem is requested and problem requestor is not active.
* (regression test for bug 179258 simple reconcile starts problem finder - main thread waiting)
*
*/
public void testNoChanges3() throws JavaModelException {
setWorkingCopyContents(this.workingCopy.getSource());
this.problemRequestor.isActive = false;
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems("Unexpected problems", "");
}
/*
* Ensures that using a non-generic method with no parameter and with a raw receiver type doesn't create a type safety warning
* (regression test for bug 105756 [1.5][model] Incorrect warning on using raw types)
*/
public void testRawUsage() throws CoreException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"Reconciler15/src/Generic105756.java",
"public class Generic105756<T> {\n" +
" void foo() {}\n" +
"}",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/X.java", this.wcOwner);
setWorkingCopyContents(
"public class X {\n" +
" void bar(Generic105756 g) {\n" +
" g.foo();\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/*
* Ensures that a reconcile participant is notified when a working copy is reconciled.
*/
public void testReconcileParticipant01() throws CoreException {
ReconcileParticipant participant = new ReconcileParticipant();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertDeltas(
"Unexpected participant delta",
"[Working copy] X.java[*]: {CHILDREN | FINE GRAINED}\n" +
" X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}\n" +
" foo()[-]: {}",
participant.delta
);
}
/*
* Ensures that a reconcile participant is not notified if not participating.
*/
public void testReconcileParticipant02() throws CoreException {
ReconcileParticipant participant = new ReconcileParticipant(){
public boolean isActive(IJavaProject project) {
return false;
}
};
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertDeltas(
"Unexpected participant delta",
"<null>",
participant.delta
);
}
/*
* Ensures that a reconcile participant is notified with the correct AST.
*/
public void testReconcileParticipant03() throws CoreException {
ReconcileParticipant participant = new ReconcileParticipant();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertASTNodeEquals(
"Unexpected participant ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar(){\n" +
" }\n" +
"}\n",
participant.ast
);
}
/*
* Ensures that the same AST as the one a reconcile participant requested is reported.
*/
public void testReconcileParticipant04() throws CoreException {
ReconcileParticipant participant = new ReconcileParticipant();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(AST.JLS3, false, null, null);
assertSame(
"Unexpected participant ast",
participant.ast,
ast
);
}
/*
* Ensures that a participant can fix an error during reconcile.
*/
public void testReconcileParticipant05() throws CoreException {
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
try {
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
"}"
);
context.resetAST();
} catch (JavaModelException e) {
e.printStackTrace();
}
}
};
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public void bar() {\n" +
" toString()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
}
/*
* Ensures that a participant can introduce an error during reconcile.
*/
public void testReconcileParticipant06() throws CoreException {
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
try {
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public void bar() {\n" +
" toString()\n" +
" }\n" +
"}"
);
context.resetAST();
} catch (JavaModelException e) {
e.printStackTrace();
}
}
};
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" toString()\n" +
" ^\n" +
"Syntax error, insert \";\" to complete BlockStatements\n" +
"----------\n"
);
}
/*
* Ensures that a reconcile participant is NOT notified when a working copy is reconciled
* in a project with insufficient source level.
* (regression test for bug 125291 Enable conditional loading of APT)
*/
public void testReconcileParticipant07() throws CoreException {
IJavaProject project = this.workingCopy.getJavaProject();
String originalSourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
try {
project.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_1);
ReconcileParticipant participant = new ReconcileParticipant();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertDeltas(
"Unexpected participant delta",
"<null>",
participant.delta
);
} finally {
project.setOption(JavaCore.COMPILER_SOURCE, originalSourceLevel);
}
}
/*
* Ensures that a problem reporting session is not started during reconcile if a participant reports an error
* and if the working copy is already consistent and the forceProblemDetection flag is false.
* (regression test for bug 154170 Printing warnings breaks in-editor quick fixes)
*/
public void testReconcileParticipant08() throws CoreException {
// set working copy contents and ensure it is consistent
String contents =
"package p1;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
"}";
setWorkingCopyContents(contents);
this.workingCopy.makeConsistent(null);
this.problemRequestor.initialize(contents.toCharArray());
// reconcile with a participant adding a list of problems
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
context.putProblems("test.marker", new CategorizedProblem[] {});
}
};
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
""
);
}
/*
* Ensures that a reconcile participant is not notified when a working copy is reconciled
* and it was consistent and forcing problem detection is off
* (regression test for 177319 Annotation Processing (APT) affects eclipse speed)
*/
public void testReconcileParticipant09() throws CoreException {
this.workingCopy.makeConsistent(null);
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
assertTrue("Participant should not be notified of a reconcile", false);
}
};
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false/*don't force problem detection*/, null, null);
}
/*
* Ensures that a reconcile participant is notified when a working copy is reconciled
* and it was consistent and forcing problem detection is on
*/
public void testReconcileParticipant10() throws CoreException {
this.workingCopy.makeConsistent(null);
final boolean[] participantReconciled = new boolean[1];
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
participantReconciled[0] = true;
}
};
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force problem detection*/, null, null);
assertTrue(
"Participant should have been notified",
participantReconciled[0]
);
}
/*
* Ensures that the delta is still correct if a participant resets the ast during reconcile
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=210310)
*/
public void testReconcileParticipant11() throws CoreException {
new ReconcileParticipant() {
public void reconcile(ReconcileContext context) {
context.resetAST();
}
};
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" private void foo() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(AST.JLS3, true/*force problem detection*/, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" foo()[*]: {MODIFIERS CHANGED}"
);
}
/*
* Ensures that a misbehaving reconcile participant doesn't interfere with a reconcile operation
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=248680 )
*/
public void testReconcileParticipant12() throws CoreException {
try {
TestCompilationParticipant.failToInstantiate = true;
simulateExitRestart();
this.workingCopy = getCompilationUnit("Reconciler/src/p1/X.java").getWorkingCopy(this.wcOwner, null);
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" System.out.println()\n" +
" }\n" +
"}"
);
startDeltas();
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected participant delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}\n" +
" foo()[-]: {}"
);
} finally {
stopDeltas();
TestCompilationParticipant.failToInstantiate = false;
}
}
/*
* Ensures that errors are fixed if renaming the .classpath file causes the missing type to be visible.
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=207890)
*/
public void testRenameClasspathFile() throws CoreException {
ICompilationUnit copy = null;
try {
createJavaProject("P1");
deleteFile("/P1/.classpath");
createFile(
"/P1/.classpath2",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<classpath>\n" +
" <classpathentry kind=\"src\" path=\"src1\"/>\n" +
" <classpathentry kind=\"var\" path=\"JCL_LIB\"/>\n" +
" <classpathentry kind=\"output\" path=\"bin\"/>\n" +
"</classpath>"
);
createFolder("/P1/src1/p1");
createFile(
"/P1/src1/p1/X.java",
"package p1;\n" +
"public class X {\n" +
"}"
);
createJavaProject("P2", new String[] {"src"}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "bin");
createFolder("/P2/src/p2");
copy = getWorkingCopy(
"/P2/src/p2/Y.java",
"package p2;\n" +
"import p1.X;\n" +
"public class Y extends X {\n" +
"}",
true/*compute problems*/
);
moveFile("/P1/.classpath2", "/P1/.classpath");
this.problemRequestor.reset();
copy.reconcile(ICompilationUnit.NO_AST, true/*for pb detection*/, null/*default owner*/, null/*no progress*/);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (copy != null)
copy.discardWorkingCopy();
deleteProject("P1");
deleteProject("P2");
}
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents, updating the structure of this reconciler's compilation
* unit, and fires the Java element deltas for the structural changes
* of a renaming a method; the original method deleted and the new method added structurally.
*/
public void testRenameMethod1() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar() {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}\n" +
" foo()[-]: {}"
);
}
/**
* Ensures that the reconciler reconciles the new contents with the current
* contents,updating the structure of this reconciler's compilation
* unit, and fires the Java element delta for the structural changes
* of the addition of a portion of a new method.
*/
public void testRenameWithSyntaxError() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void bar( {\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Unexpected delta",
"X[*]: {CHILDREN | FINE GRAINED}\n" +
" bar()[+]: {}\n" +
" foo()[-]: {}"
);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" public void bar( {\n" +
" ^\n" +
//{ObjectTeams: our grammar has different expectations:
/* orig:
"Syntax error, insert \")\" to complete MethodDeclaration\n" +
:giro */
"Syntax error, insert \")\" to complete MethodSpecLong\n" +
"----------\n" +
"2. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" public void bar( {\n" +
" ^\n" +
"Syntax error, insert \"<-\" to complete CallinBindingLeft\n" +
"----------\n" +
"3. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" public void bar( {\n" +
" ^\n" +
"Syntax error, insert \"MethodSpecsLong EmptyParameterMappings\" to complete ClassBodyDeclarations\n" +
// SH}
"----------\n"
);
}
/*
* Ensure that warning are suppressed by an @SuppressWarnings annotation.
*/
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=95056
public void testSuppressWarnings1() throws JavaModelException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"/Reconciler15/src/X.java",
"@Deprecated\n" +
"public class X {\n" +
" void foo(){}\n" +
"}\n",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/Y.java", this.wcOwner);
setWorkingCopyContents(
"public class Y extends X {\n" +
" @SuppressWarnings(\"all\")\n" +
" void foo(){ super.foo(); }\n" +
" Zork z;\n" +
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler15/src/Y.java (at line 1)\n" +
" public class Y extends X {\n" +
" ^\n" +
"The type X is deprecated\n" +
"----------\n" +
"2. ERROR in /Reconciler15/src/Y.java (at line 4)\n" +
" Zork z;\n" +
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n");
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/*
* Ensure that warning are suppressed by an @SuppressWarning annotation.
*/
public void testSuppressWarnings2() throws JavaModelException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"/Reconciler15/src/java/util/List.java",
"package java.util;\n" +
"public interface List<E> {\n" +
"}\n",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/X.java", this.wcOwner);
setWorkingCopyContents(
"import java.util.List;\n" +
"\n" +
"public class X {\n" +
" void foo(List list) {\n" +
" List<String> ls1 = list;\n" +
" }\n" +
" @SuppressWarnings(\"unchecked\")\n" +
" void bar(List list) {\n" +
" List<String> ls2 = list;\n" +
" }\n" +
" Zork z;\n" +
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler15/src/X.java (at line 5)\n" +
" List<String> ls1 = list;\n" +
" ^^^^\n" +
"Type safety: The expression of type List needs unchecked conversion to conform to List<String>\n" +
"----------\n" +
"2. ERROR in /Reconciler15/src/X.java (at line 11)\n" +
" Zork z;\n" +
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n"
);
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/*
* Ensure that warning are suppressed by an @SuppressWarning annotation.
*/
public void testSuppressWarnings3() throws JavaModelException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"/Reconciler15/src/java/util/HashMap.java",
"package java.util;\n" +
"public class HashMap implements Map {\n" +
"}\n",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/X.java", this.wcOwner);
setWorkingCopyContents(
"import java.util.*;\n" +
"@SuppressWarnings(\"unchecked\")\n" +
"public class X {\n" +
" void foo() {\n" +
" Map<String, String>[] map = new HashMap[10];\n" +
" }\n" +
" Zork z;\n" +
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler15/src/X.java (at line 7)\n" +
" Zork z;\n" +
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n"
);
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/*
* Ensure that warning are suppressed by an @SuppressWarnings annotation.
*/
public void testSuppressWarnings4() throws JavaModelException {
ICompilationUnit otherCopy = null;
try {
otherCopy = getWorkingCopy(
"/Reconciler15/src/X.java",
"/** @deprecated */\n" +
"public class X {\n" +
" void foo(){}\n" +
"}\n",
this.wcOwner
);
setUp15WorkingCopy("/Reconciler15/src/Y.java", this.wcOwner);
setWorkingCopyContents(
"public class Y extends X {\n" +
" @SuppressWarnings(\"all\")\n" +
" void foo(){ super.foo(); }\n" +
" Zork z;\n" +
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. WARNING in /Reconciler15/src/Y.java (at line 1)\n" +
" public class Y extends X {\n" +
" ^\n" +
"The type X is deprecated\n" +
"----------\n" +
"2. ERROR in /Reconciler15/src/Y.java (at line 4)\n" +
" Zork z;\n" +
" ^^^^\n" +
"Zork cannot be resolved to a type\n" +
"----------\n");
} finally {
if (otherCopy != null)
otherCopy.discardWorkingCopy();
}
}
/**
* Ensure that an unhandled exception is detected.
*/
public void testUnhandledException() throws JavaModelException {
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" public void foo() {\n" +
" throw new Exception();\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"1. ERROR in /Reconciler/src/p1/X.java (at line 4)\n" +
" throw new Exception();\n" +
" ^^^^^^^^^^^^^^^^^^^^^^\n" +
"Unhandled exception type Exception\n" +
"----------\n"
);
}
/**
* Check that forcing a make consistent action is leading the next reconcile to not notice changes.
*/
public void testMakeConsistentFoolingReconciler() throws JavaModelException {
setWorkingCopyContents("");
this.workingCopy.makeConsistent(null);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null);
assertWorkingCopyDeltas(
"Should have got NO delta",
""
);
}
/**
* Test bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=60689
* AST on reconcile: AST without Javadoc comments created
* @deprecated using deprecated code
*/
public void testBug60689() throws JavaModelException {
setWorkingCopyContents("public class X {\n" +
" /**\n" +
" * Returns the length of the string representing the number of \n" +
" * indents in the given string <code>line</code>. Returns \n" +
" * <code>-1<code> if the line isn't prefixed with an indent of\n" +
" * the given number of indents. \n" +
" */\n" +
" public static int computeIndentLength(String line, int numberOfIndents, int tabWidth) {\n" +
" return 0;\n" +
"}"
);
org.eclipse.jdt.core.dom.CompilationUnit testCU = this.workingCopy.reconcile(AST.JLS2, true, null, null);
assertNotNull("We should have a comment!", testCU.getCommentList());
assertEquals("We should have 1 comment!", 1, testCU.getCommentList().size());
testCU = this.workingCopy.reconcile(AST.JLS2, true, null, null);
assertNotNull("We should have a comment!", testCU.getCommentList());
assertEquals("We should have one comment!", 1, testCU.getCommentList().size());
}
/*
* Ensures that a working copy in a 1.4 project that references a 1.5 project can be reconciled without error.
* (regression test for bug 98434 A non-1.5 project with 1.5 projects in the classpath does not show methods with generics)
*/
public void testTwoProjectsWithDifferentCompliances() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
try {
createJavaProject("P1", new String[] {""}, new String[] {"JCL15_LIB"}, "", "1.5");
createFolder("/P1/p");
createFile(
"/P1/p/X.java",
"package p;\n" +
"public class X {\n" +
" void foo(Class<String> c) {\n" +
" }\n" +
"}"
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] {"/P1"}, "", "1.4");
createFolder("/P2/p");
this.workingCopy = getWorkingCopy("/P2/p/Y.java", "", this.wcOwner);
setWorkingCopyContents(
"package p;\n" +
"public class Y {\n" +
" void bar(Class c) {\n" +
" new X().foo(c);\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true/*force pb detection*/, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteProjects(new String[] {"P1", "P2"});
}
}
/*
* Ensures that a method that has a type parameter with bound can be overriden in another working copy.
* (regression test for bug 76780 [model] return type not recognized correctly on some generic methods)
*/
public void testTypeParameterWithBound() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
workingCopy1 = getWorkingCopy(
"/Reconciler15/src/test/I.java",
"package test;\n"+
"public interface I {\n"+
" <T extends I> void foo(T t);\n"+
"}\n",
this.wcOwner
);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getWorkingCopy("Reconciler15/src/test/X.java", "", this.wcOwner);
setWorkingCopyContents(
"package test;\n"+
"public class X implements I {\n"+
" public <T extends I> void foo(T t) {\n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
}
}
/*
* Ensures that a method that has a type parameter starting with $ can be reconciled against.
* (regression test for bug 91709 [1.5][model] Quick Fix Error but no Problem Reported)
*/
public void testTypeParameterStartingWithDollar() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
workingCopy1 = getWorkingCopy(
"/Reconciler15/src/test/Y.java",
"package test;\n"+
"public class Y<$T> {\n"+
" void foo($T t);\n"+
"}\n",
this.wcOwner
);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getWorkingCopy("Reconciler15/src/test/X.java", "", this.wcOwner);
setWorkingCopyContents(
"package test;\n"+
"public class X {\n"+
" public void bar() {\n"+
" new Y<String>().foo(\"\");\n" +
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
}
}
/*
* Ensures that a working copy with a type with a dollar name can be reconciled without errors.
* (regression test for bug 117121 Can't create class called A$B in eclipse)
*/
public void testTypeWithDollarName() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
try {
String contents =
"package p1;\n" +
"public class Y$Z {\n" +
"}";
createFile(
"/Reconciler/src/p1/Y$Z.java",
contents
);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getCompilationUnit("Reconciler/src/p1/Y$Z.java").getWorkingCopy(this.wcOwner, null);
this.problemRequestor.initialize(contents.toCharArray());
this.workingCopy.reconcile(ICompilationUnit.NO_AST, true, null, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
deleteFile("/Reconciler/src/p1/Y$Z.java");
}
}
/*
* Ensures that a working copy with a type with a dollar name can be reconciled against without errors.
* (regression test for bug 125301 Handling of classes with $ in class name.)
*/
public void testTypeWithDollarName2() throws CoreException {
ICompilationUnit workingCopy2 = null;
try {
WorkingCopyOwner owner = this.workingCopy.getOwner();
workingCopy2 = getWorkingCopy(
"/Reconciler/src/p1/Y$Z.java",
"package p1;\n" +
"public class Y$Z {\n" +
"}",
owner
);
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" Y$Z field;\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, owner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy2 != null)
workingCopy2.discardWorkingCopy();
}
}
/*
* Ensures that a working copy with a type with a dollar name can be reconciled against without errors.
* (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=232803 )
*/
public void testTypeWithDollarName3() throws CoreException {
ICompilationUnit workingCopy2 = null;
try {
WorkingCopyOwner owner = this.workingCopy.getOwner();
workingCopy2 = getWorkingCopy(
"/Reconciler/src/p1/Cl$ss.java",
"package p1;\n" +
"public interface Cl$ss {\n" +
" public void test(Cl$ss c);\n" +
" public void foo();\n" +
"}",
owner
);
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" void m(Cl$ss c2) {\n" +
" c2.test(c2);\n" +
" c2.foo();\n" +
" }\n" +
"}"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, owner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy2 != null)
workingCopy2.discardWorkingCopy();
}
}
/*
* Ensures that a varargs method can be referenced from another working copy.
*/
public void testVarargs() throws CoreException {
this.workingCopy.discardWorkingCopy(); // don't use the one created in setUp()
this.workingCopy = null;
ICompilationUnit workingCopy1 = null;
try {
workingCopy1 = getWorkingCopy(
"/Reconciler15/src/test/X.java",
"package test;\n"+
"public class X {\n"+
" void bar(String ... args) {}\n"+
"}\n",
this.wcOwner
);
this.problemRequestor = new ProblemRequestor();
this.workingCopy = getWorkingCopy("Reconciler15/src/test/Y.java", "", this.wcOwner);
setWorkingCopyContents(
"package test;\n"+
"public class Y {\n"+
" void foo(){\n"+
" X someX = new X();\n"+
" someX.bar(\"a\", \"b\");\n"+
" }\n"+
"}\n"
);
this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
} finally {
if (workingCopy1 != null) {
workingCopy1.discardWorkingCopy();
}
}
}
/**
* Bug 114338:[javadoc] Reconciler reports wrong javadoc warning (missing return type)
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=114338"
*
*/
public void testBug114338() throws CoreException {
// Set initial CU content
setWorkingCopyContents(
"package p1;\n" +
"public class X {\n" +
" /**\n" +
" * @return a\n" +
" */\n" +
" boolean get() {\n" +
" return false;\n" +
" }\n" +
"}");
this.workingCopy.reconcile(AST.JLS3, true, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
// Modify content
String contents =
"package p1;\n" +
"public class X {\n" +
" /**\n" +
" * @return boolean\n" +
" */\n" +
" boolean get() {\n" +
" return false;\n" +
" }\n" +
"}";
setWorkingCopyContents(contents);
this.workingCopy.reconcile(AST.JLS3, true, this.wcOwner, null);
assertProblems(
"Unexpected problems",
"----------\n" +
"----------\n"
);
}
/**
* Bug 36032:[plan] JavaProject.findType() fails to find second type in source file
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=36032"
*/
public void testBug36032a() throws CoreException, InterruptedException {
try {
// Resources creation
createJavaProject("P", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
String source =
"public class Test {\n" +
" public static void main(String[] args) {\n" +
" new SFoo().foo();\n" +
" }\n" +
"}\n";
this.createFile(
"/P/Foo.java",
"class SFoo { void foo() {} }\n"
);
this.createFile(
"/P/Test.java",
source
);
// Get compilation unit and reconcile it
char[] sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(this.wcOwner, null);
this.workingCopy.getBuffer().setContents(source);
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertNoProblem(sourceChars, this.workingCopy);
// Add new secondary type
this.createFile(
"/P/Bar.java",
"class SBar{ void bar() {} }\n"
);
source =
"public class Test {\n" +
" public static void main(String[] args) {\n" +
" new SFoo().foo();\n" +
" new SBar().bar();\n" +
" }\n" +
"}\n";
// Reconcile with modified source
sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopy.getBuffer().setContents(source);
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertNoProblem(sourceChars, this.workingCopy);
} finally {
deleteProject("P");
}
}
public void testBug36032b() throws CoreException, InterruptedException {
try {
// Resources creation
createJavaProject("P", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
String source =
"public class Test {\n" +
" public static void main(String[] args) {\n" +
" new SFoo().foo();\n" +
" new SBar().bar();\n" +
" }\n" +
"}\n";
createFile(
"/P/Foo.java",
"class SFoo { void foo() {} }\n"
);
createFile(
"/P/Test.java",
source
);
createFile(
"/P/Bar.java",
"class SBar{ void bar() {} }\n"
);
// Get compilation unit and reconcile it
char[] sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopy = getCompilationUnit("/P/Test.java").getWorkingCopy(this.wcOwner, null);
this.workingCopy.getBuffer().setContents(source);
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertNoProblem(sourceChars, this.workingCopy);
// Delete secondary type => should get a problem
waitUntilIndexesReady();
deleteFile("/P/Bar.java");
this.problemRequestor.initialize(source.toCharArray());
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertEquals("Working copy should not find secondary type 'Bar'!", 1, this.problemRequestor.problemCount);
assertProblems("Working copy should have problem!",
"----------\n" +
"1. ERROR in /P/Test.java (at line 4)\n" +
" new SBar().bar();\n" +
" ^^^^\n" +
"SBar cannot be resolved to a type\n" +
"----------\n"
);
// Fix the problem
source =
"public class Test {\n" +
" public static void main(String[] args) {\n" +
" new SFoo().foo();\n" +
" }\n" +
"}\n";
sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopy.getBuffer().setContents(source);
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertNoProblem(sourceChars, this.workingCopy);
} finally {
deleteProject("P");
}
}
// Secondary types used through multiple projects
public void testBug36032c() throws CoreException, InterruptedException {
try {
// Create first project
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
createFolder("/P1/test");
createFile(
"/P1/test/Foo.java",
"package test;\n" +
"class Secondary{ void foo() {} }\n"
);
createFile(
"/P1/test/Test1.java",
"package test;\n" +
"public class Test1 {\n" +
" public static void main(String[] args) {\n" +
" new Secondary().foo();\n" +
" }\n" +
"}\n"
);
// Create second project
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
String source =
"package test;\n" +
"public class Test2 {\n" +
" public static void main(String[] args) {\n" +
" new Secondary().foo();\n" +
" }\n" +
"}\n";
createFolder("/P2/test");
createFile(
"/P2/test/Test2.java",
source
);
// Get compilation unit and reconcile it => expect no error
char[] sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopy = getCompilationUnit("/P2/test/Test2.java").getWorkingCopy(this.wcOwner, null);
this.workingCopy.getBuffer().setContents(source);
this.workingCopy.reconcile(AST.JLS3, true, null, null);
assertNoProblem(sourceChars, this.workingCopy);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
/**
* Bug 118823: [model] Secondary types cache not reset while removing _all_ secondary types from CU
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118823"
*/
public void testBug118823() throws CoreException, InterruptedException, IOException {
try {
// Resources creation
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
String source = "class Test {}\n";
createFile(
"/P1/Test.java",
source
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
String source2 =
"class A {\n" +
" Secondary s;\n" +
"}\n";
createFile(
"/P2/A.java",
source2
);
waitUntilIndexesReady();
this.workingCopies = new ICompilationUnit[2];
// Get first working copy and verify that there's no error
char[] sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's one error (missing secondary type)
this.problemRequestor.initialize(source2.toCharArray());
this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, null);
assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
assertProblems("Working copy should have problem!",
"----------\n" +
"1. ERROR in /P2/A.java (at line 2)\n" +
" Secondary s;\n" +
" ^^^^^^^^^\n" +
"Secondary cannot be resolved to a type\n" +
"----------\n"
);
// Delete file and recreate it with secondary
final String source1 =
"public class Test {}\n" +
"class Secondary{}\n";
getWorkspace().run(
new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
deleteFile("/P1/Test.java");
createFile(
"/P1/Test.java",
source1
);
}
},
null
);
// Get first working copy and verify that there's still no error
sourceChars = source1.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0].getBuffer().setContents(source1);
this.workingCopies[0].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's any longer error
sourceChars = source2.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[1].getBuffer().setContents(source2);
this.workingCopies[1].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
assertNoProblem(sourceChars, this.workingCopies[1]);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
public void testBug118823b() throws CoreException, InterruptedException {
try {
// Resources creation
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
String source1 = "class Test {}\n";
createFile(
"/P1/Test.java",
source1
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
String source2 =
"class A {\n" +
" Secondary s;\n" +
"}\n";
createFile(
"/P2/A.java",
source2
);
waitUntilIndexesReady();
this.workingCopies = new ICompilationUnit[2];
// Get first working copy and verify that there's no error
char[] sourceChars = source1.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's one error (missing secondary type)
this.problemRequestor.initialize(source2.toCharArray());
this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, null);
assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
assertProblems("Working copy should have problem!",
"----------\n" +
"1. ERROR in /P2/A.java (at line 2)\n" +
" Secondary s;\n" +
" ^^^^^^^^^\n" +
"Secondary cannot be resolved to a type\n" +
"----------\n"
);
// Modify first working copy and verify that there's still no error
source1 =
"public class Test {}\n" +
"class Secondary{}\n";
sourceChars = source1.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0].getBuffer().setContents(source1);
this.workingCopies[0].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
this.workingCopies[0].commitWorkingCopy(true, null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's any longer error
sourceChars = source2.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[1].getBuffer().setContents(source2);
this.workingCopies[1].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
assertNoProblem(sourceChars, this.workingCopies[1]);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
public void testBug118823c() throws CoreException, InterruptedException {
try {
// Resources creation
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
String source1 = "class Test {}\n";
createFile(
"/P1/Test.java",
source1
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
String source2 =
"class A {\n" +
" Secondary s;\n" +
"}\n";
createFile(
"/P2/A.java",
source2
);
waitUntilIndexesReady();
this.workingCopies = new ICompilationUnit[2];
// Get first working copy and verify that there's no error
char[] sourceChars = source1.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0] = getCompilationUnit("/P1/Test.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's one error (missing secondary type)
this.problemRequestor.initialize(source2.toCharArray());
this.workingCopies[1] = getCompilationUnit("/P2/A.java").getWorkingCopy(this.wcOwner, null);
assertEquals("Working copy should not find secondary type 'Secondary'!", 1, this.problemRequestor.problemCount);
assertProblems("Working copy should have problem!",
"----------\n" +
"1. ERROR in /P2/A.java (at line 2)\n" +
" Secondary s;\n" +
" ^^^^^^^^^\n" +
"Secondary cannot be resolved to a type\n" +
"----------\n"
);
// Delete file and recreate it with secondary
deleteFile("/P1/Test.java");
source1 =
"public class Test {}\n" +
"class Secondary{}\n";
createFile(
"/P1/Test.java",
source1
);
// Get first working copy and verify that there's still no error
sourceChars = source1.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0].getBuffer().setContents(source1);
this.workingCopies[0].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
this.workingCopies[0].commitWorkingCopy(true, null);
assertNoProblem(sourceChars, this.workingCopies[0]);
// Get second working copy and verify that there's any longer error
sourceChars = source2.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[1].getBuffer().setContents(source2);
this.workingCopies[1].reconcile(AST.JLS3,
true, // force problem detection to see errors if any
null, // do not use working copy owner to not use working copies in name lookup
null);
assertNoProblem(sourceChars, this.workingCopies[1]);
} finally {
deleteProject("P1");
deleteProject("P2");
}
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=107931
// won't be fixed; this test watches the current behavior in case we change
// our mind
public void test1001() throws CoreException, InterruptedException, IOException {
try {
// Resources creation
String sources[] = new String[3];
char[] sourcesAsCharArrays[] = new char[3][];
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
sources[0] = "class X {}\n";
createFile(
"/P1/X.java",
sources[0]
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
sources[1] =
"interface I {\n" +
" void foo();\n" +
" void bar(X p);\n" +
"}\n";
createFile(
"/P2/I.java",
sources[1]
);
createJavaProject("P3", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P2" }, "bin");
sources[2] =
"class Y implements I {\n" +
" // public void foo() { }\n" +
" // public void bar(X p) { }\n" +
"}\n";
createFile(
"/P3/Y.java",
sources[2]
);
for (int i = 0 ; i < sources.length ; i++) {
sourcesAsCharArrays[i] = sources[i].toCharArray();
}
waitUntilIndexesReady();
this.workingCopies = new ICompilationUnit[3];
// Get first working copy and verify that there's no error
this.problemRequestor.initialize(sourcesAsCharArrays[0]);
this.workingCopies[0] = getCompilationUnit("/P1/X.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourcesAsCharArrays[0], this.workingCopies[0]);
// Get second working copy and verify that there's no error
this.problemRequestor.initialize(sourcesAsCharArrays[1]);
this.workingCopies[1] = getCompilationUnit("/P2/I.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourcesAsCharArrays[1], this.workingCopies[1]);
// Get third working copy and verify that all expected errors are here
this.problemRequestor.initialize(sourcesAsCharArrays[2]);
this.workingCopies[2] = getCompilationUnit("/P3/Y.java").getWorkingCopy(this.wcOwner, null);
assertProblems("Working copy should have problems:",
"----------\n" +
"1. ERROR in /P3/Y.java (at line 1)\n" +
" class Y implements I {\n" +
" ^\n" +
"The type Y must implement the inherited abstract method I.bar(X)\n" +
"----------\n" +
"2. ERROR in /P3/Y.java (at line 1)\n" +
" class Y implements I {\n" +
" ^\n" +
"The type Y must implement the inherited abstract method I.foo()\n" +
"----------\n");
} finally {
deleteProject("P1");
deleteProject("P2");
deleteProject("P3");
}
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=107931
// variant: having all needed projects on the classpath solves the issue
public void test1002() throws CoreException, InterruptedException, IOException {
try {
// Resources creation
String sources[] = new String[3];
char[] sourcesAsCharArrays[] = new char[3][];
createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
sources[0] = "class X {}\n";
createFile(
"/P1/X.java",
sources[0]
);
createJavaProject("P2", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" }, "bin");
sources[1] =
"interface I {\n" +
" void foo();\n" +
" void bar(X p);\n" +
"}\n";
createFile(
"/P2/I.java",
sources[1]
);
createJavaProject("P3", new String[] {""}, new String[] {"JCL_LIB"}, new String[] { "/P1" /* compare with test1001 */, "/P2" }, "bin");
sources[2] =
"class Y implements I {\n" +
" // public void foo() { }\n" +
" // public void bar(X p) { }\n" +
"}\n";
createFile(
"/P3/Y.java",
sources[2]
);
for (int i = 0 ; i < sources.length ; i++) {
sourcesAsCharArrays[i] = sources[i].toCharArray();
}
waitUntilIndexesReady();
this.workingCopies = new ICompilationUnit[3];
// Get first working copy and verify that there's no error
this.problemRequestor.initialize(sourcesAsCharArrays[0]);
this.workingCopies[0] = getCompilationUnit("/P1/X.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourcesAsCharArrays[0], this.workingCopies[0]);
// Get second working copy and verify that there's no error
this.problemRequestor.initialize(sourcesAsCharArrays[1]);
this.workingCopies[1] = getCompilationUnit("/P2/I.java").getWorkingCopy(this.wcOwner, null);
assertNoProblem(sourcesAsCharArrays[1], this.workingCopies[1]);
// Get third working copy and verify that all expected errors are here
this.problemRequestor.initialize(sourcesAsCharArrays[2]);
this.workingCopies[2] = getCompilationUnit("/P3/Y.java").getWorkingCopy(this.wcOwner, null);
assertProblems("Working copy should have problems:",
"----------\n" +
"1. ERROR in /P3/Y.java (at line 1)\n" +
" class Y implements I {\n" +
" ^\n" +
"The type Y must implement the inherited abstract method I.bar(X)\n" +
"----------\n" +
"2. ERROR in /P3/Y.java (at line 1)\n" +
" class Y implements I {\n" +
" ^\n" +
"The type Y must implement the inherited abstract method I.foo()\n" +
"----------\n"
);
} finally {
deleteProject("P1");
deleteProject("P2");
deleteProject("P3");
}
}
/*
* Ensure that fallthrough diagnostics are silenced by $FALL-THROUGH$ comments
*/
public void testFallthroughDiagnosis() throws CoreException, InterruptedException {
try {
// Resources creation
IJavaProject p1 = createJavaProject("P1", new String[] {""}, new String[] {"JCL_LIB"}, "bin");
p1.setOption(JavaCore.COMPILER_PB_FALLTHROUGH_CASE, JavaCore.ERROR);
String source =
"public class X {\n" +
" void foo(int i) {\n" +
" switch(i) {\n" +
" case 0:\n" +
" i ++;\n" +
" // $FALL-THROUGH$\n" +
" case 1:\n" +
" i++;\n" +
" /* $FALL-THROUGH$ */\n" +
" case 2:\n" +
" i++;\n" +
" case 3:\n" +
" }\n" +
" }\n" +
"}\n";
createFile("/P1/X.java", source);
this.workingCopies = new ICompilationUnit[1];
// Get first working copy and verify that there's no error
char[] sourceChars = source.toCharArray();
this.problemRequestor.initialize(sourceChars);
this.workingCopies[0] = getCompilationUnit("/P1/X.java").getWorkingCopy(this.wcOwner, null);
assertProblems("Working copy should have problems:",
"----------\n" +
"1. ERROR in /P1/X.java (at line 12)\n" +
" case 3:\n" +
" ^^^^^^\n" +
"Switch case may be entered by falling through previous case. If intended, add a new comment //$FALL-THROUGH$ on the line above\n" +
"----------\n"
);
} finally {
deleteProject("P1");
}
}
/*
* Ensure that the option ICompilationUnit.IGNORE_METHOD_BODIES is honored
*/
public void testIgnoreMethodBodies1() throws CoreException {
setWorkingCopyContents(
"package p1;\n" +
//{ObjectTeams: we don't check imports before analyze (see CUD.resolve())
/* orig:
"import p2.*;" +
"public class X {\n" +
*/
// trigger a different warning:
"public class X implements java.io.Serializable {\n" +
// SH}
" public int foo() {\n" + // force an error by not returning
" int i = 0;\n" +
" }\n" +
"}");
org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(AST.JLS3, ICompilationUnit.IGNORE_METHOD_BODIES, null, null);
// X.foo() not returning any value should not be reported
assertProblems("Working copy should have problems:",
"----------\n" +
"1. WARNING in /Reconciler/src/p1/X.java (at line 2)\n"+
//{ObjectTeams: expect different warning:
/* orig:
" import p2.*;public class X {\n" +
" ^^\n" +
"The import p2 is never used\n"+
:giro */
" public class X implements java.io.Serializable {\n" +
" ^\n" +
"The serializable class X does not declare a static final serialVersionUID field of type long\n" +
// SH}
"----------\n"
);
// statement declaring i should not be in the AST
assertASTNodeEquals(
"Unexpected participant ast",
"package p1;\n" +
//{ObjectTeams: different AST (see above):
/* orig:
"import p2.*;\n" +
"public class X {\n" +
:giro */
"public class X implements java.io.Serializable {\n" +
// SH}
" public int foo(){\n" +
" }\n" +
"}\n",
ast
);
}
public void testIgnoreMethodBodies2() throws CoreException {
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;" +
"public class X {\n" +
" public void foo() {\n" +
" int i = 0;\n" +
" }\n" +
" public int bar() {\n" +
" int i = 0;\n" +
" new X() /*start*/{\n" +
" }/*end*/;" +
" }\n" +
"}");
org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(AST.JLS3, ICompilationUnit.IGNORE_METHOD_BODIES, null, null);
// methods with anonymous classes should have their statements intact
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo(){\n" +
" }\n" +
" public int bar(){\n" +
" }\n" +
"}\n",
ast
);
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=130000
public void testIgnoreMethodBodies3() throws CoreException {
new ReconcileParticipant2();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;" +
"public class X {\n" +
" public void foo() {\n" +
" int i = 0;\n" +
" }\n" +
" public int bar() {\n" +
" int i = 0;\n" +
" new X() {\n" +
" };" +
" }\n" +
"}");
org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(
AST.JLS3,
ICompilationUnit.IGNORE_METHOD_BODIES | ICompilationUnit.ENABLE_STATEMENTS_RECOVERY,
null,
null);
// methods with anonymous classes should have their statements intact
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo(){\n" +
" }\n" +
" public int bar(){\n" +
" }\n" +
"}\n",
ast
);
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=130000
public void testIgnoreMethodBodies4() throws CoreException {
new ReconcileParticipant3();
setWorkingCopyContents(
"package p1;\n" +
"import p2.*;" +
"public class X {\n" +
" public void foo() {\n" +
" int i = 0;\n" +
" }\n" +
" public int bar() {\n" +
" int i = 0;\n" +
" new X() {\n" +
" };" +
" }\n" +
"}");
org.eclipse.jdt.core.dom.CompilationUnit ast = this.workingCopy.reconcile(
AST.JLS3,
ICompilationUnit.IGNORE_METHOD_BODIES,
null,
null);
// methods with anonymous classes should have their statements intact
assertASTNodeEquals(
"Unexpected ast",
"package p1;\n" +
"import p2.*;\n" +
"public class X {\n" +
" public void foo(){\n" +
" }\n" +
" public int bar(){\n" +
" }\n" +
"}\n",
ast
);
}
}