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

net.jangaroo.jooc.ImplementedMembersAnalyzer Maven / Gradle / Ivy

The newest version!
package net.jangaroo.jooc;

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.Multimap;
import net.jangaroo.jooc.ast.ClassDeclaration;
import net.jangaroo.jooc.ast.CommaSeparatedList;
import net.jangaroo.jooc.ast.CompilationUnit;
import net.jangaroo.jooc.ast.FunctionDeclaration;
import net.jangaroo.jooc.ast.Ide;
import net.jangaroo.jooc.ast.IdeDeclaration;
import net.jangaroo.jooc.ast.Implements;
import net.jangaroo.jooc.ast.TypedIdeDeclaration;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;

/**
 * Check if methods defined in interfaces are actually implemented in implementing classes.
 *
 * Adobe AS3 Docs
 */
class ImplementedMembersAnalyzer {

  private Jooc jooc;
  private Collection inspected = new HashSet<>();
  private Multimap membersByInterfaceQName = LinkedHashMultimap.create();
  private Multimap membersByClassQName = LinkedHashMultimap.create();

  ImplementedMembersAnalyzer(Jooc jooc) {
    this.jooc = jooc;
  }

  void analyzeImplementedMembers(CompilationUnit compilationUnit) {
    IdeDeclaration primaryDeclaration = compilationUnit.getPrimaryDeclaration();
    String qName = primaryDeclaration.getQualifiedNameStr();
    if (primaryDeclaration instanceof ClassDeclaration && inspected.add(qName)) {
      visitClassDeclaration((ClassDeclaration) primaryDeclaration);
    }
  }

  void visitClassDeclaration(ClassDeclaration classDeclaration) {
    String qName = classDeclaration.getQualifiedNameStr();
    boolean isInterface = classDeclaration.isInterface();

    Collection toBeImplemented = new LinkedHashSet<>();

    Implements optImplements = classDeclaration.getOptImplements();
    if (null != optImplements) {
      for (CommaSeparatedList localSuperTypes = optImplements.getSuperTypes(); localSuperTypes != null; localSuperTypes = localSuperTypes.getTail()) {
        String superClassQName = localSuperTypes.getHead().getDeclaration().getQualifiedNameStr();

        analyzeImplementedMembers(jooc.getCompilationUnit(superClassQName));

        Collection superClassMembers = membersByInterfaceQName.get(superClassQName);
        if (isInterface) {
          // add inherited methods to current methods
          membersByInterfaceQName.putAll(qName, superClassMembers);
        } else {
          toBeImplemented.addAll(superClassMembers);
        }
      }
    }

    ClassDeclaration superTypeDeclaration = classDeclaration.getSuperTypeDeclaration();
    if (null != superTypeDeclaration) {
      String superClassQName = superTypeDeclaration.getQualifiedNameStr();
      analyzeImplementedMembers(jooc.getCompilationUnit(superClassQName));

      // add inherited methods to current methods
      membersByClassQName.putAll(qName, membersByClassQName.get(superClassQName));
    }

    ClassDeclaration classModel = (ClassDeclaration) jooc.resolveCompilationUnit(qName).getPrimaryDeclaration();
    Iterable methodModels = classModel.getMethods();

    if (isInterface) {
      membersByInterfaceQName.putAll(qName, methodModels);
    } else {

      FunctionDeclaration constructor = classModel.getConstructor();
      Iterable publicNonStaticMethods = Iterables.filter(methodModels, Predicates.and(new Predicate() {
        @Override
        public boolean apply(@Nullable FunctionDeclaration input) {
          //noinspection ConstantConditions
          return !input.isStatic() && input.isPublic();
        }
      }, Predicates.not(Predicates.equalTo(constructor))));

      membersByClassQName.putAll(qName, publicNonStaticMethods);
    }

    if (!isInterface) {
      Collection implemented = membersByClassQName.get(qName);
      toBeImplemented.addAll(membersByInterfaceQName.get(qName));
      toBeImplemented.removeAll(implemented);
      if (!toBeImplemented.isEmpty()) {
        throw JangarooParser.error(optImplements, "Does not implement " + Iterables.transform(toBeImplemented, new Function() {
          @Nullable
          @Override
          public String apply(@Nullable TypedIdeDeclaration input) {
            //noinspection ConstantConditions
            if (input instanceof FunctionDeclaration && ((FunctionDeclaration) input).isGetterOrSetter()) {
              return ((FunctionDeclaration)input).getSymGetOrSet().getText() + " " + input.getName();
            }
            return input == null ? null : input.getName();
          }
        }));
      }
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy