protected void collectParamComments(Function f) {
   for (Arg arg : f.getArgs()) {
     arg.moveAllCommentsBefore();
     TypeRef argType = arg.getValueType();
     if (argType != null) {
       if (!result.config.noComments) {
         argType.moveAllCommentsBefore();
         arg.addToCommentBefore(argType.getCommentBefore());
       }
       argType.stripDetails();
     }
     if (arg.getCommentBefore() != null) {
       if (!result.config.noComments)
         f.addToCommentBefore(
             "@param " + arg.getName() + " " + Element.cleanComment(arg.getCommentBefore()));
       arg.stripDetails();
     }
   }
 }
 String getFileCommentContent(File file, Element e) {
   if (file != null) {
     String path = result.config.relativizeFileForSourceComments(file.getAbsolutePath());
     String inCategoryStr = "";
     if (e instanceof Function) {
       Function fc = (Function) e;
       Struct parent;
       if (fc.getType() == Type.ObjCMethod
           && ((parent = as(fc.getParentElement(), Struct.class)) != null)
           && (parent.getCategoryName() != null)) {
         inCategoryStr = "from " + parent.getCategoryName() + " ";
       }
     }
     return "<i>"
         + inCategoryStr
         + "native declaration : "
         + path
         + (e == null || e.getElementLine() < 0 ? "" : ":" + e.getElementLine())
         + "</i>";
   } else if (e != null && e.getElementLine() >= 0) {
     return "<i>native declaration : <input>:" + e.getElementLine() + "</i>";
   }
   return null;
 }
  public static synchronized Pair<List<Pair<Function, String>>, Set<String>>
      getMethodsAndTheirSignatures(Class<?> originalLib) {
    if (cachedForcedMethodsAndTheirSignatures == null)
      cachedForcedMethodsAndTheirSignatures =
          new HashMap<Class<?>, Pair<List<Pair<Function, String>>, Set<String>>>();

    Pair<List<Pair<Function, String>>, Set<String>> pair =
        cachedForcedMethodsAndTheirSignatures.get(originalLib);
    if (pair == null) {
      pair =
          new Pair<List<Pair<Function, String>>, Set<String>>(
              new ArrayList<Pair<Function, String>>(), new HashSet<String>());
      for (Method m : originalLib.getDeclaredMethods()) {
        Function f = Function.fromMethod(m);
        String sig = f.computeSignature(Function.SignatureType.JavaStyle);
        // if (m.getDeclaringClass().equals(NSObject.class) && f.getName().equals("as")) {
        //	Declaration
        // }
        pair.getFirst().add(new Pair<Function, String>(f, sig));
        pair.getSecond().add(sig);
      }
    }
    return pair;
  }
  @Override
  public void visitFunction(Function function) {
    super.visitFunction(function);
    Element parent = function.getParentElement();
    if (parent != null) {
      if (parent instanceof FunctionSignature) return;
      if (parent instanceof Struct) {
        Struct parentStruct = (Struct) parent;
        switch (parentStruct.getType()) {
          case CPPClass:
            //						if (config.genCPlusPlus)
            //							break;
          case JavaClass:
          case JavaInterface:
          case ObjCClass:
          case ObjCProtocol:
          case CStruct:
            return;
        }
      }
    }

    getList(functionsByLibrary, getLibrary(function)).add(function);
  }
  void addConstructor(Struct s, Function f) {
    Identifier structName = getActualTaggedTypeName(s);

    f.setName(structName);
    s.addDeclaration(f);
  }
  public void convertFunction(
      Function function,
      Signatures signatures,
      boolean isCallback,
      final DeclarationsHolder out,
      final Identifier libraryClassName,
      int iConstructor) {
    if (result.config.functionsAccepter != null && !result.config.functionsAccepter.adapt(function))
      return;

    // if (function.findParentOfType(Template))
    String library = result.getLibrary(function);
    Identifier functionName = function.getName();
    boolean isMethod = function.getParentElement() instanceof Struct;
    if (functionName == null || isCallback) {
      if (function.getParentElement() instanceof FunctionSignature)
        functionName = ident(result.config.callbackInvokeMethodName);
      else return;
    }
    if (function.getParentElement() instanceof FriendDeclaration) return;

    String n = functionName.toString();
    if (n.contains("<") || n.startsWith("~")) return;

    if (result.config.beautifyNames) functionName = ident(result.typeConverter.beautify(n, false));

    functionName = result.typeConverter.getValidJavaMethodName(functionName);
    if (functionName == null) return;

    // if (functionName.equals("operator"))
    //    functionName

    String sig = function.computeSignature(SignatureType.JavaStyle);

    DeclarationsHolder objOut =
        result.config.reification && !isCallback && !isMethod
            ? new DeclarationsHolder() {

              @Override
              public void addDeclaration(Declaration d) {
                out.addDeclaration(d);
                if (d instanceof Function) {
                  Function f = (Function) d;
                  List<Arg> args = f.getArgs();
                  List<TypeRef> trs = new ArrayList<TypeRef>(2);
                  trs.add(f.getValueType());
                  if (!args.isEmpty()) trs.add(args.get(0).getValueType());

                  for (TypeRef tr : trs) {
                    if (tr instanceof SimpleTypeRef) {
                      Identifier id = ((SimpleTypeRef) tr).getName();
                      if (result.isFakePointer(id)) {
                        result.addFunctionReifiableInFakePointer(id, libraryClassName, f);
                      }
                    }
                  }
                }
              }

              @Override
              public List<Declaration> getDeclarations() {
                return out.getDeclarations();
              }
            }
            : out;

    try {
      convertFunction(
          function,
          signatures,
          isCallback,
          objOut,
          libraryClassName,
          sig,
          functionName,
          library,
          iConstructor);
    } catch (UnsupportedConversionException ex) {
      Declaration d = skipDeclaration(function);
      if (d != null) {
        d.addToCommentBefore(ex.toString());
        out.addDeclaration(d);
      }
    }
  }