`Dialog.shortenText` performs badly with huge inputs
Let's make sure issue is not already fixed in latest builds first.
- [x] I verified I can reproduce this issue against latest Integration Build of Eclipse SDK
Steps to reproduce
- Make sure the Progress view open
- Start a Job that produces an enormous error message, e.g.,
final Job j = new Job("test") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
return Status.error("There was an Error\n".repeat(2000000));
}
};
j.schedule();
- The application freezes, because
Dialog.shortenTextis trying to reduce this large error message down to a string which can be displayed.
Excerpt from main-Thread Stack:
OS.DrawText(long, char[], int, RECT, int) line: not available [native method]
GC.textExtentInPixels(String, int) line: 5832
GC.textExtent(String) line: 5773
Dialog.shortenText(String, Control) line: 361
ProgressInfoItem.updateText(String, Link) line: 812
ProgressInfoItem.setLinkText(Job, String, int) line: 741
ProgressInfoItem.refresh() line: 528
ProgressInfoItem.createChildren() line: 271
ProgressInfoItem.<init>(Composite, int, JobTreeElement) line: 197
DetailedProgressViewer.createNewItem(JobTreeElement) line: 220
DetailedProgressViewer.reorderControls(Object[]) line: 481
DetailedProgressViewer.updateItems(Set<JobTreeElement>) line: 189
DetailedProgressViewer.add(JobTreeElement...) line: 173
DetailedProgressViewer.internalRefresh(Object) line: 367
DetailedProgressViewer(StructuredViewer).internalRefresh(Object, boolean) line: 1249
DetailedProgressViewer(StructuredViewer).lambda$3(Object, boolean) line: 1485
Lambda.run() line: not available
DetailedProgressViewer(StructuredViewer).preservingSelection(Runnable, boolean) line: 1391
DetailedProgressViewer(StructuredViewer).preservingSelection(Runnable) line: 1352
DetailedProgressViewer(StructuredViewer).refresh(Object, boolean) line: 1485
ProgressViewerContentProvider.refresh(JobTreeElement...) line: 75
ProgressViewUpdater.update() line: 299
[...]
Possible fixes for Dialog.shortenText:
- Add a hard limit to the length of the input String at which point we don't even try to shorten the string
- Perform some kind of binary-search when trying to determine
startandendinstead of moving each limit by 1 in each iteration of the for loop.
Relevant code: https://github.com/eclipse-platform/eclipse.platform.ui/blob/343fd57b98addd612e285e10c70be340e784d0b0/bundles/org.eclipse.jface/src/org/eclipse/jface/dialogs/Dialog.java#L357-L386
Add a hard limit to the length of the input String at which point we don't even try to shorten the string
Hard limit, substring to that limit and start shortening. One can assume the text to be readable needs at least 3 pixel per character. So limit would be maxWidth / 3.
Perform some kind of binary-search when trying to determine start and end instead of moving each limit by 1 in each iteration of the for loop.
Could be done, but assuming the shortening would first cut the string to hard limit, probably not needed.