@Override
  public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
    TextBuffer buffer = new TextBuffer();

    tracer.addMapping(bytecode);

    if (classdef) {
      ClassNode child =
          DecompilerContext.getClassProcessor().getMapRootClasses().get(vartype.value);
      new ClassWriter().classToJava(child, buffer, indent, tracer);
    } else {
      String name = null;
      if (processor != null) {
        name = processor.getVarName(new VarVersionPaar(index, version));
      }

      if (definition) {
        if (processor != null
            && processor.getVarFinal(new VarVersionPaar(index, version))
                == VarTypeProcessor.VAR_FINALEXPLICIT) {
          buffer.append("final ");
        }
        buffer.append(ExprProcessor.getCastTypeName(getVartype())).append(" ");
      }
      buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name);
    }

    return buffer;
  }
  @Override
  public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
    tracer.addMapping(bytecode);

    if (exitType == EXIT_RETURN) {
      TextBuffer buffer = new TextBuffer("return");

      if (retType.type != CodeConstants.TYPE_VOID) {
        buffer.append(' ');
        ExprProcessor.getCastedExprent(value, retType, buffer, indent, false, tracer);
      }

      return buffer;
    } else {
      MethodWrapper method =
          (MethodWrapper) DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
      ClassNode node =
          ((ClassNode) DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE));

      if (method != null && node != null) {
        StructExceptionsAttribute attr =
            (StructExceptionsAttribute)
                method.methodStruct.getAttributes().getWithKey("Exceptions");

        if (attr != null) {
          String classname = null;

          for (int i = 0; i < attr.getThrowsExceptions().size(); i++) {
            String exClassName = attr.getExcClassname(i, node.classStruct.getPool());
            if ("java/lang/Throwable".equals(exClassName)) {
              classname = exClassName;
              break;
            } else if ("java/lang/Exception".equals(exClassName)) {
              classname = exClassName;
            }
          }

          if (classname != null) {
            VarType exType = new VarType(classname, true);
            TextBuffer buffer = new TextBuffer("throw ");
            ExprProcessor.getCastedExprent(value, exType, buffer, indent, false, tracer);
            return buffer;
          }
        }
      }

      return value.toJava(indent, tracer).prepend("throw ");
    }
  }
  public int writeImports(TextBuffer buffer) {
    int importLinesWritten = 0;

    List<String> imports = packImports();

    for (String s : imports) {
      buffer.append("import ");
      buffer.append(s);
      buffer.append(';');
      buffer.appendLineSeparator();

      importLinesWritten++;
    }

    return importLinesWritten;
  }
  @Override
  public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
    TextBuffer buffer = new TextBuffer();

    buffer.appendIndent(indent);
    buffer.append('@');
    buffer.append(
        DecompilerContext.getImportCollector()
            .getShortName(ExprProcessor.buildJavaClassName(className)));

    int type = getAnnotationType();

    if (type != ANNOTATION_MARKER) {
      buffer.append('(');

      boolean oneLiner = type == ANNOTATION_SINGLE_ELEMENT || indent < 0;

      for (int i = 0; i < parNames.size(); i++) {
        if (!oneLiner) {
          buffer.appendLineSeparator().appendIndent(indent + 1);
        }

        if (type != ANNOTATION_SINGLE_ELEMENT) {
          buffer.append(parNames.get(i));
          buffer.append(" = ");
        }

        buffer.append(parValues.get(i).toJava(0, tracer));

        if (i < parNames.size() - 1) {
          buffer.append(',');
        }
      }

      if (!oneLiner) {
        buffer.appendLineSeparator().appendIndent(indent);
      }

      buffer.append(')');
    }

    return buffer;
  }