Source:
<code>public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { final IDocument document = textViewer.getDocument(); TextDocumentPositionParams params; try { URI uri = LSPEclipseUtils.toUri(document); if (uri == null) { return null; } params = new TextDocumentPositionParams( new TextDocumentIdentifier(uri.toString()), LSPEclipseUtils.toPosition(region.getOffset(), document)); } catch (BadLocationException e1) { LanguageServerPlugin.logError(e1); return null; } IRegion r = findWord(textViewer.getDocument(), region.getOffset()); final IRegion linkRegion = r != null ? r : region; Collection<LSBasedHyperlink> allLinks = Collections.synchronizedList(new ArrayList<>()); try { Collection<CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>>> allFutures = Collections.synchronizedCollection(new ArrayList<>()); CompletableFuture.allOf( LanguageServiceAccessor .getLanguageServers(textViewer.getDocument(), capabilities -> Boolean.TRUE.equals(capabilities.getDefinitionProvider())) .thenAcceptAsync(languageServers -> languageServers.stream().map(ls -> ls.getTextDocumentService().definition(params)).forEach(allFutures::add) ), LanguageServiceAccessor .getLanguageServers(textViewer.getDocument(), OpenDeclarationHyperlinkDetector::isTypeDefinitionProvider) .thenAcceptAsync(languageServers -> languageServers.stream().map(ls -> ls.getTextDocumentService().typeDefinition(params)).forEach(allFutures::add) ) ).thenCompose(theVoid -> CompletableFuture.allOf(allFutures.stream().map(future -> future.thenAccept(locations -> { Collection<LSBasedHyperlink> links = toHyperlinks(document, linkRegion, locations); synchronized (allLinks) { allLinks.addAll(links); } })).toArray(CompletableFuture[]::new)) <START> ).get(500, TimeUnit.SECONDS); <END> } catch (ExecutionException | TimeoutException e) { LanguageServerPlugin.logError(e); } catch (InterruptedException e) { LanguageServerPlugin.logError(e); Thread.currentThread().interrupt(); } if (allLinks.isEmpty()) { return null; } return allLinks.toArray(new IHyperlink[allLinks.size()]); }</code><technical_language>a timeout of 500 seconds => 8 minutes 20 seconds is a good idea</technical_language>

Target:
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { final IDocument document = textViewer.getDocument(); TextDocumentPositionParams params; try { URI uri = LSPEclipseUtils.toUri(document); if (uri == null) { return null; } params = new TextDocumentPositionParams( new TextDocumentIdentifier(uri.toString()), LSPEclipseUtils.toPosition(region.getOffset(), document)); } catch (BadLocationException e1) { LanguageServerPlugin.logError(e1); return null; } IRegion r = findWord(textViewer.getDocument(), region.getOffset()); final IRegion linkRegion = r != null ? r : region; Collection<LSBasedHyperlink> allLinks = Collections.synchronizedList(new ArrayList<>()); try { Collection<CompletableFuture<Either<List<? extends Location>, List<? extends LocationLink>>>> allFutures = Collections.synchronizedCollection(new ArrayList<>()); CompletableFuture.allOf( LanguageServiceAccessor .getLanguageServers(textViewer.getDocument(), capabilities -> Boolean.TRUE.equals(capabilities.getDefinitionProvider())) .thenAcceptAsync(languageServers -> languageServers.stream().map(ls -> ls.getTextDocumentService().definition(params)).forEach(allFutures::add) ), LanguageServiceAccessor .getLanguageServers(textViewer.getDocument(), OpenDeclarationHyperlinkDetector::isTypeDefinitionProvider) .thenAcceptAsync(languageServers -> languageServers.stream().map(ls -> ls.getTextDocumentService().typeDefinition(params)).forEach(allFutures::add) ) ).thenCompose(theVoid -> CompletableFuture.allOf(allFutures.stream().map(future -> future.thenAccept(locations -> { Collection<LSBasedHyperlink> links = toHyperlinks(document, linkRegion, locations); synchronized (allLinks) { allLinks.addAll(links); } })).toArray(CompletableFuture[]::new)) ).get(500, TimeUnit.MILLISECONDS); } catch (ExecutionException | TimeoutException e) { LanguageServerPlugin.logError(e); } catch (InterruptedException e) { LanguageServerPlugin.logError(e); Thread.currentThread().interrupt(); } if (allLinks.isEmpty()) { return null; } return allLinks.toArray(new IHyperlink[allLinks.size()]); }