eclipse-jdt / eclipse-jdt/eclipse.jdt.ui

Restore Type Hierarchy triggers rebuild

Open
#2,305 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
59
Forks
127
Avg merge
23h 30m
Merged PRs (30d)
35

Description

In org.eclipse.jdt.internal.ui.typehierarchy.TypeHierarchyViewPart.restoreState(IMemento), the Java model is accessed before it has been properly initialized. This premature access causes the affected ICompilationUnit to be compiled, which inadvertently triggers a rebuild of all dependent projects.

I implemented a prototype that delays accesses to the Java model, which resolves the rebuild issue. However, I have two open questions:

1. How can I reliably check if the Java model is initialized, without risking deadlocks or freezes? My current approach avoids the rebuild, but I'm unsure what the canonical or safest check is. Is there a recommended way to ensure the model is ready before accessing it?

Probably just add a waitForInitialization method to JavaCore?

2. How can I retrieve the label shown in the Type Hierarchy view for the type to be resolved?

```
private void restoreState(final IMemento memento) {
List ids = new ArrayList<>();

String elementId= memento.getString(TAG_INPUT);
int i= 0;
while (elementId != null) {
ids.add(elementId);
elementId= memento.getString(TAG_INPUT + ++i);
}

if (ids.isEmpty()) {
doRestoreState(memento, new IJavaElement[0]);
} else {
synchronized (this) {

String label= Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_restoreinput, resolveLabels(ids));
fNoHierarchyShownLabel.setText(label);

fRestoreStateJob= new Job(label) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
while(!JavaCore.INITIALIZED) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
final IJavaElement[] hierarchyInput= ids.stream().map(JavaCore::create).filter(IJavaElement::exists).toArray(length -> new IJavaElement[length]);
if(hierarchyInput.length == 0) {
doRestoreState(memento, new IJavaElement[0]);
} else {
doRestoreInBackground(memento, hierarchyInput, monitor);
}
} catch (JavaModelException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
if (fRestoreJobCanceledExplicitly) {
showEmptyViewer();
}
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
};
fRestoreStateJob.schedule();
}
}
}

private String resolveLabels(List ids) {
switch (ids.size()) {
case 0:
throw new IllegalArgumentException();
case 1:
return Messages.format(TypeHierarchyMessages.HistoryAction_inputElements_1,
new String[] { resolveLabel(ids.get(0)) });
case 2:
return Messages.format(TypeHierarchyMessages.HistoryAction_inputElements_2,
new String[] { resolveLabel(ids.get(0)), resolveLabel(ids.get(1)) });
default:
return Messages.format(TypeHierarchyMessages.HistoryAction_inputElements_more,
new String[] { resolveLabel(ids.get(0)), resolveLabel(ids.get(1)), resolveLabel(ids.get(2)) });
}
}

private String resolveLabel(String id) {
String packageName = "notFound"; //$NON-NLS-1$
String typeName = "notFound"; //$NON-NLS-1$

if(id != null && id.contains("[")) { //$NON-NLS-1$
String[] splitType = id.split("\\["); //$NON-NLS-1$
typeName = splitType[1];
if(splitType[0].contains("<")) { //$NON-NLS-1$
String[] splitBundle = splitType[0].split("<"); //$NON-NLS-1$
if(splitBundle[1].contains("{")) { //$NON-NLS-1$
packageName = splitBundle[1].split("\\{")[0]; //$NON-NLS-1$
}
}
}
return packageName + "." + typeName; //$NON-NLS-1$
}
```

Contributor guide

Open the contributing guide

Research direction

Start at org.eclipse.jdt.internal.ui.typehierarchy.TypeHierarchyViewPart.restoreState(IMemento) and inspect the JavaCore.INITIALIZED access and the label messages in TypeHierarchyMessages. Determine a safe initialization check and how to obtain the Type Hierarchy label without premature Java model access; done means restoring state no longer triggers dependent-project rebuilds and the displayed type label is correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
desktop, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.