From 0d6c3a154061f8334ffd2bae074078eb78e15d78 Mon Sep 17 00:00:00 2001 From: Jack Firth Date: Tue, 7 Jul 2026 01:16:07 -0700 Subject: [PATCH 1/2] Add rules replacing call-with-output-file with display-to-file Adds two rules to the file-io-suggestions suite. A call-with-output-file expression whose procedure just displays a value to the port is rewritten to display-to-file, and one whose procedure consists of displayln calls is rewritten to display-lines-to-file. The rules only fire when the port is used as nothing but the last argument of the display calls, and Resyntax's existing binding correctness check discards the suggestions in modules that don't import racket/file. Fixes #673. Co-Authored-By: Claude Fable 5 --- .../file-io-suggestions-test.rkt | 87 +++++++++++++++++++ .../file-io-suggestions.rkt | 36 +++++++- 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/default-recommendations/file-io-suggestions-test.rkt b/default-recommendations/file-io-suggestions-test.rkt index 0875350d..986b2c12 100644 --- a/default-recommendations/file-io-suggestions-test.rkt +++ b/default-recommendations/file-io-suggestions-test.rkt @@ -11,6 +11,93 @@ header: ---------------------------------------- +test: "call-with-output-file displaying a value refactorable to display-to-file" +---------------------------------------- +(define (f path s) + (call-with-output-file path + (lambda (out) + (display s out)))) +======================================== +(define (f path s) + (display-to-file s path)) +---------------------------------------- + + +test: "call-with-output-file with λ displaying a value refactorable to display-to-file" +---------------------------------------- +(define (f path s) + (call-with-output-file path + (λ (out) + (display s out)))) +======================================== +(define (f path s) + (display-to-file s path)) +---------------------------------------- + + +test: "call-with-output-file displaying a line refactorable to display-lines-to-file" +---------------------------------------- +(define (f path s) + (call-with-output-file path + (lambda (out) + (displayln s out)))) +======================================== +(define (f path s) + (display-lines-to-file (list s) path)) +---------------------------------------- + + +test: "call-with-output-file displaying multiple lines refactorable to display-lines-to-file" +---------------------------------------- +(define (f path a b) + (call-with-output-file path + (lambda (out) + (displayln a out) + (displayln b out)))) +======================================== +(define (f path a b) + (display-lines-to-file (list a b) path)) +---------------------------------------- + + +no-change-test: "call-with-output-file with keyword arguments not refactorable" +---------------------------------------- +(define (f path s) + (call-with-output-file path + (lambda (out) + (displayln s out)) + #:exists 'replace)) +---------------------------------------- + + +no-change-test: "call-with-output-file displaying to a different port not refactorable" +---------------------------------------- +(define (f path s other-port) + (call-with-output-file path + (lambda (out) + (displayln s other-port)))) +---------------------------------------- + + +no-change-test: "call-with-output-file with displayed value depending on the port not refactorable" +---------------------------------------- +(define (f path) + (call-with-output-file path + (lambda (out) + (displayln (object-name out) out)))) +---------------------------------------- + + +no-change-test: "call-with-output-file with non-display body forms not refactorable" +---------------------------------------- +(define (f path s) + (call-with-output-file path + (lambda (out) + (displayln s out) + (flush-output out)))) +---------------------------------------- + + no-change-test: "should not migrate make-temporary-file without 'directory to make-temporary-directory" - (make-temporary-file #:copy-from #false) diff --git a/default-recommendations/file-io-suggestions.rkt b/default-recommendations/file-io-suggestions.rkt index 2e11c3a9..212d2a2d 100644 --- a/default-recommendations/file-io-suggestions.rkt +++ b/default-recommendations/file-io-suggestions.rkt @@ -9,12 +9,42 @@ [file-io-suggestions refactoring-suite?])) -(require rebellion/private/static-name - resyntax/base) +(require racket/file + racket/set + rebellion/private/static-name + resyntax/base + resyntax/default-recommendations/private/lambda-by-any-name + resyntax/default-recommendations/private/syntax-identifier-sets + syntax/parse) ;@---------------------------------------------------------------------------------------------------- +(define-refactoring-rule call-with-output-file-to-display-to-file + #:description + "This use of `call-with-output-file` can be replaced with a simpler call to `display-to-file`." + #:literals (call-with-output-file display) + (call-with-output-file path:expr + (_:lambda-by-any-name (out:id) (display v:expr out-use:id))) + #:when (free-identifier=? (attribute out-use) (attribute out)) + #:when (not (set-member? (syntax-free-identifiers (attribute v)) (attribute out))) + (display-to-file v path)) + + +(define-refactoring-rule call-with-output-file-to-display-lines-to-file + #:description + "This use of `call-with-output-file` can be replaced with a simpler call to\ + `display-lines-to-file`." + #:literals (call-with-output-file displayln) + (call-with-output-file path:expr + (_:lambda-by-any-name (out:id) (displayln v:expr out-use:id) ...+)) + #:when (for/and ([out-use-id (in-list (attribute out-use))]) + (free-identifier=? out-use-id (attribute out))) + #:when (not (set-member? (syntax-free-identifiers #'(v ...)) (attribute out))) + (display-lines-to-file (list v ...) path)) + + (define-refactoring-suite file-io-suggestions - #:rules ()) + #:rules (call-with-output-file-to-display-lines-to-file + call-with-output-file-to-display-to-file)) From dad695c2a47b729eeb38d964f71249a25d7fc260 Mon Sep 17 00:00:00 2001 From: Jack Firth Date: Tue, 7 Jul 2026 01:28:02 -0700 Subject: [PATCH 2/2] =?UTF-8?q?Combine=20lambda=20and=20=CE=BB=20test=20ca?= =?UTF-8?q?ses=20using=20a=20multi-case=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- default-recommendations/file-io-suggestions-test.rkt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/default-recommendations/file-io-suggestions-test.rkt b/default-recommendations/file-io-suggestions-test.rkt index 986b2c12..2f1447f0 100644 --- a/default-recommendations/file-io-suggestions-test.rkt +++ b/default-recommendations/file-io-suggestions-test.rkt @@ -18,13 +18,6 @@ test: "call-with-output-file displaying a value refactorable to display-to-file" (lambda (out) (display s out)))) ======================================== -(define (f path s) - (display-to-file s path)) ----------------------------------------- - - -test: "call-with-output-file with λ displaying a value refactorable to display-to-file" ----------------------------------------- (define (f path s) (call-with-output-file path (λ (out)