diff --git a/pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-test.rkt b/pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-test.rkt index e90c8461b0..1edd450f1c 100644 --- a/pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-test.rkt +++ b/pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-test.rkt @@ -1057,8 +1057,7 @@ ("red" imported) (")" default-color)) '(((26 29) (47 50)) - ((6 17) (19 25))) - #:extra-info? #t) + ((6 17) (19 25)))) (build-test "#lang racket/base\n(require '#%kernel)\npair?" '(("#lang racket/base\n(" default-color) @@ -1689,24 +1688,6 @@ (define (click-check-syntax-button drs extra-info?) (test:run-one (lambda () (send drs syncheck:button-callback #:print-extra-info? extra-info?)))) -(let () - (define ns (make-base-namespace)) - (define stx - (parameterize ([current-namespace ns]) - (expand #'(module m racket/base - (define red 1) - (module+ tests red))))) - (define ids '()) - (let loop ([stx stx]) - (cond - [(pair? stx) (loop (car stx)) (loop (cdr stx))] - [(identifier? stx) - (when (equal? (syntax-e stx) 'red) (set! ids (cons stx ids)))] - [(syntax? stx) (loop (syntax-e stx))])) - (for ([x (in-list ids)]) - (for ([y (in-list ids)]) - (printf " ~s\n ~s\n ~s\n\n" x y (free-identifier=? x y))))) - (main) (module+ test diff --git a/pkgs/drracket-pkgs/drracket-tool-doc/info.rkt b/pkgs/drracket-pkgs/drracket-tool-doc/info.rkt new file mode 100644 index 0000000000..9b0b9e6934 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-doc/info.rkt @@ -0,0 +1,12 @@ +#lang info + +(define collection 'multi) + +(define deps '("base" "scribble-lib" "drracket-tool-lib")) +(define build-deps '("racket-doc")) + +(define pkg-desc "Docs for the programmatic interface to some IDE tools that DrRacket supports") + +(define pkg-authors '(robby)) + +(define version "1.0") diff --git a/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/drracket-tools.scrbl b/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/drracket-tools.scrbl new file mode 100644 index 0000000000..cbcf72d2c7 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/drracket-tools.scrbl @@ -0,0 +1,298 @@ +#lang scribble/manual +@(require scribble/eval + (for-label drracket/check-syntax + racket)) + +@title{DrRacket Tools} + +This manual describes portions of DrRacket's functionality +that are exposed via Racket APIs to be used with other editors. + +@section{Accessing Check Syntax Programmatically} + +@defmodule[drracket/check-syntax] + +@defproc[(make-traversal [namespace namespace?] + [path (or/c #f path-string?)]) + (values (->* (syntax?) + ((-> any/c void?)) + void?) + (-> void?))]{ + This function creates some local state about a traversal of syntax objects + and returns two functions. The first one should be called with each of the + (fully expanded) syntax objects that make up a program (there will be only + one if the program is a module) and then the second one should be called to + indicate there are no more. + + The optional argument to the first function is ignored. + It is left there for historical reasons. In the past it + was called for each sequence + of binding identifiers encountered in @racket[define-values], @racket[define-syntaxes], + and @racket[define-values-for-syntax]. + + During the dynamic extent of the call to the two result functions, the value + of the @racket[current-annotations] parameter is consulted and various + methods are invoked in the corresponding object (if any), to indicate + what has been found in the syntax object. These methods will only be called + if the syntax objects have source locations. +} + +@defparam[current-annotations ca (or/c #f (is-a?/c syncheck-annotations<%>))]{ + The methods of the value of this parameter are invoked by the functions returned + from @racket[make-traversal]. +} + +@defparam[current-max-to-send-at-once m (or/c +inf.0 (and/c exact-integer? (>=/c 2)))]{ + No longer used. +} + +@definterface[syncheck-annotations<%> ()]{ + + Classes implementing this interface are + accceptors of information about a traversal + of syntax objects. See @racket[make-traversal]. + + Do not implement this interface directly, as it + is liable to change without warning. Instead, use + the @racket[annotations-mixin] and override + the methods you're interested in. The + @racket[annotations-mixin] will keep in sync + with this interface, providing methods that + ignore their arguments. + + @defmethod[(syncheck:find-source-object [stx syntax?]) (or/c #f (not/c #f))]{ + This should return @racket[#f] if the source of this syntax object is + uninteresting for annotations (if, for example, the only interesting + annotations are those in the original file and this is a syntax object + introduced by a macro and thus has a source location from some other file). + + Otherwise, it should return some (non-@racket[#f]) + value that will then be passed to one of the other methods below as + a @racket[_source-obj] argument. + } + + @defmethod[(syncheck:add-background-color [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [end exact-nonnegative-integer?] + [color string?]) + void?]{ + Called to indicate that the color @racket[color] should be drawn on the background of + the given range in the editor, when the mouse moves over it. This method is typically + called in conjuction with some other method that provides some other annotation + on the source. + } + @defmethod[(syncheck:add-require-open-menu [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [end exact-nonnegative-integer?] + [file path-string?]) + void?]{ + Called to indicate that there is a @racket[require] at the location from + @racket[start] to @racket[end], + and that it corresponds to @racket[file]. Check Syntax adds a popup menu. + } + + @defmethod[(syncheck:add-docs-menu [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [end exact-nonnegative-integer?] + [id symbol?] + [label any/c] + [path any/c] + [tag any/c]) + void?]{ + Called to indicate that there is something that has documentation between the range + @racket[start] and @racket[end]. The documented identifier's name is given by @racket[id] + and the docs are found in the html file @racket[path] at the html tag @racket[tag]. + The @racket[label] argument describes the binding for use in the menu item (although it may + be longer than 200 characters). + } + + @defmethod[(syncheck:add-id-set [all-ids (listof (list/c (not/c #f) + exact-nonnegative-integer? + exact-nonnegative-integer?))] + [new-name-interferes? (-> symbol boolean?)]) + void?]{This method is no longer called by Check Syntax. It is here + for backwards compatibility only. The information it provided + must now be synthesized from the information supplied to + @method[syncheck-annotations<%> syncheck:add-arrow/name-dup].} + + @defmethod[(syncheck:add-arrow [start-source-obj (not/c #f)] + [start-left exact-nonnegative-integer?] + [start-right exact-nonnegative-integer?] + [end-source-obj (not/c #f)] + [end-left exact-nonnegative-integer?] + [end-right exact-nonnegative-integer?] + [actual? boolean?] + [phase-level (or/c exact-nonnegative-integer? #f)]) + void?]{ + This function is not called directly anymore by Check Syntax. Instead + @method[syncheck-annotations<%> syncheck:add-arrow/name-dup] is. + + This method is invoked by the default implementation of + @racket[_syncheck:add-arrow/name-dup] in + @racket[annotations-mixin]. + } + @defmethod[(syncheck:add-arrow/name-dup [start-source-obj (not/c #f)] + [start-left exact-nonnegative-integer?] + [start-right exact-nonnegative-integer?] + [end-source-obj (not/c #f)] + [end-left exact-nonnegative-integer?] + [end-right exact-nonnegative-integer?] + [actual? boolean?] + [phase-level (or/c exact-nonnegative-integer? #f)] + [require-arrow? boolean?] + [name-dup? (-> string? boolean?)]) + void?]{ + Called to indicate that there should be an arrow between the locations described by the first + six arguments. + + The @racket[phase-level] argument indicates the phase of the binding and the + @racket[actual?] argument indicates if the binding is a real one, or a predicted one from + a syntax template (predicted bindings are drawn with question marks in Check Syntax). + + The @racket[require-arrow?] argument indicates if this arrow points from + an imported identifier to its corresponding @racket[require]. + + The @racket[name-dup?] predicate returns @racket[#t] + in case that this variable (either the start or end), when replaced with the given string, would + shadow some other binding (or otherwise interfere with the binding structure of the program at + the time the program was expanded). + } + @defmethod[(syncheck:add-tail-arrow [from-source-obj (not/c #f)] + [from-pos exact-nonnegative-integer?] + [to-source-obj (not/c #f)] + [to-pos exact-nonnegative-integer?]) + void?]{ + Called to indicate that there are two expressions, beginning at + @racket[from-pos] and @racket[to-pos] + that are in tail position with respect to each other. + } + @defmethod[(syncheck:add-mouse-over-status [source-obj (not/c #f)] + [pos-left exact-nonnegative-integer?] + [pos-right exact-nonnegative-integer?] + [str string?]) + void?]{ + Called to indicate that the message in @racket[str] should be shown when the mouse + passes over the given position. + } + @defmethod[(syncheck:add-jump-to-definition [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [end exact-nonnegative-integer?] + [id any/c] + [filename path-string?] + [submods (listof symbol?)]) + void?]{ + Called to indicate that there is some identifier at the given location (named @racket[id]) that + is defined in the @racket[submods] of the file @racket[filename] (where an empty list in + @racket[submods] means that the identifier is defined at the top-level module). + } + + @defmethod[(syncheck:add-definition-target [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [finish exact-nonnegative-integer?] + [style-name any/c]) void?]{ + + } + + @defmethod[(syncheck:color-range [source-obj (not/c #f)] + [start exact-nonnegative-integer?] + [finish exact-nonnegative-integer?] + [style-name any/c] + [mode any/c]) + void?]{ + Called to indicate that the given location should be colored according to the + style @racket[style-name] when in @racket[mode]. The mode either indicates regular + check syntax or is used indicate blame for potential contract violations + (and still experimental). + } + @defmethod[(syncheck:add-rename-menu [id symbol?] + [all-ids (listof (list/c (not/c #f) + exact-nonnegative-integer? + exact-nonnegative-integer?))] + [new-name-interferes? (-> symbol boolean?)]) + void?]{ + This method is listed only for backwards compatibility. It is not called + by Check Syntax anymore. + } +} + +@(define syncheck-example-eval (make-base-eval)) + +@defmixin[annotations-mixin () (syncheck-annotations<%>)]{ + Supplies all of the methods in @racket[syncheck-annotations<%>] + with default behavior. Be sure to use this mixin to future-proof + your code and then override the methods you're interested in. + + By default: + @itemlist[@item{The @method[syncheck-annotations<%> syncheck:find-source-object] + method ignores its arguments and returns @racket[#f];} + @item{the @method[syncheck-annotations<%> syncheck:add-arrow/name-dup] method drops the + @racket[_require-arrow?] and @racket[_name-dup?] arguments and calls + @method[syncheck-annotations<%> syncheck:add-arrow]; and} + @item{all of the other methods ignore their arguments and return @racket[(void)].}] + + Here is an example showing how use this library to extract all + of the arrows that Check Syntax would draw from various + expressions. One subtle point: arrows are only included when + the corresponding identifiers are @racket[syntax-original?]; + the code below manages this by copying the properties from + an identifier that is @racket[syntax-original?] in the + call to @racket[datum->syntax]. + @interaction[#:eval + syncheck-example-eval + (require drracket/check-syntax racket/class) + (define arrows-collector% + (class (annotations-mixin object%) + (super-new) + (define/override (syncheck:find-source-object stx) + stx) + (define/override (syncheck:add-arrow/name-dup + start-source-obj start-left start-right + end-source-obj end-left end-right + actual? phase-level require-arrow? name-dup?) + (set! arrows + (cons (list start-source-obj end-source-obj) + arrows))) + (define arrows '()) + (define/public (get-collected-arrows) arrows))) + (define (arrows form) + (define base-namespace (make-base-namespace)) + (define-values (add-syntax done) + (make-traversal base-namespace #f)) + (define collector (new arrows-collector%)) + (parameterize ([current-annotations collector] + [current-namespace base-namespace]) + (add-syntax (expand form)) + (done)) + (send collector get-collected-arrows)) + (define (make-id name pos orig?) + (datum->syntax + #f + name + (list #f #f #f pos (string-length (symbol->string name))) + (and orig? #'is-orig))) + (arrows `(λ (,(make-id 'x 1 #t)) ,(make-id 'x 2 #t))) + (arrows `(λ (x) x)) + (arrows `(λ (,(make-id 'x 1 #f)) ,(make-id 'x 2 #t))) + (arrows `(λ (,(make-id 'x 1 #t)) x))] +} + +@(close-eval syncheck-example-eval) + +@(define-syntax-rule + (syncheck-method-id x ...) + (begin @defidform[x]{Bound to an identifier created with + @racket[define-local-member-name] + that is used in @racket[syncheck-annotations<%>].} + ...)) +@syncheck-method-id[syncheck:find-source-object + syncheck:add-background-color + syncheck:add-require-open-menu + syncheck:add-docs-menu + syncheck:add-rename-menu + syncheck:add-arrow + syncheck:add-arrow/name-dup + syncheck:add-tail-arrow + syncheck:add-mouse-over-status + syncheck:add-jump-to-definition + syncheck:add-id-set + syncheck:color-range] diff --git a/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/info.rkt b/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/info.rkt new file mode 100644 index 0000000000..1c26f80a64 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-doc/scribblings/drracket-tools/info.rkt @@ -0,0 +1,3 @@ +#lang info + +(define scribblings '(("drracket-tools.scrbl" (multi-page) (tool -200)))) diff --git a/pkgs/drracket-pkgs/drracket/drracket/check-syntax.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/check-syntax.rkt similarity index 90% rename from pkgs/drracket-pkgs/drracket/drracket/check-syntax.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/check-syntax.rkt index 25c42bb359..076d4d6903 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/check-syntax.rkt +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/check-syntax.rkt @@ -2,8 +2,8 @@ (require racket/contract racket/class "private/syncheck/traversals.rkt" - "private/syncheck/intf.rkt" - "private/syncheck/local-member-names.rkt") + "private/syncheck/syncheck-intf.rkt" + "private/syncheck/syncheck-local-member-names.rkt") (provide/contract [make-traversal @@ -36,6 +36,3 @@ syncheck:add-mouse-over-status syncheck:add-jump-to-definition syncheck:color-range) - - - diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/annotate.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/annotate.rkt similarity index 96% rename from pkgs/drracket-pkgs/drracket/drracket/private/syncheck/annotate.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/annotate.rkt index a0f70d0d10..987285218c 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/annotate.rkt +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/annotate.rkt @@ -1,7 +1,7 @@ #lang racket/base (require racket/class - "intf.rkt" - "local-member-names.rkt") + "syncheck-intf.rkt" + "syncheck-local-member-names.rkt") (provide color color-range find-source-editor find-source-editor/defs diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/colors.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/colors.rkt similarity index 100% rename from pkgs/drracket-pkgs/drracket/drracket/private/syncheck/colors.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/colors.rkt diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/contract-traversal.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/contract-traversal.rkt similarity index 99% rename from pkgs/drracket-pkgs/drracket/drracket/private/syncheck/contract-traversal.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/contract-traversal.rkt index e0cd2176b2..40dd4e024f 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/contract-traversal.rkt +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/contract-traversal.rkt @@ -1,6 +1,6 @@ #lang racket/base -(require "intf.rkt" - "local-member-names.rkt" +(require "syncheck-intf.rkt" + "syncheck-local-member-names.rkt" "annotate.rkt" "colors.rkt" syntax/boundmap diff --git a/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-intf.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-intf.rkt new file mode 100644 index 0000000000..1e03ec8372 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-intf.rkt @@ -0,0 +1,60 @@ +#lang racket/base +(require racket/class + "syncheck-local-member-names.rkt") + +(define syncheck-annotations<%> + (interface () + syncheck:find-source-object + syncheck:add-background-color + syncheck:add-require-open-menu + syncheck:add-docs-menu + syncheck:add-id-set + syncheck:add-arrow + syncheck:add-arrow/name-dup + syncheck:add-tail-arrow + syncheck:add-mouse-over-status + syncheck:add-jump-to-definition + syncheck:add-definition-target + syncheck:color-range + + syncheck:add-rename-menu)) + +;; use this to communicate the frame being +;; syntax checked w/out having to add new +;; parameters to all of the functions +(define current-annotations (make-parameter #f)) + +(define annotations-mixin + (mixin () (syncheck-annotations<%>) + (define/public (syncheck:find-source-object stx) #f) + (define/public (syncheck:add-background-color source start end color) (void)) + (define/public (syncheck:add-require-open-menu source start end key) (void)) + (define/public (syncheck:add-id-set all-ids new-name-intereferes?) (void)) + (define/public (syncheck:add-rename-menu sym all-ids new-name-intereferes?) (void)) + (define/public (syncheck:add-docs-menu text start-pos end-pos + key + the-label + path + definition-tag + tag) + (void)) + (define/public (syncheck:add-arrow start-text start-pos-left start-pos-right + end-text end-pos-left end-pos-right + actual? level) + (void)) + (define/public (syncheck:add-arrow/name-dup start-text start-pos-left start-pos-right + end-text end-pos-left end-pos-right + actual? level require-arrow? name-dup?) + (syncheck:add-arrow start-text start-pos-left start-pos-right + end-text end-pos-left end-pos-right + actual? level)) + (define/public (syncheck:add-tail-arrow from-text from-pos to-text to-pos) (void)) + (define/public (syncheck:add-mouse-over-status text pos-left pos-right str) (void)) + (define/public (syncheck:add-jump-to-definition text start end id filename submods) (void)) + (define/public (syncheck:add-definition-target source pos-left pos-right id mods) (void)) + (define/public (syncheck:color-range source start finish style-name) (void)) + (super-new))) + +(provide syncheck-annotations<%> + current-annotations + annotations-mixin) diff --git a/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-local-member-names.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-local-member-names.rkt new file mode 100644 index 0000000000..57a4cae8bb --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/syncheck-local-member-names.rkt @@ -0,0 +1,17 @@ +#lang racket/base +(require racket/class) +(provide (all-defined-out)) + +(define-local-member-name + syncheck:find-source-object + syncheck:add-background-color + syncheck:add-docs-menu + syncheck:color-range + syncheck:add-require-open-menu + syncheck:add-id-set + syncheck:add-arrow + syncheck:add-arrow/name-dup + syncheck:add-rename-menu + syncheck:add-tail-arrow + syncheck:add-mouse-over-status + syncheck:add-jump-to-definition) diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/traversals.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt similarity index 99% rename from pkgs/drracket-pkgs/drracket/drracket/private/syncheck/traversals.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt index 5537220046..3c18612a82 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/traversals.rkt +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt @@ -1,8 +1,8 @@ #lang racket/base (require "colors.rkt" - "intf.rkt" - "local-member-names.rkt" + "syncheck-intf.rkt" + "syncheck-local-member-names.rkt" "annotate.rkt" "contract-traversal.rkt" "xref.rkt" @@ -875,7 +875,6 @@ (when (pair? val) (define start (car val)) (define end (cdr val)) - (define (get-str) (send (list-ref key 0) get-text (list-ref key 1) (list-ref key 2))) (define (show-starts) (add-mouse-over/loc (list-ref key 0) (list-ref key 1) (list-ref key 2) (cond diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/xref.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/xref.rkt similarity index 100% rename from pkgs/drracket-pkgs/drracket/drracket/private/syncheck/xref.rkt rename to pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/xref.rkt diff --git a/pkgs/drracket-pkgs/drracket-tool-lib/info.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/info.rkt new file mode 100644 index 0000000000..9f496419de --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-lib/info.rkt @@ -0,0 +1,16 @@ +#lang info + +(define collection 'multi) + +(define deps '("base" + "scribble-lib" + "string-constants-lib" + "scribble-lib" + "racket-index")) +(define build-deps '("at-exp-lib")) + +(define pkg-desc "Code implementing programmatic interfaces to some IDE tools that DrRacket supports") + +(define pkg-authors '(robby)) + +(define version "1.0") diff --git a/pkgs/drracket-pkgs/drracket-tool-test/info.rkt b/pkgs/drracket-pkgs/drracket-tool-test/info.rkt new file mode 100644 index 0000000000..a4582c42b1 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool-test/info.rkt @@ -0,0 +1,14 @@ +#lang info + +(define collection 'multi) + +(define deps '("base" + "rackunit-lib" + "drracket-tool-lib")) +(define build-deps '()) + +(define pkg-desc "Tests for IDE tools that DrRacket supports") + +(define pkg-authors '(robby)) + +(define version "1.0") diff --git a/pkgs/drracket-pkgs/drracket-test/tests/check-syntax/contract-check-syntax.rkt b/pkgs/drracket-pkgs/drracket-tool-test/tests/check-syntax/contract-check-syntax.rkt similarity index 100% rename from pkgs/drracket-pkgs/drracket-test/tests/check-syntax/contract-check-syntax.rkt rename to pkgs/drracket-pkgs/drracket-tool-test/tests/check-syntax/contract-check-syntax.rkt diff --git a/pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-direct.rkt b/pkgs/drracket-pkgs/drracket-tool-test/tests/check-syntax/syncheck-direct.rkt similarity index 100% rename from pkgs/drracket-pkgs/drracket-test/tests/drracket/syncheck-direct.rkt rename to pkgs/drracket-pkgs/drracket-tool-test/tests/check-syntax/syncheck-direct.rkt diff --git a/pkgs/drracket-pkgs/drracket-tool/info.rkt b/pkgs/drracket-pkgs/drracket-tool/info.rkt new file mode 100644 index 0000000000..983e290dc4 --- /dev/null +++ b/pkgs/drracket-pkgs/drracket-tool/info.rkt @@ -0,0 +1,12 @@ +#lang info + +(define collection 'multi) + +(define deps '("drracket-tool-lib" + "drracket-tool-doc")) +(define implies '("drracket-tool-lib" + "drracket-tool-doc")) + +(define pkg-desc "Programmatic interface to some IDE tools that DrRacket supports") + +(define pkg-authors '(robby)) diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/gui.rkt b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/gui.rkt index 66b8aada68..8ae86fba5e 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/gui.rkt +++ b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/gui.rkt @@ -43,11 +43,12 @@ If the namespace does not, they are colored the unbound color. "../../private/eval-helpers-and-pref-init.rkt" "intf.rkt" "local-member-names.rkt" - "colors.rkt" - "traversals.rkt" - "annotate.rkt" "../tooltip.rkt" "blueboxes-gui.rkt" + drracket/private/syncheck/syncheck-intf + drracket/private/syncheck/colors + drracket/private/syncheck/traversals + drracket/private/syncheck/annotate framework/private/logging-timer) (provide tool@) diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/intf.rkt b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/intf.rkt index 76900917b7..2028e8acb6 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/intf.rkt +++ b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/intf.rkt @@ -1,24 +1,9 @@ #lang racket/base -(require racket/class +(provide syncheck-text<%>) +(require racket/class + drracket/private/syncheck/syncheck-intf "local-member-names.rkt") -(define syncheck-annotations<%> - (interface () - syncheck:find-source-object - syncheck:add-background-color - syncheck:add-require-open-menu - syncheck:add-docs-menu - syncheck:add-id-set - syncheck:add-arrow - syncheck:add-arrow/name-dup - syncheck:add-tail-arrow - syncheck:add-mouse-over-status - syncheck:add-jump-to-definition - syncheck:add-definition-target - syncheck:color-range - - syncheck:add-rename-menu)) - (define syncheck-text<%> (interface (syncheck-annotations<%>) syncheck:init-arrows @@ -29,39 +14,4 @@ syncheck:jump-to-binding-occurrence syncheck:jump-to-definition syncheck:rename-identifier - syncheck:tack/untack-arrows)) - -;; use this to communicate the frame being -;; syntax checked w/out having to add new -;; parameters to all of the functions -(define current-annotations (make-parameter #f)) - -(define annotations-mixin - (mixin () (syncheck-annotations<%>) - (define/public (syncheck:find-source-object stx) #f) - (define/public (syncheck:add-background-color source start end color) (void)) - (define/public (syncheck:add-require-open-menu source start end key) (void)) - (define/public (syncheck:add-id-set all-ids new-name-intereferes?) (void)) - (define/public (syncheck:add-rename-menu sym all-ids new-name-intereferes?) (void)) - (define/public (syncheck:add-docs-menu text start-pos end-pos key the-label path definition-tag tag) (void)) - (define/public (syncheck:add-arrow start-text start-pos-left start-pos-right - end-text end-pos-left end-pos-right - actual? level) - (void)) - (define/public (syncheck:add-arrow/name-dup start-text start-pos-left start-pos-right - end-text end-pos-left end-pos-right - actual? level require-arrow? name-dup?) - (syncheck:add-arrow start-text start-pos-left start-pos-right - end-text end-pos-left end-pos-right - actual? level)) - (define/public (syncheck:add-tail-arrow from-text from-pos to-text to-pos) (void)) - (define/public (syncheck:add-mouse-over-status text pos-left pos-right str) (void)) - (define/public (syncheck:add-jump-to-definition text start end id filename submods) (void)) - (define/public (syncheck:add-definition-target source pos-left pos-right id mods) (void)) - (define/public (syncheck:color-range source start finish style-name) (void)) - (super-new))) - -(provide syncheck-text<%> - syncheck-annotations<%> - current-annotations - annotations-mixin) + syncheck:tack/untack-arrows)) \ No newline at end of file diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/local-member-names.rkt b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/local-member-names.rkt index ee477f2329..2040fc8824 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/local-member-names.rkt +++ b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/local-member-names.rkt @@ -1,6 +1,8 @@ #lang racket/base -(require racket/class) -(provide (all-defined-out)) +(require racket/class + drracket/private/syncheck/syncheck-local-member-names) +(provide (all-defined-out) + (all-from-out drracket/private/syncheck/syncheck-local-member-names)) (define-local-member-name syncheck:init-arrows @@ -8,19 +10,6 @@ syncheck:clear-coloring syncheck:arrows-visible? - syncheck:find-source-object - syncheck:add-background-color - syncheck:add-docs-menu - syncheck:color-range - syncheck:add-require-open-menu - syncheck:add-id-set - syncheck:add-arrow - syncheck:add-arrow/name-dup - syncheck:add-rename-menu - syncheck:add-tail-arrow - syncheck:add-mouse-over-status - syncheck:add-jump-to-definition - syncheck:jump-to-next-bound-occurrence syncheck:jump-to-binding-occurrence syncheck:jump-to-definition diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/online-comp.rkt b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/online-comp.rkt index 04a1c13537..455365afef 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/online-comp.rkt +++ b/pkgs/drracket-pkgs/drracket/drracket/private/syncheck/online-comp.rkt @@ -4,11 +4,12 @@ racket/match racket/contract (for-syntax racket/base) + drracket/private/syncheck/traversals + drracket/private/syncheck/syncheck-intf + drracket/private/syncheck/xref "../../private/eval-helpers-and-pref-init.rkt" - "traversals.rkt" - "local-member-names.rkt" "intf.rkt" - "xref.rkt") + "local-member-names.rkt") (provide go monitor) diff --git a/pkgs/drracket-pkgs/drracket/info.rkt b/pkgs/drracket-pkgs/drracket/info.rkt index 1a4d0c4653..68f56697b2 100644 --- a/pkgs/drracket-pkgs/drracket/info.rkt +++ b/pkgs/drracket-pkgs/drracket/info.rkt @@ -37,7 +37,9 @@ "tex-table" "unstable-lib" "drracket-plugin-lib" - "gui-pkg-manager-lib")) + "gui-pkg-manager-lib" + "drracket-tool-lib" + "drracket-tool-doc")) (define build-deps '("mzscheme-doc" "net-doc" "planet-doc" @@ -52,7 +54,10 @@ "at-exp-lib" "rackunit-lib")) -(define implies '("drracket-plugin-lib")) +;; implies drracket-tool-lib so that others dependencies don't break +;; (redex, in particular, used to depend on drracket but it really +;; needs only the parts in drracket-tool-lib) +(define implies '("drracket-plugin-lib" "drracket-tool-lib")) (define pkg-desc "The DrRacket programming environment") diff --git a/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl b/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl index 6d7ada502c..e003f631c5 100644 --- a/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl +++ b/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl @@ -643,296 +643,8 @@ for a list of the capabilities registered by default. @section{Check Syntax} -Check Syntax is a part of the DrRacket collection, but is implemented via the tools API. - -@subsection{Accessing Check Syntax Programmatically} - -@defmodule[drracket/check-syntax] - -@defproc[(make-traversal [namespace namespace?] - [path (or/c #f path-string?)]) - (values (->* (syntax?) - ((-> any/c void?)) - void?) - (-> void?))]{ - This function creates some local state about a traversal of syntax objects - and returns two functions. The first one should be called with each of the - (fully expanded) syntax objects that make up a program (there will be only - one if the program is a module) and then the second one should be called to - indicate there are no more. - - The optional argument to the first function is ignored. - It is left there for historical reasons. In the past it - was called for each sequence - of binding identifiers encountered in @racket[define-values], @racket[define-syntaxes], - and @racket[define-values-for-syntax]. - - During the dynamic extent of the call to the two result functions, the value - of the @racket[current-annotations] parameter is consulted and various - methods are invoked in the corresponding object (if any), to indicate - what has been found in the syntax object. These methods will only be called - if the syntax objects have source locations. -} - -@defparam[current-annotations ca (or/c #f (is-a?/c syncheck-annotations<%>))]{ - The methods of the value of this parameter are invoked by the functions returned - from @racket[make-traversal]. -} - -@defparam[current-max-to-send-at-once m (or/c +inf.0 (and/c exact-integer? (>=/c 2)))]{ - No longer used. -} - -@definterface[syncheck-annotations<%> ()]{ - - Classes implementing this interface are - accceptors of information about a traversal - of syntax objects. See @racket[make-traversal]. - - Do not implement this interface directly, as it - is liable to change without warning. Instead, use - the @racket[annotations-mixin] and override - the methods you're interested in. The - @racket[annotations-mixin] will keep in sync - with this interface, providing methods that - ignore their arguments. - - @defmethod[(syncheck:find-source-object [stx syntax?]) (or/c #f (not/c #f))]{ - This should return @racket[#f] if the source of this syntax object is - uninteresting for annotations (if, for example, the only interesting - annotations are those in the original file and this is a syntax object - introduced by a macro and thus has a source location from some other file). - - Otherwise, it should return some (non-@racket[#f]) - value that will then be passed to one of the other methods below as - a @racket[_source-obj] argument. - } - - @defmethod[(syncheck:add-background-color [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [end exact-nonnegative-integer?] - [color string?]) - void?]{ - Called to indicate that the color @racket[color] should be drawn on the background of - the given range in the editor, when the mouse moves over it. This method is typically - called in conjuction with some other method that provides some other annotation - on the source. - } - @defmethod[(syncheck:add-require-open-menu [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [end exact-nonnegative-integer?] - [file path-string?]) - void?]{ - Called to indicate that there is a @racket[require] at the location from - @racket[start] to @racket[end], - and that it corresponds to @racket[file]. Check Syntax adds a popup menu. - } - - @defmethod[(syncheck:add-docs-menu [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [end exact-nonnegative-integer?] - [id symbol?] - [label any/c] - [path any/c] - [tag any/c]) - void?]{ - Called to indicate that there is something that has documentation between the range - @racket[start] and @racket[end]. The documented identifier's name is given by @racket[id] - and the docs are found in the html file @racket[path] at the html tag @racket[tag]. - The @racket[label] argument describes the binding for use in the menu item (although it may - be longer than 200 characters). - } - - @defmethod[(syncheck:add-id-set [all-ids (listof (list/c (not/c #f) - exact-nonnegative-integer? - exact-nonnegative-integer?))] - [new-name-interferes? (-> symbol boolean?)]) - void?]{This method is no longer called by Check Syntax. It is here - for backwards compatibility only. The information it provided - must now be synthesized from the information supplied to - @method[syncheck-annotations<%> syncheck:add-arrow/name-dup].} - - @defmethod[(syncheck:add-arrow [start-source-obj (not/c #f)] - [start-left exact-nonnegative-integer?] - [start-right exact-nonnegative-integer?] - [end-source-obj (not/c #f)] - [end-left exact-nonnegative-integer?] - [end-right exact-nonnegative-integer?] - [actual? boolean?] - [phase-level (or/c exact-nonnegative-integer? #f)]) - void?]{ - This function is not called directly anymore by Check Syntax. Instead - @method[syncheck-annotations<%> syncheck:add-arrow/name-dup] is. - - This method is invoked by the default implementation of - @racket[_syncheck:add-arrow/name-dup] in - @racket[annotations-mixin]. - } - @defmethod[(syncheck:add-arrow/name-dup [start-source-obj (not/c #f)] - [start-left exact-nonnegative-integer?] - [start-right exact-nonnegative-integer?] - [end-source-obj (not/c #f)] - [end-left exact-nonnegative-integer?] - [end-right exact-nonnegative-integer?] - [actual? boolean?] - [phase-level (or/c exact-nonnegative-integer? #f)] - [require-arrow? boolean?] - [name-dup? (-> string? boolean?)]) - void?]{ - Called to indicate that there should be an arrow between the locations described by the first - six arguments. - - The @racket[phase-level] argument indicates the phase of the binding and the - @racket[actual?] argument indicates if the binding is a real one, or a predicted one from - a syntax template (predicted bindings are drawn with question marks in Check Syntax). - - The @racket[require-arrow?] argument indicates if this arrow points from - an imported identifier to its corresponding @racket[require]. - - The @racket[name-dup?] predicate returns @racket[#t] - in case that this variable (either the start or end), when replaced with the given string, would - shadow some other binding (or otherwise interfere with the binding structure of the program at - the time the program was expanded). - } - @defmethod[(syncheck:add-tail-arrow [from-source-obj (not/c #f)] - [from-pos exact-nonnegative-integer?] - [to-source-obj (not/c #f)] - [to-pos exact-nonnegative-integer?]) - void?]{ - Called to indicate that there are two expressions, beginning at - @racket[from-pos] and @racket[to-pos] - that are in tail position with respect to each other. - } - @defmethod[(syncheck:add-mouse-over-status [source-obj (not/c #f)] - [pos-left exact-nonnegative-integer?] - [pos-right exact-nonnegative-integer?] - [str string?]) - void?]{ - Called to indicate that the message in @racket[str] should be shown when the mouse - passes over the given position. - } - @defmethod[(syncheck:add-jump-to-definition [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [end exact-nonnegative-integer?] - [id any/c] - [filename path-string?] - [submods (listof symbol?)]) - void?]{ - Called to indicate that there is some identifier at the given location (named @racket[id]) that - is defined in the @racket[submods] of the file @racket[filename] (where an empty list in - @racket[submods] means that the identifier is defined at the top-level module). - } - - @defmethod[(syncheck:add-definition-target [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [finish exact-nonnegative-integer?] - [style-name any/c]) void?]{ - - } - - @defmethod[(syncheck:color-range [source-obj (not/c #f)] - [start exact-nonnegative-integer?] - [finish exact-nonnegative-integer?] - [style-name any/c] - [mode any/c]) - void?]{ - Called to indicate that the given location should be colored according to the - style @racket[style-name] when in @racket[mode]. The mode either indicates regular - check syntax or is used indicate blame for potential contract violations - (and still experimental). - } - @defmethod[(syncheck:add-rename-menu [id symbol?] - [all-ids (listof (list/c (not/c #f) - exact-nonnegative-integer? - exact-nonnegative-integer?))] - [new-name-interferes? (-> symbol boolean?)]) - void?]{ - This method is listed only for backwards compatibility. It is not called - by Check Syntax anymore. - } -} - -@(define syncheck-example-eval (make-base-eval)) - -@defmixin[annotations-mixin () (syncheck-annotations<%>)]{ - Supplies all of the methods in @racket[syncheck-annotations<%>] - with default behavior. Be sure to use this mixin to future-proof - your code and then override the methods you're interested in. - - By default: - @itemlist[@item{The @method[syncheck-annotations<%> syncheck:find-source-object] - method ignores its arguments and returns @racket[#f];} - @item{the @method[syncheck-annotations<%> syncheck:add-arrow/name-dup] method drops the - @racket[_require-arrow?] and @racket[_name-dup?] arguments and calls - @method[syncheck-annotations<%> syncheck:add-arrow]; and} - @item{all of the other methods ignore their arguments and return @racket[(void)].}] - - Here is an example showing how use this library to extract all - of the arrows that Check Syntax would draw from various - expressions. One subtle point: arrows are only included when - the corresponding identifiers are @racket[syntax-original?]; - the code below manages this by copying the properties from - an identifier that is @racket[syntax-original?] in the - call to @racket[datum->syntax]. - @interaction[#:eval - syncheck-example-eval - (require drracket/check-syntax racket/class) - (define arrows-collector% - (class (annotations-mixin object%) - (super-new) - (define/override (syncheck:find-source-object stx) - stx) - (define/override (syncheck:add-arrow/name-dup - start-source-obj start-left start-right - end-source-obj end-left end-right - actual? phase-level require-arrow? name-dup?) - (set! arrows - (cons (list start-source-obj end-source-obj) - arrows))) - (define arrows '()) - (define/public (get-collected-arrows) arrows))) - (define (arrows form) - (define base-namespace (make-base-namespace)) - (define-values (add-syntax done) - (make-traversal base-namespace #f)) - (define collector (new arrows-collector%)) - (parameterize ([current-annotations collector] - [current-namespace base-namespace]) - (add-syntax (expand form)) - (done)) - (send collector get-collected-arrows)) - (define (make-id name pos orig?) - (datum->syntax - #f - name - (list #f #f #f pos (string-length (symbol->string name))) - (and orig? #'is-orig))) - (arrows `(λ (,(make-id 'x 1 #t)) ,(make-id 'x 2 #t))) - (arrows `(λ (x) x)) - (arrows `(λ (,(make-id 'x 1 #f)) ,(make-id 'x 2 #t))) - (arrows `(λ (,(make-id 'x 1 #t)) x))] -} - -@(close-eval syncheck-example-eval) - -@(define-syntax-rule - (syncheck-method-id x ...) - (begin @defidform[x]{Bound to an identifier created with - @racket[define-local-member-name] - that is used in @racket[syncheck-annotations<%>].} - ...)) -@syncheck-method-id[syncheck:find-source-object - syncheck:add-background-color - syncheck:add-require-open-menu - syncheck:add-docs-menu - syncheck:add-rename-menu - syncheck:add-arrow - syncheck:add-arrow/name-dup - syncheck:add-tail-arrow - syncheck:add-mouse-over-status - syncheck:add-jump-to-definition - syncheck:add-id-set - syncheck:color-range] +Check Syntax is a part of the DrRacket collection, but is implemented via the +plugin API. See also @racketmodname[drracket/check-syntax]. @subsection{Check Syntax Button} diff --git a/pkgs/main-distribution-test/info.rkt b/pkgs/main-distribution-test/info.rkt index 22b8819c81..a7011d3ae5 100644 --- a/pkgs/main-distribution-test/info.rkt +++ b/pkgs/main-distribution-test/info.rkt @@ -28,7 +28,8 @@ "images-test" "plot-test" "math-test" - "racket-benchmarks")) + "racket-benchmarks" + "drracket-tool-test")) (define pkg-desc "tests for \"main-distribution\"") diff --git a/pkgs/main-distribution/info.rkt b/pkgs/main-distribution/info.rkt index 66ea262e19..c618279c58 100644 --- a/pkgs/main-distribution/info.rkt +++ b/pkgs/main-distribution/info.rkt @@ -15,6 +15,7 @@ "draw-doc" "draw-lib" "drracket" + "drracket-tool" "eopl" "errortrace" "frtime"