From a6c33f1349c92dd4748e5f856251db094f5e0ee0 Mon Sep 17 00:00:00 2001 From: Ryan Culpepper Date: Fri, 30 Sep 2011 20:30:53 -0600 Subject: [PATCH] added functions, docs for show-dependencies original commit: 994c1f202c593dd7b7f543ca674e23589ff21dc5 --- .../analysis/show-dependencies.rkt | 57 ++++++---- collects/macro-debugger/macro-debugger.scrbl | 102 ++++++++++++++++-- 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 index cb84713..e5033a8 100644 --- 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 (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 " + [("-x" "--exclude") exclude "Exclude modules reachable from " (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 index cf941fa..60fbd39 100644 --- 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)) +] +}