docs: @Override
      protected String toStringInternal(final boolean useSimpleNames) {
          final StringBuilder buf = new StringBuilder();
          // Only append the base class name if not using simple names, or if there are no suffixes
          if (!useSimpleNames || suffixes.isEmpty()) {
              buf.append(useSimpleNames ? ClassInfo.getSimpleName(className) : className);
              if (!typeArguments.isEmpty()) {
                  buf.append('<');
                  for (int i = 0; i < typeArguments.size(); i++) {
                      if (i > 0) {
                          buf.append(", ");
                      }
                      buf.append(useSimpleNames ? typeArguments.get(i).toStringWithSimpleNames()
                              : typeArguments.get(i).toString());
                  }
                  buf.append('>');
              }
          }
          // Only use the last suffix if using simple names
          for (int i = useSimpleNames && !suffixes.isEmpty() ? suffixes.size() - 1 : 0; i < suffixes.size(); i++) {
              if (!useSimpleNames) {
                  // Use '.' before each suffix in the toString() representation, since that is
                  // how the class name will be shown in Java, e.g. OuterClass<T>.InnerClass
                  buf.append('.');
              }
              buf.append(suffixes.get(i));
              final List<TypeArgument> suffixTypeArgs = suffixTypeArguments.get(i);
              if (!suffixTypeArgs.isEmpty()) {
                  buf.append('<');
                  for (int j = 0; j < suffixTypeArgs.size(); j++) {
                      if (j > 0) {
                          buf.append(", ");
                      }
                      buf.append(useSimpleNames ? suffixTypeArgs.get(j).toStringWithSimpleNames()
                              : suffixTypeArgs.get(j).toString());
                  }
                  buf.append('>');
              }
          }
          return buf.toString();
      }