Store the registered lints in the Session
This commit is contained in:
parent
442fbc473e
commit
819f76ca82
@ -79,8 +79,12 @@ pub fn compile_input(sess: Session,
|
||||
&sess);
|
||||
let id = link::find_crate_id(krate.attrs.as_slice(),
|
||||
outputs.out_filestem.as_slice());
|
||||
let (expanded_crate, ast_map) =
|
||||
phase_2_configure_and_expand(&sess, krate, &id);
|
||||
let (expanded_crate, ast_map)
|
||||
= match phase_2_configure_and_expand(&sess, krate, &id) {
|
||||
None => return,
|
||||
Some(p) => p,
|
||||
};
|
||||
|
||||
(outputs, expanded_crate, ast_map)
|
||||
};
|
||||
write_out_deps(&sess, input, &outputs, &expanded_crate);
|
||||
@ -173,10 +177,12 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
||||
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
|
||||
/// harness if one is to be provided and injection of a dependency on the
|
||||
/// standard library and prelude.
|
||||
///
|
||||
/// Returns `None` if we're aborting after handling -W help.
|
||||
pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
mut krate: ast::Crate,
|
||||
crate_id: &CrateId)
|
||||
-> (ast::Crate, syntax::ast_map::Map) {
|
||||
-> Option<(ast::Crate, syntax::ast_map::Map)> {
|
||||
let time_passes = sess.time_passes();
|
||||
|
||||
*sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
|
||||
@ -212,6 +218,17 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
|
||||
let Registry { syntax_exts, .. } = registry;
|
||||
|
||||
// Process command line flags for lints.
|
||||
// Do this here because we will have lint plugins eventually.
|
||||
if sess.opts.describe_lints {
|
||||
super::describe_lints(&*sess.lint_store.borrow());
|
||||
return None;
|
||||
}
|
||||
sess.lint_store.borrow_mut().process_command_line(sess);
|
||||
|
||||
// Abort if there are errors from lint processing or a plugin registrar.
|
||||
sess.abort_if_errors();
|
||||
|
||||
krate = time(time_passes, "expansion", (krate, macros, syntax_exts),
|
||||
|(krate, macros, syntax_exts)| {
|
||||
// Windows dlls do not have rpaths, so they don't know how to find their
|
||||
@ -254,7 +271,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
krate.encode(&mut json).unwrap();
|
||||
}
|
||||
|
||||
(krate, map)
|
||||
Some((krate, map))
|
||||
}
|
||||
|
||||
pub struct CrateAnalysis {
|
||||
@ -631,9 +648,11 @@ pub fn pretty_print_input(sess: Session,
|
||||
|
||||
let (krate, ast_map, is_expanded) = match ppm {
|
||||
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
|
||||
let (krate, ast_map) = phase_2_configure_and_expand(&sess,
|
||||
krate,
|
||||
&id);
|
||||
let (krate, ast_map)
|
||||
= match phase_2_configure_and_expand(&sess, krate, &id) {
|
||||
None => return,
|
||||
Some(p) => p,
|
||||
};
|
||||
(krate, Some(ast_map), true)
|
||||
}
|
||||
_ => (krate, None, false)
|
||||
|
@ -13,6 +13,7 @@ pub use syntax::diagnostic;
|
||||
use back::link;
|
||||
use driver::driver::{Input, FileInput, StrInput};
|
||||
use driver::session::{Session, build_session};
|
||||
use lint::Lint;
|
||||
use lint;
|
||||
use metadata;
|
||||
|
||||
@ -48,15 +49,18 @@ fn run_compiler(args: &[String]) {
|
||||
Some(matches) => matches,
|
||||
None => return
|
||||
};
|
||||
|
||||
let sopts = config::build_session_options(&matches);
|
||||
if sopts.describe_lints {
|
||||
describe_lints();
|
||||
return;
|
||||
}
|
||||
|
||||
let (input, input_file_path) = match matches.free.len() {
|
||||
0u => early_error("no input filename given"),
|
||||
0u => {
|
||||
if sopts.describe_lints {
|
||||
let mut ls = lint::LintStore::new();
|
||||
ls.register_builtin(None);
|
||||
describe_lints(&ls);
|
||||
return;
|
||||
}
|
||||
early_error("no input filename given");
|
||||
}
|
||||
1u => {
|
||||
let ifile = matches.free.get(0).as_slice();
|
||||
if ifile == "-" {
|
||||
@ -128,43 +132,56 @@ Additional help:
|
||||
config::optgroups().as_slice()));
|
||||
}
|
||||
|
||||
fn describe_lints() {
|
||||
fn describe_lints(lint_store: &lint::LintStore) {
|
||||
println!("
|
||||
Available lint options:
|
||||
-W <foo> Warn about <foo>
|
||||
-A <foo> Allow <foo>
|
||||
-D <foo> Deny <foo>
|
||||
-F <foo> Forbid <foo> (deny, and deny all overrides)
|
||||
|
||||
");
|
||||
|
||||
let mut builtin_specs = lint::builtin_lint_specs();
|
||||
builtin_specs.sort_by(|x, y| {
|
||||
match x.default_level.cmp(&y.default_level) {
|
||||
Equal => x.name.cmp(&y.name),
|
||||
r => r,
|
||||
}
|
||||
});
|
||||
fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
|
||||
let mut lints: Vec<_> = lints.move_iter().map(|(x, _)| x).collect();
|
||||
lints.sort_by(|x: &&Lint, y: &&Lint| {
|
||||
match x.default_level.cmp(&y.default_level) {
|
||||
Equal => x.name.cmp(&y.name),
|
||||
r => r,
|
||||
}
|
||||
});
|
||||
lints
|
||||
}
|
||||
|
||||
// FIXME: What if someone uses combining characters or East Asian fullwidth
|
||||
// characters in a lint name?!?!?
|
||||
let max_name_len = builtin_specs.iter()
|
||||
let (_plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
|
||||
// let plugin = sort_lints(plugin);
|
||||
let builtin = sort_lints(builtin);
|
||||
|
||||
// FIXME (#7043): We should use the width in character cells rather than
|
||||
// the number of codepoints.
|
||||
let max_name_len = builtin.iter()
|
||||
.map(|&s| s.name.char_len())
|
||||
.max().unwrap_or(0);
|
||||
let padded = |x: &str| {
|
||||
format!("{}{}", " ".repeat(max_name_len - x.char_len()), x)
|
||||
" ".repeat(max_name_len - x.char_len()).append(x)
|
||||
};
|
||||
|
||||
println!("\nAvailable lint checks:\n");
|
||||
println!("Lint checks provided by rustc:\n");
|
||||
println!(" {} {:7.7s} {}", padded("name"), "default", "meaning");
|
||||
println!(" {} {:7.7s} {}", padded("----"), "-------", "-------");
|
||||
println!("");
|
||||
|
||||
for spec in builtin_specs.move_iter() {
|
||||
let name = spec.name.replace("_", "-");
|
||||
println!(" {} {:7.7s} {}",
|
||||
padded(name.as_slice()), spec.default_level.as_str(), spec.desc);
|
||||
}
|
||||
println!("");
|
||||
let print_lints = |lints: Vec<&Lint>| {
|
||||
for lint in lints.move_iter() {
|
||||
let name = lint.name.replace("_", "-");
|
||||
println!(" {} {:7.7s} {}",
|
||||
padded(name.as_slice()), lint.default_level.as_str(), lint.desc);
|
||||
}
|
||||
println!("\n");
|
||||
};
|
||||
|
||||
print_lints(builtin);
|
||||
|
||||
// Describe lint plugins here once they exist.
|
||||
}
|
||||
|
||||
fn describe_debug_flags() {
|
||||
|
@ -43,6 +43,7 @@ pub struct Session {
|
||||
// expected to be absolute. `None` means that there is no source file.
|
||||
pub local_crate_source_file: Option<Path>,
|
||||
pub working_dir: Path,
|
||||
pub lint_store: RefCell<lint::LintStore>,
|
||||
pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
|
||||
pub node_id: Cell<ast::NodeId>,
|
||||
pub crate_types: RefCell<Vec<config::CrateType>>,
|
||||
@ -226,7 +227,7 @@ pub fn build_session_(sopts: config::Options,
|
||||
}
|
||||
);
|
||||
|
||||
Session {
|
||||
let sess = Session {
|
||||
targ_cfg: target_cfg,
|
||||
opts: sopts,
|
||||
cstore: CStore::new(token::get_ident_interner()),
|
||||
@ -238,12 +239,16 @@ pub fn build_session_(sopts: config::Options,
|
||||
default_sysroot: default_sysroot,
|
||||
local_crate_source_file: local_crate_source_file,
|
||||
working_dir: os::getcwd(),
|
||||
lint_store: RefCell::new(lint::LintStore::new()),
|
||||
lints: RefCell::new(NodeMap::new()),
|
||||
node_id: Cell::new(1),
|
||||
crate_types: RefCell::new(Vec::new()),
|
||||
features: front::feature_gate::Features::new(),
|
||||
recursion_limit: Cell::new(64),
|
||||
}
|
||||
};
|
||||
|
||||
sess.lint_store.borrow_mut().register_builtin(Some(&sess));
|
||||
sess
|
||||
}
|
||||
|
||||
// Seems out of place, but it uses session, so I'm putting it here
|
||||
|
@ -1517,7 +1517,7 @@ impl LintPass for GatherNodeLevels {
|
||||
match it.node {
|
||||
ast::ItemEnum(..) => {
|
||||
let lint_id = lint::LintId::of(variant_size_difference);
|
||||
match cx.get_level_source(lint_id) {
|
||||
match cx.lints.get_level_source(lint_id) {
|
||||
lvlsrc @ (lvl, _) if lvl != lint::Allow => {
|
||||
cx.insert_node_level(it.id, lint_id, lvlsrc);
|
||||
},
|
||||
|
@ -48,6 +48,7 @@ use middle::ty;
|
||||
use middle::typeck::astconv::AstConv;
|
||||
use middle::typeck::infer;
|
||||
use driver::session::Session;
|
||||
use driver::early_error;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@ -58,6 +59,7 @@ use std::default::Default;
|
||||
use std::hash::Hash;
|
||||
use std::tuple::Tuple2;
|
||||
use std::hash;
|
||||
use std::mem;
|
||||
use syntax::ast_util::IdVisitingOperation;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::attr;
|
||||
@ -115,7 +117,7 @@ pub struct Lint {
|
||||
pub desc: &'static str,
|
||||
}
|
||||
|
||||
type LintArray = &'static [&'static Lint];
|
||||
pub type LintArray = &'static [&'static Lint];
|
||||
|
||||
/// Trait for types providing lint checks. Each `check` method checks a single
|
||||
/// syntax node, and should not invoke methods recursively (unlike `Visitor`).
|
||||
@ -123,7 +125,7 @@ type LintArray = &'static [&'static Lint];
|
||||
//
|
||||
// FIXME: eliminate the duplication with `Visitor`. But this also
|
||||
// contains a few lint-specific methods with no equivalent in `Visitor`.
|
||||
trait LintPass {
|
||||
pub trait LintPass {
|
||||
/// Get descriptions of the lints this `LintPass` object can emit.
|
||||
///
|
||||
/// NB: there is no enforcement that the object only emits lints it registered.
|
||||
@ -246,15 +248,117 @@ pub enum LintSource {
|
||||
|
||||
pub type LevelSource = (Level, LintSource);
|
||||
|
||||
struct Context<'a> {
|
||||
/// Information about the registered lints.
|
||||
/// This is basically the subset of `Context` that we can
|
||||
/// build early in the compile pipeline.
|
||||
pub struct LintStore {
|
||||
/// Registered lints. The bool is true if the lint was
|
||||
/// added by a plugin.
|
||||
lints: Vec<(&'static Lint, bool)>,
|
||||
|
||||
/// Trait objects for each lint pass.
|
||||
lint_objects: Vec<RefCell<LintPassObject>>,
|
||||
passes: Vec<RefCell<LintPassObject>>,
|
||||
|
||||
/// Lints indexed by name.
|
||||
lints_by_name: HashMap<&'static str, LintId>,
|
||||
by_name: HashMap<&'static str, LintId>,
|
||||
|
||||
/// Current levels of each lint, and where they were set.
|
||||
levels: HashMap<LintId, LevelSource>,
|
||||
}
|
||||
|
||||
impl LintStore {
|
||||
fn get_level_source(&self, lint: LintId) -> LevelSource {
|
||||
match self.levels.find(&lint) {
|
||||
Some(&s) => s,
|
||||
None => (Allow, Default),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_level(&mut self, lint: LintId, lvlsrc: LevelSource) {
|
||||
if lvlsrc.val0() == Allow {
|
||||
self.levels.remove(&lint);
|
||||
} else {
|
||||
self.levels.insert(lint, lvlsrc);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> LintStore {
|
||||
LintStore {
|
||||
lints: vec!(),
|
||||
passes: vec!(),
|
||||
by_name: HashMap::new(),
|
||||
levels: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] {
|
||||
self.lints.as_slice()
|
||||
}
|
||||
|
||||
pub fn register_pass(&mut self, sess: Option<&Session>,
|
||||
from_plugin: bool, pass: LintPassObject) {
|
||||
for &lint in pass.get_lints().iter() {
|
||||
self.lints.push((lint, from_plugin));
|
||||
|
||||
let id = LintId::of(lint);
|
||||
if !self.by_name.insert(lint.name, id) {
|
||||
let msg = format!("duplicate specification of lint {}", lint.name);
|
||||
match (sess, from_plugin) {
|
||||
// We load builtin lints first, so a duplicate is a compiler bug.
|
||||
// Use early_error when handling -W help with no crate.
|
||||
(None, _) => early_error(msg.as_slice()),
|
||||
(Some(sess), false) => sess.bug(msg.as_slice()),
|
||||
|
||||
// A duplicate name from a plugin is a user error.
|
||||
(Some(sess), true) => sess.err(msg.as_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
if lint.default_level != Allow {
|
||||
self.levels.insert(id, (lint.default_level, Default));
|
||||
}
|
||||
}
|
||||
self.passes.push(RefCell::new(pass));
|
||||
}
|
||||
|
||||
pub fn register_builtin(&mut self, sess: Option<&Session>) {
|
||||
macro_rules! add_builtin_lints ( ( $sess:ident, $($name:ident),*, ) => (
|
||||
{$(
|
||||
{
|
||||
let obj: builtin::$name = Default::default();
|
||||
self.register_pass($sess, false, box obj as LintPassObject);
|
||||
};
|
||||
)*}
|
||||
))
|
||||
|
||||
add_builtin_lints!(sess,
|
||||
WhileTrue, UnusedCasts, TypeLimits, CTypes, HeapMemory,
|
||||
RawPointerDeriving, UnusedAttribute, PathStatement,
|
||||
UnusedResult, DeprecatedOwnedVector, NonCamelCaseTypes,
|
||||
NonSnakeCaseFunctions, NonUppercaseStatics,
|
||||
NonUppercasePatternStatics, UppercaseVariables,
|
||||
UnnecessaryParens, UnusedUnsafe, UnsafeBlock, UnusedMut,
|
||||
UnnecessaryAllocation, MissingDoc, Stability,
|
||||
|
||||
GatherNodeLevels, HardwiredLints,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn process_command_line(&mut self, sess: &Session) {
|
||||
for &(ref lint_name, level) in sess.opts.lint_opts.iter() {
|
||||
match self.by_name.find_equiv(&lint_name.as_slice()) {
|
||||
Some(&lint_id) => self.set_level(lint_id, (level, CommandLine)),
|
||||
None => sess.err(format!("unknown {} flag: {}",
|
||||
level.as_str(), lint_name).as_slice()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Context for lint checking.
|
||||
pub struct Context<'a> {
|
||||
/// The store of registered lints.
|
||||
lints: LintStore,
|
||||
|
||||
/// Context we're checking in (used to access fields like sess).
|
||||
tcx: &'a ty::ctxt,
|
||||
@ -271,7 +375,7 @@ struct Context<'a> {
|
||||
|
||||
/// Convenience macro for calling a `LintPass` method on every pass in the context.
|
||||
macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => (
|
||||
for obj in $cx.lint_objects.iter() {
|
||||
for obj in $cx.lints.passes.iter() {
|
||||
obj.borrow_mut().$f($cx, $($args),*);
|
||||
}
|
||||
))
|
||||
@ -316,26 +420,11 @@ pub fn emit_lint(sess: &Session, lint: &'static Lint,
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
fn get_level_source(&self, lint: LintId) -> LevelSource {
|
||||
match self.levels.find(&lint) {
|
||||
Some(&s) => s,
|
||||
None => (Allow, Default),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_level(&mut self, lint: LintId, lvlsrc: LevelSource) {
|
||||
if lvlsrc.val0() == Allow {
|
||||
self.levels.remove(&lint);
|
||||
} else {
|
||||
self.levels.insert(lint, lvlsrc);
|
||||
}
|
||||
}
|
||||
|
||||
fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) {
|
||||
let (level, src) = match self.levels.find(&LintId::of(lint)) {
|
||||
pub fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) {
|
||||
let (level, src) = match self.lints.levels.find(&LintId::of(lint)) {
|
||||
None => return,
|
||||
Some(&(Warn, src))
|
||||
=> (self.get_level_source(LintId::of(builtin::warnings)).val0(), src),
|
||||
=> (self.lints.get_level_source(LintId::of(builtin::warnings)).val0(), src),
|
||||
Some(&pair) => pair,
|
||||
};
|
||||
|
||||
@ -357,17 +446,17 @@ impl<'a> Context<'a> {
|
||||
let lint_attrs = self.gather_lint_attrs(attrs);
|
||||
let mut pushed = 0u;
|
||||
for (lint_id, level, span) in lint_attrs.move_iter() {
|
||||
let now = self.get_level_source(lint_id).val0();
|
||||
let now = self.lints.get_level_source(lint_id).val0();
|
||||
if now == Forbid && level != Forbid {
|
||||
let lint_name = lint_id.as_str();
|
||||
self.tcx.sess.span_err(span,
|
||||
format!("{}({}) overruled by outer forbid({})",
|
||||
level.as_str(), lint_name, lint_name).as_slice());
|
||||
} else if now != level {
|
||||
let src = self.get_level_source(lint_id).val1();
|
||||
let src = self.lints.get_level_source(lint_id).val1();
|
||||
self.level_stack.push((lint_id, (now, src)));
|
||||
pushed += 1;
|
||||
self.set_level(lint_id, (level, Node(span)));
|
||||
self.lints.set_level(lint_id, (level, Node(span)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +467,7 @@ impl<'a> Context<'a> {
|
||||
// rollback
|
||||
for _ in range(0, pushed) {
|
||||
let (lint, lvlsrc) = self.level_stack.pop().unwrap();
|
||||
self.set_level(lint, lvlsrc);
|
||||
self.lints.set_level(lint, lvlsrc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +508,7 @@ impl<'a> Context<'a> {
|
||||
for meta in metas.iter() {
|
||||
match meta.node {
|
||||
ast::MetaWord(ref lint_name) => {
|
||||
match self.lints_by_name.find_equiv(lint_name) {
|
||||
match self.lints.by_name.find_equiv(lint_name) {
|
||||
Some(lint_id) => out.push((*lint_id, level, meta.span)),
|
||||
|
||||
None => self.span_lint(builtin::unrecognized_lint,
|
||||
@ -636,75 +725,21 @@ impl<'a> IdVisitingOperation for Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn builtin_lints() -> Vec<Box<LintPass>> {
|
||||
macro_rules! builtin_lints (( $($name:ident),*, ) => (
|
||||
vec!($(
|
||||
{
|
||||
let obj: builtin::$name = Default::default();
|
||||
box obj as LintPassObject
|
||||
}
|
||||
),*)
|
||||
))
|
||||
|
||||
builtin_lints!(
|
||||
WhileTrue, UnusedCasts, TypeLimits, CTypes, HeapMemory,
|
||||
RawPointerDeriving, UnusedAttribute, PathStatement,
|
||||
UnusedResult, DeprecatedOwnedVector, NonCamelCaseTypes,
|
||||
NonSnakeCaseFunctions, NonUppercaseStatics,
|
||||
NonUppercasePatternStatics, UppercaseVariables,
|
||||
UnnecessaryParens, UnusedUnsafe, UnsafeBlock, UnusedMut,
|
||||
UnnecessaryAllocation, MissingDoc, Stability,
|
||||
|
||||
GatherNodeLevels, HardwiredLints,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get specs for all builtin lints. Used for `-W help`.
|
||||
pub fn builtin_lint_specs() -> Vec<&'static Lint> {
|
||||
builtin_lints().move_iter()
|
||||
.flat_map(|x| x.get_lints().iter().map(|&y| y))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt,
|
||||
exported_items: &ExportedItems,
|
||||
krate: &ast::Crate) {
|
||||
let lints = builtin_lints().move_iter().map(|x| RefCell::new(x)).collect();
|
||||
|
||||
// We want to own the lint store, so move it out of the session.
|
||||
let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
|
||||
LintStore::new());
|
||||
|
||||
let mut cx = Context {
|
||||
lint_objects: lints,
|
||||
lints_by_name: HashMap::new(),
|
||||
levels: HashMap::new(),
|
||||
lints: lint_store,
|
||||
tcx: tcx,
|
||||
level_stack: Vec::new(),
|
||||
node_levels: RefCell::new(HashMap::new()),
|
||||
};
|
||||
|
||||
// Index the lints by name, and set the default levels.
|
||||
for obj in cx.lint_objects.iter() {
|
||||
for &lint in obj.borrow_mut().get_lints().iter() {
|
||||
let id = LintId::of(lint);
|
||||
if !cx.lints_by_name.insert(lint.name, id) {
|
||||
cx.tcx.sess.err(format!("duplicate specification of lint {}",
|
||||
lint.name).as_slice());
|
||||
}
|
||||
if lint.default_level != Allow {
|
||||
cx.levels.insert(id, (lint.default_level, Default));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set command line lint levels.
|
||||
for &(ref lint_name, level) in tcx.sess.opts.lint_opts.iter() {
|
||||
match cx.lints_by_name.find_equiv(&lint_name.as_slice()) {
|
||||
Some(&lint_id) => cx.set_level(lint_id, (level, CommandLine)),
|
||||
None => cx.tcx.sess.err(format!("unknown {} flag: {}",
|
||||
level.as_str(), lint_name).as_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
tcx.sess.abort_if_errors();
|
||||
|
||||
// Visit the whole crate.
|
||||
cx.with_lint_attrs(krate.attrs.as_slice(), |cx| {
|
||||
cx.visit_id(ast::CRATE_NODE_ID);
|
||||
|
@ -120,7 +120,8 @@ fn test_env(_test_name: &str,
|
||||
name: "test".to_owned(),
|
||||
version: None };
|
||||
let (krate, ast_map) =
|
||||
driver::phase_2_configure_and_expand(&sess, krate, &krate_id);
|
||||
driver::phase_2_configure_and_expand(&sess, krate, &krate_id)
|
||||
.expect("phase 2 aborted");
|
||||
|
||||
// run just enough stuff to build a tcx:
|
||||
let lang_items = lang_items::collect_language_items(&krate, &sess);
|
||||
|
@ -102,8 +102,10 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
|
||||
}
|
||||
|
||||
let krate = phase_1_parse_input(&sess, cfg, &input);
|
||||
let (krate, ast_map) = phase_2_configure_and_expand(&sess, krate,
|
||||
&from_str("rustdoc").unwrap());
|
||||
let (krate, ast_map)
|
||||
= phase_2_configure_and_expand(&sess, krate, &from_str("rustdoc").unwrap())
|
||||
.expect("phase_2_configure_and_expand aborted in rustdoc!");
|
||||
|
||||
let driver::driver::CrateAnalysis {
|
||||
exported_items, public_items, ty_cx, ..
|
||||
} = phase_3_run_analysis_passes(sess, &krate, ast_map);
|
||||
|
@ -69,7 +69,8 @@ pub fn run(input: &str,
|
||||
}));
|
||||
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
|
||||
let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
|
||||
&from_str("rustdoc-test").unwrap());
|
||||
&from_str("rustdoc-test").unwrap())
|
||||
.expect("phase_2_configure_and_expand aborted in rustdoc!");
|
||||
|
||||
let ctx = box(GC) core::DocContext {
|
||||
krate: krate,
|
||||
|
Loading…
x
Reference in New Issue
Block a user