Initial diagnostic API for proc-macros.

This commit introduces the ability to create and emit `Diagnostic`
structures from proc-macros, allowing for proc-macro authors to emit
warning, error, note, and help messages just like the compiler does.
This commit is contained in:
Sergio Benitez 2017-08-28 02:56:43 -07:00
parent a0c3bd2d23
commit 8be132e9d7
9 changed files with 314 additions and 1 deletions

View file

@ -0,0 +1,56 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::{TokenStream, TokenNode, Span, Diagnostic};
fn parse(input: TokenStream) -> Result<(), Diagnostic> {
let mut count = 0;
let mut last_span = Span::default();
for tree in input {
let span = tree.span;
if count >= 3 {
return Err(span.error(format!("expected EOF, found `{}`.", tree))
.span_note(last_span, "last good input was here")
.help("input must be: `===`"))
}
if let TokenNode::Op('=', _) = tree.kind {
count += 1;
} else {
return Err(span.error(format!("expected `=`, found `{}`.", tree)));
}
last_span = span;
}
if count < 3 {
return Err(Span::default()
.error(format!("found {} equal signs, need exactly 3", count))
.help("input must be: `===`"))
}
Ok(())
}
#[proc_macro]
pub fn three_equals(input: TokenStream) -> TokenStream {
if let Err(diag) = parse(input) {
diag.emit();
return TokenStream::empty();
}
"3".parse().unwrap()
}

View file

@ -0,0 +1,38 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:three-equals.rs
// ignore-stage1
#![feature(proc_macro)]
extern crate three_equals;
use three_equals::three_equals;
fn main() {
// This one is okay.
three_equals!(===);
// Need exactly three equals.
three_equals!(==);
// Need exactly three equals.
three_equals!(=====);
// Only equals accepted.
three_equals!(abc);
// Only equals accepted.
three_equals!(!!);
// Only three characters expected.
three_equals!(===a);
}

View file

@ -0,0 +1,48 @@
error: found 2 equal signs, need exactly 3
--> $DIR/three-equals.rs:25:5
|
25 | three_equals!(==);
| ^^^^^^^^^^^^^^^^^^
|
= help: input must be: `===`
error: expected EOF, found `=`.
--> $DIR/three-equals.rs:28:21
|
28 | three_equals!(=====);
| ^^
|
note: last good input was here
--> $DIR/three-equals.rs:28:21
|
28 | three_equals!(=====);
| ^^
= help: input must be: `===`
error: expected `=`, found `abc`.
--> $DIR/three-equals.rs:31:19
|
31 | three_equals!(abc);
| ^^^
error: expected `=`, found `!`.
--> $DIR/three-equals.rs:34:19
|
34 | three_equals!(!!);
| ^
error: expected EOF, found `a`.
--> $DIR/three-equals.rs:37:22
|
37 | three_equals!(===a);
| ^
|
note: last good input was here
--> $DIR/three-equals.rs:37:21
|
37 | three_equals!(===a);
| ^
= help: input must be: `===`
error: aborting due to 5 previous errors