/******************************************************************************* * Copyright (c) 2000, 2015 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 *******************************************************************************/ package org.eclipse.jdt.core.tests.model; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.dom.*; import org.eclipse.jdt.core.search.*; import org.eclipse.jdt.internal.core.ExternalJavaProject; import org.eclipse.jdt.internal.core.util.Util; import junit.framework.Test; /** * Tests APIs that take a WorkingCopyOwner. */ @SuppressWarnings("rawtypes") public class WorkingCopyOwnerTests extends ModifyingResourceTests { /** * Internal synonym for deprecated constant AST.JSL3 * to alleviate deprecation warnings. * @deprecated */ /*package*/ static final int JLS3_INTERNAL = AST.JLS3; ICompilationUnit workingCopy = null; public class TestWorkingCopyOwner extends WorkingCopyOwner { public String toString() { return "Test working copy owner"; } } public static Test suite() { return buildModelTestSuite(WorkingCopyOwnerTests.class); } // Use this static initializer to specify subset for tests // All specified tests which do not belong to the class are skipped... static { // TESTS_NAMES = new String[] { "testNewWorkingCopy03" }; // TESTS_NUMBERS = new int[] { 2, 12 }; // TESTS_RANGE = new int[] { 16, -1 }; } public WorkingCopyOwnerTests(String name) { super(name); } public void setUpSuite() throws Exception { super.setUpSuite(); createJavaProject("P"); createFile( "P/X.java", "public class X {\n" + "}" ); } public void tearDownSuite() throws Exception { deleteProject("P"); super.tearDownSuite(); } protected void tearDown() throws Exception { if (this.workingCopy != null) { this.workingCopy.discardWorkingCopy(); this.workingCopy = null; } super.tearDown(); } private void assertProblems(String expectedProblems, String path, String source, WorkingCopyOwner owner) throws JavaModelException { this.workingCopy = getWorkingCopy(path, source); ASTParser parser = ASTParser.newParser(JLS3_INTERNAL); parser.setSource(this.workingCopy); parser.setResolveBindings(true); parser.setWorkingCopyOwner(owner); CompilationUnit cu = (CompilationUnit) parser.createAST(null); assertProblems("Unexpected problems", expectedProblems, cu.getProblems(), source.toCharArray()); } protected void assertTypeBindingsEqual(String message, String expected, ITypeBinding[] types) { StringBuffer buffer = new StringBuffer(); if (types == null) { buffer.append("<null>"); } else { for (int i = 0, length = types.length; i < length; i++){ buffer.append(types[i].getQualifiedName()); if (i != length-1) { buffer.append("\n"); } } } if (!expected.equals(buffer.toString())) { System.out.println(org.eclipse.jdt.core.tests.util.Util.displayString(buffer.toString(), 2)); } assertEquals( message, expected, buffer.toString() ); } /* * Tests that a primary compilation unit can become a working copy. */ public void testBecomeWorkingCopy1() throws CoreException { this.workingCopy = getCompilationUnit("P/X.java"); assertTrue("should not be in working copy mode", !this.workingCopy.isWorkingCopy()); this.workingCopy.becomeWorkingCopy(null); assertTrue("should be in working copy mode", this.workingCopy.isWorkingCopy()); } /* * Tests that a working copy remains a working copy when becomeWorkingCopy() is called. */ public void testBecomeWorkingCopy2() throws CoreException { this.workingCopy = getCompilationUnit("P/X.java").getWorkingCopy(new TestWorkingCopyOwner(), null); assertTrue("should be in working copy mode", this.workingCopy.isWorkingCopy()); this.workingCopy.becomeWorkingCopy(null); assertTrue("should still be in working copy mode", this.workingCopy.isWorkingCopy()); } /* * Tests that a primary compilation unit is added from to its parent after it becomes a working copy and * there is no underlying resource. */ public void testBecomeWorkingCopy3() throws CoreException { this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); assertSortedElementsEqual( "Unexpected children of default package", "X.java [in <default> [in <project root> [in P]]]\n" + "[Working copy] Y.java [in <default> [in <project root> [in P]]]", getPackage("/P").getChildren()); } /* * Ensure an OperationCanceledException is correcly thrown when progress monitor is canceled */ public void testBecomeWorkingCopy4() throws CoreException { this.workingCopy = getCompilationUnit("P/X.java"); // count the number of time isCanceled() is called when converting this source unit CancelCounter counter = new CancelCounter(); this.workingCopy.becomeWorkingCopy(counter); this.workingCopy.discardWorkingCopy(); // throw an OperatonCanceledException at each point isCanceled() is called for (int i = 0; i < counter.count; i++) { boolean gotException = false; try { this.workingCopy.becomeWorkingCopy(new Canceler(i)); } catch (OperationCanceledException e) { gotException = true; } assertTrue("Should get an OperationCanceledException (" + i + ")", gotException); this.workingCopy.discardWorkingCopy(); } // last should not throw an OperationCanceledException this.workingCopy.becomeWorkingCopy(new Canceler(counter.count)); } /* * Tests that a primary working copy can be commited. */ public void testCommitPrimaryWorkingCopy() throws CoreException { try { IFile file = createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); String newContents = "public class Y {\n" + " void foo() {\n" + " }\n" + "}"; this.workingCopy.getBuffer().setContents(newContents); this.workingCopy.commitWorkingCopy(false, null); assertSourceEquals( "Unexpected source", newContents, new String(Util.getResourceContentsAsCharArray(file))); } finally { deleteFile("P/Y.java"); } } /* * Ensures that no delta is issued when a primary working copy that is consistent is commited. * (regression test for bug 40782 Primary working copies: unnecessary deltas on save) */ public void testDeltaCommitPrimaryWorkingCopy1() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); this.workingCopy.getBuffer().setContents( "public class Y {\n" + " void foo() {\n" + " }\n" + "}" ); this.workingCopy.makeConsistent(null); startDeltas(); this.workingCopy.commitWorkingCopy(false, null); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[*]: {PRIMARY RESOURCE}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that the correct delta is issued when a primary working copy that is not consistent is commited. */ public void testDeltaCommitPrimaryWorkingCopy2() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); this.workingCopy.getBuffer().setContents( "public class Y {\n" + " void foo() {\n" + " }\n" + "}" ); startDeltas(); this.workingCopy.commitWorkingCopy(false, null); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[*]: {CHILDREN | FINE GRAINED | PRIMARY RESOURCE}\n" + " Y[*]: {CHILDREN | FINE GRAINED}\n" + " foo()[+]: {}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that the correct delta is issued when a non-primary working copy is created. */ public void testDeltaCreateNonPrimaryWorkingCopy() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); ICompilationUnit cu = getCompilationUnit("P/Y.java"); startDeltas(); this.workingCopy = cu.getWorkingCopy(null); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[+]: {}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that the correct delta is issued when a primary compilation unit becomes a working copy. */ public void testDeltaBecomeWorkingCopy1() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); startDeltas(); this.workingCopy.becomeWorkingCopy(null); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[*]: {PRIMARY WORKING COPY}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that an ADDED delta is issued when a primary compilation unit becomes a working copy * and this compilation unit doesn't exist on disk. * (regression test for bug 44085 becomeWorkingCopy() should add the working copy in the model) */ public void testDeltaBecomeWorkingCopy2() throws CoreException { try { this.workingCopy = getCompilationUnit("P/Y.java"); startDeltas(); this.workingCopy.becomeWorkingCopy(null); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[+]: {PRIMARY WORKING COPY}" ); } finally { stopDeltas(); } } /* * Ensures that the correct delta is issued when a non-primary working copy is discarded. */ public void testDeltaDiscardNonPrimaryWorkingCopy() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); ICompilationUnit cu = getCompilationUnit("P/Y.java"); this.workingCopy = cu.getWorkingCopy(null); startDeltas(); this.workingCopy.discardWorkingCopy(); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " [Working copy] Y.java[-]: {}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that the correct delta is issued when a primary working copy becomes a compilation unit. */ public void testDeltaDiscardPrimaryWorkingCopy1() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); startDeltas(); this.workingCopy.discardWorkingCopy(); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " Y.java[*]: {PRIMARY WORKING COPY}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that the correct delta is issued when a primary working copy that contained a change * becomes a compilation unit. * (regression test for bug 40779 Primary working copies: no deltas on destroy) */ public void testDeltaDiscardPrimaryWorkingCopy2() throws CoreException { try { createFile( "P/Y.java", "public class Y {\n" + "}" ); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); this.workingCopy.getType("Y").createField("int x;", null, false, null); startDeltas(); this.workingCopy.discardWorkingCopy(); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " Y.java[*]: {CHILDREN | FINE GRAINED | PRIMARY WORKING COPY}\n" + " Y[*]: {CHILDREN | FINE GRAINED}\n" + " x[-]: {}" ); } finally { stopDeltas(); deleteFile("P/Y.java"); } } /* * Ensures that a REMOVED delta is issued when a primary working copy becomes a compilation unit * and this compilation unit doesn't exist on disk. * (regression test for bug 44084 No refresh when deleting edited unit) */ public void testDeltaDiscardPrimaryWorkingCopy3() throws CoreException { try { this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); startDeltas(); this.workingCopy.discardWorkingCopy(); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " Y.java[-]: {PRIMARY WORKING COPY}" ); } finally { stopDeltas(); } } /* * Ensures that a CONTENT delta is issued when a primary working copy becomes a compilation unit * with unsaved changes. * (regression test for bug 146012 No F_CONTENT flag on delta when reverting to old annotations) */ public void testDeltaDiscardPrimaryWorkingCopy4() throws CoreException { try { this.workingCopy = getCompilationUnit("P/X.java"); this.workingCopy.becomeWorkingCopy(null); this.workingCopy.getBuffer().setContents("/*annotation*/public class X {}"); startDeltas(); this.workingCopy.discardWorkingCopy(); assertWorkingCopyDeltas( "Unexpected delta", "P[*]: {CHILDREN}\n" + " <project root>[*]: {CHILDREN}\n" + " <default>[*]: {CHILDREN}\n" + " X.java[*]: {CONTENT | FINE GRAINED | PRIMARY WORKING COPY}" ); } finally { stopDeltas(); } } /* * Tests that a primary working copy is back in compilation unit mode when discardWorkingCopy() is called. */ public void testDiscardWorkingCopy1() throws CoreException { ICompilationUnit cu = null; try { cu = getCompilationUnit("P/X.java"); cu.becomeWorkingCopy(null); assertTrue("should be in working copy mode", cu.isWorkingCopy()); cu.discardWorkingCopy(); assertTrue("should no longer be in working copy mode", !cu.isWorkingCopy()); } finally { if (cu != null) { cu.discardWorkingCopy(); } } } /* * Tests that the same number of calls to discardWorkingCopy() is needed for primary working copy to be back * in compilation uint mode. */ public void testDiscardWorkingCopy2() throws CoreException { ICompilationUnit cu = null; try { cu = getCompilationUnit("P/X.java"); cu.becomeWorkingCopy(null); cu.becomeWorkingCopy(null); cu.becomeWorkingCopy(null); assertTrue("should be in working copy mode", cu.isWorkingCopy()); cu.discardWorkingCopy(); assertTrue("should still be in working copy mode", cu.isWorkingCopy()); cu.discardWorkingCopy(); cu.discardWorkingCopy(); assertTrue("should no longer be in working copy mode", !cu.isWorkingCopy()); } finally { if (cu != null) { int max = 3; while (cu.isWorkingCopy() && max-- > 0) { cu.discardWorkingCopy(); } } } } /* * Tests that the same number of calls to discardWorkingCopy() is needed for non-primary working copy * to be discarded. */ public void testDiscardWorkingCopy3() throws CoreException { try { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); this.workingCopy = cu.getWorkingCopy(owner, null); this.workingCopy = cu.getWorkingCopy(owner, null); assertTrue("should be in working copy mode", this.workingCopy.isWorkingCopy()); assertTrue("should be opened", this.workingCopy.isOpen()); assertTrue("should exist", this.workingCopy.exists()); this.workingCopy.discardWorkingCopy(); assertTrue("should still be in working copy mode (1)", this.workingCopy.isWorkingCopy()); assertTrue("should still be opened", this.workingCopy.isOpen()); assertTrue("should still exist", this.workingCopy.exists()); this.workingCopy.discardWorkingCopy(); this.workingCopy.discardWorkingCopy(); assertTrue("should still be in working copy mode (2)", this.workingCopy.isWorkingCopy()); assertTrue("should no longer be opened", !this.workingCopy.isOpen()); assertTrue("should no longer exist", !this.workingCopy.exists()); } finally { if (this.workingCopy != null) { int max = 3; while (this.workingCopy.isWorkingCopy() && max-- > 0) { this.workingCopy.discardWorkingCopy(); } } } } /* * Tests that a non-primary working copy that is discarded cannot be reopened. */ public void testDiscardWorkingCopy4() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); boolean gotException = false; try { this.workingCopy.getAllTypes(); } catch (JavaModelException e) { gotException = true; } assertTrue("should not get a JavaModelException before discarding working copy", !gotException); this.workingCopy.discardWorkingCopy(); gotException = false; try { this.workingCopy.getAllTypes(); } catch (JavaModelException e) { gotException = true; } assertTrue("should get a JavaModelException after discarding working copy", gotException); } /* * Tests that a primary working copy is removed from its parent after it is discarded and * there is no underlying resource. */ public void testDiscardWorkingCopy5() throws CoreException { ICompilationUnit cu = null; try { cu = getCompilationUnit("P/Y.java"); cu.becomeWorkingCopy(null); cu.discardWorkingCopy(); assertElementsEqual( "Unexpected children of default package", "X.java [in <default> [in <project root> [in P]]]", getPackage("/P").getChildren()); } finally { if (cu != null) { cu.discardWorkingCopy(); } } } /* * Ensures that a type that is otherwise missing can be looked up using the working copy owner. */ public void testFindType1() throws Exception { WorkingCopyOwner owner = new WorkingCopyOwner() { public String findSource(String typeName, String packageName) { if ("to.be".equals(packageName) && "Generated".equals(typeName)) { return "package to.be;\n" + "public class Generated {\n" + "}"; } return super.findSource(typeName, packageName); } public boolean isPackage(String[] pkg) { switch (pkg.length) { case 1: return "to".equals(pkg[0]); case 2: return "to".equals(pkg[0]) && "be".equals(pkg[1]); } return false; } }; assertProblems( "", "/P/X.java", "public class X extends to.be.Generated {\n" + "}", owner); } /* * Ensures that a type that is otherwise available can be hidden using the working copy owner. */ public void testFindType2() throws Exception { try { createFile("/P/Y.java", "public class Y {}"); WorkingCopyOwner owner = new WorkingCopyOwner() { public String findSource(String typeName, String packageName) { if ("".equals(packageName) && "Y".equals(typeName)) { return ""; } return super.findSource(typeName, packageName); } }; assertProblems( "1. ERROR in /P/X.java (at line 1)\n" + " public class X extends Y {\n" + " ^\n" + "Y cannot be resolved to a type\n" + "----------\n", "/P/X.java", "public class X extends Y {\n" + "}", owner); } finally { deleteFile("/P/Y.java"); } } /* * Ensures that getCorrespondingResource() returns a non-null value for a primary working copy. * (regression test for bug 44065 NPE during hot code replace) */ public void testGetCorrespondingResource() throws CoreException { ICompilationUnit cu = null; try { cu = getCompilationUnit("P/X.java"); cu.becomeWorkingCopy(null); assertResourceNamesEqual( "Unexpected resource", "X.java", new Object[] {cu.getCorrespondingResource()}); } finally { if (cu != null) { cu.discardWorkingCopy(); } } } /* * Ensures that getOwner() returns the correct owner for a non-primary working copy. */ public void testGetOwner1() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); assertEquals("Unexpected owner", owner, this.workingCopy.getOwner()); } /* * Ensures that getOwner() returns null for a primary compilation unit. */ public void testGetOwner2() { ICompilationUnit cu = getCompilationUnit("P/X.java"); assertEquals("Unexpected owner", null, cu.getOwner()); } /* * Ensures that getPrimary() on a non-primary working copy returns the primary compilation unit. */ public void testGetPrimary1() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); assertEquals("Unexpected compilation unit", cu, this.workingCopy.getPrimary()); } /* * Ensures that getPrimary() on a primary working copy returns the same handle. */ public void testGetPrimary2() throws CoreException { this.workingCopy = getCompilationUnit("P/X.java"); this.workingCopy.becomeWorkingCopy(null); assertEquals("Unexpected compilation unit", this.workingCopy, this.workingCopy.getPrimary()); } /* * Ensures that getPrimaryElement() on an element of a non-primary working copy returns * an element ofthe primary compilation unit. */ public void testGetPrimaryElement1() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); IJavaElement element = this.workingCopy.getType("X"); assertEquals("Unexpected element", cu.getType("X"), element.getPrimaryElement()); } /* * Ensures that getPrimaryElement() on an element of primary working copy returns the same handle. */ public void testGetPrimaryElement2() throws CoreException { this.workingCopy = getCompilationUnit("P/X.java"); this.workingCopy.becomeWorkingCopy(null); IJavaElement element = this.workingCopy.getType("X"); assertEquals("Unexpected element", element, element.getPrimaryElement()); } /* * Ensures that getPrimaryElement() on an package fragment returns the same handle. */ public void testGetPrimaryElement3() { IPackageFragment pkg = getPackage("P"); assertEquals("Unexpected element", pkg, pkg.getPrimaryElement()); } /* * Ensures that getPrimaryElement() on an initializer of a .class file returns the same handle. */ public void testGetPrimaryElement4() throws JavaModelException { IInitializer initializer = getClassFile("P/X.class").getType().getInitializer(1); assertEquals("Unexpected element", initializer, initializer.getPrimaryElement()); } /* * Ensures that the correct working copies are returned by JavaCore.getWorkingCopies(WorkingCopyOwner) */ public void testGetWorkingCopies() throws CoreException { ICompilationUnit workingCopy11 = null; ICompilationUnit workingCopy12 = null; ICompilationUnit workingCopy21 = null; try { // initialiy no working copies for this owner TestWorkingCopyOwner owner1 = new TestWorkingCopyOwner(); assertSortedElementsEqual( "Unexpected working copies (1)", "", JavaCore.getWorkingCopies(owner1) ); // create working copy on existing cu ICompilationUnit cu1 = getCompilationUnit("P/X.java"); workingCopy11 = cu1.getWorkingCopy(owner1, null); assertSortedElementsEqual( "Unexpected working copies (2)", "[Working copy] X.java [in <default> [in <project root> [in P]]]", JavaCore.getWorkingCopies(owner1) ); // create working copy on non-existing cu ICompilationUnit cu2 = getCompilationUnit("P/Y.java"); workingCopy12 = cu2.getWorkingCopy(owner1, null); assertSortedElementsEqual( "Unexpected working copies (3)", "[Working copy] X.java [in <default> [in <project root> [in P]]]\n" + "[Working copy] Y.java [in <default> [in <project root> [in P]]]", JavaCore.getWorkingCopies(owner1) ); // create working copy for another owner TestWorkingCopyOwner owner2 = new TestWorkingCopyOwner(); workingCopy21 = cu1.getWorkingCopy(owner2, null); // owner2 should have the new working copy assertSortedElementsEqual( "Unexpected working copies (4)", "[Working copy] X.java [in <default> [in <project root> [in P]]]", JavaCore.getWorkingCopies(owner2) ); // owner1 should still have the same working copies assertSortedElementsEqual( "Unexpected working copies (5)", "[Working copy] X.java [in <default> [in <project root> [in P]]]\n" + "[Working copy] Y.java [in <default> [in <project root> [in P]]]", JavaCore.getWorkingCopies(owner1) ); // discard first working copy workingCopy11.discardWorkingCopy(); assertSortedElementsEqual( "Unexpected working copies (6)", "[Working copy] Y.java [in <default> [in <project root> [in P]]]", JavaCore.getWorkingCopies(owner1) ); } finally { if (workingCopy11 != null) { workingCopy11.discardWorkingCopy(); } if (workingCopy12 != null) { workingCopy12.discardWorkingCopy(); } if (workingCopy21 != null) { workingCopy21.discardWorkingCopy(); } } } /* * Ensures that getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) * returns the same working copy if called twice with the same working copy owner. */ public void testGetWorkingCopy1() throws CoreException { try { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); assertEquals("Unexpected working copy", this.workingCopy, cu.getWorkingCopy(owner, null)); } finally { if (this.workingCopy != null) { int max = 2; while (this.workingCopy.isWorkingCopy() && max-- > 0) { this.workingCopy.discardWorkingCopy(); } } } } /* * Ensures that getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) * returns a different working copy if called twice with a different working copy owner. */ public void testGetWorkingCopy2() throws CoreException { ICompilationUnit workingCopy1 = null; ICompilationUnit workingCopy2 = null; try { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner1 = new TestWorkingCopyOwner(); workingCopy1 = cu.getWorkingCopy(owner1, null); TestWorkingCopyOwner owner2 = new TestWorkingCopyOwner(); workingCopy2 = cu.getWorkingCopy(owner2, null); assertTrue("working copies should be different", !workingCopy1.equals(workingCopy2)); } finally { if (workingCopy1 != null) { workingCopy1.discardWorkingCopy(); } if (workingCopy2 != null) { workingCopy2.discardWorkingCopy(); } } } /* * Ensure that the hierarchy using a working copy owner doesn't have primary working copy owner type * that are hidden by a type of the working copy owner * (regression test for bug 133372 [hierarchy] Type hierarchy returns type twice if executed on working copy layer) */ public void testHierarchy() throws CoreException { try { createFile( "/P/Y.java", "public class Y extends X {\n" + "}" ); WorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = getCompilationUnit("/P/Y.java").getWorkingCopy(owner, null/*no progress*/); IType focus = getCompilationUnit("/P/X.java").getType("X"); ITypeHierarchy hierarchy = focus.newTypeHierarchy(owner, null/*no progress*/); IType[] subtypes = hierarchy.getSubtypes(focus); assertTypesEqual( "Unexpected types", "Y\n", subtypes); } finally { deleteFile("/P/Y.java"); } } /* * Ensures that moving a primary working copy from one package to another removes that * working copy from the original package. * (regression test for bug 43847 IPackageFragment not updated after CUs have moved) */ public void testMoveWorkingCopy() throws CoreException { try { createFolder("/P/p1"); createFile( "/P/p1/Y.java", "package p1;\n" + "public class Y {\n" + "}" ); createFolder("/P/p2"); this.workingCopy = getCompilationUnit("P/p1/Y.java"); this.workingCopy.becomeWorkingCopy(null); // ensure the package is open getPackage("/P/p1").open(null); this.workingCopy.move(getPackage("/P/p2"), null, null, false, null); assertElementDescendants( "Unexpected content of /P/p1", "p1", getPackage("/P/p1")); } finally { deleteFolder("P/p1"); deleteFolder("P/p2"); } } /* * Ensures that creating a new working copy with no resource works. */ public void testNewWorkingCopy01() throws JavaModelException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); assertTrue("Working copy should exist", this.workingCopy.exists()); } /* * Ensures that the children of a new working copy with no resource are correct. */ public void testNewWorkingCopy02() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); assertElementDescendants( "Unexpected children", "[Working copy] X.java\n" + " class X", this.workingCopy); } /* * Ensures that the path of a new working copy with no resource is correct. */ public void testNewWorkingCopy03() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); assertEquals("Unexpected path", "/" + ExternalJavaProject.EXTERNAL_PROJECT_NAME + "/X.java", this.workingCopy.getPath().toString()); } /* * Ensures that the resource of a new working copy does not exist. */ public void testNewWorkingCopy04() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); assertFalse("Unexpected resource", this.workingCopy.getResource().exists()); } /* * Ensures that a new working copy with no resource can be reconciled and that the delta is correct. */ public void testNewWorkingCopy05() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); this.workingCopy.getBuffer().setContents( "public class X {\n" + " int field;\n" + "}" ); try { startDeltas(); this.workingCopy.reconcile(ICompilationUnit.NO_AST, false, null, null); assertWorkingCopyDeltas( "Unexpected delta", "X[*]: {CHILDREN | FINE GRAINED}\n" + " field[+]: {}" ); } finally { stopDeltas(); } } /* * Ensures that a new working copy with no resource can be reconciled and that the resulting AST is correct. */ public void testNewWorkingCopy06() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); this.workingCopy.getBuffer().setContents( "public class X {\n" + " int field;\n" + "}" ); CompilationUnit ast = this.workingCopy.reconcile(JLS3_INTERNAL, false, null, null); assertASTNodeEquals( "Unexpected AST", "public class X {\n" + " int field;\n" + "}\n", ast); } /* * Ensures that no bindings are created when reconciling a new working copy with no resource. */ public void testNewWorkingCopy07() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); this.workingCopy.getBuffer().setContents( "public class X {\n" + " int field;\n" + "}" ); CompilationUnit ast = this.workingCopy.reconcile(JLS3_INTERNAL, true/*force resolution*/, null, null); TypeDeclaration type = (TypeDeclaration) ast.types().get(0); assertNull("Unexpected binding", type.resolveBinding()); } /* * Ensures that a new working copy with no resource can be committed (its buffer is saved). */ public void testNewWorkingCopy08() throws CoreException { WorkingCopyOwner owner = new WorkingCopyOwner() { public IBuffer createBuffer(ICompilationUnit wc) { IBuffer buffer = new TestBuffer(wc); buffer.setContents( "public class X {\n" + "}" ); return buffer; } }; this.workingCopy = owner.newWorkingCopy("X.java", null/*no classpath*/, null/*no progress monitor*/); this.workingCopy.commitWorkingCopy(true, null); assertFalse("Should not have unsaved changes", this.workingCopy.hasUnsavedChanges()); } /* * Ensures that a Java project named " " doesn't exist if a working copy with no resource is created. * (regression test for bug 138999 Regression: Fix for 128258 introduces regression in JavaProject.exists()) */ public void testNewWorkingCopy09() throws CoreException { this.workingCopy = newExternalWorkingCopy( "X.java", "public class X {\n" + "}" ); assertFalse("Java project named \" \" should not exist", getJavaProject(ExternalJavaProject.EXTERNAL_PROJECT_NAME).exists()); } /** * Ensures that creating a DOM AST and computing the bindings takes the owner's working copies into account. * (regression test for bug 39533 Working copy with no corresponding file not considered by NameLookup) * @deprecated using deprecated code */ public void testParseCompilationUnit1() throws CoreException { ICompilationUnit workingCopy1 = null; ICompilationUnit workingCopy2 = null; try { TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); workingCopy1 = getCompilationUnit("P/X.java").getWorkingCopy(owner, null); workingCopy1.getBuffer().setContents( "public class X implements I {\n" + "}" ); workingCopy1.makeConsistent(null); workingCopy2 = getCompilationUnit("P/I.java").getWorkingCopy(owner, null); workingCopy2.getBuffer().setContents( "public interface I {\n" + "}" ); workingCopy2.makeConsistent(null); ASTParser parser = ASTParser.newParser(AST.JLS2); parser.setSource(workingCopy1); parser.setResolveBindings(true); parser.setWorkingCopyOwner(owner); CompilationUnit cu = (CompilationUnit) parser.createAST(null); List types = cu.types(); assertEquals("Unexpected number of types in AST", 1, types.size()); TypeDeclaration type = (TypeDeclaration)types.get(0); ITypeBinding typeBinding = type.resolveBinding(); assertTypeBindingsEqual( "Unexpected interfaces", "I", typeBinding.getInterfaces()); } finally { if (workingCopy1 != null) { workingCopy1.discardWorkingCopy(); } if (workingCopy2 != null) { workingCopy2.discardWorkingCopy(); } } } /** * Ensures that creating a DOM AST and computing the bindings takes the owner's working copies into account. * @deprecated using deprecated code */ public void testParseCompilationUnit2() throws CoreException { TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = getCompilationUnit("P/Y.java").getWorkingCopy(owner, null); this.workingCopy.getBuffer().setContents( "public class Y {\n" + "}" ); this.workingCopy.makeConsistent(null); char[] source = ( "public class Z extends Y {\n" + "}").toCharArray(); ASTParser parser = ASTParser.newParser(AST.JLS2); parser.setSource(source); parser.setUnitName("Z.java"); parser.setProject(getJavaProject("P")); parser.setWorkingCopyOwner(owner); parser.setResolveBindings(true); CompilationUnit cu = (CompilationUnit) parser.createAST(null); List types = cu.types(); assertEquals("Unexpected number of types in AST", 1, types.size()); TypeDeclaration type = (TypeDeclaration)types.get(0); ITypeBinding typeBinding = type.resolveBinding(); assertNotNull("No binding", typeBinding); assertEquals( "Unexpected super type", "Y", typeBinding.getSuperclass().getQualifiedName()); } /** * Ensures that creating a DOM AST and computing the bindings takes the owner's working copies into account. * @deprecated using deprecated code */ public void testParseCompilationUnit3() throws CoreException { try { createJavaProject("P1", new String[] {"src"}, new String[] {"JCL_LIB", "lib"}, "bin"); // create X.class in lib folder /* Evaluate the following in a scrapbook: org.eclipse.jdt.core.tests.model.ModifyingResourceTests.generateClassFile( "X", "public class X {\n" + "}") */ byte[] bytes = new byte[] { -54, -2, -70, -66, 0, 3, 0, 45, 0, 13, 1, 0, 1, 88, 7, 0, 1, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0, 3, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 12, 0, 5, 0, 6, 10, 0, 4, 0, 8, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 6, 88, 46, 106, 97, 118, 97, 0, 33, 0, 2, 0, 4, 0, 0, 0, 0, 0, 1, 0, 1, 0, 5, 0, 6, 0, 1, 0, 7, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 9, -79, 0, 0, 0, 1, 0, 10, 0, 0, 0, 6, 0, 1, 0, 0, 0, 1, 0, 1, 0, 11, 0, 0, 0, 2, 0, 12, }; this.createFile("P1/lib/X.class", bytes); // create libsrc and attach source createFolder("P1/libsrc"); createFile( "P1/libsrc/X.java", "public class X extends Y {\n" + "}" ); IPackageFragmentRoot lib = getPackageFragmentRoot("P1/lib"); lib.attachSource(new Path("/P1/libsrc"), null, null); // create Y.java in src folder createFile("P1/src/Y.java", ""); // create working copy on Y.java TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = getCompilationUnit("P1/src/Y.java").getWorkingCopy(owner, null); this.workingCopy.getBuffer().setContents( "public class Y {\n" + "}" ); this.workingCopy.makeConsistent(null); // parse and resolve class file IClassFile classFile = getClassFile("P1/lib/X.class"); ASTParser parser = ASTParser.newParser(AST.JLS2); parser.setSource(classFile); parser.setResolveBindings(true); parser.setWorkingCopyOwner(owner); CompilationUnit cu = (CompilationUnit) parser.createAST(null); List types = cu.types(); assertEquals("Unexpected number of types in AST", 1, types.size()); TypeDeclaration type = (TypeDeclaration)types.get(0); ITypeBinding typeBinding = type.resolveBinding(); ITypeBinding superType = typeBinding.getSuperclass(); assertEquals( "Unexpected super type", "Y", superType == null ? "<null>" : superType.getQualifiedName()); } finally { deleteProject("P1"); } } /* * Ensures that searching takes the owner's working copies into account. */ public void testSearch1() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/Y.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); this.workingCopy.getBuffer().setContents( "public class Y {\n" + " X field;\n" + "}" ); this.workingCopy.makeConsistent(null); SearchPattern pattern = SearchPattern.createPattern( "X", IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); JavaSearchTests.JavaSearchResultCollector resultCollector = new JavaSearchTests.JavaSearchResultCollector(); new SearchEngine(owner).search( pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, SearchEngine.createWorkspaceScope(), resultCollector, null); assertEquals( "Y.java Y.field [X]", resultCollector.toString()); } /* * Ensures that searching takes the owner's working copies into account. */ public void testSearch2() throws CoreException { ICompilationUnit cu = getCompilationUnit("P/X.java"); TestWorkingCopyOwner owner = new TestWorkingCopyOwner(); this.workingCopy = cu.getWorkingCopy(owner, null); // remove type X this.workingCopy.getBuffer().setContents(""); this.workingCopy.makeConsistent(null); SearchPattern pattern = SearchPattern.createPattern( "X", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); JavaSearchTests.JavaSearchResultCollector resultCollector = new JavaSearchTests.JavaSearchResultCollector(); new SearchEngine(owner).search( pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, SearchEngine.createWorkspaceScope(), resultCollector, null); assertEquals( "", // should not find any in the owner's context resultCollector.toString()); } /* * Ensures that searching takes the primary owner's working copies into account only if the working copy * is not saved. */ public void testSearch3() throws CoreException { try { createFile("/P/Y.java", ""); this.workingCopy = getCompilationUnit("P/Y.java"); this.workingCopy.becomeWorkingCopy(null); // create type Y in working copy this.workingCopy.getBuffer().setContents("public class Y {}"); this.workingCopy.makeConsistent(null); JavaSearchTests.JavaSearchResultCollector resultCollector = new JavaSearchTests.JavaSearchResultCollector(); search( "Y", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchEngine.createWorkspaceScope(), resultCollector); assertEquals( "Y.java Y [Y]", resultCollector.toString()); // commit new type this.workingCopy.commitWorkingCopy(false, null); resultCollector = new JavaSearchTests.JavaSearchResultCollector(); search( "Y", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchEngine.createWorkspaceScope(), resultCollector); assertEquals( "Y.java Y [Y]", resultCollector.toString()); } finally { deleteFile("/P/Y.java"); } } /* * Ensures that searching takes the primary owner's working copies and the given working copies into account. * (regression test for bug 43300 SearchEngine(IWorkingCopy[] workingCopies) not backward compatible) */ public void testSearch4() throws CoreException { ICompilationUnit primaryWorkingCopy = null; try { createFolder("P/p"); createFile("/P/p/Y.java", ""); primaryWorkingCopy = getCompilationUnit("P/p/Y.java"); primaryWorkingCopy.becomeWorkingCopy(null); // create type Y in working copy primaryWorkingCopy.getBuffer().setContents( "package p;\n" + "public class Y {\n" + "}"); primaryWorkingCopy.makeConsistent(null); // create new working copy on X.java and add type X this.workingCopy = getCompilationUnit("P/p/X.java").getWorkingCopy(null); this.workingCopy.getBuffer().setContents( "package p;\n" + "public class X {\n" + "}" ); this.workingCopy.makeConsistent(null); JavaSearchTests.JavaSearchResultCollector resultCollector = new JavaSearchTests.JavaSearchResultCollector(); IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] {primaryWorkingCopy.getParent()}); SearchPattern pattern = SearchPattern.createPattern( "*", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE); new SearchEngine(new ICompilationUnit[] {this.workingCopy}).search( pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, resultCollector, null); assertEquals( "p/X.java p.X [X]\n" + "p/Y.java p.Y [Y]", resultCollector.toString()); } finally { if (primaryWorkingCopy != null) { primaryWorkingCopy.discardWorkingCopy(); } deleteFile("/P/p/Y.java"); } } }