private static List<? extends TypeMirror> computeEnhancedForLoop(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    EnhancedForLoopTree efl = (EnhancedForLoopTree) parent.getLeaf();

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

    TypeMirror argument =
        info.getTrees()
            .getTypeMirror(
                new TreePath(new TreePath(parent, efl.getVariable()), efl.getVariable().getType()));

    if (argument == null) return null;

    if (argument.getKind().isPrimitive()) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getTypes().getArrayType(argument));
    }

    TypeElement iterable = info.getElements().getTypeElement("java.lang.Iterable"); // NOI18N
    if (iterable == null) {
      return null;
    }

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

    return Collections.singletonList(info.getTypes().getDeclaredType(iterable, argument));
  }
  @Override
  public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) {
    Tree t = treePath.getLeaf();
    JTextComponent editor = EditorRegistry.lastFocusedComponent();
    Document doc = editor.getDocument();

    SourcePositions sp = info.getTrees().getSourcePositions();
    int start = (int) sp.getStartPosition(info.getCompilationUnit(), t);
    int end = (int) sp.getEndPosition(info.getCompilationUnit(), t);
    int endLine = info.getText().indexOf("\n", start);
    String line = info.getText().substring(start, endLine).trim();

    if (!Suppression.isSuppressed(line)) {
      return Collections.<ErrorDescription>singletonList(
          ErrorDescriptionFactory.createErrorDescription(
              Severity.HINT,
              ERROR_DESCRIPTION,
              createFixes(doc, start, endLine),
              info.getFileObject(),
              start,
              end));
    } else {
      return null;
    }
  }
    private void analyzePatternsImpl(CompilationInfo javac) {
      checkState(1);
      String clsname = javaFile.getName();
      TypeElement clselm = null;
      for (TypeElement top : javac.getTopLevelElements()) {
        if (clsname.contentEquals(top.getSimpleName())) {
          clselm = top;
        }
      }

      if (clselm == null) {
        isCancelled = true;
        error =
            new NotifyDescriptor.Message(
                NbBundle.getMessage(
                    GenerateBeanInfoAction.class,
                    "MSG_FileWitoutTopLevelClass",
                    clsname,
                    FileUtil.getFileDisplayName(javaFile)),
                NotifyDescriptor.ERROR_MESSAGE);
        return;
      }

      PatternAnalyser pa = new PatternAnalyser(javaFile, null, true);
      pa.analyzeAll(javac, clselm);
      // XXX analyze also superclasses here
      try {
        bia = new BiAnalyser(pa, javac);
      } catch (Exception ex) {
        isCancelled = true;
        Exceptions.printStackTrace(ex);
      }
    }
  private static List<? extends TypeMirror> computeReturn(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    ReturnTree rt = (ReturnTree) parent.getLeaf();

    if (rt.getExpression() == error) {
      TreePath method = findMethod(parent);

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

      Element el = info.getTrees().getElement(method);

      if (el == null || el.getKind() != ElementKind.METHOD) {
        return null;
      }

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

      return Collections.singletonList(((ExecutableElement) el).getReturnType());
    }

    return null;
  }
  private static List<? extends TypeMirror> computeArrayType(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    types.add(ElementKind.CLASS);

    return Collections.singletonList(
        info.getElements().getTypeElement("java.lang.Object").asType());
  }
  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> 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> 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 List<? extends TypeMirror> computeAssert(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    AssertTree at = (AssertTree) parent.getLeaf();

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

    if (at.getCondition() == error) {
      return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.BOOLEAN));
    }

    if (at.getDetail() == error) {
      return Collections.singletonList(
          info.getElements().getTypeElement("java.lang.Object").asType());
    }

    return null;
  }
  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;
  }
 /* (non-Javadoc)
  * @see com.sun.source.util.TreeScanner#visitClass(com.sun.source.tree.ClassTree, java.lang.Object)
  */
 @Override
 public Void visitClass(ClassTree t, Void v) {
   Element el = info.getTrees().getElement(getCurrentPath());
   if (el == null) {
     StatusDisplayer.getDefault().setStatusText("Cannot resolve class!");
   } else {
     typeElement = (TypeElement) el;
   }
   return null;
 }
  private static List<? extends TypeMirror> computeAssignment(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    AssignmentTree at = (AssignmentTree) parent.getLeaf();
    TypeMirror type = null;

    if (at.getVariable() == error) {
      type = info.getTrees().getTypeMirror(new TreePath(parent, at.getExpression()));

      if (type != null) {
        // anonymous class?
        type = org.netbeans.modules.java.hints.errors.Utilities.convertIfAnonymous(type);

        if (type.getKind() == TypeKind.EXECUTABLE) {
          // TODO: does not actualy work, attempt to solve situations like:
          // t = Collections.emptyList()
          // t = Collections.<String>emptyList();
          // see also testCreateFieldMethod1 and testCreateFieldMethod2 tests:
          type = ((ExecutableType) type).getReturnType();
        }
      }
    }

    if (at.getExpression() == error) {
      type = info.getTrees().getTypeMirror(new TreePath(parent, at.getVariable()));
    }

    // class or field:
    if (type == null) {
      if (ErrorHintsProvider.ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
        ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "offset=" + offset);
        ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "errorTree=" + error);
        ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "type=null");
      }

      return null;
    }

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

    return Collections.singletonList(type);
  }
  private static List<? extends TypeMirror> computeReferenceType(
      Set<ElementKind> types, CompilationInfo info, Tree expression, Tree error, String type) {
    if (expression == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getElements().getTypeElement(type).asType());
    }

    return null;
  }
  private static List<? extends TypeMirror> computePrimitiveType(
      Set<ElementKind> types, CompilationInfo info, Tree expression, Tree error, TypeKind kind) {
    if (expression == error) {
      types.add(ElementKind.PARAMETER);
      types.add(ElementKind.LOCAL_VARIABLE);
      types.add(ElementKind.FIELD);

      return Collections.singletonList(info.getTypes().getPrimitiveType(kind));
    }

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

    if (nat.getType() == error) {
      types.add(ElementKind.CLASS);
      types.add(ElementKind.ENUM);
      types.add(ElementKind.INTERFACE);

      return null;
    }

    for (Tree dimension : nat.getDimensions()) {
      if (dimension == error) {
        types.add(ElementKind.PARAMETER);
        types.add(ElementKind.LOCAL_VARIABLE);
        types.add(ElementKind.FIELD);

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

    for (Tree init : nat.getInitializers()) {
      if (init == error) {
        TypeMirror whole = info.getTrees().getTypeMirror(parent);

        if (whole == null || whole.getKind() != TypeKind.ARRAY) return null;

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

        return Collections.singletonList(((ArrayType) whole).getComponentType());
      }
    }

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

    if (tree.getQualifiedIdentifier() == error) {
      types.add(ElementKind.ANNOTATION_TYPE);
      types.add(ElementKind.CLASS);
      types.add(ElementKind.ENUM);
      types.add(ElementKind.INTERFACE);

      return Collections.singletonList(
          info.getElements().getTypeElement("java.lang.Object").asType());
    }

    return null;
  }
  private static List<? extends TypeMirror> computeMemberSelect(
      Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) {
    // class or field:
    MemberSelectTree ms = (MemberSelectTree) parent.getLeaf();
    final TypeElement jlObject = info.getElements().getTypeElement("java.lang.Object");

    if (jlObject != null // may happen if the platform is broken
        && !"class"
            .equals(
                ms.getIdentifier()
                    .toString())) { // we obviously should not propose "Create Field" for
      // unknown.class:
      types.add(ElementKind.FIELD);
      types.add(ElementKind.CLASS);
      return Collections.singletonList(jlObject.asType());
    }

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

    if (bt.getLeftOperand() == error) {
      typeToResolve = new TreePath(parent, bt.getRightOperand());
    }

    if (bt.getRightOperand() == error) {
      typeToResolve = new TreePath(parent, bt.getLeftOperand());
    }

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

    return typeToResolve != null
        ? Collections.singletonList(info.getTrees().getTypeMirror(typeToResolve))
        : 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;
  }
  private static List<? extends TypeMirror> computeMethod(
      Set<ElementKind> types,
      CompilationInfo info,
      TreePath parent,
      TypeMirror[] typeParameterBound,
      Tree error,
      int offset) {
    // class or field:
    // check the error is in the body:
    // #92419: check for abstract method/method without body:
    MethodTree mt = (MethodTree) parent.getLeaf();

    if (mt.getReturnType() == error) {
      types.add(ElementKind.CLASS);
      types.add(ElementKind.INTERFACE);
      types.add(ElementKind.ENUM);
    }

    List<? extends ExpressionTree> throwList = mt.getThrows();
    if (throwList != null && !throwList.isEmpty()) {
      for (ExpressionTree t : throwList) {
        if (t == error) {
          types.add(ElementKind.CLASS);
          typeParameterBound[0] = info.getElements().getTypeElement("java.lang.Exception").asType();
          break;
        }
      }
    }

    if (mt.getBody() == null) {
      return null;
    }

    try {
      Document doc = info.getDocument();

      if (doc != null) { // XXX
        int bodyStart =
            Utilities.findBodyStart(
                parent.getLeaf(),
                info.getCompilationUnit(),
                info.getTrees().getSourcePositions(),
                doc);
        int bodyEnd =
            (int)
                info.getTrees()
                    .getSourcePositions()
                    .getEndPosition(info.getCompilationUnit(), parent.getLeaf());

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

        if (bodyStart <= offset && offset <= bodyEnd)
          return Collections.singletonList(
              info.getElements().getTypeElement("java.lang.Object").asType());
      }
    } catch (IOException ex) {
      Logger.getLogger("global").log(Level.INFO, ex.getMessage(), ex);
    }

    return null;
  }
Esempio n. 21
0
      @Override
      public void run(final CompilationInfo parameter) {
        TypeElement clazz = parameter.getElements().getTypeElement(annotation.getClassName());

        if (clazz == null) {
          // XXX: log
          return;
        }

        Element resolved = null;

        if (annotation instanceof FieldAnnotation) {
          FieldAnnotation fa = (FieldAnnotation) annotation;

          for (VariableElement var : ElementFilter.fieldsIn(clazz.getEnclosedElements())) {
            if (var.getSimpleName().contentEquals(fa.getFieldName())) {
              resolved = var;
              break;
            }
          }
        } else if (annotation instanceof MethodAnnotation) {
          MethodAnnotation ma = (MethodAnnotation) annotation;

          for (ExecutableElement method : ElementFilter.methodsIn(clazz.getEnclosedElements())) {
            if (method.getSimpleName().contentEquals(ma.getMethodName())) {
              if (ma.getMethodSignature()
                  .equals(SourceUtils.getJVMSignature(ElementHandle.create(method))[2])) {
                resolved = method;
                break;
              }
            }
          }
        } else if (annotation instanceof ClassAnnotation) {
          resolved = clazz;
        }

        if (resolved == null) {
          // XXX: log
          return;
        }

        final Element resolvedFin = resolved;

        new CancellableTreePathScanner<Void, Void>() {
          @Override
          public Void visitVariable(VariableTree node, Void p) {
            if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) {
              int[] span = parameter.getTreeUtilities().findNameSpan(node);

              if (span != null) {
                result[0] = span[0];
                result[1] = span[1];
              }
            }

            return super.visitVariable(node, p);
          }

          @Override
          public Void visitMethod(MethodTree node, Void p) {
            if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) {
              int[] span = parameter.getTreeUtilities().findNameSpan(node);

              if (span != null) {
                result[0] = span[0];
                result[1] = span[1];
              }
            }

            return super.visitMethod(node, p);
          }

          @Override
          public Void visitClass(ClassTree node, Void p) {
            if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) {
              int[] span = parameter.getTreeUtilities().findNameSpan(node);

              if (span != null) {
                result[0] = span[0];
                result[1] = span[1];
              }
            }

            return super.visitClass(node, p);
          }
        }.scan(parameter.getCompilationUnit(), null);
      }
  public static List<? extends TypeMirror> resolveType(
      Set<ElementKind> types,
      CompilationInfo info,
      TreePath currentPath,
      Tree unresolved,
      int offset,
      TypeMirror[] typeParameterBound,
      int[] numTypeParameters) {
    switch (currentPath.getLeaf().getKind()) {
      case METHOD:
        return computeMethod(types, info, currentPath, typeParameterBound, unresolved, offset);
      case MEMBER_SELECT:
        return computeMemberSelect(types, info, currentPath, unresolved, offset);
      case ASSIGNMENT:
        return computeAssignment(types, info, currentPath, unresolved, offset);
      case ENHANCED_FOR_LOOP:
        return computeEnhancedForLoop(types, info, currentPath, unresolved, offset);
      case ARRAY_ACCESS:
        return computeArrayAccess(types, info, currentPath, unresolved, offset);
      case VARIABLE:
        return computeVariableDeclaration(types, info, currentPath, unresolved, offset);
      case ASSERT:
        return computeAssert(types, info, currentPath, unresolved, offset);
      case PARENTHESIZED:
        return computeParenthesis(types, info, currentPath, unresolved, offset);
      case DO_WHILE_LOOP:
        return computePrimitiveType(
            types,
            info,
            ((DoWhileLoopTree) currentPath.getLeaf()).getCondition(),
            unresolved,
            TypeKind.BOOLEAN);
      case FOR_LOOP:
        return computePrimitiveType(
            types,
            info,
            ((ForLoopTree) currentPath.getLeaf()).getCondition(),
            unresolved,
            TypeKind.BOOLEAN);
      case IF:
        return computePrimitiveType(
            types,
            info,
            ((IfTree) currentPath.getLeaf()).getCondition(),
            unresolved,
            TypeKind.BOOLEAN);
      case WHILE_LOOP:
        return computePrimitiveType(
            types,
            info,
            ((WhileLoopTree) currentPath.getLeaf()).getCondition(),
            unresolved,
            TypeKind.BOOLEAN);
      case SYNCHRONIZED:
        return computeReferenceType(
            types,
            info,
            ((SynchronizedTree) currentPath.getLeaf()).getExpression(),
            unresolved,
            "java.lang.Object");
      case THROW:
        return computeReferenceType(
            types,
            info,
            ((ThrowTree) currentPath.getLeaf()).getExpression(),
            unresolved,
            "java.lang.Exception");
      case INSTANCE_OF:
        return computeReferenceType(
            types,
            info,
            ((InstanceOfTree) currentPath.getLeaf()).getExpression(),
            unresolved,
            "java.lang.Object");
      case SWITCH:
        // TODO: should consider also values in the cases?:
        return computePrimitiveType(
            types,
            info,
            ((SwitchTree) currentPath.getLeaf()).getExpression(),
            unresolved,
            TypeKind.INT);
      case EXPRESSION_STATEMENT:
        return Collections.singletonList(info.getTypes().getNoType(TypeKind.VOID));

      case RETURN:
        return computeReturn(types, info, currentPath, unresolved, offset);
      case TYPE_PARAMETER:
        return computeTypeParameter(types, info, currentPath, unresolved, offset);
      case PARAMETERIZED_TYPE:
        return computeParametrizedType(
            types, info, currentPath, unresolved, offset, typeParameterBound, numTypeParameters);
      case ANNOTATION_TYPE:
      case CLASS:
      case ENUM:
      case INTERFACE:
        return computeClass(types, info, currentPath, unresolved, offset);

      case CONDITIONAL_EXPRESSION:
        return computeConditionalExpression(types, info, currentPath, unresolved, offset);

      case NEW_ARRAY:
        return computeNewArray(types, info, currentPath, unresolved, offset);

      case METHOD_INVOCATION:
        return computeMethodInvocation(types, info, currentPath, unresolved, offset);

      case NEW_CLASS:
        return computeNewClass(types, info, currentPath, unresolved, offset);

      case POSTFIX_INCREMENT:
      case POSTFIX_DECREMENT:
      case PREFIX_INCREMENT:
      case PREFIX_DECREMENT:
      case UNARY_PLUS:
      case UNARY_MINUS:
      case BITWISE_COMPLEMENT:
      case LOGICAL_COMPLEMENT:
        return computeUnary(types, info, currentPath, unresolved, offset);

      case MULTIPLY:
      case DIVIDE:
      case REMAINDER:
      case PLUS:
      case MINUS:
      case LEFT_SHIFT:
      case RIGHT_SHIFT:
      case UNSIGNED_RIGHT_SHIFT:
      case LESS_THAN:
      case GREATER_THAN:
      case LESS_THAN_EQUAL:
      case GREATER_THAN_EQUAL:
      case EQUAL_TO:
      case NOT_EQUAL_TO:
      case AND:
      case XOR:
      case OR:
      case CONDITIONAL_AND:
      case CONDITIONAL_OR:
        return computeBinaryOperator(types, info, currentPath, unresolved, offset);

      case MULTIPLY_ASSIGNMENT:
      case DIVIDE_ASSIGNMENT:
      case REMAINDER_ASSIGNMENT:
      case PLUS_ASSIGNMENT:
      case MINUS_ASSIGNMENT:
      case LEFT_SHIFT_ASSIGNMENT:
      case RIGHT_SHIFT_ASSIGNMENT:
      case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
      case AND_ASSIGNMENT:
      case XOR_ASSIGNMENT:
      case OR_ASSIGNMENT:
        // XXX: return computeCompoundAssignment(types, info, currentPath, unresolved, offset);
        return null;

      case ARRAY_TYPE:
        return computeArrayType(types, info, currentPath, unresolved, offset);

      case IMPORT:
        return computeImport(types, info, currentPath, unresolved, offset);

      case BLOCK:
      case BREAK:
      case CATCH:
      case COMPILATION_UNIT:
      case CONTINUE:
      case IDENTIFIER:
      case TYPE_CAST:
      case TRY:
      case EMPTY_STATEMENT:
      case PRIMITIVE_TYPE:
      case LABELED_STATEMENT:
      case MODIFIERS:
      case ERRONEOUS:
      case OTHER:
      case INT_LITERAL:
      case LONG_LITERAL:
      case FLOAT_LITERAL:
      case DOUBLE_LITERAL:
      case BOOLEAN_LITERAL:
      case CHAR_LITERAL:
      case STRING_LITERAL:
      case NULL_LITERAL:
        // ignored:
        return null;

      case CASE:
      case ANNOTATION:
      case UNBOUNDED_WILDCARD:
      case EXTENDS_WILDCARD:
      case SUPER_WILDCARD:
        // XXX: currently unhandled
        return null;

      default:
        // should not happen unless set of Tree.Kind changes:
        return null;
    }
  }