///|
pub fn SemanticIndex::module_json(
  self : SemanticIndex,
  name : String,
) -> String? {
  match self.find_module(name) {
    None => None
    Some(mod) => {
      let builder = StringBuilder()
      builder.write_string("{\"name\":\"")
      builder.write_string(mod.name)
      builder.write_string("\",\"signals\":")
      builder.write_object(mod.signals.length())
      builder.write_string(",\"instances\":")
      builder.write_object(mod.instances.length())
      builder.write_string(",\"fanout\":")
      builder.write_object(self.fanout(name))
      builder.write_string(",\"rank\":")
      builder.write_object(self.module_rank(name))
      builder.write_char('}')
      Some(builder.to_string())
    }
  }
}

///|
pub fn SemanticIndex::module_json_lines(self : SemanticIndex) -> Array[String] {
  let result : Array[String] = []
  for mod in self.modules {
    match self.module_json(mod.name) {
      Some(value) => result.push(value)
      None => ()
    }
  }
  result
}

///|
pub fn SemanticIndex::issue_json(self : SemanticIndex) -> String {
  let builder = StringBuilder()
  builder.write_char('[')
  for index, issue in self.issues {
    if index > 0 {
      builder.write_char(',')
    }
    builder.write_string("{\"code\":\"")
    builder.write_string(issue.code)
    builder.write_string("\",\"message\":\"")
    builder.write_string(issue.message)
    builder.write_string("\",\"start\":")
    builder.write_object(issue.span.start)
    builder.write_string("}")
  }
  builder.write_char(']')
  builder.to_string()
}

///|
pub fn SemanticIndex::complete_ir(self : SemanticIndex) -> String {
  "{\"modules\":" +
  self.ir_module_names() +
  ",\"module_details\":" +
  self.module_json_lines().join(",") +
  ",\"metrics\":" +
  self.ir_metrics() +
  ",\"issues\":" +
  self.issue_json() +
  ",\"contracts\":" +
  self.ir_contracts() +
  "}"
}

///|
pub fn SemanticIndex::complete_ir_size(self : SemanticIndex) -> Int {
  self.complete_ir().to_array().length()
}