Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 526116 - JavaElement openWhenClosed closes parent which may have been opened elsewhere
Summary: JavaElement openWhenClosed closes parent which may have been opened elsewhere
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.7.1a   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: 4.17 RC1   Edit
Assignee: Eric Milles CLA
QA Contact: Manoj N Palat CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-10-16 20:07 EDT by Eric Milles CLA
Modified: 2020-08-25 00:39 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Milles CLA 2017-10-16 20:07:38 EDT
I have been tracking down a bug where a save action that causes an edit is leaving a dirty buffer.  I managed to track it down to a bug in JavaElement.openWhenClosed.  If resolution of a source type fails (for example trying to look up sdomething that is resolved by a static import), the compilation unit may get closed when it was opened elsewhere (by the editor).  A closed buffer leads to downstream problems in save actions.

My edits have been marked below.  Basically, if result of getOpenable() was already present in the temporary cache, it should not be closed here.

	protected Object openWhenClosed(Object info, boolean forceAdd, IProgressMonitor monitor) {
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		boolean hadTemporaryCache = manager.hasTemporaryCache();
		try {
			HashMap newElements = manager.getTemporaryCache();
			// XXX add
			Openable openable = (Openable) getOpenable();
			boolean closeParent = !(newElements.containsKey(openable));
			// XXX end
			generateInfos(info, newElements, monitor);
			if (info == null) {
				info = newElements.get(this);
			}
			if (info == null) { // a source ref element could not be opened
				// close the buffer that was opened for the openable parent
				// close only the openable's buffer (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62854)
				// XXX edit
				//Openable openable = (Openable) getOpenable();
				//if (newElements.containsKey(openable)) {
				if (closeParent && newElements.containsKey(openable)) {
				// XXX end
					openable.closeBuffer();
				}
				throw newNotPresentException();
			}
Comment 1 Eric Milles CLA 2017-10-16 22:04:13 EDT
The check may need to include an open test:

boolean closeParent = !(newElements.containsKey(openable) && openable.isOpen());
Comment 2 Eclipse Genie CLA 2020-01-13 02:21:00 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 3 Stephan Herrmann CLA 2020-02-24 17:15:25 EST
Re-opening as we have a proposed gerrit.

Frankly, I personally am not fully at ease with such a change, simply because this is not my main focus area and therefor I can't easily imagine all possible consequences.

As always, a test case would immensely help to convince us of the change :)
Comment 4 Eric Milles CLA 2020-02-24 17:37:57 EST
I can say that the current structure results in closing CompilationUnit instances that were opened elsewhere.  This results in editors with the dirty mark (star in upper-right of editor tab) and saving does not clear.

This was quite difficult to track down back in 2017.  There is some interaction between editors, save actions and the reconcile threads.  I wish I had a test case or some more concrete information.  I will try running without the patch and see if I can recreate the old problem.
Comment 5 Andrey Loskutov CLA 2020-02-25 07:34:41 EST
(In reply to Eric Milles from comment #4)
> I will try running
> without the patch and see if I can recreate the old problem.

Good idea. I would be very interested in the error log with stack traces.
Comment 6 Eric Milles CLA 2020-02-25 13:17:31 EST
I did some digging and have some more details.  Here is the original change that prompted the creation of this bug: https://github.com/groovy/groovy-eclipse/commit/23a886633d239e6f3bc9f3f18877bf9b27629c5d#diff-18569bf0654f1f02054f10920080e1ba

Recreation scenario: When a Groovy source editor is open and dirty (has unsaved edits), if a save action causes an additional edit the buffer will save but remain marked as dirty (star in upper-right of editor tab).

This happens because the buffer's working copy is closed by JavaElement#openWhenClosed.  A typical editor's becomeWorkingCopy stack involves opening the compilation unit and building its structure.  This causes type lookups for things like inner class references or static import fields/methods, which results in opening source reference elements.

    workingCopy.openWhenClosed(workingCopy.createElementInfo(), true, this.progressMonitor);
    ...
    Binding binding = currentPackage.getTypeOrPackage(name, module(), false); // name: "CompUnit$pack$Type" -- this is part of a search algorithm for resolving "Type" reference
    ...
    SourceTypeElementInfo sourceType = (SourceTypeElementInfo)((SourceType) answer.type).getElementInfo();

	public Object getElementInfo(IProgressMonitor monitor) throws JavaModelException {
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		Object info = manager.getInfo(this);
		if (info != null) return info;
		return openWhenClosed(createElementInfo(), false, monitor); // notice that the SourceType is opened regardless of current open status, unlike the comment above openWhenClosed describes
	}    

    // now the SourceType.getOpenable() returns the CompilationUnit that is already open and is the working copy; closing it causes problems for reconcile and save actions




I think the patch can be reduced to checking if openable is also the working copy before closing it.
Comment 8 Manoj N Palat CLA 2020-03-20 04:43:14 EDT
(In reply to Eclipse Genie from comment #7)
> Gerrit change https://git.eclipse.org/r/158125 was merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=3f3180b4fac968256f3e4b126c5b6a9ed43cebcc

@Eric: Have pushed in the commit for now - As discussed with Jay, Please follow up with a test case.
Comment 9 Jay Arthanareeswaran CLA 2020-08-24 02:01:55 EDT
Manoj, how long do you plan on keeping this open, for want of a test case? Given that couple of people have already reviewed this, we should perhaps close this and move on?
Comment 10 Manoj N Palat CLA 2020-08-25 00:39:46 EDT
(In reply to Jay Arthanareeswaran from comment #9)
> Manoj, how long do you plan on keeping this open, for want of a test case?
> Given that couple of people have already reviewed this, we should perhaps
> close this and move on?

Fine with me, Jay. Resolving.