From eb2db158a86aba2c5b903965c539a6367e6f0e79 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Thu, 2 Oct 2014 17:20:08 -0500 Subject: [PATCH] add support for macro-specified tooltips to check syntax --- .../drracket/private/syncheck/traversals.rkt | 15 ++++++++ .../drracket/drracket/private/tooltip.rkt | 11 ++++-- .../drracket/scribblings/tools/tools.scrbl | 35 ++++++++++++++++--- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt index 3c18612a82..544fa7bb29 100644 --- a/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt +++ b/pkgs/drracket-pkgs/drracket-tool-lib/drracket/private/syncheck/traversals.rkt @@ -251,6 +251,7 @@ (add-origins stx varrefs level-of-enclosing-module) (add-disappeared-bindings stx binders varrefs level-of-enclosing-module) (add-disappeared-uses stx varrefs level-of-enclosing-module) + (add-mouse-over-tooltips stx) (add-sub-range-binders stx sub-identifier-binding-directives level @@ -542,6 +543,20 @@ "found a vector in a 'sub-range-binders property that is ill-formed ~s" prop)]))) +(define mouse-over-tooltip-prop? + (vector/c #:flat? #t any/c exact-nonnegative-integer? exact-nonnegative-integer? string?)) +(define (add-mouse-over-tooltips stx) + (let loop ([prop (syntax-property stx 'mouse-over-tooltips)]) + (cond + [(pair? prop) + (loop (car prop)) + (loop (cdr prop))] + [(mouse-over-tooltip-prop? prop) + (add-mouse-over/loc (vector-ref prop 0) + (vector-ref prop 1) + (vector-ref prop 2) + (vector-ref prop 3))]))) + ;; add-disappeared-bindings : syntax id-set integer -> void (define (add-disappeared-bindings stx binders disappaeared-uses level-of-enclosing-module) (let ([prop (syntax-property stx 'disappeared-binding)]) diff --git a/pkgs/drracket-pkgs/drracket/drracket/private/tooltip.rkt b/pkgs/drracket-pkgs/drracket/drracket/private/tooltip.rkt index 308406217c..1898f3d147 100644 --- a/pkgs/drracket-pkgs/drracket/drracket/private/tooltip.rkt +++ b/pkgs/drracket-pkgs/drracket/drracket/private/tooltip.rkt @@ -23,8 +23,15 @@ (and (is-shown?) (begin (show #f) #t))) - (define/public (set-tooltip ls) - (send yellow-message set-lab ls)) + + ;; ls may contain strings that have newlines; break up the strings here + (define/public (set-tooltip ls) + (define broken-up-lines + (apply + append + (for/list ([str (in-list ls)]) + (regexp-split #rx"\n" str)))) + (send yellow-message set-lab broken-up-lines)) (define/override (show on?) (when timer diff --git a/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl b/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl index e003f631c5..7a34897768 100644 --- a/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl +++ b/pkgs/drracket-pkgs/drracket/scribblings/tools/tools.scrbl @@ -674,13 +674,14 @@ plugin API. See also @racketmodname[drracket/check-syntax]. @subsection{Syntax Properties that Check Syntax Looks For} -@section-index["disappeared-use" "disappeared-binding" "sub-range-binders"] +@section-index["disappeared-use" "disappeared-binding" "sub-range-binders" "mouse-over-tooltips"] Check Syntax collects the values of the @racket[syntax-property]s named @racket['disappeared-use], -@racket['disappeared-binding], and -@racket['sub-range-binders], and uses them to add +@racket['disappeared-binding], +@racket['sub-range-binders], and +@racket['mouse-over-tooltips] and uses them to add additional arrows to the program text. These properties are intended for use when a macro discards or manufactures identifiers that, from the programmers perspective, should be binding each other. @@ -706,7 +707,7 @@ The value of the @racket['sub-range-binders] property is expected to be a tree of @racket[cons] pairs (in any configuration) whose leaves are either ignored or are vectors of the shape @racketblock[(vector/c syntax? exact-nonnegative-integer? exact-nonnegative-integer? - syntax? exact-nonnegative-integer? exact-nonnegative-integer?)]. + syntax? exact-nonnegative-integer? exact-nonnegative-integer?)] If the leaf is a vector, the first syntax object is expected to be an identifier whose bound occurrences should have arrows that point to the syntax object in the fourth position in the vector. The numbers indicate the starting point and the range inside @@ -749,6 +750,32 @@ After putting this code in the DrRacket window, mouse over the words ``big'' and ``generator'' to see arrows pointing to the individual pieces of the identifier @racket[_big-generator]. +The value of the @racket['mouse-over-tooltips] property is expected to be +to be a tree of @racket[cons] pairs (in any configuration) whose leaves +are either ignored or are vectors of the shape +@racketblock[(vector/c any/c exact-nonnegative-integer? exact-nonnegative-integer? string?)] +Each vector's content indicates where to show a tooltip. The first three components are +the @racket[syntax-source] indicating which file the tooltip goes in, the start and end position +in the editor where mouseovers will show the tooltip, and the content of the tooltip. +For example, here's a macro that shows the span of itself in a tooltip on mouseover: +@codeblock{ +#lang racket +(define-syntax (char-span stx) + (syntax-case stx () + [(_ a) + (syntax-property + #'a + 'mouse-over-tooltips + (vector + (syntax-source stx) + (syntax-position stx) + (+ (syntax-position stx) + (syntax-span stx)) + (format "this expression\nspans ~a chars" + (syntax-span stx))))])) + +(char-span (+ 1 2))} + Finally, Check Syntax only draws arrows between identifiers that are @racket[syntax-original?] or that have the @racket[syntax-property] @racket['original-for-check-syntax] set to @racket[#t].