condition) {
ITextEditor textEditor = UI.getActiveTextEditor();
if (textEditor != null && condition.test(textEditor)) {
IDocument document = LSPEclipseUtils.getDocument(textEditor);
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/NullSafetyHelper.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/NullSafetyHelper.java
new file mode 100644
index 000000000..618c5fea9
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/NullSafetyHelper.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2022 Sebastian Thomschke and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Sebastian Thomschke - initial implementation
+ */
+package org.eclipse.lsp4e.internal;
+
+import java.util.function.Supplier;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
+public final class NullSafetyHelper {
+
+ /**
+ * Casts a non-null value marked as {@link Nullable} to {@link NonNull}.
+ *
+ * Only use if you are sure the value is non-null but annotation-based null analysis was not able to determine it.
+ *
+ * This method is not meant for non-null input validation.
+ *
+ * @throws IllegalStateException if the given value is null
+ */
+ public static @NonNull T castNonNull(final @Nullable T value) {
+ if (value == null)
+ throw new IllegalStateException("Unexpected null value present!"); //$NON-NLS-1$
+ return value;
+ }
+
+ /**
+ * Casts the elements of given array to {@link NonNull} without any validation.
+ *
+ * Only use if you are sure the value is non-null but annotation-based null analysis was not able to determine it.
+ */
+ @SuppressWarnings("null")
+ public static @NonNull T castNonNullUnsafe(final T value) {
+ return value;
+ }
+
+ /**
+ * Casts a non-null value as {@link Nullable}.
+ */
+ public static @Nullable T castNullable(final T value) {
+ return value;
+ }
+
+ public static T defaultIfNull(final @Nullable T object, final T defaultValue) {
+ if (object == null) {
+ return defaultValue;
+ }
+ return object;
+ }
+
+ public static T defaultIfNull(final @Nullable T object, final Supplier defaultValue) {
+ if (object == null) {
+ return defaultValue.get();
+ }
+ return object;
+ }
+
+ /**
+ * Allows to initializes a @NonNull field with null
that is
+ * initialized later.
+ */
+ @SuppressWarnings("unchecked")
+ public static @NonNull T lateNonNull() {
+ return (T) castNonNullUnsafe(null);
+ }
+
+ private NullSafetyHelper() {
+ }
+}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/StyleUtil.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/StyleUtil.java
index 25a3237b6..a67043b8f 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/StyleUtil.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/StyleUtil.java
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.lsp4e.internal;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.swt.graphics.TextStyle;
@@ -22,7 +23,7 @@ private StyleUtil() {
public static final Styler DEPRECATE = new Styler() {
@Override
- public void applyStyles(TextStyle textStyle) {
+ public void applyStyles(@NonNullByDefault({}) TextStyle textStyle) {
textStyle.strikeout = true;
}
};
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/SupportedFeatures.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/SupportedFeatures.java
index 2bfb80dc1..3a1f4f681 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/SupportedFeatures.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/SupportedFeatures.java
@@ -15,7 +15,6 @@
import java.util.Arrays;
import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.lsp4j.CodeActionCapabilities;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.CodeActionKindCapabilities;
@@ -63,7 +62,7 @@
public class SupportedFeatures {
- public static @NonNull TextDocumentClientCapabilities getTextDocumentClientCapabilities() {
+ public static TextDocumentClientCapabilities getTextDocumentClientCapabilities() {
final var textDocumentClientCapabilities = new TextDocumentClientCapabilities();
final var codeAction = new CodeActionCapabilities(new CodeActionLiteralSupportCapabilities(
new CodeActionKindCapabilities(Arrays.asList(CodeActionKind.QuickFix, CodeActionKind.Refactor,
@@ -127,7 +126,7 @@ public class SupportedFeatures {
return textDocumentClientCapabilities;
}
- public static @NonNull WorkspaceClientCapabilities getWorkspaceClientCapabilities() {
+ public static WorkspaceClientCapabilities getWorkspaceClientCapabilities() {
final var workspaceClientCapabilities = new WorkspaceClientCapabilities();
workspaceClientCapabilities.setApplyEdit(Boolean.TRUE);
workspaceClientCapabilities.setConfiguration(Boolean.TRUE);
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/package-info.java
new file mode 100644
index 000000000..9ede697f8
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.internal;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionCompletionProposal.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionCompletionProposal.java
index 7e5d7ba3d..e99d98790 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionCompletionProposal.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionCompletionProposal.java
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.codeactions;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -29,8 +30,8 @@
public class CodeActionCompletionProposal implements ICompletionProposal {
- private CodeAction fcodeAction;
- private Command fcommand;
+ private @Nullable CodeAction fcodeAction;
+ private @Nullable Command fcommand;
private String fdisplayString;
private final LanguageServerWrapper serverWrapper;
@@ -39,13 +40,13 @@ public CodeActionCompletionProposal(Either command, Languag
if (command.isLeft()) {
fcommand = command.getLeft();
fdisplayString = fcommand.getTitle();
- } else if (command.isRight()) {
+ } else {
fcodeAction = command.getRight();
fdisplayString = fcodeAction.getTitle();
}
}
- static boolean isCodeActionResolveSupported(ServerCapabilities capabilities) {
+ static boolean isCodeActionResolveSupported(@Nullable ServerCapabilities capabilities) {
if (capabilities != null) {
Either caProvider = capabilities.getCodeActionProvider();
if (caProvider.isLeft()) {
@@ -62,6 +63,7 @@ static boolean isCodeActionResolveSupported(ServerCapabilities capabilities) {
@Override
public void apply(IDocument document) {
+ final var fcodeAction = this.fcodeAction;
if (fcodeAction != null) {
if (isCodeActionResolveSupported(serverWrapper.getServerCapabilities()) && fcodeAction.getEdit() == null) {
// Unresolved code action "edit" property. Resolve it.
@@ -76,7 +78,7 @@ public void apply(IDocument document) {
}
}
- private void apply(CodeAction codeaction) {
+ private void apply(@Nullable CodeAction codeaction) {
if (codeaction != null) {
if (codeaction.getEdit() != null) {
LSPEclipseUtils.applyWorkspaceEdit(codeaction.getEdit(), codeaction.getTitle());
@@ -88,13 +90,13 @@ private void apply(CodeAction codeaction) {
}
@Override
- public Point getSelection(IDocument document) {
+ public @Nullable Point getSelection(IDocument document) {
return null;
}
@Override
- public String getAdditionalProposalInfo() {
- return ""; //$NON-NLS-1$
+ public @Nullable String getAdditionalProposalInfo() {
+ return null;
}
@Override
@@ -103,12 +105,12 @@ public String getDisplayString() {
}
@Override
- public Image getImage() {
+ public @Nullable Image getImage() {
return null;
}
@Override
- public IContextInformation getContextInformation() {
+ public @Nullable IContextInformation getContextInformation() {
return new ContextInformation("some context display string", "some information display string"); //$NON-NLS-1$//$NON-NLS-2$
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionMarkerResolution.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionMarkerResolution.java
index 0e35472b5..18ae578cb 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionMarkerResolution.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CodeActionMarkerResolution.java
@@ -20,6 +20,7 @@
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServerWrapper;
@@ -34,6 +35,7 @@
import org.eclipse.lsp4j.ExecuteCommandOptions;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.MessageType;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IMarkerResolution;
@@ -53,7 +55,7 @@ public String getDescription() {
}
@Override
- public Image getImage() {
+ public @Nullable Image getImage() {
return null;
}
@@ -92,7 +94,8 @@ public void run(IMarker marker) {
}
if (codeAction.getCommand() != null) {
Command command = codeAction.getCommand();
- ExecuteCommandOptions provider = wrapper.getServerCapabilities().getExecuteCommandProvider();
+ ServerCapabilities cap = wrapper.getServerCapabilities();
+ ExecuteCommandOptions provider = cap == null ? null : cap.getExecuteCommandProvider();
if (provider != null && provider.getCommands().contains(command.getCommand())) {
final LanguageServerDefinition serverDefinition = wrapper.serverDefinition;
wrapper.execute(ls -> ls.getWorkspaceService()
@@ -127,9 +130,6 @@ private ShowMessageRequestParams reportServerError(LanguageServerDefinition serv
@Override
public IMarker[] findOtherMarkers(IMarker[] markers) {
- if (markers == null) {
- return new IMarker[0];
- }
return Arrays.stream(markers).filter(marker -> {
try {
return codeAction.getDiagnostics()
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CommandMarkerResolution.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CommandMarkerResolution.java
index 0bdddbd73..d41179ae0 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CommandMarkerResolution.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/CommandMarkerResolution.java
@@ -14,7 +14,7 @@
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.lsp4e.LanguageServerWrapper;
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
@@ -24,15 +24,16 @@
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.ExecuteCommandOptions;
import org.eclipse.lsp4j.ExecuteCommandParams;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.views.markers.WorkbenchMarkerResolution;
public class CommandMarkerResolution extends WorkbenchMarkerResolution implements IMarkerResolution {
- private final @NonNull Command command;
+ private final Command command;
- public CommandMarkerResolution(@NonNull Command command) {
+ public CommandMarkerResolution(Command command) {
this.command = command;
}
@@ -57,14 +58,13 @@ public void run(IMarker marker) {
}
LanguageServerWrapper wrapper = LanguageServiceAccessor.getLSWrapper(resource.getProject(), definition);
- if (wrapper != null) {
- ExecuteCommandOptions provider = wrapper.getServerCapabilities().getExecuteCommandProvider();
- if (provider != null && provider.getCommands().contains(command.getCommand())) {
- wrapper.execute(ls -> ls.getWorkspaceService()
- .executeCommand(new ExecuteCommandParams(command.getCommand(), command.getArguments())));
- } else {
- CommandExecutor.executeCommandClientSide(command, resource);
- }
+ ServerCapabilities cap = wrapper.getServerCapabilities();
+ ExecuteCommandOptions provider = cap == null ? null : cap.getExecuteCommandProvider();
+ if (provider != null && provider.getCommands().contains(command.getCommand())) {
+ wrapper.execute(ls -> ls.getWorkspaceService()
+ .executeCommand(new ExecuteCommandParams(command.getCommand(), command.getArguments())));
+ } else {
+ CommandExecutor.executeCommandClientSide(command, resource);
}
}
@@ -74,7 +74,7 @@ public String getDescription() {
}
@Override
- public Image getImage() {
+ public @Nullable Image getImage() {
return null;
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
index 7d39a5272..04989a3cf 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
@@ -11,7 +11,8 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.codeactions;
-import java.io.IOException;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;
+
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
@@ -27,6 +28,7 @@
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.ITextHover;
@@ -83,7 +85,7 @@ public String getLabel() {
@Override
public Image getImage() {
// load class so image is loaded
- return JFaceResources.getImage(ProgressInfoItem.class.getPackage().getName() + ".PROGRESS_DEFAULT"); //$NON-NLS-1$
+ return JFaceResources.getImage(ProgressInfoItem.class.getPackageName() + ".PROGRESS_DEFAULT"); //$NON-NLS-1$
}
@Override
@@ -101,13 +103,13 @@ public IMarkerResolution[] getResolutions(IMarker marker) {
checkMarkerResolution(marker);
att = marker.getAttribute(LSP_REMEDIATION);
}
- } catch (IOException | CoreException | ExecutionException e) {
- LanguageServerPlugin.logError(e);
- return new IMarkerResolution[0];
} catch (InterruptedException e) {
LanguageServerPlugin.logError(e);
Thread.currentThread().interrupt();
return new IMarkerResolution[0];
+ } catch (Exception e) {
+ LanguageServerPlugin.logError(e);
+ return new IMarkerResolution[0];
}
if (att == COMPUTING) {
return new IMarkerResolution[] { COMPUTING };
@@ -119,7 +121,7 @@ public IMarkerResolution[] getResolutions(IMarker marker) {
.toArray(IMarkerResolution[]::new);
}
- private void checkMarkerResolution(IMarker marker) throws IOException, CoreException, InterruptedException, ExecutionException {
+ private void checkMarkerResolution(IMarker marker) throws CoreException, InterruptedException, ExecutionException {
IResource res = marker.getResource();
if (res instanceof IFile file) {
Object[] attributes = marker.getAttributes(new String[]{LSPDiagnosticsToMarkers.LANGUAGE_SERVER_ID, LSPDiagnosticsToMarkers.LSP_DIAGNOSTIC});
@@ -132,7 +134,7 @@ private void checkMarkerResolution(IMarker marker) throws IOException, CoreExcep
final var context = new CodeActionContext(Collections.singletonList(diagnostic));
final var params = new CodeActionParams();
params.setContext(context);
- params.setTextDocument(LSPEclipseUtils.toTextDocumentIdentifier(res));
+ params.setTextDocument(castNonNull(LSPEclipseUtils.toTextDocumentIdentifier(res)));
params.setRange(diagnostic.getRange());
if (marker.exists()) { // otherwise the marker has been removed by now
marker.setAttribute(LSP_REMEDIATION, COMPUTING);
@@ -174,7 +176,7 @@ private void reinvokeQuickfixProposalsIfNecessary(ITextViewer textViewer) {
final var ca = (ContentAssistant) f.get(quickAssistant);
Method m = ContentAssistant.class.getDeclaredMethod("isProposalPopupActive"); //$NON-NLS-1$
m.setAccessible(true);
- boolean isProposalPopupActive = (Boolean) m.invoke(ca);
+ boolean isProposalPopupActive = (Boolean) castNonNull(m.invoke(ca));
if (isProposalPopupActive) {
quickAssistant.showPossibleQuickAssists();
}
@@ -198,7 +200,7 @@ private void reinvokeQuickfixProposalsIfNecessary(ITextViewer textViewer) {
}
}
- static boolean providesCodeActions(final ServerCapabilities capabilities) {
+ static boolean providesCodeActions(final @Nullable ServerCapabilities capabilities) {
return capabilities != null && LSPEclipseUtils.hasCapability(capabilities.getCodeActionProvider());
}
@@ -217,7 +219,7 @@ public boolean hasResolutions(IMarker marker) {
return false;
}
- static boolean canPerform(Either command) {
+ static boolean canPerform(@Nullable Either command) {
if (command == null) {
return false;
}
@@ -239,7 +241,7 @@ static boolean canPerform(Either command) {
TextDocumentEdit textedit = change.getLeft();
VersionedTextDocumentIdentifier id = textedit.getTextDocument();
URI uri = URI.create(id.getUri());
- if (uri != null && LSPEclipseUtils.isReadOnly(uri)) {
+ if (LSPEclipseUtils.isReadOnly(uri)) {
return false;
}
}
@@ -249,7 +251,7 @@ static boolean canPerform(Either command) {
if (changes != null) {
for (java.util.Map.Entry> textEdit : changes.entrySet()) {
URI uri = URI.create(textEdit.getKey());
- if (uri != null && LSPEclipseUtils.isReadOnly(uri)) {
+ if (LSPEclipseUtils.isReadOnly(uri)) {
return false;
}
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionQuickAssistProcessor.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionQuickAssistProcessor.java
index cdc507a3f..ebd25093c 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionQuickAssistProcessor.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionQuickAssistProcessor.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.codeactions;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -19,10 +21,10 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
@@ -44,8 +46,8 @@
public class LSPCodeActionQuickAssistProcessor implements IQuickAssistProcessor {
// Data necessary for caching proposals
- private Object lock = new Object();
- private IQuickAssistInvocationContext cachedContext;
+ private final Object lock = new Object();
+ private @Nullable IQuickAssistInvocationContext cachedContext;
private List proposals = Collections.synchronizedList(new ArrayList<>());
private static final ICompletionProposal COMPUTING = new ICompletionProposal() {
@@ -56,12 +58,12 @@ public void apply(IDocument document) {
}
@Override
- public Point getSelection(IDocument document) {
+ public @Nullable Point getSelection(IDocument document) {
return null;
}
@Override
- public String getAdditionalProposalInfo() {
+ public @Nullable String getAdditionalProposalInfo() {
return null;
}
@@ -71,19 +73,16 @@ public String getDisplayString() {
}
@Override
- public Image getImage() {
- return JFaceResources.getImage(ProgressInfoItem.class.getPackage().getName() + ".PROGRESS_DEFAULT"); //$NON-NLS-1$
+ public @Nullable Image getImage() {
+ return JFaceResources.getImage(ProgressInfoItem.class.getPackageName() + ".PROGRESS_DEFAULT"); //$NON-NLS-1$
}
@Override
- public IContextInformation getContextInformation() {
+ public @Nullable IContextInformation getContextInformation() {
return null;
}
-
};
- CompletionProposal[] NO_PROPOSALS = {};
-
@Override
public String getErrorMessage() {
return "CodeActions not implemented on this Language Server"; //$NON-NLS-1$
@@ -105,14 +104,14 @@ public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
}
@Override
- public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
+ public ICompletionProposal @Nullable [] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
IDocument document = invocationContext.getSourceViewer().getDocument();
if (document == null) {
- return NO_PROPOSALS;
+ return null;
}
LanguageServerDocumentExecutor executor = LanguageServers.forDocument(document).withFilter(LSPCodeActionMarkerResolution::providesCodeActions);
if (!executor.anyMatching()) {
- return NO_PROPOSALS;
+ return null;
}
// If context has changed, i.e. new quick assist invocation rather than old
@@ -120,14 +119,15 @@ public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationC
// the UI
boolean needNewQuery = true;
synchronized (lock) {
- needNewQuery = cachedContext == null || invocationContext == null ||
+ final var cachedContext = this.cachedContext;
+ needNewQuery = cachedContext == null ||
cachedContext.getClass() != invocationContext.getClass() ||
cachedContext.getSourceViewer() != invocationContext.getSourceViewer() ||
cachedContext.getOffset() != invocationContext.getOffset() ||
cachedContext.getLength() != invocationContext.getLength();
// should also check whether (same) document content changed
if (needNewQuery) {
- cachedContext = invocationContext;
+ this.cachedContext = invocationContext;
}
}
@@ -138,7 +138,7 @@ public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationC
proposals.clear();
// Start all the servers computing actions - each server will append any code actions to the ongoing list of proposals
// as a side effect of this request
- List> futures = executor.computeAll((w, ls) -> ls.getTextDocumentService()
+ List> futures = executor.computeAll((w, ls) -> ls.getTextDocumentService()
.codeAction(params)
.thenAccept(actions -> LanguageServers.streamSafely(actions)
.filter(LSPCodeActionMarkerResolution::canPerform)
@@ -156,7 +156,7 @@ public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationC
// Server calls didn't complete in time; those that did will have added their results to this.proposals
and can be returned
// as an intermediate result; as we're returning control to the UI, we need any stragglers to trigger a refresh when they arrive later on
proposals.add(COMPUTING);
- for (CompletableFuture future : futures) {
+ for (CompletableFuture<@Nullable Void> future : futures) {
// Refresh will effectively re-enter this method with the same invocationContext and already computed proposals simply to show the proposals in the UI
future.whenComplete((r, t) -> {
if (futures.stream().allMatch(CompletableFuture::isDone)) {
@@ -194,7 +194,7 @@ private void refreshProposals(IQuickAssistInvocationContext invocationContext) {
private static CodeActionParams prepareCodeActionParams(final IDocument doc, int offset, int length) {
final var context = new CodeActionContext(Collections.emptyList());
final var params = new CodeActionParams();
- params.setTextDocument(LSPEclipseUtils.toTextDocumentIdentifier(doc));
+ params.setTextDocument(castNonNull(LSPEclipseUtils.toTextDocumentIdentifier(doc)));
try {
params.setRange(new Range(LSPEclipseUtils.toPosition(offset, doc), LSPEclipseUtils
.toPosition(offset + (length > 0 ? length : 0), doc)));
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionsMenu.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionsMenu.java
index 74609680a..aafc037bd 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionsMenu.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionsMenu.java
@@ -12,7 +12,8 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.codeactions;
-import java.net.URI;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.*;
+
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -20,7 +21,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
@@ -52,8 +53,8 @@
public class LSPCodeActionsMenu extends ContributionItem implements IWorkbenchContribution {
- private IDocument document;
- private Range range;
+ private IDocument document = lateNonNull();
+ private Range range = lateNonNull();
@Override
public void initialize(IServiceLocator serviceLocator) {
@@ -81,19 +82,18 @@ public void fill(final Menu menu, int index) {
item.setEnabled(false);
item.setText(Messages.computing);
- final @NonNull IDocument document = this.document;
- final URI fileUri = LSPEclipseUtils.toUri(document);
+ final IDocument document = this.document;
final var context = new CodeActionContext(Collections.emptyList());
final var params = new CodeActionParams();
- params.setTextDocument(LSPEclipseUtils.toTextDocumentIdentifier(fileUri));
+ params.setTextDocument(castNonNull(LSPEclipseUtils.toTextDocumentIdentifier(document)));
params.setRange(this.range);
params.setContext(context);
- final @NonNull List<@NonNull CompletableFuture>>> actions
- = LanguageServers.forDocument(document).withFilter(LSPCodeActionMarkerResolution::providesCodeActions)
- .computeAll((w, ls) -> ls.getTextDocumentService().codeAction(params)
- .whenComplete((codeActions, t) -> scheduleMenuUpdate(menu, item, index, document, w, t, codeActions)));
+ final List>>> actions = LanguageServers.forDocument(document)
+ .withFilter(LSPCodeActionMarkerResolution::providesCodeActions)
+ .computeAll((w, ls) -> ls.getTextDocumentService().codeAction(params).whenComplete(
+ (codeActions, t) -> scheduleMenuUpdate(menu, item, index, document, w, t, codeActions)));
if (actions.isEmpty()) {
item.setText(Messages.notImplemented);
@@ -103,13 +103,15 @@ public void fill(final Menu menu, int index) {
super.fill(menu, index);
}
- private void scheduleMenuUpdate(final Menu menu, final MenuItem placeHolder, final int index, final IDocument document, final LanguageServerWrapper wrapper, final Throwable u, final List> codeActions) {
+ private void scheduleMenuUpdate(final Menu menu, final MenuItem placeHolder, final int index,
+ final IDocument document, final LanguageServerWrapper wrapper, final @Nullable Throwable ex,
+ final @Nullable List<@Nullable Either> codeActions) {
final var job = new UIJob(menu.getDisplay(), Messages.updateCodeActions_menu) {
@Override
- public IStatus runInUIThread(IProgressMonitor monitor) {
- if (u != null) {
+ public IStatus runInUIThread(@Nullable IProgressMonitor monitor) {
+ if (ex != null) {
final var item = new MenuItem(menu, SWT.NONE, index);
- item.setText(u.getMessage());
+ item.setText(String.valueOf(ex.getMessage()));
item.setImage(LSPImages.getSharedImage(ISharedImages.IMG_DEC_FIELD_ERROR));
item.setEnabled(false);
} else if (codeActions != null) {
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/package-info.java
new file mode 100644
index 000000000..1ada6a32f
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.codeactions;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/CodeLensProvider.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/CodeLensProvider.java
index ad21a57c7..bf26be5b2 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/CodeLensProvider.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/CodeLensProvider.java
@@ -14,7 +14,7 @@
import java.util.concurrent.CompletableFuture;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
@@ -30,24 +30,24 @@
public class CodeLensProvider extends AbstractCodeMiningProvider {
- private CompletableFuture> provideCodeMinings(@NonNull IDocument document) {
+ private @Nullable CompletableFuture> provideCodeMinings(IDocument document) {
URI docURI = LSPEclipseUtils.toUri(document);
if (docURI != null) {
final var param = new CodeLensParams(LSPEclipseUtils.toTextDocumentIdentifier(docURI));
LanguageServerDocumentExecutor executor = LanguageServers.forDocument(document)
.withFilter(sc -> sc.getCodeLensProvider() != null);
- return executor.collectAll((w, ls) -> ls.getTextDocumentService().codeLens(param)
- .thenApply(codeLenses -> LanguageServers.streamSafely(codeLenses)
- .map(codeLens -> toCodeMining(document, w, codeLens))
- .filter(Objects::nonNull)))
- .thenApply(result -> result.stream().flatMap(s -> s).toList());
- }
- else {
+ return executor
+ .collectAll((w, ls) -> ls.getTextDocumentService().codeLens(param)
+ .thenApply(codeLenses -> LanguageServers.streamSafely(codeLenses)
+ .map(codeLens -> toCodeMining(document, w, codeLens)).filter(Objects::nonNull)))
+ .thenApply(result -> result.stream().flatMap(s -> s).toList());
+ } else {
return null;
}
}
- private LSPCodeMining toCodeMining(IDocument document, LanguageServerWrapper languageServerWrapper, CodeLens codeLens) {
+ private @Nullable LSPCodeMining toCodeMining(IDocument document, LanguageServerWrapper languageServerWrapper,
+ @Nullable CodeLens codeLens) {
if (codeLens == null) {
return null;
}
@@ -60,7 +60,7 @@ private LSPCodeMining toCodeMining(IDocument document, LanguageServerWrapper lan
}
@Override
- public CompletableFuture> provideCodeMinings(ITextViewer viewer,
+ public @Nullable CompletableFuture> provideCodeMinings(ITextViewer viewer,
IProgressMonitor monitor) {
IDocument document = viewer.getDocument();
return document != null ? provideCodeMinings(document) : null;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/LSPCodeMining.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/LSPCodeMining.java
index d916b6683..bd2a0cb66 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/LSPCodeMining.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/LSPCodeMining.java
@@ -12,7 +12,6 @@
import java.util.function.Consumer;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
@@ -24,15 +23,16 @@
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.ExecuteCommandOptions;
import org.eclipse.lsp4j.ExecuteCommandParams;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.swt.events.MouseEvent;
public class LSPCodeMining extends LineHeaderCodeMining {
private CodeLens codeLens;
private final LanguageServerWrapper languageServerWrapper;
- private final @NonNull IDocument document;
+ private final IDocument document;
- public LSPCodeMining(CodeLens codeLens, @NonNull IDocument document, LanguageServerWrapper languageServerWrapper,
+ public LSPCodeMining(CodeLens codeLens, IDocument document, LanguageServerWrapper languageServerWrapper,
CodeLensProvider provider) throws BadLocationException {
super(codeLens.getRange().getStart().getLine(), document, provider, null);
this.codeLens = codeLens;
@@ -41,7 +41,7 @@ public LSPCodeMining(CodeLens codeLens, @NonNull IDocument document, LanguageSer
setLabel(getCodeLensString(codeLens));
}
- protected static @Nullable String getCodeLensString(@NonNull CodeLens codeLens) {
+ protected static @Nullable String getCodeLensString(CodeLens codeLens) {
Command command = codeLens.getCommand();
if (command == null || command.getTitle().isEmpty()) {
return null;
@@ -51,22 +51,26 @@ public LSPCodeMining(CodeLens codeLens, @NonNull IDocument document, LanguageSer
@Override
protected CompletableFuture doResolve(ITextViewer viewer, IProgressMonitor monitor) {
- final Boolean resolveProvider = this.languageServerWrapper.getServerCapabilities().getCodeLensProvider().getResolveProvider();
+ final ServerCapabilities serverCapabilities = languageServerWrapper.getServerCapabilities();
+ if (serverCapabilities == null) {
+ return CompletableFuture.completedFuture(null);
+ }
+ final Boolean resolveProvider = serverCapabilities.getCodeLensProvider().getResolveProvider();
if (resolveProvider == null || !resolveProvider) {
return CompletableFuture.completedFuture(null);
}
- return this.languageServerWrapper.execute(languageServer -> languageServer.getTextDocumentService().resolveCodeLens(this.codeLens))
+ return languageServerWrapper.execute(languageServer -> languageServer.getTextDocumentService().resolveCodeLens(this.codeLens))
.thenAccept(resolvedCodeLens -> {
- codeLens = resolvedCodeLens;
if (resolvedCodeLens != null) {
+ codeLens = resolvedCodeLens;
setLabel(getCodeLensString(resolvedCodeLens));
}
});
}
@Override
- public final Consumer getAction() {
+ public final @Nullable Consumer getAction() {
final Command command = codeLens.getCommand();
if(command != null && command.getCommand() != null && !command.getCommand().isEmpty()) {
return this::performAction;
@@ -76,7 +80,8 @@ public final Consumer getAction() {
}
private void performAction(MouseEvent mouseEvent) {
- ExecuteCommandOptions provider = languageServerWrapper.getServerCapabilities().getExecuteCommandProvider();
+ final ServerCapabilities serverCapabilities = languageServerWrapper.getServerCapabilities();
+ ExecuteCommandOptions provider = serverCapabilities == null ? null : serverCapabilities.getExecuteCommandProvider();
Command command = codeLens.getCommand();
if (provider != null && provider.getCommands().contains(command.getCommand())) {
languageServerWrapper.execute(ls -> ls.getWorkspaceService()
@@ -86,5 +91,4 @@ private void performAction(MouseEvent mouseEvent) {
}
}
-
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/package-info.java
new file mode 100644
index 000000000..7832f693f
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codelens/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.codelens;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/ColorInformationMining.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/ColorInformationMining.java
index 4972db60d..22a67f4a3 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/ColorInformationMining.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/ColorInformationMining.java
@@ -13,7 +13,6 @@
import java.util.function.Consumer;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
@@ -84,7 +83,7 @@ public void accept(MouseEvent event) {
LSPEclipseUtils.toColor(rgb), colorInformation.getRange());
this.languageServerWrapper.execute(ls -> ls.getTextDocumentService().colorPresentation(params))
.thenAcceptAsync(presentations -> {
- if (presentations.isEmpty()) {
+ if (presentations == null || presentations.isEmpty()) {
return;
}
// As ColorDialog cannot be customized (to choose the color presentation (rgb,
@@ -102,7 +101,7 @@ public void accept(MouseEvent event) {
}
}
- public ColorInformationMining(ColorInformation colorInformation, @NonNull IDocument document,
+ public ColorInformationMining(ColorInformation colorInformation, IDocument document,
TextDocumentIdentifier textDocumentIdentifier, LanguageServerWrapper languageServerWrapper,
DocumentColorProvider colorProvider) throws BadLocationException {
super(toPosition(colorInformation.getRange(), document), colorProvider,
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/DocumentColorProvider.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/DocumentColorProvider.java
index dbfe56029..5282491d0 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/DocumentColorProvider.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/DocumentColorProvider.java
@@ -20,7 +20,7 @@
import java.util.function.Function;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
@@ -51,7 +51,7 @@ public DocumentColorProvider() {
colorTable = new HashMap<>();
}
- private CompletableFuture> provideCodeMinings(@NonNull IDocument document) {
+ private @Nullable CompletableFuture> provideCodeMinings(IDocument document) {
URI docURI = LSPEclipseUtils.toUri(document);
if (docURI != null) {
@@ -71,7 +71,7 @@ private CompletableFuture> provideCodeMinings(@NonNu
}
}
- private ColorInformationMining toMining(ColorInformation color, @NonNull IDocument document, TextDocumentIdentifier textDocumentIdentifier, LanguageServerWrapper wrapper) {
+ private @Nullable ColorInformationMining toMining(ColorInformation color, IDocument document, TextDocumentIdentifier textDocumentIdentifier, LanguageServerWrapper wrapper) {
try {
return new ColorInformationMining(color, document,
textDocumentIdentifier, wrapper,
@@ -83,7 +83,7 @@ private ColorInformationMining toMining(ColorInformation color, @NonNull IDocume
}
@Override
- public CompletableFuture> provideCodeMinings(ITextViewer viewer,
+ public @Nullable CompletableFuture> provideCodeMinings(ITextViewer viewer,
IProgressMonitor monitor) {
IDocument document = viewer.getDocument();
return document != null ? provideCodeMinings(document) : null;
@@ -102,7 +102,7 @@ public Color getColor(RGBA rgba, Display display) {
return colorTable.computeIfAbsent(rgba, key -> new Color(display, rgba));
}
- private static boolean isColorProvider(final ServerCapabilities capabilities) {
+ private static boolean isColorProvider(final @Nullable ServerCapabilities capabilities) {
return capabilities != null && LSPEclipseUtils.hasCapability(capabilities.getColorProvider());
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/package-info.java
new file mode 100644
index 000000000..a0d3536ae
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/color/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.color;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionProposalTools.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionProposalTools.java
index cb55528f9..97aee48dd 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionProposalTools.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionProposalTools.java
@@ -150,7 +150,7 @@ public static int getScoreOfFilterMatch(String documentFilter, String completion
}
private static int getScoreOfFilterMatchHelper(int prefixLength, String documentFilter, String completionFilter) {
- if (documentFilter == null || documentFilter.isEmpty()) {
+ if (documentFilter.isEmpty()) {
return 0;
}
char searchChar = documentFilter.charAt(0);
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionSnippetParser.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionSnippetParser.java
index 54f36dde8..a4be7779e 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionSnippetParser.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/CompletionSnippetParser.java
@@ -24,7 +24,6 @@
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.ProposalPosition;
-
/**
* A parser for the completion insert text in
* snippet syntax
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSCompletionProposal.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSCompletionProposal.java
index 81e122dad..87a097d15 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSCompletionProposal.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSCompletionProposal.java
@@ -16,10 +16,13 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.completion;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -29,7 +32,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
import org.eclipse.jface.text.BadLocationException;
@@ -118,25 +121,25 @@ public class LSCompletionProposal
private final int initialOffset;
protected int bestOffset = -1;
protected int currentOffset = -1;
- protected ITextViewer viewer;
+ protected @Nullable ITextViewer viewer;
private final IDocument document;
private final boolean isIncomplete;
- private IRegion selection;
- private LinkedPosition firstPosition;
+ private @Nullable IRegion selection;
+ private @Nullable LinkedPosition firstPosition;
// private LSPDocumentInfo info;
- private Integer rankCategory;
- private Integer rankScore;
- private String documentFilter;
+ private @Nullable Integer rankCategory;
+ private @Nullable Integer rankScore;
+ private @Nullable String documentFilter;
private String documentFilterAddition = ""; //$NON-NLS-1$
private final LanguageServerWrapper languageServerWrapper;
- public LSCompletionProposal(@NonNull IDocument document, int offset, @NonNull CompletionItem item,
+ public LSCompletionProposal(IDocument document, int offset, CompletionItem item,
LanguageServerWrapper languageServerWrapper) {
this(document, offset, item, null, languageServerWrapper, false);
}
- public LSCompletionProposal(@NonNull IDocument document, int offset, @NonNull CompletionItem item,
- CompletionItemDefaults defaults, LanguageServerWrapper languageServerWrapper, boolean isIncomplete) {
+ public LSCompletionProposal(IDocument document, int offset, CompletionItem item,
+ @Nullable CompletionItemDefaults defaults, LanguageServerWrapper languageServerWrapper, boolean isIncomplete) {
this.item = item;
this.document = document;
this.languageServerWrapper = languageServerWrapper;
@@ -193,8 +196,8 @@ public String getDocumentFilter() throws BadLocationException {
if (documentFilter != null) {
return documentFilter + documentFilterAddition;
}
- documentFilter = CompletionProposalTools.getFilterFromDocument(document, currentOffset,
- getFilterString(), bestOffset);
+ final var documentFilter = this.documentFilter = CompletionProposalTools.getFilterFromDocument(document,
+ currentOffset, getFilterString(), bestOffset);
documentFilterAddition = ""; //$NON-NLS-1$
return documentFilter;
}
@@ -208,6 +211,7 @@ public String getDocumentFilter() throws BadLocationException {
public int getRankScore() {
if (rankScore != null)
return rankScore;
+ int rankScore;
try {
rankScore = CompletionProposalTools.getScoreOfFilterMatch(getDocumentFilter(),
getFilterString());
@@ -215,6 +219,7 @@ public int getRankScore() {
LanguageServerPlugin.logError(e);
rankScore = -1;
}
+ this.rankScore = rankScore;
return rankScore;
}
@@ -229,6 +234,7 @@ public int getRankCategory() {
if (rankCategory != null) {
return rankCategory;
}
+ int rankCategory;
try {
rankCategory = CompletionProposalTools.getCategoryOfFilterMatch(getDocumentFilter(),
getFilterString());
@@ -236,6 +242,7 @@ public int getRankCategory() {
LanguageServerPlugin.logError(e);
rankCategory = 5;
}
+ this.rankCategory = rankCategory;
return rankCategory;
}
@@ -312,7 +319,7 @@ public boolean isAutoInsertable() {
}
@Override
- public IInformationControlCreator getInformationControlCreator() {
+ public @Nullable IInformationControlCreator getInformationControlCreator() {
return new AbstractReusableInformationControlCreator() {
@Override
protected IInformationControl doCreateInformationControl(Shell parent) {
@@ -348,7 +355,7 @@ public String getAdditionalProposalInfo(IProgressMonitor monitor) {
return res.toString();
}
- private boolean resolvesCompletionItem(final ServerCapabilities capabilities) {
+ private boolean resolvesCompletionItem(final @Nullable ServerCapabilities capabilities) {
if (capabilities != null) {
CompletionOptions completionProvider = capabilities.getCompletionProvider();
if (completionProvider != null) {
@@ -373,7 +380,7 @@ private void resolveItem() {
}
}
- private void updateCompletionItem(CompletionItem resolvedItem) {
+ private void updateCompletionItem(@Nullable CompletionItem resolvedItem) {
if (resolvedItem == null) {
return;
}
@@ -404,7 +411,7 @@ private void updateCompletionItem(CompletionItem resolvedItem) {
}
@Override
- public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
+ public @Nullable CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
return item.getInsertText().substring(completionOffset - bestOffset);
}
@@ -532,6 +539,7 @@ protected void apply(IDocument document, char trigger, int stateMask, int offset
}
boolean onlyPlaceCaret = regions.size() == 1 && regions.values().iterator().next().size() == 1 && regions.values().iterator().next().stream().noneMatch(ProposalPosition.class::isInstance);
+ final var viewer = this.viewer;
if (viewer != null && !regions.isEmpty() && !onlyPlaceCaret) {
final var model = new LinkedModeModel();
for (List positions: regions.values()) {
@@ -558,7 +566,8 @@ protected void apply(IDocument document, char trigger, int stateMask, int offset
if (item.getCommand() != null) {
Command command = item.getCommand();
- ExecuteCommandOptions provider = languageServerWrapper.getServerCapabilities().getExecuteCommandProvider();
+ ServerCapabilities serverCapabilities = languageServerWrapper.getServerCapabilities();
+ ExecuteCommandOptions provider = serverCapabilities == null ? null : serverCapabilities.getExecuteCommandProvider();
if (provider != null && provider.getCommands().contains(command.getCommand())) {
languageServerWrapper.execute(ls -> ls.getWorkspaceService()
.executeCommand(new ExecuteCommandParams(command.getCommand(), command.getArguments())));
@@ -583,7 +592,7 @@ private String adjustIndentation(IDocument document, String insertText, int inse
return insertText.replace("\n", whitespacesBeforeInsertion); //$NON-NLS-1$
}
- private int computeNewOffset(List additionalTextEdits, int insertionOffset, IDocument doc) {
+ private int computeNewOffset(@Nullable List additionalTextEdits, int insertionOffset, IDocument doc) {
if (additionalTextEdits != null && !additionalTextEdits.isEmpty()) {
int adjustment = 0;
for (TextEdit edit : additionalTextEdits) {
@@ -609,13 +618,23 @@ private int computeNewOffset(List additionalTextEdits, int insertionOf
private String getVariableValue(String variableName) {
return switch (variableName) {
case TM_FILENAME_BASE -> {
- IPath pathBase = LSPEclipseUtils.toPath(document).removeFileExtension();
- String fileName = pathBase.lastSegment();
+ IPath path = LSPEclipseUtils.toPath(document);
+ String fileName = path == null ? null : path.removeFileExtension().lastSegment();
+ yield fileName != null ? fileName : ""; //$NON-NLS-1$
+ }
+ case TM_FILENAME -> {
+ IPath path = LSPEclipseUtils.toPath(document);
+ String fileName = path == null ? null : path.lastSegment();
yield fileName != null ? fileName : ""; //$NON-NLS-1$
}
- case TM_FILENAME -> LSPEclipseUtils.toPath(document).lastSegment();
- case TM_FILEPATH -> getAbsoluteLocation(LSPEclipseUtils.toPath(document));
- case TM_DIRECTORY -> getAbsoluteLocation(LSPEclipseUtils.toPath(document).removeLastSegments(1));
+ case TM_FILEPATH -> {
+ IPath path = LSPEclipseUtils.toPath(document);
+ yield path == null ? "" : getAbsoluteLocation(path); //$NON-NLS-1$
+ }
+ case TM_DIRECTORY -> {
+ IPath path = LSPEclipseUtils.toPath(document);
+ yield path == null ? "" : getAbsoluteLocation(path.removeLastSegments(1)); //$NON-NLS-1$
+ }
case TM_LINE_INDEX -> {
try {
yield Integer.toString(getTextEditRange().getStart().getLine()); // TODO probably wrong, should use viewer state
@@ -645,6 +664,7 @@ private String getVariableValue(String variableName) {
}
case TM_SELECTED_TEXT -> {
try {
+ final var viewer = castNonNull(this.viewer);
String selectedText = document.get(viewer.getSelectedRange().x, viewer.getSelectedRange().y);
yield selectedText;
} catch (BadLocationException e) {
@@ -654,6 +674,7 @@ private String getVariableValue(String variableName) {
}
case TM_CURRENT_WORD -> {
try {
+ final var viewer = castNonNull(this.viewer);
String selectedText = document.get(viewer.getSelectedRange().x, viewer.getSelectedRange().y);
int beforeSelection = viewer.getSelectedRange().x - 1;
while (beforeSelection >= 0 && Character.isUnicodeIdentifierPart(document.getChar(beforeSelection))) {
@@ -718,10 +739,12 @@ protected String getInsertText() {
}
@Override
- public Point getSelection(IDocument document) {
+ public @Nullable Point getSelection(IDocument document) {
+ final var firstPosition = this.firstPosition;
if (firstPosition != null) {
return new Point(firstPosition.getOffset(), firstPosition.getLength());
}
+ final var selection = this.selection;
if (selection == null) {
return null;
}
@@ -729,28 +752,28 @@ public Point getSelection(IDocument document) {
}
@Override
- public String getAdditionalProposalInfo() {
+ public @Nullable String getAdditionalProposalInfo() {
return getAdditionalProposalInfo(new NullProgressMonitor());
}
@Override
- public Image getImage() {
+ public @Nullable Image getImage() {
return LSPImages.imageFromCompletionItem(item);
}
@Override
- public IContextInformation getContextInformation() {
+ public @Nullable IContextInformation getContextInformation() {
return this;
}
@Override
public String getContextDisplayString() {
- return getAdditionalProposalInfo();
+ return Objects.toString(getAdditionalProposalInfo());
}
@Override
public String getInformationDisplayString() {
- return getAdditionalProposalInfo();
+ return Objects.toString(getAdditionalProposalInfo());
}
public String getSortText() {
@@ -782,7 +805,7 @@ public void unselected(ITextViewer viewer) {
}
@Override
- public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ public boolean validate(IDocument document, int offset, @Nullable DocumentEvent event) {
if (item.getLabel() == null || item.getLabel().isEmpty()) {
return false;
}
@@ -805,7 +828,10 @@ public boolean validate(IDocument document, int offset, DocumentEvent event) {
@Override
public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
this.viewer = viewer;
- apply(viewer.getDocument(), trigger, stateMask, offset);
+ final var doc = viewer.getDocument();
+ if (doc != null) {
+ apply(doc, trigger, stateMask, offset);
+ }
}
@Override
@@ -819,7 +845,7 @@ public void apply(IDocument document) {
}
@Override
- public char[] getTriggerCharacters() {
+ public char @Nullable [] getTriggerCharacters() {
return null;
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSContentAssistProcessor.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSContentAssistProcessor.java
index 764899165..558e9ba15 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSContentAssistProcessor.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/LSContentAssistProcessor.java
@@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.completion;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;
+
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -30,7 +32,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
@@ -68,18 +70,21 @@ public class LSContentAssistProcessor implements IContentAssistProcessor {
private static final long TRIGGERS_TIMEOUT = 50;
private static final long CONTEXT_INFORMATION_TIMEOUT = 1000;
- private IDocument currentDocument;
- private String errorMessage;
+ private @Nullable IDocument currentDocument;
+ private @Nullable String errorMessage;
private final boolean errorAsCompletionItem;
- private CompletableFuture<@NonNull List<@NonNull Void>> completionLanguageServersFuture;
+ private @Nullable CompletableFuture> completionLanguageServersFuture;
private final Object completionTriggerCharsSemaphore = new Object();
private char[] completionTriggerChars = new char[0];
- private CompletableFuture<@NonNull List<@NonNull Void>> contextInformationLanguageServersFuture;
+ private @Nullable CompletableFuture> contextInformationLanguageServersFuture;
private final Object contextTriggerCharsSemaphore = new Object();
private char[] contextTriggerChars = new char[0];
private final boolean incompleteAsCompletionItem;
- // The cancellation support used to cancel previous LSP requests 'textDocument/completion' when completion is retriggered
+ /**
+ * The cancellation support used to cancel previous LSP requests
+ * 'textDocument/completion' when completion is retriggered
+ */
private CancellationSupport cancellationSupport;
public LSContentAssistProcessor() {
@@ -99,8 +104,11 @@ public LSContentAssistProcessor(boolean errorAsCompletionItem, boolean incomplet
private final Comparator proposalComparator = new LSCompletionProposalComparator();
@Override
- public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ public ICompletionProposal @Nullable [] computeCompletionProposals(ITextViewer viewer, int offset) {
IDocument document = viewer.getDocument();
+ if (document == null) {
+ return new LSCompletionProposal[0];
+ }
URI uri = LSPEclipseUtils.toUri(document);
if (uri == null) {
@@ -121,35 +129,42 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int
List proposals = Collections.synchronizedList(new ArrayList<>());
AtomicBoolean anyIncomplete = new AtomicBoolean(false);
try {
- // Cancel the previous LSP requests 'textDocument/completions' and completionLanguageServersFuture
+ // Cancel the previous LSP requests 'textDocument/completions' and
+ // completionLanguageServersFuture
this.cancellationSupport.cancel();
// Initialize a new cancel support to register:
// - LSP requests 'textDocument/completions'
// - completionLanguageServersFuture
CancellationSupport cancellationSupport = new CancellationSupport();
- this.completionLanguageServersFuture = LanguageServers.forDocument(document)
- .withFilter(capabilities -> capabilities.getCompletionProvider() != null) //
+ final var completionLanguageServersFuture = this.completionLanguageServersFuture = LanguageServers
+ .forDocument(document).withFilter(capabilities -> capabilities.getCompletionProvider() != null) //
.collectAll((w, ls) -> cancellationSupport.execute(ls.getTextDocumentService().completion(param)) //
.thenAccept(completion -> {
- boolean isIncomplete = completion != null && completion.isRight() ? completion.getRight().isIncomplete() : false;
- proposals.addAll(toProposals(document, offset, completion, w, cancellationSupport, isIncomplete));
+ boolean isIncomplete = completion != null && completion.isRight()
+ ? completion.getRight().isIncomplete()
+ : false;
+ proposals.addAll(toProposals(document, offset, completion, w, cancellationSupport,
+ isIncomplete));
if (isIncomplete) {
anyIncomplete.set(true);
}
}).exceptionally(t -> {
if (!CancellationUtil.isRequestCancelledException(t)) {
- LanguageServerPlugin.logError("'%s' LS failed to compute completion items.".formatted(w.serverDefinition.label), t); //$NON-NLS-1$
+ LanguageServerPlugin.logError("'%s' LS failed to compute completion items." //$NON-NLS-1$
+ .formatted(w.serverDefinition.label), t);
}
return null;
}));
cancellationSupport.execute(completionLanguageServersFuture);
this.cancellationSupport = cancellationSupport;
- // Wait for the result of all LSP requests 'textDocument/completions', this future will be canceled with the next completion
- this.completionLanguageServersFuture.get();
+ // Wait for the result of all LSP requests 'textDocument/completions', this
+ // future will be canceled with the next completion
+ completionLanguageServersFuture.get();
} catch (ExecutionException e) {
- // Ideally exceptions from each LS are handled above and we shouldn't be getting into this block
+ // Ideally exceptions from each LS are handled above and we shouldn't be getting
+ // into this block
this.errorMessage = createErrorMessage(offset, e);
return createErrorProposal(offset, e);
} catch (InterruptedException e) {
@@ -172,8 +187,10 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int
Arrays.sort(completeProposals, proposalComparator);
ICompletionProposal[] incompleteProposal = createIncompleProposal(offset, anyIncomplete.get());
if (incompleteProposal.length > 0) {
- ICompletionProposal[] incompleteProposals = Arrays.copyOf(completeProposals, completeProposals.length + incompleteProposal.length, ICompletionProposal[].class);
- System.arraycopy(incompleteProposal, 0, incompleteProposals, completeProposals.length, incompleteProposal.length);
+ ICompletionProposal[] incompleteProposals = Arrays.copyOf(completeProposals,
+ completeProposals.length + incompleteProposal.length, ICompletionProposal[].class);
+ System.arraycopy(incompleteProposal, 0, incompleteProposals, completeProposals.length,
+ incompleteProposal.length);
return incompleteProposals;
}
return completeProposals;
@@ -181,9 +198,9 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int
private ICompletionProposal[] createErrorProposal(int offset, Exception ex) {
if (errorAsCompletionItem) {
- return new ICompletionProposal[] {new CompletionProposal("", offset, 0, 0, null, Messages.completionError, null, ex.getMessage())}; //$NON-NLS-1$
- }
- else {
+ return new ICompletionProposal[] {
+ new CompletionProposal("", offset, 0, 0, null, Messages.completionError, null, ex.getMessage()) }; //$NON-NLS-1$
+ } else {
return new ICompletionProposal[0];
}
}
@@ -194,12 +211,13 @@ private String createErrorMessage(int offset, Exception ex) {
private ICompletionProposal[] createIncompleProposal(int offset, boolean incomplete) {
if (incompleteAsCompletionItem && incomplete) {
- return new ICompletionProposal[] {new CompletionProposal("", offset, 0, 0, null, Messages.completionIncomplete, null, Messages.continueIncomplete)}; //$NON-NLS-1$
+ return new ICompletionProposal[] { new CompletionProposal("", offset, 0, 0, null, //$NON-NLS-1$
+ Messages.completionIncomplete, null, Messages.continueIncomplete) };
}
return new ICompletionProposal[0];
}
- private void initiateLanguageServers(@NonNull IDocument document) {
+ private void initiateLanguageServers(IDocument document) {
if (currentDocument != document) {
this.currentDocument = document;
if (this.completionLanguageServersFuture != null) {
@@ -220,8 +238,9 @@ private void initiateLanguageServers(@NonNull IDocument document) {
this.contextTriggerChars = new char[0];
this.completionLanguageServersFuture = LanguageServers.forDocument(document)
- .withFilter(capabilities -> capabilities.getCompletionProvider() != null).collectAll((w, ls) -> {
- CompletionOptions provider = w.getServerCapabilities().getCompletionProvider();
+ .withFilter(capabilities -> capabilities.getCompletionProvider() != null) //
+ .collectAll((w, ls) -> {
+ CompletionOptions provider = castNonNull(w.getServerCapabilities()).getCompletionProvider();
synchronized (completionTriggerCharsSemaphore) {
completionTriggerChars = mergeTriggers(completionTriggerChars,
provider.getTriggerCharacters());
@@ -229,8 +248,9 @@ private void initiateLanguageServers(@NonNull IDocument document) {
return CompletableFuture.completedFuture(null);
});
this.contextInformationLanguageServersFuture = LanguageServers.forDocument(document)
- .withFilter(capabilities -> capabilities.getSignatureHelpProvider() != null).collectAll((w, ls) -> {
- SignatureHelpOptions provider = w.getServerCapabilities().getSignatureHelpProvider();
+ .withFilter(capabilities -> capabilities.getSignatureHelpProvider() != null) //
+ .collectAll((w, ls) -> {
+ SignatureHelpOptions provider = castNonNull(w.getServerCapabilities()).getSignatureHelpProvider();
synchronized (contextTriggerCharsSemaphore) {
contextTriggerChars = mergeTriggers(contextTriggerChars, provider.getTriggerCharacters());
}
@@ -242,38 +262,38 @@ private void initiateLanguageServers(@NonNull IDocument document) {
private void initiateLanguageServers() {
ITextEditor textEditor = UI.getActiveTextEditor();
- if(textEditor != null) {
+ if (textEditor != null) {
IDocument document = LSPEclipseUtils.getDocument(textEditor);
if (document != null) {
initiateLanguageServers(document);
}
}
}
- private static List toProposals(IDocument document,
- int offset, Either, CompletionList> completionList, LanguageServerWrapper languageServerWrapper, CancelChecker cancelChecker, boolean isIncomplete) {
+
+ private static List toProposals(IDocument document, int offset,
+ @Nullable Either, CompletionList> completionList,
+ LanguageServerWrapper languageServerWrapper, CancelChecker cancelChecker, boolean isIncomplete) {
if (completionList == null) {
return Collections.emptyList();
}
- //Stop the compute of ICompletionProposal if the completion has been cancelled
+ // Stop the compute of ICompletionProposal if the completion has been cancelled
cancelChecker.checkCanceled();
CompletionItemDefaults defaults = completionList.map(o -> null, CompletionList::getItemDefaults);
- List items = completionList.isLeft() ? completionList.getLeft() : completionList.getRight().getItems();
+ List items = completionList.isLeft() ? completionList.getLeft()
+ : completionList.getRight().getItems();
return items.stream() //
- .filter(Objects::nonNull)
- .map(item -> new LSCompletionProposal(document, offset, item, defaults,
+ .filter(Objects::nonNull).map(item -> new LSCompletionProposal(document, offset, item, defaults,
languageServerWrapper, isIncomplete))
.filter(proposal -> {
- //Stop the compute of ICompletionProposal if the completion has been cancelled
+ // Stop the compute of ICompletionProposal if the completion has been cancelled
cancelChecker.checkCanceled();
return true;
- })
- .filter(proposal -> proposal.validate(document, offset, null))
- .map(ICompletionProposal.class::cast)
+ }).filter(proposal -> proposal.validate(document, offset, null)).map(ICompletionProposal.class::cast)
.toList();
}
@Override
- public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
+ public IContextInformation @Nullable [] computeContextInformation(ITextViewer viewer, int offset) {
IDocument document = viewer.getDocument();
if (document == null) {
return new IContextInformation[] { /* TODO? show error in context information */ };
@@ -289,17 +309,17 @@ public IContextInformation[] computeContextInformation(ITextViewer viewer, int o
List contextInformations = Collections.synchronizedList(new ArrayList<>());
try {
this.contextInformationLanguageServersFuture = LanguageServers.forDocument(document)
- .withFilter(capabilities -> capabilities.getSignatureHelpProvider() != null).collectAll(
- ls -> ls.getTextDocumentService().signatureHelp(param).thenAccept(signatureHelp -> {
- if (signatureHelp != null) {
- signatureHelp.getSignatures().stream()
- .map(LSContentAssistProcessor::toContextInformation)
- .forEach(contextInformations::add);
- }
- }));
+ .withFilter(capabilities -> capabilities.getSignatureHelpProvider() != null)
+ .collectAll(ls -> ls.getTextDocumentService().signatureHelp(param).thenAccept(signatureHelp -> {
+ if (signatureHelp != null) {
+ signatureHelp.getSignatures().stream().map(LSContentAssistProcessor::toContextInformation)
+ .forEach(contextInformations::add);
+ }
+ }));
this.contextInformationLanguageServersFuture.get(CONTEXT_INFORMATION_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (ResponseErrorException | ExecutionException e) {
- if (!CancellationUtil.isRequestCancelledException(e)) { // do not report error if the server has cancelled the request
+ if (!CancellationUtil.isRequestCancelledException(e)) { // do not report error if the server has cancelled
+ // the request
LanguageServerPlugin.logError(e);
}
return new IContextInformation[] { /* TODO? show error in context information */ };
@@ -308,7 +328,8 @@ public IContextInformation[] computeContextInformation(ITextViewer viewer, int o
Thread.currentThread().interrupt();
return new IContextInformation[] { /* TODO? show error in context information */ };
} catch (TimeoutException e) {
- LanguageServerPlugin.logWarning("Could not compute context information due to timeout after " + CONTEXT_INFORMATION_TIMEOUT + " milliseconds", e); //$NON-NLS-1$//$NON-NLS-2$
+ LanguageServerPlugin.logWarning("Could not compute context information due to timeout after " //$NON-NLS-1$
+ + CONTEXT_INFORMATION_TIMEOUT + " milliseconds", e); //$NON-NLS-1$
return new IContextInformation[] { /* TODO? show error in context information */ };
}
return contextInformations.toArray(IContextInformation[]::new);
@@ -317,14 +338,14 @@ public IContextInformation[] computeContextInformation(ITextViewer viewer, int o
private static IContextInformation toContextInformation(SignatureInformation information) {
final var signature = new StringBuilder(information.getLabel());
String docString = LSPEclipseUtils.getDocString(information.getDocumentation());
- if (docString!=null && !docString.isEmpty()) {
+ if (docString != null && !docString.isEmpty()) {
signature.append('\n').append(docString);
}
return new ContextInformation(information.getLabel(), signature.toString());
}
- private void getFuture(CompletableFuture<@NonNull List<@NonNull Void>> future) {
- if(future == null) {
+ private void getFuture(@Nullable CompletableFuture> future) {
+ if (future == null) {
return;
}
@@ -334,15 +355,18 @@ private void getFuture(CompletableFuture<@NonNull List<@NonNull Void>> future) {
LanguageServerPlugin.logError(e);
Thread.currentThread().interrupt();
} catch (TimeoutException e) {
- LanguageServerPlugin.logWarning("Could not get trigger characters due to timeout after " + TRIGGERS_TIMEOUT + " milliseconds", e); //$NON-NLS-1$//$NON-NLS-2$
+ LanguageServerPlugin.logWarning(
+ "Could not get trigger characters due to timeout after " + TRIGGERS_TIMEOUT + " milliseconds", e); //$NON-NLS-1$//$NON-NLS-2$
} catch (OperationCanceledException | ResponseErrorException | ExecutionException | CancellationException e) {
- if (!CancellationUtil.isRequestCancelledException(e)) { // do not report error if the server has cancelled the request
+ if (!CancellationUtil.isRequestCancelledException(e)) { // do not report error if the server has cancelled
+ // the request
LanguageServerPlugin.logError(e);
}
}
}
- private static char[] mergeTriggers(char[] initialArray, Collection additionalTriggers) {
+ private static char[] mergeTriggers(char @Nullable [] initialArray,
+ @Nullable Collection additionalTriggers) {
if (initialArray == null) {
initialArray = new char[0];
}
@@ -353,8 +377,8 @@ private static char[] mergeTriggers(char[] initialArray, Collection addi
for (char c : initialArray) {
triggers.add(c);
}
- additionalTriggers.stream().filter(s -> !Strings.isNullOrEmpty(s))
- .map(triggerChar -> triggerChar.charAt(0)).forEach(triggers::add);
+ additionalTriggers.stream().filter(s -> !Strings.isNullOrEmpty(s)).map(triggerChar -> triggerChar.charAt(0))
+ .forEach(triggers::add);
char[] res = new char[triggers.size()];
int i = 0;
for (Character c : triggers) {
@@ -365,26 +389,26 @@ private static char[] mergeTriggers(char[] initialArray, Collection addi
}
@Override
- public char[] getCompletionProposalAutoActivationCharacters() {
+ public char @Nullable [] getCompletionProposalAutoActivationCharacters() {
initiateLanguageServers();
getFuture(completionLanguageServersFuture);
return completionTriggerChars;
}
@Override
- public char[] getContextInformationAutoActivationCharacters() {
+ public char @Nullable [] getContextInformationAutoActivationCharacters() {
initiateLanguageServers();
getFuture(contextInformationLanguageServersFuture);
return contextTriggerChars;
}
@Override
- public String getErrorMessage() {
+ public @Nullable String getErrorMessage() {
return this.errorMessage;
}
@Override
- public IContextInformationValidator getContextInformationValidator() {
+ public @Nullable IContextInformationValidator getContextInformationValidator() {
return new ContextInformationValidator(this);
}
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/package-info.java
new file mode 100644
index 000000000..96e2a34b1
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/completion/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.completion;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/LSBasedHyperlink.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/LSBasedHyperlink.java
index 90743a3de..e97a7586a 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/LSBasedHyperlink.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/LSBasedHyperlink.java
@@ -22,7 +22,6 @@
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.lsp4e.LSPEclipseUtils;
@@ -46,11 +45,11 @@ public LSBasedHyperlink(Either location, IRegion highlig
this.locationType = locationType;
}
- public LSBasedHyperlink(@NonNull Location location, IRegion linkRegion, String locationType) {
+ public LSBasedHyperlink(Location location, IRegion linkRegion, String locationType) {
this(Either.forLeft(location), linkRegion, locationType);
}
- public LSBasedHyperlink(@NonNull LocationLink locationLink, IRegion linkRegion, String locationType) {
+ public LSBasedHyperlink(LocationLink locationLink, IRegion linkRegion, String locationType) {
this(Either.forRight(locationLink), linkRegion, locationType);
}
@@ -70,8 +69,6 @@ public String getHyperlinkText() {
}
/**
- *
- * @return
* @noreference test only
*/
public Either getLocation() {
@@ -88,17 +85,15 @@ public void open() {
}
private String getLabel() {
- if (this.location != null) {
- String uri = this.location.isLeft() ? this.location.getLeft().getUri() : this.location.getRight().getTargetUri();
- if (uri != null) {
- if (uri.startsWith(LSPEclipseUtils.FILE_URI) && uri.length() > LSPEclipseUtils.FILE_URI.length()) {
- return getFileBasedLabel(uri);
- }
- else if (uri.startsWith(LSPEclipseUtils.INTRO_URL)) {
- return getIntroUrlBasedLabel(uri);
- }
- return getGenericUriBasedLabel(uri);
+ String uri = this.location.isLeft() ? this.location.getLeft().getUri() : this.location.getRight().getTargetUri();
+ if (uri != null) {
+ if (uri.startsWith(LSPEclipseUtils.FILE_URI) && uri.length() > LSPEclipseUtils.FILE_URI.length()) {
+ return getFileBasedLabel(uri);
}
+ else if (uri.startsWith(LSPEclipseUtils.INTRO_URL)) {
+ return getIntroUrlBasedLabel(uri);
+ }
+ return getGenericUriBasedLabel(uri);
}
return locationType;
@@ -113,8 +108,7 @@ private String getIntroUrlBasedLabel(String uri) {
return locationType + DASH_SEPARATOR + label;
}
}
- }
- catch (Exception e) {
+ } catch (Exception e) {
LanguageServerPlugin.logError(e.getMessage(), e);
}
@@ -129,7 +123,7 @@ private String getFileBasedLabel(String uriStr) {
URI uri = URI.create(uriStr);
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IFile[] files = workspaceRoot.findFilesForLocationURI(uri);
- if (files != null && files.length == 1 && files[0].getProject() != null) {
+ if (files.length == 1 && files[0].getProject() != null) {
IFile file = files[0];
IPath containerPath = file.getParent().getProjectRelativePath();
return locationType + DASH_SEPARATOR + file.getName() + DASH_SEPARATOR + file.getProject().getName()
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
index 000631143..f20d1d66f 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/OpenDeclarationHyperlinkDetector.java
@@ -22,6 +22,8 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
@@ -44,7 +46,7 @@
public class OpenDeclarationHyperlinkDetector extends AbstractHyperlinkDetector {
@Override
- public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
+ public IHyperlink @Nullable [] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
final IDocument document = textViewer.getDocument();
if (document == null) {
return null;
@@ -97,7 +99,7 @@ public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boo
* the LSP locations
*/
private static Collection toHyperlinks(IDocument document, IRegion region,
- String locationType, Either, List extends LocationLink>> locations) {
+ String locationType, @NonNullByDefault({}) Either, List extends LocationLink>> locations) {
if (locations == null) {
return Collections.emptyList();
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/package-info.java
new file mode 100644
index 000000000..76eb1eb96
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/declaration/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.declaration;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/DiagnosticAnnotation.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/DiagnosticAnnotation.java
index 687a8aebe..1f5fa337a 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/DiagnosticAnnotation.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/DiagnosticAnnotation.java
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.lsp4e.operations.diagnostics;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.lsp4j.Diagnostic;
@@ -33,7 +34,7 @@ public String getType() {
}
@Override
- public void setType(String type) {
+ public void setType(@Nullable String type) {
throw new UnsupportedOperationException();
}
@@ -43,7 +44,7 @@ public String getText() {
}
@Override
- public void setText(String text) {
+ public void setText(@Nullable String text) {
throw new UnsupportedOperationException();
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
index 062d1aab9..2f12e9728 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
@@ -34,7 +34,6 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
-import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
@@ -57,17 +56,17 @@ public class LSPDiagnosticsToMarkers implements Consumer markerAttributeComputer;
- public LSPDiagnosticsToMarkers(@NonNull String serverId, @Nullable String markerType, @Nullable IMarkerAttributeComputer markerAttributeComputer) {
+ public LSPDiagnosticsToMarkers(String serverId, @Nullable String markerType, @Nullable IMarkerAttributeComputer markerAttributeComputer) {
this.languageServerId = serverId;
this.markerType = markerType != null ? markerType : LS_DIAGNOSTIC_MARKER_TYPE;
this.markerAttributeComputer = Optional.ofNullable(markerAttributeComputer);
}
- public LSPDiagnosticsToMarkers(@NonNull String serverId) {
+ public LSPDiagnosticsToMarkers(String serverId) {
this(serverId, null, null);
}
@@ -79,7 +78,7 @@ public LSPDiagnosticsToMarkers(@NonNull String serverId) {
* @deprecated
*/
@Deprecated
- public LSPDiagnosticsToMarkers(IProject project, @NonNull String serverId) {
+ public LSPDiagnosticsToMarkers(IProject project, String serverId) {
this(serverId);
}
@@ -105,7 +104,7 @@ public void accept(PublishDiagnosticsParams diagnostics) {
}
}
- private void updateEditorAnnotations(@NonNull ISourceViewer sourceViewer, PublishDiagnosticsParams diagnostics) {
+ private void updateEditorAnnotations(ISourceViewer sourceViewer, PublishDiagnosticsParams diagnostics) {
IAnnotationModel annotationModel = sourceViewer.getAnnotationModel();
if (annotationModel == null) {
return;
@@ -120,9 +119,12 @@ private void updateEditorAnnotations(@NonNull ISourceViewer sourceViewer, Publis
final var toAdd = new HashMap(diagnostics.getDiagnostics().size(), 1.f);
diagnostics.getDiagnostics().forEach(diagnostic -> {
try {
- int startOffset = LSPEclipseUtils.toOffset(diagnostic.getRange().getStart(), sourceViewer.getDocument());
- int endOffset = LSPEclipseUtils.toOffset(diagnostic.getRange().getEnd(), sourceViewer.getDocument());
- toAdd.put(new DiagnosticAnnotation(diagnostic), new Position(startOffset, endOffset - startOffset));
+ final var doc = sourceViewer.getDocument();
+ if (doc != null) {
+ int startOffset = LSPEclipseUtils.toOffset(diagnostic.getRange().getStart(), doc);
+ int endOffset = LSPEclipseUtils.toOffset(diagnostic.getRange().getEnd(), doc);
+ toAdd.put(new DiagnosticAnnotation(diagnostic), new Position(startOffset, endOffset - startOffset));
+ }
} catch (BadLocationException ex) {
LanguageServerPlugin.logError(ex);
}
@@ -134,12 +136,12 @@ private void updateEditorAnnotations(@NonNull ISourceViewer sourceViewer, Publis
private WorkspaceJob updateMarkers(PublishDiagnosticsParams diagnostics, IResource resource) {
WorkspaceJob job = new WorkspaceJob("Update markers from diagnostics") { //$NON-NLS-1$
@Override
- public boolean belongsTo(Object family) {
+ public boolean belongsTo(@Nullable Object family) {
return LanguageServerPlugin.FAMILY_UPDATE_MARKERS == family;
}
@Override
- public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ public IStatus runInWorkspace(@Nullable IProgressMonitor monitor) throws CoreException {
if (!resource.exists()) {
return Status.OK_STATUS;
}
@@ -203,7 +205,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
return job;
}
- protected void updateMarker(@NonNull Map targetAttributes, @NonNull IMarker marker) {
+ protected void updateMarker(Map targetAttributes, IMarker marker) {
try {
if (!targetAttributes.equals(marker.getAttributes())) {
marker.setAttributes(targetAttributes);
@@ -213,7 +215,7 @@ protected void updateMarker(@NonNull Map targetAttributes, @NonN
}
}
- private IMarker getExistingMarkerFor(IDocument document, Diagnostic diagnostic, Set remainingMarkers) {
+ private @Nullable IMarker getExistingMarkerFor(@Nullable IDocument document, Diagnostic diagnostic, Set remainingMarkers) {
if (document == null) {
return null;
}
@@ -236,14 +238,11 @@ private IMarker getExistingMarkerFor(IDocument document, Diagnostic diagnostic,
return null;
}
- private @NonNull Map computeMarkerAttributes(@Nullable IDocument document,
- @NonNull Diagnostic diagnostic, @NonNull IResource resource) {
+ private Map computeMarkerAttributes(@Nullable IDocument document,
+ Diagnostic diagnostic, IResource resource) {
Either code = diagnostic.getCode();
if (code != null && code.isLeft()) {
- String left = code.getLeft();
- if (left != null) {
- diagnostic.setCode(Either.forLeft(left.intern()));
- }
+ diagnostic.setCode(Either.forLeft(code.getLeft().intern()));
}
String source = diagnostic.getSource();
if (source != null) {
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/package-info.java
new file mode 100644
index 000000000..44c072a3c
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.diagnostics;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/DocumentLinkDetector.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/DocumentLinkDetector.java
index cdfc87aed..a3c677b20 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/DocumentLinkDetector.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/DocumentLinkDetector.java
@@ -19,6 +19,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
@@ -30,7 +31,6 @@
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServers;
-import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.DocumentLink;
import org.eclipse.lsp4j.DocumentLinkParams;
@@ -63,13 +63,13 @@ public String getHyperlinkText() {
@Override
public void open() {
- LSPEclipseUtils.open(uri, UI.getActivePage(), null, true);
+ LSPEclipseUtils.open(uri, null, true);
}
}
@Override
- public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
+ public IHyperlink @Nullable [] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
final IDocument document = textViewer.getDocument();
if (document == null) {
return null;
@@ -106,7 +106,7 @@ public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boo
}
}
- private DocumentHyperlink toHyperlink(IRegion region, final IDocument document, DocumentLink link) {
+ private @Nullable DocumentHyperlink toHyperlink(IRegion region, final IDocument document, DocumentLink link) {
DocumentHyperlink jfaceLink = null;
try {
int start = LSPEclipseUtils.toOffset(link.getRange().getStart(), document);
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/LSPDocumentLinkPresentationReconcilingStrategy.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/LSPDocumentLinkPresentationReconcilingStrategy.java
index b9c449830..2bc8359e3 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/LSPDocumentLinkPresentationReconcilingStrategy.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/LSPDocumentLinkPresentationReconcilingStrategy.java
@@ -44,11 +44,11 @@ public class LSPDocumentLinkPresentationReconcilingStrategy
implements IReconcilingStrategy, IReconcilingStrategyExtension, ITextViewerLifecycle {
/** The target viewer. */
- private ITextViewer viewer;
+ private @Nullable ITextViewer viewer;
- private CompletableFuture request;
+ private @Nullable CompletableFuture request;
- private IDocument document;
+ private @Nullable IDocument document;
@Override
public void install(@Nullable ITextViewer viewer) {
@@ -87,8 +87,10 @@ private void underline() {
}
}
- private void underline(List links) {
- if (document == null || links == null) {
+ private void underline(@Nullable List links) {
+ final var viewer = this.viewer;
+ final var document = this.document;
+ if (document == null || links == null || viewer == null) {
return;
}
for (DocumentLink link : links) {
@@ -147,12 +149,12 @@ private void cancel() {
}
@Override
- public void setDocument(IDocument document) {
+ public void setDocument(@Nullable IDocument document) {
this.document = document;
}
@Override
- public void setProgressMonitor(IProgressMonitor monitor) {
+ public void setProgressMonitor(@Nullable IProgressMonitor monitor) {
// Do nothing
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/package-info.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/package-info.java
new file mode 100644
index 000000000..e6d7f7652
--- /dev/null
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/documentLink/package-info.java
@@ -0,0 +1,6 @@
+@NonNullByDefault({ ARRAY_CONTENTS, PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT })
+package org.eclipse.lsp4e.operations.documentLink;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/folding/LSPFoldingReconcilingStrategy.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/folding/LSPFoldingReconcilingStrategy.java
index 76860452a..484071b61 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/folding/LSPFoldingReconcilingStrategy.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/folding/LSPFoldingReconcilingStrategy.java
@@ -10,6 +10,8 @@
*/
package org.eclipse.lsp4e.operations.folding;
+import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;
+
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
@@ -21,7 +23,7 @@
import java.util.concurrent.CompletableFuture;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
@@ -58,10 +60,10 @@
public class LSPFoldingReconcilingStrategy
implements IReconcilingStrategy, IReconcilingStrategyExtension, IProjectionListener, ITextViewerLifecycle {
- private IDocument document;
- private ProjectionAnnotationModel projectionAnnotationModel;
- private ProjectionViewer viewer;
- private @NonNull List>> requests = List.of();
+ private @Nullable IDocument document;
+ private @Nullable ProjectionAnnotationModel projectionAnnotationModel;
+ private @Nullable ProjectionViewer viewer;
+ private List>> requests = List.of();
private volatile long timestamp = 0;
private final boolean collapseImports;
@@ -127,13 +129,13 @@ public void markCollapsed() {
}
@Override
- public void reconcile(IRegion subRegion) {
- IDocument theDocument = document;
- if (projectionAnnotationModel == null || theDocument == null) {
+ public void reconcile(@Nullable IRegion subRegion) {
+ final var document = this.document;
+ if (projectionAnnotationModel == null || document == null) {
return;
}
- URI uri = LSPEclipseUtils.toUri(theDocument);
+ URI uri = LSPEclipseUtils.toUri(document);
if (uri == null) {
return;
}
@@ -141,12 +143,13 @@ public void reconcile(IRegion subRegion) {
final var params = new FoldingRangeRequestParams(identifier);
// cancel previous requests
requests.forEach(request -> request.cancel(true));
- requests = LanguageServers.forDocument(theDocument).withCapability(ServerCapabilities::getFoldingRangeProvider)
+ requests = LanguageServers.forDocument(document)
+ .withCapability(ServerCapabilities::getFoldingRangeProvider)
.computeAll(server -> server.getTextDocumentService().foldingRange(params));
requests.forEach(ranges -> ranges.thenAccept(this::applyFolding));
}
- private void applyFolding(List ranges) {
+ private void applyFolding(@Nullable List ranges) {
// these are what are passed off to the annotation model to
// actually create and maintain the annotations
final var deletions = new ArrayList();
@@ -188,8 +191,8 @@ public void install(ITextViewer viewer) {
}
if (viewer instanceof ProjectionViewer projViewer) {
this.viewer = projViewer;
- this.viewer.addProjectionListener(this);
- this.projectionAnnotationModel = this.viewer.getProjectionAnnotationModel();
+ projViewer.addProjectionListener(this);
+ this.projectionAnnotationModel = projViewer.getProjectionAnnotationModel();
}
}
@@ -204,7 +207,7 @@ public void uninstall() {
}
@Override
- public void setDocument(IDocument document) {
+ public void setDocument(@Nullable IDocument document) {
this.document = document;
}
@@ -237,9 +240,10 @@ public void projectionEnabled() {
* the end line number
* @throws BadLocationException
*/
- private void updateAnnotation(List deletions,
- List existing, Map additions, int line, Integer endLineNumber, boolean collapsedByDefault)
+ private void updateAnnotation(List deletions, List existing,
+ Map additions, int line, Integer endLineNumber, boolean collapsedByDefault)
throws BadLocationException {
+ final var document = castNonNull(this.document);
int startOffset = document.getLineOffset(line);
int endOffset = document.getLineOffset(endLineNumber) + document.getLineLength(endLineNumber);
final var newPos = new Position(startOffset, endOffset - startOffset);
@@ -263,7 +267,7 @@ private void updateAnnotation(List deletions,
* @param deletions
* the list of annotations to be deleted
*/
- protected void updateAnnotations(Annotation existingAnnotation, Position newPos, List deletions) {
+ protected void updateAnnotations(Annotation existingAnnotation, @Nullable Position newPos, List deletions) {
if (existingAnnotation instanceof FoldingAnnotation foldingAnnotation) {
// if a new position can be calculated then update the position of
// the annotation,
@@ -296,16 +300,18 @@ protected void updateAnnotations(Annotation existingAnnotation, Position newPos,
*/
protected void markInvalidAnnotationsForDeletion(List deletions,
List