/**
   * @param node the ast node in question
   * @param decls the list to be populated. adding the declaration(s) corresponding to the ast node
   *     to this list.
   */
  @SuppressWarnings("unchecked")
  protected void getDeclarations(ASTNode node, List<Declaration> decls) {
    if (node == null) return;
    IBinding binding = null;
    switch (node.getNodeType()) {
      case ASTNode.FIELD_DECLARATION:
        final List<VariableDeclarationFragment> fragments =
            ((org.aspectj.org.eclipse.jdt.core.dom.FieldDeclaration) node).fragments();
        for (VariableDeclarationFragment frag : fragments) {
          final IBinding fieldBinding = frag.resolveBinding();
          final EclipseDeclarationImpl decl;
          if (fieldBinding != null) decl = Factory.createDeclaration(fieldBinding, this);
          else {
            decl = Factory.createDeclaration(frag, getFileForNode(frag), this);
          }
          if (decl != null) decls.add(decl);
        }
        return;

      case ASTNode.ENUM_CONSTANT_DECLARATION:
        binding =
            ((org.aspectj.org.eclipse.jdt.core.dom.EnumConstantDeclaration) node).resolveVariable();
        break;
      case ASTNode.METHOD_DECLARATION:
        binding = ((org.aspectj.org.eclipse.jdt.core.dom.MethodDeclaration) node).resolveBinding();
        break;
      case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
        binding = ((AnnotationTypeMemberDeclaration) node).resolveBinding();
        break;
      case ASTNode.TYPE_DECLARATION:
      case ASTNode.ANNOTATION_TYPE_DECLARATION:
      case ASTNode.ENUM_DECLARATION:
        binding = ((AbstractTypeDeclaration) node).resolveBinding();
        break;
      case ASTNode.SINGLE_VARIABLE_DECLARATION:
        // Need to create the declaration with the ast node, not the binding
        break;
      case ASTNode.PACKAGE_DECLARATION:
        binding = ((org.aspectj.org.eclipse.jdt.core.dom.PackageDeclaration) node).resolveBinding();
        break;
      default:
        throw new UnsupportedOperationException(
            "unknown node type: " + node.getNodeType()); // $NON-NLS-1$
    }

    final EclipseDeclarationImpl decl;
    if (binding != null) decl = Factory.createDeclaration(binding, this);
    else {
      decl = Factory.createDeclaration(node, getFileForNode(node), this);
    }
    if (decl != null) decls.add(decl);

    return;
  }
  /**
   * @return the list of all named type declarations in the compilation units associated with this
   *     environment - usually just one compilation unit, except in batch mode where it will be all
   *     compilation units in the build. This implementation is different from the API specification
   *     in that it does not return all included source types in the universe.
   */
  public Collection<TypeDeclaration> getTypeDeclarations() {
    final List<ITypeBinding> bindings = getTypeBindings();
    if (bindings.isEmpty()) return Collections.emptyList();
    final List<TypeDeclaration> mirrorDecls = new ArrayList<TypeDeclaration>(bindings.size());

    for (ITypeBinding binding : bindings) {
      final TypeDeclaration mirrorDecl = Factory.createReferenceType(binding, this);
      if (mirrorDecl != null) mirrorDecls.add(mirrorDecl);
    }

    return mirrorDecls;
  }
  // does not generate dependencies
  public TypeDeclaration getTypeDeclaration(String name) {
    if (name == null || name.length() == 0) return null;

    // get rid of the generics parts.
    final int index = name.indexOf('<');
    if (index != -1) name = name.substring(0, index);

    ITypeBinding typeBinding = null;
    try {
      typeBinding = getTypeDefinitionBindingFromName(name);
    } catch (ArrayIndexOutOfBoundsException e) {
      // https://bugs.eclipse.org/bugs/show_bug.cgi?id=133947
      // if the name is invalid, JDT can throw an ArrayIndexOutOfBoundsException
      // We'll ignore this and return null to the user
      AptPlugin.log(e, "Unable to get type definition binding for: " + name); // $NON-NLS-1$
    }

    return Factory.createReferenceType(typeBinding, this);
  }