|
51 | 51 | current-type-context modify-type-context |
52 | 52 | register-global-class-instance! constr->instances lookup-instance! |
53 | 53 | reduce-context type-reduce-context |
54 | | - attach-type attach-expected get-type get-expected make-typed-var-transformer |
| 54 | + attach-type attach-expected get-type get-expected apply-current-subst-in-tooltips |
| 55 | + make-typed-var-transformer |
55 | 56 |
|
56 | 57 | (for-template (all-from-out hackett/private/type-language) |
57 | 58 | local-class-instances @%superclasses-key)) |
|
576 | 577 |
|
577 | 578 | ;; ------------------------------------------------------------------------------------------------- |
578 | 579 |
|
579 | | -(define/contract (attach-type stx t) |
580 | | - (-> syntax? type? syntax?) |
581 | | - (syntax-property stx ': t)) |
| 580 | +; To support type tooltips, we attach 'mouse-over-tooltips properties to syntax objects whenever we |
| 581 | +; attach a type, unless the 'omit-type-tooltip property is already present. When we attach these |
| 582 | +; tooltips, we might not know the fully-solved type yet, so we perform a second pass after the module |
| 583 | +; is fully-expanded that applies the current substitution whenever it sees a type. It’s important to |
| 584 | +; apply this substitution while the module is still being expanded, since otherwise, the type context |
| 585 | +; will be empty! |
| 586 | +; |
| 587 | +; To support this, we wrap the type inside a deferred-type-in-tooltip struct. This struct cooperates |
| 588 | +; with the 'mouse-over-tooltips property by being a procedure, so even if we somehow fail to discover |
| 589 | +; the property and evaluate it earlier, we’ll at least get *some* information. When |
| 590 | +; apply-current-subst-in-tooltips is called, however, we evaluate the thunk early and replace the |
| 591 | +; property with the new value, improving the information in the tooltips. |
| 592 | + |
| 593 | +(struct deferred-type-in-tooltip (type) |
| 594 | + #:property prop:procedure |
| 595 | + (λ (self) (type->string (apply-current-subst (deferred-type-in-tooltip-type self))))) |
| 596 | + |
| 597 | +(define/contract (attach-type stx t #:tooltip-src [tooltip-src stx]) |
| 598 | + (->* [syntax? type?] [#:tooltip-src any/c] syntax?) |
| 599 | + (let ([stx* (syntax-property stx ': t)]) |
| 600 | + (if (and (not (syntax-property tooltip-src 'omit-type-tooltip)) |
| 601 | + (syntax-source tooltip-src) |
| 602 | + (syntax-position tooltip-src) |
| 603 | + (syntax-span tooltip-src)) |
| 604 | + (syntax-property |
| 605 | + stx* 'mouse-over-tooltips |
| 606 | + (syntax-parse tooltip-src |
| 607 | + ; If it’s a pair, just add the tooltip “on the parens”. |
| 608 | + [(_ . _) |
| 609 | + (cons |
| 610 | + (vector tooltip-src |
| 611 | + (sub1 (syntax-position tooltip-src)) |
| 612 | + (syntax-position tooltip-src) |
| 613 | + (deferred-type-in-tooltip t)) |
| 614 | + (vector tooltip-src |
| 615 | + (+ (sub1 (syntax-position tooltip-src)) (sub1 (syntax-span tooltip-src))) |
| 616 | + (+ (sub1 (syntax-position tooltip-src)) (syntax-span tooltip-src)) |
| 617 | + (deferred-type-in-tooltip t)))] |
| 618 | + ; Otherwise, add the tooltip on the whole region. |
| 619 | + [_ |
| 620 | + (vector tooltip-src |
| 621 | + (sub1 (syntax-position tooltip-src)) |
| 622 | + (+ (sub1 (syntax-position tooltip-src)) (syntax-span tooltip-src)) |
| 623 | + (deferred-type-in-tooltip t))])) |
| 624 | + stx*))) |
582 | 625 | (define/contract (attach-expected stx t) |
583 | 626 | (-> syntax? type? syntax?) |
584 | 627 | (syntax-property stx ':⇐ t)) |
|
592 | 635 | (let loop ([val (syntax-property stx ':⇐)]) |
593 | 636 | (if (pair? val) (loop (car val)) val))) |
594 | 637 |
|
| 638 | +(define (apply-current-subst-in-tooltips stx) |
| 639 | + (recursively-adjust-property |
| 640 | + stx 'mouse-over-tooltips |
| 641 | + (match-lambda |
| 642 | + [(vector a b c (? deferred-type-in-tooltip? d)) |
| 643 | + (vector a b c (d))] |
| 644 | + [other other]))) |
| 645 | + |
595 | 646 | (define/contract (make-typed-var-transformer x t) |
596 | 647 | (-> identifier? type? any) |
597 | | - (make-variable-like-transformer (attach-type x t))) |
| 648 | + (make-variable-like-transformer |
| 649 | + ; Adjust source location information before calling attach-type so that tooltips end up in the |
| 650 | + ; right place. |
| 651 | + (λ (stx) (attach-type (replace-stx-loc x stx) t)))) |
0 commit comments