public void writeClass(StructClass cl, TextBuffer buffer) throws IOException {
    ClassNode root = mapRootClasses.get(cl.qualifiedName);
    if (root.type != ClassNode.CLASS_ROOT) {
      return;
    }

    boolean packageInfo = cl.isSynthetic() && "package-info".equals(root.simpleName);
    boolean moduleInfo = cl.hasModifier(CodeConstants.ACC_MODULE) && cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);

    DecompilerContext.getLogger().startReadingClass(cl.qualifiedName);
    try {
      ImportCollector importCollector = new ImportCollector(root);
      DecompilerContext.startClass(importCollector);

      if (packageInfo) {
        ClassWriter.packageInfoToJava(cl, buffer);

        importCollector.writeImports(buffer, false);
      }
      else if (moduleInfo) {
        TextBuffer moduleBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
        ClassWriter.moduleInfoToJava(cl, moduleBuffer);

        importCollector.writeImports(buffer, true);

        buffer.append(moduleBuffer);
      }
      else {
        new LambdaProcessor().processClass(root);

        // add simple class names to implicit import
        addClassNameToImport(root, importCollector);

        // build wrappers for all nested classes (that's where actual processing takes place)
        initWrappers(root);

        new NestedClassProcessor().processClass(root, root);

        new NestedMemberAccess().propagateMemberAccess(root);

        TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
        new ClassWriter().classToJava(root, classBuffer, 0, null);

        int index = cl.qualifiedName.lastIndexOf('/');
        if (index >= 0) {
          String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
          buffer.append("package ").append(packageName).append(';').appendLineSeparator().appendLineSeparator();
        }

        importCollector.writeImports(buffer, true);

        int offsetLines = buffer.countLines();

        buffer.append(classBuffer);

        if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
          BytecodeSourceMapper mapper = DecompilerContext.getBytecodeSourceMapper();
          mapper.addTotalOffset(offsetLines);
          if (DecompilerContext.getOption(IFernflowerPreferences.DUMP_ORIGINAL_LINES)) {
            buffer.dumpOriginalLineNumbers(mapper.getOriginalLinesMapping());
          }
          if (DecompilerContext.getOption(IFernflowerPreferences.UNIT_TEST_MODE)) {
            buffer.appendLineSeparator();
            mapper.dumpMapping(buffer, true);
          }
        }
      }
    }
    finally {
      destroyWrappers(root);
      DecompilerContext.getLogger().endReadingClass();
    }
  }
public void writeClass(StructClass cl, TextBuffer buffer)