![JAR search and dependency download from the Maven repository](/logo.png)
org.immutables.value.internal.$generator$.$SourceOrdering Maven / Gradle / Ivy
Show all versions of value Show documentation
/*
Copyright 2014 Immutables Authors and Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.immutables.generator;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.eclipse.jdt.internal.compiler.apt.model.ElementImpl;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
/**
* Utility that abstracts away hacks to retrieve elements in source order. Currently, Javac returns
* elements in proper source order, but EJC returns elements in alphabetical order.
*
* - Bug 300408 -
* TypeElement.getEnclosedElements does not respect source order
*
- JDK-6884227 : Clarify ordering
* requirements of javax.lang.model.TypeElement.getEnclosedElements
*
*
* Based on a workaround idea provided by Christian Humer
*/
public final class SourceOrdering {
private SourceOrdering() {}
private interface OrderingProvider {
Ordering enclosedBy(Element element);
}
private static final OrderingProvider DEFAULT_PROVIDER = new OrderingProvider() {
// it's safe to cast ordering because it handles elements without regards of actual types.
@SuppressWarnings("unchecked")
@Override
public Ordering enclosedBy(Element element) {
return (Ordering) Ordering.explicit(element.getEnclosedElements());
}
};
private static final OrderingProvider PROVIDER = createProvider();
// it's safe to cast immutable list of extends Element> to a list of
@SuppressWarnings("unchecked")
public static ImmutableList getEnclosedElements(Element element) {
return (ImmutableList) enclosedBy(element).immutableSortedCopy(element.getEnclosedElements());
}
public static Ordering enclosedBy(Element element) {
return PROVIDER.enclosedBy(element);
}
private static OrderingProvider createProvider() {
if (Compiler.ECJ.isPresent()) {
return new EclipseCompilerOrderingProvider();
}
return DEFAULT_PROVIDER;
}
/**
* This inner static class will fail to load if Eclipse compliler classes will not be in
* classpath.
* If annotation processor is executed by Javac compiler in presence of ECJ classes, then
* instanceof checks will fail with fallback to defaults (Javac).
*/
private static class EclipseCompilerOrderingProvider
implements OrderingProvider, Function {
@Override
public Object apply(Element input) {
return ((ElementImpl) input)._binding;
}
@Override
public Ordering enclosedBy(Element element) {
if (element instanceof ElementImpl
&& Iterables.all(element.getEnclosedElements(), Predicates.instanceOf(ElementImpl.class))) {
ElementImpl implementation = (ElementImpl) element;
if (implementation._binding instanceof SourceTypeBinding) {
SourceTypeBinding sourceBinding = (SourceTypeBinding) implementation._binding;
return Ordering.natural().onResultOf(
Functions.compose(bindingsToSourceOrder(sourceBinding), this));
}
}
return DEFAULT_PROVIDER.enclosedBy(element);
}
private Function