@Restricted(DoNotUse.class) // accessed via REST API
 public HttpResponse doGenerateSnippet(StaplerRequest req, @QueryParameter String json)
     throws Exception {
   // TODO JENKINS-31458 is there not an easier way to do this?
   JSONObject jsonO = JSONObject.fromObject(json);
   Jenkins j = Jenkins.getActiveInstance();
   Class<?> c = j.getPluginManager().uberClassLoader.loadClass(jsonO.getString("stapler-class"));
   StepDescriptor descriptor = (StepDescriptor) j.getDescriptor(c.asSubclass(Step.class));
   Object o;
   try {
     o = descriptor.newInstance(req, jsonO);
   } catch (RuntimeException x) { // e.g. IllegalArgumentException
     return HttpResponses.plainText(Functions.printThrowable(x));
   }
   try {
     String groovy = object2Groovy(o);
     if (descriptor.isAdvanced()) {
       String warning = Messages.Snippetizer_this_step_should_not_normally_be_used_in();
       groovy = "// " + warning + "\n" + groovy;
     }
     return HttpResponses.plainText(groovy);
   } catch (UnsupportedOperationException x) {
     Logger.getLogger(CpsFlowExecution.class.getName())
         .log(Level.WARNING, "failed to render " + json, x);
     return HttpResponses.plainText(x.getMessage());
   }
 }
 private static void generateStepHelp(StepDescriptor d, PrintWriter pw) throws Exception {
   pw.println("<h2><code>" + d.getFunctionName() + "</code>: " + d.getDisplayName() + "</h2>");
   try {
     generateHelp(DescribableHelper.schemaFor(d.clazz), pw, 3);
   } catch (Exception x) {
     pw.println("<pre><code>" + /*Util.escape(Functions.printThrowable(x))*/ x + "</code></pre>");
   }
 }
 @Restricted(DoNotUse.class)
 public Collection<? extends StepDescriptor> getStepDescriptors(boolean advanced) {
   TreeSet<StepDescriptor> t = new TreeSet<StepDescriptor>(new StepDescriptorComparator());
   for (StepDescriptor d : StepDescriptor.all()) {
     if (d.isAdvanced() == advanced) {
       t.add(d);
     }
   }
   return t;
 }
 static String object2Groovy(Object o) throws UnsupportedOperationException {
   Class<? extends Object> clazz = o.getClass();
   for (StepDescriptor d : StepDescriptor.all()) {
     if (d.clazz.equals(clazz)) {
       StringBuilder b = new StringBuilder(d.getFunctionName());
       Step step = (Step) o;
       Map<String, Object> args = new TreeMap<String, Object>(d.defineArguments(step));
       boolean first = true;
       boolean singleMap = args.size() == 1 && args.values().iterator().next() instanceof Map;
       for (Map.Entry<String, Object> entry : args.entrySet()) {
         if (first) {
           first = false;
           if (d.takesImplicitBlockArgument() || singleMap) {
             b.append('(');
           } else {
             b.append(' ');
           }
         } else {
           b.append(", ");
         }
         String key = entry.getKey();
         if (args.size() > 1 || !isDefaultKey(step, key)) {
           b.append(key).append(": ");
         }
         render(b, entry.getValue());
       }
       if (d.takesImplicitBlockArgument()) {
         if (!args.isEmpty()) {
           b.append(')');
         }
         b.append(" {\n    // some block\n}");
       } else if (singleMap) {
         b.append(')');
       } else if (args.isEmpty()) {
         b.append("()");
       }
       return b.toString();
     }
   }
   throw new UnsupportedOperationException("Unknown step " + clazz);
 }
 @Override
 public int compare(StepDescriptor o1, StepDescriptor o2) {
   return o1.getFunctionName().compareTo(o2.getFunctionName());
 }