Rollup merge of #56679 - euclio:external-doc-parse, r=estebank

overhaul external doc attribute diagnostics

This PR improves the error handling and spans for the external doc attribute. Many cases that silently failed before now emit errors, spans are tightened, and the errors have help and suggestions.

I tried to address all the cases that users ran into in the tracking issue.

cc #44732

r? @QuietMisdreavus
This commit is contained in:
Pietro Albini 2018-12-15 14:47:34 +01:00 committed by GitHub
commit adc88ac0c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 18 deletions

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{self, Block, Ident, NodeId, PatKind, Path};
use ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
use ast::{MacStmtStyle, StmtKind, ItemKind};
use attr::{self, HasAttrs};
use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
@ -1535,21 +1535,65 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
}
Err(ref e) if e.kind() == ErrorKind::InvalidData => {
self.cx.span_err(
at.span,
&format!("{} wasn't a utf-8 file", filename.display()),
);
}
Err(e) => {
self.cx.span_err(
at.span,
&format!("couldn't read {}: {}", filename.display(), e),
);
let lit = it
.meta_item()
.and_then(|item| item.name_value_literal())
.unwrap();
if e.kind() == ErrorKind::InvalidData {
self.cx
.struct_span_err(
lit.span,
&format!("{} wasn't a utf-8 file", filename.display()),
)
.span_label(lit.span, "contains invalid utf-8")
.emit();
} else {
let mut err = self.cx.struct_span_err(
lit.span,
&format!("couldn't read {}: {}", filename.display(), e),
);
err.span_label(lit.span, "couldn't read file");
if e.kind() == ErrorKind::NotFound {
err.help("external doc paths are relative to the crate root");
}
err.emit();
}
}
}
} else {
items.push(noop_fold_meta_list_item(it, self));
let mut err = self.cx.struct_span_err(
it.span,
&format!("expected path to external documentation"),
);
// Check if the user erroneously used `doc(include(...))` syntax.
let literal = it.meta_item_list().and_then(|list| {
if list.len() == 1 {
list[0].literal().map(|literal| &literal.node)
} else {
None
}
});
let (path, applicability) = match &literal {
Some(LitKind::Str(path, ..)) => {
(path.to_string(), Applicability::MachineApplicable)
}
_ => (String::from("<path>"), Applicability::HasPlaceholders),
};
err.span_suggestion_with_applicability(
it.span,
"provide a file path with `=`",
format!("include = \"{}\"", path),
applicability,
);
err.emit();
}
}

View File

@ -0,0 +1 @@
<EFBFBD>(

View File

@ -2,7 +2,31 @@
#![feature(external_doc)]
#[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
pub struct SomeStruct;
#[doc(include = "not-a-file.md")]
pub struct SomeStruct; //~^ ERROR couldn't read
//~| HELP external doc paths are relative to the crate root
#[doc(include = "auxiliary/invalid-utf8.txt")]
pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
#[doc(include)]
pub struct MissingPath; //~^ ERROR expected path
//~| HELP provide a file path with `=`
//~| SUGGESTION include = "<path>"
#[doc(include("../README.md"))]
pub struct InvalidPathSyntax; //~^ ERROR expected path
//~| HELP provide a file path with `=`
//~| SUGGESTION include = "../README.md"
#[doc(include = 123)]
pub struct InvalidPathType; //~^ ERROR expected path
//~| HELP provide a file path with `=`
//~| SUGGESTION include = "<path>"
#[doc(include(123))]
pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
//~| HELP provide a file path with `=`
//~| SUGGESTION include = "<path>"
fn main() {}

View File

@ -1,8 +1,40 @@
error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/external-doc-error.rs:5:1
--> $DIR/external-doc-error.rs:5:17
|
LL | #[doc(include = "not-a-file.md")] //~ ERROR: couldn't read
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #[doc(include = "not-a-file.md")]
| ^^^^^^^^^^^^^^^ couldn't read file
|
= help: external doc paths are relative to the crate root
error: aborting due to previous error
error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
--> $DIR/external-doc-error.rs:9:17
|
LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
error: expected path to external documentation
--> $DIR/external-doc-error.rs:12:7
|
LL | #[doc(include)]
| ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
error: expected path to external documentation
--> $DIR/external-doc-error.rs:17:7
|
LL | #[doc(include("../README.md"))]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
error: expected path to external documentation
--> $DIR/external-doc-error.rs:22:7
|
LL | #[doc(include = 123)]
| ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
error: expected path to external documentation
--> $DIR/external-doc-error.rs:27:7
|
LL | #[doc(include(123))]
| ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
error: aborting due to 6 previous errors