Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: extracted methods to improve readability #978

Merged
Merged
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 @@ -17,6 +17,7 @@
import com.intellij.codeInsight.hints.presentation.InlayPresentation;
import com.intellij.codeInsight.hints.presentation.PresentationFactory;
import com.intellij.codeInsight.hints.presentation.SequencePresentation;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
Expand Down Expand Up @@ -64,53 +65,72 @@ public InlayHintsCollector getCollectorFor(@NotNull PsiFile psiFile,
@Override
public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @NotNull InlayHintsSink inlayHintsSink) {
try {
Document document = editor.getDocument();
Project project = psiElement.getProject();
if (project.isDisposed()) {
// The project has been closed, don't collect code lenses.
return false;
}
URI docURI = LSPIJUtils.toUri(editor.getDocument());
URI docURI = LSPIJUtils.toUri(document);
if (docURI != null) {
CodeLensParams param = new CodeLensParams(new TextDocumentIdentifier(docURI.toString()));
BlockingDeque<Pair<CodeLens, LanguageServer>> pairs = new LinkedBlockingDeque<>();
List<Pair<Integer, Pair<CodeLens, LanguageServer>>> codelenses = new ArrayList<>();
CompletableFuture<Void> future = LanguageServiceAccessor.getInstance(project)
.getLanguageServers(editor.getDocument(), capabilities -> capabilities.getCodeLensProvider() != null)
.thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream()
.map(languageServer -> languageServer.getSecond().getTextDocumentService().codeLens(param)
.thenAcceptAsync(codeLenses -> {
// textDocument/codeLens may return null
if (codeLenses != null) {
codeLenses.stream().filter(Objects::nonNull)
.forEach(codeLens -> pairs.add(new Pair(codeLens, languageServer.getSecond())));
}
}))
.toArray(CompletableFuture[]::new)));
while (!future.isDone() || !pairs.isEmpty()) {
ProgressManager.checkCanceled();
Pair<CodeLens, LanguageServer> pair = pairs.poll(25, TimeUnit.MILLISECONDS);
if (pair != null) {
int offset = LSPIJUtils.toOffset(pair.getFirst().getRange().getStart(), editor.getDocument());
codelenses.add(Pair.create(offset, pair));
}
}
Map<Integer, List<Pair<Integer, Pair<CodeLens, LanguageServer>>>> elements = codelenses.stream().collect(Collectors.groupingBy(p -> p.first));
elements.forEach((offset, list) -> inlayHintsSink.addBlockElement(offset, true,
true, 0, toPresentation(editor, offset, list, getFactory())));
CompletableFuture<Void> future = collect(document, project, param, pairs);
List<Pair<Integer, Pair<CodeLens, LanguageServer>>> codeLenses = createCodeLenses(document, pairs, future);
Map<Integer, List<Pair<Integer, Pair<CodeLens, LanguageServer>>>> elements = codeLenses.stream().collect(Collectors.groupingBy(p -> p.first));
elements.forEach((offset, list) ->
inlayHintsSink.addBlockElement(
offset,
true,
true,
0,
toPresentation(editor, offset, list, getFactory()))
);
}
} catch (InterruptedException e) {
LOGGER.warn(e.getLocalizedMessage(), e);
Thread.currentThread().interrupt();
}
return false;
}

@NotNull
private List<Pair<Integer, Pair<CodeLens, LanguageServer>>> createCodeLenses(Document document, BlockingDeque<Pair<CodeLens, LanguageServer>> pairs, CompletableFuture<Void> future) throws InterruptedException {
List<Pair<Integer, Pair<CodeLens, LanguageServer>>> codelenses = new ArrayList<>();
while (!future.isDone() || !pairs.isEmpty()) {
ProgressManager.checkCanceled();
Pair<CodeLens, LanguageServer> pair = pairs.poll(25, TimeUnit.MILLISECONDS);
if (pair != null) {
int offset = LSPIJUtils.toOffset(pair.getFirst().getRange().getStart(), document);
codelenses.add(Pair.create(offset, pair));
}
}
return codelenses;
}

private CompletableFuture<Void> collect(Document document, Project project, CodeLensParams param, BlockingDeque<Pair<CodeLens, LanguageServer>> pairs) {
return LanguageServiceAccessor.getInstance(project)
.getLanguageServers(document, capabilities -> capabilities.getCodeLensProvider() != null)
.thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream()
.map(languageServer -> languageServer.getSecond().getTextDocumentService().codeLens(param)
.thenAcceptAsync(codeLenses -> {
// textDocument/codeLens may return null
if (codeLenses != null) {
codeLenses.stream().filter(Objects::nonNull)
.forEach(codeLens -> pairs.add(new Pair(codeLens, languageServer.getSecond())));
}
}))
.toArray(CompletableFuture[]::new)));
}
};
}

private InlayPresentation toPresentation(Editor editor, int offset,
List<Pair<Integer, Pair<CodeLens, LanguageServer>>> elements,
PresentationFactory factory) {

private InlayPresentation toPresentation(
Editor editor,
int offset,
List<Pair<Integer, Pair<CodeLens, LanguageServer>>> elements,
PresentationFactory factory
) {
int line = editor.getDocument().getLineNumber(offset);
int column = offset - editor.getDocument().getLineStartOffset(line);
List<InlayPresentation> presentations = new ArrayList<>();
Expand All @@ -124,9 +144,9 @@ private InlayPresentation toPresentation(Editor editor, int offset,
presentations.add(text);
} else {
// Codelens defines a Command, create a clickable inlay hint
InlayPresentation clickableText = factory.referenceOnHover(text, (event, translated) -> {
executeClientCommand(p.second.second, p.second.first, (Component) event.getSource(), editor.getProject());
});
InlayPresentation clickableText = factory.referenceOnHover(text, (event, translated) ->
executeClientCommand(p.second.second, p.second.first, (Component) event.getSource(), editor.getProject())
);
presentations.add(clickableText);
}
presentations.add(factory.textSpacePlaceholder(1, true));
Expand All @@ -135,11 +155,12 @@ private InlayPresentation toPresentation(Editor editor, int offset,
}

private void executeClientCommand(LanguageServer languageServer, CodeLens codeLens, Component source, Project project) {
if (LanguageServiceAccessor.getInstance(project).checkCapability(languageServer,
capabilites -> Boolean.TRUE.equals(capabilites.getCodeLensProvider().getResolveProvider()))) {
languageServer.getTextDocumentService().resolveCodeLens(codeLens).thenAcceptAsync(resolvedCodeLens -> {
executeClientCommand(source, resolvedCodeLens.getCommand());
});
if (LanguageServiceAccessor.getInstance(project).checkCapability(languageServer, capabilities ->
Boolean.TRUE.equals(capabilities.getCodeLensProvider().getResolveProvider()))
) {
languageServer.getTextDocumentService().resolveCodeLens(codeLens).thenAcceptAsync(resolvedCodeLens ->
executeClientCommand(source, resolvedCodeLens.getCommand())
);
} else {
executeClientCommand(source, codeLens.getCommand());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,43 +63,59 @@ public InlayHintsCollector getCollectorFor(@NotNull PsiFile psiFile,
return new FactoryInlayHintsCollector(editor) {
@Override
public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @NotNull InlayHintsSink inlayHintsSink) {
Document document = editor.getDocument();
try {
URI docURI = LSPIJUtils.toUri(editor.getDocument());
if (docURI != null) {
Range viewPortRange = getViewPortRange(editor);
InlayHintParams param = new InlayHintParams(new TextDocumentIdentifier(docURI.toString()), viewPortRange);
BlockingDeque<Pair<InlayHint, LanguageServer>> pairs = new LinkedBlockingDeque<>();
List<Pair<Integer, Pair<InlayHint, LanguageServer>>> inlayhints = new ArrayList<>();
CompletableFuture<Void> future = LanguageServiceAccessor.getInstance(psiElement.getProject())
.getLanguageServers(editor.getDocument(), capabilities -> capabilities.getInlayHintProvider() != null)
.thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream()
.map(languageServer -> languageServer.getSecond().getTextDocumentService().inlayHint(param)
.thenAcceptAsync(inlayHints -> {
// textDocument/codeLens may return null
if (inlayHints != null) {
inlayHints.stream().filter(Objects::nonNull)
.forEach(inlayHint -> pairs.add(new Pair(inlayHint, languageServer.getSecond())));
}
}))
.toArray(CompletableFuture[]::new)));
while (!future.isDone() || !pairs.isEmpty()) {
ProgressManager.checkCanceled();
Pair<InlayHint, LanguageServer> pair = pairs.poll(25, TimeUnit.MILLISECONDS);
if (pair != null) {
int offset = LSPIJUtils.toOffset(pair.getFirst().getPosition(), editor.getDocument());
inlayhints.add(Pair.create(offset, pair));
}
}
Map<Integer, List<Pair<Integer, Pair<InlayHint, LanguageServer>>>> elements = inlayhints.stream().collect(Collectors.groupingBy(p -> p.first));
elements.forEach((offset, list) -> inlayHintsSink.addInlineElement(offset, false,
toPresentation(editor, offset, list, getFactory()), false));
URI docURI = LSPIJUtils.toUri(document);
if (docURI == null) {
return false;
}
Range viewPortRange = getViewPortRange(editor);
InlayHintParams param = new InlayHintParams(new TextDocumentIdentifier(docURI.toString()), viewPortRange);
BlockingDeque<Pair<InlayHint, LanguageServer>> pairs = new LinkedBlockingDeque<>();
CompletableFuture<Void> future = collect(psiElement.getProject(), document, param, pairs);
List<Pair<Integer, Pair<InlayHint, LanguageServer>>> inlayHints = createInlayHints(document, pairs, future);
Map<Integer, List<Pair<Integer, Pair<InlayHint, LanguageServer>>>> elements = inlayHints.stream().collect(Collectors.groupingBy(p -> p.first));
elements.forEach((offset, list) ->
inlayHintsSink.addInlineElement(offset, false, toPresentation(editor, list, getFactory()), false));
} catch (InterruptedException e) {
LOGGER.warn(e.getLocalizedMessage(), e);
Thread.currentThread().interrupt();
}
return false;
}

@NotNull
private List<Pair<Integer, Pair<InlayHint, LanguageServer>>> createInlayHints(
@NotNull Document document,
BlockingDeque<Pair<InlayHint, LanguageServer>> pairs,
CompletableFuture<Void> future)
throws InterruptedException {
List<Pair<Integer, Pair<InlayHint, LanguageServer>>> inlayHints = new ArrayList<>();
while (!future.isDone() || !pairs.isEmpty()) {
ProgressManager.checkCanceled();
Pair<InlayHint, LanguageServer> pair = pairs.poll(25, TimeUnit.MILLISECONDS);
if (pair != null) {
int offset = LSPIJUtils.toOffset(pair.getFirst().getPosition(), document);
inlayHints.add(Pair.create(offset, pair));
}
}
return inlayHints;
}

private CompletableFuture<Void> collect(@NotNull Project project, @NotNull Document document, InlayHintParams param, BlockingDeque<Pair<InlayHint, LanguageServer>> pairs) {
return LanguageServiceAccessor.getInstance(project)
.getLanguageServers(document, capabilities -> capabilities.getInlayHintProvider() != null)
.thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream()
.map(languageServer -> languageServer.getSecond().getTextDocumentService().inlayHint(param)
.thenAcceptAsync(inlayHints -> {
// textDocument/codeLens may return null
if (inlayHints != null) {
inlayHints.stream().filter(Objects::nonNull)
.forEach(inlayHint -> pairs.add(new Pair(inlayHint, languageServer.getSecond())));
}
}))
.toArray(CompletableFuture[]::new)));
}
};
}

Expand All @@ -114,7 +130,7 @@ private static Range getViewPortRange(Editor editor) {
return new Range(start, end);
}

private InlayPresentation toPresentation(Editor editor, int offset,
private InlayPresentation toPresentation(Editor editor,
List<Pair<Integer, Pair<InlayHint, LanguageServer>>> elements,
PresentationFactory factory) {
List<InlayPresentation> presentations = new ArrayList<>();
Expand All @@ -125,17 +141,7 @@ private InlayPresentation toPresentation(Editor editor, int offset,
} else {
int index = 0;
for (InlayHintLabelPart part : label.getRight()) {
InlayPresentation text = factory.smallText(part.getValue());
if (!hasCommand(part)) {
// No command, create a simple text inlay hint
presentations.add(text);
} else {
// InlayHintLabelPart defines a Command, create a clickable inlay hint
int finalIndex = index;
text = factory.referenceOnHover(text, (event, translated) -> {
executeClientCommand(p.second.second, p.second.first, finalIndex, (Component) event.getSource(), editor.getProject());
});
}
InlayPresentation text = createInlayPresentation(editor.getProject(), factory, presentations, p, index, part);
if (part.getTooltip() != null && part.getTooltip().isLeft()) {
text = factory.withTooltip(part.getTooltip().getLeft(), text);
}
Expand All @@ -147,13 +153,40 @@ private InlayPresentation toPresentation(Editor editor, int offset,
return factory.roundWithBackground(new SequencePresentation(presentations));
}

@NotNull
private InlayPresentation createInlayPresentation(
Project project,
PresentationFactory factory,
List<InlayPresentation> presentations, Pair<Integer,
Pair<InlayHint, LanguageServer>> p,
int index,
InlayHintLabelPart part) {
InlayPresentation text = factory.smallText(part.getValue());
if (!hasCommand(part)) {
// No command, create a simple text inlay hint
presentations.add(text);
} else {
// InlayHintLabelPart defines a Command, create a clickable inlay hint
int finalIndex = index;
text = factory.referenceOnHover(text, (event, translated) ->
executeClientCommand(p.second.second, p.second.first, finalIndex, (Component) event.getSource(), project)
);
}
return text;
}

private static boolean hasCommand(InlayHintLabelPart part) {
Command command = part.getCommand();
return (command != null && command.getCommand() != null && !command.getCommand().isEmpty());
}

private void executeClientCommand(LanguageServer languageServer, InlayHint inlayHint, int index, Component source,
Project project) {
private void executeClientCommand(
LanguageServer languageServer,
InlayHint inlayHint,
int index,
Component source,
Project project
) {
if (LanguageServiceAccessor.getInstance(project)
.checkCapability(languageServer, capabilites -> isResolveSupported(capabilites.getInlayHintProvider()))) {
languageServer.getTextDocumentService()
Expand Down
Loading