Skip to content

Commit

Permalink
Deprecate and replace Guava-using APIs in Scopes and QualifiedName
Browse files Browse the repository at this point in the history
Part of #2975
  • Loading branch information
HannesWell committed Apr 5, 2024
1 parent 77020bb commit 8e0c981
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.function.Function;

import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;
Expand All @@ -21,8 +22,6 @@
import org.junit.Assert;
import org.junit.Test;

import com.google.common.base.Function;

/**
* @author Jan Koehnlein - Initial contribution and API
*/
Expand Down Expand Up @@ -93,7 +92,7 @@ public void testAppendNull() {
assertTrue(qn.startsWithIgnoreCase(qn2));
assertFalse(qn2.startsWithIgnoreCase(qn));

assertThrows(IllegalArgumentException.class, ()->qn1.startsWith(null));
assertThrows(NullPointerException.class, () -> qn1.startsWith(null));
}

@Test public void testSkip() throws Exception {
Expand Down Expand Up @@ -213,12 +212,7 @@ public void testAppendNull() {
}

@Test public void testWrapper() throws Exception {
Function<String, String> identity = new Function<String, String>() {
@Override
public String apply(String from) {
return from;
}
};
Function<String, String> identity = from -> from;
Function<String, QualifiedName> wrapper = QualifiedName.wrapper(identity);
assertEquals(QualifiedName.create(""), wrapper.apply(""));
assertEquals(null, wrapper.apply(null));
Expand Down
29 changes: 18 additions & 11 deletions org.eclipse.xtext/src/org/eclipse/xtext/naming/QualifiedName.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import org.eclipse.emf.common.util.CommonUtil;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectOutputStream;
import org.eclipse.xtext.util.Strings;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;

/**
* A datatype for dealing with qualified names.
* Instances are usually provided by a {@link IQualifiedNameProvider}.
Expand Down Expand Up @@ -239,18 +238,26 @@ public static QualifiedName create(String singleSegment) {
return new QualifiedName(intern(singleSegment));
}

/**
* Wraps a name function to return a qualified name. Returns null if the name function returns null.
* @deprecated Instead use {@link #wrapper(Function)}
*/
@Deprecated(since = "2.35.0", forRemoval = true)
public static <F> com.google.common.base.Function<F, QualifiedName> wrapper(
com.google.common.base.Function<F, String> nameFunction) {
return wrapper((Function<F, String>) nameFunction)::apply;
}

/**
* Wraps a name function to return a qualified name. Returns null if the name function returns null.
*/
public static <F> Function<F, QualifiedName> wrapper(final Function<F, String> nameFunction) {
return new Function<F, QualifiedName>() {
@Override
public QualifiedName apply(F from) {
String name = nameFunction.apply(from);
if (name == null)
return null;
return QualifiedName.create(name);
return from -> {
String name = nameFunction.apply(from);
if (name == null) {
return null;
}
return QualifiedName.create(name);
};
}

Expand Down Expand Up @@ -486,7 +493,7 @@ public boolean startsWithIgnoreCase(QualifiedName prefix) {
}

protected boolean startsWith(QualifiedName prefix, boolean ignoreCase) {
Preconditions.checkArgument(prefix != null, "prefix must not be null");
Objects.requireNonNull(prefix, "prefix must not be null");

if (prefix.getSegmentCount() > getSegmentCount()) {
return false;
Expand Down
124 changes: 78 additions & 46 deletions org.eclipse.xtext/src/org/eclipse/xtext/scoping/Scopes.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009 itemis AG (http://www.itemis.eu) and others.
* Copyright (c) 2009, 2024 itemis AG (http://www.itemis.eu) 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
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -10,7 +10,13 @@
package org.eclipse.xtext.scoping;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
Expand All @@ -22,30 +28,18 @@
import org.eclipse.xtext.scoping.impl.SimpleScope;
import org.eclipse.xtext.util.SimpleAttributeResolver;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;

/**
* This class contains static utility functions to create and work on {@link IScope} and {@link IEObjectDescription}
*
*
* @author Sven Efftinge - Initial contribution and API
* @author Jan Koehnlein - introduced QualifiedName
*/
public class Scopes {

public static Iterable<IEObjectDescription> selectCompatible(Iterable<IEObjectDescription> exportedObjects, final EClass clazz) {
return Iterables.filter(exportedObjects, new Predicate<IEObjectDescription>() {
@Override
public boolean apply(IEObjectDescription input) {
return EcoreUtil2.isAssignableFrom(clazz,input.getEClass());
}
});
return Iterables.filter(exportedObjects, input -> EcoreUtil2.isAssignableFrom(clazz, input.getEClass()));
}

/**
Expand All @@ -60,15 +54,25 @@ public static IScope scopeFor(Iterable<? extends EObject> elements) {
* creates a scope using {@link SimpleAttributeResolver#NAME_RESOLVER} to compute the names
*/
public static IScope scopeFor(Iterable<? extends EObject> elements, IScope outer) {
return scopeFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER), outer);
return scopeFor(elements, QualifiedName.wrapper((Function<EObject, String>) SimpleAttributeResolver.NAME_RESOLVER), outer);
}

/**
* creates a scope using the passed function to compute the names and sets the passed scope as the parent scope
* @deprecated Instead use {@link #scopeFor(Iterable, Function, IScope)}
*/
@Deprecated(since = "2.35.0", forRemoval = true)
public static <T extends EObject> IScope scopeFor(Iterable<? extends T> elements,
com.google.common.base.Function<T, QualifiedName> nameComputation, IScope outer) {
return scopeFor(elements, (java.util.function.Function<T, QualifiedName>) nameComputation, outer);
}

/**
* creates a scope using the passed function to compute the names and sets the passed scope as the parent scope
*/
public static <T extends EObject> IScope scopeFor(Iterable<? extends T> elements,
final Function<T, QualifiedName> nameComputation, IScope outer) {
return new SimpleScope(outer,scopedElementsFor(elements, nameComputation));
Function<T, QualifiedName> nameComputation, IScope outer) {
return new SimpleScope(outer, scopedElementsFor(elements, nameComputation));
}

/**
Expand All @@ -77,55 +81,83 @@ public static <T extends EObject> IScope scopeFor(Iterable<? extends T> elements
* filtered out.
*/
public static Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends EObject> elements) {
return scopedElementsFor(elements, QualifiedName.wrapper(SimpleAttributeResolver.NAME_RESOLVER));
return scopedElementsFor(elements, QualifiedName.wrapper((Function<EObject, String>) SimpleAttributeResolver.NAME_RESOLVER));
}

/**
* transforms an {@link Iterable} of {@link EObject}s into an {@link Iterable} of {@link IEObjectDescription}s computing
* the name of the elements using the passed {@link Function} If the passed function returns null the object is
* filtered out.
* @deprecated Instead use {@link #scopedElementsFor(Iterable, Function)}
*/
@Deprecated(since = "2.35.0", forRemoval = true)
public static <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends T> elements,
final Function<T, QualifiedName> nameComputation) {
Iterable<IEObjectDescription> transformed = Iterables.transform(elements,
new Function<T, IEObjectDescription>() {
@Override
public IEObjectDescription apply(T from) {
final QualifiedName qualifiedName = nameComputation.apply(from);
if (qualifiedName != null)
return new EObjectDescription(qualifiedName, from, null);
return null;
}
});
return Iterables.filter(transformed, Predicates.notNull());
com.google.common.base.Function<T, QualifiedName> nameComputation) {
return scopedElementsFor(elements, (java.util.function.Function<T, QualifiedName>) nameComputation);
}


/**
* transforms an {@link Iterable} of {@link EObject}s into an {@link Iterable} of {@link IEObjectDescription}s computing
* the name of the elements using the passed {@link Function} If the passed function returns null the object is
* filtered out.
*/
public static <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor(Iterable<? extends T> elements,
Function<T, QualifiedName> nameComputation) {
Iterable<IEObjectDescription> transformed = Iterables.transform(elements, from -> {
final QualifiedName qualifiedName = nameComputation.apply(from);
if (qualifiedName != null)
return new EObjectDescription(qualifiedName, from, null);
return null;
});
return Iterables.filter(transformed, Objects::nonNull);
}

/**
* indexes the IEObject description using the given
* @deprecated Instead use {@link #index(Iterable, Function)}
*/
@Deprecated(since = "2.35.0", forRemoval = true)
public static <T> com.google.common.collect.Multimap<T, IEObjectDescription> index(
Iterable<IEObjectDescription> descriptions,
com.google.common.base.Function<IEObjectDescription, T> indexer) {
Map<T, Set<IEObjectDescription>> index = index(descriptions, (Function<IEObjectDescription, T>) indexer);
com.google.common.collect.Multimap<T, IEObjectDescription> multimap = com.google.common.collect.LinkedHashMultimap.create();
index.forEach(multimap::putAll);
return multimap;
}

/**
* indexes the IEObject description using the given
*/
public static <T> Multimap<T,IEObjectDescription> index(Iterable<IEObjectDescription> descriptions, Function<IEObjectDescription,T> indexer) {
ArrayList<IEObjectDescription> list = Lists.newArrayList(descriptions);
LinkedHashMultimap<T, IEObjectDescription> multimap = LinkedHashMultimap.create(list.size(),1);
public static <T> Map<T, Set<IEObjectDescription>> index(Iterable<IEObjectDescription> descriptions,
Function<IEObjectDescription, T> indexer) {
List<IEObjectDescription> list = new ArrayList<>();
descriptions.forEach(list::add);
Map<T, Set<IEObjectDescription>> multimap = new LinkedHashMap<>(list.size() * 4 / 3 + 1);
for (IEObjectDescription desc : list) {
multimap.put(indexer.apply(desc), desc);
multimap.computeIfAbsent(indexer.apply(desc), n -> new LinkedHashSet<>(1)).add(desc);
}
return multimap;
}

/**
* indexes the IEObject description using the given
* @deprecated Instead use {@link #indexByName(Iterable)}
*/
public static Multimap<QualifiedName,IEObjectDescription> index(Iterable<IEObjectDescription> descriptions) {
return index(descriptions, new Function<IEObjectDescription, QualifiedName>() {
@Override
public QualifiedName apply(IEObjectDescription from) {
return from.getName().toLowerCase();
}
});
@Deprecated(since = "2.35.0", forRemoval = true)
public static com.google.common.collect.Multimap<QualifiedName,IEObjectDescription> index(Iterable<IEObjectDescription> descriptions) {
return index(descriptions, from -> from.getName().toLowerCase());
}

/**
* indexes the IEObject description using the given
*/
public static Map<QualifiedName, Set<IEObjectDescription>> indexByName(Iterable<IEObjectDescription> descriptions) {
return index(descriptions, (Function<IEObjectDescription, QualifiedName>) from -> from.getName().toLowerCase());
}

public static Iterable<IEObjectDescription> filterDuplicates(Iterable<IEObjectDescription> filtered) {
Map<QualifiedName, IEObjectDescription> result = Maps.newLinkedHashMap();
Map<QualifiedName, IEObjectDescription> result = new LinkedHashMap<>();
for (IEObjectDescription e : filtered) {
QualifiedName qualifiedName = e.getName();
if (result.containsKey(qualifiedName)) {
Expand All @@ -134,7 +166,7 @@ public static Iterable<IEObjectDescription> filterDuplicates(Iterable<IEObjectDe
result.put(qualifiedName, e);
}
}
return Iterables.filter(result.values(), Predicates.notNull());
return Iterables.filter(result.values(), Objects::nonNull);
}

}

0 comments on commit 8e0c981

Please sign in to comment.