commit a6c33f1349c92dd4748e5f856251db094f5e0ee0
parent bfef6dfb5aa32774d9628b806f336e02f4aa47a1
Author: Ryan Culpepper <ryanc@racket-lang.org>
Date: Fri, 30 Sep 2011 20:30:53 -0600
added functions, docs for show-dependencies
original commit: 994c1f202c593dd7b7f543ca674e23589ff21dc5
Diffstat:
2 files changed, 127 insertions(+), 32 deletions(-)
diff --git a/collects/macro-debugger/analysis/show-dependencies.rkt b/collects/macro-debugger/analysis/show-dependencies.rkt
@@ -1,9 +1,11 @@
#lang racket/base
(require racket/cmdline
"private/util.rkt")
-(provide main)
+(provide get-dependencies
+ show-dependencies
+ main)
-(define (get-dependencies-table #:include? include? . ms)
+(define (get-dependencies-table #:include? include? ms)
(define visited (make-hash)) ;; resolved-module-path => (listof mpi-list)
(define (loop m ctx)
(let* ([resolved (module-path-index-resolve m)]
@@ -23,6 +25,7 @@
(loop (module-path-index-join m #f) null))
visited)
+;; table->dependencies : table -> (listof (list module-path (listof module-path)))
(define (table->dependencies visited)
(let* ([unsorted
(for/list ([(key mpi-lists) (in-hash visited)])
@@ -47,6 +50,31 @@
;; obviously, we don't care that much about performance in this case
(string<? (format "~s" A) (format "~s" B))]))
+;; get-dependencies : module-path ... #:excludse (listof module-path)
+;; -> (listof (list module-path (listof module-path)))
+(define (get-dependencies #:exclude [exclusions null]
+ . module-paths)
+ (let* ([table
+ (get-dependencies-table #:include? #f module-paths)]
+ [exclude-table
+ (get-dependencies-table #:include? #t exclusions)])
+ (for ([key (in-hash-keys exclude-table)])
+ (hash-remove! table key))
+ (table->dependencies table)))
+
+(define (show-dependencies #:exclude [exclusions null]
+ #:show-context? [context? #f]
+ . module-paths)
+ (for ([dep (in-list (apply get-dependencies #:exclude exclusions module-paths))])
+ (let ([mod (car dep)]
+ [direct-requirers (cadr dep)])
+ (printf "~s" mod)
+ (when context?
+ (printf " <- ~s" direct-requirers))
+ (newline))))
+
+;; ====
+
(define (main . argv)
(define mode 'auto)
(define context? #f)
@@ -60,9 +88,9 @@
(set! mode 'file)]
[("-m" "--module-path") "Interpret arguments as module-paths"
(set! mode 'module-path)]
- [("--minus") exclude "Exclude modules reachable from <exclude>"
+ [("-x" "--exclude") exclude "Exclude modules reachable from <exclude>"
(set! exclusions (cons exclude exclusions))]
- [("-b") "Same as --minus racket/base"
+ [("-b") "Same as --exclude racket/base"
(set! exclusions (cons 'racket/base exclusions))]
#:args module-path
(let ()
@@ -77,23 +105,10 @@
((module-path)
(read (open-input-string x))))]
[else x]))
- (let* ([table
- (apply get-dependencies-table
- #:include? #f
- (map ->modpath module-path))]
- [exclude-table
- (apply get-dependencies-table
- #:include? #t
- (map ->modpath exclusions))])
- (for ([key (in-hash-keys exclude-table)])
- (hash-remove! table key))
- (for ([dep (in-list (table->dependencies table))])
- (let ([mod (car dep)]
- [direct-requirers (cadr dep)])
- (printf "~s" mod)
- (when context?
- (printf " <- ~s" direct-requirers))
- (newline)))))))
+ (apply show-dependencies
+ #:exclude (map ->modpath exclusions)
+ #:show-context? context?
+ (map ->modpath module-path)))))
#|
diff --git a/collects/macro-debugger/macro-debugger.scrbl b/collects/macro-debugger/macro-debugger.scrbl
@@ -3,20 +3,25 @@
scribble/struct
scribble/decode
scribble/eval
- (for-label scheme/base
+ (for-label racket/base
+ racket/contract/base
+ racket/runtime-path
macro-debugger/expand
macro-debugger/emit
macro-debugger/stepper
macro-debugger/stepper-text
macro-debugger/syntax-browser
- macro-debugger/analysis/check-requires
- (rename-in scheme (free-identifier=? module-identifier=?))))
+ (except-in macro-debugger/analysis/check-requires main)
+ (except-in macro-debugger/analysis/show-dependencies main)))
@(define the-eval
(let ([the-eval (make-base-eval)])
- (the-eval '(require macro-debugger/expand
+ (the-eval '(require racket/pretty
+ macro-debugger/expand
macro-debugger/stepper-text
- macro-debugger/analysis/check-requires))
+ (except-in macro-debugger/analysis/check-requires main)
+ (except-in macro-debugger/analysis/show-dependencies main)))
+ (the-eval '(current-print pretty-print-handler))
the-eval))
@(define (defoutput proto . text)
@@ -344,15 +349,17 @@ racket -lm macro-debugger/analysis/check-requires \
collects/syntax/*.rkt
racket -lm macro-debugger/analysis/check-requires -- -kbu \
- collects/syntax/*.rkt
+ openssl
}
-See @racket[check-requires] for a description of the output format,
-known limitations in the script's recommendations, etc.
+Each argument is interpreted as a file path if it exists; otherwise,
+it is interpreted as a module path. See @racket[check-requires] for a
+description of the output format, known limitations in the script's
+recommendations, etc.
@defproc[(check-requires [module-to-analyze module-path?]
- [#:show-keep? show-keep? boolean? #f]
- [#:show-bypass? show-bypass? boolean? #f]
+ [#:show-keep? show-keep? boolean? #t]
+ [#:show-bypass? show-bypass? boolean? #t]
[#:show-drop? show-drop? boolean? #t]
[#:show-uses? show-uses? boolean? #f])
void?]{
@@ -465,7 +472,7 @@ typical reasons for such bad suggestions:
@examples[#:eval the-eval
(check-requires 'framework)
-(check-requires 'syntax/stx #:show-uses? #t)
+(check-requires 'openssl #:show-uses? #t)
]
}
@@ -487,3 +494,76 @@ returns one element per (non-label) require in the following format:
(show-requires 'framework)
]
}
+
+
+@section{Showing Module Dependencies}
+@section-index["show-dependencies"]
+
+@defmodule[macro-debugger/analysis/show-dependencies]
+
+The @racketmodname[macro-debugger/analysis/show-dependencies] module
+can be run as a command-line script. For example (from racket root
+directory):
+
+@verbatim{
+racket -lm macro-debugger/analysis/show-dependencies -- -bc \
+ collects/openssl/main.rkt
+
+racket -lm macro-debugger/analysis/show-dependencies -- -c \
+ --exclude racket \
+ openssl
+}
+
+Each argument is interpreted as a file path if it exists; otherwise it
+is interpreted as a module path. See @racket[show-dependencies] for a
+description of the output format.
+
+@defproc[(show-dependencies [root module-path?] ...
+ [#:exclude exclusions
+ (listof module-path?) null]
+ [#:show-context? show-context? boolean? #f])
+ void?]{
+
+Computes the set of modules transitively required by the @racket[root]
+module(s). A @racket[root] module is included in the output
+only if it is a dependency of another @racket[root] module. The
+computed dependencies do not include modules reached through
+@racket[dynamic-require] or referenced by
+@racket[define-runtime-module-path-index] but do include modules
+referenced by @racket[define-runtime-module-path] (since that
+implicitly creates a @racket[for-label] dependency).
+
+Dependencies are printed, one per line, in the following format:
+
+@defoutput[@tt{@racket[_dep-module] [<- @racket[(_direct-dependent ...)]]}]{
+
+Indicates that @racket[_dep-module] is transitively required by one or
+more @racket[root] modules. If @racket[show-context?] is true, then
+the @racket[_direct-dependent]s are shown; they are the modules
+reachable from (and including) the @racket[root] modules that directly
+require @racket[_dep-module].
+}
+
+The dependencies are trimmed by removing any module reachable from (or
+equal to) a module in @racket[exclusions].
+
+@examples[#:eval the-eval
+(show-dependencies 'openssl
+ #:show-context? #t
+ #:exclude (list 'racket))
+]
+}
+
+@defproc[(get-dependencies [root module-path?] ...
+ [#:exclude exclusions
+ (listof module-path?) null])
+ (listof (list module-path? (listof module-path?)))]{
+
+Like @racket[show-dependencies], but returns a list instead of
+producing output. Each element of the list is a list containing a
+module path and the module paths of its immediate dependents.
+
+@examples[#:eval the-eval
+(get-dependencies 'openssl #:exclude (list 'racket))
+]
+}