docs: public static Object generate(Object service, String groupName, Map<String, String> commands, String suffix) throws Exception {
          // generate class with unique name
          CtClass ctClass = POOL.makeClass(AbstractEquinoxCommandProvider.class.getName() + suffix);
          try {
              Set<String> commandHelps = new HashSet<String>();
              if (!ctClass.isFrozen()) {
                  // set superclass
                  CtClass abstractCtClass = POOL.getCtClass(AbstractEquinoxCommandProvider.class.getName());
                  ctClass.setSuperclass(abstractCtClass);
  
                  // add constructor
                  CtClass serviceCtClass = POOL.getCtClass(Object.class.getName());
                  CtClass stringCtClass = POOL.getCtClass(String.class.getName());
                  CtClass setCtClass = POOL.getCtClass(Set.class.getName());
                  CtConstructor ctConstructor = new CtConstructor(new CtClass[]{
                          serviceCtClass, stringCtClass, setCtClass
                  }, ctClass);
                  ctConstructor.setModifiers(Modifier.PUBLIC);
                  ctConstructor.setBody("super($1, $2, $3);");
                  ctClass.addConstructor(ctConstructor);
  
                  // add method for each command
                  CtClass interpreterCtClass = POOL.getCtClass(CommandInterpreter.class.getName());
                  Set<String> names = commands.keySet();
                  for (String name : names) {
                      if (isMethodAvailable(service, name)) {
                          CtMethod ctMethod = new CtMethod(CtClass.voidType, "_" + name, new CtClass[]{
                                  interpreterCtClass
                          }, ctClass);
                          ctMethod.setModifiers(Modifier.PUBLIC);
                          ctMethod.setBody("runCommand(\"" + name + "\", $1);");
                          ctClass.addMethod(ctMethod);
  
                          commandHelps.add(commands.get(name));
                      }
                  }
              }
  
              // create new instance
              Class<?> aClass = ctClass.toClass(EquinoxCommandProviderGenerator.class.getClassLoader());
              Constructor<?> constructor = aClass.getConstructor(Object.class, String.class, Set.class);
              return constructor.newInstance(service, groupName, commandHelps);
          } catch (Exception e) {
              ctClass.detach();
              throw e;
          }
      }