Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,57 +94,79 @@ protected void createContent(Composite parent) {
}

private void updateBrowserSize(final Browser browser) {
updateBrowserSize(browser, 1);
}

private void updateBrowserSize(final Browser browser, final int attempt) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebthom , can you rebase your PR? Now that I think I have solved the problem with safeEvaluate returning exceptions, I think you can go back to your original attempt which was much simpler.

if (attempt > 100) // ~1s total
return;

if (getShell().isDisposed() || browser.isDisposed() || getInput() == null)
return;

@Nullable
Point constraints = getSizeConstraints();
Point hint = computeSizeHint();
final @Nullable Point constraints = getSizeConstraints();
final Point hint = computeSizeHint();
setSize(hint.x, hint.y);

if (!"complete".equals(safeEvaluate(browser, "return document.readyState"))) { //$NON-NLS-1$ //$NON-NLS-2$
UI.getDisplay().timerExec(200, () -> updateBrowserSize(browser));
final var docReadyState = safeEvaluate(browser, "return document.readyState"); //$NON-NLS-1$
if (!"complete".equals(docReadyState)) { //$NON-NLS-1$
retryUpdateBrowserSize(browser, attempt);
return;
}

safeExecute(browser, "document.getElementsByTagName('html')[0].style.whiteSpace = 'nowrap'"); //$NON-NLS-1$
final Object widthObj = safeEvaluate(browser, "var b = document.body; return b && b.scrollWidth"); //$NON-NLS-1$
if (!(widthObj instanceof final Number widthValue)) {
retryUpdateBrowserSize(browser, attempt);
return;
}
double width = 20 + widthValue.doubleValue();
setSize((int) width, hint.y);

safeExecute(browser, "document.getElementsByTagName('html')[0].style.whiteSpace = 'normal'"); //$NON-NLS-1$
final Object heightObj = safeEvaluate(browser, "var b = document.body; return b && b.scrollHeight"); //$NON-NLS-1$
if (!(heightObj instanceof final Number heightValue)) {
retryUpdateBrowserSize(browser, attempt);
return;
}

safeExecute(browser, "document.getElementsByTagName(\"html\")[0].style.whiteSpace = \"nowrap\""); //$NON-NLS-1$
Double width = 20
+ (safeEvaluate(browser, "return document.body.scrollWidth;") instanceof Double evaluated ? evaluated //$NON-NLS-1$
: 0);
setSize(width.intValue(), hint.y);

safeExecute(browser, "document.getElementsByTagName(\"html\")[0].style.whiteSpace = \"normal\""); //$NON-NLS-1$
Double height = safeEvaluate(browser, "return document.body.scrollHeight;") instanceof Double evaluated //$NON-NLS-1$
? evaluated
: 0d;
Object marginTop = safeEvaluate(browser, "return window.getComputedStyle(document.body).marginTop;"); //$NON-NLS-1$
Object marginBottom = safeEvaluate(browser, "return window.getComputedStyle(document.body).marginBottom;"); //$NON-NLS-1$
double height = heightValue.doubleValue();
if (Platform.getPreferencesService().getBoolean(EditorsUI.PLUGIN_ID,
AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE, true, null)) {
FontData[] fontDatas = JFaceResources.getDialogFont().getFontData();
final FontData[] fontDatas = JFaceResources.getDialogFont().getFontData();
height += fontDatas[0].getHeight();
}

width = width * 1.5;
if (Util.isWin32()) {
Object marginTop = safeEvaluate(browser,
"var b = document.body; return b && window.getComputedStyle(b).marginTop"); //$NON-NLS-1$
Object marginBottom = safeEvaluate(browser,
"var b = document.body; return b && window.getComputedStyle(b).marginBottom"); //$NON-NLS-1$
height = adjust(height, marginTop);
height = adjust(height, marginBottom);
}
if (constraints != null && constraints.x < width) {
width = (double) constraints.x;
width = constraints.x;
}
if (constraints != null && constraints.y < height) {
height = (double) constraints.y;
height = constraints.y;
}

setSize(width.intValue(), height.intValue());
setSize((int) width, (int) height);
}

private void retryUpdateBrowserSize(final Browser browser, final int currentAttempt) {
UI.getDisplay().timerExec(10, () -> updateBrowserSize(browser, currentAttempt + 1));
}

private static @Nullable Object safeEvaluate(Browser browser, String expression) {
try {
return browser.evaluate(expression);
} catch (Exception ex) {
LanguageServerPlugin.logError(ex);
if (LanguageServerPlugin.DEBUG || LanguageServerPlugin.isLogTraceEnabled()) {
LanguageServerPlugin.logError("Failed to evaluate browser expression: " + expression, ex); //$NON-NLS-1$
}
}
return null;
}
Expand All @@ -153,7 +175,9 @@ private static boolean safeExecute(Browser browser, String expression) {
try {
return browser.execute(expression);
} catch (Exception ex) {
LanguageServerPlugin.logError(ex);
if (LanguageServerPlugin.DEBUG || LanguageServerPlugin.isLogTraceEnabled()) {
LanguageServerPlugin.logError("Failed to execute browser expression: " + expression, ex); //$NON-NLS-1$
}
}
return false;
}
Expand Down Expand Up @@ -191,6 +215,7 @@ public void setInput(@Nullable Object input) {
}));
return;
}
this.currentAsyncToken = null;
if (input instanceof String html) {
input = styleHtml(html);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
@SuppressWarnings("restriction")
public class LSPTextHover implements ITextHover, ITextHoverExtension, ITextHoverExtension2 {

private static final int GET_LEGACY_HOVER_INFO_TIMEOUT_MS = 1000;
private static final int GET_ASYNC_HOVER_INFO_TIMEOUT_MS = 100;
private static final int GET_HOVER_REGION_TIMEOUT_MS = 100;

private @Nullable IRegion lastRegion;
Expand All @@ -74,17 +76,17 @@ public class LSPTextHover implements ITextHover, ITextHoverExtension, ITextHover
private @Nullable CompletableFuture<@Nullable String> hoverInfoFuture;

@Override
@Deprecated
public @Nullable String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
// Non-blocking: only return immediately available content.
final var hoverInfoRequest_ = this.hoverInfoFuture = getHoverInfoFuture(textViewer, hoverRegion);
if (hoverInfoRequest_.isDone()) {
try {
return hoverInfoRequest_.getNow(null);
} catch (final Exception ex) {
if (CancellationUtil.isRequestCancelledException(ex)) {
// Hover was cancelled; ignore as this is an expected fast-mouse-move scenario.
return null;
}

try {
return hoverInfoRequest_.get(GET_LEGACY_HOVER_INFO_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
LanguageServerPlugin.logError(ex);
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException ex) {
if (!CancellationUtil.isRequestCancelledException(ex)) {
LanguageServerPlugin.logError(ex);
}
}
Expand All @@ -94,8 +96,22 @@ public class LSPTextHover implements ITextHover, ITextHoverExtension, ITextHover
@Override
public @Nullable Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
final var hoverInfoRequest_ = this.hoverInfoFuture = getHoverInfoFuture(textViewer, hoverRegion);
final String placeholder = "<html><body>Loading…</body></html>"; //$NON-NLS-1$
return new AsyncHtmlHoverInput(hoverInfoRequest_, placeholder);

try {
return hoverInfoRequest_.get(GET_ASYNC_HOVER_INFO_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
LanguageServerPlugin.logError(ex);
Thread.currentThread().interrupt();
return null;
} catch (ExecutionException ex) {
if (!CancellationUtil.isRequestCancelledException(ex)) {
LanguageServerPlugin.logError(ex);
}
return null;
} catch (TimeoutException ex) {
final String placeholder = "<html><body>Loading…</body></html>"; //$NON-NLS-1$
return new AsyncHtmlHoverInput(hoverInfoRequest_, placeholder);
}
}

public CompletableFuture<@Nullable String> getHoverInfoFuture(ITextViewer textViewer, IRegion hoverRegion) {
Expand Down