diff --git a/Makefile.in b/Makefile.in index 3c7542e19c7..eca5c3453e6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -214,7 +214,6 @@ CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc) CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax) CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg) 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_LIBRUST_$(1) :=$(call CFG_LIB_NAME_$(1),rust) @@ -224,7 +223,6 @@ LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc) LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax) LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg) 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) LIBRUST_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rust) EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra) @@ -233,7 +231,6 @@ LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc) LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax) LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg) 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) LIBRUST_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rust) @@ -442,12 +439,10 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ $$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ - $$(HBIN$(1)_H_$(3))/rustdoc_ng$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rusti$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rust$$(X_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(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_LIBRUST_$(3)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ @@ -456,7 +451,6 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(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_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_LIBRUST_$(2)) diff --git a/RELEASES.txt b/RELEASES.txt index 71243df3f6c..63080fe6528 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -143,7 +143,8 @@ Version 0.8 (October 2013) * The runtime uses jemalloc for allocations. * Segmented stacks are temporarily disabled as part of the transition to the new runtime. Stack overflows are possible! - * A new documentation backend, rustdoc_ng, is available for use + * A new documentation backend, rustdoc_ng, is available for use. It is + still invoked through the normal `rustdoc` command. Version 0.7 (July 2013) ----------------------- diff --git a/mk/clean.mk b/mk/clean.mk index 30ec6b15bfe..cb8861f6597 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -68,12 +68,10 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustpkg$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X_$(2)) - $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc_ng$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rusti$(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_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_STDLIB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2)) @@ -87,7 +85,6 @@ clean$(1)_H_$(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))/$(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))/$(LIBRUST_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2)) @@ -106,12 +103,10 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X_$(2)) - $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc_ng$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rusti$(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_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_STDLIB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) @@ -125,7 +120,6 @@ 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))/$(LIBRUSTPKG_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))/$(LIBRUST_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2)) diff --git a/mk/dist.mk b/mk/dist.mk index 34230e6a5aa..4a980edf767 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -39,7 +39,6 @@ PKG_FILES := \ libsyntax \ rt \ librustdoc \ - rustdoc_ng \ rustllvm \ snapshots.txt \ test) \ diff --git a/mk/docs.mk b/mk/docs.mk index d7b5d6855ad..b89bf3483fc 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -213,40 +213,21 @@ else # The rustdoc executable RUSTDOC = $(HBIN2_H_$(CFG_BUILD_TRIPLE))/rustdoc$(X_$(CFG_BUILD_TRIPLE)) -RUSTDOC_NG = $(HBIN2_H_$(CFG_BUILD_TRIPLE))/rustdoc_ng$(X_$(CFG_BUILD_TRIPLE)) # The library documenting macro -# $(1) - The output directory +# $(1) - The crate name (std/extra) # $(2) - The crate file -# $(3) - The crate soruce files +# $(3) - The relevant host build triple (to depend on libstd) define libdoc -doc/$(1)/index.html: $(2) $(3) $$(RUSTDOC) doc/$(1)/rust.css +doc/$(1)/index.html: $$(RUSTDOC) $$(TLIB2_T_$(3)_H_$(3))/$(CFG_STDLIB_$(3)) @$$(call E, rustdoc: $$@) - $(Q)$(RUSTDOC) $(2) --output-dir=doc/$(1) - -doc/$(1)/rust.css: rust.css - @$$(call E, cp: $$@) - $(Q)cp $$< $$@ + $(Q)$(RUSTDOC) html $(2) DOCS += doc/$(1)/index.html endef -# The "next generation" library documenting macro -# $(1) - The crate name (std/extra) -# $(2) - The crate file -# $(3) - The relevant host build triple (to depend on libstd) -define libdocng -doc/ng/$(1)/index.html: $$(RUSTDOC_NG) $$(TLIB2_T_$(3)_H_$(3))/$(CFG_STDLIB_$(3)) - @$$(call E, rustdoc_ng: $$@) - $(Q)$(RUSTDOC_NG) html $(2) -o doc/ng - -DOCS += doc/ng/$(1)/index.html -endef - -$(eval $(call libdoc,std,$(STDLIB_CRATE),$(STDLIB_INPUTS))) -$(eval $(call libdoc,extra,$(EXTRALIB_CRATE),$(EXTRALIB_INPUTS))) -$(eval $(call libdocng,std,$(STDLIB_CRATE),$(CFG_BUILD_TRIPLE))) -$(eval $(call libdocng,extra,$(EXTRALIB_CRATE),$(CFG_BUILD_TRIPLE))) +$(eval $(call libdoc,std,$(STDLIB_CRATE),$(CFG_BUILD_TRIPLE))) +$(eval $(call libdoc,extra,$(EXTRALIB_CRATE),$(CFG_BUILD_TRIPLE))) endif diff --git a/mk/install.mk b/mk/install.mk index 3989e4f8119..4b50c5aa796 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -104,7 +104,6 @@ install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_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,$$(LIBRUST_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,libmorestack.a) @@ -140,7 +139,6 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE)) $(Q)$(call INSTALL,$(HB2),$(PHB),rustc$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustpkg$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc_ng$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rusti$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rust$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(STDLIB_GLOB_$(CFG_BUILD_TRIPLE))) @@ -151,7 +149,6 @@ 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,$(LIBRUSTPKG_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_RUSTLLVM_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rust.1) @@ -172,7 +169,6 @@ uninstall: $(Q)rm -f $(PHB)/rusti$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rust$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rustdoc$(X_$(CFG_BUILD_TRIPLE)) - $(Q)rm -f $(PHB)/rustdoc_ng$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)) $(Q)for i in \ @@ -182,7 +178,6 @@ uninstall: $(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) \ - $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTDOCNG_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUST_GLOB_$(CFG_BUILD_TRIPLE))) \ ; \ diff --git a/mk/tests.mk b/mk/tests.mk index 14b06bf047e..9fe163e509b 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -15,7 +15,7 @@ # The names of crates that must be tested TEST_TARGET_CRATES = std extra -TEST_HOST_CRATES = rust rusti rustpkg rustc rustdoc rustdocng syntax +TEST_HOST_CRATES = rust rusti rustpkg rustc rustdoc syntax TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) # Markdown files under doc/ that should have their code extracted and run @@ -393,14 +393,6 @@ $(3)/stage$(1)/test/rustdoctest-$(2)$$(X_$(2)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test -$(3)/stage$(1)/test/rustdocngtest-$(2)$$(X_$(2)): \ - $$(RUSTDOCNG_LIB) $$(RUSTDOCNG_INPUTS) \ - $$(SREQ$(1)_T_$(2)_H_$(3)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test - endef $(foreach host,$(CFG_HOST_TRIPLES), \ diff --git a/mk/tools.mk b/mk/tools.mk index 212b7e570f7..09c3de01478 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -23,11 +23,6 @@ RUSTPKG_INPUTS := $(wildcard $(S)src/librustpkg/*.rs) RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs RUSTDOC_INPUTS := $(wildcard $(S)src/librustdoc/*.rs) -# rustdoc_ng, the next generation documentation tool - -RUSTDOCNG_LIB := $(S)src/rustdoc_ng/rustdoc_ng.rs -RUSTDOCNG_INPUTS := $(wildcard $(S)src/rustdoc_ng/*.rs) - # Rusti, the JIT REPL RUSTI_LIB := $(S)src/librusti/rusti.rs RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs) @@ -83,24 +78,6 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$< -$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(4)): \ - $$(RUSTDOCNG_LIB) $$(RUSTDOCNG_INPUTS) \ - $$(SREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \ - | $$(TLIB$(1)_T_$(4)_H_$(3))/ - @$$(call E, compile_and_link: $$@) - $$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOCNG_GLOB_$(4)),$$(notdir $$@)) - $$(STAGE$(1)_T_$(4)_H_$(3)) --out-dir $$(@D) $$< && touch $$@ - $$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOCNG_GLOB_$(4)),$$(notdir $$@)) - -$$(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)): \ $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ $$(SREQ$(1)_T_$(4)_H_$(3)) \ @@ -125,7 +102,6 @@ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUST_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \ | $$(TLIB$(1)_T_$(4)_H_$(3))/ @$$(call E, compile_and_link: $$@) @@ -195,27 +171,6 @@ $$(HBIN$(2)_H_$(4))/rustdoc$$(X_$(4)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTDOCNG_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOCNG_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HLIB$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOCNG_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp $$< $$@ - $$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOCNG_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTDOCNG_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTDOCNG_DSYM_GLOB_$(4))) \ - $$(HLIB$(2)_H_$(4)) - -$$(HBIN$(2)_H_$(4))/rustdoc_ng$$(X_$(4)): \ - $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc_ng$$(X_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTDOCNG_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HBIN$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTI_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ diff --git a/src/librust/rust.rs b/src/librust/rust.rs index 01902c356a7..eb82cfcc0b2 100644 --- a/src/librust/rust.rs +++ b/src/librust/rust.rs @@ -92,7 +92,7 @@ static COMMANDS: &'static [Command<'static>] = &'static [ cmd: "doc", action: CallMain("rustdoc", rustdoc::main_args), usage_line: "generate documentation from doc comments", - usage_full: UsgCall(rustdoc::config::usage), + usage_full: UsgCall(rustdoc_help), }, Command { cmd: "pkg", @@ -122,6 +122,10 @@ fn rustc_help() { rustc::usage(os::args()[0].clone()) } +fn rustdoc_help() { + rustdoc::usage(os::args()[0].clone()) +} + fn find_cmd(command_string: &str) -> Option { do COMMANDS.iter().find |command| { command.cmd == command_string diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs deleted file mode 100644 index b2b7599aae3..00000000000 --- a/src/librustdoc/astsrv.rs +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Provides all access to AST-related, non-sendable info - -Rustdoc is intended to be parallel, and the rustc AST is filled with -shared boxes. The AST service attempts to provide a single place to -query AST-related information, shielding the rest of Rustdoc from its -non-sendableness. -*/ - - -use parse; - -use std::cell::Cell; -use std::comm::{stream, SharedChan, Port}; -use std::task; -use rustc::driver::driver; -use rustc::driver::session::Session; -use rustc::driver::session::{basic_options, options}; -use rustc::front; -use syntax::ast; -use syntax::ast_map; -use syntax::ast_util; -use syntax; - -pub struct Ctxt { - ast: @ast::Crate, - ast_map: ast_map::map -} - -type SrvOwner<'self,T> = &'self fn(srv: Srv) -> T; -pub type CtxtHandler = ~fn(ctxt: Ctxt) -> T; -type Parser = ~fn(Session, s: @str) -> @ast::Crate; - -enum Msg { - HandleRequest(~fn(Ctxt)), - Exit -} - -#[deriving(Clone)] -pub struct Srv { - ch: SharedChan -} - -pub fn from_str(source: ~str, owner: SrvOwner) -> T { - run(owner, source.clone(), parse::from_str_sess) -} - -pub fn from_file(file: ~str, owner: SrvOwner) -> T { - run(owner, file.clone(), |sess, f| parse::from_file_sess(sess, &Path(f))) -} - -fn run(owner: SrvOwner, source: ~str, parse: Parser) -> T { - - let (po, ch) = stream(); - - let source = Cell::new(source); - let parse = Cell::new(parse); - do task::spawn { - act(&po, source.take().to_managed(), parse.take()); - } - - let srv_ = Srv { - ch: SharedChan::new(ch) - }; - - let res = owner(srv_.clone()); - srv_.ch.send(Exit); - res -} - -fn act(po: &Port, source: @str, parse: Parser) { - let sess = build_session(); - - let ctxt = build_ctxt( - sess, - parse(sess, source) - ); - - let mut keep_going = true; - while keep_going { - match po.recv() { - HandleRequest(f) => { - f(ctxt); - } - Exit => { - keep_going = false; - } - } - } -} - -pub fn exec( - srv: Srv, - f: ~fn(ctxt: Ctxt) -> T -) -> T { - let (po, ch) = stream(); - let msg = HandleRequest(|ctxt| ch.send(f(ctxt))); - srv.ch.send(msg); - po.recv() -} - -fn assign_node_ids(crate: @ast::Crate) -> @ast::Crate { - let next_id = @mut 0; - let fold = ast_util::node_id_assigner(|| { - let i = *next_id; - *next_id += 1; - i - }); - @fold.fold_crate(crate) -} - -fn build_ctxt(sess: Session, - ast: @ast::Crate) -> Ctxt { - - use rustc::front::config; - - let ast = syntax::ext::expand::inject_std_macros(sess.parse_sess, - sess.opts.cfg.clone(), - ast); - let ast = config::strip_unconfigured_items(ast); - let ast = syntax::ext::expand::expand_crate(sess.parse_sess, - sess.opts.cfg.clone(), - ast); - let ast = front::test::modify_for_testing(sess, ast); - let ast = assign_node_ids(ast); - let ast_map = ast_map::map_crate(sess.diagnostic(), ast); - - Ctxt { - ast: ast, - ast_map: ast_map, - } -} - -fn build_session() -> Session { - let sopts: @options = basic_options(); - let emitter = syntax::diagnostic::emit; - - let session = driver::build_session(sopts, emitter); - session -} - -#[test] -fn should_prune_unconfigured_items() { - let source = ~"#[cfg(shut_up_and_leave_me_alone)]fn a() { }"; - do from_str(source) |srv| { - do exec(srv) |ctxt| { - // one item: the __std_macros secret module - assert_eq!(ctxt.ast.module.items.len(), 1); - } - } -} - -#[test] -fn srv_should_build_ast_map() { - let source = ~"fn a() { }"; - do from_str(source) |srv| { - do exec(srv) |ctxt| { - assert!(!ctxt.ast_map.is_empty()) - }; - } -} - -#[test] -fn should_ignore_external_import_paths_that_dont_exist() { - let source = ~"use forble; use forble::bippy;"; - from_str(source, |_srv| { } ) -} - -#[test] -fn srv_should_return_request_result() { - let source = ~"fn a() { }"; - do from_str(source) |srv| { - let result = exec(srv, |_ctxt| 1000 ); - assert_eq!(result, 1000); - } -} diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs deleted file mode 100644 index ce8d1977443..00000000000 --- a/src/librustdoc/attr_parser.rs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Attribute parsing - -The attribute parser provides methods for pulling documentation out of -an AST's attributes. -*/ - - -use syntax::ast; -use syntax::attr; -use syntax::attr::{AttrMetaMethods, AttributeMethods}; - -pub struct CrateAttrs { - name: Option<~str> -} - -fn doc_metas(attrs: ~[ast::Attribute]) -> ~[@ast::MetaItem] { - attrs.iter() - .filter(|at| "doc" == at.name()) - .map(|at| at.desugar_doc().meta()) - .collect() -} - -pub fn parse_crate(attrs: ~[ast::Attribute]) -> CrateAttrs { - let link_metas = attr::find_linkage_metas(attrs); - let name = attr::last_meta_item_value_str_by_name(link_metas, "name"); - - CrateAttrs { - name: name.map(|s| s.to_owned()) - } -} - -pub fn parse_desc(attrs: ~[ast::Attribute]) -> Option<~str> { - let doc_strs = do doc_metas(attrs).move_iter().filter_map |meta| { - meta.value_str() - }.collect::<~[@str]>(); - if doc_strs.is_empty() { - None - } else { - Some(doc_strs.connect("\n")) - } -} - -pub fn parse_hidden(attrs: ~[ast::Attribute]) -> bool { - let r = doc_metas(attrs); - do r.iter().any |meta| { - match meta.meta_item_list() { - Some(metas) => attr::contains_name(metas, "hidden"), - None => false - } - } -} - -#[cfg(test)] -mod test { - use syntax::ast; - use syntax; - use super::{parse_hidden, parse_crate, parse_desc}; - - fn parse_attributes(source: @str) -> ~[ast::Attribute] { - use syntax::parse; - use syntax::parse::attr::parser_attr; - - let parse_sess = syntax::parse::new_parse_sess(None); - let parser = parse::new_parser_from_source_str( - parse_sess, ~[], @"-", source); - - parser.parse_outer_attributes() - } - - - #[test] - fn should_extract_crate_name_from_link_attribute() { - let source = @"#[link(name = \"snuggles\")]"; - let attrs = parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == Some(~"snuggles")); - } - - #[test] - fn should_not_extract_crate_name_if_no_link_attribute() { - let source = @""; - let attrs = parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == None); - } - - #[test] - fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() { - let source = @"#[link(whatever)]"; - let attrs = parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == None); - } - - #[test] - fn parse_desc_should_handle_undocumented_mods() { - let source = @""; - let attrs = parse_attributes(source); - let attrs = parse_desc(attrs); - assert!(attrs == None); - } - - #[test] - fn parse_desc_should_parse_simple_doc_attributes() { - let source = @"#[doc = \"basic\"]"; - let attrs = parse_attributes(source); - let attrs = parse_desc(attrs); - assert!(attrs == Some(~"basic")); - } - - #[test] - fn should_parse_hidden_attribute() { - let source = @"#[doc(hidden)]"; - let attrs = parse_attributes(source); - assert!(parse_hidden(attrs) == true); - } - - #[test] - fn should_parse_hidden_attribute_with_other_docs() { - let source = @"#[doc = \"foo\"] #[doc(hidden)] #[doc = \"foo\"]"; - let attrs = parse_attributes(source); - assert!(parse_hidden(attrs) == true); - } - - #[test] - fn should_not_parse_non_hidden_attribute() { - let source = @"#[doc = \"\"]"; - let attrs = parse_attributes(source); - assert!(parse_hidden(attrs) == false); - } - - #[test] - fn should_concatenate_multiple_doc_comments() { - let source = @"/// foo\n/// bar"; - let desc = parse_desc(parse_attributes(source)); - assert!(desc == Some(~" foo\n bar")); - } -} diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs deleted file mode 100644 index bd8d9a65cd3..00000000000 --- a/src/librustdoc/attr_pass.rs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -The attribute parsing pass - -Traverses the document tree, pulling relevant documention out of the -corresponding AST nodes. The information gathered here is the basis -of the natural-language documentation for a crate. -*/ - - -use astsrv; -use attr_parser; -use doc::ItemUtils; -use doc; -use extract::to_str; -use fold::Fold; -use fold; -use pass::Pass; - -use syntax::ast; -use syntax::ast_map; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"attr", - f: run - } -} - -pub fn run( - srv: astsrv::Srv, - doc: doc::Doc -) -> doc::Doc { - let fold = Fold { - ctxt: srv.clone(), - fold_crate: fold_crate, - fold_item: fold_item, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - .. fold::default_any_fold(srv) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_crate( - fold: &fold::Fold, - doc: doc::CrateDoc -) -> doc::CrateDoc { - - let srv = fold.ctxt.clone(); - let doc = fold::default_seq_fold_crate(fold, doc); - - let attrs = do astsrv::exec(srv) |ctxt| { - let attrs = ctxt.ast.attrs.clone(); - attr_parser::parse_crate(attrs) - }; - - doc::CrateDoc { - topmod: doc::ModDoc { - item: doc::ItemDoc { - name: attrs.name.clone().unwrap_or(doc.topmod.name_()), - .. doc.topmod.item.clone() - }, - .. doc.topmod.clone() - } - } -} - -fn fold_item( - fold: &fold::Fold, - doc: doc::ItemDoc -) -> doc::ItemDoc { - - let srv = fold.ctxt.clone(); - let doc = fold::default_seq_fold_item(fold, doc); - - let desc = if doc.id == ast::CRATE_NODE_ID { - // This is the top-level mod, use the crate attributes - do astsrv::exec(srv) |ctxt| { - attr_parser::parse_desc(ctxt.ast.attrs.clone()) - } - } else { - parse_item_attrs(srv, doc.id, attr_parser::parse_desc) - }; - - doc::ItemDoc { - desc: desc, - .. doc - } -} - -fn parse_item_attrs( - srv: astsrv::Srv, - id: doc::AstId, - parse_attrs: ~fn(a: ~[ast::Attribute]) -> T) -> T { - do astsrv::exec(srv) |ctxt| { - let attrs = match ctxt.ast_map.get_copy(&id) { - ast_map::node_item(item, _) => item.attrs.clone(), - ast_map::node_foreign_item(item, _, _, _) => item.attrs.clone(), - _ => fail!("parse_item_attrs: not an item") - }; - parse_attrs(attrs) - } -} - -fn fold_enum( - fold: &fold::Fold, - doc: doc::EnumDoc -) -> doc::EnumDoc { - - let srv = fold.ctxt.clone(); - let doc_id = doc.id(); - let doc = fold::default_seq_fold_enum(fold, doc); - - doc::EnumDoc { - variants: do doc.variants.iter().map |variant| { - let variant = (*variant).clone(); - let desc = { - let variant = variant.clone(); - do astsrv::exec(srv.clone()) |ctxt| { - match ctxt.ast_map.get_copy(&doc_id) { - ast_map::node_item(@ast::item { - node: ast::item_enum(ref enum_definition, _), _ - }, _) => { - let ast_variant = - (*enum_definition.variants.iter().find(|v| { - to_str(v.node.name) == variant.name - }).unwrap()).clone(); - - attr_parser::parse_desc( - ast_variant.node.attrs.clone()) - } - _ => { - fail!("Enum variant %s has id that's not bound to an enum item", - variant.name) - } - } - } - }; - - doc::VariantDoc { - desc: desc, - .. variant - } - }.collect(), - .. doc - } -} - -fn fold_trait( - fold: &fold::Fold, - doc: doc::TraitDoc -) -> doc::TraitDoc { - let srv = fold.ctxt.clone(); - let doc = fold::default_seq_fold_trait(fold, doc); - - doc::TraitDoc { - methods: merge_method_attrs(srv, doc.id(), doc.methods.clone()), - .. doc - } -} - -fn merge_method_attrs( - srv: astsrv::Srv, - item_id: doc::AstId, - docs: ~[doc::MethodDoc] -) -> ~[doc::MethodDoc] { - - // Create an assoc list from method name to attributes - let attrs: ~[(~str, Option<~str>)] = do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&item_id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(_, _, ref methods), _ - }, _) => { - methods.iter().map(|method| { - match (*method).clone() { - ast::required(ty_m) => { - (to_str(ty_m.ident), - attr_parser::parse_desc(ty_m.attrs.clone())) - } - ast::provided(m) => { - (to_str(m.ident), attr_parser::parse_desc(m.attrs.clone())) - } - } - }).collect() - } - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref methods), _ - }, _) => { - methods.iter().map(|method| { - (to_str(method.ident), - attr_parser::parse_desc(method.attrs.clone())) - }).collect() - } - _ => fail!("unexpected item") - } - }; - - do docs.iter().zip(attrs.iter()).map |(doc, attrs)| { - assert!(doc.name == attrs.first()); - let desc = attrs.second(); - - doc::MethodDoc { - desc: desc, - .. (*doc).clone() - } - }.collect() -} - - -fn fold_impl( - fold: &fold::Fold, - doc: doc::ImplDoc -) -> doc::ImplDoc { - let srv = fold.ctxt.clone(); - let doc = fold::default_seq_fold_impl(fold, doc); - - doc::ImplDoc { - methods: merge_method_attrs(srv, doc.id(), doc.methods.clone()), - .. doc - } -} - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass::run; - use doc; - use extract; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - run(srv.clone(), doc) - } - } - - #[test] - fn should_replace_top_module_name_with_crate_name() { - let doc = mk_doc(~"#[link(name = \"bond\")];"); - assert!(doc.cratemod().name_() == ~"bond"); - } - - #[test] - fn should_should_extract_mod_attributes() { - let doc = mk_doc(~"#[doc = \"test\"] mod a { }"); - // hidden __std_macros module at the start. - assert!(doc.cratemod().mods()[1].desc() == Some(~"test")); - } - - #[test] - fn should_extract_top_mod_attributes() { - let doc = mk_doc(~"#[doc = \"test\"];"); - assert!(doc.cratemod().desc() == Some(~"test")); - } - - #[test] - fn should_extract_foreign_fn_attributes() { - let doc = mk_doc(~"extern { #[doc = \"test\"] fn a(); }"); - assert!(doc.cratemod().nmods()[0].fns[0].desc() == Some(~"test")); - } - - #[test] - fn should_extract_fn_attributes() { - let doc = mk_doc(~"#[doc = \"test\"] fn a() -> int { }"); - assert!(doc.cratemod().fns()[0].desc() == Some(~"test")); - } - - #[test] - fn should_extract_enum_docs() { - let doc = mk_doc(~"#[doc = \"b\"]\ - enum a { v }"); - debug!("%?", doc); - assert!(doc.cratemod().enums()[0].desc() == Some(~"b")); - } - - #[test] - fn should_extract_variant_docs() { - let doc = mk_doc(~"enum a { #[doc = \"c\"] v }"); - assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"c")); - } - - #[test] - fn should_extract_trait_docs() { - let doc = mk_doc(~"#[doc = \"whatever\"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].desc() == Some(~"whatever")); - } - - #[test] - fn should_extract_trait_method_docs() { - let doc = mk_doc( - ~"trait i {\ - #[doc = \"desc\"]\ - fn f(a: bool) -> bool;\ - }"); - assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"desc")); - } - - #[test] - fn should_extract_impl_docs() { - let doc = mk_doc( - ~"#[doc = \"whatever\"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].desc() == Some(~"whatever")); - } - - #[test] - fn should_extract_impl_method_docs() { - let doc = mk_doc( - ~"impl int {\ - #[doc = \"desc\"]\ - fn f(a: bool) -> bool { }\ - }"); - assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"desc")); - } -} diff --git a/src/rustdoc_ng/clean.rs b/src/librustdoc/clean.rs similarity index 100% rename from src/rustdoc_ng/clean.rs rename to src/librustdoc/clean.rs diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs deleted file mode 100644 index 71ece178807..00000000000 --- a/src/librustdoc/config.rs +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use std::cell::Cell; -use std::os; -use std::result::Result; -use std::result; -use std::run::ProcessOutput; -use std::run; -use std::vec; -use extra::getopts; - -/// The type of document to output -#[deriving(Clone, Eq)] -pub enum OutputFormat { - /// Markdown - Markdown, - /// HTML, via markdown and pandoc - PandocHtml -} - -/// How to organize the output -#[deriving(Clone, Eq)] -pub enum OutputStyle { - /// All in a single document - DocPerCrate, - /// Each module in its own document - DocPerMod -} - -/// The configuration for a rustdoc session -#[deriving(Clone)] -pub struct Config { - input_crate: Path, - output_dir: Path, - output_format: OutputFormat, - output_style: OutputStyle, - pandoc_cmd: Option<~str> -} - -fn opt_output_dir() -> ~str { ~"output-dir" } -fn opt_output_format() -> ~str { ~"output-format" } -fn opt_output_style() -> ~str { ~"output-style" } -fn opt_pandoc_cmd() -> ~str { ~"pandoc-cmd" } -fn opt_help() -> ~str { ~"h" } - -fn opts() -> ~[(getopts::Opt, ~str)] { - ~[ - (getopts::optopt(opt_output_dir()), - ~"--output-dir Put documents here (default: .)"), - (getopts::optopt(opt_output_format()), - ~"--output-format 'markdown' or 'html' (default)"), - (getopts::optopt(opt_output_style()), - ~"--output-style 'doc-per-crate' or 'doc-per-mod' (default)"), - (getopts::optopt(opt_pandoc_cmd()), - ~"--pandoc-cmd Command for running pandoc"), - (getopts::optflag(opt_help()), - ~"-h, --help Print help") - ] -} - -pub fn usage() { - use std::io::println; - - println("Usage: rustdoc [options] \n"); - println("Options:\n"); - let r = opts(); - for opt in r.iter() { - printfln!(" %s", opt.second()); - } - println(""); -} - -pub fn default_config(input_crate: &Path) -> Config { - Config { - input_crate: (*input_crate).clone(), - output_dir: Path("."), - output_format: PandocHtml, - output_style: DocPerMod, - pandoc_cmd: None - } -} - -type Process = ~fn((&str), (&[~str])) -> ProcessOutput; - -pub fn mock_process_output(_prog: &str, _args: &[~str]) -> ProcessOutput { - ProcessOutput { - status: 0, - output: ~[], - error: ~[] - } -} - -pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput { - run::process_output(prog, args) -} - -pub fn parse_config(args: &[~str]) -> Result { - parse_config_(args, process_output) -} - -pub fn parse_config_( - args: &[~str], - process_output: Process -) -> Result { - let args = args.tail(); - let opts = vec::unzip(opts().move_iter()).first(); - match getopts::getopts(args, opts) { - Ok(matches) => { - if matches.free.len() == 1 { - let input_crate = Path(*matches.free.head()); - config_from_opts(&input_crate, &matches, process_output) - } else if matches.free.is_empty() { - Err(~"no crates specified") - } else { - Err(~"multiple crates specified") - } - } - Err(f) => { - Err(f.to_err_msg()) - } - } -} - -fn config_from_opts( - input_crate: &Path, - matches: &getopts::Matches, - process_output: Process -) -> Result { - - let config = default_config(input_crate); - let result = result::Ok(config); - let result = do result.and_then |config| { - let output_dir = matches.opt_str(opt_output_dir()); - let output_dir = output_dir.map_move(|s| Path(s)); - result::Ok(Config { - output_dir: output_dir.unwrap_or(config.output_dir.clone()), - .. config - }) - }; - let result = do result.and_then |config| { - let output_format = matches.opt_str(opt_output_format()); - do output_format.map_move_default(result::Ok(config.clone())) |output_format| { - do parse_output_format(output_format).and_then |output_format| { - result::Ok(Config { - output_format: output_format, - .. config.clone() - }) - } - } - }; - let result = do result.and_then |config| { - let output_style = - matches.opt_str(opt_output_style()); - do output_style.map_move_default(result::Ok(config.clone())) |output_style| { - do parse_output_style(output_style).and_then |output_style| { - result::Ok(Config { - output_style: output_style, - .. config.clone() - }) - } - } - }; - let process_output = Cell::new(process_output); - let result = do result.and_then |config| { - let pandoc_cmd = matches.opt_str(opt_pandoc_cmd()); - let pandoc_cmd = maybe_find_pandoc( - &config, pandoc_cmd, process_output.take()); - do pandoc_cmd.and_then |pandoc_cmd| { - result::Ok(Config { - pandoc_cmd: pandoc_cmd, - .. config.clone() - }) - } - }; - return result; -} - -fn parse_output_format(output_format: &str) -> Result { - match output_format.to_str() { - ~"markdown" => result::Ok(Markdown), - ~"html" => result::Ok(PandocHtml), - _ => result::Err(fmt!("unknown output format '%s'", output_format)) - } -} - -fn parse_output_style(output_style: &str) -> Result { - match output_style.to_str() { - ~"doc-per-crate" => result::Ok(DocPerCrate), - ~"doc-per-mod" => result::Ok(DocPerMod), - _ => result::Err(fmt!("unknown output style '%s'", output_style)) - } -} - -pub fn maybe_find_pandoc( - config: &Config, - maybe_pandoc_cmd: Option<~str>, - process_output: Process -) -> Result, ~str> { - if config.output_format != PandocHtml { - return result::Ok(maybe_pandoc_cmd); - } - - let possible_pandocs = match maybe_pandoc_cmd { - Some(pandoc_cmd) => ~[pandoc_cmd], - None => { - ~[~"pandoc"] + match os::homedir() { - Some(dir) => { - ~[dir.push_rel(&Path(".cabal/bin/pandoc")).to_str()] - } - None => ~[] - } - } - }; - - let pandoc = do possible_pandocs.iter().find |&pandoc| { - let output = process_output(*pandoc, [~"--version"]); - debug!("testing pandoc cmd %s: %?", *pandoc, output); - output.status == 0 - }; - - match pandoc { - Some(x) => Ok(Some((*x).clone())), // ugly, shouldn't be doubly wrapped - None => Err(~"couldn't find pandoc") - } -} - -#[cfg(test)] -mod test { - - use config::*; - use std::result; - use std::run::ProcessOutput; - - fn parse_config(args: &[~str]) -> Result { - parse_config_(args, mock_process_output) - } - - #[test] - fn should_find_pandoc() { - let config = Config { - output_format: PandocHtml, - .. default_config(&Path("test")) - }; - let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| { - ProcessOutput { status: 0, output: "pandoc 1.8.2.1".as_bytes().to_owned(), error: ~[] } - }; - let result = maybe_find_pandoc(&config, None, mock_process_output); - assert!(result == result::Ok(Some(~"pandoc"))); - } - - #[test] - fn should_error_with_no_pandoc() { - let config = Config { - output_format: PandocHtml, - .. default_config(&Path("test")) - }; - let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| { - ProcessOutput { status: 1, output: ~[], error: ~[] } - }; - let result = maybe_find_pandoc(&config, None, mock_process_output); - assert!(result == result::Err(~"couldn't find pandoc")); - } - - #[test] - fn should_error_with_no_crates() { - let config = parse_config([~"rustdoc"]); - assert!(config.unwrap_err() == ~"no crates specified"); - } - - #[test] - fn should_error_with_multiple_crates() { - let config = - parse_config([~"rustdoc", ~"crate1.rc", ~"crate2.rc"]); - assert!(config.unwrap_err() == ~"multiple crates specified"); - } - - #[test] - fn should_set_output_dir_to_cwd_if_not_provided() { - let config = parse_config([~"rustdoc", ~"crate.rc"]); - assert!(config.unwrap().output_dir == Path(".")); - } - - #[test] - fn should_set_output_dir_if_provided() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles" - ]); - assert!(config.unwrap().output_dir == Path("snuggles")); - } - - #[test] - fn should_set_output_format_to_pandoc_html_if_not_provided() { - let config = parse_config([~"rustdoc", ~"crate.rc"]); - assert!(config.unwrap().output_format == PandocHtml); - } - - #[test] - fn should_set_output_format_to_markdown_if_requested() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"markdown" - ]); - assert!(config.unwrap().output_format == Markdown); - } - - #[test] - fn should_set_output_format_to_pandoc_html_if_requested() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"html" - ]); - assert!(config.unwrap().output_format == PandocHtml); - } - - #[test] - fn should_error_on_bogus_format() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"bogus" - ]); - assert!(config.unwrap_err() == ~"unknown output format 'bogus'"); - } - - #[test] - fn should_set_output_style_to_doc_per_mod_by_default() { - let config = parse_config([~"rustdoc", ~"crate.rc"]); - assert!(config.unwrap().output_style == DocPerMod); - } - - #[test] - fn should_set_output_style_to_one_doc_if_requested() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-crate" - ]); - assert!(config.unwrap().output_style == DocPerCrate); - } - - #[test] - fn should_set_output_style_to_doc_per_mod_if_requested() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-mod" - ]); - assert!(config.unwrap().output_style == DocPerMod); - } - - #[test] - fn should_error_on_bogus_output_style() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"bogus" - ]); - assert!(config.unwrap_err() == ~"unknown output style 'bogus'"); - } - - #[test] - fn should_set_pandoc_command_if_requested() { - let config = parse_config([ - ~"rustdoc", ~"crate.rc", ~"--pandoc-cmd", ~"panda-bear-doc" - ]); - assert!(config.unwrap().pandoc_cmd == Some(~"panda-bear-doc")); - } - - #[test] - fn should_set_pandoc_command_when_using_pandoc() { - let config = parse_config([~"rustdoc", ~"crate.rc"]); - assert!(config.unwrap().pandoc_cmd == Some(~"pandoc")); - } -} diff --git a/src/rustdoc_ng/core.rs b/src/librustdoc/core.rs similarity index 100% rename from src/rustdoc_ng/core.rs rename to src/librustdoc/core.rs diff --git a/src/librustdoc/demo.rs b/src/librustdoc/demo.rs deleted file mode 100644 index 23c55488332..00000000000 --- a/src/librustdoc/demo.rs +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// no-reformat - -/*! - * A demonstration module - * - * Contains documentation in various forms that rustdoc understands, - * for testing purposes. It doesn't surve any functional - * purpose. This here, for instance, is just some filler text. - * - * FIXME (#3731): It would be nice if we could run some automated - * tests on this file - */ - - -/// The base price of a muffin on a non-holiday -static PRICE_OF_A_MUFFIN: float = 70f; - -struct WaitPerson { - hair_color: ~str -} - -/// The type of things that produce omnomnom -enum OmNomNomy { - /// Delicious sugar cookies - Cookie, - /// It's pizza - PizzaPie(~[uint]) -} - -fn take_my_order_please( - _waitperson: WaitPerson, - _order: ~[OmNomNomy] -) -> uint { - - /*! - * OMG would you take my order already? - * - * # Arguments - * - * * _waitperson - The waitperson that you want to bother - * * _order - The order vector. It should be filled with food - * - * # Return - * - * The price of the order, including tax - * - * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec - * molestie nisl. Duis massa risus, pharetra a scelerisque a, - * molestie eu velit. Donec mattis ligula at ante imperdiet ut - * dapibus mauris malesuada. - * - * Sed gravida nisi a metus elementum sit amet hendrerit dolor - * bibendum. Aenean sit amet neque massa, sed tempus tortor. Sed ut - * lobortis enim. Proin a mauris quis nunc fermentum ultrices eget a - * erat. Mauris in lectus vitae metus sodales auctor. Morbi nunc - * quam, ultricies at venenatis non, pellentesque ac dui. - * - * # Failure - * - * This function is full of fail - */ - - fail!(); -} - -mod fortress_of_solitude { - /*! - * Superman's vacation home - * - * The fortress of solitude is located in the Arctic and it is - * cold. What you may not know about the fortress of solitude - * though is that it contains two separate bowling alleys. One of - * them features bumper-bowling and is kind of lame. - * - * Really, it's pretty cool. - */ - -} - -mod blade_runner { - /*! - * Blade Runner is probably the best movie ever - * - * I like that in the world of Blade Runner it is always - * raining, and that it's always night time. And Aliens - * was also a really good movie. - * - * Alien 3 was crap though. - */ -} - -/** - * Bored - * - * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec - * molestie nisl. Duis massa risus, pharetra a scelerisque a, - * molestie eu velit. Donec mattis ligula at ante imperdiet ut - * dapibus mauris malesuada. Sed gravida nisi a metus elementum sit - * amet hendrerit dolor bibendum. Aenean sit amet neque massa, sed - * tempus tortor. Sed ut lobortis enim. Proin a mauris quis nunc - * fermentum ultrices eget a erat. Mauris in lectus vitae metus - * sodales auctor. Morbi nunc quam, ultricies at venenatis non, - * pellentesque ac dui. - * - * Quisque vitae est id eros placerat laoreet sit amet eu - * nisi. Curabitur suscipit neque porttitor est euismod - * lacinia. Curabitur non quam vitae ipsum adipiscing - * condimentum. Mauris ut ante eget metus sollicitudin - * blandit. Aliquam erat volutpat. Morbi sed nisl mauris. Nulla - * facilisi. Phasellus at mollis ipsum. Maecenas sed convallis - * sapien. Nullam in ligula turpis. Pellentesque a neque augue. Sed - * eget ante feugiat tortor congue auctor ac quis ante. Proin - * condimentum lacinia tincidunt. - */ -struct Bored { - bored: bool, -} - -impl Drop for Bored { - fn drop(&mut self) { } -} - -/** - * The Shunned House - * - * From even the greatest of horrors irony is seldom absent. Sometimes it - * enters directly into the composition of the events, while sometimes it - * relates only to their fortuitous position among persons and - * places. The latter sort is splendidly exemplified by a case in the - * ancient city of Providence, where in the late forties Edgar Allan Poe - * used to sojourn often during his unsuccessful wooing of the gifted - * poetess, Mrs. Whitman. Poe generally stopped at the Mansion House in - * Benefit Street--the renamed Golden Ball Inn whose roof has sheltered - * Washington, Jefferson, and Lafayette--and his favorite walk led - * northward along the same street to Mrs. Whitman's home and the - * neighboring hillside churchyard of St. John's, whose hidden expanse of - * Eighteenth Century gravestones had for him a peculiar fascination. - */ -trait TheShunnedHouse { - /** - * Now the irony is this. In this walk, so many times repeated, the - * world's greatest master of the terrible and the bizarre was - * obliged to pass a particular house on the eastern side of the - * street; a dingy, antiquated structure perched on the abruptly - * rising side hill, with a great unkempt yard dating from a time - * when the region was partly open country. It does not appear that - * he ever wrote or spoke of it, nor is there any evidence that he - * even noticed it. And yet that house, to the two persons in - * possession of certain information, equals or outranks in horror - * the wildest fantasy of the genius who so often passed it - * unknowingly, and stands starkly leering as a symbol of all that is - * unutterably hideous. - * - * # Arguments - * - * * unkempt_yard - A yard dating from a time when the region was partly - * open country - */ - fn dingy_house(&self, unkempt_yard: int); - - /** - * The house was--and for that matter still is--of a kind to attract - * the attention of the curious. Originally a farm or semi-farm - * building, it followed the average New England colonial lines of - * the middle Eighteenth Century--the prosperous peaked-roof sort, - * with two stories and dormerless attic, and with the Georgian - * doorway and interior panelling dictated by the progress of taste - * at that time. It faced south, with one gable end buried to the - * lower windows in the eastward rising hill, and the other exposed - * to the foundations toward the street. Its construction, over a - * century and a half ago, had followed the grading and straightening - * of the road in that especial vicinity; for Benefit Street--at - * first called Back Street--was laid out as a lane winding amongst - * the graveyards of the first settlers, and straightened only when - * the removal of the bodies to the North Burial Ground made it - * decently possible to cut through the old family plots. - */ - fn construct(&self) -> bool; -} - -/// Whatever -impl TheShunnedHouse for OmNomNomy { - fn dingy_house(&self, _unkempt_yard: int) { - } - - fn construct(&self) -> bool { - fail!(); - } -} diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs deleted file mode 100644 index 9f8041712ea..00000000000 --- a/src/librustdoc/desc_to_brief_pass.rs +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Pulls a brief description out of a long description. - -If the first paragraph of a long description is short enough then it -is interpreted as the brief description. -*/ - - -use astsrv; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -use std::util; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"desc_to_brief", - f: run - } -} - -pub fn run( - _srv: astsrv::Srv, - doc: doc::Doc -) -> doc::Doc { - let fold = Fold { - fold_item: fold_item, - fold_trait: fold_trait, - fold_impl: fold_impl, - .. fold::default_any_fold(()) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_item(fold: &fold::Fold<()>, doc: doc::ItemDoc) -> doc::ItemDoc { - let doc = fold::default_seq_fold_item(fold, doc); - - doc::ItemDoc { - brief: extract(doc.desc.clone()), - .. doc - } -} - -fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc { - let doc =fold::default_seq_fold_trait(fold, doc); - - doc::TraitDoc { - methods: doc.methods.map(|doc| doc::MethodDoc { - brief: extract(doc.desc.clone()), - .. (*doc).clone() - }), - .. doc - } -} - -fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc { - let doc =fold::default_seq_fold_impl(fold, doc); - - doc::ImplDoc { - methods: doc.methods.map(|doc| doc::MethodDoc { - brief: extract(doc.desc.clone()), - .. (*doc).clone() - }), - .. doc - } -} - -pub fn extract(desc: Option<~str>) -> Option<~str> { - if desc.is_none() { - return None - } - - parse_desc(desc.clone().unwrap()) -} - -fn parse_desc(desc: ~str) -> Option<~str> { - static MAX_BRIEF_LEN: uint = 120u; - - match first_sentence(desc.clone()) { - Some(first_sentence) => { - if first_sentence.len() <= MAX_BRIEF_LEN { - Some(first_sentence) - } else { - None - } - } - None => None - } -} - -fn first_sentence(s: ~str) -> Option<~str> { - let paras = paragraphs(s); - if !paras.is_empty() { - let first_para = paras.head(); - Some(first_sentence_(*first_para).replace("\n", " ")) - } else { - None - } -} - -fn first_sentence_(s: &str) -> ~str { - let mut dotcount = 0; - // The index of the character following a single dot. This allows - // Things like [0..1) to appear in the brief description - let idx = s.find(|ch: char| { - if ch == '.' { - dotcount += 1; - false - } else if dotcount == 1 { - true - } else { - dotcount = 0; - false - } - }); - match idx { - Some(idx) if idx > 2u => s.slice(0, idx - 1).to_owned(), - _ => { - if s.ends_with(".") { - s.to_owned() - } else { - s.to_owned() - } - } - } -} - -pub fn paragraphs(s: &str) -> ~[~str] { - let mut whitespace_lines = 0; - let mut accum = ~""; - let mut paras = do s.any_line_iter().fold(~[]) |paras, line| { - let mut res = paras; - - if line.is_whitespace() { - whitespace_lines += 1; - } else { - if whitespace_lines > 0 { - if !accum.is_empty() { - let v = util::replace(&mut accum, ~""); - res.push(v); - } - } - - whitespace_lines = 0; - - accum = if accum.is_empty() { - line.to_owned() - } else { - fmt!("%s\n%s", accum, line) - } - } - - res - }; - - if !accum.is_empty() { paras.push(accum); } - paras -} - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass; - use super::{extract, paragraphs, run}; - use doc; - use extract; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - run(srv.clone(), doc) - } - } - - #[test] - fn should_promote_desc() { - let doc = mk_doc(~"#[doc = \"desc\"] mod m { }"); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().mods()[1].brief(), Some(~"desc")); - } - - #[test] - fn should_promote_trait_method_desc() { - let doc = mk_doc(~"trait i { #[doc = \"desc\"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].brief == - Some(~"desc")); - } - - #[test] - fn should_promote_impl_method_desc() { - let doc = mk_doc( - ~"impl int { #[doc = \"desc\"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"desc")); - } - - #[test] - fn test_paragraphs_1() { - let paras = paragraphs("1\n\n2"); - assert_eq!(paras, ~[~"1", ~"2"]); - } - - #[test] - fn test_paragraphs_2() { - let paras = paragraphs("\n\n1\n1\n\n2\n\n"); - assert_eq!(paras, ~[~"1\n1", ~"2"]); - } - - #[test] - fn should_promote_short_descs() { - let desc = Some(~"desc"); - let brief = extract(desc.clone()); - assert_eq!(brief, desc); - } - - #[test] - fn should_not_promote_long_descs() { - let desc = Some(~"Warkworth Castle is a ruined medieval building -in the town of the same name in the English county of Northumberland, -and the town and castle occupy a loop of the River Coquet, less than a mile -from England's north-east coast. When the castle was founded is uncertain, -but traditionally its construction has been ascribed to Prince Henry of -Scotland in the mid 12th century, although it may have been built by -King Henry II of England when he took control of England'snorthern -counties."); - let brief = extract(desc); - assert_eq!(brief, None); - } - - #[test] - fn should_promote_first_sentence() { - let desc = Some(~"Warkworth Castle is a ruined medieval building -in the town. of the same name in the English county of Northumberland, -and the town and castle occupy a loop of the River Coquet, less than a mile -from England's north-east coast. When the castle was founded is uncertain, -but traditionally its construction has been ascribed to Prince Henry of -Scotland in the mid 12th century, although it may have been built by -King Henry II of England when he took control of England'snorthern -counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth Castle is a ruined medieval building in the town")); - } - - #[test] - fn should_not_consider_double_period_to_end_sentence() { - let desc = Some(~"Warkworth..Castle is a ruined medieval building -in the town. of the same name in the English county of Northumberland, -and the town and castle occupy a loop of the River Coquet, less than a mile -from England's north-east coast. When the castle was founded is uncertain, -but traditionally its construction has been ascribed to Prince Henry of -Scotland in the mid 12th century, although it may have been built by -King Henry II of England when he took control of England'snorthern -counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth..Castle is a ruined medieval building in the town")); - } - - #[test] - fn should_not_consider_triple_period_to_end_sentence() { - let desc = Some(~"Warkworth... Castle is a ruined medieval building -in the town. of the same name in the English county of Northumberland, -and the town and castle occupy a loop of the River Coquet, less than a mile -from England's north-east coast. When the castle was founded is uncertain, -but traditionally its construction has been ascribed to Prince Henry of -Scotland in the mid 12th century, although it may have been built by -King Henry II of England when he took control of England'snorthern -counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth... Castle is a ruined medieval building in the town")); - } -} diff --git a/src/librustdoc/doc.rs b/src/librustdoc/doc.rs deleted file mode 100644 index aba7ea1f0d7..00000000000 --- a/src/librustdoc/doc.rs +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The document model - - -use doc; - -pub type AstId = int; - -#[deriving(Clone, Eq)] -pub struct Doc { - pages: ~[Page] -} - -#[deriving(Clone, Eq)] -pub enum Page { - CratePage(CrateDoc), - ItemPage(ItemTag) -} - -#[deriving(Clone, Eq)] -pub enum Implementation { - Required, - Provided, -} - -/** - * Most rustdocs can be parsed into 'sections' according to their markdown - * headers - */ -#[deriving(Clone, Eq)] -pub struct Section { - header: ~str, - body: ~str -} - -// FIXME (#2596): We currently give topmod the name of the crate. There -// would probably be fewer special cases if the crate had its own name -// and topmod's name was the empty string. -#[deriving(Clone, Eq)] -pub struct CrateDoc { - topmod: ModDoc -} - -#[deriving(Clone, Eq)] -pub enum ItemTag { - ModTag(ModDoc), - NmodTag(NmodDoc), - StaticTag(StaticDoc), - FnTag(FnDoc), - EnumTag(EnumDoc), - TraitTag(TraitDoc), - ImplTag(ImplDoc), - TyTag(TyDoc), - StructTag(StructDoc) -} - -#[deriving(Clone, Eq)] -pub struct ItemDoc { - id: AstId, - name: ~str, - path: ~[~str], - brief: Option<~str>, - desc: Option<~str>, - sections: ~[Section], - // Indicates that this node is a reexport of a different item - reexport: bool -} - -#[deriving(Clone, Eq)] -pub struct SimpleItemDoc { - item: ItemDoc, - sig: Option<~str> -} - -#[deriving(Clone, Eq)] -pub struct ModDoc { - item: ItemDoc, - items: ~[ItemTag], - index: Option -} - -#[deriving(Clone, Eq)] -pub struct NmodDoc { - item: ItemDoc, - fns: ~[FnDoc], - index: Option -} - -pub type StaticDoc = SimpleItemDoc; - -pub type FnDoc = SimpleItemDoc; - -#[deriving(Clone, Eq)] -pub struct EnumDoc { - item: ItemDoc, - variants: ~[VariantDoc] -} - -#[deriving(Clone, Eq)] -pub struct VariantDoc { - name: ~str, - desc: Option<~str>, - sig: Option<~str> -} - -#[deriving(Clone, Eq)] -pub struct TraitDoc { - item: ItemDoc, - methods: ~[MethodDoc] -} - -#[deriving(Clone, Eq)] -pub struct MethodDoc { - name: ~str, - brief: Option<~str>, - desc: Option<~str>, - sections: ~[Section], - sig: Option<~str>, - implementation: Implementation, -} - -#[deriving(Clone, Eq)] -pub struct ImplDoc { - item: ItemDoc, - bounds_str: Option<~str>, - trait_types: ~[~str], - self_ty: Option<~str>, - methods: ~[MethodDoc] -} - -pub type TyDoc = SimpleItemDoc; - -#[deriving(Clone, Eq)] -pub struct StructDoc { - item: ItemDoc, - fields: ~[~str], - sig: Option<~str> -} - -#[deriving(Clone, Eq)] -pub struct Index { - entries: ~[IndexEntry] -} - -/** - * A single entry in an index - * - * Fields: - * - * * kind - The type of thing being indexed, e.g. 'Module' - * * name - The name of the thing - * * brief - The brief description - * * link - A format-specific string representing the link target - */ -#[deriving(Clone, Eq)] -pub struct IndexEntry { - kind: ~str, - name: ~str, - brief: Option<~str>, - link: ~str -} - -impl Doc { - pub fn CrateDoc(&self) -> CrateDoc { - self.pages.iter().fold(None, |_m, page| { - match (*page).clone() { - doc::CratePage(doc) => Some(doc), - _ => None - } - }).unwrap() - } - - pub fn cratemod(&self) -> ModDoc { - self.CrateDoc().topmod.clone() - } -} - -macro_rules! filt_mapper { - ($vec:expr, $pat:pat) => { - do ($vec).iter().filter_map |thing| { - match thing { - &$pat => Some((*x).clone()), - _ => None - } - }.collect() - } -} - -macro_rules! md { - ($id:ident) => { - filt_mapper!(self.items, $id(ref x)) - } -} -/// Some helper methods on ModDoc, mostly for testing -impl ModDoc { - pub fn mods(&self) -> ~[ModDoc] { - md!(ModTag) - } - - pub fn nmods(&self) -> ~[NmodDoc] { - md!(NmodTag) - } - - pub fn fns(&self) -> ~[FnDoc] { - md!(FnTag) - } - - pub fn statics(&self) -> ~[StaticDoc] { - md!(StaticTag) - } - - pub fn enums(&self) -> ~[EnumDoc] { - md!(EnumTag) - } - - pub fn traits(&self) -> ~[TraitDoc] { - md!(TraitTag) - } - - pub fn impls(&self) -> ~[ImplDoc] { - md!(ImplTag) - } - - pub fn types(&self) -> ~[TyDoc] { - md!(TyTag) - } - - pub fn structs(&self) -> ~[StructDoc] { - md!(StructTag) - } -} - -macro_rules! pu { - ($id:ident) => { - filt_mapper!(*self, ItemPage($id(ref x))) - } -} - -pub trait PageUtils { - fn mods(&self) -> ~[ModDoc]; - fn nmods(&self) -> ~[NmodDoc]; - fn fns(&self) -> ~[FnDoc]; - fn statics(&self) -> ~[StaticDoc]; - fn enums(&self) -> ~[EnumDoc]; - fn traits(&self) -> ~[TraitDoc]; - fn impls(&self) -> ~[ImplDoc]; - fn types(&self) -> ~[TyDoc]; -} - -impl PageUtils for ~[Page] { - - fn mods(&self) -> ~[ModDoc] { - pu!(ModTag) - } - - fn nmods(&self) -> ~[NmodDoc] { - pu!(NmodTag) - } - - fn fns(&self) -> ~[FnDoc] { - pu!(FnTag) - } - - fn statics(&self) -> ~[StaticDoc] { - pu!(StaticTag) - } - - fn enums(&self) -> ~[EnumDoc] { - pu!(EnumTag) - } - - fn traits(&self) -> ~[TraitDoc] { - pu!(TraitTag) - } - - fn impls(&self) -> ~[ImplDoc] { - pu!(ImplTag) - } - - fn types(&self) -> ~[TyDoc] { - pu!(TyTag) - } -} - -pub trait Item { - fn item(&self) -> ItemDoc; -} - -impl Item for ItemTag { - fn item(&self) -> ItemDoc { - match self { - &doc::ModTag(ref doc) => doc.item.clone(), - &doc::NmodTag(ref doc) => doc.item.clone(), - &doc::FnTag(ref doc) => doc.item.clone(), - &doc::StaticTag(ref doc) => doc.item.clone(), - &doc::EnumTag(ref doc) => doc.item.clone(), - &doc::TraitTag(ref doc) => doc.item.clone(), - &doc::ImplTag(ref doc) => doc.item.clone(), - &doc::TyTag(ref doc) => doc.item.clone(), - &doc::StructTag(ref doc) => doc.item.clone(), - } - } -} - -impl Item for SimpleItemDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for ModDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for NmodDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for EnumDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for TraitDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for ImplDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -impl Item for StructDoc { - fn item(&self) -> ItemDoc { - self.item.clone() - } -} - -pub trait ItemUtils { - fn id(&self) -> AstId; - /// FIXME #5898: This conflicts with - /// syntax::attr::AttrMetaMethods.name; This rustdoc seems to be on - /// the way out so I'm making this one look bad rather than the - /// new methods in attr. - fn name_(&self) -> ~str; - fn path(&self) -> ~[~str]; - fn brief(&self) -> Option<~str>; - fn desc(&self) -> Option<~str>; - fn sections(&self) -> ~[Section]; -} - -impl ItemUtils for A { - fn id(&self) -> AstId { - self.item().id - } - - fn name_(&self) -> ~str { - self.item().name.clone() - } - - fn path(&self) -> ~[~str] { - self.item().path.clone() - } - - fn brief(&self) -> Option<~str> { - self.item().brief.clone() - } - - fn desc(&self) -> Option<~str> { - self.item().desc.clone() - } - - fn sections(&self) -> ~[Section] { - self.item().sections.clone() - } -} diff --git a/src/rustdoc_ng/doctree.rs b/src/librustdoc/doctree.rs similarity index 100% rename from src/rustdoc_ng/doctree.rs rename to src/librustdoc/doctree.rs diff --git a/src/librustdoc/escape_pass.rs b/src/librustdoc/escape_pass.rs deleted file mode 100644 index 2f09e0a5ddc..00000000000 --- a/src/librustdoc/escape_pass.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Escapes text sequences - -use pass::Pass; -use text_pass; - -pub fn mk_pass() -> Pass { - text_pass::mk_pass(~"escape", escape) -} - -fn escape(s: &str) -> ~str { - s.replace("\\", "\\\\") -} - -#[test] -fn should_escape_backslashes() { - let s = ~"\\n"; - let r = escape(s); - assert_eq!(r, ~"\\\\n"); -} diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs deleted file mode 100644 index 2ab0530ccb3..00000000000 --- a/src/librustdoc/extract.rs +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Converts the Rust AST to the rustdoc document model - - -use astsrv; -use doc::ItemUtils; -use doc; - -use syntax::ast; -use syntax::parse::token::{ident_interner, ident_to_str}; -use syntax::parse::token; - -// Hack; rather than thread an interner through everywhere, rely on -// thread-local data -// Hack-Becomes-Feature: using thread-local-state everywhere... -pub fn to_str(id: ast::Ident) -> ~str { - /* bad */ ident_to_str(&id).to_owned() -} - -// get rid of this pointless function: -pub fn interner() -> @ident_interner { - return token::get_ident_interner(); -} - -pub fn from_srv( - srv: astsrv::Srv, - default_name: ~str -) -> doc::Doc { - - //! Use the AST service to create a document tree - - do astsrv::exec(srv) |ctxt| { - extract(ctxt.ast, default_name.clone()) - } -} - -pub fn extract( - crate: @ast::Crate, - default_name: ~str -) -> doc::Doc { - doc::Doc { - pages: ~[ - doc::CratePage(doc::CrateDoc { - topmod: top_moddoc_from_crate(crate, default_name), - }) - ] - } -} - -fn top_moddoc_from_crate( - crate: @ast::Crate, - default_name: ~str -) -> doc::ModDoc { - moddoc_from_mod(mk_itemdoc(ast::CRATE_NODE_ID, default_name), - crate.module.clone()) -} - -fn mk_itemdoc(id: ast::NodeId, name: ~str) -> doc::ItemDoc { - doc::ItemDoc { - id: id, - name: name, - path: ~[], - brief: None, - desc: None, - sections: ~[], - reexport: false - } -} - -fn moddoc_from_mod( - itemdoc: doc::ItemDoc, - module_: ast::_mod -) -> doc::ModDoc { - doc::ModDoc { - item: itemdoc, - items: do module_.items.iter().filter_map |item| { - let ItemDoc = mk_itemdoc(item.id, to_str(item.ident)); - match item.node.clone() { - ast::item_mod(m) => { - Some(doc::ModTag( - moddoc_from_mod(ItemDoc, m) - )) - } - ast::item_foreign_mod(nm) => { - Some(doc::NmodTag( - nmoddoc_from_mod(ItemDoc, nm) - )) - } - ast::item_fn(*) => { - Some(doc::FnTag( - fndoc_from_fn(ItemDoc) - )) - } - ast::item_static(*) => { - Some(doc::StaticTag( - staticdoc_from_static(ItemDoc) - )) - } - ast::item_enum(enum_definition, _) => { - Some(doc::EnumTag( - enumdoc_from_enum(ItemDoc, enum_definition.variants.clone()) - )) - } - ast::item_trait(_, _, methods) => { - Some(doc::TraitTag( - traitdoc_from_trait(ItemDoc, methods) - )) - } - ast::item_impl(_, _, _, methods) => { - Some(doc::ImplTag( - impldoc_from_impl(ItemDoc, methods) - )) - } - ast::item_ty(_, _) => { - Some(doc::TyTag( - tydoc_from_ty(ItemDoc) - )) - } - ast::item_struct(def, _) => { - Some(doc::StructTag( - structdoc_from_struct(ItemDoc, def) - )) - } - _ => None - } - }.collect(), - index: None - } -} - -fn nmoddoc_from_mod( - itemdoc: doc::ItemDoc, - module_: ast::foreign_mod -) -> doc::NmodDoc { - let mut fns = ~[]; - for item in module_.items.iter() { - let ItemDoc = mk_itemdoc(item.id, to_str(item.ident)); - match item.node { - ast::foreign_item_fn(*) => { - fns.push(fndoc_from_fn(ItemDoc)); - } - ast::foreign_item_static(*) => {} // XXX: Not implemented. - } - } - doc::NmodDoc { - item: itemdoc, - fns: fns, - index: None - } -} - -fn fndoc_from_fn(itemdoc: doc::ItemDoc) -> doc::FnDoc { - doc::SimpleItemDoc { - item: itemdoc, - sig: None - } -} - -fn staticdoc_from_static(itemdoc: doc::ItemDoc) -> doc::StaticDoc { - doc::SimpleItemDoc { - item: itemdoc, - sig: None - } -} - -fn enumdoc_from_enum( - itemdoc: doc::ItemDoc, - variants: ~[ast::variant] -) -> doc::EnumDoc { - doc::EnumDoc { - item: itemdoc, - variants: variantdocs_from_variants(variants) - } -} - -fn variantdocs_from_variants( - variants: ~[ast::variant] -) -> ~[doc::VariantDoc] { - variants.iter().map(variantdoc_from_variant).collect() -} - -fn variantdoc_from_variant(variant: &ast::variant) -> doc::VariantDoc { - doc::VariantDoc { - name: to_str(variant.node.name), - desc: None, - sig: None - } -} - -fn traitdoc_from_trait( - itemdoc: doc::ItemDoc, - methods: ~[ast::trait_method] -) -> doc::TraitDoc { - doc::TraitDoc { - item: itemdoc, - methods: do methods.iter().map |method| { - match (*method).clone() { - ast::required(ty_m) => { - doc::MethodDoc { - name: to_str(ty_m.ident), - brief: None, - desc: None, - sections: ~[], - sig: None, - implementation: doc::Required, - } - } - ast::provided(m) => { - doc::MethodDoc { - name: to_str(m.ident), - brief: None, - desc: None, - sections: ~[], - sig: None, - implementation: doc::Provided, - } - } - } - }.collect() - } -} - -fn impldoc_from_impl( - itemdoc: doc::ItemDoc, - methods: ~[@ast::method] -) -> doc::ImplDoc { - doc::ImplDoc { - item: itemdoc, - bounds_str: None, - trait_types: ~[], - self_ty: None, - methods: do methods.iter().map |method| { - doc::MethodDoc { - name: to_str(method.ident), - brief: None, - desc: None, - sections: ~[], - sig: None, - implementation: doc::Provided, - } - }.collect() - } -} - -fn tydoc_from_ty( - itemdoc: doc::ItemDoc -) -> doc::TyDoc { - doc::SimpleItemDoc { - item: itemdoc, - sig: None - } -} - -fn structdoc_from_struct( - itemdoc: doc::ItemDoc, - struct_def: @ast::struct_def -) -> doc::StructDoc { - doc::StructDoc { - item: itemdoc, - fields: do struct_def.fields.map |field| { - match field.node.kind { - ast::named_field(ident, _) => to_str(ident), - ast::unnamed_field => ~"(unnamed)", - } - }, - sig: None - } -} - -#[cfg(test)] -mod test { - use astsrv; - use doc; - use extract::{extract, from_srv}; - use parse; - - fn mk_doc(source: @str) -> doc::Doc { - let ast = parse::from_str(source); - debug!("ast=%?", ast); - extract(ast, ~"") - } - - #[test] - fn extract_empty_crate() { - let doc = mk_doc(@""); - assert!(doc.cratemod().mods().is_empty()); - assert!(doc.cratemod().fns().is_empty()); - } - - #[test] - fn extract_mods() { - let doc = mk_doc(@"mod a { mod b { } mod c { } }"); - assert!(doc.cratemod().mods()[0].name_() == ~"a"); - assert!(doc.cratemod().mods()[0].mods()[0].name_() == ~"b"); - assert!(doc.cratemod().mods()[0].mods()[1].name_() == ~"c"); - } - - #[test] - fn extract_fns_from_foreign_mods() { - let doc = mk_doc(@"extern { fn a(); }"); - assert!(doc.cratemod().nmods()[0].fns[0].name_() == ~"a"); - } - - #[test] - fn extract_mods_deep() { - let doc = mk_doc(@"mod a { mod b { mod c { } } }"); - assert!(doc.cratemod().mods()[0].mods()[0].mods()[0].name_() == - ~"c"); - } - - #[test] - fn extract_should_set_mod_ast_id() { - let doc = mk_doc(@"mod a { }"); - assert!(doc.cratemod().mods()[0].id() != 0); - } - - #[test] - fn extract_fns() { - let doc = mk_doc( - @"fn a() { } \ - mod b { fn c() { - } }"); - assert!(doc.cratemod().fns()[0].name_() == ~"a"); - assert!(doc.cratemod().mods()[0].fns()[0].name_() == ~"c"); - } - - #[test] - fn extract_should_set_fn_ast_id() { - let doc = mk_doc(@"fn a() { }"); - assert!(doc.cratemod().fns()[0].id() != 0); - } - - #[test] - fn extract_should_use_default_crate_name() { - let source = @""; - let ast = parse::from_str(source); - let doc = extract(ast, ~"burp"); - assert!(doc.cratemod().name_() == ~"burp"); - } - - #[test] - fn extract_from_seq_srv() { - let source = ~""; - do astsrv::from_str(source) |srv| { - let doc = from_srv(srv, ~"name"); - assert!(doc.cratemod().name_() == ~"name"); - } - } - - #[test] - fn should_extract_static_name_and_id() { - let doc = mk_doc(@"static a: int = 0;"); - assert!(doc.cratemod().statics()[0].id() != 0); - assert!(doc.cratemod().statics()[0].name_() == ~"a"); - } - - #[test] - fn should_extract_enums() { - let doc = mk_doc(@"enum e { v }"); - assert!(doc.cratemod().enums()[0].id() != 0); - assert!(doc.cratemod().enums()[0].name_() == ~"e"); - } - - #[test] - fn should_extract_enum_variants() { - let doc = mk_doc(@"enum e { v }"); - assert!(doc.cratemod().enums()[0].variants[0].name == ~"v"); - } - - #[test] - fn should_extract_traits() { - let doc = mk_doc(@"trait i { fn f(); }"); - assert!(doc.cratemod().traits()[0].name_() == ~"i"); - } - - #[test] - fn should_extract_trait_methods() { - let doc = mk_doc(@"trait i { fn f(); }"); - assert!(doc.cratemod().traits()[0].methods[0].name == ~"f"); - } - - #[test] - fn should_extract_impl_methods() { - let doc = mk_doc(@"impl int { fn f() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].name == ~"f"); - } - - #[test] - fn should_extract_tys() { - let doc = mk_doc(@"type a = int;"); - assert!(doc.cratemod().types()[0].name_() == ~"a"); - } - - #[test] - fn should_extract_structs() { - let doc = mk_doc(@"struct Foo { field: () }"); - assert!(doc.cratemod().structs()[0].name_() == ~"Foo"); - } - - #[test] - fn should_extract_struct_fields() { - let doc = mk_doc(@"struct Foo { field: () }"); - assert!(doc.cratemod().structs()[0].fields[0] == ~"field"); - } -} diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 3e74916228f..ae74f4e37c3 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,397 +8,92 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std; +use clean::*; +use std::iter::Extendable; -use doc; -#[cfg(test)] use extract; -#[cfg(test)] use parse; +pub trait DocFolder { + fn fold_item(&mut self, item: Item) -> Option { + self.fold_item_recur(item) + } -pub struct Fold { - ctxt: T, - fold_doc: FoldDoc, - fold_crate: FoldCrate, - fold_item: FoldItem, - fold_mod: FoldMod, - fold_nmod: FoldNmod, - fold_fn: FoldFn, - fold_static: FoldStatic, - fold_enum: FoldEnum, - fold_trait: FoldTrait, - fold_impl: FoldImpl, - fold_type: FoldType, - fold_struct: FoldStruct -} + /// don't override! + fn fold_item_recur(&mut self, item: Item) -> Option { + 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(this: &mut T, trm: TraitMethod) -> Option { + 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 + }; -impl Clone for Fold { - fn clone(&self) -> Fold { - Fold { - ctxt: self.ctxt.clone(), - fold_doc: self.fold_doc, - fold_crate: self.fold_crate, - fold_item: self.fold_item, - fold_mod: self.fold_mod, - fold_nmod: self.fold_nmod, - fold_fn: self.fold_fn, - fold_static: self.fold_static, - fold_enum: self.fold_enum, - fold_trait: self.fold_trait, - fold_impl: self.fold_impl, - fold_type: self.fold_type, - fold_struct: self.fold_struct - } + 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 { + c.module = match std::util::replace(&mut c.module, None) { + Some(module) => self.fold_item(module), None => None + }; + return c; } } - -type FoldDoc = @fn(fold: &Fold, doc: doc::Doc) -> doc::Doc; -type FoldCrate = @fn(fold: &Fold, doc: doc::CrateDoc) -> doc::CrateDoc; -type FoldItem = @fn(fold: &Fold, doc: doc::ItemDoc) -> doc::ItemDoc; -type FoldMod = @fn(fold: &Fold, doc: doc::ModDoc) -> doc::ModDoc; -type FoldNmod = @fn(fold: &Fold, doc: doc::NmodDoc) -> doc::NmodDoc; -type FoldFn = @fn(fold: &Fold, doc: doc::FnDoc) -> doc::FnDoc; -type FoldStatic = @fn(fold: &Fold, doc: doc::StaticDoc) -> doc::StaticDoc; -type FoldEnum = @fn(fold: &Fold, doc: doc::EnumDoc) -> doc::EnumDoc; -type FoldTrait = @fn(fold: &Fold, doc: doc::TraitDoc) -> doc::TraitDoc; -type FoldImpl = @fn(fold: &Fold, doc: doc::ImplDoc) -> doc::ImplDoc; -type FoldType = @fn(fold: &Fold, doc: doc::TyDoc) -> doc::TyDoc; -type FoldStruct = @fn(fold: &Fold, - doc: doc::StructDoc) -> doc::StructDoc; - -// This exists because fn types don't infer correctly as record -// initializers, but they do as function arguments -fn mk_fold( - ctxt: T, - fold_doc: FoldDoc, - fold_crate: FoldCrate, - fold_item: FoldItem, - fold_mod: FoldMod, - fold_nmod: FoldNmod, - fold_fn: FoldFn, - fold_static: FoldStatic, - fold_enum: FoldEnum, - fold_trait: FoldTrait, - fold_impl: FoldImpl, - fold_type: FoldType, - fold_struct: FoldStruct -) -> Fold { - Fold { - ctxt: ctxt, - fold_doc: fold_doc, - fold_crate: fold_crate, - fold_item: fold_item, - fold_mod: fold_mod, - fold_nmod: fold_nmod, - fold_fn: fold_fn, - fold_static: fold_static, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - fold_type: fold_type, - fold_struct: fold_struct - } -} - -pub fn default_any_fold(ctxt: T) -> Fold { - mk_fold( - ctxt, - |f, d| default_seq_fold_doc(f, d), - |f, d| default_seq_fold_crate(f, d), - |f, d| default_seq_fold_item(f, d), - |f, d| default_any_fold_mod(f, d), - |f, d| default_any_fold_nmod(f, d), - |f, d| default_seq_fold_fn(f, d), - |f, d| default_seq_fold_static(f, d), - |f, d| default_seq_fold_enum(f, d), - |f, d| default_seq_fold_trait(f, d), - |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d), - |f, d| default_seq_fold_struct(f, d) - ) -} - -pub fn default_seq_fold(ctxt: T) -> Fold { - mk_fold( - ctxt, - |f, d| default_seq_fold_doc(f, d), - |f, d| default_seq_fold_crate(f, d), - |f, d| default_seq_fold_item(f, d), - |f, d| default_seq_fold_mod(f, d), - |f, d| default_seq_fold_nmod(f, d), - |f, d| default_seq_fold_fn(f, d), - |f, d| default_seq_fold_static(f, d), - |f, d| default_seq_fold_enum(f, d), - |f, d| default_seq_fold_trait(f, d), - |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d), - |f, d| default_seq_fold_struct(f, d) - ) -} - -pub fn default_par_fold(ctxt: T) -> Fold { - mk_fold( - ctxt, - |f, d| default_seq_fold_doc(f, d), - |f, d| default_seq_fold_crate(f, d), - |f, d| default_seq_fold_item(f, d), - |f, d| default_par_fold_mod(f, d), - |f, d| default_par_fold_nmod(f, d), - |f, d| default_seq_fold_fn(f, d), - |f, d| default_seq_fold_static(f, d), - |f, d| default_seq_fold_enum(f, d), - |f, d| default_seq_fold_trait(f, d), - |f, d| default_seq_fold_impl(f, d), - |f, d| default_seq_fold_type(f, d), - |f, d| default_seq_fold_struct(f, d) - ) -} - -pub fn default_seq_fold_doc(fold: &Fold, doc: doc::Doc) -> doc::Doc { - doc::Doc { - pages: do doc.pages.iter().map |page| { - match (*page).clone() { - doc::CratePage(doc) => { - doc::CratePage((fold.fold_crate)(fold, doc)) - } - doc::ItemPage(doc) => { - doc::ItemPage(fold_ItemTag(fold, doc)) - } - } - }.collect(), - .. doc - } -} - -pub fn default_seq_fold_crate( - fold: &Fold, - doc: doc::CrateDoc -) -> doc::CrateDoc { - doc::CrateDoc { - topmod: (fold.fold_mod)(fold, doc.topmod.clone()) - } -} - -pub fn default_seq_fold_item( - _fold: &Fold, - doc: doc::ItemDoc -) -> doc::ItemDoc { - doc -} - -pub fn default_any_fold_mod( - fold: &Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - doc::ModDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - items: doc.items.iter().map(|ItemTag| { - fold_ItemTag(fold, (*ItemTag).clone()) - }).collect(), - .. doc - } -} - -pub fn default_seq_fold_mod( - fold: &Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - doc::ModDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - items: doc.items.iter().map(|ItemTag| { - fold_ItemTag(fold, (*ItemTag).clone()) - }).collect(), - .. doc - } -} - -pub fn default_par_fold_mod( - fold: &Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - doc::ModDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - items: doc.items.iter().map(|ItemTag| { - fold_ItemTag(fold, (*ItemTag).clone()) - }).collect(), - .. doc - } -} - -pub fn default_any_fold_nmod( - fold: &Fold, - doc: doc::NmodDoc -) -> doc::NmodDoc { - doc::NmodDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - fns: doc.fns.iter().map(|FnDoc| { - (fold.fold_fn)(fold, (*FnDoc).clone()) - }).collect(), - .. doc - } -} - -pub fn default_seq_fold_nmod( - fold: &Fold, - doc: doc::NmodDoc -) -> doc::NmodDoc { - doc::NmodDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - fns: doc.fns.iter().map(|FnDoc| { - (fold.fold_fn)(fold, (*FnDoc).clone()) - }).collect(), - .. doc - } -} - -pub fn default_par_fold_nmod( - fold: &Fold, - doc: doc::NmodDoc -) -> doc::NmodDoc { - doc::NmodDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - fns: doc.fns.iter().map(|FnDoc| { - (fold.fold_fn)(fold, (*FnDoc).clone()) - }).collect(), - .. doc - } -} - -pub fn fold_ItemTag(fold: &Fold, doc: doc::ItemTag) -> doc::ItemTag { - match doc { - doc::ModTag(ModDoc) => { - doc::ModTag((fold.fold_mod)(fold, ModDoc)) - } - doc::NmodTag(nModDoc) => { - doc::NmodTag((fold.fold_nmod)(fold, nModDoc)) - } - doc::FnTag(FnDoc) => { - doc::FnTag((fold.fold_fn)(fold, FnDoc)) - } - doc::StaticTag(StaticDoc) => { - doc::StaticTag((fold.fold_static)(fold, StaticDoc)) - } - doc::EnumTag(EnumDoc) => { - doc::EnumTag((fold.fold_enum)(fold, EnumDoc)) - } - doc::TraitTag(TraitDoc) => { - doc::TraitTag((fold.fold_trait)(fold, TraitDoc)) - } - doc::ImplTag(ImplDoc) => { - doc::ImplTag((fold.fold_impl)(fold, ImplDoc)) - } - doc::TyTag(TyDoc) => { - doc::TyTag((fold.fold_type)(fold, TyDoc)) - } - doc::StructTag(StructDoc) => { - doc::StructTag((fold.fold_struct)(fold, StructDoc)) - } - } -} - -pub fn default_seq_fold_fn( - fold: &Fold, - doc: doc::FnDoc -) -> doc::FnDoc { - doc::SimpleItemDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_static( - fold: &Fold, - doc: doc::StaticDoc -) -> doc::StaticDoc { - doc::SimpleItemDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_enum( - fold: &Fold, - doc: doc::EnumDoc -) -> doc::EnumDoc { - doc::EnumDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_trait( - fold: &Fold, - doc: doc::TraitDoc -) -> doc::TraitDoc { - doc::TraitDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_impl( - fold: &Fold, - doc: doc::ImplDoc -) -> doc::ImplDoc { - doc::ImplDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_type( - fold: &Fold, - doc: doc::TyDoc -) -> doc::TyDoc { - doc::SimpleItemDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -pub fn default_seq_fold_struct( - fold: &Fold, - doc: doc::StructDoc -) -> doc::StructDoc { - doc::StructDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -#[test] -fn default_fold_should_produce_same_doc() { - let source = @"mod a { fn b() { } mod c { fn d() { } } }"; - let ast = parse::from_str(source); - let doc = extract::extract(ast, ~""); - let fld = default_seq_fold(()); - let folded = (fld.fold_doc)(&fld, doc.clone()); - assert_eq!(doc, folded); -} - -#[test] -fn default_fold_should_produce_same_statics() { - let source = @"static a: int = 0;"; - let ast = parse::from_str(source); - let doc = extract::extract(ast, ~""); - let fld = default_seq_fold(()); - let folded = (fld.fold_doc)(&fld, doc.clone()); - assert_eq!(doc, folded); -} - -#[test] -fn default_fold_should_produce_same_enums() { - let source = @"enum a { b }"; - let ast = parse::from_str(source); - let doc = extract::extract(ast, ~""); - let fld = default_seq_fold(()); - let folded = (fld.fold_doc)(&fld, doc.clone()); - assert_eq!(doc, folded); -} - -#[test] -fn default_parallel_fold_should_produce_same_doc() { - let source = @"mod a { fn b() { } mod c { fn d() { } } }"; - let ast = parse::from_str(source); - let doc = extract::extract(ast, ~""); - let fld = default_par_fold(()); - let folded = (fld.fold_doc)(&fld, doc.clone()); - assert_eq!(doc, folded); -} diff --git a/src/rustdoc_ng/html/format.rs b/src/librustdoc/html/format.rs similarity index 100% rename from src/rustdoc_ng/html/format.rs rename to src/librustdoc/html/format.rs diff --git a/src/rustdoc_ng/html/layout.rs b/src/librustdoc/html/layout.rs similarity index 100% rename from src/rustdoc_ng/html/layout.rs rename to src/librustdoc/html/layout.rs diff --git a/src/rustdoc_ng/html/markdown.rs b/src/librustdoc/html/markdown.rs similarity index 100% rename from src/rustdoc_ng/html/markdown.rs rename to src/librustdoc/html/markdown.rs diff --git a/src/rustdoc_ng/html/render.rs b/src/librustdoc/html/render.rs similarity index 100% rename from src/rustdoc_ng/html/render.rs rename to src/librustdoc/html/render.rs diff --git a/src/rustdoc_ng/html/static/jquery-2.0.3.min.js b/src/librustdoc/html/static/jquery-2.0.3.min.js similarity index 100% rename from src/rustdoc_ng/html/static/jquery-2.0.3.min.js rename to src/librustdoc/html/static/jquery-2.0.3.min.js diff --git a/src/rustdoc_ng/html/static/main.css b/src/librustdoc/html/static/main.css similarity index 100% rename from src/rustdoc_ng/html/static/main.css rename to src/librustdoc/html/static/main.css diff --git a/src/rustdoc_ng/html/static/main.js b/src/librustdoc/html/static/main.js similarity index 100% rename from src/rustdoc_ng/html/static/main.js rename to src/librustdoc/html/static/main.js diff --git a/src/rustdoc_ng/html/static/normalize.css b/src/librustdoc/html/static/normalize.css similarity index 100% rename from src/rustdoc_ng/html/static/normalize.css rename to src/librustdoc/html/static/normalize.css diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs deleted file mode 100644 index 90634770a50..00000000000 --- a/src/librustdoc/markdown_index_pass.rs +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Build indexes as appropriate for the markdown pass - - -use astsrv; -use config; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use markdown_pass; -use markdown_writer; -use pass::Pass; - -pub fn mk_pass(config: config::Config) -> Pass { - Pass { - name: ~"markdown_index", - f: |srv, doc| run(srv, doc, config.clone()) - } -} - -pub fn run( - _srv: astsrv::Srv, - doc: doc::Doc, - config: config::Config -) -> doc::Doc { - let fold = Fold { - fold_mod: fold_mod, - fold_nmod: fold_nmod, - .. fold::default_any_fold(config) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_mod( - fold: &fold::Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - - let doc = fold::default_any_fold_mod(fold, doc); - - doc::ModDoc { - index: Some(build_mod_index(doc.clone(), fold.ctxt.clone())), - .. doc - } -} - -fn fold_nmod( - fold: &fold::Fold, - doc: doc::NmodDoc -) -> doc::NmodDoc { - - let doc = fold::default_any_fold_nmod(fold, doc); - - doc::NmodDoc { - index: Some(build_nmod_index(doc.clone(), fold.ctxt.clone())), - .. doc - } -} - -fn build_mod_index( - doc: doc::ModDoc, - config: config::Config -) -> doc::Index { - doc::Index { - entries: doc.items.map(|doc| { - item_to_entry((*doc).clone(), &config) - }) - } -} - -fn build_nmod_index( - doc: doc::NmodDoc, - config: config::Config -) -> doc::Index { - doc::Index { - entries: doc.fns.map(|doc| { - item_to_entry(doc::FnTag((*doc).clone()), &config) - }) - } -} - -fn item_to_entry( - doc: doc::ItemTag, - config: &config::Config -) -> doc::IndexEntry { - let link = match doc { - doc::ModTag(_) | doc::NmodTag(_) - if config.output_style == config::DocPerMod => { - markdown_writer::make_filename(config, - doc::ItemPage(doc.clone())).to_str() - } - _ => { - ~"#" + pandoc_header_id(markdown_pass::header_text(doc.clone())) - } - }; - - doc::IndexEntry { - kind: markdown_pass::header_kind(doc.clone()), - name: markdown_pass::header_name(doc.clone()), - brief: doc.brief(), - link: link - } -} - -pub fn pandoc_header_id(header: &str) -> ~str { - - // http://johnmacfarlane.net/pandoc/README.html#headers - - let header = remove_formatting(header); - let header = remove_punctuation(header); - let header = replace_with_hyphens(header); - let header = convert_to_lowercase(header); - let header = remove_up_to_first_letter(header); - let header = maybe_use_section_id(header); - return header; - - fn remove_formatting(s: &str) -> ~str { - s.replace("`", "") - } - fn remove_punctuation(s: &str) -> ~str { - let s = s.replace("<", ""); - let s = s.replace(">", ""); - let s = s.replace("[", ""); - let s = s.replace("]", ""); - let s = s.replace("(", ""); - let s = s.replace(")", ""); - let s = s.replace("@~", ""); - let s = s.replace("~", ""); - let s = s.replace("/", ""); - let s = s.replace(":", ""); - let s = s.replace("&", ""); - let s = s.replace("^", ""); - let s = s.replace(",", ""); - let s = s.replace("'", ""); - let s = s.replace("+", ""); - return s; - } - fn replace_with_hyphens(s: &str) -> ~str { - // Collapse sequences of whitespace to a single dash - // XXX: Hacky implementation here that only covers - // one or two spaces. - let s = s.trim(); - let s = s.replace(" ", "-"); - let s = s.replace(" ", "-"); - return s; - } - // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use - // to_ascii_consume and to_str_consume to not do a unnecessary copy. - fn convert_to_lowercase(s: &str) -> ~str { s.to_ascii().to_lower().to_str_ascii() } - fn remove_up_to_first_letter(s: &str) -> ~str { s.to_str() } - fn maybe_use_section_id(s: &str) -> ~str { s.to_str() } -} - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass; - use config; - use desc_to_brief_pass; - use doc; - use extract; - use markdown_index_pass::run; - use path_pass; - use prune_hidden_pass; - use super::pandoc_header_id; - - fn mk_doc(output_style: config::OutputStyle, source: ~str) - -> doc::Doc { - do astsrv::from_str(source) |srv| { - let config = config::Config { - output_style: output_style, - .. config::default_config(&Path("whatever")) - }; - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc); - let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); - let doc = (path_pass::mk_pass().f)(srv.clone(), doc); - - run(srv.clone(), doc, config) - } - } - - #[test] - fn should_remove_punctuation_from_headers() { - assert!(pandoc_header_id("impl foo of bar") == - ~"impl-foo-of-bara"); - assert!(pandoc_header_id("impl of num::num for int") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id("impl of num::num for int/&") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id("impl of num::num for ^int") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id("impl for & condvar") - == ~"impl-for-condvar"); - assert!(pandoc_header_id("impl of Select for (Left, Right)") - == ~"impl-of-selectt-u-for-left-right"); - assert!(pandoc_header_id("impl of Condition<'self, T, U>") - == ~"impl-of-conditionself-t-u"); - assert!(pandoc_header_id("impl of Condition") - == ~"impl-of-conditiont-clone"); - } - - #[test] - fn should_trim_whitespace_after_removing_punctuation() { - assert_eq!(pandoc_header_id("impl foo for ()"), ~"impl-foo-for"); - } - - #[test] - fn should_index_mod_contents() { - let doc = mk_doc( - config::DocPerCrate, - ~"mod a { } fn b() { }" - ); - assert!(doc.cratemod().index.unwrap().entries[0] == doc::IndexEntry { - kind: ~"Module", - name: ~"a", - brief: None, - link: ~"#module-a" - }); - assert!(doc.cratemod().index.unwrap().entries[1] == doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); - } - - #[test] - fn should_index_mod_contents_multi_page() { - let doc = mk_doc( - config::DocPerMod, - ~"mod a { } fn b() { }" - ); - assert_eq!(doc.cratemod().index.unwrap().entries[0], doc::IndexEntry { - kind: ~"Module", - name: ~"a", - brief: None, - link: ~"a.html" - }); - assert_eq!(doc.cratemod().index.unwrap().entries[1], doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); - } - - #[test] - fn should_add_brief_desc_to_index() { - let doc = mk_doc( - config::DocPerMod, - ~"#[doc = \"test\"] mod a { }" - ); - assert_eq!(doc.cratemod().index.unwrap().entries[0].brief, Some(~"test")); - } - - #[test] - fn should_index_foreign_mod_contents() { - let doc = mk_doc( - config::DocPerCrate, - ~"extern { fn b(); }" - ); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().nmods()[0].index.unwrap().entries[0], - doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); - } -} diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs deleted file mode 100644 index 7d07b4864f5..00000000000 --- a/src/librustdoc/markdown_pass.rs +++ /dev/null @@ -1,941 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Generate markdown from a document tree - - -use astsrv; -use doc::ItemUtils; -use doc; -use markdown_pass; -use markdown_writer::Writer; -use markdown_writer::WriterUtils; -use markdown_writer::WriterFactory; -use pass::Pass; -use sort_pass; - -use std::cell::Cell; -use std::str; -use std::vec; -use syntax; - -pub fn mk_pass(writer_factory: WriterFactory) -> Pass { - let writer_factory = Cell::new(writer_factory); - Pass { - name: ~"markdown", - f: |srv, doc| run(srv, doc, writer_factory.take()) - } -} - -fn run( - srv: astsrv::Srv, - doc: doc::Doc, - writer_factory: WriterFactory -) -> doc::Doc { - - fn mods_last(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { - fn is_mod(item: &doc::ItemTag) -> bool { - match *item { - doc::ModTag(_) => true, - _ => false - } - } - - let lteq = !is_mod(item1) || is_mod(item2); - lteq - } - - // Sort the items so mods come last. All mods will be - // output at the same header level so sorting mods last - // makes the headers come out nested correctly. - let sorted_doc = (sort_pass::mk_pass( - ~"mods last", mods_last - ).f)(srv, doc.clone()); - - write_markdown(sorted_doc, writer_factory); - - return doc; -} - -struct Ctxt { - w: Writer -} - -pub fn write_markdown( - doc: doc::Doc, - writer_factory: WriterFactory -) { - // There is easy parallelism to be had here, but - // we don't want to spawn too many pandoc processes. - // (See #2484, which is closed.) - do doc.pages.map |page| { - let ctxt = Ctxt { - w: writer_factory((*page).clone()) - }; - write_page(&ctxt, page) - }; -} - -fn write_page(ctxt: &Ctxt, page: &doc::Page) { - write_title(ctxt, (*page).clone()); - match (*page).clone() { - doc::CratePage(doc) => { - write_crate(ctxt, doc); - } - doc::ItemPage(doc) => { - // We don't write a header for item's pages because their - // header in the html output is created by the page title - write_item_no_header(ctxt, doc); - } - } - ctxt.w.put_done(); -} - -fn write_title(ctxt: &Ctxt, page: doc::Page) { - ctxt.w.put_line(fmt!("%% %s", make_title(page))); - ctxt.w.put_line(~""); -} - -fn make_title(page: doc::Page) -> ~str { - let item = match page { - doc::CratePage(CrateDoc) => { - doc::ModTag(CrateDoc.topmod.clone()) - } - doc::ItemPage(ItemTag) => { - ItemTag - } - }; - let title = markdown_pass::header_text(item); - let title = title.replace("`", ""); - return title; -} - -enum Hlvl { - H1 = 1, - H2 = 2, - H3 = 3, - H4 = 4 -} - -fn write_header(ctxt: &Ctxt, lvl: Hlvl, doc: doc::ItemTag) { - let text = header_text(doc); - write_header_(ctxt, lvl, text); -} - -fn write_header_(ctxt: &Ctxt, lvl: Hlvl, title: ~str) { - let hashes = str::from_chars(vec::from_elem(lvl as uint, '#')); - ctxt.w.put_line(fmt!("%s %s", hashes, title)); - ctxt.w.put_line(~""); -} - -pub fn header_kind(doc: doc::ItemTag) -> ~str { - match doc { - doc::ModTag(_) => { - if doc.id() == syntax::ast::CRATE_NODE_ID { - ~"Crate" - } else { - ~"Module" - } - } - doc::NmodTag(_) => { - ~"Foreign module" - } - doc::FnTag(_) => { - ~"Function" - } - doc::StaticTag(_) => { - ~"Static" - } - doc::EnumTag(_) => { - ~"Enum" - } - doc::TraitTag(_) => { - ~"Trait" - } - doc::ImplTag(_) => { - ~"Implementation" - } - doc::TyTag(_) => { - ~"Type" - } - doc::StructTag(_) => { - ~"Struct" - } - } -} - -pub fn header_name(doc: doc::ItemTag) -> ~str { - let fullpath = (doc.path() + &[doc.name_()]).connect("::"); - match &doc { - &doc::ModTag(_) if doc.id() != syntax::ast::CRATE_NODE_ID => { - fullpath - } - &doc::NmodTag(_) => { - fullpath - } - &doc::ImplTag(ref doc) => { - assert!(doc.self_ty.is_some()); - let bounds = if doc.bounds_str.is_some() { - fmt!(" where %s", *doc.bounds_str.get_ref()) - } else { - ~"" - }; - let self_ty = doc.self_ty.get_ref(); - let mut trait_part = ~""; - for (i, trait_type) in doc.trait_types.iter().enumerate() { - if i == 0 { - trait_part.push_str(" of "); - } else { - trait_part.push_str(", "); - } - trait_part.push_str(*trait_type); - } - fmt!("%s for %s%s", trait_part, *self_ty, bounds) - } - _ => { - doc.name_() - } - } -} - -pub fn header_text(doc: doc::ItemTag) -> ~str { - match &doc { - &doc::ImplTag(ref ImplDoc) => { - let header_kind = header_kind(doc.clone()); - let bounds = if ImplDoc.bounds_str.is_some() { - fmt!(" where `%s`", *ImplDoc.bounds_str.get_ref()) - } else { - ~"" - }; - let desc = if ImplDoc.trait_types.is_empty() { - fmt!("for `%s`%s", *ImplDoc.self_ty.get_ref(), bounds) - } else { - fmt!("of `%s` for `%s`%s", - ImplDoc.trait_types[0], - *ImplDoc.self_ty.get_ref(), - bounds) - }; - return fmt!("%s %s", header_kind, desc); - } - _ => {} - } - - header_text_(header_kind(doc.clone()), - header_name(doc)) -} - -fn header_text_(kind: &str, name: &str) -> ~str { - fmt!("%s `%s`", kind, name) -} - -fn write_crate( - ctxt: &Ctxt, - doc: doc::CrateDoc -) { - write_top_module(ctxt, doc.topmod.clone()); -} - -fn write_top_module( - ctxt: &Ctxt, - ModDoc: doc::ModDoc -) { - write_mod_contents(ctxt, ModDoc); -} - -fn write_mod( - ctxt: &Ctxt, - ModDoc: doc::ModDoc -) { - write_mod_contents(ctxt, ModDoc); -} - -fn write_common( - ctxt: &Ctxt, - desc: Option<~str>, - sections: &[doc::Section] -) { - write_desc(ctxt, desc); - write_sections(ctxt, sections); -} - -fn write_desc( - ctxt: &Ctxt, - desc: Option<~str> -) { - match desc { - Some(desc) => { - ctxt.w.put_line(desc); - ctxt.w.put_line(~""); - } - None => () - } -} - -fn write_sections(ctxt: &Ctxt, sections: &[doc::Section]) { - for section in sections.iter() { - write_section(ctxt, (*section).clone()); - } -} - -fn write_section(ctxt: &Ctxt, section: doc::Section) { - write_header_(ctxt, H4, section.header.clone()); - ctxt.w.put_line(section.body.clone()); - ctxt.w.put_line(~""); -} - -fn write_mod_contents( - ctxt: &Ctxt, - doc: doc::ModDoc -) { - write_common(ctxt, doc.desc(), doc.sections()); - if doc.index.is_some() { - write_index(ctxt, doc.index.get_ref()); - } - - for itemTag in doc.items.iter() { - write_item(ctxt, (*itemTag).clone()); - } -} - -fn write_item(ctxt: &Ctxt, doc: doc::ItemTag) { - write_item_(ctxt, doc, true); -} - -fn write_item_no_header(ctxt: &Ctxt, doc: doc::ItemTag) { - write_item_(ctxt, doc, false); -} - -fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) { - if write_header { - write_item_header(ctxt, doc.clone()); - } - - match doc { - doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc), - doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc), - doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc), - doc::StaticTag(StaticDoc) => write_static(ctxt, StaticDoc), - doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc), - doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc), - doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc), - doc::TyTag(TyDoc) => write_type(ctxt, TyDoc), - doc::StructTag(StructDoc) => put_struct(ctxt, StructDoc), - } -} - -fn write_item_header(ctxt: &Ctxt, doc: doc::ItemTag) { - write_header(ctxt, item_header_lvl(&doc), doc); -} - -fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl { - match doc { - &doc::ModTag(_) | &doc::NmodTag(_) => H1, - _ => H2 - } -} - -fn write_index(ctxt: &Ctxt, index: &doc::Index) { - if index.entries.is_empty() { - return; - } - - ctxt.w.put_line(~"
"); - ctxt.w.put_line(~""); - - for entry in index.entries.iter() { - let header = header_text_(entry.kind, entry.name); - let id = entry.link.clone(); - if entry.brief.is_some() { - ctxt.w.put_line(fmt!("* [%s](%s) - %s", - header, id, *entry.brief.get_ref())); - } else { - ctxt.w.put_line(fmt!("* [%s](%s)", header, id)); - } - } - ctxt.w.put_line(~""); - ctxt.w.put_line(~"
"); - ctxt.w.put_line(~""); -} - -fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) { - write_common(ctxt, doc.desc(), doc.sections()); - if doc.index.is_some() { - write_index(ctxt, doc.index.get_ref()); - } - - for FnDoc in doc.fns.iter() { - write_item_header(ctxt, doc::FnTag((*FnDoc).clone())); - write_fn(ctxt, (*FnDoc).clone()); - } -} - -fn write_fn( - ctxt: &Ctxt, - doc: doc::FnDoc -) { - write_fnlike(ctxt, doc.sig.clone(), doc.desc(), doc.sections()); -} - -fn write_fnlike( - ctxt: &Ctxt, - sig: Option<~str>, - desc: Option<~str>, - sections: &[doc::Section] -) { - write_sig(ctxt, sig); - write_common(ctxt, desc, sections); -} - -fn write_sig(ctxt: &Ctxt, sig: Option<~str>) { - match sig { - Some(sig) => { - ctxt.w.put_line(code_block(sig)); - ctxt.w.put_line(~""); - } - None => fail!("unimplemented") - } -} - -fn code_block(s: ~str) -> ~str { - fmt!("~~~ {.rust} -%s -~~~", s) -} - -fn write_static( - ctxt: &Ctxt, - doc: doc::StaticDoc -) { - write_sig(ctxt, doc.sig.clone()); - write_common(ctxt, doc.desc(), doc.sections()); -} - -fn write_enum( - ctxt: &Ctxt, - doc: doc::EnumDoc -) { - write_common(ctxt, doc.desc(), doc.sections()); - write_variants(ctxt, doc.variants); -} - -fn write_variants( - ctxt: &Ctxt, - docs: &[doc::VariantDoc] -) { - if docs.is_empty() { - return; - } - - write_header_(ctxt, H4, ~"Variants"); - - for variant in docs.iter() { - write_variant(ctxt, (*variant).clone()); - } - - ctxt.w.put_line(~""); -} - -fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) { - assert!(doc.sig.is_some()); - let sig = doc.sig.get_ref(); - - // space out list items so they all end up within paragraph elements - ctxt.w.put_line(~""); - - match doc.desc.clone() { - Some(desc) => { - ctxt.w.put_line(list_item_indent(fmt!("* `%s` - %s", *sig, desc))); - } - None => { - ctxt.w.put_line(fmt!("* `%s`", *sig)); - } - } -} - -fn list_item_indent(item: &str) -> ~str { - let indented = item.any_line_iter().collect::<~[&str]>(); - - // separate markdown elements within `*` lists must be indented by four - // spaces, or they will escape the list context. indenting everything - // seems fine though. - indented.connect("\n ") -} - -fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) { - write_common(ctxt, doc.desc(), doc.sections()); - write_methods(ctxt, doc.methods); -} - -fn write_methods(ctxt: &Ctxt, docs: &[doc::MethodDoc]) { - for doc in docs.iter() { - write_method(ctxt, (*doc).clone()); - } -} - -fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) { - write_header_(ctxt, H3, header_text_("Method", doc.name)); - write_fnlike(ctxt, doc.sig.clone(), doc.desc.clone(), doc.sections); -} - -fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) { - write_common(ctxt, doc.desc(), doc.sections()); - write_methods(ctxt, doc.methods); -} - -fn write_type( - ctxt: &Ctxt, - doc: doc::TyDoc -) { - write_sig(ctxt, doc.sig.clone()); - write_common(ctxt, doc.desc(), doc.sections()); -} - -fn put_struct( - ctxt: &Ctxt, - doc: doc::StructDoc -) { - write_sig(ctxt, doc.sig.clone()); - write_common(ctxt, doc.desc(), doc.sections()); -} - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass; - use config; - use desc_to_brief_pass; - use doc; - use extract; - use markdown_index_pass; - use markdown_pass::{mk_pass, write_markdown}; - use markdown_writer; - use path_pass; - use page_pass; - use prune_hidden_pass; - use sectionalize_pass; - use trim_pass; - use tystr_pass; - use unindent_pass; - - fn render(source: ~str) -> ~str { - let (srv, doc) = create_doc_srv(source); - let markdown = write_markdown_str_srv(srv, doc); - debug!("markdown: %s", markdown); - markdown - } - - fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) { - do astsrv::from_str(source) |srv| { - - let config = config::Config { - output_style: config::DocPerCrate, - .. config::default_config(&Path("whatever")) - }; - - let doc = extract::from_srv(srv.clone(), ~""); - debug!("doc (extract): %?", doc); - let doc = (tystr_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (tystr): %?", doc); - let doc = (path_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (path): %?", doc); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (attr): %?", doc); - let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (prune_hidden): %?", doc); - let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (desc_to_brief): %?", doc); - let doc = (unindent_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (unindent): %?", doc); - let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (trim): %?", doc); - let doc = (trim_pass::mk_pass().f)(srv.clone(), doc); - debug!("doc (sectionalize): %?", doc); - let doc = (markdown_index_pass::mk_pass(config).f)( - srv.clone(), doc); - debug!("doc (index): %?", doc); - (srv.clone(), doc) - } - } - - fn create_doc(source: ~str) -> doc::Doc { - let (_, doc) = create_doc_srv(source); - doc - } - - fn write_markdown_str( - doc: doc::Doc - ) -> ~str { - let (writer_factory, po) = markdown_writer::future_writer_factory(); - write_markdown(doc, writer_factory); - return po.recv().second(); - } - - fn write_markdown_str_srv( - srv: astsrv::Srv, - doc: doc::Doc - ) -> ~str { - let (writer_factory, po) = markdown_writer::future_writer_factory(); - let pass = mk_pass(writer_factory); - (pass.f)(srv, doc); - return po.recv().second(); - } - - #[test] - fn write_markdown_should_write_mod_headers() { - let markdown = render(~"mod moo { }"); - assert!(markdown.contains("# Module `moo`")); - } - - #[test] - fn should_leave_blank_line_after_header() { - let markdown = render(~"mod morp { }"); - assert!(markdown.contains("Module `morp`\n\n")); - } - - #[test] - fn should_write_modules_last() { - /* - Because the markdown pass writes all modules at the same level of - indentation (it doesn't 'nest' them), we need to make sure that we - write all of the modules contained in each module after all other - types of items, or else the header nesting will end up wrong, with - modules appearing to contain items that they do not. - */ - let markdown = render( - ~"mod a { }\ - fn b() { }\ - mod c { -}\ - fn d() { }" - ); - - let idx_a = markdown.find_str("# Module `a`").unwrap(); - let idx_b = markdown.find_str("## Function `b`").unwrap(); - let idx_c = markdown.find_str("# Module `c`").unwrap(); - let idx_d = markdown.find_str("## Function `d`").unwrap(); - - assert!(idx_b < idx_d); - assert!(idx_d < idx_a); - assert!(idx_a < idx_c); - } - - #[test] - fn should_request_new_writer_for_each_page() { - // This port will send us a (page, str) pair for every writer - // that was created - let (writer_factory, po) = markdown_writer::future_writer_factory(); - let (srv, doc) = create_doc_srv(~"mod a { }"); - // Split the document up into pages - let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); - write_markdown(doc, writer_factory); - // We expect two pages to have been written - for _ in range(0, 2u) { - po.recv(); - } - } - - #[test] - fn should_write_title_for_each_page() { - let (writer_factory, po) = markdown_writer::future_writer_factory(); - let (srv, doc) = create_doc_srv( - ~"#[link(name = \"core\")]; mod a { }"); - let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); - write_markdown(doc, writer_factory); - for _ in range(0, 2u) { - let (page, markdown) = po.recv(); - match page { - doc::CratePage(_) => { - assert!(markdown.contains("% Crate core")); - } - doc::ItemPage(_) => { - assert!(markdown.contains("% Module a")); - } - } - } - } - - #[test] - fn should_write_full_path_to_mod() { - let markdown = render(~"mod a { mod b { mod c { } } }"); - assert!(markdown.contains("# Module `a::b::c`")); - } - - #[test] - fn should_write_sections() { - let markdown = render( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { -}"); - assert!(markdown.contains("#### Header\n\nBody\n\n")); - } - - #[test] - fn should_write_crate_description() { - let markdown = render(~"#[doc = \"this is the crate\"];"); - assert!(markdown.contains("this is the crate")); - } - - - #[test] - fn should_write_index() { - let markdown = render(~"mod a { } mod b { }"); - assert!(markdown.contains( - "\n\n* [Module `a`](#module-a)\n\ - * [Module `b`](#module-b)\n\n" - )); - } - - #[test] - fn should_write_index_brief() { - let markdown = render(~"#[doc = \"test\"] mod a { }"); - assert!(markdown.contains("(#module-a) - test\n")); - } - - #[test] - fn should_not_write_index_if_no_entries() { - let markdown = render(~""); - assert!(!markdown.contains("\n\n\n")); - } - - #[test] - fn should_write_index_for_foreign_mods() { - let markdown = render(~"extern { fn a(); }"); - assert!(markdown.contains( - "\n\n* [Function `a`](#function-a)\n\n" - )); - } - - #[test] - fn should_write_foreign_fns() { - let markdown = render( - ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(markdown.contains("test")); - } - - #[test] - fn should_write_foreign_fn_headers() { - let markdown = render( - ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(markdown.contains("## Function `a`")); - } - - #[test] - fn write_markdown_should_write_function_header() { - let markdown = render(~"fn func() { }"); - assert!(markdown.contains("## Function `func`")); - } - - #[test] - fn should_write_the_function_signature() { - let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(markdown.contains("\n~~~ {.rust}\nfn a()\n")); - } - - #[test] - fn should_insert_blank_line_after_fn_signature() { - let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(markdown.contains("fn a()\n~~~\n\n")); - } - - #[test] - fn should_correctly_bracket_fn_signature() { - let doc = create_doc(~"fn a() { }"); - let doc = doc::Doc{ - pages: ~[ - doc::CratePage(doc::CrateDoc{ - topmod: doc::ModDoc{ - items: ~[doc::FnTag(doc::SimpleItemDoc{ - sig: Some(~"line 1\nline 2"), - .. (doc.cratemod().fns()[0]).clone() - })], - .. doc.cratemod() - }, - .. doc.CrateDoc() - }) - ] - }; - let markdown = write_markdown_str(doc); - assert!(markdown.contains("~~~ {.rust}\nline 1\nline 2\n~~~")); - } - - #[test] - fn should_leave_blank_line_between_fn_header_and_sig() { - let markdown = render(~"fn a() { }"); - assert!(markdown.contains("Function `a`\n\n~~~ {.rust}\nfn a()")); - } - - #[test] - fn should_write_static_header() { - let markdown = render(~"static a: bool = true;"); - assert!(markdown.contains("## Static `a`\n\n")); - } - - #[test] - fn should_write_static_description() { - let markdown = render( - ~"#[doc = \"b\"]\ - static a: bool = true;"); - assert!(markdown.contains("\n\nb\n\n")); - } - - #[test] - fn should_write_enum_header() { - let markdown = render(~"enum a { b }"); - assert!(markdown.contains("## Enum `a`\n\n")); - } - - #[test] - fn should_write_enum_description() { - let markdown = render(~"#[doc = \"b\"] enum a { b }"); - assert!(markdown.contains("\n\nb\n\n")); - } - - #[test] - fn should_write_variant_list() { - let markdown = render( - ~"enum a { \ - #[doc = \"test\"] b, \ - #[doc = \"test\"] c }"); - assert!(markdown.contains( - "\n\n#### Variants\n\ - \n\ - \n* `b` - test\ - \n\ - \n* `c` - test\n\n")); - } - - #[test] - fn should_write_variant_list_without_descs() { - let markdown = render(~"enum a { b, c }"); - assert!(markdown.contains( - "\n\n#### Variants\n\ - \n\ - \n* `b`\ - \n\ - \n* `c`\n\n")); - } - - #[test] - fn should_write_variant_list_with_indent() { - let markdown = render( - ~"enum a { #[doc = \"line 1\\n\\nline 2\"] b, c }"); - assert!(markdown.contains( - "\n\n#### Variants\n\ - \n\ - \n* `b` - line 1\ - \n \ - \n line 2\ - \n\ - \n* `c`\n\n")); - } - - #[test] - fn should_write_variant_list_with_signatures() { - let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }"); - assert!(markdown.contains( - "\n\n#### Variants\n\ - \n\ - \n* `b(int)`\ - \n\ - \n* `c(int)` - a\n\n")); - } - - #[test] - fn should_write_trait_header() { - let markdown = render(~"trait i { fn a(); }"); - assert!(markdown.contains("## Trait `i`")); - } - - #[test] - fn should_write_trait_desc() { - let markdown = render(~"#[doc = \"desc\"] trait i { fn a(); }"); - assert!(markdown.contains("desc")); - } - - #[test] - fn should_write_trait_method_header() { - let markdown = render(~"trait i { fn a(); }"); - assert!(markdown.contains("### Method `a`")); - } - - #[test] - fn should_write_trait_method_signature() { - let markdown = render(~"trait i { fn a(&self); }"); - assert!(markdown.contains("\n~~~ {.rust}\nfn a(&self)")); - } - - #[test] - fn should_write_impl_header() { - let markdown = render(~"impl int { fn a() { } }"); - assert!(markdown.contains("## Implementation for `int`")); - } - - #[test] - fn should_write_impl_header_with_bounds() { - let markdown = render(~"impl int { }"); - assert!(markdown.contains("## Implementation for `int` where ``")); - } - - #[test] - fn should_write_impl_header_with_trait() { - let markdown = render(~"impl j for int { fn a() { } }"); - assert!(markdown.contains( - "## Implementation of `j` for `int`")); - } - - #[test] - fn should_write_impl_desc() { - let markdown = render( - ~"#[doc = \"desc\"] impl int { fn a() { } }"); - assert!(markdown.contains("desc")); - } - - #[test] - fn should_write_impl_method_header() { - let markdown = render( - ~"impl int { fn a() { } }"); - assert!(markdown.contains("### Method `a`")); - } - - #[test] - fn should_write_impl_method_signature() { - let markdown = render( - ~"impl int { fn a(&mut self) { } }"); - assert!(markdown.contains("~~~ {.rust}\nfn a(&mut self)")); - } - - #[test] - fn should_write_type_header() { - let markdown = render(~"type t = int;"); - assert!(markdown.contains("## Type `t`")); - } - - #[test] - fn should_write_type_desc() { - let markdown = render( - ~"#[doc = \"desc\"] type t = int;"); - assert!(markdown.contains("\n\ndesc\n\n")); - } - - #[test] - fn should_write_type_signature() { - let markdown = render(~"type t = int;"); - assert!(markdown.contains("\n\n~~~ {.rust}\ntype t = int\n~~~\n")); - } - - #[test] - fn should_put_struct_header() { - let markdown = render(~"struct S { field: () }"); - assert!(markdown.contains("## Struct `S`\n\n")); - } -} diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs deleted file mode 100644 index fb58e5c2bf0..00000000000 --- a/src/librustdoc/markdown_writer.rs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use config; -use doc::ItemUtils; -use doc; - -use std::comm::*; -use std::comm; -use std::io; -use std::result; -use std::run; -use std::str; -use std::task; -use extra::future::Future; - -#[deriving(Clone)] -pub enum WriteInstr { - Write(~str), - Done -} - -pub type Writer = ~fn(v: WriteInstr); -pub type WriterFactory = ~fn(page: doc::Page) -> Writer; - -pub trait WriterUtils { - fn put_str(&self, str: ~str); - fn put_line(&self, str: ~str); - fn put_done(&self); -} - -impl WriterUtils for Writer { - fn put_str(&self, str: ~str) { - (*self)(Write(str)); - } - - fn put_line(&self, str: ~str) { - self.put_str(str + "\n"); - } - - fn put_done(&self) { - (*self)(Done) - } -} - -pub fn make_writer_factory(config: config::Config) -> WriterFactory { - match config.output_format { - config::Markdown => { - markdown_writer_factory(config) - } - config::PandocHtml => { - pandoc_writer_factory(config) - } - } -} - -fn markdown_writer_factory(config: config::Config) -> WriterFactory { - let result: ~fn(page: doc::Page) -> Writer = |page| { - markdown_writer(&config, page) - }; - result -} - -fn pandoc_writer_factory(config: config::Config) -> WriterFactory { - let result: ~fn(doc::Page) -> Writer = |page| { - pandoc_writer(&config, page) - }; - result -} - -fn markdown_writer( - config: &config::Config, - page: doc::Page -) -> Writer { - let filename = make_local_filename(config, page); - do generic_writer |markdown| { - write_file(&filename, markdown); - } -} - -fn pandoc_writer( - config: &config::Config, - page: doc::Page -) -> Writer { - assert!(config.pandoc_cmd.is_some()); - let pandoc_cmd = (*config.pandoc_cmd.get_ref()).clone(); - let filename = make_local_filename(config, page); - - let pandoc_args = ~[ - ~"--standalone", - ~"--section-divs", - ~"--from=markdown", - ~"--to=html", - ~"--css=rust.css", - ~"--output=" + filename.to_str() - ]; - - do generic_writer |markdown| { - use std::io::WriterUtil; - - debug!("pandoc cmd: %s", pandoc_cmd); - debug!("pandoc args: %s", pandoc_args.connect(" ")); - - let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new()); - - proc.input().write_str(markdown); - let output = proc.finish_with_output(); - - debug!("pandoc result: %i", output.status); - if output.status != 0 { - error!("pandoc-out: %s", str::from_utf8(output.output)); - error!("pandoc-err: %s", str::from_utf8(output.error)); - fail!("pandoc failed"); - } - } -} - -fn generic_writer(process: ~fn(markdown: ~str)) -> Writer { - let (po, ch) = stream::(); - do task::spawn || { - let mut markdown = ~""; - let mut keep_going = true; - while keep_going { - match po.recv() { - Write(s) => markdown.push_str(s), - Done => keep_going = false - } - } - process(markdown); - }; - let result: ~fn(instr: WriteInstr) = |instr| ch.send(instr); - result -} - -pub fn make_local_filename( - config: &config::Config, - page: doc::Page -) -> Path { - let filename = make_filename(config, page); - config.output_dir.push_rel(&filename) -} - -pub fn make_filename( - config: &config::Config, - page: doc::Page -) -> Path { - let filename = { - match page { - doc::CratePage(doc) => { - if config.output_format == config::PandocHtml && - config.output_style == config::DocPerMod { - ~"index" - } else { - assert!(doc.topmod.name_() != ~""); - doc.topmod.name_() - } - } - doc::ItemPage(doc) => { - (doc.path() + &[doc.name_()]).connect("_") - } - } - }; - let ext = match config.output_format { - config::Markdown => ~"md", - config::PandocHtml => ~"html" - }; - - Path(filename).with_filetype(ext) -} - -fn write_file(path: &Path, s: ~str) { - use std::io::WriterUtil; - - match io::file_writer(path, [io::Create, io::Truncate]) { - result::Ok(writer) => { - writer.write_str(s); - } - result::Err(e) => fail!(e) - } -} - -pub fn future_writer_factory( -) -> (WriterFactory, Port<(doc::Page, ~str)>) { - let (markdown_po, markdown_ch) = stream(); - let markdown_ch = SharedChan::new(markdown_ch); - let writer_factory: WriterFactory = |page| { - let (writer_po, writer_ch) = comm::stream(); - let markdown_ch = markdown_ch.clone(); - do task::spawn || { - let (writer, future) = future_writer(); - let mut future = future; - writer_ch.send(writer); - let s = future.get(); - markdown_ch.send((page.clone(), s)); - } - writer_po.recv() - }; - - (writer_factory, markdown_po) -} - -fn future_writer() -> (Writer, Future<~str>) { - let (port, chan) = comm::stream(); - let writer: ~fn(instr: WriteInstr) = |instr| chan.send(instr.clone()); - let future = do Future::from_fn || { - let mut res = ~""; - loop { - match port.recv() { - Write(s) => res.push_str(s), - Done => break - } - } - res - }; - (writer, future) -} - -#[cfg(test)] -mod test { - - use astsrv; - use doc; - use extract; - use path_pass; - use config; - use super::make_local_filename; - - fn mk_doc(name: ~str, source: ~str) -> doc::Doc { - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), name.clone()); - let doc = (path_pass::mk_pass().f)(srv.clone(), doc); - doc - } - } - - #[test] - fn should_use_markdown_file_name_based_off_crate() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::Markdown, - output_style: config::DocPerCrate, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = mk_doc(~"test", ~""); - let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(&config, page); - assert_eq!(filename.to_str(), ~"output/dir/test.md"); - } - - #[test] - fn should_name_html_crate_file_name_index_html_when_doc_per_mod() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::PandocHtml, - output_style: config::DocPerMod, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = mk_doc(~"", ~""); - let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(&config, page); - assert_eq!(filename.to_str(), ~"output/dir/index.html"); - } - - #[test] - fn should_name_mod_file_names_by_path() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::PandocHtml, - output_style: config::DocPerMod, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = mk_doc(~"", ~"mod a { mod b { } }"); - // hidden __std_macros module at the start. - let modb = doc.cratemod().mods()[1].mods()[0].clone(); - let page = doc::ItemPage(doc::ModTag(modb)); - let filename = make_local_filename(&config, page); - assert_eq!(filename, Path("output/dir/a_b.html")); - } -} diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs deleted file mode 100644 index 342c949e3fc..00000000000 --- a/src/librustdoc/page_pass.rs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Divides the document tree into pages. - -Each page corresponds is a logical section. There may be pages for -individual modules, pages for the crate, indexes, etc. -*/ - - -use astsrv; -use config; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -use std::comm::*; -use std::task; -use syntax::ast; - -#[cfg(test)] use doc::PageUtils; - -pub fn mk_pass(output_style: config::OutputStyle) -> Pass { - Pass { - name: ~"page", - f: |srv, doc| run(srv, doc, output_style) - } -} - -pub fn run( - _srv: astsrv::Srv, - doc: doc::Doc, - output_style: config::OutputStyle -) -> doc::Doc { - - if output_style == config::DocPerCrate { - return doc; - } - - let (result_port, result_chan) = stream(); - let (page_port, page_chan) = stream(); - let page_chan = SharedChan::new(page_chan); - do task::spawn { - result_chan.send(make_doc_from_pages(&page_port)); - }; - - find_pages(doc, page_chan); - result_port.recv() -} - -type PagePort = Port>; -type PageChan = SharedChan>; - -fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc { - let mut pages = ~[]; - loop { - let val = page_port.recv(); - if val.is_some() { - pages.push(val.unwrap()); - } else { - break; - } - } - doc::Doc { - pages: pages - } -} - -fn find_pages(doc: doc::Doc, page_chan: PageChan) { - let fold = Fold { - ctxt: page_chan.clone(), - fold_crate: fold_crate, - fold_mod: fold_mod, - fold_nmod: fold_nmod, - .. fold::default_any_fold(page_chan.clone()) - }; - (fold.fold_doc)(&fold, doc.clone()); - - page_chan.send(None); -} - -fn fold_crate(fold: &fold::Fold, doc: doc::CrateDoc) - -> doc::CrateDoc { - let doc = fold::default_seq_fold_crate(fold, doc); - - let page = doc::CratePage(doc::CrateDoc { - topmod: strip_mod(doc.topmod.clone()), - .. doc.clone() - }); - - fold.ctxt.send(Some(page)); - - doc -} - -fn fold_mod(fold: &fold::Fold, doc: doc::ModDoc) -> doc::ModDoc { - let doc = fold::default_any_fold_mod(fold, doc); - - if doc.id() != ast::CRATE_NODE_ID { - - let doc = strip_mod(doc.clone()); - let page = doc::ItemPage(doc::ModTag(doc)); - fold.ctxt.send(Some(page)); - } - - doc -} - -fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc { - doc::ModDoc { - items: do doc.items.iter().filter |item| { - match **item { - doc::ModTag(_) | doc::NmodTag(_) => false, - _ => true - } - }.map(|x| (*x).clone()).collect::<~[doc::ItemTag]>(), - .. doc.clone() - } -} - -fn fold_nmod(fold: &fold::Fold, doc: doc::NmodDoc) -> doc::NmodDoc { - let doc = fold::default_seq_fold_nmod(fold, doc); - let page = doc::ItemPage(doc::NmodTag(doc.clone())); - fold.ctxt.send(Some(page)); - return doc; -} - -#[cfg(test)] -mod test { - use astsrv; - use config; - use attr_pass; - use doc; - use extract; - use prune_hidden_pass; - use page_pass::run; - - fn mk_doc_( - output_style: config::OutputStyle, - source: ~str - ) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc); - run(srv.clone(), doc, output_style) - } - } - - fn mk_doc(source: ~str) -> doc::Doc { - mk_doc_(config::DocPerMod, source.clone()) - } - - #[test] - fn should_not_split_the_doc_into_pages_for_doc_per_crate() { - let doc = mk_doc_( - config::DocPerCrate, - ~"mod a { } mod b { mod c { } }" - ); - assert_eq!(doc.pages.len(), 1u); - } - - #[test] - fn should_make_a_page_for_every_mod() { - let doc = mk_doc(~"mod a { }"); - // hidden __std_macros module at the start. - assert_eq!(doc.pages.mods()[0].name_(), ~"a"); - } - - #[test] - fn should_remove_mods_from_containing_mods() { - let doc = mk_doc(~"mod a { }"); - assert!(doc.cratemod().mods().is_empty()); - } -} diff --git a/src/librustdoc/parse.rs b/src/librustdoc/parse.rs deleted file mode 100644 index a8321dd95a1..00000000000 --- a/src/librustdoc/parse.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! AST-parsing helpers - -use rustc::driver::driver; -use rustc::driver::session; -use syntax::ast; -use syntax::parse; - -pub fn from_file(file: &Path) -> @ast::Crate { - parse::parse_crate_from_file( - file, ~[], parse::new_parse_sess(None)) -} - -pub fn from_str(source: @str) -> @ast::Crate { - parse::parse_crate_from_source_str( - @"-", source, ~[], parse::new_parse_sess(None)) -} - -pub fn from_file_sess(sess: session::Session, file: &Path) -> @ast::Crate { - parse::parse_crate_from_file( - file, cfg(sess), sess.parse_sess) -} - -pub fn from_str_sess(sess: session::Session, source: @str) -> @ast::Crate { - parse::parse_crate_from_source_str( - @"-", source, cfg(sess), sess.parse_sess) -} - -fn cfg(sess: session::Session) -> ast::CrateConfig { - driver::build_configuration(sess) -} - diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs deleted file mode 100644 index aadc1b31acc..00000000000 --- a/src/librustdoc/pass.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - - -use astsrv; -use doc; -use time; - -#[cfg(test)] use extract; - -/// A single operation on the document model -pub struct Pass { - name: ~str, - f: @fn(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc -} - -pub fn run_passes( - srv: astsrv::Srv, - doc: doc::Doc, - passes: ~[Pass] -) -> doc::Doc { - let mut passno = 0; - do passes.iter().fold(doc) |doc, pass| { - debug!("pass #%d", passno); - passno += 1; - do time(pass.name.clone()) { - (pass.f)(srv.clone(), doc.clone()) - } - } -} - -#[test] -fn test_run_passes() { - fn pass1( - _srv: astsrv::Srv, - doc: doc::Doc - ) -> doc::Doc { - doc::Doc{ - pages: ~[ - doc::CratePage(doc::CrateDoc{ - topmod: doc::ModDoc{ - item: doc::ItemDoc { - name: doc.cratemod().name_() + "two", - .. doc.cratemod().item.clone() - }, - items: ~[], - index: None - } - }) - ] - } - } - fn pass2( - _srv: astsrv::Srv, - doc: doc::Doc - ) -> doc::Doc { - doc::Doc{ - pages: ~[ - doc::CratePage(doc::CrateDoc{ - topmod: doc::ModDoc{ - item: doc::ItemDoc { - name: doc.cratemod().name_() + "three", - .. doc.cratemod().item.clone() - }, - items: ~[], - index: None - } - }) - ] - } - } - let source = ~""; - do astsrv::from_str(source) |srv| { - let passes = ~[ - Pass { - name: ~"", - f: pass1 - }, - Pass { - name: ~"", - f: pass2 - } - ]; - let doc = extract::from_srv(srv.clone(), ~"one"); - let doc = run_passes(srv, doc, passes); - assert_eq!(doc.cratemod().name_(), ~"onetwothree"); - } -} diff --git a/src/rustdoc_ng/passes.rs b/src/librustdoc/passes.rs similarity index 100% rename from src/rustdoc_ng/passes.rs rename to src/librustdoc/passes.rs diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs deleted file mode 100644 index 6e6092a6a3f..00000000000 --- a/src/librustdoc/path_pass.rs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Records the full path to items - - -use astsrv; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -#[cfg(test)] use extract; - -use syntax::ast; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"path", - f: run - } -} - -struct Ctxt { - srv: astsrv::Srv, - path: @mut ~[~str] -} - -impl Clone for Ctxt { - fn clone(&self) -> Ctxt { - Ctxt { - srv: self.srv.clone(), - path: @mut (*self.path).clone() - } - } -} - -fn run(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { - let ctxt = Ctxt { - srv: srv, - path: @mut ~[] - }; - let fold = Fold { - ctxt: ctxt.clone(), - fold_item: fold_item, - fold_mod: fold_mod, - fold_nmod: fold_nmod, - .. fold::default_any_fold(ctxt) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_item(fold: &fold::Fold, doc: doc::ItemDoc) -> doc::ItemDoc { - doc::ItemDoc { - path: (*fold.ctxt.path).clone(), - .. doc - } -} - -fn fold_mod(fold: &fold::Fold, doc: doc::ModDoc) -> doc::ModDoc { - let is_topmod = doc.id() == ast::CRATE_NODE_ID; - - if !is_topmod { fold.ctxt.path.push(doc.name_()); } - let doc = fold::default_any_fold_mod(fold, doc); - if !is_topmod { fold.ctxt.path.pop(); } - - doc::ModDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -fn fold_nmod(fold: &fold::Fold, doc: doc::NmodDoc) -> doc::NmodDoc { - fold.ctxt.path.push(doc.name_()); - let doc = fold::default_seq_fold_nmod(fold, doc); - fold.ctxt.path.pop(); - - doc::NmodDoc { - item: (fold.fold_item)(fold, doc.item.clone()), - .. doc - } -} - -#[test] -fn should_record_mod_paths() { - let source = ~"mod a { mod b { mod c { } } mod d { mod e { } } }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = run(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().mods()[1].mods()[0].mods()[0].path(), - ~[~"a", ~"b"]); - assert_eq!(doc.cratemod().mods()[1].mods()[1].mods()[0].path(), - ~[~"a", ~"d"]); - } -} - -#[test] -fn should_record_fn_paths() { - let source = ~"mod a { fn b() { } }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = run(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().mods()[1].fns()[0].path(), ~[~"a"]); - } -} diff --git a/src/rustdoc_ng/plugins.rs b/src/librustdoc/plugins.rs similarity index 100% rename from src/rustdoc_ng/plugins.rs rename to src/librustdoc/plugins.rs diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs deleted file mode 100644 index 9dc2f43f7ac..00000000000 --- a/src/librustdoc/prune_hidden_pass.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Prunes things with the #[doc(hidden)] attribute - -use astsrv; -use attr_parser; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"prune_hidden", - f: run - } -} - -pub fn run(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { - let fold = Fold { - ctxt: srv.clone(), - fold_mod: fold_mod, - .. fold::default_any_fold(srv) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_mod( - fold: &fold::Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - let doc = fold::default_any_fold_mod(fold, doc); - - doc::ModDoc { - items: do doc.items.iter().filter |item_tag| { - !is_hidden(fold.ctxt.clone(), item_tag.item()) - }.map(|x| (*x).clone()).collect(), - .. doc - } -} - -fn is_hidden(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { - use syntax::ast_map; - - let id = doc.id; - do astsrv::exec(srv) |ctxt| { - let attrs = match ctxt.ast_map.get_copy(&id) { - ast_map::node_item(item, _) => item.attrs.clone(), - _ => ~[] - }; - attr_parser::parse_hidden(attrs) - } -} - -#[cfg(test)] -mod test { - use astsrv; - use doc; - use extract; - use prune_hidden_pass::run; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - run(srv.clone(), doc) - } - } - - #[test] - fn should_prune_hidden_items() { - let doc = mk_doc(~"#[doc(hidden)] mod a { }"); - assert!(doc.cratemod().mods().is_empty()) - } -} diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs deleted file mode 100644 index 6a2a0ef502c..00000000000 --- a/src/librustdoc/prune_private_pass.rs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Prune things that are private - - -use extract; -use syntax::ast; -use syntax::ast_map; -use astsrv; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"prune_private", - f: run - } -} - -pub fn run(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { - // First strip private methods out of impls - let fold = Fold { - ctxt: srv.clone(), - fold_impl: fold_impl, - .. fold::default_any_fold(srv.clone()) - }; - let doc = (fold.fold_doc)(&fold, doc); - - // Then strip private items and empty impls - let fold = Fold { - ctxt: srv.clone(), - fold_mod: fold_mod, - .. fold::default_any_fold(srv) - }; - let doc = (fold.fold_doc)(&fold, doc); - - return doc; -} - -fn fold_impl( - fold: &fold::Fold, - doc: doc::ImplDoc -) -> doc::ImplDoc { - let doc = fold::default_seq_fold_impl(fold, doc); - - do astsrv::exec(fold.ctxt.clone()) |ctxt| { - match ctxt.ast_map.get_copy(&doc.item.id) { - ast_map::node_item(item, _) => { - match item.node { - ast::item_impl(_, None, _, ref methods) => { - // Associated impls have complex rules for method visibility - strip_priv_methods(doc.clone(), *methods, item.vis) - } - ast::item_impl(_, Some(_), _ ,_) => { - // Trait impls don't - doc.clone() - } - _ => fail!() - } - } - _ => fail!() - } - } -} - -fn strip_priv_methods( - doc: doc::ImplDoc, - methods: &[@ast::method], - item_vis: ast::visibility -) -> doc::ImplDoc { - let methods = do doc.methods.iter().filter |method| { - let ast_method = do methods.iter().find |m| { - extract::to_str(m.ident) == method.name - }; - assert!(ast_method.is_some()); - let ast_method = ast_method.unwrap(); - match ast_method.vis { - ast::public => true, - ast::private => false, - ast::inherited => item_vis == ast::public - } - }.map(|x| (*x).clone()).collect(); - - doc::ImplDoc { - methods: methods, - .. doc - } -} - -fn fold_mod( - fold: &fold::Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - let doc = fold::default_any_fold_mod(fold, doc); - - doc::ModDoc { - items: doc.items.iter().filter(|item_tag| { - match item_tag { - & &doc::ImplTag(ref doc) => { - if doc.trait_types.is_empty() { - // This is an associated impl. We have already pruned the - // non-visible methods. If there are any left then - // retain the impl, otherwise throw it away - !doc.methods.is_empty() - } else { - // This is a trait implementation, make it visible - // NB: This is not quite right since this could be an impl - // of a private trait. We can't know that without running - // resolve though. - true - } - } - _ => { - is_visible(fold.ctxt.clone(), item_tag.item()) - } - } - }).map(|x| (*x).clone()).collect(), - .. doc - } -} - -fn is_visible(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { - let id = doc.id; - - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&id) { - ast_map::node_item(item, _) => { - match &item.node { - &ast::item_impl(*) => { - // Impls handled elsewhere - fail!() - } - _ => { - // Otherwise just look at the visibility - item.vis == ast::public - } - } - } - _ => unreachable!() - } - } -} - - -#[cfg(test)] -mod test { - use astsrv; - use doc; - use extract; - use tystr_pass; - use prune_private_pass::run; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = tystr_pass::run(srv.clone(), doc); - run(srv.clone(), doc) - } - } - - #[test] - fn should_prune_items_without_pub_modifier() { - let doc = mk_doc(~"mod a { }"); - assert!(doc.cratemod().mods().is_empty()); - } - - #[test] - fn should_not_prune_trait_impls() { - // Impls are more complicated - let doc = mk_doc( - ~" \ - trait Foo { } \ - impl Foo for int { } \ - "); - assert!(!doc.cratemod().impls().is_empty()); - } - - #[test] - fn should_prune_associated_methods_without_vis_modifier_on_impls_without_vis_modifier() { - let doc = mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); - } - - #[test] - fn should_prune_priv_associated_methods_on_impls_without_vis_modifier() { - let doc = mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); - } - - #[test] - fn should_prune_priv_associated_methods_on_pub_impls() { - let doc = mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); - } - - #[test] - fn should_prune_associated_methods_without_vis_modifier_on_priv_impls() { - let doc = mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); - } - - #[test] - fn should_prune_priv_associated_methods_on_priv_impls() { - let doc = mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); - } - - #[test] - fn should_prune_associated_impls_with_no_pub_methods() { - let doc = mk_doc( - ~"impl Foo {\ - fn baz() { }\ - }"); - assert!(doc.cratemod().impls().is_empty()); - } - - #[test] - fn should_not_prune_associated_impls_with_pub_methods() { - let doc = mk_doc( - ~" \ - impl Foo { pub fn bar() { } } \ - "); - assert!(!doc.cratemod().impls().is_empty()); - } -} diff --git a/src/librustdoc/rustdoc.rs b/src/librustdoc/rustdoc.rs index 9708644d06c..bc7e6c8926d 100644 --- a/src/librustdoc/rustdoc.rs +++ b/src/librustdoc/rustdoc.rs @@ -8,140 +8,209 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Rustdoc - The Rust documentation generator - #[link(name = "rustdoc", vers = "0.8", - uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", - url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; + uuid = "8c6e4598-1596-4aa5-a24c-b811914bbbc6", + url = "https://github.com/mozilla/rust/tree/master/src/librustdoc")]; -#[comment = "The Rust documentation generator"]; +#[desc = "rustdoc, the Rust documentation extractor"]; #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod extra; -extern mod rustc; extern mod syntax; +extern mod rustc; +extern mod extra; -use std::os; +use extra::serialize::Encodable; +use extra::time; +use extra::getopts::groups; +use std::cell::Cell; +use std::rt::io; +use std::rt::io::Writer; +use std::rt::io::file::FileInfo; -use config::Config; -use doc::Item; -use doc::ItemUtils; - -pub mod pass; -pub mod config; -pub mod parse; -pub mod extract; -pub mod attr_parser; -pub mod doc; -pub mod markdown_index_pass; -pub mod markdown_pass; -pub mod markdown_writer; +pub mod clean; +pub mod core; +pub mod doctree; pub mod fold; -pub mod path_pass; -pub mod attr_pass; -pub mod tystr_pass; -pub mod prune_hidden_pass; -pub mod desc_to_brief_pass; -pub mod text_pass; -pub mod unindent_pass; -pub mod trim_pass; -pub mod astsrv; -pub mod demo; -pub mod sort_pass; -pub mod sort_item_name_pass; -pub mod sort_item_type_pass; -pub mod page_pass; -pub mod sectionalize_pass; -pub mod escape_pass; -pub mod prune_private_pass; +pub mod html { + pub mod render; + pub mod layout; + pub mod markdown; + pub mod format; +} +pub mod passes; +pub mod plugins; +pub mod visit_ast; + +pub static SCHEMA_VERSION: &'static str = "0.8.0"; + +local_data_key!(pub ctxtkey: @core::DocContext) + +enum OutputFormat { + HTML, JSON +} pub fn main() { - let args = os::args(); - main_args(args); + main_args(std::os::args()); +} + +pub fn opts() -> ~[groups::OptGroup] { + use extra::getopts::groups::*; + ~[ + optmulti("L", "library-path", "directory to add to crate search path", + "DIR"), + optmulti("", "plugin-path", "directory to load plugins from", "DIR"), + optmulti("", "passes", "space separated list of passes to also run", + "PASSES"), + optmulti("", "plugins", "space separated list of plugins to also load", + "PLUGINS"), + optflag("h", "help", "show this help message"), + optflag("", "nodefaults", "don't run the default passes"), + optopt("o", "output", "where to place the output", "PATH"), + ] +} + +pub fn usage(argv0: &str) { + println(groups::usage(format!("{} [options] [html|json] ", + argv0), opts())); } pub fn main_args(args: &[~str]) { - if args.iter().any(|x| "-h" == *x) || args.iter().any(|x| "--help" == *x) { - config::usage(); + //use extra::getopts::groups::*; + + let matches = groups::getopts(args.tail(), opts()).unwrap(); + + if matches.opt_present("h") || matches.opt_present("help") { + usage(args[0]); return; } - let config = match config::parse_config(args) { - Ok(config) => config, - Err(err) => { - printfln!("error: %s", err); - return; - } + let (format, cratefile) = match matches.free.clone() { + [~"json", crate] => (JSON, crate), + [~"html", crate] => (HTML, crate), + [s, _] => { + println!("Unknown output format: `{}`", s); + usage(args[0]); + exit(1); + } + [_, .._] => { + println!("Expected exactly one crate to process"); + usage(args[0]); + exit(1); + } + _ => { + println!("Expected an output format and then one crate"); + usage(args[0]); + exit(1); + } }; - run(config); -} + // First, parse the crate and extract all relevant information. + let libs = Cell::new(matches.opt_strs("L").map(|s| Path(*s))); + let cr = Cell::new(Path(cratefile)); + info2!("starting to run rustc"); + let crate = do std::task::try { + let cr = cr.take(); + core::run_core(libs.take(), &cr) + }.unwrap(); + info2!("finished with rustc"); -/// Runs rustdoc over the given file -fn run(config: Config) { - - let source_file = config.input_crate.clone(); - - // Create an AST service from the source code - do astsrv::from_file(source_file.to_str()) |srv| { - - // Just time how long it takes for the AST to become available - do time(~"wait_ast") { - do astsrv::exec(srv.clone()) |_ctxt| { } - }; - - // Extract the initial doc tree from the AST. This contains - // just names and node ids. - let doc = time(~"extract", || { - let default_name = source_file.clone(); - extract::from_srv(srv.clone(), default_name.to_str()) - }); - - // Refine and publish the document - pass::run_passes(srv, doc, ~[ - // Generate type and signature strings - tystr_pass::mk_pass(), - // Record the full paths to various nodes - path_pass::mk_pass(), - // Extract the docs attributes and attach them to doc nodes - attr_pass::mk_pass(), - // Perform various text escaping - escape_pass::mk_pass(), - // Remove things marked doc(hidden) - prune_hidden_pass::mk_pass(), - // Remove things that are private - prune_private_pass::mk_pass(), - // Extract brief documentation from the full descriptions - desc_to_brief_pass::mk_pass(), - // Massage the text to remove extra indentation - unindent_pass::mk_pass(), - // Split text into multiple sections according to headers - sectionalize_pass::mk_pass(), - // Trim extra spaces from text - trim_pass::mk_pass(), - // Sort items by name - sort_item_name_pass::mk_pass(), - // Sort items again by kind - sort_item_type_pass::mk_pass(), - // Create indexes appropriate for markdown - markdown_index_pass::mk_pass(config.clone()), - // Break the document into pages if required by the - // output format - page_pass::mk_pass(config.output_style), - // Render - markdown_pass::mk_pass( - markdown_writer::make_writer_factory(config.clone()) - ) - ]); + // Process all of the crate attributes, extracting plugin metadata along + // with the passes which we are supposed to run. + let mut default_passes = !matches.opt_present("nodefaults"); + let mut passes = matches.opt_strs("passes"); + let mut plugins = matches.opt_strs("plugins"); + match crate.module.get_ref().doc_list() { + Some(nested) => { + for inner in nested.iter() { + match *inner { + clean::Word(~"no_default_passes") => { + default_passes = false; + } + clean::NameValue(~"passes", ref value) => { + for pass in value.word_iter() { + passes.push(pass.to_owned()); + } + } + clean::NameValue(~"plugins", ref value) => { + for p in value.word_iter() { + plugins.push(p.to_owned()); + } + } + _ => {} + } + } + } + None => {} } + if default_passes { + passes.unshift(~"collapse-docs"); + passes.unshift(~"unindent-comments"); + } + + // Load all plugins/passes into a PluginManager + let mut pm = plugins::PluginManager::new(Path("/tmp/rustdoc_ng/plugins")); + for pass in passes.iter() { + let plugin = match pass.as_slice() { + "strip-hidden" => passes::strip_hidden, + "unindent-comments" => passes::unindent_comments, + "collapse-docs" => passes::collapse_docs, + "collapse-privacy" => passes::collapse_privacy, + s => { error!("unknown pass %s, skipping", s); loop }, + }; + pm.add_plugin(plugin); + } + info2!("loading plugins..."); + for pname in plugins.move_iter() { + pm.load_plugin(pname); + } + + // Run everything! + info2!("Executing passes/plugins"); + let (crate, res) = pm.run_plugins(crate); + + info2!("going to format"); + let started = time::precise_time_ns(); + let output = matches.opt_str("o").map(|s| Path(*s)); + match format { + HTML => { html::render::run(crate, output.unwrap_or(Path("doc"))) } + JSON => { jsonify(crate, res, output.unwrap_or(Path("doc.json"))) } + } + let ended = time::precise_time_ns(); + info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64); } -pub fn time(what: ~str, f: &fn() -> T) -> T { - let start = extra::time::precise_time_s(); - let rv = f(); - let end = extra::time::precise_time_s(); - info!("time: %3.3f s %s", end - start, what); - rv +fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) { + // { + // "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 plugins_json = ~res.move_iter().filter_map(|opt| opt).collect(); + + // FIXME #8335: 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)); + + let mut file = dst.open_writer(io::Create).unwrap(); + let output = extra::json::Object(json).to_str(); + file.write(output.as_bytes()); +} + +fn exit(status: int) -> ! { + #[fixed_stack_segment]; #[inline(never)]; + use std::libc; + unsafe { libc::exit(status as libc::c_int) } } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs deleted file mode 100644 index 20f3ff3e98d..00000000000 --- a/src/librustdoc/sectionalize_pass.rs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Breaks rustdocs into sections according to their headers - - -use astsrv; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"sectionalize", - f: run - } -} - -pub fn run(_srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc { - let fold = Fold { - fold_item: fold_item, - fold_trait: fold_trait, - fold_impl: fold_impl, - .. fold::default_any_fold(()) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_item(fold: &fold::Fold<()>, doc: doc::ItemDoc) -> doc::ItemDoc { - let doc = fold::default_seq_fold_item(fold, doc); - let (desc, sections) = sectionalize(doc.desc.clone()); - - doc::ItemDoc { - desc: desc, - sections: sections, - .. doc - } -} - -fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc { - let doc = fold::default_seq_fold_trait(fold, doc); - - doc::TraitDoc { - methods: do doc.methods.map |method| { - let (desc, sections) = sectionalize(method.desc.clone()); - - doc::MethodDoc { - desc: desc, - sections: sections, - .. (*method).clone() - } - }, - .. doc - } -} - -fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc { - let doc = fold::default_seq_fold_impl(fold, doc); - - doc::ImplDoc { - methods: do doc.methods.map |method| { - let (desc, sections) = sectionalize(method.desc.clone()); - - doc::MethodDoc { - desc: desc, - sections: sections, - .. (*method).clone() - } - }, - .. doc - } -} - -fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { - - /*! - * Take a description of the form - * - * General text - * - * # Section header - * - * Section text - * - * # Section header - * - * Section text - * - * and remove each header and accompanying text into section records. - */ - - if desc.is_none() { - return (None, ~[]); - } - - let mut new_desc = None::<~str>; - let mut current_section: Option = None; - let mut sections = ~[]; - - for line in desc.get_ref().any_line_iter() { - match parse_header(line) { - Some(header) => { - if current_section.is_some() { - sections.push((*current_section.get_ref()).clone()); - } - current_section = Some(doc::Section { - header: header.to_owned(), - body: ~"" - }); - } - None => { - match current_section.clone() { - Some(section) => { - current_section = Some(doc::Section { - body: fmt!("%s\n%s", section.body, line), - .. section - }); - } - None => { - new_desc = match new_desc.clone() { - Some(desc) => { - Some(fmt!("%s\n%s", desc, line)) - } - None => { - Some(line.to_owned()) - } - }; - } - } - } - } - } - - if current_section.is_some() { - sections.push(current_section.unwrap()); - } - - (new_desc, sections) -} - -fn parse_header<'a>(line: &'a str) -> Option<&'a str> { - if line.starts_with("# ") { - Some(line.slice_from(2)) - } else { - None - } -} - - - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass; - use doc; - use extract; - use prune_hidden_pass; - use sectionalize_pass::run; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc); - run(srv.clone(), doc) - } - } - - #[test] - fn should_create_section_headers() { - let doc = mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { -}"); - assert!(doc.cratemod().mods()[0].item.sections[0].header.contains("Header")); - } - - #[test] - fn should_create_section_bodies() { - let doc = mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { -}"); - assert!(doc.cratemod().mods()[0].item.sections[0].body.contains("Body")); - } - - #[test] - fn should_not_create_sections_from_indented_headers() { - let doc = mk_doc( - ~"#[doc = \"\n\ - Text\n # Header\n\ - Body\"]\ - mod a { -}"); - assert!(doc.cratemod().mods()[0].item.sections.is_empty()); - } - - #[test] - fn should_remove_section_text_from_main_desc() { - let doc = mk_doc( - ~"#[doc = \"\ - Description\n\n\ - # Header\n\ - Body\"]\ - mod a { -}"); - assert!(!doc.cratemod().mods()[0].desc().unwrap().contains("Header")); - assert!(!doc.cratemod().mods()[0].desc().unwrap().contains("Body")); - } - - #[test] - fn should_eliminate_desc_if_it_is_just_whitespace() { - let doc = mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { -}"); - assert_eq!(doc.cratemod().mods()[0].desc(), None); - } - - #[test] - fn should_sectionalize_trait_methods() { - let doc = mk_doc( - ~"trait i { -#[doc = \"\ - # Header\n\ - Body\"]\ - fn a(); }"); - assert_eq!(doc.cratemod().traits()[0].methods[0].sections.len(), 1u); - } - - #[test] - fn should_sectionalize_impl_methods() { - let doc = mk_doc( - ~"impl bool { -#[doc = \"\ - # Header\n\ - Body\"]\ - fn a() { } }"); - assert_eq!(doc.cratemod().impls()[0].methods[0].sections.len(), 1u); - } -} diff --git a/src/librustdoc/sort_item_name_pass.rs b/src/librustdoc/sort_item_name_pass.rs deleted file mode 100644 index 8c7267e0b21..00000000000 --- a/src/librustdoc/sort_item_name_pass.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Sorts items by name - -use doc::ItemUtils; -use doc; -use pass::Pass; -use sort_pass; - -pub fn mk_pass() -> Pass { - fn by_item_name(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { - (*item1).name_() <= (*item2).name_() - } - sort_pass::mk_pass(~"sort_item_name", by_item_name) -} - -#[test] -fn test() { - use astsrv; - use extract; - - let source = ~"mod z { } fn y() { }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (mk_pass().f)(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().items[1].name_(), ~"y"); - assert_eq!(doc.cratemod().items[2].name_(), ~"z"); - } -} diff --git a/src/librustdoc/sort_item_type_pass.rs b/src/librustdoc/sort_item_type_pass.rs deleted file mode 100644 index ba8f37601fd..00000000000 --- a/src/librustdoc/sort_item_type_pass.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Sorts items by type - -use doc; -use pass::Pass; -use sort_pass; - -pub fn mk_pass() -> Pass { - fn by_score(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { - fn score(item: &doc::ItemTag) -> int { - match *item { - doc::StaticTag(_) => 0, - doc::TyTag(_) => 1, - doc::EnumTag(_) => 2, - doc::StructTag(_) => 3, - doc::TraitTag(_) => 4, - doc::ImplTag(_) => 5, - doc::FnTag(_) => 6, - doc::ModTag(_) => 7, - doc::NmodTag(_) => 8 - } - } - - score(item1) <= score(item2) - } - - sort_pass::mk_pass(~"sort_item_type", by_score) -} - -#[test] -fn test() { - use astsrv; - use extract; - - let source = - ~"mod imod { } \ - static istatic: int = 0; \ - fn ifn() { } \ - enum ienum { ivar } \ - trait itrait { fn a(); } \ - impl int { fn a() { } } \ - type itype = int; \ - struct istruct { f: () }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (mk_pass().f)(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().items[0].name_(), ~"istatic"); - assert_eq!(doc.cratemod().items[1].name_(), ~"itype"); - assert_eq!(doc.cratemod().items[2].name_(), ~"ienum"); - assert_eq!(doc.cratemod().items[3].name_(), ~"istruct"); - assert_eq!(doc.cratemod().items[4].name_(), ~"itrait"); - assert_eq!(doc.cratemod().items[5].name_(), ~"__extensions__"); - assert_eq!(doc.cratemod().items[6].name_(), ~"ifn"); - // hidden __std_macros module fits here. - assert_eq!(doc.cratemod().items[8].name_(), ~"imod"); - } -} diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs deleted file mode 100644 index a6aa9480f38..00000000000 --- a/src/librustdoc/sort_pass.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A general sorting pass - -use astsrv; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -#[cfg(test)] use extract; - -use extra::sort; -use std::clone::Clone; - -pub type ItemLtEqOp = @fn(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; - -struct ItemLtEq { - op: ItemLtEqOp, -} - -impl Clone for ItemLtEq { - fn clone(&self) -> ItemLtEq { - ItemLtEq { - op: self.op, - } - } -} - -pub fn mk_pass(name: ~str, lteq: ItemLtEqOp) -> Pass { - Pass { - name: name.clone(), - f: |srv, doc| run(srv, doc, ItemLtEq { op: lteq }) - } -} - -fn run( - _srv: astsrv::Srv, - doc: doc::Doc, - lteq: ItemLtEq -) -> doc::Doc { - let fold = Fold { - fold_mod: fold_mod, - .. fold::default_any_fold(lteq) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_mod( - fold: &fold::Fold, - doc: doc::ModDoc -) -> doc::ModDoc { - let doc = fold::default_any_fold_mod(fold, doc); - doc::ModDoc { - items: sort::merge_sort(doc.items, fold.ctxt.op), - .. doc - } -} - -#[test] -fn test() { - fn name_lteq(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { - (*item1).name_() <= (*item2).name_() - } - - let source = ~"mod z { mod y { } fn x() { } } mod w { }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (mk_pass(~"", name_lteq).f)(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().mods()[1].name_(), ~"w"); - assert_eq!(doc.cratemod().mods()[2].items[0].name_(), ~"x"); - assert_eq!(doc.cratemod().mods()[2].items[1].name_(), ~"y"); - assert_eq!(doc.cratemod().mods()[2].name_(), ~"z"); - } -} - -#[test] -fn should_be_stable() { - fn always_eq(_item1: &doc::ItemTag, _item2: &doc::ItemTag) -> bool { - true - } - - let source = ~"mod a { mod b { } } mod c { mod d { } }"; - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (mk_pass(~"", always_eq).f)(srv.clone(), doc); - // hidden __std_macros module at the start. - assert_eq!(doc.cratemod().mods()[1].items[0].name_(), ~"b"); - assert_eq!(doc.cratemod().mods()[2].items[0].name_(), ~"d"); - let doc = (mk_pass(~"", always_eq).f)(srv.clone(), doc); - assert_eq!(doc.cratemod().mods()[1].items[0].name_(), ~"b"); - assert_eq!(doc.cratemod().mods()[2].items[0].name_(), ~"d"); - } -} diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs deleted file mode 100644 index 41c0dcfb6d2..00000000000 --- a/src/librustdoc/text_pass.rs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Generic pass for performing an operation on all descriptions - - -use astsrv; -use doc::ItemUtils; -use doc; -use fold::Fold; -use fold; -use pass::Pass; - -use std::cell::Cell; - -pub fn mk_pass(name: ~str, op: @fn(&str) -> ~str) -> Pass { - let op = Cell::new(op); - Pass { - name: name.clone(), - f: |srv: astsrv::Srv, doc: doc::Doc| -> doc::Doc { - run(srv, doc, op.take()) - } - } -} - -type Op = @fn(&str) -> ~str; - -struct WrappedOp { - op: Op, -} - -impl Clone for WrappedOp { - fn clone(&self) -> WrappedOp { - WrappedOp { - op: self.op, - } - } -} - -fn run( - _srv: astsrv::Srv, - doc: doc::Doc, - op: Op -) -> doc::Doc { - let op = WrappedOp { - op: op - }; - let fold = Fold { - fold_item: fold_item, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - .. fold::default_any_fold(op) - }; - (fold.fold_doc)(&fold, doc) -} - -fn maybe_apply_op(op: WrappedOp, s: &Option<~str>) -> Option<~str> { - s.map(|s| (op.op)(*s) ) -} - -fn fold_item(fold: &fold::Fold, doc: doc::ItemDoc) - -> doc::ItemDoc { - let doc = fold::default_seq_fold_item(fold, doc); - - doc::ItemDoc { - brief: maybe_apply_op(fold.ctxt, &doc.brief), - desc: maybe_apply_op(fold.ctxt, &doc.desc), - sections: apply_to_sections(fold.ctxt, doc.sections.clone()), - .. doc - } -} - -fn apply_to_sections(op: WrappedOp, sections: ~[doc::Section]) - -> ~[doc::Section] { - sections.map(|section| doc::Section { - header: (op.op)(section.header.clone()), - body: (op.op)(section.body.clone()) - }) -} - -fn fold_enum(fold: &fold::Fold, doc: doc::EnumDoc) - -> doc::EnumDoc { - let doc = fold::default_seq_fold_enum(fold, doc); - let fold_copy = *fold; - - doc::EnumDoc { - variants: do doc.variants.map |variant| { - doc::VariantDoc { - desc: maybe_apply_op(fold_copy.ctxt, &variant.desc), - .. (*variant).clone() - } - }, - .. doc - } -} - -fn fold_trait(fold: &fold::Fold, doc: doc::TraitDoc) - -> doc::TraitDoc { - let doc = fold::default_seq_fold_trait(fold, doc); - - doc::TraitDoc { - methods: apply_to_methods(fold.ctxt, doc.methods.clone()), - .. doc - } -} - -fn apply_to_methods(op: WrappedOp, docs: ~[doc::MethodDoc]) - -> ~[doc::MethodDoc] { - do docs.map |doc| { - doc::MethodDoc { - brief: maybe_apply_op(op, &doc.brief), - desc: maybe_apply_op(op, &doc.desc), - sections: apply_to_sections(op, doc.sections.clone()), - .. (*doc).clone() - } - } -} - -fn fold_impl(fold: &fold::Fold, doc: doc::ImplDoc) - -> doc::ImplDoc { - let doc = fold::default_seq_fold_impl(fold, doc); - - doc::ImplDoc { - methods: apply_to_methods(fold.ctxt, doc.methods.clone()), - .. doc - } -} - -#[cfg(test)] -mod test { - - use astsrv; - use attr_pass; - use desc_to_brief_pass; - use doc; - use extract; - use sectionalize_pass; - use text_pass::mk_pass; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); - let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc); - (mk_pass(~"", |s| s.trim().to_owned() ).f)(srv.clone(), doc) - } - } - - #[test] - fn should_execute_op_on_enum_brief() { - let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert_eq!(doc.cratemod().enums()[0].brief(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_enum_desc() { - let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert_eq!(doc.cratemod().enums()[0].desc(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_variant_desc() { - let doc = mk_doc(~"enum a { #[doc = \" a \"] b }"); - assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"a")); - } - - #[test] - fn should_execute_op_on_trait_brief() { - let doc = mk_doc( - ~"#[doc = \" a \"] trait i { fn a(); }"); - assert_eq!(doc.cratemod().traits()[0].brief(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_trait_desc() { - let doc = mk_doc( - ~"#[doc = \" a \"] trait i { fn a(); }"); - assert_eq!(doc.cratemod().traits()[0].desc(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_trait_method_brief() { - let doc = mk_doc( - ~"trait i { #[doc = \" a \"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].brief == Some(~"a")); - } - - #[test] - fn should_execute_op_on_trait_method_desc() { - let doc = mk_doc( - ~"trait i { #[doc = \" a \"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"a")); - } - - #[test] - fn should_execute_op_on_impl_brief() { - let doc = mk_doc( - ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert_eq!(doc.cratemod().impls()[0].brief(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_impl_desc() { - let doc = mk_doc( - ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert_eq!(doc.cratemod().impls()[0].desc(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_impl_method_brief() { - let doc = mk_doc( - ~"impl int { #[doc = \" a \"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"a")); - } - - #[test] - fn should_execute_op_on_impl_method_desc() { - let doc = mk_doc( - ~"impl int { #[doc = \" a \"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"a")); - } - - #[test] - fn should_execute_op_on_type_brief() { - let doc = mk_doc( - ~"#[doc = \" a \"] type t = int;"); - assert_eq!(doc.cratemod().types()[0].brief(), Some(~"a")); - } - - #[test] - fn should_execute_op_on_type_desc() { - let doc = mk_doc( - ~"#[doc = \" a \"] type t = int;"); - assert_eq!(doc.cratemod().types()[0].desc(), Some(~"a")); - } - - #[test] - fn should_execute_on_item_section_headers() { - let doc = mk_doc( - ~"#[doc = \"\ - # Header \n\ - Body\"]\ - fn a() { }"); - assert!(doc.cratemod().fns()[0].sections()[0].header == ~"Header"); - } - - #[test] - fn should_execute_on_item_section_bodies() { - let doc = mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body \"]\ - fn a() { }"); - assert!(doc.cratemod().fns()[0].sections()[0].body == ~"Body"); - } - - #[test] - fn should_execute_on_trait_method_section_headers() { - let doc = mk_doc( - ~"trait i { -#[doc = \"\ - # Header \n\ - Body\"]\ - fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections[0].header - == ~"Header"); - } - - #[test] - fn should_execute_on_trait_method_section_bodies() { - let doc = mk_doc( - ~"trait i { -#[doc = \"\ - # Header\n\ - Body \"]\ - fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections[0].body == - ~"Body"); - } - - #[test] - fn should_execute_on_impl_method_section_headers() { - let doc = mk_doc( - ~"impl bool { -#[doc = \"\ - # Header \n\ - Body\"]\ - fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections[0].header - == ~"Header"); - } - - #[test] - fn should_execute_on_impl_method_section_bodies() { - let doc = mk_doc( - ~"impl bool { -#[doc = \"\ - # Header\n\ - Body \"]\ - fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections[0].body == - ~"Body"); - } -} diff --git a/src/librustdoc/trim_pass.rs b/src/librustdoc/trim_pass.rs deleted file mode 100644 index aaba0427b62..00000000000 --- a/src/librustdoc/trim_pass.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Pulls a brief description out of a long description. - -If the first paragraph of a long description is short enough then it -is interpreted as the brief description. -*/ - -use pass::Pass; -use text_pass; - -pub fn mk_pass() -> Pass { - text_pass::mk_pass(~"trim", |s| s.trim().to_owned() ) -} - -#[cfg(test)] -mod test { - use astsrv; - use attr_pass; - use doc; - use extract; - use prune_hidden_pass; - use trim_pass::mk_pass; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (prune_hidden_pass::mk_pass().f)(srv.clone(), doc); - (mk_pass().f)(srv.clone(), doc) - } - } - - #[test] - fn should_trim_text() { - use std::option::Some; - - let doc = mk_doc(~"#[doc = \" desc \"] \ - mod m { -}"); - assert_eq!(doc.cratemod().mods()[0].desc(), Some(~"desc")); - } -} diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs deleted file mode 100644 index aa4407af76d..00000000000 --- a/src/librustdoc/tystr_pass.rs +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Pulls type information out of the AST and attaches it to the document - - -use astsrv; -use doc::ItemUtils; -use doc; -use extract::to_str; -use extract; -use fold::Fold; -use fold; -use pass::Pass; - -use syntax::ast; -use syntax::print::pprust; -use syntax::parse::token; -use syntax::ast_map; - -pub fn mk_pass() -> Pass { - Pass { - name: ~"tystr", - f: run - } -} - -pub fn run( - srv: astsrv::Srv, - doc: doc::Doc -) -> doc::Doc { - let fold = Fold { - ctxt: srv.clone(), - fold_fn: fold_fn, - fold_static: fold_static, - fold_enum: fold_enum, - fold_trait: fold_trait, - fold_impl: fold_impl, - fold_type: fold_type, - fold_struct: fold_struct, - .. fold::default_any_fold(srv) - }; - (fold.fold_doc)(&fold, doc) -} - -fn fold_fn( - fold: &fold::Fold, - doc: doc::FnDoc -) -> doc::FnDoc { - - let srv = fold.ctxt.clone(); - - doc::SimpleItemDoc { - sig: get_fn_sig(srv, doc.id()), - .. doc - } -} - -fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> { - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&fn_id) { - ast_map::node_item(@ast::item { - ident: ident, - node: ast::item_fn(ref decl, purity, _, ref tys, _), _ - }, _) => { - Some(pprust::fun_to_str(decl, - purity, - ident, - None, - tys, - token::get_ident_interner())) - } - ast_map::node_foreign_item(@ast::foreign_item { - ident: ident, - node: ast::foreign_item_fn(ref decl, ref tys), _ - }, _, _, _) => { - Some(pprust::fun_to_str(decl, - ast::impure_fn, - ident, - None, - tys, - token::get_ident_interner())) - } - _ => fail!("get_fn_sig: fn_id not bound to a fn item") - } - } -} - -fn fold_static( - fold: &fold::Fold, - doc: doc::StaticDoc -) -> doc::StaticDoc { - let srv = fold.ctxt.clone(); - - doc::SimpleItemDoc { - sig: Some({ - let doc = doc.clone(); - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&doc.id()) { - ast_map::node_item(@ast::item { - node: ast::item_static(ref ty, _, _), _ - }, _) => { - pprust::ty_to_str(ty, extract::interner()) - } - _ => fail!("fold_static: id not bound to a static item") - } - }}), - .. doc - } -} - -fn fold_enum( - fold: &fold::Fold, - doc: doc::EnumDoc -) -> doc::EnumDoc { - let doc_id = doc.id(); - let srv = fold.ctxt.clone(); - - doc::EnumDoc { - variants: do doc.variants.iter().map |variant| { - let sig = { - let variant = (*variant).clone(); - do astsrv::exec(srv.clone()) |ctxt| { - match ctxt.ast_map.get_copy(&doc_id) { - ast_map::node_item(@ast::item { - node: ast::item_enum(ref enum_definition, _), _ - }, _) => { - let ast_variant = - (*do enum_definition.variants.iter().find |v| { - to_str(v.node.name) == variant.name - }.unwrap()).clone(); - - pprust::variant_to_str( - &ast_variant, extract::interner()) - } - _ => fail!("enum variant not bound to an enum item") - } - } - }; - - doc::VariantDoc { - sig: Some(sig), - .. (*variant).clone() - } - }.collect(), - .. doc - } -} - -fn fold_trait( - fold: &fold::Fold, - doc: doc::TraitDoc -) -> doc::TraitDoc { - doc::TraitDoc { - methods: merge_methods(fold.ctxt.clone(), doc.id(), doc.methods.clone()), - .. doc - } -} - -fn merge_methods( - srv: astsrv::Srv, - item_id: doc::AstId, - docs: ~[doc::MethodDoc] -) -> ~[doc::MethodDoc] { - do docs.iter().map |doc| { - doc::MethodDoc { - sig: get_method_sig(srv.clone(), item_id, doc.name.clone()), - .. (*doc).clone() - } - }.collect() -} - -fn get_method_sig( - srv: astsrv::Srv, - item_id: doc::AstId, - method_name: ~str -) -> Option<~str> { - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&item_id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(_, _, ref methods), _ - }, _) => { - match methods.iter().find(|&method| { - match (*method).clone() { - ast::required(ty_m) => to_str(ty_m.ident) == method_name, - ast::provided(m) => to_str(m.ident) == method_name, - } - }) { - Some(method) => { - match (*method).clone() { - ast::required(ty_m) => { - Some(pprust::fun_to_str( - &ty_m.decl, - ty_m.purity, - ty_m.ident, - Some(ty_m.explicit_self.node), - &ty_m.generics, - extract::interner() - )) - } - ast::provided(m) => { - Some(pprust::fun_to_str( - &m.decl, - m.purity, - m.ident, - Some(m.explicit_self.node), - &m.generics, - extract::interner() - )) - } - } - } - _ => fail!("method not found") - } - } - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref methods), _ - }, _) => { - match methods.iter().find(|method| { - to_str(method.ident) == method_name - }) { - Some(method) => { - Some(pprust::fun_to_str( - &method.decl, - method.purity, - method.ident, - Some(method.explicit_self.node), - &method.generics, - extract::interner() - )) - } - None => fail!("method not found") - } - } - _ => fail!("get_method_sig: item ID not bound to trait or impl") - } - } -} - -fn fold_impl( - fold: &fold::Fold, - doc: doc::ImplDoc -) -> doc::ImplDoc { - - let srv = fold.ctxt.clone(); - - let (bounds, trait_types, self_ty) = { - let doc = doc.clone(); - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&doc.id()) { - ast_map::node_item(@ast::item { - node: ast::item_impl(ref generics, ref opt_trait_type, ref self_ty, _), _ - }, _) => { - let bounds = pprust::generics_to_str(generics, extract::interner()); - let bounds = if bounds.is_empty() { None } else { Some(bounds) }; - let trait_types = do opt_trait_type.map_default(~[]) |p| { - ~[pprust::path_to_str(&p.path, extract::interner())] - }; - (bounds, - trait_types, - Some(pprust::ty_to_str( - self_ty, extract::interner()))) - } - _ => fail!("expected impl") - } - } - }; - - doc::ImplDoc { - bounds_str: bounds, - trait_types: trait_types, - self_ty: self_ty, - methods: merge_methods(fold.ctxt.clone(), doc.id(), doc.methods.clone()), - .. doc - } -} - -fn fold_type( - fold: &fold::Fold, - doc: doc::TyDoc -) -> doc::TyDoc { - - let srv = fold.ctxt.clone(); - - doc::SimpleItemDoc { - sig: { - let doc = doc.clone(); - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&doc.id()) { - ast_map::node_item(@ast::item { - ident: ident, - node: ast::item_ty(ref ty, ref params), _ - }, _) => { - Some(fmt!( - "type %s%s = %s", - to_str(ident), - pprust::generics_to_str(params, - extract::interner()), - pprust::ty_to_str(ty, extract::interner()) - )) - } - _ => fail!("expected type") - } - } - }, - .. doc - } -} - -fn fold_struct( - fold: &fold::Fold, - doc: doc::StructDoc -) -> doc::StructDoc { - let srv = fold.ctxt.clone(); - - doc::StructDoc { - sig: { - let doc = doc.clone(); - do astsrv::exec(srv) |ctxt| { - match ctxt.ast_map.get_copy(&doc.id()) { - ast_map::node_item(item, _) => { - let item = strip_struct_extra_stuff(item); - Some(pprust::item_to_str(item, - extract::interner())) - } - _ => fail!("not an item") - } - } - }, - .. doc - } -} - -/// Removes various things from the struct item definition that -/// shouldn't be displayed in the struct signature. Probably there -/// should be a simple pprust::struct_to_str function that does -/// what I actually want -fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item { - let node = match item.node.clone() { - ast::item_struct(def, tys) => ast::item_struct(def, tys), - _ => fail!("not a struct") - }; - - @ast::item { - attrs: ~[], // Remove the attributes - node: node, - .. (*item).clone() - } -} - -#[cfg(test)] -mod test { - - use astsrv; - use doc; - use extract; - use tystr_pass::run; - - fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(source.clone()) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - run(srv.clone(), doc) - } - } - - #[test] - fn should_add_fn_sig() { - let doc = mk_doc(~"fn a() -> int { }"); - assert!(doc.cratemod().fns()[0].sig == Some(~"fn a() -> int")); - } - - #[test] - fn should_add_foreign_fn_sig() { - let doc = mk_doc(~"extern { fn a() -> int; }"); - assert!(doc.cratemod().nmods()[0].fns[0].sig == - Some(~"fn a() -> int")); - } - - #[test] - fn should_add_static_types() { - let doc = mk_doc(~"static a: bool = true;"); - assert!(doc.cratemod().statics()[0].sig == Some(~"bool")); - } - - #[test] - fn should_add_variant_sigs() { - let doc = mk_doc(~"enum a { b(int) }"); - assert!(doc.cratemod().enums()[0].variants[0].sig == - Some(~"b(int)")); - } - - #[test] - fn should_add_trait_method_sigs() { - let doc = mk_doc(~"trait i { fn a(&mut self) -> int; }"); - assert!(doc.cratemod().traits()[0].methods[0].sig - == Some(~"fn a(&mut self) -> int")); - } - - #[test] - fn should_add_impl_bounds() { - let doc = mk_doc(~"impl Option { }"); - assert!(doc.cratemod().impls()[0].bounds_str == Some(~"")); - } - - #[test] - fn should_add_impl_trait_types() { - let doc = mk_doc(~"impl j for int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].trait_types[0] == ~"j"); - } - - #[test] - fn should_not_add_impl_trait_types_if_none() { - let doc = mk_doc(~"impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].trait_types.len() == 0); - } - - #[test] - fn should_add_impl_self_ty() { - let doc = mk_doc(~"impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].self_ty == Some(~"int")); - } - - #[test] - fn should_add_impl_method_sigs() { - let doc = mk_doc(~"impl int { fn a(&self) -> int { fail!() } }"); - assert!(doc.cratemod().impls()[0].methods[0].sig - == Some(~"fn a(&self) -> int")); - } - - #[test] - fn should_add_type_signatures() { - let doc = mk_doc(~"type t = int;"); - assert!(doc.cratemod().types()[0].sig == Some(~"type t = int")); - } - - #[test] - fn should_add_struct_defs() { - let doc = mk_doc(~"struct S { field: () }"); - assert!(doc.cratemod().structs()[0].sig.unwrap().contains( - "struct S {")); - } - - #[test] - fn should_not_serialize_struct_attrs() { - // All we care about are the fields - let doc = mk_doc(~"#[wut] struct S { field: () }"); - assert!(!doc.cratemod().structs()[0].sig.unwrap().contains("wut")); - } -} diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs deleted file mode 100644 index 4c2464f8b34..00000000000 --- a/src/librustdoc/unindent_pass.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Removes the common level of indention from description strings. For -instance, if an entire doc comment is indented 8 spaces we want to -remove those 8 spaces from every line. - -The first line of a string is allowed to be intend less than -subsequent lines in the same paragraph in order to account for -instances where the string containing the doc comment is opened in the -middle of a line, and each of the following lines is indented. -*/ - - -use std::num; -use std::uint; -use pass::Pass; -use text_pass; - -pub fn mk_pass() -> Pass { - text_pass::mk_pass(~"unindent", unindent) -} - -fn unindent(s: &str) -> ~str { - let lines = s.any_line_iter().collect::<~[&str]>(); - let mut saw_first_line = false; - let mut saw_second_line = false; - let min_indent = do lines.iter().fold(uint::max_value) - |min_indent, line| { - - // After we see the first non-whitespace line, look at - // the line we have. If it is not whitespace, and therefore - // part of the first paragraph, then ignore the indentation - // level of the first line - let ignore_previous_indents = - saw_first_line && - !saw_second_line && - !line.is_whitespace(); - - let min_indent = if ignore_previous_indents { - uint::max_value - } else { - min_indent - }; - - if saw_first_line { - saw_second_line = true; - } - - if line.is_whitespace() { - min_indent - } else { - saw_first_line = true; - let mut spaces = 0; - do line.iter().all |char| { - // Only comparing against space because I wouldn't - // know what to do with mixed whitespace chars - if char == ' ' { - spaces += 1; - true - } else { - false - } - }; - num::min(min_indent, spaces) - } - }; - - match lines { - [head, .. tail] => { - let mut unindented = ~[ head.trim() ]; - unindented.push_all(do tail.map |&line| { - if line.is_whitespace() { - line - } else { - assert!(line.len() >= min_indent); - line.slice_from(min_indent) - } - }); - unindented.connect("\n") - } - [] => s.to_owned() - } -} - -#[test] -fn should_unindent() { - let s = ~" line1\n line2"; - let r = unindent(s); - assert_eq!(r, ~"line1\nline2"); -} - -#[test] -fn should_unindent_multiple_paragraphs() { - let s = ~" line1\n\n line2"; - let r = unindent(s); - assert_eq!(r, ~"line1\n\nline2"); -} - -#[test] -fn should_leave_multiple_indent_levels() { - // Line 2 is indented another level beyond the - // base indentation and should be preserved - let s = ~" line1\n\n line2"; - let r = unindent(s); - assert_eq!(r, ~"line1\n\n line2"); -} - -#[test] -fn should_ignore_first_line_indent() { - // Thi first line of the first paragraph may not be indented as - // far due to the way the doc string was written: - // - // #[doc = "Start way over here - // and continue here"] - let s = ~"line1\n line2"; - let r = unindent(s); - assert_eq!(r, ~"line1\nline2"); -} - -#[test] -fn should_not_ignore_first_line_indent_in_a_single_line_para() { - let s = ~"line1\n\n line2"; - let r = unindent(s); - assert_eq!(r, ~"line1\n\n line2"); -} diff --git a/src/rustdoc_ng/visit_ast.rs b/src/librustdoc/visit_ast.rs similarity index 100% rename from src/rustdoc_ng/visit_ast.rs rename to src/librustdoc/visit_ast.rs diff --git a/src/rustdoc_ng/.gitignore b/src/rustdoc_ng/.gitignore deleted file mode 100644 index 62f94a1a44e..00000000000 --- a/src/rustdoc_ng/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.swp -main diff --git a/src/rustdoc_ng/fold.rs b/src/rustdoc_ng/fold.rs deleted file mode 100644 index ae74f4e37c3..00000000000 --- a/src/rustdoc_ng/fold.rs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std; -use clean::*; -use std::iter::Extendable; - -pub trait DocFolder { - fn fold_item(&mut self, item: Item) -> Option { - self.fold_item_recur(item) - } - - /// don't override! - fn fold_item_recur(&mut self, item: Item) -> Option { - 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(this: &mut T, trm: TraitMethod) -> Option { - 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 { - c.module = match std::util::replace(&mut c.module, None) { - Some(module) => self.fold_item(module), None => None - }; - return c; - } -} diff --git a/src/rustdoc_ng/rustdoc_ng.rs b/src/rustdoc_ng/rustdoc_ng.rs deleted file mode 100644 index 968e0fb07c0..00000000000 --- a/src/rustdoc_ng/rustdoc_ng.rs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[link(name = "rustdoc_ng", - vers = "0.8", - uuid = "8c6e4598-1596-4aa5-a24c-b811914bbbc6", - url = "https://github.com/mozilla/rust/tree/master/src/rustdoc_ng")]; - -#[desc = "rustdoc, the Rust documentation extractor"]; -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -extern mod syntax; -extern mod rustc; -extern mod extra; - -use extra::serialize::Encodable; -use extra::time; -use std::cell::Cell; -use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::file::FileInfo; - -pub mod clean; -pub mod core; -pub mod doctree; -pub mod fold; -pub mod html { - pub mod render; - pub mod layout; - pub mod markdown; - pub mod format; -} -pub mod passes; -pub mod plugins; -pub mod visit_ast; - -pub static SCHEMA_VERSION: &'static str = "0.8.0"; - -local_data_key!(pub ctxtkey: @core::DocContext) - -enum OutputFormat { - HTML, JSON -} - -pub fn main() { - main_args(std::os::args()); -} - -pub fn main_args(args: &[~str]) { - use extra::getopts::groups::*; - - let opts = ~[ - optmulti("L", "library-path", "directory to add to crate search path", - "DIR"), - optmulti("", "plugin-path", "directory to load plugins from", "DIR"), - optmulti("", "passes", "space separated list of passes to also run", - "PASSES"), - optmulti("", "plugins", "space separated list of plugins to also load", - "PLUGINS"), - optflag("h", "help", "show this help message"), - optflag("", "nodefaults", "don't run the default passes"), - optopt("o", "output", "where to place the output", "PATH"), - ]; - - let matches = getopts(args.tail(), opts).unwrap(); - - let myusage = || { - println(usage(format!("{} [options] [html|json] ", args[0]), opts)); - }; - - if matches.opt_present("h") || matches.opt_present("help") { - myusage(); - return; - } - - let (format, cratefile) = match matches.free.clone() { - [~"json", crate] => (JSON, crate), - [~"html", crate] => (HTML, crate), - [s, _] => { - println!("Unknown output format: `{}`", s); - myusage(); - exit(1); - } - [_, .._] => { - println!("Expected exactly one crate to process"); - myusage(); - exit(1); - } - _ => { - println!("Expected an output format and then one crate"); - myusage(); - exit(1); - } - }; - - // First, parse the crate and extract all relevant information. - let libs = Cell::new(matches.opt_strs("L").map(|s| Path(*s))); - let cr = Cell::new(Path(cratefile)); - info2!("starting to run rustc"); - let crate = do std::task::try { - let cr = cr.take(); - core::run_core(libs.take(), &cr) - }.unwrap(); - info2!("finished with rustc"); - - // Process all of the crate attributes, extracting plugin metadata along - // with the passes which we are supposed to run. - let mut default_passes = !matches.opt_present("nodefaults"); - let mut passes = matches.opt_strs("passes"); - let mut plugins = matches.opt_strs("plugins"); - match crate.module.get_ref().doc_list() { - Some(nested) => { - for inner in nested.iter() { - match *inner { - clean::Word(~"no_default_passes") => { - default_passes = false; - } - clean::NameValue(~"passes", ref value) => { - for pass in value.word_iter() { - passes.push(pass.to_owned()); - } - } - clean::NameValue(~"plugins", ref value) => { - for p in value.word_iter() { - plugins.push(p.to_owned()); - } - } - _ => {} - } - } - } - None => {} - } - if default_passes { - passes.unshift(~"collapse-docs"); - passes.unshift(~"unindent-comments"); - } - - // Load all plugins/passes into a PluginManager - let mut pm = plugins::PluginManager::new(Path("/tmp/rustdoc_ng/plugins")); - for pass in passes.iter() { - let plugin = match pass.as_slice() { - "strip-hidden" => passes::strip_hidden, - "unindent-comments" => passes::unindent_comments, - "collapse-docs" => passes::collapse_docs, - "collapse-privacy" => passes::collapse_privacy, - s => { error!("unknown pass %s, skipping", s); loop }, - }; - pm.add_plugin(plugin); - } - info2!("loading plugins..."); - for pname in plugins.move_iter() { - pm.load_plugin(pname); - } - - // Run everything! - info2!("Executing passes/plugins"); - let (crate, res) = pm.run_plugins(crate); - - info2!("going to format"); - let started = time::precise_time_ns(); - let output = matches.opt_str("o").map(|s| Path(*s)); - match format { - HTML => { html::render::run(crate, output.unwrap_or(Path("doc"))) } - JSON => { jsonify(crate, res, output.unwrap_or(Path("doc.json"))) } - } - let ended = time::precise_time_ns(); - info2!("Took {:.03f}s", (ended as f64 - started as f64) / 1000000000f64); -} - -fn jsonify(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) { - // { - // "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 plugins_json = ~res.move_iter().filter_map(|opt| opt).collect(); - - // FIXME #8335: 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)); - - let mut file = dst.open_writer(io::Create).unwrap(); - let output = extra::json::Object(json).to_str(); - file.write(output.as_bytes()); -} - -fn exit(status: int) -> ! { - #[fixed_stack_segment]; #[inline(never)]; - use std::libc; - unsafe { libc::exit(status as libc::c_int) } -}