Skip to content

Commit

Permalink
api: Expose ComponentLike -> Component conversion method
Browse files Browse the repository at this point in the history
  • Loading branch information
kashike committed May 13, 2021
1 parent 551ca25 commit cbcf57f
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 41 deletions.
35 changes: 4 additions & 31 deletions api/src/main/java/net/kyori/adventure/text/AbstractComponent.java
Expand Up @@ -23,11 +23,10 @@
*/
package net.kyori.adventure.text;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.util.Buildable;
Expand All @@ -46,34 +45,7 @@
*/
@Debug.Renderer(text = "this.debuggerString()", childrenArray = "this.children().toArray()", hasChildren = "!this.children().isEmpty()")
public abstract class AbstractComponent implements Component {
static List<Component> asComponents(final List<? extends ComponentLike> list) {
return asComponents(list, false);
}

static List<Component> asComponents(final List<? extends ComponentLike> list, final boolean allowEmpty) {
if(list.isEmpty()) {
// We do not need to create a new list if the one we are copying is empty - we can
// simply just return our known-empty list instead.
return Collections.emptyList();
}
final List<Component> components = new ArrayList<>(list.size());
for(int i = 0, size = list.size(); i < size; i++) {
final ComponentLike like = list.get(i);
final Component component = like.asComponent();
if(allowEmpty || component != Component.empty()) {
components.add(component);
}
}
return Collections.unmodifiableList(components);
}

static <T> List<T> addOne(final List<T> oldList, final T newElement) {
if(oldList.isEmpty()) return Collections.singletonList(newElement);
final List<T> newList = new ArrayList<>(oldList.size() + 1);
newList.addAll(oldList);
newList.add(newElement);
return newList;
}
private static final Predicate<Component> NOT_EMPTY = component -> component != Component.empty();

/**
* The list of children.
Expand All @@ -85,7 +57,7 @@ static <T> List<T> addOne(final List<T> oldList, final T newElement) {
protected final Style style;

protected AbstractComponent(final @NonNull List<? extends ComponentLike> children, final @NonNull Style style) {
this.children = asComponents(children);
this.children = ComponentLike.asComponents(children, NOT_EMPTY);
this.style = style;
}

Expand Down Expand Up @@ -130,6 +102,7 @@ public int hashCode() {
return result;
}

@SuppressWarnings("unused")
private String debuggerString() {
return StringExaminer.simpleEscaping().examine(this.examinableName(), this.examinablePropertiesWithoutChildren());
}
Expand Down
54 changes: 54 additions & 0 deletions api/src/main/java/net/kyori/adventure/text/ComponentLike.java
Expand Up @@ -23,7 +23,12 @@
*/
package net.kyori.adventure.text;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.Contract;

/**
Expand All @@ -33,6 +38,55 @@
*/
@FunctionalInterface
public interface ComponentLike {
/**
* Converts a list of {@link ComponentLike}s to a list of {@link Component}s.
*
* @param likes the component-likes
* @return the components
* @since 4.8.0
*/
static @NonNull List<Component> asComponents(final @NonNull List<? extends ComponentLike> likes) {
return asComponents(likes, null);
}

/**
* Converts a list of {@link ComponentLike}s to a list of {@link Component}s.
*
* <p>Only components that match {@code filter} will be returned.</p>
*
* @param likes the component-likes
* @param filter the component filter
* @return the components
* @since 4.8.0
*/
static @NonNull List<Component> asComponents(final @NonNull List<? extends ComponentLike> likes, final @Nullable Predicate<? super Component> filter) {
if(likes.isEmpty()) {
// We do not need to create a new list if the one we are copying is empty - we can
// simply just return our known-empty list instead.
return Collections.emptyList();
}
final int size = likes.size();
@Nullable ArrayList<Component> components = null;
for(int i = 0; i < size; i++) {
final ComponentLike like = likes.get(i);
final Component component = like.asComponent();
if(filter == null || filter.test(component)) {
if(components == null) {
components = new ArrayList<>(size);
}
components.add(component);
}
}
if(components != null) {
// https://github.com/KyoriPowered/adventure/pull/327/files#r631420264
// we pre-size the list, but filtering might make the actual size much smaller
components.trimToSize();
}
// if we filtered all elements out, just use an empty list instead
if(components == null || components.isEmpty()) return Collections.emptyList();
return Collections.unmodifiableList(components);
}

/**
* Gets a {@link Component} representation.
*
Expand Down
Expand Up @@ -31,6 +31,7 @@
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.util.MonkeyBars;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

Expand Down Expand Up @@ -76,7 +77,7 @@ public interface ScopedComponent<C extends Component> extends Component {
default @NonNull C append(final @NonNull Component component) {
if(component == Component.empty()) return (C) this;
final List<Component> oldChildren = this.children();
return this.children(AbstractComponent.addOne(oldChildren, component));
return this.children(MonkeyBars.addOne(oldChildren, component));
}

@Override
Expand Down
Expand Up @@ -48,7 +48,7 @@ final class TranslatableComponentImpl extends AbstractComponent implements Trans
super(children, style);
this.key = requireNonNull(key, "key");
// Since translation arguments can be indexed, empty components are also included.
this.args = AbstractComponent.asComponents(args, true);
this.args = ComponentLike.asComponents(args);
}

@Override
Expand Down Expand Up @@ -164,7 +164,7 @@ static final class BuilderImpl extends AbstractComponentBuilder<TranslatableComp

@Override
public @NonNull Builder args(final @NonNull List<? extends ComponentLike> args) {
this.args = AbstractComponent.asComponents(args, true);
this.args = ComponentLike.asComponents(args);
return this;
}

Expand Down
4 changes: 2 additions & 2 deletions api/src/main/java/net/kyori/adventure/text/format/Style.java
Expand Up @@ -34,7 +34,7 @@
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.util.Buildable;
import net.kyori.adventure.util.ShadyPines;
import net.kyori.adventure.util.MonkeyBars;
import net.kyori.examination.Examinable;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -577,7 +577,7 @@ enum Merge {
* @since 4.0.0
*/
public static @Unmodifiable @NonNull Set<Merge> of(final Merge@NonNull... merges) {
return ShadyPines.enumSet(Merge.class, merges);
return MonkeyBars.enumSet(Merge.class, merges);
}

static boolean hasAll(final @NonNull Set<Merge> merges) {
Expand Down
78 changes: 78 additions & 0 deletions api/src/main/java/net/kyori/adventure/util/MonkeyBars.java
@@ -0,0 +1,78 @@
/*
* This file is part of adventure, licensed under the MIT License.
*
* Copyright (c) 2017-2021 KyoriPowered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.kyori.adventure.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.NonNull;

/**
* {@link Collection} related utilities.
*
* @since 4.8.0
*/
public final class MonkeyBars {
private MonkeyBars() {
}

/**
* Creates a set from an array of enum constants.
*
* @param type the enum type
* @param constants the enum constants
* @param <E> the enum type
* @return the set
* @since 4.0.0
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <E extends Enum<E>> @NonNull Set<E> enumSet(final Class<E> type, final E@NonNull... constants) {
final Set<E> set = EnumSet.noneOf(type);
Collections.addAll(set, constants);
return Collections.unmodifiableSet(set);
}

/**
* Adds an element to the end of the list, or returns a new list.
*
* <p>The returned list is unmodifiable.</p>
*
* @param oldList the old list
* @param newElement the element to add
* @param <T> the element type
* @return a list
* @since 4.8.0
*/
public static <T> @NonNull List<T> addOne(final @NonNull List<T> oldList, final T newElement) {
if(oldList.isEmpty()) return Collections.singletonList(newElement);
final List<T> newList = new ArrayList<>(oldList.size() + 1);
newList.addAll(oldList);
newList.add(newElement);
return Collections.unmodifiableList(newList);
}
}
8 changes: 3 additions & 5 deletions api/src/main/java/net/kyori/adventure/util/ShadyPines.java
Expand Up @@ -23,8 +23,6 @@
*/
package net.kyori.adventure.util;

import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.NonNull;

Expand All @@ -44,14 +42,14 @@ private ShadyPines() {
* @param constants the enum constants
* @param <E> the enum type
* @return the set
* @deprecated for removal since 4.8.0, use {@link MonkeyBars#enumSet(Class, Enum[])}
* @since 4.0.0
*/
@Deprecated
@SafeVarargs
@SuppressWarnings("varargs")
public static <E extends Enum<E>> @NonNull Set<E> enumSet(final Class<E> type, final E@NonNull... constants) {
final Set<E> set = EnumSet.noneOf(type);
Collections.addAll(set, constants);
return Collections.unmodifiableSet(set);
return MonkeyBars.enumSet(type, constants);
}

/**
Expand Down

0 comments on commit cbcf57f

Please sign in to comment.