All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.zerobuilder.compiler.common.LessElements Maven / Gradle / Ivy

There is a newer version: 1.644
Show newest version
package net.zerobuilder.compiler.common;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor6;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;

import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.lang.model.util.ElementFilter.methodsIn;
import static net.zerobuilder.compiler.common.LessTypes.asTypeElement;

/**
 * Guava-free versions of some helpers from auto-common.
 */
public final class LessElements {

  private static final ElementVisitor TYPE_ELEMENT_VISITOR =
      new SimpleElementVisitor6() {
        @Override
        protected TypeElement defaultAction(Element e, Void p) {
          throw new IllegalArgumentException();
        }

        @Override
        public TypeElement visitType(TypeElement e, Void p) {
          return e;
        }
      };

  private static final ElementVisitor EXECUTABLE_ELEMENT_VISITOR =
      new SimpleElementVisitor6() {
        @Override
        protected ExecutableElement defaultAction(Element e, Void p) {
          throw new IllegalArgumentException();
        }

        @Override
        public ExecutableElement visitExecutable(ExecutableElement e, Void p) {
          return e;
        }
      };

  /**
   * Find all non-static, visible methods that match the predicate, and group by name.
   * In case of name conflict, the first found wins.
   * The iteration order is:
   * 
    *
  • {@code type} first, {@code Object} last
  • *
  • concrete types before interfaces
  • *
* Ideally the {@code predicate} should prevent name conflicts. * * @param type type to search * @param predicate filter * @return methods by name */ public static Map getLocalAndInheritedMethods( TypeElement type, Predicate predicate) { Map methods = new LinkedHashMap<>(); PackageElement packageElement = getPackage(type); addFromSuperclass(packageElement, type, methods, predicate); addFromInterfaces(packageElement, type, methods, predicate); return methods; } private static void addFromSuperclass( PackageElement pkg, TypeElement type, Map methods, Predicate predicate) { addEnclosed(pkg, type, methods, predicate); if (type.getSuperclass().getKind() == TypeKind.NONE) { return; } addFromSuperclass(pkg, asTypeElement(type.getSuperclass()), methods, predicate); } private static void addFromInterfaces( PackageElement pkg, TypeElement type, Map methods, Predicate predicate) { addEnclosed(pkg, type, methods, predicate); for (TypeMirror superInterface : type.getInterfaces()) { addFromInterfaces(pkg, asTypeElement(superInterface), methods, predicate); } } private static void addEnclosed(PackageElement pkg, TypeElement type, Map methods, Predicate predicate) { methodsIn(type.getEnclosedElements()) .stream() .filter(predicate) .forEach(method -> { if (method.getKind() == ElementKind.METHOD && !method.getModifiers().contains(Modifier.STATIC) && methodVisibleFromPackage(method, pkg)) { methods.computeIfAbsent(method.getSimpleName().toString(), name -> method); } }); } private static boolean methodVisibleFromPackage(ExecutableElement method, PackageElement pkg) { Visibility visibility = Visibility.ofElement(method); switch (visibility) { case PRIVATE: return false; case DEFAULT: return getPackage(method).equals(pkg); default: return true; } } private static PackageElement getPackage(Element element) { while (element.getKind() != PACKAGE) { element = element.getEnclosingElement(); } return (PackageElement) element; } public static ExecutableElement asExecutable(Element element) { return element.accept(EXECUTABLE_ELEMENT_VISITOR, null); } static TypeElement asType(Element element) { return element.accept(TYPE_ELEMENT_VISITOR, null); } private LessElements() { throw new UnsupportedOperationException("no instances"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy