start the drracket-tools pkg

pull out the drracket/check-syntax library into this pkg
This commit is contained in:
Robby Findler 2014-09-30 21:01:01 -05:00
parent 994c54c722
commit 43ffd4b6ce
25 changed files with 469 additions and 400 deletions

View File

@ -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

View File

@ -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")

View File

@ -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]

View File

@ -0,0 +1,3 @@
#lang info
(define scribblings '(("drracket-tools.scrbl" (multi-page) (tool -200))))

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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))

View File

@ -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@)

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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}

View File

@ -28,7 +28,8 @@
"images-test"
"plot-test"
"math-test"
"racket-benchmarks"))
"racket-benchmarks"
"drracket-tool-test"))
(define pkg-desc "tests for \"main-distribution\"")

View File

@ -15,6 +15,7 @@
"draw-doc"
"draw-lib"
"drracket"
"drracket-tool"
"eopl"
"errortrace"
"frtime"