public StringBuilder getQualifiedName(StringBuilder b, boolean generic) {
      if (getEnclosingType() instanceof ClassRef) {
        getEnclosingType().getQualifiedName(b, generic).append('$');
      } else if (getEnclosingType() instanceof NamespaceRef) {
        getEnclosingType().getQualifiedName(b, generic).append('.');
      }
      b.append(ident.simpleName);
      if (generic && ident.templateArguments != null) {
        int args = 0;
        for (int i = 0, n = ident.templateArguments.length; i < n; i++) {
          TemplateArg arg = ident.templateArguments[i];
          if (!(arg instanceof TypeRef)) {
            continue;
          }

          if (args == 0) {
            b.append('<');
          } else {
            b.append(", ");
          }
          ((TypeRef) arg).getQualifiedName(b, generic);
          args++;
        }
        if (args > 0) {
          b.append('>');
        }
      }
      return b;
    }
    private boolean matchesArgs(Type[] parameterTypes, Annotation[][] anns, int offset) {
      int totalArgs = offset;
      for (int i = 0, n = templateArguments == null ? 0 : templateArguments.length; i < n; i++) {
        if (totalArgs >= parameterTypes.length) {
          return false;
        }

        Type paramType = parameterTypes[offset + i];

        TemplateArg arg = templateArguments[i];
        if (arg instanceof TypeRef) {
          if (!paramType.equals(Class.class)) {
            return false;
          }
        } else if (arg instanceof Constant) {
          try {
            getTypeClass(paramType).cast(((Constant) arg).value);
          } catch (ClassCastException ex) {
            return false;
          }
        }
        totalArgs++;
      }

      for (int i = 0, n = paramTypes == null ? 0 : paramTypes.length; i < n; i++) {
        if (totalArgs >= parameterTypes.length) {
          return false;
        }

        TypeRef paramType = paramTypes[i];
        Type parameterType = parameterTypes[totalArgs];
        if (!paramType.matches(parameterType, annotations(anns == null ? null : anns[i]))) {
          return false;
        }

        totalArgs++;
      }

      if (totalArgs != parameterTypes.length) {
        BridJ.error("Not enough args for " + this);
        return false;
      }

      return true;
    }
    public boolean matchesEnclosingType(Method method) {
      TypeRef et = getEnclosingType();
      if (et == null) {
        return true;
      }

      Annotations annotations = annotations(method);
      Class dc = method.getDeclaringClass();
      do {
        if (et.matches(dc, annotations)) {
          return true;
        }

        dc = dc.getSuperclass();
      } while (dc != null && dc != Object.class);

      return false;
    }