Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
197
vendor/codespan-reporting/examples/custom_files.rs
vendored
Normal file
197
vendor/codespan-reporting/examples/custom_files.rs
vendored
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
//! An example that shows how to implement a simple custom file database.
|
||||
//! The database uses 32-bit file-ids, which could be useful for optimizing
|
||||
//! memory usage.
|
||||
//!
|
||||
//! To run this example, execute the following command from the top level of
|
||||
//! this repository:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example custom_files
|
||||
//! ```
|
||||
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::term;
|
||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||
use std::ops::Range;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let mut files = files::Files::new();
|
||||
|
||||
let file_id0 = files.add("0.greeting", "hello world!").unwrap();
|
||||
let file_id1 = files.add("1.greeting", "bye world").unwrap();
|
||||
|
||||
let messages = vec![
|
||||
Message::UnwantedGreetings {
|
||||
greetings: vec![(file_id0, 0..5), (file_id1, 0..3)],
|
||||
},
|
||||
Message::OverTheTopExclamations {
|
||||
exclamations: vec![(file_id0, 11..12)],
|
||||
},
|
||||
];
|
||||
|
||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||
let config = term::Config::default();
|
||||
for message in &messages {
|
||||
let writer = &mut writer.lock();
|
||||
term::emit(writer, &config, &files, &message.to_diagnostic())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A module containing the file implementation
|
||||
mod files {
|
||||
use codespan_reporting::files;
|
||||
use std::ops::Range;
|
||||
|
||||
/// A file that is backed by an `Arc<String>`.
|
||||
#[derive(Debug, Clone)]
|
||||
struct File {
|
||||
/// The name of the file.
|
||||
name: String,
|
||||
/// The source code of the file.
|
||||
source: String,
|
||||
/// The starting byte indices in the source code.
|
||||
line_starts: Vec<usize>,
|
||||
}
|
||||
|
||||
impl File {
|
||||
fn line_start(&self, line_index: usize) -> Result<usize, files::Error> {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
match line_index.cmp(&self.line_starts.len()) {
|
||||
Ordering::Less => Ok(self
|
||||
.line_starts
|
||||
.get(line_index)
|
||||
.expect("failed despite previous check")
|
||||
.clone()),
|
||||
Ordering::Equal => Ok(self.source.len()),
|
||||
Ordering::Greater => Err(files::Error::LineTooLarge {
|
||||
given: line_index,
|
||||
max: self.line_starts.len() - 1,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An opaque file identifier.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct FileId(u32);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Files {
|
||||
files: Vec<File>,
|
||||
}
|
||||
|
||||
impl Files {
|
||||
/// Create a new files database.
|
||||
pub fn new() -> Files {
|
||||
Files { files: Vec::new() }
|
||||
}
|
||||
|
||||
/// Add a file to the database, returning the handle that can be used to
|
||||
/// refer to it again.
|
||||
pub fn add(
|
||||
&mut self,
|
||||
name: impl Into<String>,
|
||||
source: impl Into<String>,
|
||||
) -> Option<FileId> {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let file_id = FileId(u32::try_from(self.files.len()).ok()?);
|
||||
let name = name.into();
|
||||
let source = source.into();
|
||||
let line_starts = files::line_starts(&source).collect();
|
||||
|
||||
self.files.push(File {
|
||||
name,
|
||||
line_starts,
|
||||
source,
|
||||
});
|
||||
|
||||
Some(file_id)
|
||||
}
|
||||
|
||||
/// Get the file corresponding to the given id.
|
||||
fn get(&self, file_id: FileId) -> Result<&File, files::Error> {
|
||||
self.files
|
||||
.get(file_id.0 as usize)
|
||||
.ok_or(files::Error::FileMissing)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'files> files::Files<'files> for Files {
|
||||
type FileId = FileId;
|
||||
type Name = &'files str;
|
||||
type Source = &'files str;
|
||||
|
||||
fn name(&self, file_id: FileId) -> Result<&str, files::Error> {
|
||||
Ok(self.get(file_id)?.name.as_ref())
|
||||
}
|
||||
|
||||
fn source(&self, file_id: FileId) -> Result<&str, files::Error> {
|
||||
Ok(&self.get(file_id)?.source)
|
||||
}
|
||||
|
||||
fn line_index(&self, file_id: FileId, byte_index: usize) -> Result<usize, files::Error> {
|
||||
self.get(file_id)?
|
||||
.line_starts
|
||||
.binary_search(&byte_index)
|
||||
.or_else(|next_line| Ok(next_line - 1))
|
||||
}
|
||||
|
||||
fn line_range(
|
||||
&self,
|
||||
file_id: FileId,
|
||||
line_index: usize,
|
||||
) -> Result<Range<usize>, files::Error> {
|
||||
let file = self.get(file_id)?;
|
||||
let line_start = file.line_start(line_index)?;
|
||||
let next_line_start = file.line_start(line_index + 1)?;
|
||||
|
||||
Ok(line_start..next_line_start)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Diagnostic message.
|
||||
enum Message {
|
||||
UnwantedGreetings {
|
||||
greetings: Vec<(files::FileId, Range<usize>)>,
|
||||
},
|
||||
OverTheTopExclamations {
|
||||
exclamations: Vec<(files::FileId, Range<usize>)>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Message {
|
||||
fn to_diagnostic(&self) -> Diagnostic<files::FileId> {
|
||||
match self {
|
||||
Message::UnwantedGreetings { greetings } => Diagnostic::error()
|
||||
.with_message("greetings are not allowed")
|
||||
.with_labels(
|
||||
greetings
|
||||
.iter()
|
||||
.map(|(file_id, range)| {
|
||||
Label::primary(*file_id, range.clone()).with_message("a greeting")
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.with_notes(vec![
|
||||
"found greetings!".to_owned(),
|
||||
"pleas no greetings :(".to_owned(),
|
||||
]),
|
||||
Message::OverTheTopExclamations { exclamations } => Diagnostic::error()
|
||||
.with_message("over-the-top exclamations")
|
||||
.with_labels(
|
||||
exclamations
|
||||
.iter()
|
||||
.map(|(file_id, range)| {
|
||||
Label::primary(*file_id, range.clone()).with_message("an exclamation")
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.with_notes(vec!["ridiculous!".to_owned()]),
|
||||
}
|
||||
}
|
||||
}
|
||||
68
vendor/codespan-reporting/examples/peg_calculator.rs
vendored
Normal file
68
vendor/codespan-reporting/examples/peg_calculator.rs
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//! An example of using `peg` with `codespan_reporting`.
|
||||
//!
|
||||
//! To run this example, execute the following command from the top level of
|
||||
//! this repository:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example peg_calculator
|
||||
//! ```
|
||||
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::files::SimpleFile;
|
||||
use codespan_reporting::term;
|
||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
|
||||
peg::parser! {
|
||||
grammar arithmetic() for str {
|
||||
rule number() -> i64
|
||||
= n:$(['0'..='9']+) { n.parse().unwrap() }
|
||||
|
||||
pub rule calculate() -> i64 = precedence!{
|
||||
x:(@) "+" y:@ { x + y }
|
||||
x:(@) "-" y:@ { x - y }
|
||||
"-" v:@ { - v }
|
||||
--
|
||||
x:(@) "*" y:@ { x * y }
|
||||
x:(@) "/" y:@ { x / y }
|
||||
--
|
||||
x:@ "^" y:(@) { i64::pow(x, y as u32) }
|
||||
v:@ "!" { (1..v+1).product() }
|
||||
--
|
||||
"(" v:calculate() ")" { v }
|
||||
n:number() { n }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
let mut editor = Editor::<()>::new();
|
||||
|
||||
loop {
|
||||
let line = match editor.readline("> ") {
|
||||
Ok(line) => line,
|
||||
Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => return Ok(()),
|
||||
Err(error) => return Err(error.into()),
|
||||
};
|
||||
|
||||
match arithmetic::calculate(&line) {
|
||||
Ok(number) => println!("{}", number),
|
||||
Err(error) => {
|
||||
let file = SimpleFile::new("<repl>", line);
|
||||
|
||||
let start = error.location.offset;
|
||||
let diagnostic = Diagnostic::error()
|
||||
.with_message("parse error")
|
||||
.with_labels(vec![
|
||||
Label::primary((), start..start).with_message("parse error")
|
||||
])
|
||||
.with_notes(vec![format!("expected: {}", error.expected)]);
|
||||
|
||||
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
356
vendor/codespan-reporting/examples/readme_preview.rs
vendored
Normal file
356
vendor/codespan-reporting/examples/readme_preview.rs
vendored
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
//! Renders the preview SVG for the README.
|
||||
//!
|
||||
//! To update the preview, execute the following command from the top level of
|
||||
//! the repository:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example readme_preview svg > codespan-reporting/assets/readme_preview.svg
|
||||
//! ```
|
||||
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::files::SimpleFile;
|
||||
use codespan_reporting::term::termcolor::{Color, ColorSpec, StandardStream, WriteColor};
|
||||
use codespan_reporting::term::{self, ColorArg};
|
||||
use std::io::{self, Write};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "emit")]
|
||||
pub enum Opts {
|
||||
/// Render SVG output
|
||||
Svg,
|
||||
/// Render Stderr output
|
||||
Stderr {
|
||||
/// Configure coloring of output
|
||||
#[structopt(
|
||||
long = "color",
|
||||
parse(try_from_str),
|
||||
default_value = "auto",
|
||||
possible_values = ColorArg::VARIANTS,
|
||||
case_insensitive = true
|
||||
)]
|
||||
color: ColorArg,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let file = SimpleFile::new(
|
||||
"FizzBuzz.fun",
|
||||
unindent::unindent(
|
||||
r#"
|
||||
module FizzBuzz where
|
||||
|
||||
fizz₁ : Nat → String
|
||||
fizz₁ num = case (mod num 5) (mod num 3) of
|
||||
0 0 => "FizzBuzz"
|
||||
0 _ => "Fizz"
|
||||
_ 0 => "Buzz"
|
||||
_ _ => num
|
||||
|
||||
fizz₂ : Nat → String
|
||||
fizz₂ num =
|
||||
case (mod num 5) (mod num 3) of
|
||||
0 0 => "FizzBuzz"
|
||||
0 _ => "Fizz"
|
||||
_ 0 => "Buzz"
|
||||
_ _ => num
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
let diagnostics = [Diagnostic::error()
|
||||
.with_message("`case` clauses have incompatible types")
|
||||
.with_code("E0308")
|
||||
.with_labels(vec![
|
||||
Label::primary((), 328..331).with_message("expected `String`, found `Nat`"),
|
||||
Label::secondary((), 211..331).with_message("`case` clauses have incompatible types"),
|
||||
Label::secondary((), 258..268).with_message("this is found to be of type `String`"),
|
||||
Label::secondary((), 284..290).with_message("this is found to be of type `String`"),
|
||||
Label::secondary((), 306..312).with_message("this is found to be of type `String`"),
|
||||
Label::secondary((), 186..192).with_message("expected type `String` found here"),
|
||||
])
|
||||
.with_notes(vec![unindent::unindent(
|
||||
"
|
||||
expected type `String`
|
||||
found type `Nat`
|
||||
",
|
||||
)])];
|
||||
|
||||
// let mut files = SimpleFiles::new();
|
||||
match Opts::from_args() {
|
||||
Opts::Svg => {
|
||||
let mut buffer = Vec::new();
|
||||
let mut writer = HtmlEscapeWriter::new(SvgWriter::new(&mut buffer));
|
||||
let config = codespan_reporting::term::Config {
|
||||
styles: codespan_reporting::term::Styles::with_blue(Color::Blue),
|
||||
..codespan_reporting::term::Config::default()
|
||||
};
|
||||
|
||||
for diagnostic in &diagnostics {
|
||||
term::emit(&mut writer, &config, &file, &diagnostic)?;
|
||||
}
|
||||
|
||||
let num_lines = buffer.iter().filter(|byte| **byte == b'\n').count() + 1;
|
||||
|
||||
let padding = 10;
|
||||
let font_size = 12;
|
||||
let line_spacing = 3;
|
||||
let width = 882;
|
||||
let height = padding + num_lines * (font_size + line_spacing) + padding;
|
||||
|
||||
let stdout = std::io::stdout();
|
||||
let writer = &mut stdout.lock();
|
||||
|
||||
write!(
|
||||
writer,
|
||||
r#"<svg viewBox="0 0 {width} {height}" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
/* https://github.com/aaron-williamson/base16-alacritty/blob/master/colors/base16-tomorrow-night-256.yml */
|
||||
pre {{
|
||||
background: #1d1f21;
|
||||
margin: 0;
|
||||
padding: {padding}px;
|
||||
border-radius: 6px;
|
||||
color: #ffffff;
|
||||
font: {font_size}px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
}}
|
||||
|
||||
pre .bold {{ font-weight: bold; }}
|
||||
|
||||
pre .fg.black {{ color: #1d1f21; }}
|
||||
pre .fg.red {{ color: #cc6666; }}
|
||||
pre .fg.green {{ color: #b5bd68; }}
|
||||
pre .fg.yellow {{ color: #f0c674; }}
|
||||
pre .fg.blue {{ color: #81a2be; }}
|
||||
pre .fg.magenta {{ color: #b294bb; }}
|
||||
pre .fg.cyan {{ color: #8abeb7; }}
|
||||
pre .fg.white {{ color: #c5c8c6; }}
|
||||
|
||||
pre .fg.black.bright {{ color: #969896; }}
|
||||
pre .fg.red.bright {{ color: #cc6666; }}
|
||||
pre .fg.green.bright {{ color: #b5bd68; }}
|
||||
pre .fg.yellow.bright {{ color: #f0c674; }}
|
||||
pre .fg.blue.bright {{ color: #81a2be; }}
|
||||
pre .fg.magenta.bright {{ color: #b294bb; }}
|
||||
pre .fg.cyan.bright {{ color: #8abeb7; }}
|
||||
pre .fg.white.bright {{ color: #ffffff; }}
|
||||
|
||||
pre .bg.black {{ background-color: #1d1f21; }}
|
||||
pre .bg.red {{ background-color: #cc6666; }}
|
||||
pre .bg.green {{ background-color: #b5bd68; }}
|
||||
pre .bg.yellow {{ background-color: #f0c674; }}
|
||||
pre .bg.blue {{ background-color: #81a2be; }}
|
||||
pre .bg.magenta {{ background-color: #b294bb; }}
|
||||
pre .bg.cyan {{ background-color: #8abeb7; }}
|
||||
pre .bg.white {{ background-color: #c5c8c6; }}
|
||||
|
||||
pre .bg.black.bright {{ background-color: #969896; }}
|
||||
pre .bg.red.bright {{ background-color: #cc6666; }}
|
||||
pre .bg.green.bright {{ background-color: #b5bd68; }}
|
||||
pre .bg.yellow.bright {{ background-color: #f0c674; }}
|
||||
pre .bg.blue.bright {{ background-color: #81a2be; }}
|
||||
pre .bg.magenta.bright {{ background-color: #b294bb; }}
|
||||
pre .bg.cyan.bright {{ background-color: #8abeb7; }}
|
||||
pre .bg.white.bright {{ background-color: #ffffff; }}
|
||||
</style>
|
||||
|
||||
<foreignObject x="0" y="0" width="{width}" height="{height}">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||
<pre>"#,
|
||||
padding = padding,
|
||||
font_size = font_size,
|
||||
width = width,
|
||||
height = height,
|
||||
)?;
|
||||
|
||||
writer.write_all(&buffer)?;
|
||||
|
||||
write!(
|
||||
writer,
|
||||
"</pre>
|
||||
</div>
|
||||
</foreignObject>
|
||||
</svg>
|
||||
"
|
||||
)?;
|
||||
}
|
||||
Opts::Stderr { color } => {
|
||||
let writer = StandardStream::stderr(color.into());
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
for diagnostic in &diagnostics {
|
||||
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Rudimentary HTML escaper which performs the following conversions:
|
||||
///
|
||||
/// - `<` ⇒ `<`
|
||||
/// - `>` ⇒ `>`
|
||||
/// - `&` ⇒ `&`
|
||||
pub struct HtmlEscapeWriter<W> {
|
||||
upstream: W,
|
||||
}
|
||||
|
||||
impl<W> HtmlEscapeWriter<W> {
|
||||
pub fn new(upstream: W) -> HtmlEscapeWriter<W> {
|
||||
HtmlEscapeWriter { upstream }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for HtmlEscapeWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let mut last_term = 0usize;
|
||||
for (i, byte) in buf.iter().enumerate() {
|
||||
let escape = match byte {
|
||||
b'<' => &b"<"[..],
|
||||
b'>' => &b">"[..],
|
||||
b'&' => &b"&"[..],
|
||||
_ => continue,
|
||||
};
|
||||
self.upstream.write_all(&buf[last_term..i])?;
|
||||
last_term = i + 1;
|
||||
self.upstream.write_all(escape)?;
|
||||
}
|
||||
self.upstream.write_all(&buf[last_term..])?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.upstream.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: WriteColor> WriteColor for HtmlEscapeWriter<W> {
|
||||
fn supports_color(&self) -> bool {
|
||||
self.upstream.supports_color()
|
||||
}
|
||||
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
self.upstream.set_color(spec)
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
self.upstream.reset()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SvgWriter<W> {
|
||||
upstream: W,
|
||||
color: ColorSpec,
|
||||
}
|
||||
|
||||
impl<W> SvgWriter<W> {
|
||||
pub fn new(upstream: W) -> SvgWriter<W> {
|
||||
SvgWriter {
|
||||
upstream,
|
||||
color: ColorSpec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for SvgWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.upstream.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.upstream.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> WriteColor for SvgWriter<W> {
|
||||
fn supports_color(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
if self.color == *spec {
|
||||
return Ok(());
|
||||
} else {
|
||||
if !self.color.is_none() {
|
||||
write!(self, "</span>")?;
|
||||
}
|
||||
self.color = spec.clone();
|
||||
}
|
||||
|
||||
if spec.is_none() {
|
||||
write!(self, "</span>")?;
|
||||
return Ok(());
|
||||
} else {
|
||||
write!(self, "<span class=\"")?;
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
|
||||
fn write_first<W: Write>(first: bool, writer: &mut SvgWriter<W>) -> io::Result<bool> {
|
||||
if !first {
|
||||
write!(writer, " ")?;
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
};
|
||||
|
||||
fn write_color<W: Write>(color: &Color, writer: &mut SvgWriter<W>) -> io::Result<()> {
|
||||
match color {
|
||||
Color::Black => write!(writer, "black"),
|
||||
Color::Blue => write!(writer, "blue"),
|
||||
Color::Green => write!(writer, "green"),
|
||||
Color::Red => write!(writer, "red"),
|
||||
Color::Cyan => write!(writer, "cyan"),
|
||||
Color::Magenta => write!(writer, "magenta"),
|
||||
Color::Yellow => write!(writer, "yellow"),
|
||||
Color::White => write!(writer, "white"),
|
||||
// TODO: other colors
|
||||
_ => Ok(()),
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(fg) = spec.fg() {
|
||||
first = write_first(first, self)?;
|
||||
write!(self, "fg ")?;
|
||||
write_color(fg, self)?;
|
||||
}
|
||||
|
||||
if let Some(bg) = spec.bg() {
|
||||
first = write_first(first, self)?;
|
||||
write!(self, "bg ")?;
|
||||
write_color(bg, self)?;
|
||||
}
|
||||
|
||||
if spec.bold() {
|
||||
first = write_first(first, self)?;
|
||||
write!(self, "bold")?;
|
||||
}
|
||||
|
||||
if spec.underline() {
|
||||
first = write_first(first, self)?;
|
||||
write!(self, "underline")?;
|
||||
}
|
||||
|
||||
if spec.intense() {
|
||||
first = write_first(first, self)?;
|
||||
write!(self, "bright")?;
|
||||
}
|
||||
|
||||
write!(self, "\">")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
let color = self.color.clone();
|
||||
|
||||
if color != ColorSpec::new() {
|
||||
write!(self, "</span>")?;
|
||||
self.color = ColorSpec::new();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
105
vendor/codespan-reporting/examples/reusable_diagnostic.rs
vendored
Normal file
105
vendor/codespan-reporting/examples/reusable_diagnostic.rs
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::files::SimpleFile;
|
||||
use codespan_reporting::term::termcolor::StandardStream;
|
||||
use codespan_reporting::term::{self, ColorArg};
|
||||
use std::ops::Range;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "emit")]
|
||||
pub struct Opts {
|
||||
#[structopt(long = "color",
|
||||
parse(try_from_str),
|
||||
default_value = "auto",
|
||||
possible_values = ColorArg::VARIANTS,
|
||||
case_insensitive = true
|
||||
)]
|
||||
color: ColorArg,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let file = SimpleFile::new(
|
||||
"main.rs",
|
||||
unindent::unindent(
|
||||
r#"
|
||||
fn main() {
|
||||
let foo: i32 = "hello, world";
|
||||
foo += 1;
|
||||
}
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
let errors = [
|
||||
Error::MismatchType(
|
||||
Item::new(20..23, "i32"),
|
||||
Item::new(31..45, "\"hello, world\""),
|
||||
),
|
||||
Error::MutatingImmutable(Item::new(20..23, "foo"), Item::new(51..59, "foo += 1")),
|
||||
];
|
||||
|
||||
let opts = Opts::from_args();
|
||||
let writer = StandardStream::stderr(opts.color.into());
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
for diagnostic in errors.iter().map(Error::report) {
|
||||
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An error enum that represent all possible errors within your program
|
||||
enum Error {
|
||||
MismatchType(Item, Item),
|
||||
MutatingImmutable(Item, Item),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
fn report(&self) -> Diagnostic<()> {
|
||||
match self {
|
||||
Error::MismatchType(left, right) => Diagnostic::error()
|
||||
.with_code("E0308")
|
||||
.with_message("mismatch types")
|
||||
.with_labels(vec![
|
||||
Label::primary((), right.range.clone()).with_message(format!(
|
||||
"Expected `{}`, found: `{}`",
|
||||
left.content, right.content,
|
||||
)),
|
||||
Label::secondary((), left.range.clone()).with_message("expected due to this"),
|
||||
]),
|
||||
Error::MutatingImmutable(original, mutating) => Diagnostic::error()
|
||||
.with_code("E0384")
|
||||
.with_message(format!(
|
||||
"cannot mutate immutable variable `{}`",
|
||||
original.content,
|
||||
))
|
||||
.with_labels(vec![
|
||||
Label::secondary((), original.range.clone()).with_message(unindent::unindent(
|
||||
&format!(
|
||||
r#"
|
||||
first assignment to `{0}`
|
||||
help: make this binding mutable: `mut {0}`
|
||||
"#,
|
||||
original.content,
|
||||
),
|
||||
)),
|
||||
Label::primary((), mutating.range.clone())
|
||||
.with_message("cannot assign twice to immutable variable"),
|
||||
]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An item in the source code to be used in the `Error` enum.
|
||||
/// In a more complex program it could also contain a `files::FileId` to handle errors that occur inside multiple files.
|
||||
struct Item {
|
||||
range: Range<usize>,
|
||||
content: String,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
fn new(range: Range<usize>, content: impl Into<String>) -> Item {
|
||||
let content = content.into();
|
||||
Item { range, content }
|
||||
}
|
||||
}
|
||||
175
vendor/codespan-reporting/examples/term.rs
vendored
Normal file
175
vendor/codespan-reporting/examples/term.rs
vendored
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//! To run this example, execute the following command from the top level of
|
||||
//! this repository:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example term
|
||||
//! ```
|
||||
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use codespan_reporting::files::SimpleFiles;
|
||||
use codespan_reporting::term::termcolor::StandardStream;
|
||||
use codespan_reporting::term::{self, ColorArg};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(name = "emit")]
|
||||
pub struct Opts {
|
||||
/// Configure coloring of output
|
||||
#[structopt(
|
||||
long = "color",
|
||||
parse(try_from_str),
|
||||
default_value = "auto",
|
||||
possible_values = ColorArg::VARIANTS,
|
||||
case_insensitive = true
|
||||
)]
|
||||
pub color: ColorArg,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let opts = Opts::from_args();
|
||||
let mut files = SimpleFiles::new();
|
||||
|
||||
let file_id1 = files.add(
|
||||
"Data/Nat.fun",
|
||||
unindent::unindent(
|
||||
"
|
||||
module Data.Nat where
|
||||
|
||||
data Nat : Type where
|
||||
zero : Nat
|
||||
succ : Nat → Nat
|
||||
|
||||
{-# BUILTIN NATRAL Nat #-}
|
||||
|
||||
infixl 6 _+_ _-_
|
||||
|
||||
_+_ : Nat → Nat → Nat
|
||||
zero + n₂ = n₂
|
||||
succ n₁ + n₂ = succ (n₁ + n₂)
|
||||
|
||||
_-_ : Nat → Nat → Nat
|
||||
n₁ - zero = n₁
|
||||
zero - succ n₂ = zero
|
||||
succ n₁ - succ n₂ = n₁ - n₂
|
||||
",
|
||||
),
|
||||
);
|
||||
|
||||
let file_id2 = files.add(
|
||||
"Test.fun",
|
||||
unindent::unindent(
|
||||
r#"
|
||||
module Test where
|
||||
|
||||
_ : Nat
|
||||
_ = 123 + "hello"
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
let file_id3 = files.add(
|
||||
"FizzBuzz.fun",
|
||||
unindent::unindent(
|
||||
r#"
|
||||
module FizzBuzz where
|
||||
|
||||
fizz₁ : Nat → String
|
||||
fizz₁ num = case (mod num 5) (mod num 3) of
|
||||
0 0 => "FizzBuzz"
|
||||
0 _ => "Fizz"
|
||||
_ 0 => "Buzz"
|
||||
_ _ => num
|
||||
|
||||
fizz₂ : Nat → String
|
||||
fizz₂ num =
|
||||
case (mod num 5) (mod num 3) of
|
||||
0 0 => "FizzBuzz"
|
||||
0 _ => "Fizz"
|
||||
_ 0 => "Buzz"
|
||||
_ _ => num
|
||||
"#,
|
||||
),
|
||||
);
|
||||
|
||||
let diagnostics = [
|
||||
// Unknown builtin error
|
||||
Diagnostic::error()
|
||||
.with_message("unknown builtin: `NATRAL`")
|
||||
.with_labels(vec![
|
||||
Label::primary(file_id1, 96..102).with_message("unknown builtin")
|
||||
])
|
||||
.with_notes(vec![
|
||||
"there is a builtin with a similar name: `NATURAL`".to_owned()
|
||||
]),
|
||||
// Unused parameter warning
|
||||
Diagnostic::warning()
|
||||
.with_message("unused parameter pattern: `n₂`")
|
||||
.with_labels(vec![
|
||||
Label::primary(file_id1, 285..289).with_message("unused parameter")
|
||||
])
|
||||
.with_notes(vec!["consider using a wildcard pattern: `_`".to_owned()]),
|
||||
// Unexpected type error
|
||||
Diagnostic::error()
|
||||
.with_message("unexpected type in application of `_+_`")
|
||||
.with_code("E0001")
|
||||
.with_labels(vec![
|
||||
Label::primary(file_id2, 37..44).with_message("expected `Nat`, found `String`"),
|
||||
Label::secondary(file_id1, 130..155)
|
||||
.with_message("based on the definition of `_+_`"),
|
||||
])
|
||||
.with_notes(vec![unindent::unindent(
|
||||
"
|
||||
expected type `Nat`
|
||||
found type `String`
|
||||
",
|
||||
)]),
|
||||
// Incompatible match clause error
|
||||
Diagnostic::error()
|
||||
.with_message("`case` clauses have incompatible types")
|
||||
.with_code("E0308")
|
||||
.with_labels(vec![
|
||||
Label::primary(file_id3, 163..166).with_message("expected `String`, found `Nat`"),
|
||||
Label::secondary(file_id3, 62..166)
|
||||
.with_message("`case` clauses have incompatible types"),
|
||||
Label::secondary(file_id3, 41..47)
|
||||
.with_message("expected type `String` found here"),
|
||||
])
|
||||
.with_notes(vec![unindent::unindent(
|
||||
"
|
||||
expected type `String`
|
||||
found type `Nat`
|
||||
",
|
||||
)]),
|
||||
// Incompatible match clause error
|
||||
Diagnostic::error()
|
||||
.with_message("`case` clauses have incompatible types")
|
||||
.with_code("E0308")
|
||||
.with_labels(vec![
|
||||
Label::primary(file_id3, 328..331).with_message("expected `String`, found `Nat`"),
|
||||
Label::secondary(file_id3, 211..331)
|
||||
.with_message("`case` clauses have incompatible types"),
|
||||
Label::secondary(file_id3, 258..268)
|
||||
.with_message("this is found to be of type `String`"),
|
||||
Label::secondary(file_id3, 284..290)
|
||||
.with_message("this is found to be of type `String`"),
|
||||
Label::secondary(file_id3, 306..312)
|
||||
.with_message("this is found to be of type `String`"),
|
||||
Label::secondary(file_id3, 186..192)
|
||||
.with_message("expected type `String` found here"),
|
||||
])
|
||||
.with_notes(vec![unindent::unindent(
|
||||
"
|
||||
expected type `String`
|
||||
found type `Nat`
|
||||
",
|
||||
)]),
|
||||
];
|
||||
|
||||
let writer = StandardStream::stderr(opts.color.into());
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
for diagnostic in &diagnostics {
|
||||
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue