public TextBuffer addGenericTypeTokens(int index, String text, VarType type) {
    if (!type.isGeneric()) {
      return this;
    }

    GenericType genType = (GenericType) type;
    index += text.indexOf("<") + 1;
    int offset = 0;
    for (int i = 0; i < genType.getArguments().size(); i++) {
      VarType t = genType.getArguments().get(i);

      if (t == null) {
        offset += 1; // skip '?'
      } else if (t.isGeneric()) {
        GenericType gt = (GenericType) t;
        switch (gt.getWildcard()) {
          case GenericType.WILDCARD_EXTENDS:
            offset += 10; // skip "? extends "
            break;
          case GenericType.WILDCARD_SUPER:
            offset += 8; // skip "? super "
            break;
        }

        String name = GenericMain.getGenericCastTypeName(gt);
        if (gt.type == CodeType.OBJECT) {
          addAllClassTokens(index + offset, name, gt.value);
        }

        addGenericTypeTokens(index + offset, name, gt);
        offset += name.length();
      } else {
        if (t.type == CodeType.OBJECT) {
          addTypeNameToken(t, index + offset);
        }

        offset += ExprProcessor.getCastTypeName(t).length();
      }

      offset += 2; // skip ", "
    }

    return this;
  }
Allows to connect text with resulting lines

@author egor
src/org/jetbrains/java/decompiler/util/TextBuffer.java