-
Notifications
You must be signed in to change notification settings - Fork 109
Open
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:
- 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?
- 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<String> 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<String> 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$
}
Metadata
Metadata
Assignees
Labels
No labels