Skip to content

Commit

Permalink
refact: add various ArrayUtil methods and use where applicable
Browse files Browse the repository at this point in the history
...with the goal to increase readability and improve performance
  • Loading branch information
sebthom committed Aug 25, 2024
1 parent ea6a9ae commit e0d12cc
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.eclipse.lsp4e.debug.console.DSPProcess;
import org.eclipse.lsp4e.debug.console.DSPStreamsProxy;
import org.eclipse.lsp4e.debug.debugmodel.TransportStreams.DefaultTransportStreams;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4j.debug.BreakpointEventArguments;
import org.eclipse.lsp4j.debug.Capabilities;
import org.eclipse.lsp4j.debug.ConfigurationDoneArguments;
Expand Down Expand Up @@ -313,13 +314,13 @@ private CompletableFuture<?> initialize(Map<String, Object> dspParameters, IProg

private void terminated() {
fTerminated = true;
Arrays.stream(getThreads()).forEach(t -> {
for (final DSPThread t : getThreads()) {
try {
t.terminate();
} catch (DebugException e) {
DSPPlugin.logError(e);
}
});
}
final var process = this.process;
if (process != null && process.canTerminate()) {
try {
Expand Down Expand Up @@ -452,7 +453,7 @@ public void continued(ContinuedEventArguments body) {
DSPDebugElement source = null;
source = getThread(body.getThreadId());
if (source == null || body.getAllThreadsContinued() == null || body.getAllThreadsContinued()) {
Arrays.asList(getThreads()).forEach(DSPThread::continued);
ArrayUtil.forEach(getThreads(), DSPThread::continued);
}
if (source != null) {
source.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
Expand All @@ -468,10 +469,10 @@ public void stopped(StoppedEventArguments body) {
source = getThread(body.getThreadId());
}
if (source == null || body.getAllThreadsStopped() == null || body.getAllThreadsStopped()) {
Arrays.asList(getThreads()).forEach(t -> {
for (final DSPThread t : getThreads()) {
t.stopped();
t.fireChangeEvent(DebugEvent.CHANGE);
});
}
}

if (source != null) {
Expand Down Expand Up @@ -506,8 +507,7 @@ public boolean canSuspend() {
@Override
public boolean isSuspended() {
DSPThread[] dspThreads = getThreads();
boolean anyMatch = Arrays.asList(dspThreads).stream().anyMatch(DSPThread::isSuspended);
return anyMatch;
return ArrayUtil.anyMatch(dspThreads, DSPThread::isSuspended);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.lsp4e.debug.DSPPlugin;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4j.debug.ContinueArguments;
import org.eclipse.lsp4j.debug.NextArguments;
import org.eclipse.lsp4j.debug.PauseArguments;
Expand Down Expand Up @@ -225,12 +226,7 @@ public boolean hasStackFrames() throws DebugException {

@Override
public @Nullable IStackFrame getTopStackFrame() throws DebugException {
IStackFrame[] stackFrames = getStackFrames();
if (stackFrames.length > 0) {
return stackFrames[0];
} else {
return null;
}
return ArrayUtil.findFirst(getStackFrames());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.eclipse.lsp4e.ContentTypeToLanguageServerDefinition;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.swt.widgets.Composite;
Expand Down Expand Up @@ -112,7 +113,7 @@ public static IEditorPart getEditor(IFile file) {
IWorkbenchPage page = workbenchWindow.getActivePage();
final var input = new FileEditorInput(file);

return Arrays.asList(page.getEditorReferences()).stream()
return List.of(page.getEditorReferences()).stream()
.filter(r -> {
try {
return r.getEditorInput().equals(input);
Expand Down Expand Up @@ -205,11 +206,7 @@ public static void delete(IProject project) throws CoreException {
}

public static void delete(IProject... projects) throws CoreException {
if (projects != null && projects.length > 0) {
for (IProject project : projects) {
delete(project);
}
}
ArrayUtil.forEach(projects, TestUtils::delete);
}

public static void delete(Path path) throws IOException {
Expand All @@ -219,11 +216,7 @@ public static void delete(Path path) throws IOException {
}

public static void delete(Path... paths) throws IOException {
if (paths != null && paths.length > 0) {
for (Path path : paths) {
delete(path);
}
}
ArrayUtil.forEach(paths, TestUtils::delete);
}

public static File createTempFile(String prefix, String suffix) throws IOException {
Expand Down Expand Up @@ -257,10 +250,8 @@ public static ContentTypeToLanguageServerDefinition getDisabledLS() {
}

public static Shell findNewShell(Set<Shell> beforeShells, Display display) {
Shell[] afterShells = Arrays.stream(display.getShells())
.filter(Shell::isVisible)
.filter(shell -> !beforeShells.contains(shell))
.toArray(Shell[]::new);
Shell[] afterShells = ArrayUtil.filter(display.getShells(),
shell -> shell.isVisible() && !beforeShells.contains(shell));
return afterShells.length > 0 ? afterShells[0] : null;
}

Expand Down
19 changes: 5 additions & 14 deletions org.eclipse.lsp4e/src/org/eclipse/lsp4e/LSPEclipseUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.IFileSystem;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
Expand Down Expand Up @@ -90,6 +89,7 @@
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4e.internal.DocumentInputStream;
import org.eclipse.lsp4e.refactoring.CreateFileChange;
import org.eclipse.lsp4e.refactoring.DeleteExternalFile;
Expand Down Expand Up @@ -425,11 +425,7 @@ public static IFile getFileHandle(@Nullable URI uri) {
}
if (FILE_SCHEME.equals(uri.getScheme())) {
IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
IFile[] files = wsRoot.findFilesForLocationURI(uri);
if (files.length > 0) {
return files[0];
}
return null;
return ArrayUtil.findFirst(wsRoot.findFilesForLocationURI(uri));
} else {
return Adapters.adapt(uri.toString(), IFile.class, true);
}
Expand Down Expand Up @@ -476,11 +472,7 @@ public static IResource findResourceFor(@Nullable URI uri) {
}
}

final IContainer[] containers = wsRoot.findContainersForLocationURI(uri);
if (containers.length > 0) {
return containers[0];
}
return null;
return ArrayUtil.findFirst(wsRoot.findContainersForLocationURI(uri));
} else {
return Adapters.adapt(uri, IResource.class, true);
}
Expand Down Expand Up @@ -1352,13 +1344,12 @@ public static List<IContentType> getFileContentTypes(IFile file) {
if (file.exists()) {
try (InputStream contents = file.getContents()) {
// TODO consider using document as inputstream
contentTypes.addAll(
Arrays.asList(contentTypeManager.findContentTypesFor(contents, file.getName())));
Collections.addAll(contentTypes, contentTypeManager.findContentTypesFor(contents, file.getName()));
} catch (CoreException | IOException e) {
LanguageServerPlugin.logError(e);
}
} else {
contentTypes.addAll(Arrays.asList(contentTypeManager.findContentTypesFor(file.getName())));
Collections.addAll(contentTypes, contentTypeManager.findContentTypesFor(file.getName()));
}
return contentTypes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4e.internal.CancellationUtil;
import org.eclipse.lsp4e.internal.FileBufferListenerAdapter;
import org.eclipse.lsp4e.internal.SupportedFeatures;
Expand Down Expand Up @@ -733,10 +734,8 @@ private boolean supportsWorkspaceFolderCapability() {
public void disconnectContentType(IContentType contentType) {
final var urisToDisconnect = new ArrayList<URI>();
for (URI uri : connectedDocuments.keySet()) {
IFile[] foundFiles = ResourcesPlugin.getWorkspace().getRoot()
.findFilesForLocationURI(uri);
if (foundFiles.length != 0
&& LSPEclipseUtils.getFileContentTypes(foundFiles[0]).stream().anyMatch(contentType::equals)) {
final var file = ArrayUtil.findFirst(ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri));
if (file != null && LSPEclipseUtils.getFileContentTypes(file).stream().anyMatch(contentType::equals)) {
urisToDisconnect.add(uri);
}
}
Expand Down
3 changes: 2 additions & 1 deletion org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServers.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
Expand All @@ -49,7 +50,7 @@ public abstract class LanguageServers<E extends LanguageServers<E>> {
private static void forwardCancellation(CompletableFuture<?> from, CompletableFuture<?>... to) {
from.exceptionally(t -> {
if (t instanceof CancellationException) {
Stream.of(to).forEach(f -> f.cancel(true));
ArrayUtil.forEach(to, f -> f.cancel(true));
}
return null;
});
Expand Down
123 changes: 123 additions & 0 deletions org.eclipse.lsp4e/src/org/eclipse/lsp4e/internal/ArrayUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
*******************************************************************************/
package org.eclipse.lsp4e.internal;

import static org.eclipse.lsp4e.internal.NullSafetyHelper.castNonNull;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;

import org.eclipse.jdt.annotation.Nullable;

public class ArrayUtil {

/** reusable empty byte array */
Expand All @@ -25,6 +35,119 @@ public class ArrayUtil {
/** reusable empty {@link String} array */
public static final String[] NO_STRINGS = new String[0];

/**
* @return true if any element of the given array is matched by the filter
*/
public static <T, X extends Throwable> boolean anyMatch(final T @Nullable [] array,
final ThrowingPredicate<? super T, X> filter) throws X {
if (array == null || array.length == 0)
return false;
for (final T e : array) {
if (filter.testOrThrow(e))
return true;
}
return false;
}

/**
* @return a modifiable {@link ArrayList} with the given elements
*/
@SafeVarargs
public static <T> ArrayList<T> asArrayList(final T... array) {
final var list = new ArrayList<T>(array.length);
Collections.addAll(list, array);
return list;
}

/**
* @return a modifiable {@link HashSet} with the given elements
*/
@SafeVarargs
public static <T> HashSet<T> asHashSet(final T... array) {
final var set = new HashSet<T>();
Collections.addAll(set, array);
return set;
}

public static <T> boolean contains(final T @Nullable [] array, final T searchFor) {
if (array == null || array.length == 0)
return false;
for (final T e : array) {
if (Objects.equals(e, searchFor))
return true;
}
return false;
}

/**
* @return a new array containing only elements that match the predicate
*/
public static <T, X extends Throwable> T[] filter(final T[] array, final ThrowingPredicate<? super T, X> filter)
throws X {
if (array.length == 0)
return array;

final var result = new ArrayList<T>();
for (final T item : array)
if (filter.testOrThrow(item)) {
result.add(item);
}

@SuppressWarnings("unchecked")
final T[] resultArray = (T[]) Array.newInstance(getComponentType(array), result.size());
return result.toArray(resultArray);
}

/**
* @return returns the first element of the given array or null if the array is
* empty
*/
@SafeVarargs
public static @Nullable <T> T findFirst(final T @Nullable... array) {
if (array == null || array.length == 0)
return null;
return array[0];
}

/**
* @return returns the first element of the given array matching the filter or null if the array is
* empty or no match was found
*/
public static @Nullable <T, X extends Throwable> T findFirstMatching(final T @Nullable [] array,
final ThrowingPredicate<T, X> filter) throws X {
if (array == null || array.length == 0)
return null;
for (final T e : array) {
if (filter.testOrThrow(e))
return e;
}
return null;
}

/**
* Iterates over the given array and applies the specified consumer to each
* element.
* <p>
* Does nothing if array is null/empty or consumer is null.
*/
public static <T, X extends Throwable> void forEach(final T @Nullable [] array,
final @Nullable ThrowingConsumer<T, X> consumer) throws X {
if (array == null || array.length == 0 || consumer == null)
return;

for (final T element : array) {
consumer.acceptOrThrow(element);
}
}

/**
* Returns the component type of the specified array.
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getComponentType(final T[] array) {
return (Class<T>) castNonNull(array.getClass().getComponentType());
}

private ArrayUtil() {
}
}
Loading

0 comments on commit e0d12cc

Please sign in to comment.