/**
   * In the first enclosing class, find the top-level member that contains tree. TODO: should we
   * look whether these elements are enclosed within another class that is itself under
   * construction.
   *
   * <p>Are there any other type of top level objects?
   */
  private Tree findTopLevelClassMemberForTree(TreePath path) {
    ClassTree enclosingClass = TreeUtils.enclosingClass(path);
    if (enclosingClass != null) {

      List<? extends Tree> classMembers = enclosingClass.getMembers();
      TreePath searchPath = path;
      while (searchPath.getParentPath() != null && searchPath.getParentPath() != enclosingClass) {
        searchPath = searchPath.getParentPath();
        if (classMembers.contains(searchPath.getLeaf())) {
          return searchPath.getLeaf();
        }
      }
    }
    return null;
  }
  private static List<? extends TypeMirror> computeUnary(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    UnaryTree tree = (UnaryTree) parent.getLeaf();

    if (tree.getExpression() == error) {
      List<? extends TypeMirror> parentTypes =
          resolveType(types, info, parent.getParentPath(), tree, offset, null, null);

      if (parentTypes != null) {
        // may contain only "void", ignore:
        if (parentTypes.size() != 1) {
          return parentTypes;
        }
        if (parentTypes.get(0).getKind() != TypeKind.VOID) {
          return parentTypes;
        }
      }

      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT));
    }

    return null;
  }
  private static List<? extends TypeMirror> computeVariableDeclaration(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    VariableTree vt = (VariableTree) parent.getLeaf();

    if (vt.getInitializer() == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(
          info.getTrees().getTypeMirror(new TreePath(parent, vt.getType())));
    }

    TreePath context = parent.getParentPath();
    if (vt.getType() != error || context == null) {
      return null;
    }

    switch (context.getLeaf().getKind()) {
      case ENHANCED_FOR_LOOP:
        ExpressionTree iterableTree = ((EnhancedForLoopTree) context.getLeaf()).getExpression();
        TreePath iterablePath = new TreePath(context, iterableTree);
        TypeMirror type = getIterableGenericType(info, iterablePath);
        types.add(ElementKind.LOCAL_VARIABLE);
        return Collections.singletonList(type);
      default:
        types.add(ElementKind.CLASS);
        return Collections.<TypeMirror>emptyList();
    }
  }
  private static List<? extends TypeMirror> computeParametrizedType(
      Set<ElementKind> types,
      CompilationInfo info,
      TreePath parent,
      Tree error,
      int offset,
      TypeMirror[] typeParameterBound,
      int[] numTypeParameters) {
    ParameterizedTypeTree ptt = (ParameterizedTypeTree) parent.getLeaf();

    if (ptt.getType() == error) {
      Tree gpt = parent.getParentPath().getLeaf();
      if (TreeUtilities.CLASS_TREE_KINDS.contains(gpt.getKind())
          && ((ClassTree) gpt).getExtendsClause() == ptt) {
        types.add(ElementKind.CLASS);
      } else if (TreeUtilities.CLASS_TREE_KINDS.contains(gpt.getKind())
          && ((ClassTree) gpt).getImplementsClause().contains(ptt)) {
        types.add(ElementKind.INTERFACE);
      } else {
        types.add(ElementKind.CLASS);
        types.add(ElementKind.INTERFACE);
      }

      if (numTypeParameters != null) {
        numTypeParameters[0] = ptt.getTypeArguments().size();
      }
      return null;
    }

    TypeMirror resolved = info.getTrees().getTypeMirror(parent);
    DeclaredType resolvedDT = null;

    if (resolved != null && resolved.getKind() == TypeKind.DECLARED) {
      resolvedDT = (DeclaredType) resolved;
    }

    int index = 0;

    for (Tree t : ptt.getTypeArguments()) {
      if (t == error) {
        if (resolvedDT != null && typeParameterBound != null) {
          List<? extends TypeMirror> typeArguments =
              ((DeclaredType) resolvedDT.asElement().asType()).getTypeArguments();

          if (typeArguments.size() > index) {
            typeParameterBound[0] = ((TypeVariable) typeArguments.get(index)).getUpperBound();
          }
        }

        types.add(ElementKind.CLASS); // XXX: class/interface/enum/annotation?
        return null;
      }

      index++;
    }

    return null;
  }
  private static TreePath findMethod(TreePath tp) {
    while (!STOP_LOOKING_FOR_METHOD.contains(tp.getLeaf().getKind())) {
      tp = tp.getParentPath();
    }

    if (tp.getLeaf().getKind() == Kind.METHOD) {
      return tp;
    }

    return null;
  }
 /**
  * Search up the hierarchy of elements for one of the given kind.
  *
  * @param kind the element's kind to search for
  * @param path the starting element
  * @return {@code null} if no element was found.
  */
 static TreePath getParentElementOfKind(Tree.Kind kind, TreePath path) {
   if (path != null) {
     TreePath tpath = path;
     while (tpath != null) {
       if (kind == tpath.getLeaf().getKind()) {
         return tpath;
       }
       tpath = tpath.getParentPath();
     }
   }
   return null;
 }
  /** {@inheritDoc} */
  @Override
  public boolean isSatisfiedBy(TreePath path) {
    do {
      Tree.Kind kind = path.getLeaf().getKind();
      if (kind == Tree.Kind.METHOD) return false;
      if (ASTPath.isClassEquiv(kind)) {
        return true;
      }
      path = path.getParentPath();
    } while (path != null && path.getLeaf() != null);

    return true;
  }
  private static List<? extends TypeMirror> computeParenthesis(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    ParenthesizedTree pt = (ParenthesizedTree) parent.getLeaf();

    if (pt.getExpression() != error) {
      return null;
    }

    TreePath parentParent = parent.getParentPath();
    List<? extends TypeMirror> upperTypes =
        resolveType(types, info, parentParent, pt, offset, null, null);

    if (upperTypes == null) {
      return null;
    }

    return upperTypes;
  }
  private static List<? extends TypeMirror> computeArrayAccess(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    ArrayAccessTree aat = (ArrayAccessTree) parent.getLeaf();

    if (aat.getExpression() == error) {
      TreePath parentParent = parent.getParentPath();
      List<? extends TypeMirror> upperTypes =
          resolveType(types, info, parentParent, aat, offset, null, null);

      if (upperTypes == null) {
        return null;
      }

      List<TypeMirror> arrayTypes = new ArrayList<TypeMirror>();

      for (TypeMirror tm : upperTypes) {
        if (tm == null) continue;
        switch (tm.getKind()) {
          case VOID:
          case EXECUTABLE:
          case WILDCARD:
          case PACKAGE:
            continue;
        }

        arrayTypes.add(info.getTypes().getArrayType(tm));
      }

      if (arrayTypes.isEmpty()) return null;

      return arrayTypes;
    }

    if (aat.getIndex() == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT));
    }

    return null;
  }
  private static List<? extends TypeMirror> computeNewClass(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    NewClassTree nct = (NewClassTree) parent.getLeaf();
    boolean errorInRealArguments = false;

    for (Tree param : nct.getArguments()) {
      errorInRealArguments |= param == error;
    }

    if (errorInRealArguments) {
      TypeMirror[] proposedType = new TypeMirror[1];
      int[] proposedIndex = new int[1];
      ExecutableElement ee =
          org.netbeans.modules.editor.java.Utilities.fuzzyResolveMethodInvocation(
              info, parent, proposedType, proposedIndex);

      if (ee == null) { // cannot be resolved
        return null;
      }

      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(proposedType[0]);
    }

    Tree id = nct.getIdentifier();

    if (id.getKind() == Kind.PARAMETERIZED_TYPE) {
      id = ((ParameterizedTypeTree) id).getType();
    }

    if (id == error) {
      return resolveType(
          EnumSet.noneOf(ElementKind.class), info, parent.getParentPath(), nct, offset, null, null);
    }

    return null;
  }
  private static List<? extends TypeMirror> computeConditionalExpression(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    ConditionalExpressionTree cet = (ConditionalExpressionTree) parent.getLeaf();

    if (cet.getCondition() == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.BOOLEAN));
    }

    if (cet.getTrueExpression() == error || cet.getFalseExpression() == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return resolveType(types, info, parent.getParentPath(), cet, offset, null, null);
    }

    return null;
  }
예제 #12
0
 /**
  * Given a TreePath, walks up the tree until it finds a node of the given type and returns the
  * path from that node to the top-level node in the path (typically a {@code
  * CompilationUnitTree}).
  */
 public static <T> TreePath findPathFromEnclosingNodeToTopLevel(TreePath path, Class<T> klass) {
   while (path != null && !(klass.isInstance(path.getLeaf()))) {
     path = path.getParentPath();
   }
   return path;
 }