1 Accessing Check Syntax Programmatically
(require drracket/check-syntax) | |
package: drracket-tool-lib |
procedure
(show-content file-or-stx) → (listof vector?)
file-or-stx :
(or/c path-string? (and/c syntax? (λ (x) (path-string? (syntax-source x)))))
This doesn’t work as well for use in a real tool, however, because it doesn’t account for the callback procedures present in syncheck:add-arrow/name-dup/pxpy and syncheck:add-id-set and the resulting vectors are probably less convenient to work with than direct method calls for most uses of this library. Nevertheless, it gives a quick feel for the results that can come back from Check Syntax.
See annotations-mixin for some example code to use the other parts of this library.
Note that the paths in the example below have been replaced via make-paths-be-module-paths in order to make the results be platform independent.
> (define (make-paths-be-module-paths x) (let loop ([x x]) (cond [(pair? x) (cons (loop (car x)) (loop (cdr x)))] [(vector? x) (for/vector ([x (in-vector x)]) (loop x))] [(path? x) (path->relative-string/library x)] [else x])))
> (let ([example-module '(module m racket (λ (x) x))]) (make-paths-be-module-paths (show-content (read-syntax (build-path (current-directory) "dummy-file.rkt") (open-input-string (format "~s" example-module))))))
'(#(syncheck:add-require-open-menu 10 16 "<collects>/racket/main.rkt")
#(syncheck:add-tail-arrow 17 25)
#(syncheck:add-background-color 1 7 "palegreen")
#(syncheck:add-docs-menu
1
7
module
"View documentation for “module” from racket/base, racket"
"<pkgs>/racket-doc/scribblings/reference/doc/reference/module.html"
(form ('#%kernel module))
"(form._((quote._~23~25kernel)._module))")
#(syncheck:add-arrow/name-dup/pxpy
22
23
0.5
0.5
25
26
0.5
0.5
#t
0
#f
#<procedure:name-dup?>)
#(syncheck:add-background-color 19 20 "palegreen")
#(syncheck:add-docs-menu
19
20
λ
"View documentation for “λ” from racket/base, racket"
"<pkgs>/racket-doc/scribblings/reference/doc/reference/lambda.html"
(form ((lib "racket/private/base.rkt") λ))
"(form._((lib._racket/private/base..rkt)._~ce~bb))")
#(syncheck:add-jump-to-definition
19
20
new-λ
"<collects>/racket/private/kw.rkt"
())
#(syncheck:add-mouse-over-status 19 20 "imported from “racket”")
#(syncheck:add-arrow/name-dup/pxpy
10
16
0.5
0.5
19
20
0.5
0.5
#t
0
module-lang
#<procedure:name-dup?>)
#(syncheck:add-background-color 19 20 "palegreen")
#(syncheck:add-docs-menu
19
20
λ
"View documentation for “λ” from racket/base, racket"
"<pkgs>/racket-doc/scribblings/reference/doc/reference/lambda.html"
(form ((lib "racket/private/base.rkt") λ))
"(form._((lib._racket/private/base..rkt)._~ce~bb))")
#(syncheck:add-jump-to-definition
19
20
new-λ
"<collects>/racket/private/kw.rkt"
())
#(syncheck:add-mouse-over-status 19 20 "imported from “racket”")
#(syncheck:add-arrow/name-dup/pxpy
10
16
0.5
0.5
19
20
0.5
0.5
#t
0
module-lang
#<procedure:name-dup?>)
#(syncheck:add-mouse-over-status 22 23 "1 bound occurrence")
#(syncheck:add-mouse-over-status 10 16 "1 bound occurrence"))
procedure
(make-traversal namespace path) →
(->* (syntax?) ((-> any/c void?)) void?) (-> void?) namespace : namespace? path : (or/c #f path-string?)
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 define-values, define-syntaxes, and define-values-for-syntax.
During the dynamic extent of the call to the two result functions, the value of the 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.
parameter
→ (or/c #f (is-a?/c syncheck-annotations<%>)) (current-annotations ca) → void? ca : (or/c #f (is-a?/c syncheck-annotations<%>))
parameter
→ (or/c +inf.0 (and/c exact-integer? (>=/c 2))) (current-max-to-send-at-once m) → void? m : (or/c +inf.0 (and/c exact-integer? (>=/c 2)))
|
method
(send a-syncheck-annotations syncheck:find-source-object stx)
→ (or/c #f (not/c #f)) stx : syntax? This should return #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-#f) value that will then be passed to one of the other methods below as a source-obj argument.
method
(send a-syncheck-annotations syncheck:add-background-color source-obj start end color) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? end : exact-nonnegative-integer? color : string? Called to indicate that the color 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.
method
(send a-syncheck-annotations syncheck:add-require-open-menu source-obj start end file) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? end : exact-nonnegative-integer? file : path-string? Called to indicate that there is a require at the location from start to end, and that it corresponds to file. Check Syntax adds a popup menu.
method
(send a-syncheck-annotations syncheck:add-docs-menu source-obj start end id label path tag) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? end : exact-nonnegative-integer? id : symbol? label : any/c path : any/c tag : any/c Called to indicate that there is something that has documentation between the range start and end. The documented identifier’s name is given by id and the docs are found in the html file path at the html tag tag. The label argument describes the binding for use in the menu item (although it may be longer than 200 characters).
method
(send a-syncheck-annotations syncheck:add-id-set all-ids new-name-interferes?) → void?
all-ids :
(listof (list/c (not/c #f) exact-nonnegative-integer? exact-nonnegative-integer?)) new-name-interferes? : (-> symbol boolean?) 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 syncheck:add-arrow/name-dup/pxpy.
method
(send a-syncheck-annotations syncheck:add-arrow start-source-obj start-left start-right end-source-obj end-left end-right actual? phase-level) → void? 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) This function is not called directly anymore by Check Syntax. Instead syncheck:add-arrow/name-dup/pxpy is.This method is invoked by the default implementation of syncheck:add-arrow/name-dup in annotations-mixin.
method
(send a-syncheck-annotations 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?) → void? 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?) This function is not called directly anymore by Check Syntax. Instead syncheck:add-arrow/name-dup/pxpy is.The default implementation of syncheck:add-arrow/name-dup/pxpy discards the start-px start-py end-px end-py arguments and calls this method.
method
(send a-syncheck-annotations syncheck:add-arrow/name-dup/pxpy start-source-obj start-left start-right start-px start-py end-source-obj end-left end-right end-px end-py actual? phase-level require-arrow name-dup?) → void? start-source-obj : (not/c #f) start-left : exact-nonnegative-integer? start-right : exact-nonnegative-integer? start-px : (real-in 0 1) start-py : (real-in 0 1) end-source-obj : (not/c #f) end-left : exact-nonnegative-integer? end-right : exact-nonnegative-integer? end-px : (real-in 0 1) end-py : (real-in 0 1) actual? : boolean? phase-level : (or/c exact-nonnegative-integer? #f) require-arrow : (or/c boolean? 'module-lang-require) name-dup? : (-> string? boolean?) Called to indicate that there should be an arrow between the locations described by the first ten arguments. The start-px and start-py indicate how far along the diagonal between the upper-left coordinate of the editor position start-left and the bottom-right of the editor position start-right to draw the foot of the arrow. The end-px and end-py indicate the same things for the head of the arrow.The phase-level argument indicates the phase of the binding and the 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 require-arrow argument indicates if this arrow points from an imported identifier to its corresponding require. Any true value means that it points to an import via require; #t means it was a normal require and 'module-lang-require means it comes from the implicit require that a module language provides.
The name-dup? predicate returns #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).
Changed in version 1.1 of package drracket-tool-lib: Changed require-arrow to sometimes be 'module-lang-require.
method
(send a-syncheck-annotations syncheck:add-tail-arrow from-source-obj from-pos to-source-obj to-pos) → void? from-source-obj : (not/c #f) from-pos : exact-nonnegative-integer? to-source-obj : (not/c #f) to-pos : exact-nonnegative-integer? Called to indicate that there are two expressions, beginning at from-pos and to-pos that are in tail position with respect to each other.
method
(send a-syncheck-annotations syncheck:add-mouse-over-status source-obj pos-left pos-right str) → void? source-obj : (not/c #f) pos-left : exact-nonnegative-integer? pos-right : exact-nonnegative-integer? str : string? Called to indicate that the message in str should be shown when the mouse passes over the given position.
method
(send a-syncheck-annotations syncheck:add-prefixed-require-reference req-src req-pos-left req-pos-right) → void? req-src : (not/c #f) req-pos-left : exact-nonnegative-integer? req-pos-right : exact-nonnegative-integer? This method is called for each require in the program that has a prefix or prefix-all-except around it in fully expanded form (i.e., it seems to come from a prefix-in or a similar form). The method is passed the location of the require in the original program.
method
(send a-syncheck-annotations syncheck:add-unused-require req-src req-pos-left req-pos-right) → void? req-src : (not/c #f) req-pos-left : exact-nonnegative-integer? req-pos-right : exact-nonnegative-integer? This method is called for each require that Check Syntax determines to be unused. The method is passed the location of the name of the required module in the original program.
method
(send a-syncheck-annotations syncheck:add-jump-to-definition source-obj start end id filename submods) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? end : exact-nonnegative-integer? id : any/c filename : path-string? submods : (listof symbol?) Called to indicate that there is some identifier at the given location (named id) that is defined in the submods of the file filename (where an empty list in submods means that the identifier is defined at the top-level module).
method
(send a-syncheck-annotations syncheck:add-definition-target source-obj start finish style-name) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? finish : exact-nonnegative-integer? style-name : any/c
method
(send a-syncheck-annotations syncheck:color-range source-obj start finish style-name mode) → void? source-obj : (not/c #f) start : exact-nonnegative-integer? finish : exact-nonnegative-integer? style-name : any/c mode : any/c Called to indicate that the given location should be colored according to the style style-name when in mode. The mode either indicates regular check syntax or is used indicate blame for potential contract violations (and still experimental).
method
(send a-syncheck-annotations syncheck:add-rename-menu id all-ids new-name-interferes?) → void? id : symbol?
all-ids :
(listof (list/c (not/c #f) exact-nonnegative-integer? exact-nonnegative-integer?)) new-name-interferes? : (-> symbol boolean?) This method is listed only for backwards compatibility. It is not called by Check Syntax anymore.
| ||
|
The syncheck:find-source-object method ignores its arguments and returns #f;
the syncheck:add-arrow/name-dup method drops the require-arrow? and name-dup? arguments and calls syncheck:add-arrow;
the syncheck:add-arrow/name-dup/pxpy method drops the from-px, from-py, to-px, and to-py arguments and calls syncheck:add-arrow/name-dup; and
all of the other methods ignore their arguments and return (void).
> (define arrows-collector% (class (annotations-mixin object%) (super-new) (define/override (syncheck:find-source-object stx) stx) (define/override (syncheck:add-arrow/name-dup/pxpy start-source-obj start-left start-right start-px start-py end-source-obj end-left end-right end-px end-py 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))) '((#<syntax::1 x> #<syntax::2 x>))
> (arrows `(λ (x) x)) '()
> (arrows `(λ (,(make-id 'x 1 #f)) ,(make-id 'x 2 #t))) '()
> (arrows `(λ (,(make-id 'x 1 #t)) x)) '()
syntax
syntax
syntax
syntax
syntax
syntax