func collect_doc_comments(source: String, outcome: &ParseOutcome) -> DocIndexAttaches leading line-comment groups without changing the parser token stream.
A group must end on the line immediately before a declaration after skipping declaration modifiers. Imports may be crossed as one block, but any blank line breaks attachment. The merge is ordered and local declarations are excluded.
View Source
pub func collect_doc_comments(source: String, outcome: &ParseOutcome) -> DocIndex {
let view = source.utf8()
let spans = collect_item_spans(items: outcome.items, spans: [])
let entries: [DocumentedDecl] = []
let orphans: [Comment] = []
let group: [Comment] = []
let si = 0
for c in outcome.comments {
// A comment sharing its line with preceding code is trailing.
let trailing = false
let j = c.start - 1
loop j >= 0 {
let b = view.at(index: j)._toInt()
if b == newline_byte { break }
if b == space_byte || b == tab_byte || b == return_byte {
j = j - 1
continue
}
trailing = true
break
}
if trailing {
let f = flush_group(source: source, group: group, spans: spans, si: si)
si = f.si
group = []
if let .some(e) = f.entry { entries.push(e) }
for o in f.orphans { orphans.push(Comment(start: o.start, end: o.end)) }
orphans.push(Comment(start: c.start, end: c.end))
continue
}
// `// no-core` is a compiler pragma, not documentation: it
// breaks the current group and never attaches.
if c.end - c.start == 10 {
let is_pragma = true
let pragma = "// no-core".utf8()
let p = 0
loop p < 10 {
if view.at(index: c.start + p)._toInt() != pragma.at(index: p)._toInt() {
is_pragma = false
break
}
p = p + 1
}
if is_pragma {
let f = flush_group(source: source, group: group, spans: spans, si: si)
si = f.si
group = []
if let .some(e) = f.entry { entries.push(e) }
for o in f.orphans { orphans.push(Comment(start: o.start, end: o.end)) }
orphans.push(Comment(start: c.start, end: c.end))
continue
}
}
// A group continues only across adjacent comment lines.
if group.is_empty() == false {
let k = group[group.count - 1].end
let newlines = 0
let blocked = false
loop k < c.start {
let b = view.at(index: k)._toInt()
if b == newline_byte {
newlines = newlines + 1
} else if b == space_byte || b == tab_byte || b == return_byte { } else {
blocked = true
}
k = k + 1
}
if blocked || newlines != 1 {
let f = flush_group(source: source, group: group, spans: spans, si: si)
si = f.si
group = []
if let .some(e) = f.entry { entries.push(e) }
for o in f.orphans { orphans.push(Comment(start: o.start, end: o.end)) }
}
}
group.push(Comment(start: c.start, end: c.end))
}
let f = flush_group(source: source, group: group, spans: spans, si: si)
if let .some(e) = f.entry { entries.push(e) }
for o in f.orphans { orphans.push(Comment(start: o.start, end: o.end)) }
DocIndex(entries: entries, orphans: orphans)
}