JDT/Core Breaking API changes

jdt core - Breaking API changes from R2.1 to R3.0
java development tooling core
This document lists all API changes (breaking or not) that occured between R2.1 and R3.0 and how to migrate from the R2.1 API to the R3.0 API.

# New API on `org.eclipse.jdt.core.dom.AST`

(in progress) Last edit: 2003/07/18

## Problem description

Creating an DOM/AST for a compilation unit costs a lot when the user wants only a subpart of the compilation unit to be populated. For example, only the statements of one method are useful and there is no need to create the statements of the other methods.

See also bug 40474.

## Problem resolution

Two new APIs have been added on `org.eclipse.jdt.core.dom.AST`.

-     public static org.eclipse.jdt.core.dom.CompilationUnit parsePartialCompilationUnit(
      		org.eclipse.jdt.core.ICompilationUnit unit,
      		int position,
      		boolean resolveBindings)

-     public static org.eclipse.jdt.core.dom.CompilationUnit parsePartialCompilationUnit(
      		org.eclipse.jdt.core.ICompilationUnit unit,
      		int position,
      		boolean resolveBindings,
      		org.eclipse.jdt.core.WorkingCopyOwner owner)

## Converting to the new API

None.

# IWorkingCopy is removed

(in progress) Last edit: 2003/07/03

## Problem description

Historically, `IWorkingCopy` gathered all working copy concerns, and `ICompilationUnit` implement this interface, though only the factory method makes sense for them; thus their implementation of the working copy features do nothing relevant to clients. `IWorkingCopy` also implements the spec'ed factory method, but it doesn't work for these.

See also bug 36987.

## Problem resolution

Interface `IWorkingCopy` is removed and all its functionality is moved to `ICompilationUnit`.

## Converting to the new API

Clients using `IWorkingCopy` and `ICompilationUnit` can adapt to this change by referencing `ICompilationUnit` instead of `IWorkingCopy` when a working copy is needed.

# Working copy factory methods return ICompilationUnit

(in progress) Last edit: 2003/07/03

## Problem description

Working copies were initialy designed to be editable elements on any `IJavaElement`. Pratice showed that they were used only to edit `ICompilationUnit`. This imposed downcasting to `IWorkingCopy` when using the working copy factory methods.

## Problem resolution

Factory methods that create `ICompilationUnits` (i.e. `getWorkingCopy`) now return an `ICompilationUint` instead of an `IJavaElement`.

## Converting to the new API

Clients using factory methods to create working copies can now remove the cast from `IJavaElement` to `IWorkingCopy`, `ICompilationUint` being compatible with `IWorkingCopy`.

# CharOperation.pathMatch(...) treats non absolute pattern as Ant does

Last edit: 2003/06/11 (->M2)

## Problem description

`CharOperation.pathMatch(...)` used to treat non absolute pattern `'foo'` as `'**/foo'` for free. This was inconsistent with Ant patternset rules.

## Problem resolution

`CharOperation.pathMatch(...)` no longer treat non absolute pattern `'foo'` as `'**/foo'` for free. This has no incidence on source folder exclusion patterns which are implicitely concatenating exclusion patterns to source folder paths when using them. Only direct clients to this `CharOperation` API will be affected.

## Converting to the new API

TODO

# Change in syntax error message ID

Last edit: 2003/06/11 (->M2)

## Problem description

TODO

## Problem resolution

The new diagnose of syntax errors use new error messages.

The following messages ID are added:

- IProblem.ParsingErrorInsertTokenBefore
- IProblem.ParsingErrorInsertTokenAfter
- IProblem.ParsingErrorDeleteToken
- IProblem.ParsingErrorDeleteTokens
- IProblem.ParsingErrorMergeTokens
- IProblem.ParsingErrorInvalidToken
- IProblem.ParsingErrorMisplacedConstruct
- IProblem.ParsingErrorReplaceTokens
- IProblem.ParsingErrorNoSuggestionForTokens
- IProblem.ParsingErrorUnexpectedEOF
- IProblem.ParsingErrorInsertToComplete
- IProblem.ParsingErrorInsertToCompleteScope
- IProblem.ParsingErrorInsertToCompletePhrase

The following messages ID are removed:

- IProblem.ParsingErrorNoSuggestion
- IProblem.ParsingErrorOnKeyword
- IProblem.ParsingErrorOnKeywordNoSuggestion
- IProblem.UnmatchedBracket
- IProblem.InvalidExpressionAsStatement

## Converting to the new API

TODO

# Force reload of .classpath file

Last edit: 2003/06/12 (->M2)

## Problem description

TODO

## Problem resolution

Added API `IJavaProject#forceClasspathReload(IProgressMonitor)` to force reload of `.classpath` file before next automatic update occurs.

    /**
     * Force the project to reload its .classpath file from disk and update the classpath accordingly.
     * Usually, a change to the .classpath file is automatically noticed and reconciled at the next
     * resource change notification event. If required to consider such a change prior to the next automatic
     * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
     * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
     * necessary.
     *
     * @param monitor a progress monitor for reporting operation progress
     * @exception JavaModelException if the classpath could not be updated. Reasons
     * include:
     *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)
     *  - Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
     *  - A entry of kind CPE_PROJECT refers to this project (INVALID_PATH)
     *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)
     *  - The output location path refers to a location not contained in this project (PATH_OUTSIDE_PROJECT)
     *  - The output location path is not an absolute path (RELATIVE_PATH)
     *  - The output location path is nested inside a package fragment root of this project (INVALID_PATH)
     *  - The classpath is being modified during resource change event notification (CORE_EXCEPTION)
     * @since 3.0
     */

## Converting to the new API

TODO

# Allow empty path to be equivalent to no source attachment

Last edit: 2003/06/13 (->M2)

## Problem description

`JavaCore.newLibraryEntry(...)` used to not allow an empty source attachment ( `new Path("")`) to be equivalent to no source attachment (i.e. `null`). This adjustment is made necessary for library entries generated from classpath variables which cannot be set to `null`. Also see bug 38531.

## Problem resolution

`JavaCore.newLibraryEntry(...)` will now allow an empty source attachment ( `new Path("")`) to be equivalent to no source attachment (i.e. `null`).

    * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
    *    or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
    *   and will be automatically converted to null.

## Converting to the new API

TODO

# Close the gap between compilation units and working copies

Last edit: 2003/06/27 (->M2)

## Problem description

TODO

See also bug 36888.

## Problem resolution

The following new APIs are added to `ICompilationUnit`:

-     /**
       * Changes this compilation unit handle into a working copy. A new IBuffer is
       * created using this compilation unit handle's owner. Uses the primary owner is none was
       * specified when this compilation unit handle was created.
       *
       * When switching to working copy mode, problems are reported to given
       * IProblemRequestor.
       *
       * Once in working copy mode, changes to this compilation unit or its children are done in memory.
       * Only the new buffer is affected. Using commitWorkingCopy(boolean, IProgressMonitor)
       * will bring the underlying resource in sync with this compilation unit.
       *
       * If this compilation unit was already in working copy mode, an internal counter is incremented and no
       * other action is taken on this compilation unit. To bring this compilation unit back into the original mode
       * (where it reflects the underlying resource), discardWorkingCopy must be call as many
       * times as becomeWorkingCopy.
       *
       * @param problemRequestor a requestor which will get notified of problems detected during
       * 	reconciling as they are discovered. The requestor can be set to null indicating
       * 	that the client is not interested in problems.
       * @param monitor a progress monitor used to report progress while opening this compilation unit
       * 	or null if no progress should be reported
       * @exception JavaModelException if this compilation unit could not become a working copy.
       * @see discardWorkingCopy
       * @since 3.0
       */
      void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;

-     /**
       * Commits the contents of this working copy to its underlying resource.
       *
       * It is possible that the contents of the original resource have changed
       * since this working copy was created, in which case there is an update conflict.
       * The value of the force parameter affects the resolution of
       * such a conflict:
       * - true - in this case the contents of this working copy are applied to
       * 	the underlying resource even though this working copy was created
       * 	before a subsequent change in the resource
       * - false - in this case a JavaModelException is thrown
       *
       * Since 2.1, a working copy can be created on a not-yet existing compilation
       * unit. In particular, such a working copy can then be committed in order to create
       * the corresponding compilation unit.
       *
       * @param force a flag to handle the cases when the contents of the original resource have changed
       * since this working copy was created
       * @param monitor the given progress monitor
       * @exception JavaModelException if this working copy could not commit. Reasons include:
       * - A CoreException occurred while updating an underlying resource
       * - This element is not a working copy (INVALID_ELEMENT_TYPES)
       * - A update conflict (described above) (UPDATE_CONFLICT)
       * @since 3.0
       */
      void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;

-     /**
       * Changes this compilation unit in working copy mode back to its original mode.
       *
       * This has no effect if this compilation unit was not in working copy mode.
       *
       * If becomeWorkingCopy was called several times on this
       * compilation unit, discardWorkingCopy must be called as
       * many times before it switches back to the original mode.
       *
       * @see becomeWorkingCopy
       * @exception JavaModelException if this working copy could not return in its original mode.
       * @since 3.0
       */
      void discardWorkingCopy() throws JavaModelException;

-     /**
       * Returns the working copy owner of this working copy.
       * Returns null if it is not a working copy or if it has no owner.
       *
       * @return WorkingCopyOwner the owner of this working copy or null
       * @since 3.0
       */
      WorkingCopyOwner getOwner();

-     /**
       * Returns a new working copy of this element if this element is not
       * a working copy, or this element if this element is already a working copy.
       *
       * Note: if intending to share a working copy amongst several clients, then
       * getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
       * should be used instead.
       *
       * When the working copy instance is created, an ADDED IJavaElementDelta is
       * reported on this working copy.
       *
       * Since 2.1, a working copy can be created on a not-yet existing compilation
       * unit. In particular, such a working copy can then be committed in order to create
       * the corresponding compilation unit.
       *
      * @param monitor a progress monitor used to report progress while opening this compilation unit
       * 	or null if no progress should be reported
       * @exception JavaModelException if the contents of this element can
       * 	not be determined.
       * @return a new working copy of this element if this element is not
       * 	a working copy, or this element if this element is already a working copy
       * @since 3.0
       */
      ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;

-     /**
       * Returns a shared working copy on this element using the given working copy owner to create
       * the buffer, or this element if this element is already a working copy.
       * This API can only answer an already existing working copy if it is based on the same
       * original compilation unit AND was using the same working copy owner (that is, as defined by Object.equals).
       *
       * The life time of a shared working copy is as follows:
       * - The first call to getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
       *   creates a new working copy for this element
       * - Subsequent calls increment an internal counter.
       * - A call to discardWorkingCopy() decrements the internal counter.
       * - When this counter is 0, the working copy is discarded.
       *
       * So users of this method must discard exactly once the working copy.
       *
       * Note that the working copy owner will be used for the life time of this working copy, that is if the
       * working copy is closed then reopened, this owner will be used.
       * The buffer will be automatically initialized with the original's compilation unit content
       * upon creation.
       *
       * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
       * working copy.
       *
       * Since 2.1, a working copy can be created on a not-yet existing compilation
       * unit. In particular, such a working copy can then be committed in order to create
       * the corresponding compilation unit.
       *
       * @param owner the working copy owner that creates a buffer that is used to get the content
       *  	of the working copy
       * @param problemRequestor a requestor which will get notified of problems detected during
       * 	reconciling as they are discovered. The requestor can be set to null indicating
       * 	that the client is not interested in problems.
       * @param monitor a progress monitor used to report progress while opening this compilation unit
       * 	or null if no progress should be reported
       * @exception JavaModelException if the contents of this element can
       *  	not be determined.
       * @return a new working copy of this element using the given factory to create
       * the buffer, or this element if this element is already a working copy
       * @since 3.0
       */
      ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;

And the following abstract class replaces `IBufferFactory`:

    /**
     * The owner of an ICompilationUnit handle in working copy mode.
     * An owner is used to identify a working copy and to create its buffer.
     *
     * @see ICompilationUnit#becomeWorkingCopy
     * @see ICompilationUnit#discardWorkingCopy
     * @since 3.0
     */
    public abstract class WorkingCopyOwner {
    	/**
    	 * Creates a buffer for the given working copy.
    	 * The new buffer will be initialized with the contents of the underlying file
    	 * if and only if it was not already initialized by the compilation owner (a buffer is
    	 * uninitialized if its content is null).
    	 *
    	 * @param workingCopy the working copy of the buffer
    	 * @return IBuffer the created buffer for the given working copy
    	 * @see IBuffer
    	 */
    	public IBuffer createBuffer(ICompilationUnit workingCopy) {
    		...
    	}
    }

To generalize the usage of a working copy owner (entire JavaModel is now aware of owned working copies), new APIs were added. These new APIs are copies of existing APIs augmented with a `WorkingCopyOwner` parameter, that defines the working copies to consider in the operation. When specifying an owner parameter, all working copies belonging to this owner will implicitly take precedence over primary ones (without requiring the owner to remember all its working copies, as in 2.1 era). Note that when no owned working copy is found, a primary unit will be considered instead, and since primary units have a built-in working copy (see `ICompilationUnit.becomeWorkingCopy(...)`), the primary unit may already be in working copy mode (very likely since an editor got opened on it). This means that an owner will already transparently see unsaved editor contents for all units for which it has no better working copy to contribute. The following new APIs were added:

- `AST.parseCompilationUnit(char[] source, String unitName, IJavaProject project, WorkingCopyOwner owner)`
- `AST.parseCompilationUnit(IClassFile classFile, boolean resolveBindings, WorkingCopyOwner owner)`
- `AST.parseCompilationUnit(ICompilationUnit unit, boolean resolveBindings, WorkingCopyOwner owner)`
- `IEvaluationContext.codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner)`
- `IEvaluationContext.codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)`
- `IDOMCompilationUnit.getCompilationUnit(IPackageFragment parent, WorkingCopyOwner owner)`
- `ICodeAssist.codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)`
- `ICodeAssist.codeSelect(int offset, int length, WorkingCopyOwner owner)`
- `ICompilationUnit.reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IJavaProject.findElement(IPath path, WorkingCopyOwner owner)`
- `IJavaProject.findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner)`
- `IJavaProject.findType(String fullyQualifiedName, WorkingCopyOwner owner)`
- `IJavaProject.newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IJavaProject.newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IPackageFragment.getCompilationUnit(String name, WorkingCopyOwner owner)`
- `IPackageFragment.getCompilationUnits(WorkingCopyOwner owner)`
- `IType.codeComplete(char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor, WorkingCopyOwner owner)`
- `IType.newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IType.newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IType.newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)`
- `IType.resolveType(String typeName, WorkingCopyOwner owner)`
- `JavaCore.create(IFile file, WorkingCopyOwner owner)`
- `JavaCore.create(IResource resource, WorkingCopyOwner owner)`
- `JavaCore.create(String handleIdentifier, WorkingCopyOwner owner)`
- `JavaCore.createCompilationUnitFrom(IFile file, WorkingCopyOwner owner)`
- `JavaCore.getWorkingCopies(WorkingCopyOwner owner)`
- `SearchEngine.SearchEngine(WorkingCopyOwner workingCopyOwner)`
- `SearchEngine.createHierarchyScope(IType type, WorkingCopyOwner owner)`

## Converting to the new API

TODO

# IJavaElement.getResource() returns a non null value for working copies

Last edit: 2003/06/18 (->M2)

## Problem description

`IJavaElement.getResource()` was specified to return `null` for working copies. This didn't make sense as this is a handle-only operation and an `IResource` is also a handle.

## Problem resolution

This restriction was removed and `IJavaElement.getResource()` now returns a non-`null` value for a working copy.

## Converting to the new API

TODO

# Rename getOriginalElement() into getPrimaryElement()

Last edit: 2003/06/20 (->M2)

## Problem description

The 2.1 API `IWorkingCopy.getOriginalElement()` returns an `IJavaElement`. In practice the original element for a working copy is always an `ICompilationUnit` whose owner is the primary owner.

## Problem resolution

`getPrimary()` was added on `ICompilationUnit` to return an `ICompilationUnit`. This new API replaces `getOriginalElement()`.

    /**
     * Returns the primary compilation unit (whose owner is the primary owner)
     * this working copy was created from, or this compilation unit if this a primary
     * compilation unit.
     * Note that the returned primary compilation unit can be in working copy mode.
     *
     * @return the primary compilation unit this working copy was created from,
     * or this compilation unit if it is primary
     * @since 3.0
     */
    ICompilationUnit getPrimary();

In the same manner, `IWorkingCopy.getOriginalElement(IJavaElement)` is replaced with `IJavaElement.getPrimaryElement()`.

    /**
     * Returns the primary element (whose compilation unit is the primary compilation unit)
     * this working copy element was created from, or this element if it is a descendant of a
     * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
     * binary member).
     * The returned element may or may not exist.
     *
     * @return the primary element this working copy element was created from, or this
     *		element.
     * @since 3.0
     */
    IJavaElement getPrimaryElement();

## Converting to the new API

TODO

# JavaCore.newLibraryEntry(...) no longer accepts a relative source attachment path

Last edit: 2003/06/30 (->M2)

## Problem description

The API `JavaCore.newLibraryEntry(IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, boolean isExported)` for creating a library classpath entry with a source attachment used to accept a relative source attachment path. It was spec'ed as such, but its implementation was too permissive.

## Problem resolution

From 3.0 on, an `IllegalArgumentException` will be raised if a non-relative source attachment path is provided. Note that the only exception to this rule is an empty path (answering `true` to `IPath.isEmpty()`) which is now automatically translated into `null` denoting no source attachment. In 3.0, a .classpath file will compact source attachments into project relative ones (as it does with other entry pathes already). During this process, relative pathes are known to be meaning project relative (internally when reading/writing the .classpath file). Externally, only absolute pathes are allowed to avoid confusion when reading/writing the .classpath file. The tolerance for empty relative pathes comes from the fact that it is possible for variable classpath entries can be resolved to library entries with no classpath. Then the variable source attachment needs to be positionned to a value meaning no source (`null`). However, assigning a classpath variable to `null` is not allowed (nullification is used to remove variables), thus an empty relative source path is tolerated to work around this limitation.

## Converting to the new API

TODO

# Read `.classpath` file contents even if project has not the java nature yet

Last edit: 2003/09/01 (->M4)

## Problem description

In 2.0 it was allowed to access IJavaProject.getOutputLocation/getRawClasspath on a project where the JavaNature was not set yet. Since 2.1 a JavaModelException is thrown if that happens. For example, the new Java project wizard does this if a .classpath file is found at the location where the project will be created.

## Problem resolution

Added API `IJavaProject#readRawClasspath()` to allow user to read the raw classpath from `.classpath` disk file on a java project which java nature has not been set yet.

    /**
     * Returns the raw classpath for the project as defined by its .classpath file from disk, or null
     * if unable to read the file.
     *
     * This classpath may differ from the in-memory classpath returned by getRawClasspath, in case the
     * automatic reconciliation mechanism has not been performed yet. Usually, any change to the .classpath file
     * is automatically noticed and reconciled at the next resource change notification event.
     * However, if the file is modified within an operation, where this change needs to be taken into account before the
     * operation ends, then the classpath from disk can be read using this method, and further assigned to the project
     * using setRawClasspath(...).
     *
     * A raw classpath may contain classpath variable and/or container entries. Classpath variable entries can be resolved
     * individually (see JavaCore#getClasspathVariable), or the full classpath can be resolved at once using the
     * helper method getResolvedClasspath.
     * TODO (jim) please reformulate to include classpath containers in resolution aspects
     *
     * Note that no check is performed whether the project has the Java nature set, allowing an existing .classpath
     * file to be considered independantly (unlike getRawClasspath which requires the Java nature to be associated
     * with the project).
     *
     * @return the raw classpath from disk for the project, as a list of classpath entries
     * @see #getRawClassPath
     * @see IClasspathEntry
     * @since 3.0
     */

Added API `IJavaProject#readOutputLocation()` to allow user to read the output location from `.classpath` disk file on a java project which java nature has not been set yet.

    /**
     * Returns the default output location for the project as defined by its .classpath file from disk, or null
     * if unable to read the file.
     *
     * This output location may differ from the in-memory one returned by getOutputLocation, in case the
     * automatic reconciliation mechanism has not been performed yet. Usually, any change to the .classpath file
     * is automatically noticed and reconciled at the next resource change notification event.
     * However, if the file is modified within an operation, where this change needs to be taken into account before the
     * operation ends, then the output location from disk can be read using this method, and further assigned to the project
     * using setRawClasspath(...).
     *
     * The default output location is where class files are ordinarily generated
     * (and resource files, copied). Each source classpath entry can also
     * specify an output location for the generated class files (and copied
     * resource files) corresponding to compilation units under that source
     * folder. This makes it possible to arrange generated class files for
     * different source folders in different output folders, and not
     * necessarily the default output folder. This means that the generated
     * class files for the project may end up scattered across several folders,
     * rather than all in the default output folder (which is more standard).
     *
     * @return the workspace-relative absolute path of the default output folder
     * @see #getOutputLocation
     * @since 3.0
     */

## Converting to the new API

TODO