diff --git a/base.rkt b/base.rkt index 1d14d28..29f7b41 100644 --- a/base.rkt +++ b/base.rkt @@ -15,6 +15,7 @@ [refactoring-rule? (-> any/c boolean?)] [refactoring-rule-description (-> refactoring-rule? immutable-string?)] [refactoring-rule-analyzers (-> refactoring-rule? (set/c expansion-analyzer?))] + [refactoring-rule-suggestion-count (-> refactoring-rule? exact-nonnegative-integer?)] [refactoring-suite? (-> any/c boolean?)] [refactoring-suite (->* () @@ -108,7 +109,7 @@ [(_ new-stx) (syntax-property #'new-stx 'focus-replacement-on #true)])) -(define-object-type refactoring-rule (transformer description uses-universal-tagged-syntax? analyzers) +(define-object-type refactoring-rule (transformer description uses-universal-tagged-syntax? analyzers suggestion-count) #:omit-root-binding #:constructor-name constructor:refactoring-rule) @@ -143,7 +144,7 @@ parse-option:syntax-parse-option ... pattern pattern-directive:syntax-parse-pattern-directive ... - replacement) + (~or (~and #:no-suggestion no-suggestion-kw) replacement)) #:declare description (expr/c #'string?) #:declare analyzers (expr/c #'(sequence/c expansion-analyzer?)) @@ -155,6 +156,8 @@ (syntax-parse directive [(#:when condition:expr) #'(#:when (log-resyntax-rule-condition condition))] [_ directive])) + + #:with suggestion-count-val (datum->syntax #'id (if (attribute no-suggestion-kw) 0 1)) (define id (constructor:refactoring-rule @@ -162,13 +165,15 @@ #:description (string->immutable-string description.c) #:uses-universal-tagged-syntax? (~? uses-universal-tagged-syntax? #false) #:analyzers (for/set ([analyzer (~? analyzers.c '())]) analyzer) + #:suggestion-count suggestion-count-val #:transformer (λ (stx) (syntax-parse stx (~@ . parse-option) ... [pattern (~? (~@ #:do [partial-match-log-statement])) - (~@ . wrapped-pattern-directive) ... (present #'replacement)] + (~@ . wrapped-pattern-directive) ... + (~? (present #'replacement) (present #t))] [_ absent]))))) diff --git a/cli.rkt b/cli.rkt index f1917b1..7d880c8 100644 --- a/cli.rkt +++ b/cli.rkt @@ -300,18 +300,20 @@ For help on these, use 'analyze --help' or 'fix --help'." (match (resyntax-analyze-options-output-format options) [(== plain-text) (for ([result (in-list results)]) - (define path - (file-source-path - (syntax-replacement-source (refactoring-result-syntax-replacement result)))) + (define source (refactoring-result-source result)) + (define path (file-source-path source)) (define line (refactoring-result-original-line result)) (define column (refactoring-result-original-column result)) (printf "resyntax: ~a:~a:~a [~a]\n" path line column (refactoring-result-rule-name result)) (printf "\n\n~a\n" (string-indent (refactoring-result-message result) #:amount 2)) (define old-code (refactoring-result-original-code result)) (define new-code (refactoring-result-new-code result)) - (printf "\n\n~a\n\n\n~a\n\n\n" - (string-indent (~a old-code) #:amount 2) - (string-indent (~a new-code) #:amount 2)))] + (if new-code + (printf "\n\n~a\n\n\n~a\n\n\n" + (string-indent (~a old-code) #:amount 2) + (string-indent (~a new-code) #:amount 2)) + (printf "\n\n~a\n\n\n" + (string-indent (~a old-code) #:amount 2))))] [(== github-pull-request-review) (define req (refactoring-results->github-review results #:file-count (hash-count sources))) (write-json (github-review-request-jsexpr req))])) diff --git a/main.rkt b/main.rkt index a9db4eb..f00563a 100644 --- a/main.rkt +++ b/main.rkt @@ -382,48 +382,65 @@ syntax (string-indent (exn-message e) #:amount 3)) absent)]) - (guarded-block - (guard-match (present replacement) - (parameterize ([current-namespace (source-code-analysis-namespace analysis)]) - (refactoring-rule-refactor rule syntax (source-code-analysis-code analysis))) - #:else absent) - (guard (syntax-replacement-introduces-incorrect-bindings? replacement) #:else - (define bad-ids (syntax-replacement-introduced-incorrect-identifiers replacement)) - (define orig-stx (syntax-replacement-original-syntax replacement)) - (define intro (syntax-replacement-introduction-scope replacement)) - (log-resyntax-warning - (string-append - "~a: suggestion discarded because it introduces identifiers with incorrect bindings\n" - " incorrect identifiers: ~a\n" - " bindings in original context: ~a\n" - " bindings in syntax replacement: ~a\n" - " replaced syntax: ~a") - (object-name rule) - bad-ids - (for/list ([id (in-list bad-ids)]) - (identifier-binding (datum->syntax orig-stx (syntax->datum id)))) - (for/list ([id (in-list bad-ids)]) - (identifier-binding (intro id 'remove))) - orig-stx) - absent) - (guard (syntax-replacement-preserves-comments? replacement comments) #:else - (log-resyntax-warning - (string-append "~a: suggestion discarded because it does not preserve all comments\n" - " dropped comment locations: ~v\n" - " original syntax:\n" - " ~v\n" - " replacement syntax:\n" - " ~v") - (object-name rule) - (syntax-replacement-dropped-comment-locations replacement comments) - (syntax-replacement-original-syntax replacement) - (syntax-replacement-new-syntax replacement)) - absent) - (present - (refactoring-result - #:rule-name (object-name rule) - #:message (refactoring-rule-description rule) - #:syntax-replacement replacement))))) + ;; Check if this is a warning-only rule + (cond + [(zero? (refactoring-rule-suggestion-count rule)) + ;; For warning-only rules, try to match the pattern + (define match-result + (parameterize ([current-namespace (source-code-analysis-namespace analysis)]) + (refactoring-rule-refactor rule syntax (source-code-analysis-code analysis)))) + ;; If pattern matched, create a warning result + (option-map match-result + (λ (_) + (warning-result + #:rule-name (object-name rule) + #:message (refactoring-rule-description rule) + #:source (source-code-analysis-code analysis) + #:original-syntax syntax)))] + [else + ;; For rules with fixes, validate and create a regular refactoring result + (guarded-block + (guard-match (present replacement) + (parameterize ([current-namespace (source-code-analysis-namespace analysis)]) + (refactoring-rule-refactor rule syntax (source-code-analysis-code analysis))) + #:else absent) + (guard (syntax-replacement-introduces-incorrect-bindings? replacement) #:else + (define bad-ids (syntax-replacement-introduced-incorrect-identifiers replacement)) + (define orig-stx (syntax-replacement-original-syntax replacement)) + (define intro (syntax-replacement-introduction-scope replacement)) + (log-resyntax-warning + (string-append + "~a: suggestion discarded because it introduces identifiers with incorrect bindings\n" + " incorrect identifiers: ~a\n" + " bindings in original context: ~a\n" + " bindings in syntax replacement: ~a\n" + " replaced syntax: ~a") + (object-name rule) + bad-ids + (for/list ([id (in-list bad-ids)]) + (identifier-binding (datum->syntax orig-stx (syntax->datum id)))) + (for/list ([id (in-list bad-ids)]) + (identifier-binding (intro id 'remove))) + orig-stx) + absent) + (guard (syntax-replacement-preserves-comments? replacement comments) #:else + (log-resyntax-warning + (string-append "~a: suggestion discarded because it does not preserve all comments\n" + " dropped comment locations: ~v\n" + " original syntax:\n" + " ~v\n" + " replacement syntax:\n" + " ~v") + (object-name rule) + (syntax-replacement-dropped-comment-locations replacement comments) + (syntax-replacement-original-syntax replacement) + (syntax-replacement-new-syntax replacement)) + absent) + (present + (refactoring-result + #:rule-name (object-name rule) + #:message (refactoring-rule-description rule) + #:syntax-replacement replacement)))]))) (falsey->option (for*/first ([rule (in-list rules)] diff --git a/private/github.rkt b/private/github.rkt index dcfe4f1..f93ec00 100644 --- a/private/github.rkt +++ b/private/github.rkt @@ -93,11 +93,14 @@ (define (refactoring-result->github-review-comment result) - (define path - (file-source-path (syntax-replacement-source (refactoring-result-syntax-replacement result)))) - (define replacement (refactoring-result-line-replacement result)) - (define body - (format #< EOS - (refactoring-result-rule-name result) - (refactoring-result-message result) - (line-replacement-new-text replacement) - (string-indent (pretty-format replacement) #:amount 2) - (string-indent (pretty-format (refactoring-result-syntax-replacement result)) - #:amount 2))) - (github-review-comment - #:path (first (git-path path)) - #:body body - #:start-line (line-replacement-start-line replacement) - #:end-line (line-replacement-original-end-line replacement) - #:start-side "RIGHT" - #:end-side "RIGHT")) + (refactoring-result-rule-name result) + (refactoring-result-message result) + (line-replacement-new-text replacement) + (string-indent (pretty-format replacement) #:amount 2) + (string-indent (pretty-format (refactoring-result-syntax-replacement result)) + #:amount 2))) + (github-review-comment + #:path (first (git-path path)) + #:body body + #:start-line (line-replacement-start-line replacement) + #:end-line (line-replacement-original-end-line replacement) + #:start-side "RIGHT" + #:end-side "RIGHT")] + [else + ;; For warning-only results, generate a comment without a suggestion + (define source (refactoring-result-source result)) + (define path (file-source-path source)) + (define line (refactoring-result-original-line result)) + (define body + (format "**`~a`:** ~a" + (refactoring-result-rule-name result) + (refactoring-result-message result))) + (github-review-comment + #:path (first (git-path path)) + #:body body + #:start-line line + #:end-line line + #:start-side "RIGHT" + #:end-side "RIGHT")])) (define branch-ref (getenv "GITHUB_REF")) diff --git a/private/refactoring-result.rkt b/private/refactoring-result.rkt index 9b5d5ed..175a9e2 100644 --- a/private/refactoring-result.rkt +++ b/private/refactoring-result.rkt @@ -8,22 +8,29 @@ (contract-out [refactoring-result? (-> any/c boolean?)] [refactoring-result + (->* (#:rule-name interned-symbol? + #:message string?) + (#:syntax-replacement (or/c syntax-replacement? #false)) + refactoring-result?)] + [warning-result (-> #:rule-name interned-symbol? #:message string? - #:syntax-replacement syntax-replacement? + #:source source? + #:original-syntax syntax? refactoring-result?)] [refactoring-result-rule-name (-> refactoring-result? interned-symbol?)] [refactoring-result-message (-> refactoring-result? immutable-string?)] [refactoring-result-source (-> refactoring-result? source?)] + [refactoring-result-has-fix? (-> refactoring-result? boolean?)] [refactoring-result-modified-range (-> refactoring-result? range?)] [refactoring-result-modified-line-range (-> refactoring-result? range?)] - [refactoring-result-syntax-replacement (-> refactoring-result? syntax-replacement?)] - [refactoring-result-string-replacement (-> refactoring-result? string-replacement?)] - [refactoring-result-line-replacement (-> refactoring-result? line-replacement?)] + [refactoring-result-syntax-replacement (-> refactoring-result? (or/c syntax-replacement? #false))] + [refactoring-result-string-replacement (-> refactoring-result? (or/c string-replacement? #false))] + [refactoring-result-line-replacement (-> refactoring-result? (or/c line-replacement? #false))] [refactoring-result-original-line (-> refactoring-result? exact-positive-integer?)] [refactoring-result-original-column (-> refactoring-result? exact-nonnegative-integer?)] [refactoring-result-original-code (-> refactoring-result? code-snippet?)] - [refactoring-result-new-code (-> refactoring-result? code-snippet?)] + [refactoring-result-new-code (-> refactoring-result? (or/c code-snippet? #false))] [refactoring-result-set? (-> any/c boolean?)] [refactoring-result-set (-> #:base-source source? #:results (sequence/c refactoring-result?) refactoring-result-set?)] @@ -62,45 +69,88 @@ (define-record-type refactoring-result - (rule-name message syntax-replacement string-replacement line-replacement) + (rule-name message source original-syntax syntax-replacement string-replacement line-replacement) #:omit-root-binding) -(define (refactoring-result #:rule-name rule-name #:message message #:syntax-replacement replacement) +(define (refactoring-result #:rule-name rule-name + #:message message + #:syntax-replacement [replacement #false]) + (unless replacement + (raise-arguments-error 'refactoring-result + "must provide either #:syntax-replacement" + "rule-name" + rule-name + "message" + message)) (define str-replacement (syntax-replacement-render replacement)) (define full-orig-code (source->string (syntax-replacement-source replacement))) (constructor:refactoring-result #:rule-name rule-name #:message (string->immutable-string message) + #:source (syntax-replacement-source replacement) + #:original-syntax (syntax-replacement-original-syntax replacement) #:syntax-replacement replacement #:string-replacement str-replacement #:line-replacement (string-replacement->line-replacement str-replacement full-orig-code))) -(define (refactoring-result-source result) - (syntax-replacement-source (refactoring-result-syntax-replacement result))) +(define (warning-result #:rule-name rule-name #:message message #:source source #:original-syntax original-syntax) + (constructor:refactoring-result + #:rule-name rule-name + #:message (string->immutable-string message) + #:source source + #:original-syntax original-syntax + #:syntax-replacement #false + #:string-replacement #false + #:line-replacement #false)) + + +(define (refactoring-result-has-fix? result) + (and (refactoring-result-syntax-replacement result) #true)) (define (refactoring-result-modified-range result) - (define replacement (refactoring-result-string-replacement result)) - (closed-open-range (add1 (string-replacement-start replacement)) - (add1 (string-replacement-original-end replacement)) - #:comparator natural<=>)) + (cond + [(refactoring-result-has-fix? result) + (define replacement (refactoring-result-string-replacement result)) + (closed-open-range (add1 (string-replacement-start replacement)) + (add1 (string-replacement-original-end replacement)) + #:comparator natural<=>)] + [else + (define orig-stx (refactoring-result-original-syntax result)) + (define pos (syntax-position orig-stx)) + (define span (syntax-span orig-stx)) + (if (and pos span) + (closed-open-range pos (+ pos span) #:comparator natural<=>) + (closed-open-range 1 2 #:comparator natural<=>))])) (define (refactoring-result-modified-line-range result) - (define replacement (refactoring-result-line-replacement result)) - (closed-open-range (line-replacement-start-line replacement) - (line-replacement-original-end-line replacement) - #:comparator natural<=>)) + (cond + [(refactoring-result-has-fix? result) + (define replacement (refactoring-result-line-replacement result)) + (closed-open-range (line-replacement-start-line replacement) + (line-replacement-original-end-line replacement) + #:comparator natural<=>)] + [else + (define orig-stx (refactoring-result-original-syntax result)) + (define line (syntax-line orig-stx)) + (if line + (closed-range line line #:comparator natural<=>) + (closed-range 1 1 #:comparator natural<=>))])) (define (refactoring-result-original-line result) - (line-replacement-start-line (refactoring-result-line-replacement result))) + (if (refactoring-result-has-fix? result) + (line-replacement-start-line (refactoring-result-line-replacement result)) + (or (syntax-line (refactoring-result-original-syntax result)) 1))) (define (refactoring-result-original-column result) - (code-snippet-start-column (refactoring-result-original-code result))) + (if (refactoring-result-has-fix? result) + (code-snippet-start-column (refactoring-result-original-code result)) + (or (syntax-column (refactoring-result-original-syntax result)) 0))) (define-record-type refactoring-result-set (base-source results) @@ -116,6 +166,7 @@ (define (refactoring-result-set-updated-source result-set) (define replacement (transduce (refactoring-result-set-results result-set) + (filtering refactoring-result-has-fix?) (mapping refactoring-result-string-replacement) #:into union-into-string-replacement)) (define base (refactoring-result-set-base-source result-set)) @@ -141,6 +192,7 @@ (define rule-names (transduce (in-hash-values result-map) (append-mapping refactoring-result-set-results) + (filtering refactoring-result-has-fix?) ; Only include results with fixes (mapping refactoring-result-rule-name) (deduplicating) #:into into-list)) @@ -154,13 +206,15 @@ (define rule-results (for*/list ([results (in-hash-values result-map)] [result (in-list (refactoring-result-set-results results))] - #:when (equal? (refactoring-result-rule-name result) rule)) + #:when (and (equal? (refactoring-result-rule-name result) rule) + (refactoring-result-has-fix? result))) result)) (define replacements (for/hash ([(source results) (in-hash result-map)]) (define source-replacements (transduce (refactoring-result-set-results results) - (filtering (λ (r) (equal? (refactoring-result-rule-name r) rule))) + (filtering (λ (r) (and (equal? (refactoring-result-rule-name r) rule) + (refactoring-result-has-fix? r)))) (mapping refactoring-result-string-replacement) #:into (into-sorted-set string-replacement<=>))) (values source source-replacements))) @@ -186,28 +240,48 @@ (define (refactoring-result-original-code result) - (define replacement (refactoring-result-string-replacement result)) - (define full-orig-code - (source->string (syntax-replacement-source (refactoring-result-syntax-replacement result)))) - (define lmap (string-linemap full-orig-code)) - (define start (string-replacement-start replacement)) - (define end (string-replacement-original-end replacement)) - (define start-column (- (add1 start) (linemap-position-to-start-of-line lmap (add1 start)))) - (define raw-text (string->immutable-string (substring full-orig-code start end))) - (code-snippet raw-text start-column (linemap-position-to-line lmap (add1 start)))) + (cond + [(refactoring-result-has-fix? result) + (define replacement (refactoring-result-string-replacement result)) + (define full-orig-code + (source->string (syntax-replacement-source (refactoring-result-syntax-replacement result)))) + (define lmap (string-linemap full-orig-code)) + (define start (string-replacement-start replacement)) + (define end (string-replacement-original-end replacement)) + (define start-column (- (add1 start) (linemap-position-to-start-of-line lmap (add1 start)))) + (define raw-text (string->immutable-string (substring full-orig-code start end))) + (code-snippet raw-text start-column (linemap-position-to-line lmap (add1 start)))] + [else + (define orig-stx (refactoring-result-original-syntax result)) + (define source (refactoring-result-source result)) + (define full-orig-code (source->string source)) + (define pos (syntax-position orig-stx)) + (define span (syntax-span orig-stx)) + (define line (or (syntax-line orig-stx) 1)) + (define col (or (syntax-column orig-stx) 0)) + (cond + [(and pos span) + (define start (sub1 pos)) + (define end (+ start span)) + (define raw-text (string->immutable-string (substring full-orig-code start end))) + (code-snippet raw-text col line)] + [else (code-snippet "" col line)])])) (define (refactoring-result-new-code result) - (define replacement (refactoring-result-string-replacement result)) - (define full-orig-code - (source->string (syntax-replacement-source (refactoring-result-syntax-replacement result)))) - (define lmap (string-linemap full-orig-code)) - (define start (string-replacement-start replacement)) - (define original-line (linemap-position-to-line lmap (add1 start))) - (define original-column (- (add1 start) (linemap-position-to-start-of-line lmap (add1 start)))) - (define refactored-source-code (string-apply-replacement full-orig-code replacement)) - (define new-code-string - (substring refactored-source-code - (string-replacement-start replacement) - (string-replacement-new-end replacement))) - (code-snippet new-code-string original-column original-line)) + (cond + [(refactoring-result-has-fix? result) + (define replacement (refactoring-result-string-replacement result)) + (define full-orig-code + (source->string (syntax-replacement-source (refactoring-result-syntax-replacement result)))) + (define lmap (string-linemap full-orig-code)) + (define start (string-replacement-start replacement)) + (define original-line (linemap-position-to-line lmap (add1 start))) + (define original-column (- (add1 start) (linemap-position-to-start-of-line lmap (add1 start)))) + (define refactored-source-code (string-apply-replacement full-orig-code replacement)) + (define new-code-string + (substring refactored-source-code + (string-replacement-start replacement) + (string-replacement-new-end replacement))) + (code-snippet new-code-string original-column original-line)] + [else #f])) diff --git a/private/warning-rule-test.rkt b/private/warning-rule-test.rkt new file mode 100644 index 0000000..318adc6 --- /dev/null +++ b/private/warning-rule-test.rkt @@ -0,0 +1,45 @@ +#lang racket/base + +(require racket/list + resyntax/base + resyntax + resyntax/private/refactoring-result + resyntax/private/source + rackunit) + +;; Define a warning-only rule that matches any (equal? x y) +(define-refactoring-rule test-warning-rule + #:description "This is a test warning rule for equal?" + #:literals (equal?) + (equal? x y) + #:no-suggestion) + +;; Test that the rule works +(define test-suite (refactoring-suite #:rules (list test-warning-rule))) + +(define test-source (string-source "#lang racket/base\n(define a 5)\n(equal? a a)\n")) + +(define result-set (resyntax-analyze test-source #:suite test-suite)) + +(define results (refactoring-result-set-results result-set)) + +(test-case "warning-only rule produces a result" + (check-equal? (length results) 1 "Should have one result")) + +(test-case "warning-only result has no fix" + (define result (first results)) + (check-false (refactoring-result-has-fix? result) "Should not have a fix") + (check-false (refactoring-result-syntax-replacement result) "Should have no syntax replacement") + (check-false (refactoring-result-new-code result) "Should have no new code")) + +( test-case "warning-only result has message and location" + (define result (first results)) + (check-equal? (refactoring-result-message result) "This is a test warning rule for equal?") + (check-equal? (refactoring-result-rule-name result) 'test-warning-rule) + (check-true (positive? (refactoring-result-original-line result)))) + +(test-case "warning-only result doesn't modify source" + (define updated (refactoring-result-set-updated-source result-set)) + (define updated-contents (modified-source-contents updated)) + (check-equal? updated-contents (source->string test-source) + "Source should not be modified")) diff --git a/test-warning-suite.rkt b/test-warning-suite.rkt new file mode 100644 index 0000000..1e00711 --- /dev/null +++ b/test-warning-suite.rkt @@ -0,0 +1,15 @@ +#lang racket/base + +(require resyntax/base) + +(provide test-warning-suite) + +;; Define a warning-only rule that matches any (equal? x y) +(define-refactoring-rule test-warning-rule + #:description "Test warning rule for equal?" + #:literals (equal?) + (equal? x y) + #:no-suggestion) + +(define test-warning-suite + (refactoring-suite #:rules (list test-warning-rule))) diff --git a/test.rkt b/test.rkt index 2703e32..d5af787 100644 --- a/test.rkt +++ b/test.rkt @@ -8,7 +8,8 @@ header test no-change-test - analysis-test) + analysis-test + comment-only-test) (require (for-syntax racket/base @@ -228,6 +229,25 @@ 'expected-value)))])))) +(define-syntax comment-only-test + (statement-transformer + (λ (stx) + (syntax-parse stx + #:track-literals + #:datum-literals (option @within @inspect @assertMatch) + [(#:statement _ name:str + code:literal-code + (~seq (#:option #:within context-block:literal-code) ... + (#:option #:inspect target-block:literal-code) + (#:option #:assertMatch rule-name:id))) + #`(test-case 'name + #,(syntax/loc this-syntax + (check-suite-comment-only code + (list context-block ...) + target-block + 'rule-name)))])))) + + ;; Helper function to check if any require: statements are present (begin-for-syntax (define (has-require-statements? body-stxs) @@ -400,7 +420,7 @@ (define (add-uts-properties stx) (syntax-traverse stx - #:datum-literals (require header test no-change-test analysis-test) + #:datum-literals (require header test no-change-test analysis-test comment-only-test) [:id (define as-string (symbol->string (syntax-e this-syntax))) @@ -425,7 +445,7 @@ (add-uts-properties (attribute code)))) (datum->syntax #false new-datum this-syntax this-syntax)] - [((~and tag #:statement) (~and test-id (~or test no-change-test analysis-test)) arg ...) + [((~and tag #:statement) (~and test-id (~or test no-change-test analysis-test comment-only-test)) arg ...) (define separators (append (list "" ": " "\n") (make-list (length (attribute arg)) ""))) (define tag-with-prop (syntax-property (attribute tag) 'uts-separators separators)) (define new-datum diff --git a/test/comment-only-test-demo.rkt b/test/comment-only-test-demo.rkt new file mode 100644 index 0000000..4188060 --- /dev/null +++ b/test/comment-only-test-demo.rkt @@ -0,0 +1,15 @@ +#lang resyntax/test + + +require: resyntax/test-warning-suite test-warning-suite + + +comment-only-test: "warning-only rule should produce a comment" +-------------------- +#lang racket/base + +(define a 5) +(equal? a a) +-------------------- +@inspect - (equal? a a) +@assertMatch test-warning-rule diff --git a/test/private/rackunit.rkt b/test/private/rackunit.rkt index 424d4f4..4779aca 100644 --- a/test/private/rackunit.rkt +++ b/test/private/rackunit.rkt @@ -12,7 +12,8 @@ add-suite-under-test! check-suite-refactors check-suite-does-not-refactor - check-suite-analysis) + check-suite-analysis + check-suite-comment-only) (require racket/logging @@ -312,6 +313,47 @@ (fail-check "analysis assigned an incorrect value for the given syntax property key")))) +(define-check (check-suite-comment-only program context-list target rule-name) + (define suite (current-suite-under-test)) + (set! program (code-block-append (current-header) program)) + (define program-src (string-source (code-block-raw-string program))) + (define-values (call-with-logs-captured build-logs-info) (make-log-capture-utilities)) + + (define result-set + (call-with-logs-captured + (λ () (resyntax-analyze program-src + #:suite suite + #:timeout-ms (current-analyzer-timeout-millis))))) + + (define results (refactoring-result-set-results result-set)) + + ;; Find target location + (define target-src (string-source (string-trim (code-block-raw-string target)))) + (define context-src-list + (for/list ([ctx (in-list context-list)]) + (string-source (string-trim (code-block-raw-string ctx))))) + + ;; Try to find a result that matches the target location and rule name + (define matching-results + (for/list ([result (in-list results)] + #:when (and (equal? (refactoring-result-rule-name result) rule-name) + (not (refactoring-result-has-fix? result)))) + result)) + + (with-check-info (['logs (build-logs-info)] + ['program (string-block-info (string-source-contents program-src))] + ['target (string-block-info (string-source-contents target-src))] + ['rule-name rule-name]) + (when (empty? matching-results) + (fail-check "no warning-only result found for the specified rule")) + + (when (> (length matching-results) 1) + (fail-check (format "found ~a warning-only results, expected exactly 1" (length matching-results)))) + + ;; Success - we found exactly one matching warning-only result + (void))) + + (define (source-find-path-of src target-src #:contexts [context-srcs '()]) (define stx (syntax-label-paths (source-read-syntax src) 'source-path)) (define target-as-string (string-source-contents target-src))