about summary refs log tree commit diff
path: root/src/libsyntax/errors
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-04-20 14:57:20 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-05-02 11:47:10 -0400
commite7c7a18d94cf672d6a031455d091e0bebe1a6b7c (patch)
treeee98b75622f96471777a18882ad24b06e04af2ce /src/libsyntax/errors
parenta20ee76b56c46a593238ce7ac9b9f70a99c43ff4 (diff)
downloadrust-e7c7a18d94cf672d6a031455d091e0bebe1a6b7c.tar.gz
rust-e7c7a18d94cf672d6a031455d091e0bebe1a6b7c.zip
adapt JSON to new model
Each Span now carries a `is_primary` boolean along with an optional
label. If there are multiple labels for a span, it will appear multiple
times.
Diffstat (limited to 'src/libsyntax/errors')
-rw-r--r--src/libsyntax/errors/json.rs202
1 files changed, 83 insertions, 119 deletions
diff --git a/src/libsyntax/errors/json.rs b/src/libsyntax/errors/json.rs
index 821617bfe89..b343c3f3fbb 100644
--- a/src/libsyntax/errors/json.rs
+++ b/src/libsyntax/errors/json.rs
@@ -20,7 +20,7 @@
 // FIXME spec the JSON output properly.
 
 
-use codemap::{self, Span, MacroBacktrace, MultiSpan, CodeMap};
+use codemap::{self, MacroBacktrace, Span, SpanLabel, MultiSpan, CodeMap};
 use diagnostics::registry::Registry;
 use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion};
 use errors::emitter::Emitter;
@@ -53,20 +53,13 @@ impl JsonEmitter {
 }
 
 impl Emitter for JsonEmitter {
-    fn emit(&mut self, span: Option<&MultiSpan>, msg: &str, code: Option<&str>, level: Level) {
+    fn emit(&mut self, span: &MultiSpan, msg: &str, code: Option<&str>, level: Level) {
         let data = Diagnostic::new(span, msg, code, level, self);
         if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
             panic!("failed to print diagnostics: {:?}", e);
         }
     }
 
-    fn custom_emit(&mut self, sp: &RenderSpan, msg: &str, level: Level) {
-        let data = Diagnostic::from_render_span(sp, msg, level, self);
-        if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
-            panic!("failed to print diagnostics: {:?}", e);
-        }
-    }
-
     fn emit_struct(&mut self, db: &DiagnosticBuilder) {
         let data = Diagnostic::from_diagnostic_builder(db, self);
         if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
@@ -104,8 +97,13 @@ struct DiagnosticSpan {
     /// 1-based, character offset.
     column_start: usize,
     column_end: usize,
+    /// Is this a "primary" span -- meaning the point, or one of the points,
+    /// where the error occurred?
+    is_primary: bool,
     /// Source text from the start of line_start to the end of line_end.
     text: Vec<DiagnosticSpanLine>,
+    /// Label that should be placed at this location (if any)
+    label: Option<String>,
     /// If we are suggesting a replacement, this will contain text
     /// that should be sliced in atop this span. You may prefer to
     /// load the fully rendered version from the parent `Diagnostic`,
@@ -148,7 +146,7 @@ struct DiagnosticCode {
 }
 
 impl<'a> Diagnostic<'a> {
-    fn new(msp: Option<&MultiSpan>,
+    fn new(msp: &MultiSpan,
            msg: &'a str,
            code: Option<&str>,
            level: Level,
@@ -158,27 +156,12 @@ impl<'a> Diagnostic<'a> {
             message: msg,
             code: DiagnosticCode::map_opt_string(code.map(|c| c.to_owned()), je),
             level: level.to_str(),
-            spans: msp.map_or(vec![], |msp| DiagnosticSpan::from_multispan(msp, je)),
+            spans: DiagnosticSpan::from_multispan(msp, je),
             children: vec![],
             rendered: None,
         }
     }
 
-    fn from_render_span(span: &RenderSpan,
-                        msg: &'a str,
-                        level: Level,
-                        je: &JsonEmitter)
-                        -> Diagnostic<'a> {
-        Diagnostic {
-            message: msg,
-            code: None,
-            level: level.to_str(),
-            spans: DiagnosticSpan::from_render_span(span, je),
-            children: vec![],
-            rendered: je.render(span),
-        }
-    }
-
     fn from_diagnostic_builder<'c>(db: &'c DiagnosticBuilder,
                                    je: &JsonEmitter)
                                    -> Diagnostic<'c> {
@@ -186,7 +169,7 @@ impl<'a> Diagnostic<'a> {
             message: &db.message,
             code: DiagnosticCode::map_opt_string(db.code.clone(), je),
             level: db.level.to_str(),
-            spans: db.span.as_ref().map_or(vec![], |sp| DiagnosticSpan::from_multispan(sp, je)),
+            spans: DiagnosticSpan::from_multispan(&db.span, je),
             children: db.children.iter().map(|c| {
                 Diagnostic::from_sub_diagnostic(c, je)
             }).collect(),
@@ -201,8 +184,7 @@ impl<'a> Diagnostic<'a> {
             level: db.level.to_str(),
             spans: db.render_span.as_ref()
                      .map(|sp| DiagnosticSpan::from_render_span(sp, je))
-                     .or_else(|| db.span.as_ref().map(|s| DiagnosticSpan::from_multispan(s, je)))
-                     .unwrap_or(vec![]),
+                     .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
             children: vec![],
             rendered: db.render_span.as_ref()
                                     .and_then(|rsp| je.render(rsp)),
@@ -211,44 +193,68 @@ impl<'a> Diagnostic<'a> {
 }
 
 impl DiagnosticSpan {
-    fn from_span(span: Span, suggestion: Option<&String>, je: &JsonEmitter)
-                 -> DiagnosticSpan {
+    fn from_span_label(span: SpanLabel,
+                       suggestion: Option<&String>,
+                       je: &JsonEmitter)
+                       -> DiagnosticSpan {
+        Self::from_span_etc(span.span,
+                            span.is_primary,
+                            span.label,
+                            suggestion,
+                            je)
+    }
+
+    fn from_span_etc(span: Span,
+                     is_primary: bool,
+                     label: Option<String>,
+                     suggestion: Option<&String>,
+                     je: &JsonEmitter)
+                     -> DiagnosticSpan {
         // obtain the full backtrace from the `macro_backtrace`
         // helper; in some ways, it'd be better to expand the
         // backtrace ourselves, but the `macro_backtrace` helper makes
         // some decision, such as dropping some frames, and I don't
         // want to duplicate that logic here.
         let backtrace = je.cm.macro_backtrace(span).into_iter();
-        DiagnosticSpan::from_span_and_backtrace(span, suggestion, backtrace, je)
+        DiagnosticSpan::from_span_full(span,
+                                       is_primary,
+                                       label,
+                                       suggestion,
+                                       backtrace,
+                                       je)
     }
 
-    fn from_span_and_backtrace(span: Span,
-                               suggestion: Option<&String>,
-                               mut backtrace: vec::IntoIter<MacroBacktrace>,
-                               je: &JsonEmitter)
-                               -> DiagnosticSpan {
+    fn from_span_full(span: Span,
+                      is_primary: bool,
+                      label: Option<String>,
+                      suggestion: Option<&String>,
+                      mut backtrace: vec::IntoIter<MacroBacktrace>,
+                      je: &JsonEmitter)
+                      -> DiagnosticSpan {
         let start = je.cm.lookup_char_pos(span.lo);
         let end = je.cm.lookup_char_pos(span.hi);
-        let backtrace_step =
-            backtrace.next()
-                     .map(|bt| {
-                         let call_site =
-                             Self::from_span_and_backtrace(bt.call_site,
-                                                           None,
-                                                           backtrace,
-                                                           je);
-                         let def_site_span = bt.def_site_span.map(|sp| {
-                             Self::from_span_and_backtrace(sp,
-                                                           None,
-                                                           vec![].into_iter(),
-                                                           je)
-                         });
-                         Box::new(DiagnosticSpanMacroExpansion {
-                             span: call_site,
-                             macro_decl_name: bt.macro_decl_name,
-                             def_site_span: def_site_span,
-                         })
-                     });
+        let backtrace_step = backtrace.next().map(|bt| {
+            let call_site =
+                Self::from_span_full(bt.call_site,
+                                     false,
+                                     None,
+                                     None,
+                                     backtrace,
+                                     je);
+            let def_site_span = bt.def_site_span.map(|sp| {
+                Self::from_span_full(sp,
+                                     false,
+                                     None,
+                                     None,
+                                     vec![].into_iter(),
+                                     je)
+            });
+            Box::new(DiagnosticSpanMacroExpansion {
+                span: call_site,
+                macro_decl_name: bt.macro_decl_name,
+                def_site_span: def_site_span,
+            })
+        });
         DiagnosticSpan {
             file_name: start.file.name.clone(),
             byte_start: span.lo.0,
@@ -257,53 +263,42 @@ impl DiagnosticSpan {
             line_end: end.line,
             column_start: start.col.0 + 1,
             column_end: end.col.0 + 1,
+            is_primary: is_primary,
             text: DiagnosticSpanLine::from_span(span, je),
             suggested_replacement: suggestion.cloned(),
             expansion: backtrace_step,
+            label: label,
         }
     }
 
     fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
-        msp.spans.iter().map(|&span| Self::from_span(span, None, je)).collect()
+        msp.span_labels()
+           .into_iter()
+           .map(|span_str| Self::from_span_label(span_str, None, je))
+           .collect()
     }
 
     fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
                        -> Vec<DiagnosticSpan> {
-        assert_eq!(suggestion.msp.spans.len(), suggestion.substitutes.len());
-        suggestion.msp.spans.iter()
-                            .zip(&suggestion.substitutes)
-                            .map(|(&span, suggestion)| {
-                                DiagnosticSpan::from_span(span, Some(suggestion), je)
-                            })
-                            .collect()
+        assert_eq!(suggestion.msp.span_labels().len(), suggestion.substitutes.len());
+        suggestion.msp.span_labels()
+                      .into_iter()
+                      .zip(&suggestion.substitutes)
+                      .map(|(span_label, suggestion)| {
+                          DiagnosticSpan::from_span_label(span_label,
+                                                          Some(suggestion),
+                                                          je)
+                      })
+                      .collect()
     }
 
     fn from_render_span(rsp: &RenderSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> {
         match *rsp {
             RenderSpan::FileLine(ref msp) |
-            RenderSpan::FullSpan(ref msp) => {
-                DiagnosticSpan::from_multispan(msp, je)
-            }
-            RenderSpan::Suggestion(ref suggestion) => {
-                DiagnosticSpan::from_suggestion(suggestion, je)
-            }
-            RenderSpan::EndSpan(ref msp) => {
-                msp.spans.iter().map(|&span| {
-                    let end = je.cm.lookup_char_pos(span.hi);
-                    DiagnosticSpan {
-                        file_name: end.file.name.clone(),
-                        byte_start: span.hi.0,
-                        byte_end: span.hi.0,
-                        line_start: end.line,
-                        line_end: end.line,
-                        column_start: end.col.0 + 1,
-                        column_end: end.col.0 + 1,
-                        text: DiagnosticSpanLine::from_span_end(span, je),
-                        suggested_replacement: None,
-                        expansion: None,
-                    }
-                }).collect()
-            }
+            RenderSpan::FullSpan(ref msp) =>
+                DiagnosticSpan::from_multispan(msp, je),
+            RenderSpan::Suggestion(ref suggestion) =>
+                DiagnosticSpan::from_suggestion(suggestion, je),
         }
     }
 }
@@ -340,34 +335,6 @@ impl DiagnosticSpanLine {
              })
             .unwrap_or(vec![])
     }
-
-    /// Create a list of DiagnosticSpanLines from span - the result covers all
-    /// of `span`, but the highlight is zero-length and at the end of `span`.
-    fn from_span_end(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
-        je.cm.span_to_lines(span)
-             .map(|lines| {
-                 let fm = &*lines.file;
-                 lines.lines.iter()
-                            .enumerate()
-                            .map(|(i, line)| {
-                                // Invariant - CodeMap::span_to_lines
-                                // will not return extra context lines
-                                // - the last line returned is the last
-                                // line of `span`.
-                                let highlight = if i == lines.lines.len() - 1 {
-                                    (line.end_col.0 + 1, line.end_col.0 + 1)
-                                } else {
-                                    (0, 0)
-                                };
-                                DiagnosticSpanLine::line_from_filemap(fm,
-                                                                      line.line_index,
-                                                                      highlight.0,
-                                                                      highlight.1)
-                            })
-                            .collect()
-             })
-            .unwrap_or(vec![])
-    }
 }
 
 impl DiagnosticCode {
@@ -396,9 +363,6 @@ impl JsonEmitter {
             RenderSpan::Suggestion(ref suggestion) => {
                 Some(suggestion.splice_lines(&self.cm))
             }
-            RenderSpan::EndSpan(_) => {
-                None
-            }
         }
     }
 }