Bug 46668 - Changes to class path containers should not change .project
Summary: Changes to class path containers should not change .project
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.0 M8   Edit
Assignee: Jerome Lanneluc CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 48014 54235 54851 (view as bug list)
Depends on:
Blocks:
 
Reported: 2003-11-14 09:53 EST by John Arthorne CLA
Modified: 2017-11-21 06:59 EST (History)
14 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Arthorne CLA 2003-11-14 09:53:31 EST
This is a fork of bug 45767.  The problem is this:

When a classpath container changes its value, the .project file is modified.
Since classpaths are now dynamic but project references are not, this means end
users constantly have outgoing changes on their .project files.

Example (from PDE):

- Plugin B requires Plugin A
- Plugin B is being developed in a workspace, compiling against Plugin A as
external JARs

Observe: .classpath has the PDE container, .project has no project references

- User decides to checkout Plugin A from repository to hack it

Observe: .project now has a new project reference.

Since different users on a team will have different self-hosting styles, they
now have incompatible .project files.
Comment 1 John Arthorne CLA 2003-11-14 10:15:01 EST
I discussed this problem with Jeem yesterday and he had the following idea:

Classpath containers essentially delegate responsibility for computation of a
portion of a project's classpath to a third party.  However, JDT has not
delegated the responsibility of updating the project references to this third
party. This means that JDT has to "guess" based on the resolved classpath
container values what the appropriate project references are.  In other words,
JDT is guessing what the project references are based on incomplete knowledge of
that project's dependencies.

A solution to this problem would be to defer responsibility for updating project
references to the provider of the classpath container.  This breaks down as follows:

- JDT continues to add project references for all classpath entries *except*
classpath containers.  It makes the assumption that whoever provided the
container also has responsibility to add any necessary project references.

- PDE is now responsible for adding project references when classpath containers
are used.  It does this quite simply by adding a project reference for every
plugin import in the plugin manifest.  The set of plugin imports is "static"
regardless of a user's self-hosting style, so the set of project references will
not change either.  When plug-in imports are added or removed, it updates the
project references accordingly (just as I assume it is currently updating the
classpath container values).

- This will work because project references are "soft" by design.  The platform
does not care of a referenced project actually exists in the workspace.  If the
reference exists, it will be added to the build order appropriately.  If the
reference does not exist in the workspace, it has no impact on the build order.
The build order is automatically updated whenever projects are created, deleted,
opened, or closed.

How does that sound?
Comment 2 Philipe Mulet CLA 2003-11-14 12:03:12 EST
How would this change the net result ? 

Requiring classpath container providers to be aware of the proper build order 
is likely not an obvious thing for them, and clients could argue that it should 
be done in JDT Core as it is today. The project references are really an 
implementation detail, I'd rather hide to clients.

I would rather be in favor of a dynamic build order obtained by asking builder 
contributors.
Comment 3 John Arthorne CLA 2003-11-14 12:39:24 EST
I just had another realization.  PDE knows the complete set of project
references for a plugin from the plugin manifest.  JDT can infer some dynamic
subset of these references by looking at the values of the container.  Since
what JDT sees is simply a subset, then both PDE and JDT can add project
references.  Here's a revision of my previous proposal.

- PDE always adds project references for all required plugins.  It does this
quite simply by adding a project reference for every plugin import in the plugin
manifest.  This set is essentially static so the .project file will never change.

- JDT continues to add project references for all classpath entries including
classpath containers. I assume it already checks if a project reference exists
before adding it.  This means the .project will never be dirtied when the user
changes self-hosting styles (causing classpath container values to change).
Comment 4 Wassim Melhem CLA 2003-11-14 13:07:40 EST
I need a clarification:

>PDE always adds project references for all required plugins.  It does this
>quite simply by adding a project reference for every plugin import in the 
>plugin manifest. 
I'm assuming you are talking about adding project references to the .project 
file.  As you know, adding project references to the classpath will cause an 
error if the project does not exist in the workspace.
Also direct imports is not the only thing we have to worry about here, we also 
have to account for reexported imports.  
For example, plug-in A imports org.eclipse.ui and is getting 
org.eclipse.ui.workbench for free because org.eclipse.ui reexports it.  If 
org.eclipse.ui is external and org.eclipse.ui.workbench is in the workspace, a 
project reference to org.eclipse.ui.workbench would have to be made.

Either way, I have to echo Philippe's sentiment that I don't understand why 
all of a sudden PDE has to worry about .project files.  I was unaware of their 
use for a year and a half and I prefer if we kept it that way ;-)
Comment 5 Dejan Glozic CLA 2003-11-14 13:46:42 EST
I have to echo Wassim's sentiment who echoed Philippe's sentiment that project 
references is not something in the JDT contract from PDE's point of view. As 
far as we know, we are modifying project classpath. We simply state that this 
project depends on a list of other projects. We have no idea what project 
references are used for. Yes, thanks to you we now know that they are used for 
build order :-) but that is not what we are doing in a classpath container. 

We are simply computing classpath entries dynamically and the fact that that 
changes .project file is an implementation side-effect that we learned about 
only recently. We would hate to all of the sudden be responsible for build 
order. Philippe hates it as well because he will be on the hook every time the 
build fails due to the wrong build order even though PDE is to blame.
Comment 6 Philipe Mulet CLA 2003-11-17 05:28:37 EST
Answering comment #3, JDT is never touching the project description is the 
required set of project references (from JDT standpoint) is a subset of 
existing ones. So whatever occurs upstream, JDT should be resilient.

I think most of the troubles in touching .project files is related to the fact 
PDE container slightly changed the project reference set by including fragments 
in certain cases (bug 45767). If bug 45767 is addressed, then there is no need 
for PDE to compute project references if JDT does it underneath, with the same 
net result.  

What is the problem with a notion of a dynamic build order ?

Comment 7 Wassim Melhem CLA 2003-11-17 05:56:05 EST
Philippe, JDT will overwrite the .project even when bug 45767 gets fixed.
Here is a scenario:
plug-in X requires org.eclipse.ui, which in turns imports and re-exports 
org.elipse.ui.workbench, org.eclipse.jface and org.eclipse.swt.
When all these plug-ins are projects in the workspace: 
    1. The .project file of plug-in X contains only a reference to project    
org.eclipse.ui.  Good.
    2. The classpath of plug-in project A only contains a project reference to 
project org.eclipse.ui.  All good!

Suppose now that the developer closes projecgt org.eclipse.ui:
    PDE will dynamically recompute the classpath of plug-in X.  This time, the 
classpath of X will contain a reference to the external JAR of org.eclipse.ui 
(since the workspace version is now closed).  The classpath of X must now also 
contain direct references to projects org.eclipse.ui.workbench and 
org.eclipse.swt.  These two new project references will cause JDT to overwrite 
the .project file.  The .project file is thus very susceptible to workspace 
changes, while the .classpath file is unchanged.  As you can see, no fragments 
were used to illustrate this example.

While a dynamic build order is the best solution for many reasons that go 
beyond this defect, I was persuaded by Jim that PDE should not wait for the 
big build order issue to get resolved if this particular problem can be 
avoided with the current build mechanism unchanged.

Here is the suggestion:
1. JDT Core should not update the .project file in the case of classpath 
containers.
2. The PDE builder will be the one responsible for updating the .project file 
when necessary.  It is only necessary to update it when the plug-in's list of 
dependencies changes, and *not* every time the workspace state changes as it 
is the case today.
3. The list of projects in the .project of the plug-in project are references 
to all the direct imports of the plug-in and all the reexported imports of its 
direct imports.  This way the list of projects is complete, and no matter what 
projects are added/deleted from the workspace, the .project does not need to 
be modified.
Comment 8 Philipe Mulet CLA 2003-11-17 06:43:16 EST
My comment #6 should have mentionned that the set of project references in a 
self-hosted workspace with all plugins as projects. I was bothered by the 
introduced fragments. As you correctly pointed out, further differences occurs 
once users start using the flexibility the PDE container provides.

From a JDT standpoint, it doesn't make sense to require our clients to prepare 
the proper build order. What about other container contributors ? This is a 
breaking API change. If PDE is willing to contribute more project references 
than what JDT would induce, this is a fair workaround, but not a fix to the 
original problem.

Another reason for discouraging such practice is that there is no mechanism to 
avoid project references from stepping on each other. This is not a happy story 
on orthogonal natures, but if multiple tools start playing with Java references 
we may be in trouble. 
Again dynamic references seem the only hope.
Comment 9 John Arthorne CLA 2003-11-17 10:40:55 EST
I was thinking that JDT would not be required to make any changes.  This works
fine when required projects are imported, since JDT attempts to add a project
reference that already exists, and this case is optimized out.  However, when a
required project is removed from the workspace (to be replaced by an external
jar), JDT is removing the project reference.
Comment 10 Dejan Glozic CLA 2003-11-17 10:48:55 EST
I second Philippe's sentiment. To ask classpath container providers to change 
project references is breaking encapsulation. JDT is updating project 
references is an internal implementation detail (a consequence of classpath 
change). As far as we as customers are concerned, we only change JDT classpath.

Bottom line:

1) Use of project references is an implementation detail that classpath 
containers should not know about
2) Project references are used for build order, which is something that we 
don't care about, but JDT builder does, and should remain in its control.

Even though it is agaist our short-term interests when it comes to dynamic
classpaths, I have a really bad feeling about PDE going down this
path and would rather sit it out until Platorm Core and JDT Core find a
better (dynamic) way of managing build order.
Comment 11 Dejan Glozic CLA 2003-11-17 11:09:31 EST
On the other hand, if we all agree that this is a short-term solution until a 
better one is found, we can do it in PDE for the sake of dynamic classpaths 
faster adoption.
Comment 12 Wassim Melhem CLA 2003-11-17 11:16:29 EST
I'm all for it.
The only thing that JDT needs to, as John A. points out, is to not remove 
project references upon the deletion of a project.  I'm not sure how they feel 
about this.
Comment 13 Dejan Glozic CLA 2003-11-17 11:21:43 EST
Perhaps a backward-compatible solution would be to make the classpath 
initializer implement a certain interface to indicate that it will handle 
project references. Without it, do what you do today. Otherwise, let the 
initializer handle project references.
Comment 14 Dejan Glozic CLA 2003-11-17 11:23:11 EST
Yet another alternative would be to add a boolean attribute 'manage-
references' in the classpath container intializer extension point schema. The 
attribute would be false by default, and PDE can set its own to true.
Comment 15 John Arthorne CLA 2003-11-17 11:24:13 EST
Out of curiosity, is it true that PDE does not care about the build order?  PDE
does register builders... do they not care if they are run out of order with
respect to plugin dependencies?
Comment 16 Wassim Melhem CLA 2003-11-17 11:26:10 EST
I was thinking that this should be handled at the PDE builder level to pre-
empt the Java builder, and not at the container initializer level. This would 
also be the best point in time to determine if the list of dependencies has 
changed and whether the .project file needs to be modified or not.

To answer John's question, we do not care about build order.
Comment 17 Jim des Rivieres CLA 2003-11-17 11:27:25 EST
Re: comment #10

Project build order is defined in Platform core, not by JDT. Although project 
references and default build order is far from ideal, it is currently *the* 
way we establish the build order.

PDE knows about interdependencies between plug-in projects in the workspace, 
inferred from interdependencies between plug-ins stated in the manifest. 

This makes project references something that PDE is in a unique position to 
contribute to. Just as PDE can feed JDT the classpath entries it needs to 
properly compile code in the plug-in, so too it can feed Platform Core with 
the project references that ensure multiple plug-in projects get built in a 
reasonable relative order.

I don't think PDE should be reluctant about going down this path. When and if 
we have an improved story for how to order the building of projects in 
workspace, PDE would naturally move to supporting that new story.
Comment 18 Dejan Glozic CLA 2003-11-17 11:28:27 EST
... and the reason we don't care is because our builders do not produce new 
resources - they are simply validators. Each manifest can be validated in 
isolation - validation order is not important.
Comment 19 Wassim Melhem CLA 2003-11-17 11:35:36 EST
Removing Dejan from cc as he is a trouble maker :-)
Comment 20 Philipe Mulet CLA 2003-11-17 11:46:40 EST
Whatever PDE decides so as to workaround the platform issue, JDT must honour a 
proper Java build order. PDE is implemented in term of Java projects, thus it 
cannot bypass the fact that JDT computes some reasonable build order based on 
Java classpath information.

Re: comment #12. If a project is removed, we must remove a project references, 
so as not to leak references. Obsolete references may induce false platform 
diagnosis such as builder order cycles ?

Re: comment #13. This isn't an option as we would have to live forever with 
this (based on previous experience). Besides, why would JDT provide a new 
intermediate API to cover for a missing support in the platform. There are 
enough evidences that static project references do not scale, for these to be 
replaced by a better mechanism; and then I'd be more than happy to jump on it.


Comment 21 Wassim Melhem CLA 2003-11-17 11:52:52 EST
If JDT continues removing project references upon project deletions, and there 
seems to be a good reason for it, then this workaround will never work... 
Should we even pursue this?
Comment 22 Jim des Rivieres CLA 2003-11-17 12:04:22 EST
re: comment #21 - It would not be a problem if JDT never updated project 
references based on info obtained from classpath containers, as proposed in 
comment #1.
Comment 23 Philipe Mulet CLA 2003-11-17 12:55:25 EST
Feels inconsistent to me that JDT would not help on certain classpath entries. 
I would be more easily convinced to do nothing at all any longer <g>.
Comment 24 Dirk Baeumer CLA 2003-11-17 13:29:02 EST
If JDT/Core doesn't do anything anymore will this mean that JDT/UI has to 
maintain the project references. This seems strange to me since JDT/UI doesn't 
want to know anything about the relationship between class path and project 
references.
Comment 25 John Arthorne CLA 2003-11-17 13:42:32 EST
Dirk, there is no suggestion for JDT UI to do anything here.  We're debating
whether it should be done by JDT core or by clients of the container API (PDE in
this case).
Comment 26 Dirk Baeumer CLA 2003-11-17 16:11:17 EST
Just to note that there are other implementors of class path containers as 
well. 
Comment 27 Philipe Mulet CLA 2003-11-18 05:26:57 EST
WSDD has some in particular. Dirk, to clarify, I have no plan to remove any 
support from JDT Core with respect to project references (i.e. you don't have 
to revive the old project references panel in project creation wizard, yet 
<g>). 
Comment 28 Wassim Melhem CLA 2003-12-03 13:38:56 EST
*** Bug 48014 has been marked as a duplicate of this bug. ***
Comment 29 Tony Poppleton CLA 2004-02-14 13:21:53 EST
How about a dirty solution that would solve the .project file changing, by 
simply moving the <projects> element (where the changes happen) out of 
the .project file into a .buildorder file or something.

When using containers this file will get changed instead of the .project file, 
and users can add the .buildorder file to the .cvsignore file to stop being 
told of changes.  In these cases, the issue would be how is this .buildorder 
file created when you first check out the project from CVS.  Would the 
container be able to create them automatically in both the development 
workspace and the runtime workspace?
Comment 30 Philipe Mulet CLA 2004-02-16 05:36:42 EST
I think we should consider anything but dynamic project references contributed 
by registered builders. Any static approach is doomed in the same way, even if 
you separate concerns even more...
Comment 31 Wassim Melhem CLA 2004-03-09 23:15:05 EST
*** Bug 54235 has been marked as a duplicate of this bug. ***
Comment 32 David Williams CLA 2004-03-10 00:05:03 EST
There's a lot of deep discussion on this "bug" .... but I'm wondering if a 
solution to the pratical problem original mentioned would be to provide a 
filter on the CVS synchronize view (so .project could be filtered out)? I know 
by itself this wouldn't solve everything (for example, would still be told 
there were unsynchronized changes when tagging projects) but seeing all 
the "changed projects" in the synchronized view really is tiring. And, 
actually, its nearly caused me to miss some project's out going synchs, because 
I have so many (like 20) its easy to overlook one. Just thought I'd ask, since 
I'd hate to see the practical problem not addressed at all. 
Comment 33 Ritchie Schacher CLA 2004-03-10 07:50:01 EST
In addition to the syncrhonize view, using the label decorators in the other 
viewers (navigator, package explorer, etc).  The simple thing would be to 
ignore .project if it is in the .cvsignore file.  The problem with this is that 
then users my miss other important changes to .project, such as a nature or 
builder added.
Comment 34 John Arthorne CLA 2004-03-10 11:33:15 EST
Since many people have been asking lately, I will give a summary of the current
position on this bug.

Last fall I investigated changes that could be made to the platform core builder
infrastructure that would solve this problem. The result of this investigation
was recorded at:

http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-core-home/documents/eclipse3_builder_issues.html

The only solution that attacked the root of the problem was S1, and it required
breaking API changes for which there was no solid backward compatibility story.
This kind of breakage to all existing builders didn't feel an acceptable
tradeoff for the magnitude of the problem that it solved.  S2 solved only the
.project problem (by making build paths dynamically computed). Nobody was
entirely happy with that solution, since it required a wad of new API that
solved only the "dirty .project" problem but didn't address other long-standing
concerns about the platform build infrastructure.

Jeem and I made a counter-proposal that the clients who were dynamically
computing the build path should also be responsible (or could optionally assume
responsibility) for updating project references (comment #1 and comment #17).
This was based on the observation that the project references are actually very
static - a plug-in's pre-requisites don't actually change when they switch from
being internal to external and vice-versa. Only the client of the classpath
container (PDE in this case), knows what the static, stable set of plugin
project dependencies are, so it is the only one that has any hope of computing
them. Since project references currently have a strong relationship with build
order, this proposal was rejected because it moved responsibility for
maintaining project references away from the plug-in that cares about builder
order (JDT), and because it didn't address unrelated long-standing concerns
about the platform build infrastructure.

Having come to this stalement, I don't know how to proceed. David's recent
suggestion (comment #32), while well-intentioned, is a no-go.  It defeats the
purpose of putting the .project in the project content area in the first place.
 The .project contains important information apart from the project references,
so hiding it prevents those important changes from being shared with a team.

The only other suggestion I have heard is to move the project references out of
the .project file, such as in the new preference store which has support for
project-level preference scopes. I'm willing to investigate this, but I'm not
that happy with it.  This has implications for builders that rely on the
platform to store project references.  JDT isn't affected because they duplicate
the project reference information in the .classpath file, but this might not be
true for all builders. Hiding the project references could result in some
builders not obtaining the desired build order.
Comment 35 David Williams CLA 2004-03-10 12:12:12 EST
Thanks for the summary and update, John. Just to clarify, my suggest was for a 
user settable filter (just like on package explorer's filter dialog) ... so, 
would at least be "use at your own risk" sort of thing. Frankly, once we get 
these files as we like them, we ignore their synch state anyway ... its just we 
have to ignore them "manually". Hope that doesn't burst any bubbles, but the 
alternative is that some on the team always get a "wrong" one, or everyone on 
the team has to have the exact same environment. Maybe we are not a typical 
team, but we are all intimately aware of these files, their contents, and don't 
blush to occasionally edit them by hand. Just consider this a "report from the 
trenches". 
Comment 36 Philipe Mulet CLA 2004-03-10 20:09:30 EST
What about simply letting builders declare recommendation for a build order ? 
This is what I mentionned as dynamic references. The build manager would gather 
all recommendations either static or dynamic, and compute a global build order 
as it does today. This allows tools inferring build orders (as we do) to avoid 
polluting project description with generated contextual information.

Comment 37 Wassim Melhem CLA 2004-03-11 23:12:04 EST
I am not convinced that we have come to a stalemate.

Having heard all the arguments and examined the conclusions of John's 
investigation, I still don't see a compelling reason or a realistic use case 
to not take the approach Philippe is suggesting in comments 2, 8, 30 and 36.  

Dynamic build order seems the only way to go and JDT is more than willing to 
be in control of that for Java projects.  As for the other builders in the 
SDK, namely the PDE builders, we are more than happy with any order JDT 
chooses, since build order really has no effect whatsoever on the validation 
that we do.
Comment 38 John Arthorne CLA 2004-03-12 09:24:47 EST
I have acquiesced.  Core will introduce dynamic project references that are not
stored in the .project file.  More details to follow shortly, I'm just writing
some more tests to make sure it all works.
Comment 39 Philipe Mulet CLA 2004-03-12 09:28:50 EST
The only corner case I could come up with is a situation where one copy/paste a 
project folder into a workspace (no metadata), then creates a Java project on 
it. Unsure whether we will consider this as a classpath change (and thus issue 
dynamic references in reaction). Need to be tested.
Comment 40 Wassim Melhem CLA 2004-03-12 09:38:33 EST
For reference regarding comment #38,
http://dictionary.reference.com/search?q=acquiesce

John comes up with pretty good ones :-)
Comment 41 John Arthorne CLA 2004-03-12 12:05:27 EST
Summary of API changes in core:

New methods: IProjectDescription.get/setDynamicReferences.  Dynamic references
behave just like ordinary references, except they are not stored in the .project
file.  The intent is that references that are likely to change based on local
workspace conditions should be stored as dynamic references.  References that
are not workspace-dependent, or that need to be shared between teams for any
reason, should use the old (static) project references.  For example, JDT would
store references resolved from dynamic classpath variables as dynamic project
references, but could leave fixed classpath project dependencies as normal
project references.

Other API changes:
IProject.getReferencedProjects() - This method will return the union of static
and dynamic references, with duplicates omitted.  Clients that are interested in
knowing a project's references, but don't care to distinguish dynamic from
non-dynamic, should use this method.

IProject.getReferencingProjects() - Changed to compute in-references based on
both static and dyanmic references

IWorkspace.computeProjectOrder - Changed to compute topological order using both
static and dynamic references.

IProject.setDescription - This method is now "smart" about only writing the
.project file if the contents of the .project file have actually changed. I.e.,
changes to the location or dynamic references will not dirty the .project file.

These changes are available in HEAD.
Comment 42 Dejan Glozic CLA 2004-03-12 12:20:55 EST
This is a great day for the selfhosting community :-).
Comment 43 John Arthorne CLA 2004-03-15 19:14:28 EST
Now that the platform core changes have been released, it just remains for JDT
core to start using dynamic references for classpath containers.  Moving this
bug to JDT core.
Comment 44 Jerome Lanneluc CLA 2004-03-22 07:22:43 EST
*** Bug 54851 has been marked as a duplicate of this bug. ***
Comment 45 Jerome Lanneluc CLA 2004-03-22 07:24:06 EST
Fixed SetClasspathOperation.updateProjectReferencesIfNecessary() to use dynamic 
project references.

Changed ClasspathInitializer.testContainerInitializer6() to reflect this change 
(i.e. the .project file is no longer changed)

Comment 46 Jerome Lanneluc CLA 2004-03-22 07:24:39 EST
Reopen to assign
Comment 47 Jerome Lanneluc CLA 2004-03-22 07:25:41 EST
Marking as fixed (sorry for the mass mailing)
Comment 48 Frederic Fusier CLA 2004-03-24 10:50:18 EST
Verified for 3.0 using build I200403240800.