Bug 36888 - Close the gap between original and working copies
Summary: Close the gap between original and working copies
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.1   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.0 M2   Edit
Assignee: Jerome Lanneluc CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-04-25 07:30 EDT by Jerome Lanneluc CLA
Modified: 2003-10-16 13:57 EDT (History)
10 users (show)

See Also:


Attachments
code example (3.70 KB, text/plain)
2003-05-14 12:16 EDT, Martin Aeschlimann CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jerome Lanneluc CLA 2003-04-25 07:30:17 EDT
Build 2.1

Once a shared working copy is created, it would be used in place of its 
original element accross the Java model.

E.g. asking for the children of a pkg fragment would return a wrapper on each 
compilation unit: this wrapper would query the compilation unit if no shared 
working copy exists, it would use the shared working copy otherwise.
Comment 1 Philipe Mulet CLA 2003-04-25 08:38:41 EDT
Posted on newsgroup

Are there any client using shared working copies outside JDT/UI ? 

These working copies are meant to be reused in multiple spots (e.g. several 
editors in different windows) and thus provide some notion of sharing. This 
mechanism allows all editors pointing at the same file to be updated 
simultaneously when edits occur, since the underlying working copy and 
associated buffer is the same.

Moving towards 3.0, shared working copies seem to be still hard to manage, and 
bug report http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888 expresses the 
need to make these 'special' working copies being edited more transparent. A 
typical situation causing grief is the package explorer view, which needs to 
switch a child element from a compilation unit to its corresponding shared 
working copy, as soon as it gets open in an editor. These items aren't 
identical, and what they'd like instead is to have a unique handle onto the 
unit, which would be smart enough to understand it becomes edited and thus 
would switch to a working copy like behavior from thereon.

Currently, shared working copies are associated with a buffer factory, which is 
contributed by clients who care about these working copies. This mechanism 
allows to have each client manage its own set of shared working copies.

If moving away from these, and rather considering some smarter and more 
transparent compilation units instead, then naturally we wonder whether we 
should preserve supporting multiple clients or not.
If all clients are only interested in sharing the edited unit contents anyway, 
the multiple clients story is just unnecessary flexibility which will likely 
cause major API changes so as to provide the client viewpoint information when 
necessary.

Please answer the PR directly, so that the discussion gets archived.
Comment 2 Philipe Mulet CLA 2003-04-25 11:03:47 EDT
One thing to remember is that the buffer implementation for an edited unit is 
still customizable. This allows the client to reuse its underlying buffer 
implementation and just adapt it to our APIs.

This should be still preserved, and if loosing the multi-client approach, this 
would mean than once starting editing a unit, the first client who contributed 
a buffer implementation is winning. If we believe there is only one client 
anyway, this may not be an issue.

If we want to enable multiple clients, then each client can contribute its own 
buffer implementation, but all accesses need to mention explicitely which 
client is doing the work, since there would be no privileged default client.

i.e. all operations which can return IType elements would need to specify the 
client to consider so as to transparently reach the edited type. This would 
likely clutter lots of APIs.
Comment 3 Martin Aeschlimann CLA 2003-04-25 12:12:32 EDT
My suggestion is to eliminate the two kind of element showing up in UI by
introducing a new adapting Compilation Unit.

-Viewers currently have to listen to deltas to know when to replace elements
-Actions have to be aware that elements retrieved in selectionChanged can be
different to the elements available in 'run' (they have to retrieve the elements
again). When making modifications they must make sure that either an editor is
opened on the element (so the modification is done on a working copy) or have to
create and (when done) save a working copy.

The approach I want to suggest tries to be as non-breaking as possible. We
introduce a new adapting compilation unit which hides the two worlds (original
elements and shared working copy elements). All viewers now only show these
elements. The suggestion is to not change the control of the life-cycle of the
shared working copy: Creating and saving it is still controlled by the Java
editor, or, by the action.

ICompilationUnit.getAdaptingCompilationUnit(IBufferManager) : ICompilationUnit

returns a IComilationUnit that is from now on the compilation unit shown by
viewers. This adapting compilation unit can be requested at any time, regardless
if the original element has a shared working copy or not. The adapting
compilation unit and its children internally switch the element infos between
original and shared working copy, depending on the creation/release of the
shared working copy.
- If no shared working copy exists: Adapting compilation unit internally points
to the buffer of the original
- If a shared working copy exists: Adapting compilation unit internally points
to the buffer of the shared working copy

A Java element delta is offered for this adapting compilation unit that is equal
to the shared working copy delta when a shared working copy exists or the
original delta when no shared working copy exists.

The advantage of this solution is that viewers can now show the adapting working
copy instead of the original and don't have to be aware of editor
creations/close. They now only have to listen to one delta. 

When calling a create method (e.g. createMethod) on a adapting element
- If no shared working copy exists: Modification is done on the original
(includes a save, resource modification)
- If a shared working copy exists: Modification is done on the shared working
copy (no save)

The switch from original to working copy is still performed through a call of
ICompilationUnit.getSharedWorkingCopy (called on the original) or on
IWorkingCopy.release() (called on the shared working copy)

Original elements and shared working copy elements still are available and have
the same role in the system. Views written for 2.0, tracking the switching from
original to working copy still can do so.
For compatibility reasons, Actions have to be ready for getting original or
shared working copies, but can convert them once ('toAdaptingElement') and then
stick to them.

An adapting working copy is parameterized with the BufferManager.

There should be no memory overhead with the adapted elements:
- Only new handles are created. No new element infos
- If all views are rewritten for the new elements, we even reduce the number of
created handles as we have now only one world instead of two.
Comment 4 Martin Aeschlimann CLA 2003-04-25 12:38:32 EDT
Suggestion b.) is a bit more breaking. The idea is to merge the adapting
compilation unit suggested in comment #3 into the existing 'shared working copy':

A shared working copy has a reference count which is increased when
getSharedWorkingCopy is called and decreased on 'destroy'.
When the counter is 0, the shared working copy is destroyed: it does not exist
anymore and all accesses to its buffer or members throw a JavaModelException
(viewer have to switch to originals).

The suggestion is to allow a reference count of 0. A shared working copy can be
requested even if the reference count is 0. In this case the shared working copy
is equal to the original and uses the buffer/infos of the original (...adapts to
the original...)
As soon as the reference count goes from 0 to 1, all its infos are flushed and
the new buffer is used. When the count changes from 1 to 0, again all infos are
flushed.
This new behavior only applies to the working copies marked as 'shared' working
copy. The delta created for the shared working copy has to be augmented.

Having this change, all views can now directly show the 'shared working copy'
and only have to listen to the shared working copy delta.

There is no memory overhead; no buffers/new infos are created until an editor is
created.
Comment 5 Philipe Mulet CLA 2003-04-28 05:23:32 EDT
I agree with the fact that a separate layer (adapting units in Martin's 
comment) allow to still reach the original elements. However, these require a 
new kind of elements, and APIs for them as well. There would not be much 
transparency, except that the handle onto these entities would be stable. But, 
in order to reach these, new APIs have to be defined so as to pass along the 
IBufferFactory, which identifies the client.

Also, if nobody else is using shared working copies, I'd rather discard them 
alltogether, instead of maintaining yet another story which nobody uses.
Comment 6 Philipe Mulet CLA 2003-04-28 07:10:15 EDT
We would do the following:
- define IEditableCompilationUnit (prefer this to adapting unit)
- change IWorkingCopy to subclass ICompilationUnit (instead of the opposite 
currently)
- have IEditableCompilationUnit implements IWorkingCopy and have the 
characteristics of a shared working copy (as of today) which would map to a 
compilation unit contents when nobody is editing it.

We are trying to measure the API breakage.
Comment 7 Philipe Mulet CLA 2003-04-28 08:30:58 EDT
Entered separate bug 36876 for working copy hierarchy issue.
Comment 8 Philipe Mulet CLA 2003-04-28 09:31:48 EDT
Current thinking is to name those new unit handles IWorkingCopyAdapter (since 
they adapt units to working copies transparently). Then in order to switch it 
to a working copy (when starting editing it), an API would be used: 
#becomeWorkingCopy().

From thereon, it would naturally behave as a working copy (#destroy, #commit).

How does this sound to clients ?
Comment 9 Jerome Lanneluc CLA 2003-04-29 03:18:40 EDT
Working copy hierarchy issue is bug 36987.
Comment 10 Martin Aeschlimann CLA 2003-04-29 15:45:34 EDT
Sounds good to me. Does the EditableCompilationUnit still contain a counter like
the shared working copies do? I think they should otherwise client code becomes
quite tricky as the client needs to remember who created the
EditableCompilationUnit.
Comment 11 Dirk Baeumer CLA 2003-04-30 03:41:49 EDT
The presented interface sounds good to me as well (given Martin's comments). 
Thinking about the IEditableCompilationUnit I would now propose that 
manipulating an original working copy should be forbidden (if the breaking is 
not to big). This would mean a client must always create a 
IEditableCompilationUnit, apply the changes to this object and then commit 
them back to the original. What do you think ?
Comment 12 Jerome Lanneluc CLA 2003-04-30 04:41:46 EDT
Yes, an IWorkingCopyAdapter would have a counter: calling becomeWorkingCopy() 
would increment it, and calling destroy() would decrement it. 

Note we prefer to call it IWorkingCopyAdapter (instead of 
IEditableCompilationUnit) as this doesn't imply that the client is a UI client.
Comment 13 Jerome Lanneluc CLA 2003-04-30 04:52:32 EDT
Dirk, I'm not sure I understand the advantage of your proposal.
Comment 14 Dirk Baeumer CLA 2003-04-30 05:04:44 EDT
Cleaner model (we are working this way anyway as far as I know). And it might 
give us some advantages when doing more stuff in parallel. Then we know that 
the original CU is "particial" read-only (except for the case of a commit of 
an IWorkingCopyAdapter).
Comment 15 Jerome Lanneluc CLA 2003-04-30 07:37:35 EDT
To do stuff in parallel (I guess you meant that you want to create several 
IWorkingCopyAdapaters on a given compilation unit), do you agree that you need 
to pass some sort of client ID to all the Java model operations so that the 
right IWorkingCopyAdapter would be returned by the Java model operation? 

I'm thinking about refactoring here: you first need to search in the working 
copies corresponding to open editors (client ID for the search operation would 
be "Java editor"), then you need to create new working copies that contain the 
potential changes and resolve in this new working copies (client ID for the 
resolve operation would be "Java refactoring").
Comment 16 Philipe Mulet CLA 2003-04-30 07:44:16 EDT
To Dirk's last comment: maybe we could add notion of read-only-ness for working 
copy adapters which aren't in working copy mode.

As said Jerome, last thinking also surfaces the notion of an 
IWorkingCopyClient, denoting the one who requested this working copy creation, 
and may care about it later on (same idea as the buffer factory in the past). 
The client would still be used to find the buffer to use, and could be asked 
other questions like a clientID which we could use to serialize such handles 
(mementos). 

In order to step further, we want to also support the fact that operations 
which perform resolution against other units, have a way to indicate that they 
prefer to use their working copies in place of underlying units. This would 
allow for instance reconciling against other editor contents, whithout 
requiring to save buffer contents.

This desire has been expressed in various other bug reports, and this means 
that we would need to pass along a reference onto the client in quite a number 
of APIs. 

One more thing. We anticipate that some clients may want to be aware of each 
other, e.g. refactoring client may want to provide working copies based on 
edited units (as opposed to forcing editor contents to be saved before 
proceeding). We would thus allow some client composition to be achieved through 
some delegation, so that the editor buffer can be reused by refactoring 
automatically. Is this need any real, or just extra unnecessary complexity ? 
(this wouldn't be another API breakage, just extra flexibility).

Last, regular working copies would also benefit from this client approach. WC 
adapters would only have the transparency mode as an extra behavior.

Comment 17 Martin Aeschlimann CLA 2003-04-30 12:17:29 EDT
Let's just have one dedicated BufferManager, describing the
IWorkingCopyAdapaters  world. A UI less text infrastructure plugin
(resources.text) should define this buffer manager.

The client IDs could come into the game when creating working copies of a
IWorkingCopyAdapaters.
Comment 18 Jerome Lanneluc CLA 2003-04-30 12:25:35 EDT
What would the BufferManager API look like?
Comment 19 Philipe Mulet CLA 2003-04-30 12:42:51 EDT
The notion of buffer manager suggests some caching strategy. A client sounds 
more generic, and can be requested to create a buffer (which we can cache later 
on, as we do currently). We may ask it a few more questions down the road than 
just the buffer (its mementoID for instance).

I also think it should be an abstract type, so that it can later be augmented 
in term of APIs in a non-breaking way.
Comment 20 Dirk Baeumer CLA 2003-05-02 06:22:22 EDT
Regarding comment #16:

this is a real need, but another solution would be (this is how it works right 
now):

1. collect the set of effected compilation units using IWorkingCopyAdapters.
2. for precondition checking we create a new set of working copies form
   the IWorkingCopyAdapters from step 1. We change those working copies and
   do the analysis.
3. apply the changes to the IWorkingCopyAdapters if 2. was successful.

So from refactoring prespective there is no need for a client id in the 
IWorkingCopyAdapter world.
Comment 21 Jerome Lanneluc CLA 2003-05-05 06:38:30 EDT
From bug 36232, I understand you want to take the IWorkingCopyAdapters into 
account during the analysis in step 2. To do so, you would need to pass all the 
IWorkingCopyAdapters to the resolve operation, but a simpler solution would be 
to pass the client ID (that we also call IWorkingCopyClient) to the resolve 
operation, don't you think?
Comment 22 Dirk Baeumer CLA 2003-05-05 06:43:36 EDT
Jerome, you are right. A client id would make life easier in the refactoring 
world. Currently we manage the "virtual world" by our own.
Comment 23 Philipe Mulet CLA 2003-05-05 07:07:39 EDT
Just some thought. Given most APIs would need to be revisited to pass an extra 
argument denoting the client (or working copies instead). Wouldn't it be 
simpler to set the default client at a convenient location, and then use this 
one from thereon ? A convenient location for defining this would be JavaModel 
batch operation. 
Comment 24 Philipe Mulet CLA 2003-05-05 08:14:55 EDT
Even further thinking...

We could unify compilation units and working copies into one entity. Pretty 
much our working copy adapter would be promoted as true compilation units.

Some global API would allow clients to check-in/out, and from thereon all our 
APIs would answer results specific to this implicit client.

e.g. when JDT/UI starts up, it would register its editor client, and subsequent 
use of our APIs would transparently reflect the editor contents. Other clients 
would not be able to tell the difference in between an edited unit and a unit 
on filesystem (except if using #isWorkingCopy()).

We could imagine to allow client layers. For instance, refactoring would 
usually want to perform its modification starting from editor contents. Thus, 
it could register a refactoring client which would provide this new layer. The 
UI client would still be alive underneath. Then, when refactoring creates its 
working copies, they would be associated with the buffer contents implicitly 
obtained from the enclosing client (UI).

Multiple clients would still be supported, and could be nested in each other.

Consequently, separate working copies would not longer be necessary. Regular 
units would intrinsically support their functionalities once becoming such.

In term of API, this means less changes than previous approaches, except that 
IWorkingCopy would disappear alltogether.
Comment 25 Jerome Lanneluc CLA 2003-05-13 10:35:22 EDT
So the new proposal is as follow:

1. IWorkingCopy disapears. Clients will manipulate ICompilationUnits only.

2. An ICompilationUnit handle is still implicetly defined by its path, but 
   also by a CompilationUnitOwner. So 2 ICompilationUnits on the same IResource 
   are equal only if their owners are equal.

3. A run operation (tentatively on the abstract class CompilationUnitOwner)
   will define which is the current owner. During this run operation, created 
   ICompilationUnit handles (e.g. through 
   IPackageFragment.getCompilationUnits()) will have the current owner. This 
   run operation will also allow owner nesting: the ICompilationUnit handle
   will be created with the inner most owner.

4. For a given owner, an ICompilationUnit can have 2 modes: a file mode and a
   working copy mode. 
   In file mode (mode by default), operations on the ICompilationUnit handle
   use a default buffer populated from the underlying IFile.
   In working copy mode, operations on the ICompilationUnit handle use a buffer
   created by the owner. This replaces IBufferFactory.createBuffer(...).

5. An ICompilationUnit in file mode becomes an ICompilationUnit in working copy
   mode using the becomeWorkingCopy() protocol. It switches back to file mode
   using the discardWorkingCopy() protocol. An internal counter is maintained
   so that the same number of calls to discardWorkingCopy() as to 
   becomeWorkingCopy() must be done before the ICompilationUnit switches back
   to file mode.

6. In working copy mode only, commitWorkingCopy() allows to save the content of
   the buffer to the underlying IFile.

7. In addition to the createBuffer(...) protocol, a CompilationUnitOwner also
   provides protocols to pass in an IProblemRequestor used to report problems
   in working copy mode and a owner ID used to create a memento of the
   ICompilationUnit.

8. If no client is specified (i.e. the ICompilationUnit has been created
   outside the CompilationUnitOwner run operation), a default
   CompilationUnitOwner will be used and attempting to switch the 
   ICompilationUnit in working copy mode will be refused.

9. As several clients may create ICompilationUnit handles on the same IFile but
   with different owners, they will need to pass in the owner they're 
   interested in when registring for Java element changes.
   Thus the IJavaElementDelta will contain ICompilationUnit handles for a given
   owner.

10. The following protocols that were on IWorkingCopy will be moved to
    ICompilationUnit:
      - findElements(IJavaElement)
      - findPrimaryType()
      - getOriginal(IJavaElement)
      - getOriginalElement()
      - isBasedOn(IResource)
      - isWorkingCopy()
      - reconcile()
      - reconcile(boolean, IProgressMonitor)
      - restore()
     Thus all protocols having to do with the creation of working copies
     (getWorkingCopy(...), getSharedWorkingCopy(...), etc.)will disapear. 
     becomeWorkingCopy() will play their role. destroy() will be replaced by
     discardWorkingCopy()

11. The protocols for creating a hierarchy (e.g. 
    IType.newTypeHierarchy(IWorkingCopy[], ...) or for searching (e.g. 
    SearchEngine(IWorkingCopy[]) will disapear. Clients would use a 
    CompilationUnitOwner run operation instead.

We expect to first deprecate IWorkingCopy and all protocols described above 
to make the transition easier.

Comments are welcome.
Comment 26 Philipe Mulet CLA 2003-05-13 11:01:08 EDT
Not yet addressed, but on the list:
12- some mechanism for delegating amongst owners should be proposed. For 
instance, refactoring may be interested in getting UI (editor) client buffer 
contents somewhat transparently.

13- we should no longer support editing directly compilation units, but only 
working copies (some JDOM operations currently allow modifying units in file 
mode).

Comment 27 Martin Aeschlimann CLA 2003-05-14 12:16:33 EDT
Created attachment 4874 [details]
code example

To understand what point 3 would mean for the client code I tried to create an
example content provider as well as an example action: If I understood right,
all accesses to the Java model have to be done in a runnable: So whenever Java
Core needs the current CompilationUnitOwner it can find it in the call stack.

I assumed that a runnable is required for all accesses to the Java model, not
just 
packageFragment.getCompilationUnit()
Comment 28 Martin Aeschlimann CLA 2003-05-14 12:40:25 EDT
Problems to be mentioned:
- It's hard to pass return values and thrown exceptions out of a runnable
- What happens if an JDT action gets a ICompilation that is not from us? What if
it gets a mixed selection?
- What happens if you access a ICompilation of an other owner (in your own runnable)
- All JDT UI code has to be rewritten, including client code that wants to work
with 'our' compilation units
- Everybody who wants to work in 'our' world has to get the
JDTCompilationUnitOwner. If it is defined in JDT-UI, all clients need to know JDT-UI



Comment 29 Jerome Lanneluc CLA 2003-05-14 13:08:50 EDT
> I assumed that a runnable is required for all accesses to the Java model, 
> not just packageFragment.getCompilationUnit()
You need the runnable only when creating a handle for a compilation unit (or 
inside a compilation unit). Handles for IPackageFragment, IJavaProject, etc 
don't need to be in a runnable.

> It's hard to pass return values and thrown exceptions out of a runnable
The only other alternative would be to pass the CompilationUnitOwner to all 
Java model APIs that may create a ICompilationUnit handle. That would be too 
many.

> What happens if an JDT action gets a ICompilation that is not from us? What 
> if it gets a mixed selection?
Same as would happen if it got an IWorkingCopy that was not from you.

> What happens if you access a ICompilation of an other owner (in your own
> runnable)
It would behave normally (as if you would access an IWorkingCopy that you 
didn't create)

> All JDT UI code has to be rewritten, including client code that wants to work
> with 'our' compilation units
What do you mean by 'rewritten'?

> Everybody who wants to work in 'our' world has to get the
> JDTCompilationUnitOwner. If it is defined in JDT-UI, all clients need to know
> JDT-UI
Right
Comment 30 Dani Megert CLA 2003-05-15 05:14:18 EDT
The proposal suggests not to code any working copy / owner information into the
handle. Currently markers do not allow objects other than Boolean, String and
Integer to be stored in them therefore we store the handle identifier
(IJavaElement.getHandleIdentifier()) in the marker. Currently when accessing the
marker later we have ugly code which tries to figure out whether the handle
identifier belongs to a (still existing) working copy or to a compilation unit.
Am I right that such code will still be necessary with you proposal?
Comment 31 Jerome Lanneluc CLA 2003-05-15 05:25:41 EDT
Funny, we just talked about it. The idea would be that you would call 
JavaCore.create(String) in a runnable on your CompilationUnitOwner. The 
resulting ICompilationUnit handle would have your CompilationUnitOwner. It 
would then know if it is in working copy mode or in file mode.
Comment 32 Martin Aeschlimann CLA 2003-05-15 09:32:17 EDT
I think the example code shows that forcing the client to do most accesses to
JavaModel in a runnable are very clumbsy. Of course I agree with Jerome than
adding a CompilationUnitOwner to most of the JavaModel API is scary too.
So here is another proposal, based on the latest, tring to simplify the model.

8*. If no client is specified (i.e. the ICompilationUnit has been created
outside the CompilationUnitOwner run operation), a default CompilationUnitOwner
is used which describes the world as seen by the JDT editors and views. Working
copy mode is supported.
This Primary CompilationUnitOwner is created and owned by JDT-Core on plugin
startup using a text-buffer infrastructure offered by UI-independend plugin
org.eclipse.platform.text (to be implemented).

12*. Client created CompilationUnitOwners are based on a parent
CompilationUnitOwner (e.g. Primary CompilationUnitOwner). Analog to point 4;
they are either in 'parent' mode (content is the same as the parent content) or
in working copy mode. A commit does change the content of the parent.

14 (new). Client created CompilationUnitOwners only have the life span of a
runnable: When the runnable terminates, all compilation units that are in
working copy mode (=not commited) are discarded, no buffers are kept. While in a
runnable it is not possible to modify ComilationUnits of other owners except the
parent by committing a own compilation unit.

The idea of point 8*. is that it is not realistic that there will be 2 or more
primary worlds, e.g. 2 editors of the same file with different contents.
Contributed tools and actions want to work on the most current JDT world as in
the editor. As such contributions can be headless (UI-independend) the
conclusion is that a core plugin has to provide such a primary CompilationUnitOwner.

To limit a client CompilationUnitOwner to a life span of a runnable (14) is
intended to simplify the model. It avoids problems like: - What happens if there
is a change in a parent compilation unit (can not happen because parent
compilation units can not be changed while a runnable is active). - Multiple
worlds existing at the same time: e.g 2 viewers show same compilation unit but
of different worlds: Do actions have to be aware of multiple worlds? (can not
happen except if a client runnable would explicitly call one of our actions)

Comment 33 Jerome Lanneluc CLA 2003-05-15 10:37:27 EDT
Based on our current thinking (not yet taking Martin's comment #32 into 
account), I posted a version of org.eclipse.jdt.core with the new APIs. You can 
find it at:
http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/jdt-core-
home/patches/org.eclipse.jdt.core_bug36888_3.0.0.zip
Comment 34 Jerome Lanneluc CLA 2003-05-15 11:56:45 EDT
> 8*. ...
If I undertand you correctly, the buffer creation mechanism is contributed to 
jdt.core through an extension point. What if another plugin contributes to this 
extension point? If it is loaded before jdt.ui, then the world would not be the 
one jdt.ui expects.
Comment 35 Martin Aeschlimann CLA 2003-05-15 13:12:57 EDT
No, not contributed. Defined by jdt.core or a plugin required by jdt.core.
Something like org.eclipse.text would offer the infrastructure (IDocument,
DocumentProvider) and care about annotations ect. so you would have something
like JavaCore.getPrimaryBufferManager().
Comment 36 Jerome Lanneluc CLA 2003-05-16 04:55:10 EDT
Is this platform.text plugin on the plan, or is this just hypothetical?
Comment 37 Dani Megert CLA 2003-05-16 04:57:28 EDT
it exists for a while ;-)
Comment 38 Philipe Mulet CLA 2003-05-16 05:25:52 EDT
The notion of default cu owner is tied with the filesystem. i.e. through the 
default owner, you can never see working copies.

What you suggest is that it tolerates #becomeWorkingCopy, using a global custom 
buffer factory defined in PLATFORM/TEXT. However, from thereon, nobody else can 
access filesystem units, until the editor closes and saves its changes.

I can see this being useful for JDT/UI, but other clients may not be interested 
by editor contents and would be burnt by this approach.

The new working copy APIs should not be reserved to other clients than JDT/UI, 
where JDT/UI has a privileged way to register its own customizations. Either we 
support no other client or all of them.

The remaining options are:
1- make the cu owner explicit, and add basically one argument in all/most of 
our existing APIs. We are not keen on this one.

2- support multiple implicit cu owners, as we described before. We still need 
to remove unnecessary pain for client code.

3- units have built-in support for one working copy (likely the one opened in 
editor). Further shareable working copies can be created, but these aren't 
transparent to clients (no free delta, no free navigation). In particular, 
operations requiring to consider these working copies over the original units 
will have a way to express this explicitely.

Comment 39 Jerome Lanneluc CLA 2003-05-16 11:07:41 EDT
Martin, I looked at org.eclipse.text and I don't see how we can have the same 
behavior as DocumentAdapter without some UI knowledge.

Would it be possible for you to do the first implementation of createBuffer
(...) and getProblemRequestor() so that we can integrate it after all?
Comment 40 Martin Aeschlimann CLA 2003-05-19 08:59:27 EDT
Discussed with Kai (text team): The DocumentProvider is not yet moved down to a
UI independend plugin. Best is probably to start with an own buffer manager
using your own buffers and later change it to documents and the document
provider when text is ready. (of course until then jdt ui is broken).

Another interesting thought is if this wouldn't be a good moment to eliminate
IBuffer in favor of IDocument... (of course this is easier said than done)
Comment 41 Frank Sauer CLA 2003-06-18 11:00:52 EDT
Does all this mean that getHandleIdentifier() for an ICompilationUnit will not 
always return the same thing but has some owner part to it? If so, this is a 
problem for me since I use them as keys in persistent storage to associate 
metrics with java elements.

Frank
Comment 42 Jerome Lanneluc CLA 2003-06-19 05:57:26 EDT
Frank, no the format of getHandleIdentifier() will not be changed. It is only 
when you create the ICompilationUnit from it (using JavaCore.create(String)) 
that you would pass a owner if you didn't want the handle to have the primary 
owner.
Comment 43 Jerome Lanneluc CLA 2003-06-27 05:57:41 EDT
After discussing this issue on jdt-core-dev, the following solution was decided:

1. IWorkingCopy disapears. Clients will manipulate ICompilationUnits only.

2. An ICompilationUnit handle is still implicetly defined by its path, but 
   also by a WorkingCopyOwner. So 2 ICompilationUnits on the same IResource 
   are equal only if their owners are equal.

3. The working copy owner also defines how the buffer of a working copy is 
created (see WorkingCopyOwner.createBuffer(...)).

4. There exists a default working copy owner in the Java model called the 
primary owner. Compilation units that have this owner are called primary 
compilation units. They can switch back and forth between the original mode and 
the working mode using becomWorkingCopy(...) and discardWorkingCopy(...).

5. Clients that want to use different working copies than the primary 
compilation units in working copy mode can define a WorkingCopyOwner.

6. Java model operations that create compilation unit handles were augmented to 
include a working copy owner. Clients can pass their working copy owner along 
with these Java model operations. The operations are then run in the context of 
the working copies of this owner.

7. Working copies are now all implicitely shared and can be retrieved using 
their working copy owner.


See build notes for more details.
Comment 44 David Audel CLA 2003-07-17 06:31:42 EDT
Verified.