language_reporting/
components.rs

1#![allow(non_snake_case)]
2
3use crate::emitter::DiagnosticData;
4use crate::models::severity;
5use crate::render_tree::prelude::*;
6use crate::ReportingFiles;
7use crate::{models, Location};
8
9pub(crate) fn Diagnostic<'args>(data: DiagnosticData<'args, impl ReportingFiles>, into: Document) -> Document {
10    let header = models::Header::new(&data.diagnostic);
11
12    into.add(tree! {
13        <Section name={severity(&data.diagnostic)} as {
14            <Header args={header}>
15            <Body args={data}>
16        }>
17    })
18}
19
20pub(crate) fn Header<'args>(header: models::Header<'args>, into: Document) -> Document {
21    into.add(tree! {
22        <Section name="header" as {
23            <Line as {
24                <Section name="primary" as {
25                    // error
26                    {header.severity()}
27                    // [E0001]
28                    {IfSome(header.code(), |code| tree! { "[" {code} "]" })}
29                }>
30                ": "
31                // Unexpected type in `+` application
32                {header.message()}
33            }>
34        }>
35    })
36}
37
38pub(crate) fn Body<'args>(data: DiagnosticData<'args, impl ReportingFiles>, mut into: Document) -> Document {
39    for label in &data.diagnostic.labels {
40        let source_line = models::SourceLine::new(data.files, label, data.config);
41        let labelled_line = models::LabelledLine::new(source_line.clone(), label);
42
43        into = into.add(tree! {
44            // - <test>:2:9
45            <SourceCodeLocation args={source_line}>
46
47            // 2 | (+ test "")
48            //   |         ^^
49            <SourceCodeLine args={labelled_line}>
50        });
51    }
52
53    into
54}
55
56pub(crate) fn SourceCodeLocation(
57    source_line: models::SourceLine<impl ReportingFiles>,
58    into: Document,
59) -> Document {
60    let Location { line, column } = source_line.location();
61    let filename = source_line.filename().to_string();
62
63    into.add(tree! {
64        <Section name="source-code-location" as {
65            <Line as {
66                // - <test>:3:9
67                "- " {filename} ":" {line + 1}
68                ":" {column}
69            }>
70        }>
71    })
72}
73
74pub(crate) fn SourceCodeLine<'args>(
75    model: models::LabelledLine<'args, impl ReportingFiles>,
76    into: Document,
77) -> Document {
78    let source_line = model.source_line();
79
80    into.add(tree! {
81        <Line as {
82            <Section name="gutter" as {
83                {source_line.line_number()}
84                " | "
85            }>
86
87            <Section name="before-marked" as {
88                {source_line.before_marked()}
89            }>
90
91            <Section name={model.style()} as {
92                {model.source_line().marked()}
93            }>
94
95            <Section name="after-marked" as {
96                {source_line.after_marked()}
97            }>
98        }>
99
100        <Line as {
101            <Section name="underline" as {
102                <Section name="gutter" as {
103                    {repeat(" ", model.source_line().line_number_len())}
104                    " | "
105                }>
106
107                {repeat(" ", model.source_line().before_marked().len())}
108
109                <Section name={model.style()} as {
110                    {repeat(model.mark(), model.source_line().marked().len())}
111                    {IfSome(model.message(), |message| tree!({" "} {message}))}
112                }>
113            }>
114        }>
115    })
116}