Skip to content

Commit 7b002f3

Browse files
committed
put a parsed form of the require spec into phase-to-requires and add a
check that the symbolic name of a binder and its reference are the same Also, it appears that something changed along the way such that we no longer need the special case that solved issue #110 anymore
1 parent fa28922 commit 7b002f3

File tree

2 files changed

+143
-85
lines changed

2 files changed

+143
-85
lines changed

drracket-tool-test/tests/check-syntax/syncheck-direct.rkt

+71-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@
261261
'((10 21 0.5 0.5) (23 30 0.5 0.5))
262262
'((64 68 0.5 0.5) (125 130 0.5 0.5))
263263
'((118 121 0.5 0.5) (131 134 0.5 0.5))
264-
'((118 121 0.5 0.5) (125 130 0.5 0.5))
264+
;'((118 121 0.5 0.5) (125 130 0.5 0.5))
265265
'((99 110 0.5 0.5) (131 134 0.5 0.5))))
266266

267267
(check-equal? (get-binding-arrows
@@ -484,7 +484,41 @@
484484
'((28 39) (71 78))
485485
'((50 53) (79 82))))
486486

487+
(check-equal?
488+
(get-binding-arrows
489+
(string-append
490+
"#lang racket/base\n"
491+
"(require racket/list)\n"
492+
"(let ([first #f])\n"
493+
" (local-require racket/list)\n"
494+
" first)\n"))
495+
(set
496+
'((6 17) (53 53))
497+
'((6 17) (19 26))
498+
'((6 17) (41 44))
499+
'((6 17) (61 74))
500+
'((75 86) (90 95))
487501

502+
;; this one is wrong but there doesn't seem to be
503+
;; enough information in the fully-expanded form
504+
;; to drop it.
505+
'((27 38) (90 95))))
506+
507+
(check-equal?
508+
(get-binding-arrows
509+
(string-append
510+
"#lang racket/base\n"
511+
"(require racket/list)\n"
512+
"first\n"
513+
"(require (rename-in racket/list [first 1st]))\n"
514+
"1st\n"))
515+
(set
516+
'((6 17) (19 26))
517+
'((6 17) (47 54))
518+
'((6 17) (56 65))
519+
'((27 38) (40 45))
520+
'((66 77) (92 95)) ;; sketchy; should we eliminate?
521+
'((85 88) (92 95))))
488522

489523
;
490524
;
@@ -672,6 +706,42 @@
672706
" first)\n"))
673707
(set '(27 83) '(68 83) '(27 40)))
674708

709+
(check-equal?
710+
(get-require-arrows
711+
(string-append
712+
"#lang racket/base\n"
713+
"(require (prefix-in x: racket/list) racket/list)\n"
714+
"x:first\n"
715+
"first\n"))
716+
(set '(54 75) '(38 67) '(41 69)))
717+
718+
(check-equal?
719+
(get-require-arrows
720+
(string-append
721+
"#lang racket/base\n"
722+
"(require racket/list)\n"
723+
"(let ([first #f])\n"
724+
" (local-require racket/list)\n"
725+
" first)\n"))
726+
(set '(75 90)
727+
728+
;; this one is wrong but there doesn't seem to be
729+
;; enough information in the fully-expanded form
730+
;; to drop it.
731+
'(27 90)))
732+
733+
(check-equal?
734+
(get-require-arrows
735+
(string-append
736+
"#lang racket/base\n"
737+
"(require racket/list)\n"
738+
"first\n"
739+
"(require (rename-in racket/list [first 1st]))\n"
740+
"1st\n"))
741+
(set '(27 40)
742+
743+
;; this arrow is sketchy. Can we get rid of it?
744+
'(66 92)))
675745

676746

677747
;

drracket-tool-text-lib/drracket/private/syncheck/traversals.rkt

+72-84
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,14 @@
172172

173173
;; binder : syntax?
174174
;; mods : same contract as `mods` in level+tail+mod-loop
175-
(struct binder+mods (binder mods))
175+
(struct binder+mods (binder mods) #:transparent)
176+
177+
;; ids : (listof syntax?)
178+
;; in? : boolean? -- indicates if `ids` are the only ones included (#t) or if they are excluded (#f)
179+
;; prefix : (or/c #f syntax?)
180+
;; b+m : binder+mods?
181+
;; -- INVARIANT: if prefix? is syntax?, then in? must be #f
182+
(struct require-context (ids in? prefix b+m) #:transparent)
176183

177184
;; annotate-basic :
178185
;; stx-obj: syntax?
@@ -448,7 +455,8 @@
448455
(hash-ref! phase-to-requires
449456
(list (+ level level-of-enclosing-module) next-level-mods)
450457
(λ () (make-hash))))
451-
(hash-cons! sub-requires (syntax->datum (syntax lang)) (binder+mods (syntax lang) this-submodule))
458+
(hash-cons! sub-requires (syntax->datum #'lang)
459+
(require-context '() #f #f (binder+mods #'lang this-submodule)))
452460
(for ([body (in-list (syntax->list (syntax (bodies ...))))])
453461
(mod-loop body this-submodule)))]
454462
[(module* m-name lang (mb bodies ...))
@@ -463,7 +471,8 @@
463471
(hash-ref! phase-to-requires
464472
(list (+ level level-of-enclosing-module) next-level-mods)
465473
(λ () (make-hash))))
466-
(hash-cons! sub-requires (syntax->datum (syntax lang)) (binder+mods (syntax lang) this-submodule)))
474+
(hash-cons! sub-requires (syntax->datum #'lang)
475+
(require-context '() #f #f (binder+mods #'lang this-submodule))))
467476

468477
(for ([body (in-list (syntax->list (syntax (bodies ...))))])
469478
(if (syntax-e #'lang)
@@ -516,13 +525,15 @@
516525
(define require-ht (hash-ref! phase-to-requires
517526
(list adjusted-level mods)
518527
(λ () (make-hash))))
519-
(define raw-module-path
520-
(phaseless-spec->raw-module-path
528+
(define require-context
529+
(phaseless-spec->require-context
530+
mods
521531
stx
522532
(λ (local-id)
523533
(add-binders (list local-id) binders binding-inits #'b
524534
level level-of-enclosing-module
525535
sub-identifier-binding-directives mods))))
536+
(define raw-module-path (binder+mods-binder (require-context-b+m require-context)))
526537
(annotate-require-open user-namespace user-directory raw-module-path level stx)
527538
(when (original-enough? raw-module-path)
528539
(define key
@@ -534,7 +545,7 @@
534545
`(submod "." ,m)
535546
`',m)]
536547
[rmp rmp]))
537-
(hash-cons! require-ht key (binder+mods stx mods))))
548+
(hash-cons! require-ht key require-context)))
538549

539550
(for ([spec (in-list (syntax->list #'(raw-require-specs ...)))])
540551
(handle-raw-require-spec spec)))]
@@ -855,34 +866,30 @@
855866
;; -> void
856867
(define (color-unused requires unused module-lang-requires)
857868
(for ([(k v) (in-hash unused)])
858-
(define requires-binder+modss
869+
(define require-contexts
859870
(hash-ref requires k
860871
(λ ()
861872
(error 'syncheck/traversals.rkt
862873
"requires doesn't have a mapping for ~s"
863874
k))))
864-
(for ([binder+mods (in-list requires-binder+modss)])
875+
(for ([require-context (in-list require-contexts)])
876+
(define binder+mods (require-context-b+m require-context))
865877
(define stx (binder+mods-binder binder+mods))
866878
(unless (hash-ref module-lang-requires (list (syntax-source stx)
867879
(syntax-position stx)
868880
(syntax-span stx)) #f)
869-
;; Use module path portion of syntax: Its more-specific
870-
;; location matters for e.g. combine-in and things that expand
871-
;; to it. See issue #110.
872-
(define raw-mod-stx (phaseless-spec->raw-module-path stx))
873-
(define mod-stx (if (syntax-source raw-mod-stx) raw-mod-stx stx))
874881
(define defs-text (current-annotations))
875-
(define source-editor (find-source-editor mod-stx))
882+
(define source-editor (find-source-editor stx))
876883
(when (and defs-text source-editor)
877-
(define pos (syntax-position mod-stx))
878-
(define span (syntax-span mod-stx))
884+
(define pos (syntax-position stx))
885+
(define span (syntax-span stx))
879886
(when (and pos span)
880887
(define start (- pos 1))
881888
(define fin (+ start span))
882889
(send defs-text syncheck:add-unused-require source-editor start fin)
883890
(send defs-text syncheck:add-text-type
884891
source-editor start fin 'unused-identifier)))
885-
(color mod-stx unused-require-style-name)))))
892+
(color stx unused-require-style-name)))))
886893

887894
;; color-unused-binder : source integer integer -> void
888895
(define (color-unused-binder source start end)
@@ -913,23 +920,24 @@
913920
(when binders
914921
(for ([binder+mods (in-list binders)])
915922
(define binder (binder+mods-binder binder+mods))
916-
(define binder-is-outside-reference?
917-
(or (not mods-where-var-is)
918-
(not (binder+mods-mods binder+mods))
919-
(let loop ([mods-where-var-is (reverse mods-where-var-is)]
920-
[mods-where-binder-is (reverse (binder+mods-mods binder+mods))])
921-
(cond
922-
[(null? mods-where-binder-is)
923-
(for/and ([mod (in-list mods-where-var-is)])
924-
(submodule-enclosing-bindings-visible? mod))]
925-
[(null? mods-where-var-is) #f]
926-
[else
927-
(and (equal? (car mods-where-var-is)
928-
(car mods-where-binder-is))
929-
(loop (cdr mods-where-var-is)
930-
(cdr mods-where-binder-is)))]))))
931-
(when binder-is-outside-reference?
932-
(connect-syntaxes binder var actual? all-binders phase-level connections #f))))
923+
(when (equal? (syntax->datum binder) (syntax->datum var))
924+
(define binder-is-outside-reference?
925+
(or (not mods-where-var-is)
926+
(not (binder+mods-mods binder+mods))
927+
(let loop ([mods-where-var-is (reverse mods-where-var-is)]
928+
[mods-where-binder-is (reverse (binder+mods-mods binder+mods))])
929+
(cond
930+
[(null? mods-where-binder-is)
931+
(for/and ([mod (in-list mods-where-var-is)])
932+
(submodule-enclosing-bindings-visible? mod))]
933+
[(null? mods-where-var-is) #f]
934+
[else
935+
(and (equal? (car mods-where-var-is)
936+
(car mods-where-binder-is))
937+
(loop (cdr mods-where-var-is)
938+
(cdr mods-where-binder-is)))]))))
939+
(when binder-is-outside-reference?
940+
(connect-syntaxes binder var actual? all-binders phase-level connections #f)))))
933941

934942
(when (and unused/phases phase-to-requires)
935943
(define req-path/pr (get-module-req-path var phase-level))
@@ -964,10 +972,11 @@
964972
(when req-binder+modss
965973
(define unused (hash-ref unused/phases require-hash-key #f))
966974
(when unused (hash-remove! unused req-path))
967-
(for ([binder+mods (in-list req-binder+modss)])
975+
(for ([require-context (in-list req-binder+modss)])
976+
(define binder+mods (require-context-b+m require-context))
968977
(define req-stx (binder+mods-binder binder+mods))
969978
(define match/prefix
970-
(id/require-match (syntax->datum var) id req-stx))
979+
(id/require-match (syntax->datum var) id require-context))
971980
(when match/prefix
972981
(when id
973982
(define-values (filename submods)
@@ -985,7 +994,8 @@
985994
(syntax-span match/prefix))
986995
(syntax-span match/prefix)]
987996
[else 0]))
988-
(define raw-module-path (phaseless-spec->raw-module-path req-stx))
997+
(define require-context (phaseless-spec->require-context mods req-stx))
998+
(define raw-module-path (binder+mods-binder (require-context-b+m require-context)))
989999
(add-mouse-over var
9901000
(format
9911001
(string-constant cs-mouse-over-import/library-only)
@@ -1018,40 +1028,34 @@
10181028
'module-lang
10191029
#t))))))))
10201030

1021-
(define (id/require-match var id req-stx)
1022-
(syntax-case* req-stx (only prefix all-except prefix-all-except rename)
1023-
symbolic-compare?
1024-
[(only raw-mod-path . ids)
1025-
(and (memq id (syntax->datum #'ids))
1026-
(eq? var id))]
1027-
[(prefix the-prefix raw-mod-path)
1028-
(and (equal? (format "~a~a" (syntax->datum #'the-prefix) id)
1029-
(symbol->string var))
1030-
#'the-prefix)]
1031-
[(all-except raw-mod-path . ids)
1032-
(and (eq? var id)
1033-
(not (member var (syntax->datum #'ids))))]
1034-
[(prefix-all-except the-prefix raw-mod-path . rest)
1035-
(and (not (memq id (syntax->datum #'rest)))
1036-
(equal? (format "~a~a" (syntax->datum #'the-prefix) id)
1037-
(symbol->string var))
1038-
#'the-prefix)]
1039-
[(rename raw-mod-path local-id exported-id)
1040-
(and (eq? (syntax->datum #'local-id) var))]
1041-
[raw-mod-path
1042-
(eq? var id)]))
1043-
1044-
(define (phaseless-spec->raw-module-path stx [found-local-id void])
1031+
(define (id/require-match var id require-context)
1032+
(define prefix (require-context-prefix require-context))
1033+
(cond
1034+
[prefix
1035+
(and (equal? (format "~a~a" (syntax->datum prefix) id) (symbol->string var))
1036+
(not (member var (map syntax-e (require-context-ids require-context))))
1037+
prefix)]
1038+
[(require-context-in? require-context)
1039+
(member var (map syntax-e (require-context-ids require-context)))]
1040+
[else
1041+
(and (not (member var (map syntax-e (require-context-ids require-context))))
1042+
(equal? var id))]))
1043+
1044+
(define (phaseless-spec->require-context mods stx [found-local-id void])
10451045
(syntax-case* stx (only prefix all-except prefix-all-except rename) symbolic-compare?
1046-
[(only raw-module-path id ...) #'raw-module-path]
1047-
[(prefix prefix-id raw-module-path) #'raw-module-path]
1048-
[(all-except raw-module-path id ...) #'raw-module-path]
1049-
[(prefix-all-except prefix-id raw-module-path id ...) #'raw-module-path]
1046+
[(only raw-module-path id ...)
1047+
(require-context (syntax->list #'(id ...)) #t #f (binder+mods #'raw-module-path mods))]
1048+
[(prefix prefix-id raw-module-path)
1049+
(require-context '() #f #'prefix-id (binder+mods #'raw-module-path mods))]
1050+
[(all-except raw-module-path id ...)
1051+
(require-context (syntax->list #'(id ...)) #f #f (binder+mods #'raw-module-path mods))]
1052+
[(prefix-all-except prefix-id raw-module-path id ...)
1053+
(require-context (syntax->list #'(id ...)) #t #'prefix-id (binder+mods #'raw-module-path mods))]
10501054
[(rename raw-module-path local-id exported-id)
10511055
(found-local-id #'local-id)
1052-
#'raw-module-path]
1053-
[_ stx]))
1054-
1056+
(require-context (list #'local-id) #t #f (binder+mods #'raw-module-path mods))]
1057+
[_
1058+
(require-context '() #f #f (binder+mods stx mods))]))
10551059

10561060
;; get-module-req-path : identifier number [#:nominal? boolean]
10571061
;; -> (union #f (list require-sexp sym ?? module-path-index? phase+space?))
@@ -1391,22 +1395,6 @@
13911395
[_
13921396
null]))
13931397

1394-
;; trim-require-prefix : syntax -> syntax
1395-
(define (trim-require-prefix require-spec)
1396-
(syntax-case* require-spec (only prefix all-except prefix-all-except rename)
1397-
symbolic-compare?
1398-
[(only module-name identifier ...)
1399-
(syntax module-name)]
1400-
[(prefix identifier module-name)
1401-
(syntax module-name)]
1402-
[(all-except module-name identifier ...)
1403-
(syntax module-name)]
1404-
[(prefix-all-except module-name identifier ...)
1405-
(syntax module-name)]
1406-
[(rename module-name local-identifier exported-identifier)
1407-
(syntax module-name)]
1408-
[_ require-spec]))
1409-
14101398
(define (symbolic-compare? x y) (eq? (syntax-e x) (syntax-e y)))
14111399

14121400
;; add-binders : syntax id-set (or/c #f id-set) (or/c #f syntax) integer -> void

0 commit comments

Comments
 (0)