• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jackfirth / resyntax / #152

03 Nov 2025 05:39PM UTC coverage: 92.902% (+0.02%) from 92.882%
#152

Pull #708

cover

Copilot
Address code review feedback and finalize function-expression-analyzer

Co-authored-by: jackfirth <8175575+jackfirth@users.noreply.github.com>
Pull Request #708: Add function-expression-analyzer for identifying application subexpressions

58 of 59 new or added lines in 2 files covered. (98.31%)

14633 of 15751 relevant lines covered (92.9%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.44
/default-recommendations/analyzers/function-expression-analyzer.rkt
1
#lang racket/base
1✔
2

3

4
(require racket/contract/base)
1✔
5

6

7
(provide
1✔
8
 (contract-out
1✔
9
  [function-expression-analyzer expansion-analyzer?]))
1✔
10

11

12
(require racket/stream
1✔
13
         rebellion/streaming/transducer
1✔
14
         resyntax/private/analyzer
1✔
15
         resyntax/private/syntax-path
1✔
16
         resyntax/private/syntax-property-bundle
1✔
17
         resyntax/private/syntax-traversal
1✔
18
         syntax/parse)
1✔
19

20

21
(module+ test
22
  (require (submod "..")
23
           rackunit))
24

25

26
;@----------------------------------------------------------------------------------------------------
27

28

29
(define (annotate-application-subexpressions expanded-stx)
1✔
30
  (let loop ([expanded-stx expanded-stx] [phase 0])
1✔
31
    (syntax-search expanded-stx
1✔
32
      #:literal-sets ([kernel-literals #:phase phase])
1✔
33
      
34
      ;; Phase mismatch - recurse with correct phase
35
      [(id:id _ ...)
1✔
36
       #:do [(define id-phase (syntax-property (attribute id) 'phase))]
1✔
37
       #:when (not (equal? id-phase phase))
1✔
38
       (loop this-syntax id-phase)]
1✔
39

40
      ;; Skip quote-syntax - no function applications inside
NEW
41
      [(quote-syntax _) (stream)]
×
42
      
43
      ;; Function application - annotate function and arguments
44
      ;; Note: In fully expanded code, we need to match #%plain-app using identifier comparison
45
      [(app-id:id func arg ...)
1✔
46
       #:when (free-identifier=? (attribute app-id) #'#%plain-app)
1✔
47
       #:do [(define func-path (syntax-property (attribute func) 'expansion-path))]
1✔
48
       #:when func-path
1✔
49
       (define func-entry (syntax-property-entry func-path 'application-subexpression-kind 'function))
1✔
50
       (define arg-entries
1✔
51
         (for/stream ([arg-stx (in-list (attribute arg))])
1✔
52
           (define arg-path (syntax-property arg-stx 'expansion-path))
1✔
53
           (and arg-path
1✔
54
                (syntax-property-entry arg-path 'application-subexpression-kind 'argument))))
1✔
55
       (stream-cons func-entry (stream-filter values arg-entries))])))
1✔
56

57

58
(define function-expression-analyzer
1✔
59
  (make-expansion-analyzer
1✔
60
   #:name 'function-expression-analyzer
1✔
61
   (λ (expanded-stx)
1✔
62
     (define labeled-stx (syntax-label-paths expanded-stx 'expansion-path))
1✔
63
     (transduce (annotate-application-subexpressions labeled-stx)
1✔
64
                #:into into-syntax-property-bundle))))
1✔
65

66

67
(module+ test
68
  (test-case "function-expression-analyzer"
69

70
    (test-case "empty module"
71
      (define stx #'(module foo racket/base))
72
      (define props (expansion-analyze function-expression-analyzer (expand stx)))
73
      ;; Even empty modules have configure-runtime calls, so we check that we get some properties
74
      (check-true (syntax-property-bundle? props)))))
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc