Add rustdoc_ng
This commit is contained in:
parent
d87078be72
commit
268f3f0ff5
|
@ -214,6 +214,7 @@ CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc)
|
||||||
CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax)
|
CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax)
|
||||||
CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg)
|
CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg)
|
||||||
CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc)
|
CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc)
|
||||||
|
CFG_LIBRUSTDOCNG_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc_ng)
|
||||||
CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti)
|
CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti)
|
||||||
CFG_LIBRUST_$(1) :=$(call CFG_LIB_NAME_$(1),rust)
|
CFG_LIBRUST_$(1) :=$(call CFG_LIB_NAME_$(1),rust)
|
||||||
|
|
||||||
|
@ -223,6 +224,7 @@ LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc)
|
||||||
LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax)
|
LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax)
|
||||||
LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg)
|
LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg)
|
||||||
LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc)
|
LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc)
|
||||||
|
LIBRUSTDOCNG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc_ng)
|
||||||
LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti)
|
LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti)
|
||||||
LIBRUST_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rust)
|
LIBRUST_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rust)
|
||||||
EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra)
|
EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra)
|
||||||
|
@ -231,6 +233,7 @@ LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc)
|
||||||
LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax)
|
LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax)
|
||||||
LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg)
|
LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg)
|
||||||
LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc)
|
LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc)
|
||||||
|
LIBRUSTDOCNG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc_ng)
|
||||||
LIBRUSTI_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rusti)
|
LIBRUSTI_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rusti)
|
||||||
LIBRUST_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rust)
|
LIBRUST_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rust)
|
||||||
|
|
||||||
|
@ -443,6 +446,7 @@ CSREQ$(1)_T_$(2)_H_$(3) = \
|
||||||
$$(HBIN$(1)_H_$(3))/rust$$(X_$(3)) \
|
$$(HBIN$(1)_H_$(3))/rust$$(X_$(3)) \
|
||||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \
|
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \
|
||||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \
|
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \
|
||||||
|
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(3)) \
|
||||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \
|
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \
|
||||||
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUST_$(3)) \
|
$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUST_$(3)) \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
|
||||||
|
@ -451,6 +455,7 @@ CSREQ$(1)_T_$(2)_H_$(3) = \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \
|
||||||
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(2)) \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) \
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) \
|
||||||
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUST_$(2))
|
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUST_$(2))
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ clean$(1)_H_$(2):
|
||||||
$(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2))
|
$(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2))
|
||||||
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOCNG_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_STDLIB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_STDLIB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2))
|
||||||
|
@ -85,6 +86,7 @@ clean$(1)_H_$(2):
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2))
|
||||||
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOCNG_GLOB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTI_GLOB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTI_GLOB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUST_GLOB_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUST_GLOB_$(2))
|
||||||
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2))
|
$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2))
|
||||||
|
@ -107,6 +109,7 @@ clean$(1)_T_$(2)_H_$(3):
|
||||||
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2))
|
$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2))
|
||||||
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
|
||||||
|
@ -120,6 +123,7 @@ clean$(1)_T_$(2)_H_$(3):
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2))
|
||||||
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOCNG_GLOB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTI_GLOB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTI_GLOB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUST_GLOB_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUST_GLOB_$(2))
|
||||||
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2))
|
$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2))
|
||||||
|
|
|
@ -104,6 +104,7 @@ install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2))
|
||||||
$$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1)))
|
$$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1)))
|
||||||
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_GLOB_$(1)))
|
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_GLOB_$(1)))
|
||||||
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOC_GLOB_$(1)))
|
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOC_GLOB_$(1)))
|
||||||
|
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOCNG_GLOB_$(1)))
|
||||||
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTI_GLOB_$(1)))
|
$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTI_GLOB_$(1)))
|
||||||
$$(Q)$$(call INSTALL_LIB,$$(LIBRUST_GLOB_$(1)))
|
$$(Q)$$(call INSTALL_LIB,$$(LIBRUST_GLOB_$(1)))
|
||||||
$$(Q)$$(call INSTALL_LIB,libmorestack.a)
|
$$(Q)$$(call INSTALL_LIB,libmorestack.a)
|
||||||
|
@ -149,6 +150,7 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE))
|
||||||
$(Q)$(call INSTALL_LIB,$(LIBRUST_GLOB_$(CFG_BUILD_TRIPLE)))
|
$(Q)$(call INSTALL_LIB,$(LIBRUST_GLOB_$(CFG_BUILD_TRIPLE)))
|
||||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE)))
|
$(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE)))
|
||||||
$(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE)))
|
$(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE)))
|
||||||
|
$(Q)$(call INSTALL_LIB,$(LIBRUSTDOCNG_GLOB_$(CFG_BUILD_TRIPLE)))
|
||||||
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)))
|
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)))
|
||||||
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)))
|
$(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)))
|
||||||
$(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rust.1)
|
$(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rust.1)
|
||||||
|
|
13
mk/tools.mk
13
mk/tools.mk
|
@ -23,6 +23,11 @@ RUSTPKG_INPUTS := $(wildcard $(S)src/librustpkg/*.rs)
|
||||||
RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs
|
RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs
|
||||||
RUSTDOC_INPUTS := $(wildcard $(S)src/librustdoc/*.rs)
|
RUSTDOC_INPUTS := $(wildcard $(S)src/librustdoc/*.rs)
|
||||||
|
|
||||||
|
# rustdoc_ng, the next generation documentation tool
|
||||||
|
|
||||||
|
RUSTDOCNG_LIB := $(S)src/rustdoc/lib.rs
|
||||||
|
RUSTDOCNG_INPUTS := $(wildcard $(S)src/rustdoc/*.rs)
|
||||||
|
|
||||||
# Rusti, the JIT REPL
|
# Rusti, the JIT REPL
|
||||||
RUSTI_LIB := $(S)src/librusti/rusti.rs
|
RUSTI_LIB := $(S)src/librusti/rusti.rs
|
||||||
RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs)
|
RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs)
|
||||||
|
@ -78,6 +83,14 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \
|
||||||
@$$(call E, compile_and_link: $$@)
|
@$$(call E, compile_and_link: $$@)
|
||||||
$$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$<
|
$$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$<
|
||||||
|
|
||||||
|
$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc_ng$$(X_$(4)): \
|
||||||
|
$$(DRIVER_CRATE) \
|
||||||
|
$$(TSREQ$(1)_T_$(4)_H_$(3)) \
|
||||||
|
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(4)) \
|
||||||
|
| $$(TBIN$(1)_T_$(4)_H_$(3))/
|
||||||
|
@$$(call E, compile_and_link: $$@)
|
||||||
|
$$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc_ng -o $$@ $$<
|
||||||
|
|
||||||
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)): \
|
$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)): \
|
||||||
$$(RUSTI_LIB) $$(RUSTI_INPUTS) \
|
$$(RUSTI_LIB) $$(RUSTI_INPUTS) \
|
||||||
$$(SREQ$(1)_T_$(4)_H_$(3)) \
|
$$(SREQ$(1)_T_$(4)_H_$(3)) \
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.swp
|
||||||
|
main
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,68 @@
|
||||||
|
use rustc;
|
||||||
|
use rustc::{driver, middle};
|
||||||
|
|
||||||
|
use syntax;
|
||||||
|
use syntax::parse;
|
||||||
|
use syntax::ast;
|
||||||
|
|
||||||
|
use std::os;
|
||||||
|
use std::local_data;
|
||||||
|
|
||||||
|
use visit_ast::RustdocVisitor;
|
||||||
|
use clean;
|
||||||
|
use clean::Clean;
|
||||||
|
|
||||||
|
pub struct DocContext {
|
||||||
|
crate: @ast::Crate,
|
||||||
|
tycx: middle::ty::ctxt,
|
||||||
|
sess: driver::session::Session
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses, resolves, and typechecks the given crate
|
||||||
|
fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {
|
||||||
|
use syntax::codemap::dummy_spanned;
|
||||||
|
use rustc::driver::driver::*;
|
||||||
|
|
||||||
|
let parsesess = parse::new_parse_sess(None);
|
||||||
|
let input = file_input(cpath.clone());
|
||||||
|
|
||||||
|
let sessopts = @driver::session::options {
|
||||||
|
binary: @"rustdoc",
|
||||||
|
maybe_sysroot: Some(@os::self_exe_path().unwrap().pop()),
|
||||||
|
addl_lib_search_paths: @mut libs,
|
||||||
|
.. (*rustc::driver::session::basic_options()).clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let diagnostic_handler = syntax::diagnostic::mk_handler(None);
|
||||||
|
let span_diagnostic_handler =
|
||||||
|
syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
|
||||||
|
|
||||||
|
let sess = driver::driver::build_session_(sessopts, parsesess.cm,
|
||||||
|
syntax::diagnostic::emit,
|
||||||
|
span_diagnostic_handler);
|
||||||
|
|
||||||
|
let mut cfg = build_configuration(sess, @"rustdoc_ng", &input);
|
||||||
|
cfg.push(@dummy_spanned(ast::MetaWord(@"stage2")));
|
||||||
|
|
||||||
|
let mut crate = phase_1_parse_input(sess, cfg.clone(), &input);
|
||||||
|
crate = phase_2_configure_and_expand(sess, cfg, crate);
|
||||||
|
let analysis = phase_3_run_analysis_passes(sess, crate);
|
||||||
|
|
||||||
|
debug!("crate: %?", crate);
|
||||||
|
DocContext { crate: crate, tycx: analysis.ty_cx, sess: sess }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_core (libs: ~[Path], path: &Path) -> clean::Crate {
|
||||||
|
let ctxt = @get_ast_and_resolve(path, libs);
|
||||||
|
debug!("defmap:");
|
||||||
|
for (k, v) in ctxt.tycx.def_map.iter() {
|
||||||
|
debug!("%?: %?", k, v);
|
||||||
|
}
|
||||||
|
local_data::set(super::ctxtkey, ctxt);
|
||||||
|
|
||||||
|
let v = @mut RustdocVisitor::new();
|
||||||
|
v.visit(ctxt.crate);
|
||||||
|
|
||||||
|
v.clean()
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
//! This module is used to store stuff from Rust's AST in a more convenient
|
||||||
|
//! manner (and with prettier names) before cleaning.
|
||||||
|
|
||||||
|
use syntax;
|
||||||
|
use syntax::codemap::span;
|
||||||
|
use syntax::ast;
|
||||||
|
use syntax::ast::{ident, NodeId};
|
||||||
|
|
||||||
|
pub struct Module {
|
||||||
|
name: Option<ident>,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
where: span,
|
||||||
|
structs: ~[Struct],
|
||||||
|
enums: ~[Enum],
|
||||||
|
fns: ~[Function],
|
||||||
|
mods: ~[Module],
|
||||||
|
id: NodeId,
|
||||||
|
typedefs: ~[Typedef],
|
||||||
|
statics: ~[Static],
|
||||||
|
traits: ~[Trait],
|
||||||
|
vis: ast::visibility,
|
||||||
|
impls: ~[Impl],
|
||||||
|
view_items: ~[ast::view_item],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Module {
|
||||||
|
pub fn new(name: Option<ident>) -> Module {
|
||||||
|
Module {
|
||||||
|
name : name,
|
||||||
|
id: 0,
|
||||||
|
vis: ast::private,
|
||||||
|
where: syntax::codemap::dummy_sp(),
|
||||||
|
attrs : ~[],
|
||||||
|
structs : ~[],
|
||||||
|
enums : ~[],
|
||||||
|
fns : ~[],
|
||||||
|
mods : ~[],
|
||||||
|
typedefs : ~[],
|
||||||
|
statics : ~[],
|
||||||
|
traits : ~[],
|
||||||
|
impls : ~[],
|
||||||
|
view_items : ~[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(ToStr, Clone, Encodable, Decodable)]
|
||||||
|
pub enum StructType {
|
||||||
|
/// A normal struct
|
||||||
|
Plain,
|
||||||
|
/// A tuple struct
|
||||||
|
Tuple,
|
||||||
|
/// A newtype struct (tuple struct with one element)
|
||||||
|
Newtype,
|
||||||
|
/// A unit struct
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TypeBound {
|
||||||
|
RegionBound,
|
||||||
|
TraitBound(ast::trait_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Struct {
|
||||||
|
vis: ast::visibility,
|
||||||
|
id: NodeId,
|
||||||
|
struct_type: StructType,
|
||||||
|
name: ident,
|
||||||
|
generics: ast::Generics,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
fields: ~[@ast::struct_field],
|
||||||
|
where: span,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Enum {
|
||||||
|
vis: ast::visibility,
|
||||||
|
variants: ~[Variant],
|
||||||
|
generics: ast::Generics,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
id: NodeId,
|
||||||
|
where: span,
|
||||||
|
name: ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Variant {
|
||||||
|
name: ident,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
kind: ast::variant_kind,
|
||||||
|
id: ast::NodeId,
|
||||||
|
vis: ast::visibility,
|
||||||
|
where: span,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Function {
|
||||||
|
decl: ast::fn_decl,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
id: NodeId,
|
||||||
|
name: ident,
|
||||||
|
vis: ast::visibility,
|
||||||
|
where: span,
|
||||||
|
generics: ast::Generics,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Typedef {
|
||||||
|
ty: ast::Ty,
|
||||||
|
gen: ast::Generics,
|
||||||
|
name: ast::ident,
|
||||||
|
id: ast::NodeId,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
where: span,
|
||||||
|
vis: ast::visibility,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Static {
|
||||||
|
type_: ast::Ty,
|
||||||
|
mutability: ast::mutability,
|
||||||
|
expr: @ast::expr,
|
||||||
|
name: ast::ident,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
vis: ast::visibility,
|
||||||
|
id: ast::NodeId,
|
||||||
|
where: span,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Trait {
|
||||||
|
name: ast::ident,
|
||||||
|
methods: ~[ast::trait_method], //should be TraitMethod
|
||||||
|
generics: ast::Generics,
|
||||||
|
parents: ~[ast::trait_ref],
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
id: ast::NodeId,
|
||||||
|
where: span,
|
||||||
|
vis: ast::visibility,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Impl {
|
||||||
|
generics: ast::Generics,
|
||||||
|
trait_: Option<ast::trait_ref>,
|
||||||
|
for_: ast::Ty,
|
||||||
|
methods: ~[@ast::method],
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
where: span,
|
||||||
|
vis: ast::visibility,
|
||||||
|
id: ast::NodeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn struct_type_from_def(sd: &ast::struct_def) -> StructType {
|
||||||
|
if sd.ctor_id.is_some() {
|
||||||
|
// We are in a tuple-struct
|
||||||
|
match sd.fields.len() {
|
||||||
|
0 => Unit,
|
||||||
|
1 => Newtype,
|
||||||
|
_ => Tuple
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Plain
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
use std;
|
||||||
|
use clean::*;
|
||||||
|
use std::iterator::Extendable;
|
||||||
|
|
||||||
|
pub trait DocFolder {
|
||||||
|
fn fold_item(&mut self, item: Item) -> Option<Item> {
|
||||||
|
self.fold_item_recur(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// don't override!
|
||||||
|
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
|
||||||
|
use std::util::swap;
|
||||||
|
let Item { attrs, name, source, visibility, id, inner } = item;
|
||||||
|
let inner = inner;
|
||||||
|
let c = |x| self.fold_item(x);
|
||||||
|
let inner = match inner {
|
||||||
|
StructItem(i) => {
|
||||||
|
let mut i = i;
|
||||||
|
let mut foo = ~[]; swap(&mut foo, &mut i.fields);
|
||||||
|
i.fields.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
|
||||||
|
StructItem(i)
|
||||||
|
},
|
||||||
|
ModuleItem(i) => {
|
||||||
|
ModuleItem(self.fold_mod(i))
|
||||||
|
},
|
||||||
|
EnumItem(i) => {
|
||||||
|
let mut i = i;
|
||||||
|
let mut foo = ~[]; swap(&mut foo, &mut i.variants);
|
||||||
|
i.variants.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
|
||||||
|
EnumItem(i)
|
||||||
|
},
|
||||||
|
TraitItem(i) => {
|
||||||
|
fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
|
||||||
|
match trm {
|
||||||
|
Required(it) => {
|
||||||
|
match this.fold_item(it) {
|
||||||
|
Some(x) => return Some(Required(x)),
|
||||||
|
None => return None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Provided(it) => {
|
||||||
|
match this.fold_item(it) {
|
||||||
|
Some(x) => return Some(Provided(x)),
|
||||||
|
None => return None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut i = i;
|
||||||
|
let mut foo = ~[]; swap(&mut foo, &mut i.methods);
|
||||||
|
i.methods.extend(&mut foo.move_iter().filter_map(|x| vtrm(self, x)));
|
||||||
|
TraitItem(i)
|
||||||
|
},
|
||||||
|
ImplItem(i) => {
|
||||||
|
let mut i = i;
|
||||||
|
let mut foo = ~[]; swap(&mut foo, &mut i.methods);
|
||||||
|
i.methods.extend(&mut foo.move_iter().filter_map(|x| self.fold_item(x)));
|
||||||
|
ImplItem(i)
|
||||||
|
},
|
||||||
|
VariantItem(i) => {
|
||||||
|
let i2 = i.clone(); // this clone is small
|
||||||
|
match i.kind {
|
||||||
|
StructVariant(j) => {
|
||||||
|
let mut j = j;
|
||||||
|
let mut foo = ~[]; swap(&mut foo, &mut j.fields);
|
||||||
|
j.fields.extend(&mut foo.move_iter().filter_map(c));
|
||||||
|
VariantItem(Variant {kind: StructVariant(j), ..i2})
|
||||||
|
},
|
||||||
|
_ => VariantItem(i2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
x => x
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(Item { attrs: attrs, name: name, source: source, inner: inner,
|
||||||
|
visibility: visibility, id: id })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_mod(&mut self, m: Module) -> Module {
|
||||||
|
Module { items: m.items.move_iter().filter_map(|i| self.fold_item(i)).collect() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_crate(&mut self, mut c: Crate) -> Crate {
|
||||||
|
let mut mod_ = None;
|
||||||
|
std::util::swap(&mut mod_, &mut c.module);
|
||||||
|
let mod_ = mod_.unwrap();
|
||||||
|
c.module = self.fold_item(mod_);
|
||||||
|
let Crate { name, module } = c;
|
||||||
|
match module {
|
||||||
|
Some(Item { inner: ModuleItem(m), name: name_, attrs: attrs_,
|
||||||
|
source, visibility: vis, id }) => {
|
||||||
|
return Crate { module: Some(Item { inner:
|
||||||
|
ModuleItem(self.fold_mod(m)),
|
||||||
|
name: name_, attrs: attrs_,
|
||||||
|
source: source, id: id, visibility: vis }), name: name};
|
||||||
|
},
|
||||||
|
Some(_) => fail!("non-module item set as module of crate"),
|
||||||
|
None => return Crate { module: None, name: name},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#[link(name = "rustdoc_ng",
|
||||||
|
vers = "0.1.0",
|
||||||
|
uuid = "8c6e4598-1596-4aa5-a24c-b811914bbbc6")];
|
||||||
|
#[desc = "rustdoc, the Rust documentation extractor"];
|
||||||
|
#[license = "MIT/ASL2"];
|
||||||
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
|
#[deny(warnings)];
|
||||||
|
|
||||||
|
extern mod syntax;
|
||||||
|
extern mod rustc;
|
||||||
|
|
||||||
|
extern mod extra;
|
||||||
|
|
||||||
|
use extra::serialize::Encodable;
|
||||||
|
|
||||||
|
pub mod core;
|
||||||
|
pub mod doctree;
|
||||||
|
pub mod clean;
|
||||||
|
pub mod visit_ast;
|
||||||
|
pub mod fold;
|
||||||
|
pub mod plugins;
|
||||||
|
pub mod passes;
|
||||||
|
|
||||||
|
pub static SCHEMA_VERSION: &'static str = "0.8.0";
|
||||||
|
|
||||||
|
pub static ctxtkey: std::local_data::Key<@core::DocContext> = &std::local_data::Key;
|
|
@ -0,0 +1,94 @@
|
||||||
|
#[link(name = "rustdoc_ng",
|
||||||
|
vers = "0.1.0",
|
||||||
|
uuid = "8c6e4598-1596-4aa5-a24c-b811914bbbc6")];
|
||||||
|
#[desc = "rustdoc, the Rust documentation extractor"];
|
||||||
|
#[license = "MIT/ASL2"];
|
||||||
|
#[crate_type = "bin"];
|
||||||
|
|
||||||
|
extern mod extra;
|
||||||
|
extern mod rustdoc_ng;
|
||||||
|
|
||||||
|
use rustdoc_ng::*;
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use extra::serialize::Encodable;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use extra::getopts::*;
|
||||||
|
use extra::getopts::groups::*;
|
||||||
|
|
||||||
|
let args = std::os::args();
|
||||||
|
let opts = ~[
|
||||||
|
optmulti("L", "library-path", "directory to add to crate search path", "DIR"),
|
||||||
|
optmulti("p", "plugin", "plugin to load and run", "NAME"),
|
||||||
|
optmulti("", "plugin-path", "directory to load plugins from", "DIR"),
|
||||||
|
// auxillary pass (defaults to hidden_strip
|
||||||
|
optmulti("a", "pass", "auxillary pass to run", "NAME"),
|
||||||
|
optflag("n", "no-defult-passes", "do not run the default passes"),
|
||||||
|
optflag("h", "help", "show this help message"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let matches = getopts(args.tail(), opts).unwrap();
|
||||||
|
|
||||||
|
if opt_present(&matches, "h") || opt_present(&matches, "help") {
|
||||||
|
println(usage(args[0], opts));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let libs = Cell::new(opt_strs(&matches, "L").map(|s| Path(*s)));
|
||||||
|
|
||||||
|
let mut passes = if opt_present(&matches, "n") {
|
||||||
|
~[]
|
||||||
|
} else {
|
||||||
|
~[~"collapse-docs", ~"clean-comments", ~"collapse-privacy" ]
|
||||||
|
};
|
||||||
|
|
||||||
|
opt_strs(&matches, "a").map(|x| passes.push(x.clone()));
|
||||||
|
|
||||||
|
if matches.free.len() != 1 {
|
||||||
|
println(usage(args[0], opts));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cr = Cell::new(Path(matches.free[0]));
|
||||||
|
|
||||||
|
let crate = std::task::try(|| {let cr = cr.take(); core::run_core(libs.take(), &cr)}).unwrap();
|
||||||
|
|
||||||
|
// { "schema": version, "crate": { parsed crate ... }, "plugins": { output of plugins ... }}
|
||||||
|
let mut json = ~extra::treemap::TreeMap::new();
|
||||||
|
json.insert(~"schema", extra::json::String(SCHEMA_VERSION.to_owned()));
|
||||||
|
|
||||||
|
let mut pm = plugins::PluginManager::new(Path("/tmp/rustdoc_ng/plugins"));
|
||||||
|
|
||||||
|
for pass in passes.iter() {
|
||||||
|
pm.add_plugin(match pass.as_slice() {
|
||||||
|
"strip-hidden" => passes::strip_hidden,
|
||||||
|
"clean-comments" => passes::clean_comments,
|
||||||
|
"collapse-docs" => passes::collapse_docs,
|
||||||
|
"collapse-privacy" => passes::collapse_privacy,
|
||||||
|
s => { error!("unknown pass %s, skipping", s); passes::noop },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for pname in opt_strs(&matches, "p").move_iter() {
|
||||||
|
pm.load_plugin(pname);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (crate, res) = pm.run_plugins(crate);
|
||||||
|
let plugins_json = ~res.move_iter().filter_map(|opt| opt).collect();
|
||||||
|
|
||||||
|
// FIXME: yuck, Rust -> str -> JSON round trip! No way to .encode
|
||||||
|
// straight to the Rust JSON representation.
|
||||||
|
let crate_json_str = do std::io::with_str_writer |w| {
|
||||||
|
crate.encode(&mut extra::json::Encoder(w));
|
||||||
|
};
|
||||||
|
let crate_json = match extra::json::from_str(crate_json_str) {
|
||||||
|
Ok(j) => j,
|
||||||
|
Err(_) => fail!("Rust generated JSON is invalid??")
|
||||||
|
};
|
||||||
|
|
||||||
|
json.insert(~"crate", crate_json);
|
||||||
|
json.insert(~"plugins", extra::json::Object(plugins_json));
|
||||||
|
|
||||||
|
println(extra::json::Object(json).to_str());
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
use std;
|
||||||
|
use clean;
|
||||||
|
use syntax::ast;
|
||||||
|
use clean::Item;
|
||||||
|
use plugins;
|
||||||
|
use fold;
|
||||||
|
use fold::DocFolder;
|
||||||
|
|
||||||
|
/// A sample pass showing the minimum required work for a plugin.
|
||||||
|
pub fn noop(crate: clean::Crate) -> plugins::PluginResult {
|
||||||
|
(crate, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Strip items marked `#[doc(hidden)]`
|
||||||
|
pub fn strip_hidden(crate: clean::Crate) -> plugins::PluginResult {
|
||||||
|
struct Stripper;
|
||||||
|
impl fold::DocFolder for Stripper {
|
||||||
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
|
for attr in i.attrs.iter() {
|
||||||
|
match attr {
|
||||||
|
&clean::List(~"doc", ref l) => {
|
||||||
|
for innerattr in l.iter() {
|
||||||
|
match innerattr {
|
||||||
|
&clean::Word(ref s) if "hidden" == *s => {
|
||||||
|
info!("found one in strip_hidden; removing");
|
||||||
|
return None;
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.fold_item_recur(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut stripper = Stripper;
|
||||||
|
let crate = stripper.fold_crate(crate);
|
||||||
|
(crate, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clean_comments(crate: clean::Crate) -> plugins::PluginResult {
|
||||||
|
struct CommentCleaner;
|
||||||
|
impl fold::DocFolder for CommentCleaner {
|
||||||
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
|
let mut i = i;
|
||||||
|
let mut avec: ~[clean::Attribute] = ~[];
|
||||||
|
for attr in i.attrs.iter() {
|
||||||
|
match attr {
|
||||||
|
&clean::NameValue(~"doc", ref s) => avec.push(
|
||||||
|
clean::NameValue(~"doc", clean_comment_body(s.clone()))),
|
||||||
|
x => avec.push(x.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.attrs = avec;
|
||||||
|
self.fold_item_recur(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut cleaner = CommentCleaner;
|
||||||
|
let crate = cleaner.fold_crate(crate);
|
||||||
|
(crate, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collapse_privacy(crate: clean::Crate) -> plugins::PluginResult {
|
||||||
|
struct PrivacyCollapser {
|
||||||
|
stack: ~[clean::Visibility]
|
||||||
|
}
|
||||||
|
impl fold::DocFolder for PrivacyCollapser {
|
||||||
|
fn fold_item(&mut self, mut i: Item) -> Option<Item> {
|
||||||
|
if i.visibility.is_some() {
|
||||||
|
if i.visibility == Some(ast::inherited) {
|
||||||
|
i.visibility = Some(self.stack.last().clone());
|
||||||
|
} else {
|
||||||
|
self.stack.push(i.visibility.clone().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.fold_item_recur(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut privacy = PrivacyCollapser { stack: ~[] };
|
||||||
|
let crate = privacy.fold_crate(crate);
|
||||||
|
(crate, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collapse_docs(crate: clean::Crate) -> plugins::PluginResult {
|
||||||
|
struct Collapser;
|
||||||
|
impl fold::DocFolder for Collapser {
|
||||||
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
|
let mut docstr = ~"";
|
||||||
|
let mut i = i;
|
||||||
|
for attr in i.attrs.iter() {
|
||||||
|
match *attr {
|
||||||
|
clean::NameValue(~"doc", ref s) => {
|
||||||
|
docstr.push_str(s.clone());
|
||||||
|
docstr.push_char('\n');
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut a: ~[clean::Attribute] = i.attrs.iter().filter(|&a| match a {
|
||||||
|
&clean::NameValue(~"doc", _) => false,
|
||||||
|
_ => true
|
||||||
|
}).map(|x| x.clone()).collect();
|
||||||
|
if "" != docstr {
|
||||||
|
a.push(clean::NameValue(~"doc", docstr.trim().to_owned()));
|
||||||
|
}
|
||||||
|
i.attrs = a;
|
||||||
|
self.fold_item_recur(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut collapser = Collapser;
|
||||||
|
let crate = collapser.fold_crate(crate);
|
||||||
|
(crate, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Utility
|
||||||
|
enum CleanCommentStates {
|
||||||
|
Collect,
|
||||||
|
Strip,
|
||||||
|
Stripped,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the index of the last character all strings have common in their
|
||||||
|
/// prefix.
|
||||||
|
fn longest_common_prefix(s: ~[~str]) -> uint {
|
||||||
|
// find the longest common prefix
|
||||||
|
|
||||||
|
debug!("lcp: looking into %?", s);
|
||||||
|
// index of the last character all the strings share
|
||||||
|
let mut index = 0u;
|
||||||
|
|
||||||
|
if s.len() <= 1 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// whether one of the strings has been exhausted of characters yet
|
||||||
|
let mut exhausted = false;
|
||||||
|
|
||||||
|
// character iterators for all the lines
|
||||||
|
let mut lines = s.iter().filter(|x| x.len() != 0).map(|x| x.iter()).to_owned_vec();
|
||||||
|
|
||||||
|
'outer: loop {
|
||||||
|
// because you can't label a while loop
|
||||||
|
if exhausted == true {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug!("lcp: index %u", index);
|
||||||
|
let mut lines = lines.mut_iter();
|
||||||
|
let ch = match lines.next().unwrap().next() {
|
||||||
|
Some(c) => c,
|
||||||
|
None => { exhausted = true; loop },
|
||||||
|
};
|
||||||
|
debug!("looking for char %c", ch);
|
||||||
|
for line in lines {
|
||||||
|
match line.next() {
|
||||||
|
Some(c) => if c == ch { loop } else { exhausted = true; loop 'outer },
|
||||||
|
None => { exhausted = true; loop 'outer }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("lcp: last index %u", index);
|
||||||
|
index
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clean_comment_body(s: ~str) -> ~str {
|
||||||
|
// FIXME #31: lots of copies in here.
|
||||||
|
let lines = s.line_iter().to_owned_vec();
|
||||||
|
match lines.len() {
|
||||||
|
0 => return ~"",
|
||||||
|
1 => return lines[0].slice_from(2).trim().to_owned(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ol = std::vec::with_capacity(lines.len());
|
||||||
|
for line in lines.clone().move_iter() {
|
||||||
|
// replace meaningless things with a single newline
|
||||||
|
match line {
|
||||||
|
x if ["/**", "/*!", "///", "//!", "*/"].contains(&x.trim()) => ol.push(~""),
|
||||||
|
x if x.trim() == "" => ol.push(~""),
|
||||||
|
x => ol.push(x.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let li = longest_common_prefix(ol.clone());
|
||||||
|
|
||||||
|
let x = ol.iter()
|
||||||
|
.filter(|x| { debug!("cleaning line: %s", **x); true })
|
||||||
|
.map(|x| if x.len() == 0 { ~"" } else { x.slice_chars(li, x.char_len()).to_owned() })
|
||||||
|
.to_owned_vec().connect("\n");
|
||||||
|
x.trim().to_owned()
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
use clean;
|
||||||
|
|
||||||
|
use extra;
|
||||||
|
use dl = std::unstable::dynamic_lib;
|
||||||
|
|
||||||
|
pub type PluginJson = Option<(~str, extra::json::Json)>;
|
||||||
|
pub type PluginResult = (clean::Crate, PluginJson);
|
||||||
|
pub type plugin_callback = extern fn (clean::Crate) -> PluginResult;
|
||||||
|
|
||||||
|
/// Manages loading and running of plugins
|
||||||
|
pub struct PluginManager {
|
||||||
|
priv dylibs: ~[dl::DynamicLibrary],
|
||||||
|
priv callbacks: ~[plugin_callback],
|
||||||
|
/// The directory plugins will be loaded from
|
||||||
|
prefix: Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginManager {
|
||||||
|
/// Create a new plugin manager
|
||||||
|
pub fn new(prefix: Path) -> PluginManager {
|
||||||
|
PluginManager {
|
||||||
|
dylibs: ~[],
|
||||||
|
callbacks: ~[],
|
||||||
|
prefix: prefix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load a plugin with the given name.
|
||||||
|
///
|
||||||
|
/// Turns `name` into the proper dynamic library filename for the given
|
||||||
|
/// platform. On windows, it turns into name.dll, on OS X, name.dylib, and
|
||||||
|
/// elsewhere, libname.so.
|
||||||
|
pub fn load_plugin(&mut self, name: ~str) {
|
||||||
|
let x = self.prefix.push(libname(name));
|
||||||
|
let lib_result = dl::DynamicLibrary::open(Some(&x));
|
||||||
|
let lib = lib_result.unwrap();
|
||||||
|
let plugin = unsafe { lib.symbol("rustdoc_plugin_entrypoint") }.unwrap();
|
||||||
|
self.dylibs.push(lib);
|
||||||
|
self.callbacks.push(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load a normal Rust function as a plugin.
|
||||||
|
///
|
||||||
|
/// This is to run passes over the cleaned crate. Plugins run this way
|
||||||
|
/// correspond to the A-aux tag on Github.
|
||||||
|
pub fn add_plugin(&mut self, plugin: plugin_callback) {
|
||||||
|
self.callbacks.push(plugin);
|
||||||
|
}
|
||||||
|
/// Run all the loaded plugins over the crate, returning their results
|
||||||
|
pub fn run_plugins(&self, crate: clean::Crate) -> (clean::Crate, ~[PluginJson]) {
|
||||||
|
let mut out_json = ~[];
|
||||||
|
let mut crate = crate;
|
||||||
|
for &callback in self.callbacks.iter() {
|
||||||
|
let (c, res) = callback(crate);
|
||||||
|
crate = c;
|
||||||
|
out_json.push(res);
|
||||||
|
}
|
||||||
|
(crate, out_json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os="win32")]
|
||||||
|
fn libname(mut n: ~str) -> ~str {
|
||||||
|
n.push_str(".dll");
|
||||||
|
n
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os="macos")]
|
||||||
|
fn libname(mut n: ~str) -> ~str {
|
||||||
|
n.push_str(".dylib");
|
||||||
|
n
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os="win32"), not(target_os="macos"))]
|
||||||
|
fn libname(n: ~str) -> ~str {
|
||||||
|
let mut i = ~"lib";
|
||||||
|
i.push_str(n);
|
||||||
|
i.push_str(".so");
|
||||||
|
i
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
//! Rust AST Visitor. Extracts useful information and massages it into a form
|
||||||
|
//! usable for clean
|
||||||
|
|
||||||
|
use syntax::abi::AbiSet;
|
||||||
|
use syntax::{ast, ast_map};
|
||||||
|
use syntax::codemap::span;
|
||||||
|
|
||||||
|
use doctree::*;
|
||||||
|
use std::local_data;
|
||||||
|
|
||||||
|
pub struct RustdocVisitor {
|
||||||
|
module: Module,
|
||||||
|
attrs: ~[ast::Attribute],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RustdocVisitor {
|
||||||
|
pub fn new() -> RustdocVisitor {
|
||||||
|
RustdocVisitor {
|
||||||
|
module: Module::new(None),
|
||||||
|
attrs: ~[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RustdocVisitor {
|
||||||
|
pub fn visit(@mut self, crate: &ast::Crate) {
|
||||||
|
self.attrs = crate.attrs.clone();
|
||||||
|
fn visit_struct_def(item: &ast::item, sd: @ast::struct_def, generics:
|
||||||
|
&ast::Generics) -> Struct {
|
||||||
|
debug!("Visiting struct");
|
||||||
|
let struct_type = struct_type_from_def(sd);
|
||||||
|
Struct {
|
||||||
|
id: item.id,
|
||||||
|
struct_type: struct_type,
|
||||||
|
name: item.ident,
|
||||||
|
vis: item.vis,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
generics: generics.clone(),
|
||||||
|
fields: sd.fields.iter().map(|x| (*x).clone()).to_owned_vec(),
|
||||||
|
where: item.span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_enum_def(it: &ast::item, def: &ast::enum_def, params: &ast::Generics) -> Enum {
|
||||||
|
debug!("Visiting enum");
|
||||||
|
let mut vars: ~[Variant] = ~[];
|
||||||
|
for x in def.variants.iter() {
|
||||||
|
vars.push(Variant {
|
||||||
|
name: x.node.name,
|
||||||
|
attrs: x.node.attrs.clone(),
|
||||||
|
vis: x.node.vis,
|
||||||
|
id: x.node.id,
|
||||||
|
kind: x.node.kind.clone(),
|
||||||
|
where: x.span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Enum {
|
||||||
|
name: it.ident,
|
||||||
|
variants: vars,
|
||||||
|
vis: it.vis,
|
||||||
|
generics: params.clone(),
|
||||||
|
attrs: it.attrs.clone(),
|
||||||
|
id: it.id,
|
||||||
|
where: it.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_fn(item: &ast::item, fd: &ast::fn_decl, _purity: &ast::purity,
|
||||||
|
_abi: &AbiSet, gen: &ast::Generics) -> Function {
|
||||||
|
debug!("Visiting fn");
|
||||||
|
Function {
|
||||||
|
id: item.id,
|
||||||
|
vis: item.vis,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
decl: fd.clone(),
|
||||||
|
name: item.ident,
|
||||||
|
where: item.span,
|
||||||
|
generics: gen.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mod_contents(span: span, attrs: ~[ast::Attribute], vis:
|
||||||
|
ast::visibility, id: ast::NodeId, m: &ast::_mod) -> Module {
|
||||||
|
let am = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.items;
|
||||||
|
let name = match am.find(&id) {
|
||||||
|
Some(m) => match m {
|
||||||
|
&ast_map::node_item(ref it, _) => Some(it.ident),
|
||||||
|
_ => fail!("mod id mapped to non-item in the ast map")
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
let mut om = Module::new(name);
|
||||||
|
om.view_items = m.view_items.clone();
|
||||||
|
om.where = span;
|
||||||
|
om.attrs = attrs;
|
||||||
|
om.vis = vis;
|
||||||
|
om.id = id;
|
||||||
|
for i in m.items.iter() {
|
||||||
|
visit_item(*i, &mut om);
|
||||||
|
}
|
||||||
|
om
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_item(item: &ast::item, om: &mut Module) {
|
||||||
|
debug!("Visiting item %?", item);
|
||||||
|
match item.node {
|
||||||
|
ast::item_mod(ref m) => {
|
||||||
|
om.mods.push(visit_mod_contents(item.span, item.attrs.clone(),
|
||||||
|
item.vis, item.id, m));
|
||||||
|
},
|
||||||
|
ast::item_enum(ref ed, ref gen) => om.enums.push(visit_enum_def(item, ed, gen)),
|
||||||
|
ast::item_struct(sd, ref gen) => om.structs.push(visit_struct_def(item, sd, gen)),
|
||||||
|
ast::item_fn(ref fd, ref pur, ref abi, ref gen, _) =>
|
||||||
|
om.fns.push(visit_fn(item, fd, pur, abi, gen)),
|
||||||
|
ast::item_ty(ref ty, ref gen) => {
|
||||||
|
let t = Typedef {
|
||||||
|
ty: ty.clone(),
|
||||||
|
gen: gen.clone(),
|
||||||
|
name: item.ident,
|
||||||
|
id: item.id,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.typedefs.push(t);
|
||||||
|
},
|
||||||
|
ast::item_static(ref ty, ref mut_, ref exp) => {
|
||||||
|
let s = Static {
|
||||||
|
type_: ty.clone(),
|
||||||
|
mutability: mut_.clone(),
|
||||||
|
expr: exp.clone(),
|
||||||
|
id: item.id,
|
||||||
|
name: item.ident,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.statics.push(s);
|
||||||
|
},
|
||||||
|
ast::item_trait(ref gen, ref tr, ref met) => {
|
||||||
|
let t = Trait {
|
||||||
|
name: item.ident,
|
||||||
|
methods: met.clone(),
|
||||||
|
generics: gen.clone(),
|
||||||
|
parents: tr.clone(),
|
||||||
|
id: item.id,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.traits.push(t);
|
||||||
|
},
|
||||||
|
ast::item_impl(ref gen, ref tr, ref ty, ref meths) => {
|
||||||
|
let i = Impl {
|
||||||
|
generics: gen.clone(),
|
||||||
|
trait_: tr.clone(),
|
||||||
|
for_: ty.clone(),
|
||||||
|
methods: meths.clone(),
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
id: item.id,
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.impls.push(i);
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.module = visit_mod_contents(crate.span, crate.attrs.clone(),
|
||||||
|
ast::public, ast::CRATE_NODE_ID, &crate.module);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue