// Copyright 2023 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Adapted from mlir-tblgen.cpp. Simply delegates through to MlirTblgenMain.

#include <optional>

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "mlir/TableGen/AttrOrTypeDef.h"
#include "mlir/TableGen/Dialect.h"
#include "mlir/TableGen/GenInfo.h"
#include "mlir/TableGen/Interfaces.h"
#include "mlir/TableGen/Operator.h"
#include "mlir/Tools/mlir-tblgen/MlirTblgenMain.h"

using namespace llvm;
using namespace mlir;
using namespace mlir::tblgen;

//===----------------------------------------------------------------------===//
// JSON Documentation Generation
//===----------------------------------------------------------------------===//

// Strips consistent leading whitespace from description text.
// Detects the pattern `= [{\n  ...` and removes that leading whitespace
// from all lines. Preserves relative indentation for ASCII art, etc.
// Returns original text if parsing fails at any point.
static std::string cleanDescription(StringRef desc) {
  if (desc.empty()) {
    return "";
  }

  SmallVector<StringRef> lines;
  desc.split(lines, '\n');

  // Find minimum indentation (excluding empty lines).
  // Use std::optional to avoid npos sentinel value bugs.
  std::optional<size_t> minIndent;
  for (StringRef line : lines) {
    size_t firstNonWS = line.find_first_not_of(" \t");
    if (firstNonWS != StringRef::npos) {
      // Non-empty line found.
      if (!minIndent || firstNonWS < *minIndent) {
        minIndent = firstNonWS;
      }
    }
  }

  // If no non-empty lines or indentation is zero, return original.
  if (!minIndent || *minIndent == 0) {
    return desc.str();
  }

  // Strip the common indentation from all lines.
  std::string result;
  for (size_t i = 0; i < lines.size(); ++i) {
    StringRef line = lines[i];
    if (line.find_first_not_of(" \t") == StringRef::npos) {
      // Empty/whitespace-only line - preserve it.
      if (i > 0) {
        result += '\n';
      }
    } else {
      // Non-empty line - strip common indentation.
      if (line.size() < *minIndent) {
        // Line is shorter than expected indentation - bail cleanly.
        // This shouldn't happen if logic is correct, but handle defensively.
        return desc.str();
      }
      if (i > 0) {
        result += '\n';
      }
      result += line.substr(*minIndent).str();
    }
  }

  // Trim leading/trailing blank lines.
  while (!result.empty() && result.front() == '\n') {
    result.erase(0, 1);
  }
  while (!result.empty() && result.back() == '\n') {
    result.pop_back();
  }

  return result;
}

// Cleans assembly format by replacing newlines with spaces.
// Assembly format strings in TableGen files may have newlines for readability,
// but they're ignored by the parser so we normalize to single line.
static std::string cleanAssemblyFormat(StringRef format) {
  if (format.empty()) {
    return "";
  }

  std::string result = format.str();
  // Replace all newlines with spaces.
  for (char& c : result) {
    if (c == '\n') {
      c = ' ';
    }
  }

  // Collapse multiple spaces into single space.
  size_t writePos = 0;
  bool lastWasSpace = false;
  for (size_t i = 0; i < result.size(); ++i) {
    if (result[i] == ' ') {
      if (!lastWasSpace) {
        result[writePos++] = ' ';
        lastWasSpace = true;
      }
    } else {
      result[writePos++] = result[i];
      lastWasSpace = false;
    }
  }
  result.resize(writePos);

  // Trim leading/trailing spaces.
  while (!result.empty() && result.front() == ' ') {
    result.erase(0, 1);
  }
  while (!result.empty() && result.back() == ' ') {
    result.pop_back();
  }

  return result;
}

// Resolves relative path to absolute path using the defining record's location.
// This is best-effort resolution - returns original path if resolution fails.
// Paths in metadata are relative to the repository root (e.g.,
// "test/foo.mlir"), so we walk up from the .td file location to find the
// repository root. Note: Assumes IREE-style repo structure with "compiler/src/"
// directory.
static std::string resolveRelativePath(StringRef relativePath,
                                       const Record* definingRecord) {
  if (relativePath.empty()) {
    return "";
  }

  // Get source location of the record (the .td file).
  ArrayRef<SMLoc> locs = definingRecord->getLoc();
  if (locs.empty() || !locs[0].isValid()) {
    // No valid location - can't resolve, return original path.
    return relativePath.str();
  }

  // Find buffer containing this location.
  unsigned bufferID = llvm::SrcMgr.FindBufferContainingLoc(locs[0]);
  if (bufferID == 0) {
    // Buffer not found - return original path.
    return relativePath.str();
  }

  // Get .td file path from buffer.
  const MemoryBuffer* buffer = llvm::SrcMgr.getMemoryBuffer(bufferID);
  if (!buffer) {
    // Defensive: buffer should exist if bufferID != 0, but check anyway.
    return relativePath.str();
  }
  StringRef tdFilePath = buffer->getBufferIdentifier();

  // Find repository root by walking up from .td file directory.
  // The repository root is assumed to be the directory containing
  // "compiler/src/".
  SmallString<256> currentDir(tdFilePath);
  llvm::sys::path::remove_filename(
      currentDir);  // Start from .td file's directory.

  SmallString<256> repoRoot;
  bool foundRoot = false;

  // Walk up the directory tree looking for "compiler/src/".
  while (!currentDir.empty() && currentDir != "/") {
    SmallString<256> compilerSrcPath(currentDir);
    llvm::sys::path::append(compilerSrcPath, "compiler", "src");

    // Check if this directory contains "compiler/src/".
    bool isDir = false;
    std::error_code ec = llvm::sys::fs::is_directory(compilerSrcPath, isDir);
    if (!ec && isDir) {
      // Found the repository root.
      repoRoot = currentDir;
      foundRoot = true;
      break;
    }
    // If error checking directory, continue walking up (graceful degradation).

    // Move up one directory.
    llvm::sys::path::remove_filename(currentDir);
  }

  // Fallback: if root-finding failed, try extracting from .td file path.
  if (!foundRoot) {
    // Try to find "compiler/src/" in the .td file path itself.
    StringRef tdFileStr(tdFilePath);
    size_t compilerSrcPos = tdFileStr.find("compiler/src/");
    if (compilerSrcPos != StringRef::npos) {
      // Extract everything before "compiler/src/" as repo root.
      repoRoot = tdFileStr.substr(0, compilerSrcPos);
      foundRoot = true;
    } else {
      // Could not determine repository root - return original path unchanged.
      // This is acceptable for non-IREE projects or different layouts.
      return relativePath.str();
    }
  }

  // Resolve relative path against repository root.
  SmallString<256> absolutePath(repoRoot);
  llvm::sys::path::append(absolutePath, relativePath);

  // Normalize to remove . and ..
  llvm::sys::path::remove_dots(absolutePath, /*remove_dot_dot=*/true);

  return std::string(absolutePath.str());
}

// Emits source location information for a record.
// Gracefully degrades: if location can't be determined, emits nothing.
// This is acceptable as source location is supplementary information.
static void emitSourceLocation(const Record* def, const RecordKeeper& records,
                               json::OStream& J) {
  (void)records;  // Not needed - using global llvm::SrcMgr.

  // Get the primary location (first element of location array).
  ArrayRef<SMLoc> locs = def->getLoc();
  if (locs.empty() || !locs[0].isValid()) {
    // No location available - skip emitting sourceLocation attribute.
    return;
  }

  SMLoc loc = locs[0];

  // Find which buffer contains this location.
  unsigned bufferID = llvm::SrcMgr.FindBufferContainingLoc(loc);
  if (bufferID == 0) {
    // Location not associated with a buffer - skip sourceLocation.
    return;
  }

  // Get the file path from buffer.
  const MemoryBuffer* buffer = llvm::SrcMgr.getMemoryBuffer(bufferID);
  if (!buffer) {
    // Defensive: buffer should exist if bufferID != 0, but check anyway.
    return;
  }
  StringRef filename = buffer->getBufferIdentifier();

  // Get line and column numbers.
  std::pair<unsigned, unsigned> lineCol =
      llvm::SrcMgr.getLineAndColumn(loc, bufferID);

  // Emit as JSON.
  J.attributeObject("sourceLocation", [&] {
    J.attribute("file", filename);
    J.attribute("line", lineCol.first);
    J.attribute("column", lineCol.second);
  });
}

// Emits parameters for a type or attribute.
static void emitParameters(ArrayRef<AttrOrTypeParameter> params,
                           json::OStream& J) {
  if (params.empty()) {
    return;
  }

  J.attributeArray("parameters", [&] {
    for (const auto& param : params) {
      J.object([&] {
        if (!param.isAnonymous()) {
          J.attribute("name", param.getName());
        }
        J.attribute("cppType", param.getCppType());

        if (auto summary = param.getSummary()) {
          J.attribute("summary", *summary);
        }

        if (param.isOptional()) {
          J.attribute("isOptional", true);
          if (auto defaultValue = param.getDefaultValue()) {
            J.attribute("defaultValue", *defaultValue);
          }
        } else {
          J.attribute("isOptional", false);
        }

        if (auto constraint = param.getConstraint()) {
          J.attributeObject("constraint", [&] {
            if (!constraint->getSummary().empty()) {
              J.attribute("summary", constraint->getSummary());
            }
            if (!constraint->getDescription().empty()) {
              J.attribute("description",
                          cleanDescription(constraint->getDescription()));
            }
          });
        }
      });
    }
  });
}

// Emits traits for a type or attribute.
static void emitTraits(ArrayRef<Trait> traits, json::OStream& J) {
  if (traits.empty()) {
    return;
  }

  J.attributeArray("traits", [&] {
    for (const Trait& trait : traits) {
      J.object([&] {
        if (const auto* nt = dyn_cast<NativeTrait>(&trait)) {
          J.attribute("kind", "NativeTrait");
          J.attribute("trait", nt->getFullyQualifiedTraitName());
        } else if (const auto* it = dyn_cast<InterfaceTrait>(&trait)) {
          J.attribute("kind", "Interface");
          J.attribute("trait", it->getFullyQualifiedTraitName());
        } else {
          J.attribute("kind", "Other");
        }
      });
    }
  });
}

// Emits builders for an operation.
static void emitBuilders(ArrayRef<Builder> builders, json::OStream& J) {
  if (builders.empty()) {
    return;
  }

  J.attributeArray("builders", [&] {
    for (const Builder& builder : builders) {
      J.object([&] {
        // Emit parameters.
        J.attributeArray("parameters", [&] {
          for (const Builder::Parameter& param : builder.getParameters()) {
            J.object([&] {
              J.attribute("type", param.getCppType());

              if (auto name = param.getName()) {
                J.attribute("name", *name);
              }

              if (auto defaultValue = param.getDefaultValue()) {
                J.attribute("defaultValue", *defaultValue);
              }
            });
          }
        });

        // Check if deprecated.
        if (auto deprecatedMsg = builder.getDeprecatedMessage()) {
          J.attribute("deprecated", true);
          J.attribute("deprecationMessage", *deprecatedMsg);
        }
      });
    }
  });
}

// Emits interface methods.
static void emitInterfaceMethods(ArrayRef<InterfaceMethod> methods,
                                 json::OStream& J) {
  if (methods.empty()) {
    return;
  }

  J.attributeArray("methods", [&] {
    for (const InterfaceMethod& method : methods) {
      J.object([&] {
        J.attribute("name", method.getName());
        J.attribute("returnType", method.getReturnType());

        J.attributeArray("arguments", [&] {
          for (const auto& arg : method.getArguments()) {
            J.object([&] {
              J.attribute("type", arg.type);
              J.attribute("name", arg.name);
            });
          }
        });

        J.attribute("isStatic", method.isStatic());

        if (auto desc = method.getDescription()) {
          J.attribute("description", cleanDescription(*desc));
        }

        // Check if method has a default implementation.
        bool hasDefault = method.getDefaultImplementation().has_value();
        J.attribute("hasDefaultImpl", hasDefault);
      });
    }
  });
}

// Returns all operation definitions.
static std::vector<const Record*> getOpDefinitions(
    const RecordKeeper& records) {
  const Record* classDef = records.getClass("Op");
  if (!classDef) {
    return {};
  }

  std::vector<const Record*> defs;
  for (const auto& def : records.getDefs()) {
    if (def.second->isSubClassOf(classDef)) {
      defs.push_back(def.second.get());
    }
  }
  return defs;
}

// Returns all type definitions.
static std::vector<const Record*> getTypeDefinitions(
    const RecordKeeper& records) {
  const Record* classDef = records.getClass("TypeDef");
  if (!classDef) {
    return {};
  }

  std::vector<const Record*> defs;
  for (const auto& def : records.getDefs()) {
    if (def.second->isSubClassOf(classDef)) {
      defs.push_back(def.second.get());
    }
  }
  return defs;
}

// Returns all attribute definitions.
static std::vector<const Record*> getAttrDefinitions(
    const RecordKeeper& records) {
  const Record* classDef = records.getClass("AttrDef");
  if (!classDef) {
    return {};
  }

  std::vector<const Record*> defs;
  for (const auto& def : records.getDefs()) {
    if (def.second->isSubClassOf(classDef)) {
      defs.push_back(def.second.get());
    }
  }
  return defs;
}

// Returns all interface definitions (Op, Type, and Attr interfaces).
static std::vector<const Record*> getInterfaceDefinitions(
    const RecordKeeper& records) {
  std::vector<const Record*> defs;

  // OpInterface, AttrInterface, TypeInterface.
  for (const char* className :
       {"OpInterface", "AttrInterface", "TypeInterface"}) {
    const Record* classDef = records.getClass(className);
    if (!classDef) {
      continue;
    }

    for (const auto& def : records.getDefs()) {
      if (def.second->isSubClassOf(classDef)) {
        // Skip anonymous records generated by DeclareInterfaceMethods helpers.
        // These are implementation details that duplicate named interfaces.
        StringRef name = def.second->getName();
        if (name.starts_with("anonymous_")) {
          continue;
        }
        defs.push_back(def.second.get());
      }
    }
  }
  return defs;
}

// Returns all dialect definitions.
static std::vector<Dialect> getDialects(const RecordKeeper& records) {
  auto dialectDefs = records.getAllDerivedDefinitions("Dialect");
  std::vector<Dialect> dialects;
  dialects.reserve(dialectDefs.size());
  for (const Record* def : dialectDefs) {
    dialects.emplace_back(def);
  }
  return dialects;
}

// Extracts dialect name from a fully qualified interface name.
// Tries multiple common namespace patterns:
// 1. ::mlir::iree_compiler::IREE::DialectName::ClassName (IREE pattern)
// 2. ::mlir::DialectName::ClassName (simple MLIR pattern)
// 3. Generic: second-to-last namespace component before ClassName
// Returns empty optional if extraction fails.
static std::optional<std::string> extractDialectFromNamespace(StringRef fqn) {
  // Try IREE-specific pattern: ::mlir::iree_compiler::IREE::DialectName::
  StringRef ireePrefix = "::mlir::iree_compiler::IREE::";
  if (fqn.starts_with(ireePrefix)) {
    StringRef afterPrefix = fqn.substr(ireePrefix.size());
    size_t nextColon = afterPrefix.find("::");
    if (nextColon != StringRef::npos) {
      return afterPrefix.substr(0, nextColon).lower();
    }
  }

  // Try simple MLIR pattern: ::mlir::DialectName::ClassName
  StringRef mlirPrefix = "::mlir::";
  if (fqn.starts_with(mlirPrefix)) {
    StringRef afterMlir = fqn.substr(mlirPrefix.size());
    size_t firstColon = afterMlir.find("::");
    if (firstColon != StringRef::npos) {
      StringRef candidate = afterMlir.substr(0, firstColon);
      // Make sure there's another :: after this (i.e., ClassName exists).
      StringRef afterCandidate = afterMlir.substr(firstColon + 2);
      if (!afterCandidate.empty() &&
          afterCandidate.find("::") == StringRef::npos) {
        // Pattern matches: ::mlir::DialectName::ClassName
        return candidate.lower();
      }
    }
  }

  // Generic fallback: extract second-to-last namespace component.
  // Find last :: to get ClassName, then find previous :: for DialectName.
  size_t lastColons = fqn.rfind("::");
  if (lastColons != StringRef::npos && lastColons > 0) {
    StringRef beforeLast = fqn.substr(0, lastColons);
    size_t secondLastColons = beforeLast.rfind("::");
    if (secondLastColons != StringRef::npos) {
      StringRef dialectName = beforeLast.substr(secondLastColons + 2);
      if (!dialectName.empty()) {
        return dialectName.lower();
      }
    }
  }

  // Could not extract dialect name - return empty.
  return std::nullopt;
}

// Emits structured constraint information for type unions.
// Extracts the allowedTypes list from AnyTypeOf/AllOfType constraints.
static void emitConstraintMetadata(const tblgen::Constraint& constraint,
                                   json::OStream& J) {
  const Record& def = constraint.getDef();

  // Check if this is a union-type constraint (AnyTypeOf, AllOfType, etc.).
  // These constraints have an "allowedTypes" field with the constituent types.
  if (!def.getValue("allowedTypes")) {
    return;  // Not a union constraint, nothing to emit.
  }

  std::vector<const Record*> allowedTypes =
      def.getValueAsListOfDefs("allowedTypes");
  if (allowedTypes.empty()) {
    return;  // No types listed, skip emission.
  }

  // Emit structured constraint object.
  J.attributeObject("constraint", [&] {
    // Determine constraint kind from the class hierarchy.
    std::string kind = "UnionType";
    if (def.isSubClassOf("AnyTypeOf")) {
      kind = "AnyTypeOf";
    } else if (def.isSubClassOf("AllOfType")) {
      kind = "AllOfType";
    } else if (def.isSubClassOf("TypeConstraint")) {
      kind = "TypeConstraint";
    }
    J.attribute("kind", kind);

    // Emit the list of allowed type names.
    J.attributeArray("allowedTypes", [&] {
      for (const Record* typeRecord : allowedTypes) {
        J.value(typeRecord->getName());
      }
    });
  });
}

// Emits common metadata fields (used by types, attrs, interfaces).
static void emitCommonMetadata(const Record* metadata,
                               const Record* definingRecord, json::OStream& J,
                               const char* relatedListName) {
  if (!metadata) {
    return;
  }

  J.attributeObject("metadata", [&] {
    if (StringRef category = metadata->getValueAsString("category");
        !category.empty()) {
      J.attribute("category", category);
    }

    auto relatedList = metadata->getValueAsListOfStrings(relatedListName);
    if (!relatedList.empty()) {
      J.attributeArray(relatedListName, [&] {
        for (StringRef related : relatedList) {
          J.value(related);
        }
      });
    }

    if (StringRef testFile = metadata->getValueAsString("testFile");
        !testFile.empty()) {
      std::string absolutePath = resolveRelativePath(testFile, definingRecord);
      J.attribute("testFile", absolutePath);
    }

    auto exampleRefs = metadata->getValueAsListOfStrings("exampleRefs");
    if (!exampleRefs.empty()) {
      J.attributeArray("exampleRefs", [&] {
        for (StringRef ref : exampleRefs) {
          J.value(ref);
        }
      });
    }

    auto textualExamples = metadata->getValueAsListOfStrings("textualExamples");
    if (!textualExamples.empty()) {
      J.attributeArray("textualExamples", [&] {
        for (StringRef example : textualExamples) {
          J.value(example);
        }
      });
    }

    auto tags = metadata->getValueAsListOfStrings("tags");
    if (!tags.empty()) {
      J.attributeArray("tags", [&] {
        for (StringRef tag : tags) {
          J.value(tag);
        }
      });
    }
  });
}

// Emits a single operation as JSON.
static void emitOperatorJSON(const Operator& op, const RecordKeeper& records,
                             json::OStream& J) {
  const Record& def = op.getDef();

  J.object([&] {
    J.attribute("name", op.getOperationName());

    // Dialect reference.
    J.attribute("dialect", op.getDialect().getName());

    // C++ class names.
    J.attribute("cppClassName", op.getCppClassName());
    std::string fullyQualifiedName = op.getDialect().getCppNamespace().str() +
                                     "::" + op.getCppClassName().str();
    J.attribute("fullyQualifiedName", fullyQualifiedName);

    // Source location.
    emitSourceLocation(&def, records, J);

    if (op.hasSummary()) {
      J.attribute("summary", cleanDescription(op.getSummary()));
    }
    if (op.hasDescription()) {
      J.attribute("description", cleanDescription(op.getDescription()));
    }
    if (op.hasAssemblyFormat()) {
      J.attribute("assemblyFormat",
                  cleanAssemblyFormat(op.getAssemblyFormat()));
    }

    // Custom metadata extraction (Util_OpDocMetadata).
    if (const Record* metadata = def.getValueAsOptionalDef("docMetadata")) {
      J.attributeObject("metadata", [&] {
        // Extract category from OpDocGroup if present.
        if (const Record* docGroup =
                metadata->getValueAsOptionalDef("docGroup")) {
          if (StringRef summary = docGroup->getValueAsString("summary");
              !summary.empty()) {
            J.attribute("category", summary);
          }
        }

        auto relatedOps = metadata->getValueAsListOfStrings("relatedOps");
        if (!relatedOps.empty()) {
          J.attributeArray("relatedOps", [&] {
            for (StringRef relOp : relatedOps) {
              J.value(relOp);
            }
          });
        }

        if (StringRef testFile = metadata->getValueAsString("testFile");
            !testFile.empty()) {
          std::string absolutePath = resolveRelativePath(testFile, &def);
          J.attribute("testFile", absolutePath);
        }

        auto exampleRefs = metadata->getValueAsListOfStrings("exampleRefs");
        if (!exampleRefs.empty()) {
          J.attributeArray("exampleRefs", [&] {
            for (StringRef exampleRef : exampleRefs) {
              J.value(exampleRef);
            }
          });
        }

        auto textualExamples =
            metadata->getValueAsListOfStrings("textualExamples");
        if (!textualExamples.empty()) {
          J.attributeArray("textualExamples", [&] {
            for (StringRef example : textualExamples) {
              J.value(example);
            }
          });
        }

        auto tags = metadata->getValueAsListOfStrings("tags");
        if (!tags.empty()) {
          J.attributeArray("tags", [&] {
            for (StringRef tag : tags) {
              J.value(tag);
            }
          });
        }
      });
    }

    // Operands.
    J.attributeArray("operands", [&] {
      for (const auto& operand : op.getOperands()) {
        J.object([&] {
          J.attribute("name", operand.name);

          // Basic type information.
          if (!operand.constraint.getSummary().empty()) {
            J.attribute("summary", operand.constraint.getSummary());
          }
          if (!operand.constraint.getDescription().empty()) {
            J.attribute("description",
                        cleanDescription(operand.constraint.getDescription()));
          }

          // Type constraint details.
          // Skip anonymous TableGen-generated type constraint names.
          if (StringRef defName = operand.constraint.getDefName();
              !defName.empty() && !defName.starts_with("anonymous_")) {
            J.attribute("defName", defName);
          }

          // C++ type information.
          if (StringRef cppType = operand.constraint.getCppType();
              !cppType.empty()) {
            J.attribute("cppType", cppType);
          }

          // Emit structured constraint metadata if this is a union type.
          emitConstraintMetadata(operand.constraint, J);

          // Variadic/optional flags.
          J.attributeObject("properties", [&] {
            J.attribute("isOptional", operand.isOptional());
            J.attribute("isVariadic", operand.isVariadic());
            J.attribute("isVariadicOfVariadic", operand.isVariadicOfVariadic());
          });
        });
      }
    });

    // Results.
    J.attributeArray("results", [&] {
      for (const auto& result : op.getResults()) {
        J.object([&] {
          J.attribute("name", result.name);

          // Basic type information.
          if (!result.constraint.getSummary().empty()) {
            J.attribute("summary", result.constraint.getSummary());
          }
          if (!result.constraint.getDescription().empty()) {
            J.attribute("description",
                        cleanDescription(result.constraint.getDescription()));
          }

          // Type constraint details.
          // Skip anonymous TableGen-generated type constraint names.
          if (StringRef defName = result.constraint.getDefName();
              !defName.empty() && !defName.starts_with("anonymous_")) {
            J.attribute("defName", defName);
          }

          // C++ type information.
          if (StringRef cppType = result.constraint.getCppType();
              !cppType.empty()) {
            J.attribute("cppType", cppType);
          }

          // Emit structured constraint metadata if this is a union type.
          emitConstraintMetadata(result.constraint, J);

          // Variadic/optional flags.
          J.attributeObject("properties", [&] {
            J.attribute("isOptional", result.isOptional());
            J.attribute("isVariadic", result.isVariadic());
            J.attribute("isVariadicOfVariadic", result.isVariadicOfVariadic());
          });
        });
      }
    });

    // Traits.
    J.attributeArray("traits", [&] {
      for (const Trait& trait : op.getTraits()) {
        if (const auto* nt = dyn_cast<NativeTrait>(&trait)) {
          J.value(nt->getFullyQualifiedTraitName());
        } else if (const auto* it = dyn_cast<InterfaceTrait>(&trait)) {
          J.value(it->getFullyQualifiedTraitName());
        }
      }
    });

    // Builders.
    emitBuilders(op.getBuilders(), J);
  });
}

// Emits a single type as JSON.
static void emitTypeJSON(const Record& def, const RecordKeeper& records,
                         json::OStream& J) {
  // Wrap in TypeDef to access TableGen APIs.
  TypeDef type(&def);

  J.object([&] {
    J.attribute("name", def.getName());

    // Dialect reference.
    Dialect dialect = type.getDialect();
    J.attribute("dialect", dialect.getName());

    // C++ class names.
    J.attribute("cppClassName", type.getCppClassName());
    std::string fullyQualifiedName =
        (dialect.getCppNamespace() + "::" + type.getCppClassName()).str();
    J.attribute("fullyQualifiedName", fullyQualifiedName);

    // Source location.
    emitSourceLocation(&def, records, J);

    // Mnemonic and assembly format.
    if (def.getValue("mnemonic")) {
      if (StringRef mnemonic = def.getValueAsString("mnemonic");
          !mnemonic.empty()) {
        J.attribute("mnemonic", mnemonic);
      }
    }

    if (auto assemblyFormat = type.getAssemblyFormat()) {
      J.attribute("assemblyFormat", cleanAssemblyFormat(*assemblyFormat));
    }

    // Documentation.
    if (def.getValue("summary")) {
      if (StringRef summary = def.getValueAsString("summary");
          !summary.empty()) {
        J.attribute("summary", cleanDescription(summary));
      }
    }

    if (def.getValue("description")) {
      if (StringRef desc = def.getValueAsString("description"); !desc.empty()) {
        J.attribute("description", cleanDescription(desc));
      }
    }

    // Parameters.
    emitParameters(type.getParameters(), J);

    // Traits.
    emitTraits(type.getTraits(), J);

    // Emit custom metadata (only if the field exists).
    if (def.getValue("docMetadata")) {
      if (const Record* metadata = def.getValueAsOptionalDef("docMetadata")) {
        emitCommonMetadata(metadata, &def, J, "relatedTypes");
      }
    }
  });
}

// Emits a single attribute as JSON.
static void emitAttrJSON(const Record& def, const RecordKeeper& records,
                         json::OStream& J) {
  // Wrap in AttrDef to access TableGen APIs.
  AttrDef attr(&def);

  J.object([&] {
    J.attribute("name", def.getName());

    // Dialect reference.
    Dialect dialect = attr.getDialect();
    J.attribute("dialect", dialect.getName());

    // C++ class names.
    J.attribute("cppClassName", attr.getCppClassName());
    std::string fullyQualifiedName =
        (dialect.getCppNamespace() + "::" + attr.getCppClassName()).str();
    J.attribute("fullyQualifiedName", fullyQualifiedName);

    // Source location.
    emitSourceLocation(&def, records, J);

    // Mnemonic and assembly format.
    if (def.getValue("mnemonic")) {
      if (StringRef mnemonic = def.getValueAsString("mnemonic");
          !mnemonic.empty()) {
        J.attribute("mnemonic", mnemonic);
      }
    }

    if (auto assemblyFormat = attr.getAssemblyFormat()) {
      J.attribute("assemblyFormat", cleanAssemblyFormat(*assemblyFormat));
    }

    // Documentation.
    if (def.getValue("summary")) {
      if (StringRef summary = def.getValueAsString("summary");
          !summary.empty()) {
        J.attribute("summary", cleanDescription(summary));
      }
    }

    if (def.getValue("description")) {
      if (StringRef desc = def.getValueAsString("description"); !desc.empty()) {
        J.attribute("description", cleanDescription(desc));
      }
    }

    // Parameters.
    emitParameters(attr.getParameters(), J);

    // Traits.
    emitTraits(attr.getTraits(), J);

    // Emit custom metadata (only if the field exists).
    if (def.getValue("docMetadata")) {
      if (const Record* metadata = def.getValueAsOptionalDef("docMetadata")) {
        emitCommonMetadata(metadata, &def, J, "relatedAttrs");
      }
    }
  });
}

// Emits a single interface as JSON.
static void emitInterfaceJSON(const Record& def, const RecordKeeper& records,
                              json::OStream& J) {
  // Wrap in Interface to access TableGen APIs.
  Interface interface(&def);

  J.object([&] {
    J.attribute("name", def.getName());

    // C++ class names.
    std::string fullyQualifiedName = interface.getFullyQualifiedName();
    StringRef fqnRef(fullyQualifiedName);

    // Try to extract dialect name from namespace using generic patterns.
    if (auto dialectName = extractDialectFromNamespace(fqnRef)) {
      J.attribute("dialect", *dialectName);
    }

    // Extract class name from fully qualified name (part after last "::").
    size_t lastColons = fqnRef.rfind("::");
    if (lastColons != StringRef::npos) {
      J.attribute("cppClassName", fqnRef.substr(lastColons + 2));
    } else {
      J.attribute("cppClassName", fqnRef);
    }

    J.attribute("fullyQualifiedName", fullyQualifiedName);

    // Source location.
    emitSourceLocation(&def, records, J);

    // Determine interface type.
    std::string interfaceType = "unknown";
    if (def.isSubClassOf("OpInterface")) {
      interfaceType = "op";
    } else if (def.isSubClassOf("TypeInterface")) {
      interfaceType = "type";
    } else if (def.isSubClassOf("AttrInterface")) {
      interfaceType = "attr";
    }
    J.attribute("interfaceType", interfaceType);

    // Documentation.
    if (def.getValue("summary")) {
      if (StringRef summary = def.getValueAsString("summary");
          !summary.empty()) {
        J.attribute("summary", cleanDescription(summary));
      }
    }

    if (auto desc = interface.getDescription()) {
      J.attribute("description", cleanDescription(*desc));
    }

    // Base interfaces.
    auto baseInterfaces = interface.getBaseInterfaces();
    if (!baseInterfaces.empty()) {
      J.attributeArray("baseInterfaces", [&] {
        for (const Interface& base : baseInterfaces) {
          J.value(base.getFullyQualifiedName());
        }
      });
    }

    // Methods.
    emitInterfaceMethods(interface.getMethods(), J);

    // Emit custom metadata (only if the field exists).
    if (def.getValue("docMetadata")) {
      if (const Record* metadata = def.getValueAsOptionalDef("docMetadata")) {
        emitCommonMetadata(metadata, &def, J, "relatedInterfaces");
      }
    }
  });
}

// Main JSON generation function.
static bool emitDialectJSON(const RecordKeeper& records, raw_ostream& os) {
  // Get all definitions.
  auto dialects = getDialects(records);
  auto opDefs = getOpDefinitions(records);
  auto typeDefs = getTypeDefinitions(records);
  auto attrDefs = getAttrDefinitions(records);
  auto interfaceDefs = getInterfaceDefinitions(records);

  // Collect categories from operations.
  std::map<std::string, std::string> categories;
  for (const Record* def : opDefs) {
    if (const Record* metadata = def->getValueAsOptionalDef("docMetadata")) {
      if (const Record* docGroup =
              metadata->getValueAsOptionalDef("docGroup")) {
        StringRef categoryName = docGroup->getValueAsString("summary");
        StringRef categoryDesc = docGroup->getValueAsString("description");
        if (!categoryName.empty()) {
          // Store category if not already present.
          categories.try_emplace(categoryName.str(), categoryDesc.str());
        }
      }
    }
  }

  json::OStream J(os, 2);  // Indent with 2 spaces.
  J.object([&] {
    // Dialects.
    if (!dialects.empty()) {
      J.attributeObject("dialects", [&] {
        for (const Dialect& dialect : dialects) {
          J.attributeObject(dialect.getName(), [&] {
            // C++ class names.
            J.attribute("cppClassName", dialect.getCppClassName());
            std::string fullyQualifiedName =
                (dialect.getCppNamespace() + "::" + dialect.getCppClassName())
                    .str();
            J.attribute("fullyQualifiedName", fullyQualifiedName);

            // Source location.
            emitSourceLocation(dialect.getDef(), records, J);

            if (!dialect.getSummary().empty()) {
              J.attribute("summary", cleanDescription(dialect.getSummary()));
            }

            if (!dialect.getDescription().empty()) {
              J.attribute("description",
                          cleanDescription(dialect.getDescription()));
            }

            // Dependent dialects.
            ArrayRef<StringRef> deps = dialect.getDependentDialects();
            if (!deps.empty()) {
              J.attributeArray("dependentDialects", [&] {
                for (StringRef dep : deps) {
                  J.value(dep);
                }
              });
            }

            // Feature flags (only emit if any are non-default).
            if (dialect.hasCanonicalizer() ||
                dialect.hasConstantMaterializer() ||
                !dialect.useDefaultAttributePrinterParser() ||
                !dialect.useDefaultTypePrinterParser() ||
                dialect.isExtensible()) {
              J.attributeObject("features", [&] {
                J.attribute("hasCanonicalizer", dialect.hasCanonicalizer());
                J.attribute("hasConstantMaterializer",
                            dialect.hasConstantMaterializer());
                J.attribute("useDefaultAttributePrinterParser",
                            dialect.useDefaultAttributePrinterParser());
                J.attribute("useDefaultTypePrinterParser",
                            dialect.useDefaultTypePrinterParser());
                J.attribute("isExtensible", dialect.isExtensible());
              });
            }
          });
        }
      });
    }

    // Categories.
    if (!categories.empty()) {
      J.attributeObject("categories", [&] {
        for (const auto& category : categories) {
          J.attributeObject(category.first, [&] {
            if (!category.second.empty()) {
              J.attribute("description", category.second);
            }
          });
        }
      });
    }

    // Operations.
    if (!opDefs.empty()) {
      J.attributeArray("operations", [&] {
        for (const Record* def : opDefs) {
          emitOperatorJSON(Operator(def), records, J);
        }
      });
    }

    // Types.
    if (!typeDefs.empty()) {
      J.attributeArray("types", [&] {
        for (const Record* def : typeDefs) {
          emitTypeJSON(*def, records, J);
        }
      });
    }

    // Attributes.
    if (!attrDefs.empty()) {
      J.attributeArray("attributes", [&] {
        for (const Record* def : attrDefs) {
          emitAttrJSON(*def, records, J);
        }
      });
    }

    // Interfaces.
    if (!interfaceDefs.empty()) {
      J.attributeArray("interfaces", [&] {
        for (const Record* def : interfaceDefs) {
          emitInterfaceJSON(*def, records, J);
        }
      });
    }
  });

  return false;
}

// Register the JSON dialect doc generation backend.
GenRegistration genDialectJSON("gen-dialect-json",
                               "Generate JSON documentation for a dialect",
                               emitDialectJSON);

//===----------------------------------------------------------------------===//
// Other Generators
//===----------------------------------------------------------------------===//

// Generator that prints records.
GenRegistration genPrintRecords("print-records", "Print all records to stdout",
                                [](const RecordKeeper& records,
                                   raw_ostream& os) {
                                  os << records;
                                  return false;
                                });

int main(int argc, char** argv) { return MlirTblgenMain(argc, argv); }
