diff --git a/src/compiler/crystal/tools/doc/constant.cr b/src/compiler/crystal/tools/doc/constant.cr index c3a7a0be0c32..e14d34455f9c 100644 --- a/src/compiler/crystal/tools/doc/constant.cr +++ b/src/compiler/crystal/tools/doc/constant.cr @@ -24,4 +24,12 @@ class Crystal::Doc::Constant def formatted_value Highlighter.highlight value.to_s end + + def to_json(builder : JSON::Builder) + builder.object do + builder.field "value", value.try(&.to_s) + builder.field "doc", doc + builder.field "summary", formatted_summary + end + end end diff --git a/src/compiler/crystal/tools/doc/generator.cr b/src/compiler/crystal/tools/doc/generator.cr index 482d1f809ba4..adf303d9f3dc 100644 --- a/src/compiler/crystal/tools/doc/generator.cr +++ b/src/compiler/crystal/tools/doc/generator.cr @@ -67,12 +67,17 @@ class Crystal::Doc::Generator end if filename - body = doc(program_type, File.read(filename)) + raw_body = File.read(filename) + body = doc(program_type, raw_body) else + raw_body = "" body = "" end File.write File.join(@output_dir, "index.html"), MainTemplate.new(body, types, repository_name) + + main_index = Main.new(raw_body, Type.new(self, @program), repository_name) + File.write File.join(@output_dir, "index.json"), main_index end def copy_files @@ -350,7 +355,15 @@ class Crystal::Doc::Generator filename[@base_dir.size..-1] end - record RelativeLocation, filename : String, line_number : Int32, url : String? + record RelativeLocation, filename : String, line_number : Int32, url : String? do + def to_json(builder : JSON::Builder) + builder.object do + builder.field "filename", filename + builder.field "line_number", line_number + builder.field "url", url + end + end + end SRC_SEP = "src#{File::SEPARATOR}" def relative_locations(type) diff --git a/src/compiler/crystal/tools/doc/macro.cr b/src/compiler/crystal/tools/doc/macro.cr index 00dc9a319faf..d3af7c4848e1 100644 --- a/src/compiler/crystal/tools/doc/macro.cr +++ b/src/compiler/crystal/tools/doc/macro.cr @@ -92,4 +92,19 @@ class Crystal::Doc::Macro def must_be_included? @generator.must_include? @macro end + + def to_json(builder : JSON::Builder) + builder.object do + builder.field "id", id + builder.field "html_id", html_id + builder.field "name", name + builder.field "doc", doc + builder.field "summary", formatted_summary + builder.field "abstract", abstract? + builder.field "args", args + builder.field "args_string", args_to_s + builder.field "source_link", source_link + builder.field "def", self.macro + end + end end diff --git a/src/compiler/crystal/tools/doc/main.cr b/src/compiler/crystal/tools/doc/main.cr new file mode 100644 index 000000000000..a7ab92bd2ae2 --- /dev/null +++ b/src/compiler/crystal/tools/doc/main.cr @@ -0,0 +1,15 @@ +module Crystal::Doc + record Main, body : String, program : Type, repository_name : String do + def to_s(io : IO) + to_json(io) + end + + def to_json(builder : JSON::Builder) + builder.object do + builder.field "repository_name", repository_name + builder.field "body", body + builder.field "program", program + end + end + end +end diff --git a/src/compiler/crystal/tools/doc/method.cr b/src/compiler/crystal/tools/doc/method.cr index 70b5bf7a238a..5b9b9e250ba1 100644 --- a/src/compiler/crystal/tools/doc/method.cr +++ b/src/compiler/crystal/tools/doc/method.cr @@ -202,4 +202,20 @@ class Crystal::Doc::Method def has_args? !@def.args.empty? || @def.block_arg || @def.yields end + + def to_json(builder : JSON::Builder) + builder.object do + builder.field "id", id + builder.field "html_id", html_id + builder.field "name", name + builder.field "doc", doc + builder.field "summary", formatted_summary + builder.field "abstract", abstract? + builder.field "args", args + builder.field "args_string", args_to_s + builder.field "source_link", source_link + builder.field "source_link", source_link + builder.field "def", self.def + end + end end diff --git a/src/compiler/crystal/tools/doc/to_json.cr b/src/compiler/crystal/tools/doc/to_json.cr new file mode 100644 index 000000000000..32c42712c1ca --- /dev/null +++ b/src/compiler/crystal/tools/doc/to_json.cr @@ -0,0 +1,41 @@ +class Crystal::Arg + def to_json(builder : JSON::Builder) + builder.object do + builder.field "name", name + builder.field "doc", doc + builder.field "default_value", default_value.to_s + builder.field "external_name", external_name.to_s + builder.field "restriction", restriction.to_s + end + end +end + +class Crystal::Def + def to_json(builder : JSON::Builder) + builder.object do + builder.field "name", name + builder.field "args", args + builder.field "double_splat", double_splat + builder.field "splat_index", splat_index + builder.field "yields", yields + builder.field "block_arg", block_arg + builder.field "return_type", return_type.to_s + builder.field "visibility", visibility.to_s + builder.field "body", body.to_s + end + end +end + +class Crystal::Macro + def to_json(builder : JSON::Builder) + builder.object do + builder.field "name", name + builder.field "args", args + builder.field "double_splat", double_splat + builder.field "splat_index", splat_index + builder.field "block_arg", block_arg + builder.field "visibility", visibility.to_s + builder.field "body", body.to_s + end + end +end diff --git a/src/compiler/crystal/tools/doc/type.cr b/src/compiler/crystal/tools/doc/type.cr index 608160f30261..d5af4895e49e 100644 --- a/src/compiler/crystal/tools/doc/type.cr +++ b/src/compiler/crystal/tools/doc/type.cr @@ -134,12 +134,12 @@ class Crystal::Doc::Type end def alias_definition - alias_def = @type.as(AliasType).aliased_type + alias_def = @type.as?(AliasType).try(&.aliased_type) alias_def end def formatted_alias_definition - type_to_html alias_definition + type_to_html alias_definition.as(Crystal::Type) end @types : Array(Type)? @@ -772,4 +772,66 @@ class Crystal::Doc::Type end delegate to_s, inspect, to: @type + + def to_json(builder : JSON::Builder) + builder.object do + builder.field "html_id", html_id + builder.field "path", path + builder.field "kind", kind + builder.field "full_name", full_name + builder.field "name", name + builder.field "abstract", abstract? + builder.field "superclass" { superclass.try(&.to_json_simple(builder)) || builder.scalar(nil) } + builder.field "ancestors" do + builder.array do + ancestors.each &.to_json_simple(builder) + end + end + builder.field "locations", locations + builder.field "repository_name", repository_name + builder.field "program", program? + builder.field "enum", enum? + builder.field "alias", alias? + builder.field "aliased", alias_definition.to_s + builder.field "const", const? + builder.field "constants", constants + builder.field "included_modules" do + builder.array do + included_modules.each &.to_json_simple(builder) + end + end + builder.field "extended_modules" do + builder.array do + extended_modules.each &.to_json_simple(builder) + end + end + builder.field "subclasses" do + builder.array do + subclasses.each &.to_json_simple(builder) + end + end + builder.field "including_types" do + builder.array do + including_types.each &.to_json_simple(builder) + end + end + builder.field "namespace" { namespace.try(&.to_json_simple(builder)) || builder.scalar(nil) } + builder.field "doc", doc + builder.field "summary", formatted_summary + builder.field "class_methods", class_methods + builder.field "constructors", constructors + builder.field "instance_methods", instance_methods + builder.field "macros", macros + builder.field "types", types + end + end + + def to_json_simple(builder : JSON::Builder) + builder.object do + builder.field "html_id", html_id + builder.field "kind", kind + builder.field "full_name", full_name + builder.field "name", name + end + end end