doc: add comment example support (#7924)
parent
ea4981df90
commit
30a2f125ef
|
@ -121,6 +121,7 @@ mut:
|
||||||
is_vlib bool
|
is_vlib bool
|
||||||
is_verbose bool
|
is_verbose bool
|
||||||
include_readme bool
|
include_readme bool
|
||||||
|
include_examples bool = true
|
||||||
open_docs bool
|
open_docs bool
|
||||||
server_port int = 8046
|
server_port int = 8046
|
||||||
inline_assets bool
|
inline_assets bool
|
||||||
|
@ -307,7 +308,12 @@ fn escape(str string) string {
|
||||||
fn (cfg DocConfig) gen_json(idx int) string {
|
fn (cfg DocConfig) gen_json(idx int) string {
|
||||||
dcs := cfg.docs[idx]
|
dcs := cfg.docs[idx]
|
||||||
mut jw := strings.new_builder(200)
|
mut jw := strings.new_builder(200)
|
||||||
jw.write('{"module_name":"$dcs.head.name","description":"${escape(dcs.head.comment)}","contents":')
|
comments := if cfg.include_examples {
|
||||||
|
dcs.head.merge_comments()
|
||||||
|
} else {
|
||||||
|
dcs.head.merge_comments_without_examples()
|
||||||
|
}
|
||||||
|
jw.write('{"module_name":"$dcs.head.name","description":"${escape(comments)}","contents":')
|
||||||
jw.write(json.encode(dcs.contents.keys().map(dcs.contents[it])))
|
jw.write(json.encode(dcs.contents.keys().map(dcs.contents[it])))
|
||||||
jw.write(',"generator":"vdoc","time_generated":"$dcs.time_generated.str()"}')
|
jw.write(',"generator":"vdoc","time_generated":"$dcs.time_generated.str()"}')
|
||||||
return jw.str()
|
return jw.str()
|
||||||
|
@ -395,11 +401,12 @@ fn html_highlight(code string, tb &table.Table) string {
|
||||||
return buf.str()
|
return buf.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string {
|
fn doc_node_html(dd doc.DocNode, link string, head bool, include_examples bool, tb &table.Table) string {
|
||||||
mut dnw := strings.new_builder(200)
|
mut dnw := strings.new_builder(200)
|
||||||
link_svg := '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>'
|
link_svg := '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>'
|
||||||
head_tag := if head { 'h1' } else { 'h2' }
|
head_tag := if head { 'h1' } else { 'h2' }
|
||||||
md_content := markdown.to_html(html_tag_escape(dd.comment))
|
comments := dd.merge_comments_without_examples()
|
||||||
|
md_content := markdown.to_html(html_tag_escape(comments))
|
||||||
hlighted_code := html_highlight(dd.content, tb)
|
hlighted_code := html_highlight(dd.content, tb)
|
||||||
node_class := if dd.kind == .const_group { ' const' } else { '' }
|
node_class := if dd.kind == .const_group { ' const' } else { '' }
|
||||||
sym_name := get_sym_name(dd)
|
sym_name := get_sym_name(dd)
|
||||||
|
@ -425,7 +432,19 @@ fn doc_node_html(dd doc.DocNode, link string, head bool, tb &table.Table) string
|
||||||
dnw.writeln('<pre class="signature"><code>$hlighted_code</code></pre>')
|
dnw.writeln('<pre class="signature"><code>$hlighted_code</code></pre>')
|
||||||
}
|
}
|
||||||
// do not mess with md_content further, its formatting is important, just output it 1:1 !
|
// do not mess with md_content further, its formatting is important, just output it 1:1 !
|
||||||
dnw.writeln('$md_content\n</section>')
|
dnw.writeln('$md_content\n')
|
||||||
|
// Write examples if any found
|
||||||
|
examples := dd.examples()
|
||||||
|
if include_examples && examples.len > 0 {
|
||||||
|
example_title := if examples.len > 1 { 'Examples' } else { 'Example' }
|
||||||
|
dnw.writeln('<section class="doc-node examples"><h4>$example_title</h4>')
|
||||||
|
for example in examples {
|
||||||
|
// hl_example := html_highlight(example, tb)
|
||||||
|
dnw.writeln('<pre><code class="language-v">$example</code></pre>')
|
||||||
|
}
|
||||||
|
dnw.writeln('</section>')
|
||||||
|
}
|
||||||
|
dnw.writeln('</section>')
|
||||||
dnw_str := dnw.str()
|
dnw_str := dnw.str()
|
||||||
defer {
|
defer {
|
||||||
dnw.free()
|
dnw.free()
|
||||||
|
@ -499,12 +518,12 @@ fn (cfg DocConfig) write_content(cn &doc.DocNode, dcs &doc.Doc, mut hw strings.B
|
||||||
}
|
}
|
||||||
src_link := get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line)
|
src_link := get_src_link(cfg.manifest.repo_url, file_path_name, cn.pos.line)
|
||||||
if cn.content.len != 0 || (cn.name == 'Constants') {
|
if cn.content.len != 0 || (cn.name == 'Constants') {
|
||||||
hw.write(doc_node_html(cn, src_link, false, dcs.table))
|
hw.write(doc_node_html(cn, src_link, false, cfg.include_examples, dcs.table))
|
||||||
}
|
}
|
||||||
for child in cn.children {
|
for child in cn.children {
|
||||||
child_file_path_name := child.file_path.replace('$base_dir/', '')
|
child_file_path_name := child.file_path.replace('$base_dir/', '')
|
||||||
child_src_link := get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line)
|
child_src_link := get_src_link(cfg.manifest.repo_url, child_file_path_name, child.pos.line)
|
||||||
hw.write(doc_node_html(child, child_src_link, false, dcs.table))
|
hw.write(doc_node_html(child, child_src_link, false, cfg.include_examples, dcs.table))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +534,7 @@ fn (cfg DocConfig) gen_html(idx int) string {
|
||||||
dcs := cfg.docs[idx]
|
dcs := cfg.docs[idx]
|
||||||
dcs_contents := dcs.contents.arr()
|
dcs_contents := dcs.contents.arr()
|
||||||
// generate toc first
|
// generate toc first
|
||||||
contents.writeln(doc_node_html(dcs.head, '', true, dcs.table))
|
contents.writeln(doc_node_html(dcs.head, '', true, cfg.include_examples, dcs.table))
|
||||||
if is_module_readme(dcs.head) {
|
if is_module_readme(dcs.head) {
|
||||||
write_toc(dcs.head, mut symbols_toc)
|
write_toc(dcs.head, mut symbols_toc)
|
||||||
}
|
}
|
||||||
|
@ -602,8 +621,13 @@ fn (cfg DocConfig) gen_plaintext(idx int) string {
|
||||||
dcs := cfg.docs[idx]
|
dcs := cfg.docs[idx]
|
||||||
mut pw := strings.new_builder(200)
|
mut pw := strings.new_builder(200)
|
||||||
pw.writeln('$dcs.head.content\n')
|
pw.writeln('$dcs.head.content\n')
|
||||||
if dcs.head.comment.trim_space().len > 0 && !cfg.pub_only {
|
comments := if cfg.include_examples {
|
||||||
pw.writeln(dcs.head.comment.split_into_lines().map(' ' + it).join('\n'))
|
dcs.head.merge_comments()
|
||||||
|
} else {
|
||||||
|
dcs.head.merge_comments_without_examples()
|
||||||
|
}
|
||||||
|
if comments.trim_space().len > 0 && !cfg.pub_only {
|
||||||
|
pw.writeln(comments.split_into_lines().map(' ' + it).join('\n'))
|
||||||
}
|
}
|
||||||
cfg.write_plaintext_content(dcs.contents.arr(), mut pw)
|
cfg.write_plaintext_content(dcs.contents.arr(), mut pw)
|
||||||
return pw.str()
|
return pw.str()
|
||||||
|
@ -613,8 +637,13 @@ fn (cfg DocConfig) write_plaintext_content(contents []doc.DocNode, mut pw string
|
||||||
for cn in contents {
|
for cn in contents {
|
||||||
if cn.content.len > 0 {
|
if cn.content.len > 0 {
|
||||||
pw.writeln(cn.content)
|
pw.writeln(cn.content)
|
||||||
if cn.comment.len > 0 && !cfg.pub_only {
|
if cn.comments.len > 0 && !cfg.pub_only {
|
||||||
pw.writeln(cn.comment.trim_space().split_into_lines().map(' ' + it).join('\n'))
|
comments := if cfg.include_examples {
|
||||||
|
cn.merge_comments()
|
||||||
|
} else {
|
||||||
|
cn.merge_comments_without_examples()
|
||||||
|
}
|
||||||
|
pw.writeln(comments.trim_space().split_into_lines().map(' ' + it).join('\n'))
|
||||||
}
|
}
|
||||||
if cfg.show_loc {
|
if cfg.show_loc {
|
||||||
pw.writeln('Location: $cn.file_path:$cn.pos.line\n')
|
pw.writeln('Location: $cn.file_path:$cn.pos.line\n')
|
||||||
|
@ -629,8 +658,13 @@ fn (cfg DocConfig) gen_markdown(idx int, with_toc bool) string {
|
||||||
mut hw := strings.new_builder(200)
|
mut hw := strings.new_builder(200)
|
||||||
mut cw := strings.new_builder(200)
|
mut cw := strings.new_builder(200)
|
||||||
hw.writeln('# $dcs.head.content\n')
|
hw.writeln('# $dcs.head.content\n')
|
||||||
if dcs.head.comment.len > 0 {
|
if dcs.head.comments.len > 0 {
|
||||||
hw.writeln('$dcs.head.comment\n')
|
comments := if cfg.include_examples {
|
||||||
|
dcs.head.merge_comments()
|
||||||
|
} else {
|
||||||
|
dcs.head.merge_comments_without_examples()
|
||||||
|
}
|
||||||
|
hw.writeln('$comments\n')
|
||||||
}
|
}
|
||||||
if with_toc {
|
if with_toc {
|
||||||
hw.writeln('## Contents')
|
hw.writeln('## Contents')
|
||||||
|
@ -648,7 +682,18 @@ fn (cfg DocConfig) write_markdown_content(contents []doc.DocNode, mut cw strings
|
||||||
cw.writeln('## $cn.name')
|
cw.writeln('## $cn.name')
|
||||||
}
|
}
|
||||||
if cn.content.len > 0 {
|
if cn.content.len > 0 {
|
||||||
cw.writeln('```v\n$cn.content\n```$cn.comment\n')
|
comments := cn.merge_comments_without_examples()
|
||||||
|
cw.writeln('```v\n$cn.content\n```\n$comments\n')
|
||||||
|
// Write examples if any found
|
||||||
|
examples := cn.examples()
|
||||||
|
if cfg.include_examples && examples.len > 0 {
|
||||||
|
example_title := if examples.len > 1 { 'Examples' } else { 'Example' }
|
||||||
|
cw.writeln('$example_title\n```v\n')
|
||||||
|
for example in examples {
|
||||||
|
cw.writeln('$example\n')
|
||||||
|
}
|
||||||
|
cw.writeln('```\n')
|
||||||
|
}
|
||||||
cw.writeln('[\[Return to contents\]](#Contents)\n')
|
cw.writeln('[\[Return to contents\]](#Contents)\n')
|
||||||
}
|
}
|
||||||
cfg.write_markdown_content(cn.children, mut cw, mut hw, indent + 1, with_toc)
|
cfg.write_markdown_content(cn.children, mut cw, mut hw, indent + 1, with_toc)
|
||||||
|
@ -742,8 +787,13 @@ fn (mut cfg DocConfig) collect_search_index() {
|
||||||
for doc in cfg.docs {
|
for doc in cfg.docs {
|
||||||
mod := doc.head.name
|
mod := doc.head.name
|
||||||
cfg.search_module_index << mod
|
cfg.search_module_index << mod
|
||||||
|
comments := if cfg.include_examples {
|
||||||
|
doc.head.merge_comments()
|
||||||
|
} else {
|
||||||
|
doc.head.merge_comments_without_examples()
|
||||||
|
}
|
||||||
cfg.search_module_data << SearchModuleResult{
|
cfg.search_module_data << SearchModuleResult{
|
||||||
description: trim_doc_node_description(doc.head.comment)
|
description: trim_doc_node_description(comments)
|
||||||
link: cfg.get_file_name(mod)
|
link: cfg.get_file_name(mod)
|
||||||
}
|
}
|
||||||
for _, dn in doc.contents {
|
for _, dn in doc.contents {
|
||||||
|
@ -756,7 +806,12 @@ fn (mut cfg DocConfig) create_search_results(mod string, dn doc.DocNode) {
|
||||||
if dn.kind == .const_group {
|
if dn.kind == .const_group {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dn_description := trim_doc_node_description(dn.comment)
|
comments := if cfg.include_examples {
|
||||||
|
dn.merge_comments()
|
||||||
|
} else {
|
||||||
|
dn.merge_comments_without_examples()
|
||||||
|
}
|
||||||
|
dn_description := trim_doc_node_description(comments)
|
||||||
cfg.search_index << dn.name
|
cfg.search_index << dn.name
|
||||||
cfg.search_data << SearchResult{
|
cfg.search_data << SearchResult{
|
||||||
prefix: if dn.parent_name != '' {
|
prefix: if dn.parent_name != '' {
|
||||||
|
@ -894,13 +949,16 @@ fn (mut cfg DocConfig) generate_docs_from_file() {
|
||||||
}
|
}
|
||||||
if cfg.include_readme {
|
if cfg.include_readme {
|
||||||
readme_contents := cfg.get_readme(dir_path)
|
readme_contents := cfg.get_readme(dir_path)
|
||||||
|
comment := doc.DocComment{
|
||||||
|
text: readme_contents
|
||||||
|
}
|
||||||
if cfg.output_type == .stdout {
|
if cfg.output_type == .stdout {
|
||||||
println(markdown.to_plain(readme_contents))
|
println(markdown.to_plain(readme_contents))
|
||||||
} else if cfg.output_type == .html && cfg.is_multi {
|
} else if cfg.output_type == .html && cfg.is_multi {
|
||||||
cfg.docs << doc.Doc{
|
cfg.docs << doc.Doc{
|
||||||
head: doc.DocNode{
|
head: doc.DocNode{
|
||||||
name: 'README'
|
name: 'README'
|
||||||
comment: readme_contents
|
comments: [comment]
|
||||||
}
|
}
|
||||||
time_generated: time.now()
|
time_generated: time.now()
|
||||||
}
|
}
|
||||||
|
@ -932,7 +990,10 @@ fn (mut cfg DocConfig) generate_docs_from_file() {
|
||||||
if !is_local_and_single {
|
if !is_local_and_single {
|
||||||
if cfg.is_multi || (!cfg.is_multi && cfg.include_readme) {
|
if cfg.is_multi || (!cfg.is_multi && cfg.include_readme) {
|
||||||
readme_contents := cfg.get_readme(dirpath)
|
readme_contents := cfg.get_readme(dirpath)
|
||||||
dcs.head.comment = readme_contents
|
comment := doc.DocComment{
|
||||||
|
text: readme_contents
|
||||||
|
}
|
||||||
|
dcs.head.comments = [comment]
|
||||||
}
|
}
|
||||||
if cfg.pub_only {
|
if cfg.pub_only {
|
||||||
for name, dc in dcs.contents {
|
for name, dc in dcs.contents {
|
||||||
|
@ -1183,6 +1244,9 @@ fn main() {
|
||||||
'-no-timestamp' {
|
'-no-timestamp' {
|
||||||
cfg.no_timestamp = true
|
cfg.no_timestamp = true
|
||||||
}
|
}
|
||||||
|
'-no-examples' {
|
||||||
|
cfg.include_examples = false
|
||||||
|
}
|
||||||
'-readme' {
|
'-readme' {
|
||||||
cfg.include_readme = true
|
cfg.include_readme = true
|
||||||
}
|
}
|
||||||
|
@ -1231,7 +1295,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_module_readme(dn doc.DocNode) bool {
|
fn is_module_readme(dn doc.DocNode) bool {
|
||||||
if dn.comment.len > 0 && dn.content == 'module $dn.name' {
|
if dn.comments.len > 0 && dn.content == 'module $dn.name' {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
module doc
|
||||||
|
|
||||||
|
const (
|
||||||
|
example_pattern = '\x01 Example: '
|
||||||
|
)
|
||||||
|
|
||||||
|
pub struct DocComment {
|
||||||
|
pub mut:
|
||||||
|
text string // Raw text content of the comment, excluding the comment token chars ('//, /*, */')
|
||||||
|
is_multi bool // Is a block / multi-line comment
|
||||||
|
pos DocPos = DocPos{-1, -1, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_example returns true if the contents of this comment is a doc example.
|
||||||
|
// The current convention is '// Example: <content>'
|
||||||
|
pub fn (dc DocComment) is_example() bool {
|
||||||
|
return dc.text.starts_with(example_pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// example returns the content of the example body
|
||||||
|
pub fn (dc DocComment) example() string {
|
||||||
|
return dc.text.all_after(example_pattern)
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ pub struct DocNode {
|
||||||
pub mut:
|
pub mut:
|
||||||
name string
|
name string
|
||||||
content string
|
content string
|
||||||
comment string
|
comments []DocComment
|
||||||
pos DocPos = DocPos{-1, -1, 0}
|
pos DocPos = DocPos{-1, -1, 0}
|
||||||
file_path string
|
file_path string
|
||||||
kind SymbolKind
|
kind SymbolKind
|
||||||
|
@ -128,7 +128,6 @@ pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) ?DocNode {
|
||||||
mut node := DocNode{
|
mut node := DocNode{
|
||||||
name: d.stmt_name(stmt)
|
name: d.stmt_name(stmt)
|
||||||
content: d.stmt_signature(stmt)
|
content: d.stmt_signature(stmt)
|
||||||
comment: ''
|
|
||||||
pos: d.convert_pos(filename, stmt.position())
|
pos: d.convert_pos(filename, stmt.position())
|
||||||
file_path: os.join_path(d.base_path, filename)
|
file_path: os.join_path(d.base_path, filename)
|
||||||
is_pub: d.stmt_pub(stmt)
|
is_pub: d.stmt_pub(stmt)
|
||||||
|
@ -139,7 +138,7 @@ pub fn (mut d Doc) stmt(stmt ast.Stmt, filename string) ?DocNode {
|
||||||
if node.name.starts_with(d.orig_mod_name + '.') {
|
if node.name.starts_with(d.orig_mod_name + '.') {
|
||||||
node.name = node.name.all_after(d.orig_mod_name + '.')
|
node.name = node.name.all_after(d.orig_mod_name + '.')
|
||||||
}
|
}
|
||||||
if node.name.len == 0 && node.comment.len == 0 && node.content.len == 0 {
|
if node.name.len == 0 && node.comments.len == 0 && node.content.len == 0 {
|
||||||
return error('empty stmt')
|
return error('empty stmt')
|
||||||
}
|
}
|
||||||
match stmt {
|
match stmt {
|
||||||
|
@ -246,12 +245,13 @@ pub fn (mut d Doc) file_ast(file_ast ast.File) map[string]DocNode {
|
||||||
last_import_stmt_idx = sidx
|
last_import_stmt_idx = sidx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut prev_comments := []ast.Comment{}
|
mut preceeding_comments := []DocComment{}
|
||||||
mut imports_section := true
|
mut imports_section := true
|
||||||
for sidx, stmt in stmts {
|
for sidx, stmt in stmts {
|
||||||
if stmt is ast.ExprStmt {
|
if stmt is ast.ExprStmt {
|
||||||
|
// Collect comments
|
||||||
if stmt.expr is ast.Comment {
|
if stmt.expr is ast.Comment {
|
||||||
prev_comments << stmt.expr
|
preceeding_comments << ast_comment_to_doc_comment(stmt.expr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,37 +261,41 @@ pub fn (mut d Doc) file_ast(file_ast ast.File) map[string]DocNode {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// the previous comments were probably a copyright/license one
|
// the previous comments were probably a copyright/license one
|
||||||
module_comment := get_comment_block_right_before(prev_comments)
|
module_comment := merge_doc_comments(preceeding_comments)
|
||||||
prev_comments = []
|
preceeding_comments = []
|
||||||
if !d.is_vlib && !module_comment.starts_with('Copyright (c)') {
|
if !d.is_vlib && !module_comment.starts_with('Copyright (c)') {
|
||||||
if module_comment in ['', d.head.comment] {
|
if module_comment == '' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if d.head.comment != '' {
|
if d.head.comment != '' {
|
||||||
d.head.comment += '\n'
|
d.head.comment += '\n'
|
||||||
}
|
}
|
||||||
d.head.comment += module_comment
|
*/
|
||||||
|
d.head.comments << preceeding_comments //+= module_comment
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if last_import_stmt_idx > 0 && sidx == last_import_stmt_idx {
|
if last_import_stmt_idx > 0 && sidx == last_import_stmt_idx {
|
||||||
// the accumulated comments were interspersed before/between the imports;
|
// the accumulated comments were interspersed before/between the imports;
|
||||||
// just add them all to the module comment:
|
// just add them all to the module comments:
|
||||||
if d.with_head {
|
if d.with_head {
|
||||||
import_comments := merge_comments(prev_comments)
|
// import_comments := merge_comments(preceeding_comments)
|
||||||
|
/*
|
||||||
if d.head.comment != '' {
|
if d.head.comment != '' {
|
||||||
d.head.comment += '\n'
|
d.head.comment += '\n'
|
||||||
}
|
}
|
||||||
d.head.comment += import_comments
|
*/
|
||||||
|
d.head.comments << preceeding_comments //+= import_comments
|
||||||
}
|
}
|
||||||
prev_comments = []
|
preceeding_comments = []
|
||||||
imports_section = false
|
imports_section = false
|
||||||
}
|
}
|
||||||
if stmt is ast.Import {
|
if stmt is ast.Import {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut node := d.stmt(stmt, os.base(file_ast.path)) or {
|
mut node := d.stmt(stmt, os.base(file_ast.path)) or {
|
||||||
prev_comments = []
|
preceeding_comments = []
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if node.parent_name !in contents {
|
if node.parent_name !in contents {
|
||||||
|
@ -305,18 +309,20 @@ pub fn (mut d Doc) file_ast(file_ast ast.File) map[string]DocNode {
|
||||||
kind: parent_node_kind
|
kind: parent_node_kind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if d.with_comments && (prev_comments.len > 0) {
|
if d.with_comments && (preceeding_comments.len > 0) {
|
||||||
// last_comment := contents[contents.len - 1].comment
|
// last_comment := contents[contents.len - 1].comment
|
||||||
// cmt := last_comment + '\n' + get_comment_block_right_before(prev_comments)
|
// cmt := last_comment + '\n' + merge_doc_comments(preceeding_comments)
|
||||||
mut cmt := get_comment_block_right_before(prev_comments)
|
/*
|
||||||
|
mut cmt := merge_doc_comments(preceeding_comments)
|
||||||
len := node.name.len
|
len := node.name.len
|
||||||
// fixed-width symbol name at start of comment
|
// fixed-width symbol name at start of comment
|
||||||
if cmt.starts_with(node.name) && cmt.len > len && cmt[len] == ` ` {
|
if cmt.starts_with(node.name) && cmt.len > len && cmt[len] == ` ` {
|
||||||
cmt = '`${cmt[..len]}`' + cmt[len..]
|
cmt = '`${cmt[..len]}`' + cmt[len..]
|
||||||
}
|
}
|
||||||
node.comment = cmt
|
*/
|
||||||
|
node.comments << preceeding_comments //= cmt
|
||||||
}
|
}
|
||||||
prev_comments = []
|
preceeding_comments = []
|
||||||
if node.parent_name.len > 0 {
|
if node.parent_name.len > 0 {
|
||||||
parent_name := node.parent_name
|
parent_name := node.parent_name
|
||||||
if node.parent_name == 'Constants' {
|
if node.parent_name == 'Constants' {
|
||||||
|
|
|
@ -45,3 +45,26 @@ pub fn (cnts map[string]DocNode) arr() []DocNode {
|
||||||
contents.sort_by_kind()
|
contents.sort_by_kind()
|
||||||
return contents
|
return contents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// merge_comments returns a `string` with the combined contents of `DocNode.comments`.
|
||||||
|
pub fn (dc DocNode) merge_comments() string {
|
||||||
|
return merge_doc_comments(dc.comments)
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge_comments_without_examples returns a `string` with the
|
||||||
|
// combined contents of `DocNode.comments` - excluding any examples.
|
||||||
|
pub fn (dc DocNode) merge_comments_without_examples() string {
|
||||||
|
sans_examples := dc.comments.filter(!it.is_example())
|
||||||
|
return merge_doc_comments(sans_examples)
|
||||||
|
}
|
||||||
|
|
||||||
|
// examples returns a `[]string` containing examples parsed from `DocNode.comments`.
|
||||||
|
pub fn (dn DocNode) examples() []string {
|
||||||
|
mut output := []string{}
|
||||||
|
for comment in dn.comments {
|
||||||
|
if comment.is_example() {
|
||||||
|
output << comment.example()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,33 @@ pub fn merge_comments(comments []ast.Comment) string {
|
||||||
return res.join('\n')
|
return res.join('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_comment_block_right_before merges all the comments starting from
|
// ast_comment_to_doc_comment converts an `ast.Comment` node type to a `DocComment`
|
||||||
|
pub fn ast_comment_to_doc_comment(ast_node ast.Comment) DocComment {
|
||||||
|
text := ast_node.text // TODO .trim_left('\x01') // BUG why are this byte here in the first place?
|
||||||
|
return DocComment{
|
||||||
|
text: text
|
||||||
|
is_multi: ast_node.is_multi
|
||||||
|
pos: DocPos{
|
||||||
|
line: ast_node.pos.line_nr - 1
|
||||||
|
col: 0 // ast_node.pos.pos - ast_node.text.len
|
||||||
|
len: text.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ast_comments_to_doc_comments converts an array of `ast.Comment` nodes to
|
||||||
|
// an array of `DocComment` nodes
|
||||||
|
pub fn ast_comments_to_doc_comments(ast_nodes []ast.Comment) []DocComment {
|
||||||
|
mut doc_comments := []DocComment{len: ast_nodes.len}
|
||||||
|
for ast_comment in ast_nodes {
|
||||||
|
doc_comments << ast_comment_to_doc_comment(ast_comment)
|
||||||
|
}
|
||||||
|
return doc_comments
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge_doc_comments merges all the comments starting from
|
||||||
// the last up to the first item of the array.
|
// the last up to the first item of the array.
|
||||||
pub fn get_comment_block_right_before(comments []ast.Comment) string {
|
pub fn merge_doc_comments(comments []DocComment) string {
|
||||||
if comments.len == 0 {
|
if comments.len == 0 {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -26,7 +50,7 @@ pub fn get_comment_block_right_before(comments []ast.Comment) string {
|
||||||
mut last_comment_line_nr := 0
|
mut last_comment_line_nr := 0
|
||||||
for i := comments.len - 1; i >= 0; i-- {
|
for i := comments.len - 1; i >= 0; i-- {
|
||||||
cmt := comments[i]
|
cmt := comments[i]
|
||||||
if last_comment_line_nr != 0 && cmt.pos.line_nr < last_comment_line_nr - 1 {
|
if last_comment_line_nr != 0 && cmt.pos.line < last_comment_line_nr - 1 {
|
||||||
// skip comments that are not part of a continuous block,
|
// skip comments that are not part of a continuous block,
|
||||||
// located right above the top level statement.
|
// located right above the top level statement.
|
||||||
// break
|
// break
|
||||||
|
@ -58,7 +82,7 @@ pub fn get_comment_block_right_before(comments []ast.Comment) string {
|
||||||
// eprintln('cmt: $cmt')
|
// eprintln('cmt: $cmt')
|
||||||
cseparator := if cmt_content.starts_with('```') { '\n' } else { ' ' }
|
cseparator := if cmt_content.starts_with('```') { '\n' } else { ' ' }
|
||||||
comment = cmt_content + cseparator + comment
|
comment = cmt_content + cseparator + comment
|
||||||
last_comment_line_nr = cmt.pos.line_nr
|
last_comment_line_nr = cmt.pos.line
|
||||||
}
|
}
|
||||||
return comment
|
return comment
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue