///|
/// Source code location
pub(all) struct Loc {
/// Package path
path : String
/// File name
file : String
/// Line number
line : Int
/// Column number
column : Int
} derive(Show, ToJson, FromJson, Eq)
///|
/// Type path, represents fully qualified name
pub(all) struct TypePath {
/// Package path
path : String
/// Type name
name : String
} derive(Show, ToJson, FromJson, Eq)
///|
/// Semantic type, represents complete type information
pub(all) enum Stype {
/// Constructor type, e.g. Array[Int]
Constr(constr~ : TypePath, arguments~ : Array[Stype])
/// Arrow/function type
Arrow(
parameters~ : Array[Stype],
return_type~ : Stype,
error_type~ : Stype?,
is_async~ : Bool
)
/// Type parameter, e.g. T
Param(name~ : String)
/// Simple type path
Path(path~ : String, name~ : String)
} derive(Show, Eq)
///|
/// Custom ToJson for Stype to output format with "kind" field
pub impl ToJson for Stype with to_json(self) {
match self {
Constr(constr~, arguments~) => {
let obj : Map[String, Json] = {}
obj["kind"] = Json::string("constr")
obj["constructor"] = constr.to_json()
obj["arguments"] = Json::array(arguments.map(fn(s) { s.to_json() }))
Json::object(obj)
}
Arrow(parameters~, return_type~, error_type~, is_async~) => {
let obj : Map[String, Json] = {}
obj["kind"] = Json::string("arrow")
obj["parameters"] = Json::array(parameters.map(fn(s) { s.to_json() }))
obj["return_type"] = return_type.to_json()
match error_type {
Some(e) => obj["error_type"] = e.to_json()
None => obj["error_type"] = Json::null()
}
obj["is_async"] = Json::boolean(is_async)
Json::object(obj)
}
Param(name~) => {
let obj : Map[String, Json] = {}
obj["kind"] = Json::string("param")
obj["name"] = Json::string(name)
Json::object(obj)
}
Path(path~, name~) => {
let obj : Map[String, Json] = {}
obj["kind"] = Json::string("path")
obj["path"] = Json::string(path)
obj["name"] = Json::string(name)
Json::object(obj)
}
}
}
///|
/// Custom FromJson for Stype to handle JSON format with "kind" field
/// Also handles untagged Path variant (no "kind" field, just "name" and "path")
pub impl @json.FromJson for Stype with from_json(json, path) {
let obj = match json {
Object(m) => m
_ => raise @json.JsonDecodeError((path, "Expected object for Stype"))
}
// Check for "kind" field - if missing, assume it's an untagged Path
let kind : String = match obj.get("kind") {
Some(String(s)) => s
_ => "path" // Default to path for untagged variant
}
match kind {
"constr" => {
let constr : TypePath = @json.from_json(
obj.get("constructor").unwrap_or(Json::null()),
path=path.add_key("constructor"),
)
let arguments : Array[Stype] = @json.from_json(
obj.get("arguments").unwrap_or(Json::array([])),
path=path.add_key("arguments"),
)
Stype::Constr(constr~, arguments~)
}
"arrow" => {
let parameters : Array[Stype] = @json.from_json(
obj.get("parameters").unwrap_or(Json::array([])),
path=path.add_key("parameters"),
)
let return_type : Stype = @json.from_json(
obj.get("return_type").unwrap_or(Json::null()),
path=path.add_key("return_type"),
)
// error_type can be null or object
let error_type : Stype? = match obj.get("error_type") {
Some(Null) | None => None
Some(e) => Some(@json.from_json(e, path=path.add_key("error_type")))
}
let is_async : Bool = match obj.get("is_async") {
Some(True) => true
_ => false
}
Stype::Arrow(parameters~, return_type~, error_type~, is_async~)
}
"param" => {
let name : String = match obj.get("name") {
Some(String(s)) => s
_ => raise @json.JsonDecodeError((path, "Missing 'name' for param"))
}
Stype::Param(name~)
}
"path" | _ => {
// Handle both explicit "path" kind and untagged variant
let type_path : String = match obj.get("path") {
Some(String(s)) => s
_ => ""
}
let name : String = match obj.get("name") {
Some(String(s)) => s
_ => raise @json.JsonDecodeError((path, "Missing 'name' for path"))
}
Stype::Path(path=type_path, name~)
}
}
}
///|
/// Module/package metadata (from JSON)
pub(all) struct MetaInfo {
/// Full name, e.g. moonbitlang/core
name : String
/// Version
version : String
/// License
license : String?
/// Keywords
keywords : Array[String]
/// Repository URL
repository : String?
} derive(Show, ToJson, FromJson, Eq)
///|
/// Resource from JSON (flattened structure)
pub(all) struct Resource {
/// Resource kind: "module", "package", or "module_and_package"
kind : String
/// README content
readme_content : String
/// Meta info (for module types)
meta_info : MetaInfo?
/// Module index path (for module types)
module_index : String?
/// Package data path (for package types)
package_data : String?
/// Source files (for package types)
source_files : Array[String]?
/// Parent module path (for package types)
module_path : String?
} derive(Show, ToJson, FromJson, Eq)
///|
/// Value/function documentation
pub(all) struct ValueDoc {
/// Name
name : String
/// Documentation string
docstring : String
/// Function signature (HTML format)
signature : String
/// Source location
loc : Loc
} derive(Show, ToJson, FromJson, Eq)
///|
/// Implementation documentation
pub(all) struct ImplDoc {
/// Implemented type
self_ : Stype
/// Implemented trait
trait_ : TypePath
/// Method list
methods : Array[ValueDoc]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Type documentation
pub(all) struct TypeDoc {
/// Type name
name : String
/// Documentation string
docstring : String
/// Type signature (HTML format)
signature : String
/// Source location
loc : Loc
/// Method list
methods : Array[ValueDoc]
/// Implementation list
impls : Array[ImplDoc]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Trait documentation
pub(all) struct TraitDoc {
/// Trait name
name : String
/// Documentation string
docstring : String
/// Trait signature (HTML format)
signature : String
/// Source location
loc : Loc
/// Implementation list
impls : Array[ImplDoc]
/// Object type info (optional)
object_type_info : MiscDoc?
} derive(Show, ToJson, FromJson, Eq)
///|
/// Type alias documentation
pub(all) struct TypeAliasDoc {
/// Alias name
name : String
/// Documentation string
docstring : String
/// Alias signature (HTML format)
signature : String
/// Source location
loc : Loc
} derive(Show, ToJson, FromJson, Eq)
///|
/// Error type documentation
pub(all) struct ErrorDoc {
/// Error name
name : String
/// Documentation string
docstring : String
/// Error signature (HTML format)
signature : String
/// Source location
loc : Loc
/// Implementation list
impls : Array[ImplDoc]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Miscellaneous documentation (e.g. extension methods)
pub(all) struct MiscDoc {
/// Name
name : String
/// Implementation list
impls : Array[ImplDoc]
/// Method list
methods : Array[ValueDoc]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Complete package documentation data
pub(all) struct PackageData {
/// Package name
name : String
/// Type list
types : Array[TypeDoc]
/// Trait list
traits : Array[TraitDoc]
/// Type alias list (renamed from "typealias" in JSON)
type_aliases : Array[TypeAliasDoc]
/// Error type list
errors : Array[ErrorDoc]
/// Value/function list
values : Array[ValueDoc]
/// Miscellaneous (e.g. extension methods)
misc : Array[MiscDoc]
} derive(Show, ToJson, Eq)
///|
/// Custom FromJson for PackageData to handle "typealias" field name
pub impl @json.FromJson for PackageData with from_json(json, path) {
let obj = match json {
Object(m) => m
_ => raise @json.JsonDecodeError((path, "Expected object for PackageData"))
}
let name : String = @json.from_json(
obj.get("name").unwrap_or(Json::string("")),
path=path.add_key("name"),
)
let types : Array[TypeDoc] = @json.from_json(
obj.get("types").unwrap_or(Json::array([])),
path=path.add_key("types"),
)
let traits : Array[TraitDoc] = @json.from_json(
obj.get("traits").unwrap_or(Json::array([])),
path=path.add_key("traits"),
)
// Handle "typealias" -> "type_aliases"
let type_aliases : Array[TypeAliasDoc] = @json.from_json(
obj.get("typealias").unwrap_or(Json::array([])),
path=path.add_key("typealias"),
)
let errors : Array[ErrorDoc] = @json.from_json(
obj.get("errors").unwrap_or(Json::array([])),
path=path.add_key("errors"),
)
let values : Array[ValueDoc] = @json.from_json(
obj.get("values").unwrap_or(Json::array([])),
path=path.add_key("values"),
)
let misc : Array[MiscDoc] = @json.from_json(
obj.get("misc").unwrap_or(Json::array([])),
path=path.add_key("misc"),
)
PackageData::{ name, types, traits, type_aliases, errors, values, misc }
}
///|
/// Implementation index
pub(all) struct ImplIndex {
/// Implemented type
self_ : Stype
/// Implemented trait
trait_ : TypePath
/// Method name list
methods : Array[String]
} derive(Show, ToJson, Eq)
///|
/// Custom FromJson for ImplIndex to handle "self" and "trait" field names
pub impl @json.FromJson for ImplIndex with from_json(json, path) {
let obj = match json {
Object(m) => m
_ => raise @json.JsonDecodeError((path, "Expected object for ImplIndex"))
}
let self_ : Stype = @json.from_json(
obj.get("self").unwrap_or(Json::null()),
path=path.add_key("self"),
)
let trait_ : TypePath = @json.from_json(
obj.get("trait").unwrap_or(Json::null()),
path=path.add_key("trait"),
)
let methods : Array[String] = @json.from_json(
obj.get("methods").unwrap_or(Json::array([])),
path=path.add_key("methods"),
)
ImplIndex::{ self_, trait_, methods }
}
///|
/// Trait index
pub(all) struct TraitIndex {
/// Trait name
name : String
/// Implementation index list
impls : Array[ImplIndex]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Type index
pub(all) struct TypeIndex {
/// Type name
name : String
/// Implementation index list
impls : Array[ImplIndex]
/// Method name list
methods : Array[String]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Miscellaneous index
pub(all) struct MiscIndex {
/// Name
name : String
/// Implementation index list
impls : Array[ImplIndex]
/// Method name list
methods : Array[String]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Package index
pub(all) struct PackageIndex {
/// Package path
path : String
/// Trait index list
traits : Array[TraitIndex]
/// Type index list
types : Array[TypeIndex]
/// Type alias name list (renamed from "typealias" in JSON)
type_aliases : Array[String]
/// Value name list
values : Array[String]
/// Miscellaneous index list
misc : Array[MiscIndex]
} derive(Show, ToJson, Eq)
///|
/// Custom FromJson for PackageIndex to handle "typealias" field name
pub impl @json.FromJson for PackageIndex with from_json(json, path) {
let obj = match json {
Object(m) => m
_ => raise @json.JsonDecodeError((path, "Expected object for PackageIndex"))
}
let pkg_path : String = @json.from_json(
obj.get("path").unwrap_or(Json::string("")),
path=path.add_key("path"),
)
let traits : Array[TraitIndex] = @json.from_json(
obj.get("traits").unwrap_or(Json::array([])),
path=path.add_key("traits"),
)
let types : Array[TypeIndex] = @json.from_json(
obj.get("types").unwrap_or(Json::array([])),
path=path.add_key("types"),
)
let type_aliases : Array[String] = @json.from_json(
obj.get("typealias").unwrap_or(Json::array([])),
path=path.add_key("typealias"),
)
let values : Array[String] = @json.from_json(
obj.get("values").unwrap_or(Json::array([])),
path=path.add_key("values"),
)
let misc : Array[MiscIndex] = @json.from_json(
obj.get("misc").unwrap_or(Json::array([])),
path=path.add_key("misc"),
)
PackageIndex::{ path: pkg_path, traits, types, type_aliases, values, misc }
}
///|
/// Index node (tree structure)
pub(all) struct IndexNode {
/// Node name
name : String
/// Package index (optional)
pkg : PackageIndex?
/// Child node list
childs : Array[IndexNode]
} derive(Show, ToJson, Eq)
///|
/// Custom FromJson for IndexNode to handle "package" field name
pub impl @json.FromJson for IndexNode with from_json(json, path) {
let obj = match json {
Object(m) => m
_ => raise @json.JsonDecodeError((path, "Expected object for IndexNode"))
}
let name : String = @json.from_json(
obj.get("name").unwrap_or(Json::string("")),
path=path.add_key("name"),
)
// Handle "package" -> "pkg", where package can be null or an object
let pkg : PackageIndex? = match obj.get("package") {
Some(Null) | None => None
Some(pkg_json) =>
Some(@json.from_json(pkg_json, path=path.add_key("package")))
}
let childs : Array[IndexNode] = @json.from_json(
obj.get("childs").unwrap_or(Json::array([])),
path=path.add_key("childs"),
)
IndexNode::{ name, pkg, childs }
}
///|
/// Module summary (for list display)
pub(all) struct ModuleSummary {
/// Module name
name : String
/// Version
version : String
/// License
license : String
/// Repository URL
repository : String
/// Keywords
keywords : Array[String]
/// Description
description : String
/// Whether new module
is_new : Bool
/// Created time
created_at : String
} derive(Show, ToJson, FromJson, Eq)
///|
/// Statistics
pub(all) struct Statistics {
/// Total modules
total_modules : Int
/// Total packages
total_packages : Int
/// Total lines of code
total_lines : Int
} derive(Show, ToJson, FromJson, Eq)
///|
/// User module info
pub(all) struct UserModule {
/// Module name
name : String
/// Version
version : String
} derive(Show, ToJson, FromJson, Eq)
///|
/// User info
pub(all) struct UserInfo {
/// Username
username : String
/// Avatar URL
avatar_url : String?
/// Published modules list
modules : Array[UserModule]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Full module data including all packages
pub(all) struct FullModuleData {
/// Module path
path : String
/// Module resource
resource : Resource
/// Module index
index : IndexNode
/// All package data, keyed by package path
packages : Map[String, PackageData]
} derive(Show, ToJson, FromJson, Eq)
///|
/// Search entry for fuzzy search
pub(all) struct SearchEntry {
/// Display name
name : String
/// Full path
path : String
/// Entry kind (type, trait, value, etc.)
kind : String
/// Signature (optional)
signature : String?
} derive(Show, ToJson, FromJson, Eq)