]> git.lizzy.rs Git - rust.git/blob - src/librustc_errors/snippet.rs
Do not show `::constructor` on tuple struct diagnostics
[rust.git] / src / librustc_errors / snippet.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Code for annotating snippets.
12
13 use syntax_pos::{Span, FileMap};
14 use CodeMapper;
15 use std::rc::Rc;
16 use Level;
17
18 #[derive(Clone)]
19 pub struct SnippetData {
20     codemap: Rc<CodeMapper>,
21     files: Vec<FileInfo>,
22 }
23
24 #[derive(Clone)]
25 pub struct FileInfo {
26     file: Rc<FileMap>,
27
28     /// The "primary file", if any, gets a `-->` marker instead of
29     /// `>>>`, and has a line-number/column printed and not just a
30     /// filename.  It appears first in the listing. It is known to
31     /// contain at least one primary span, though primary spans (which
32     /// are designated with `^^^`) may also occur in other files.
33     primary_span: Option<Span>,
34
35     lines: Vec<Line>,
36 }
37
38 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
39 pub struct Line {
40     pub line_index: usize,
41     pub annotations: Vec<Annotation>,
42 }
43
44
45 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
46 pub struct MultilineAnnotation {
47     pub depth: usize,
48     pub line_start: usize,
49     pub line_end: usize,
50     pub start_col: usize,
51     pub end_col: usize,
52     pub is_primary: bool,
53     pub label: Option<String>,
54 }
55
56 impl MultilineAnnotation {
57     pub fn increase_depth(&mut self) {
58         self.depth += 1;
59     }
60
61     pub fn as_start(&self) -> Annotation {
62         Annotation {
63             start_col: self.start_col,
64             end_col: self.start_col + 1,
65             is_primary: self.is_primary,
66             label: Some("starting here...".to_owned()),
67             annotation_type: AnnotationType::MultilineStart(self.depth)
68         }
69     }
70
71     pub fn as_end(&self) -> Annotation {
72         Annotation {
73             start_col: self.end_col - 1,
74             end_col: self.end_col,
75             is_primary: self.is_primary,
76             label: match self.label {
77                 Some(ref label) => Some(format!("...ending here: {}", label)),
78                 None => Some("...ending here".to_owned()),
79             },
80             annotation_type: AnnotationType::MultilineEnd(self.depth)
81         }
82     }
83
84     pub fn as_line(&self) -> Annotation {
85         Annotation {
86             start_col: 0,
87             end_col: 0,
88             is_primary: self.is_primary,
89             label: None,
90             annotation_type: AnnotationType::MultilineLine(self.depth)
91         }
92     }
93 }
94
95 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
96 pub enum AnnotationType {
97     /// Annotation under a single line of code
98     Singleline,
99
100     /// Annotation enclosing the first and last character of a multiline span
101     Multiline(MultilineAnnotation),
102
103     // The Multiline type above is replaced with the following three in order
104     // to reuse the current label drawing code.
105     //
106     // Each of these corresponds to one part of the following diagram:
107     //
108     //     x |   foo(1 + bar(x,
109     //       |  _________^ starting here...           < MultilineStart
110     //     x | |             y),                      < MultilineLine
111     //       | |______________^ ...ending here: label < MultilineEnd
112     //     x |       z);
113     /// Annotation marking the first character of a fully shown multiline span
114     MultilineStart(usize),
115     /// Annotation marking the last character of a fully shown multiline span
116     MultilineEnd(usize),
117     /// Line at the left enclosing the lines of a fully shown multiline span
118     // Just a placeholder for the drawing algorithm, to know that it shouldn't skip the first 4
119     // and last 2 lines of code. The actual line is drawn in `emit_message_default` and not in
120     // `draw_multiline_line`.
121     MultilineLine(usize),
122 }
123
124 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
125 pub struct Annotation {
126     /// Start column, 0-based indexing -- counting *characters*, not
127     /// utf-8 bytes. Note that it is important that this field goes
128     /// first, so that when we sort, we sort orderings by start
129     /// column.
130     pub start_col: usize,
131
132     /// End column within the line (exclusive)
133     pub end_col: usize,
134
135     /// Is this annotation derived from primary span
136     pub is_primary: bool,
137
138     /// Optional label to display adjacent to the annotation.
139     pub label: Option<String>,
140
141     /// Is this a single line, multiline or multiline span minimized down to a
142     /// smaller span.
143     pub annotation_type: AnnotationType,
144 }
145
146 impl Annotation {
147     /// Wether this annotation is a vertical line placeholder.
148     pub fn is_line(&self) -> bool {
149         if let AnnotationType::MultilineLine(_) = self.annotation_type {
150             true
151         } else {
152             false
153         }
154     }
155
156     pub fn is_multiline(&self) -> bool {
157         match self.annotation_type {
158             AnnotationType::Multiline(_) |
159             AnnotationType::MultilineStart(_) |
160             AnnotationType::MultilineLine(_) |
161             AnnotationType::MultilineEnd(_) => true,
162             _ => false,
163         }
164     }
165
166     pub fn len(&self) -> usize {
167         // Account for usize underflows
168         if self.end_col > self.start_col {
169             self.end_col - self.start_col
170         } else {
171             self.start_col - self.end_col
172         }
173     }
174
175     pub fn has_label(&self) -> bool {
176         if let Some(ref label) = self.label {
177             // Consider labels with no text as effectively not being there
178             // to avoid weird output with unnecessary vertical lines, like:
179             //
180             //     X | fn foo(x: u32) {
181             //       | -------^------
182             //       | |      |
183             //       | |
184             //       |
185             //
186             // Note that this would be the complete output users would see.
187             label.len() > 0
188         } else {
189             false
190         }
191     }
192 }
193
194 #[derive(Debug)]
195 pub struct StyledString {
196     pub text: String,
197     pub style: Style,
198 }
199
200 #[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
201 pub enum Style {
202     HeaderMsg,
203     FileNameStyle,
204     LineAndColumn,
205     LineNumber,
206     Quotation,
207     UnderlinePrimary,
208     UnderlineSecondary,
209     LabelPrimary,
210     LabelSecondary,
211     OldSchoolNoteText,
212     OldSchoolNote,
213     NoStyle,
214     ErrorCode,
215     Level(Level),
216     Highlight,
217 }