From 9a3981f9784c9429f01d7958f977d2aa5375b931 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:03:53 +0000 Subject: [PATCH 1/3] Initial plan From d2935a5a988f9967ea42ed92d30dad9a640b2cd4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:20:35 +0000 Subject: [PATCH 2/3] Add keep-sorted macro and refactoring rule for maintaining sorted lists Co-authored-by: jackfirth <8175575+jackfirth@users.noreply.github.com> --- default-recommendations.rkt | 3 ++ .../keep-sorted-suggestions-test.rkt | 54 +++++++++++++++++++ .../keep-sorted-suggestions.rkt | 53 ++++++++++++++++++ keep-sorted.rkt | 26 +++++++++ 4 files changed, 136 insertions(+) create mode 100644 default-recommendations/keep-sorted-suggestions-test.rkt create mode 100644 default-recommendations/keep-sorted-suggestions.rkt create mode 100644 keep-sorted.rkt diff --git a/default-recommendations.rkt b/default-recommendations.rkt index dd32c8a..b0fbe7f 100644 --- a/default-recommendations.rkt +++ b/default-recommendations.rkt @@ -18,6 +18,7 @@ resyntax/default-recommendations/function-definition-shortcuts resyntax/default-recommendations/function-shortcuts resyntax/default-recommendations/hash-shortcuts + resyntax/default-recommendations/keep-sorted-suggestions resyntax/default-recommendations/legacy/define-simple-macro-migration resyntax/default-recommendations/legacy/legacy-contract-migrations resyntax/default-recommendations/legacy/legacy-struct-migrations @@ -60,6 +61,7 @@ resyntax/default-recommendations/function-definition-shortcuts resyntax/default-recommendations/function-shortcuts resyntax/default-recommendations/hash-shortcuts + resyntax/default-recommendations/keep-sorted-suggestions resyntax/default-recommendations/legacy/define-simple-macro-migration resyntax/default-recommendations/legacy/legacy-contract-migrations resyntax/default-recommendations/legacy/legacy-struct-migrations @@ -107,6 +109,7 @@ function-definition-shortcuts function-shortcuts hash-shortcuts + keep-sorted-suggestions legacy-contract-migrations ;; Excluded for lots of reasons. See the following github issues: diff --git a/default-recommendations/keep-sorted-suggestions-test.rkt b/default-recommendations/keep-sorted-suggestions-test.rkt new file mode 100644 index 0000000..63c6496 --- /dev/null +++ b/default-recommendations/keep-sorted-suggestions-test.rkt @@ -0,0 +1,54 @@ +#lang resyntax/test + + +require: resyntax/default-recommendations/keep-sorted-suggestions keep-sorted-suggestions + + +header: +-------------------- +#lang racket/base +(require resyntax/keep-sorted) +(define apple 'apple) +(define banana 'banana) +(define mango 'mango) +(define orange 'orange) +(define zebra 'zebra) +-------------------- + + +test: "unsorted marked list should be resorted" +------------------------------ +(void (keep-sorted (list apple orange banana))) +============================== +(void (keep-sorted (list apple banana orange))) +------------------------------ + + +test: "unsorted marked set should be resorted" +------------------------------ +(require racket/set) +(void (keep-sorted (set orange apple banana))) +============================== +(require racket/set) +(void (keep-sorted (set apple banana orange))) +------------------------------ + + +test: "unsorted marked vector should be resorted" +------------------------------ +(void (keep-sorted (vector zebra apple mango))) +============================== +(void (keep-sorted (vector apple mango zebra))) +------------------------------ + + +no-change-test: "already sorted marked list should not be changed" +------------------------------ +(void (keep-sorted (list apple banana orange))) +------------------------------ + + +no-change-test: "unmarked unsorted list should not be changed" +------------------------------ +(void (list orange apple banana)) +------------------------------ diff --git a/default-recommendations/keep-sorted-suggestions.rkt b/default-recommendations/keep-sorted-suggestions.rkt new file mode 100644 index 0000000..31d7cb1 --- /dev/null +++ b/default-recommendations/keep-sorted-suggestions.rkt @@ -0,0 +1,53 @@ +#lang racket/base + + +(require racket/contract/base) + + +(provide + (contract-out + [keep-sorted-suggestions refactoring-suite?])) + + +(require racket/list + racket/sequence + resyntax/base + syntax/parse + syntax/parse/define) + + +;@---------------------------------------------------------------------------------------------------- + + +;; Check if a list of identifiers is sorted alphabetically by their symbol names +(define (identifiers-sorted? ids) + (define id-list (sequence->list ids)) + (define id-strings (map (λ (id) (symbol->string (syntax-e id))) id-list)) + (equal? id-strings (sort id-strings stringlist ids) + stringstring (syntax-e id))))) + + +;; Syntax class for matching a list expression with identifier elements +(define-syntax-class list-of-ids + #:attributes (constructor [element 1] sorted?) + (pattern (constructor:id element:id ...) + #:attr sorted? (identifiers-sorted? (attribute element)))) + + +(define-refactoring-rule resort-keep-sorted-list + #:description "This list is marked with `keep-sorted` but its elements are not in sorted order." + body:list-of-ids + #:when (syntax-property this-syntax 'keep-sorted) + #:when (not (attribute body.sorted?)) + #:with (sorted-element ...) (sort-identifiers (attribute body.element)) + (body.constructor sorted-element ...)) + + +(define-refactoring-suite keep-sorted-suggestions + #:rules (resort-keep-sorted-list)) diff --git a/keep-sorted.rkt b/keep-sorted.rkt new file mode 100644 index 0000000..a9e3084 --- /dev/null +++ b/keep-sorted.rkt @@ -0,0 +1,26 @@ +#lang racket/base + + +(provide + keep-sorted) + + +(require (for-syntax racket/base + syntax/parse)) + + +;@---------------------------------------------------------------------------------------------------- + + +;; The keep-sorted macro marks a collection as needing to be kept in sorted order. +;; Resyntax refactoring rules can detect this syntax property and suggest reordering +;; the elements when they're not sorted. + +;; The macro expands to a syntax property on the inner expression that Resyntax can detect. +;; The first form in the list is ignored (it's the collection constructor like list, set, vector). + + +(define-syntax (keep-sorted stx) + (syntax-parse stx + [(_ body:expr) + (syntax-property #'body 'keep-sorted #true)])) From 688b3e7f1ee745ecc45d0e0c9b4db999f2e9ffa6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 17:22:26 +0000 Subject: [PATCH 3/3] Optimize keep-sorted-suggestions: extract shared helper function Co-authored-by: jackfirth <8175575+jackfirth@users.noreply.github.com> --- default-recommendations/keep-sorted-suggestions.rkt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/default-recommendations/keep-sorted-suggestions.rkt b/default-recommendations/keep-sorted-suggestions.rkt index 31d7cb1..86ed1e3 100644 --- a/default-recommendations/keep-sorted-suggestions.rkt +++ b/default-recommendations/keep-sorted-suggestions.rkt @@ -10,7 +10,6 @@ (require racket/list - racket/sequence resyntax/base syntax/parse syntax/parse/define) @@ -19,18 +18,20 @@ ;@---------------------------------------------------------------------------------------------------- +;; Convert an identifier syntax object to its string representation +(define (identifier->string id) + (symbol->string (syntax-e id))) + + ;; Check if a list of identifiers is sorted alphabetically by their symbol names (define (identifiers-sorted? ids) - (define id-list (sequence->list ids)) - (define id-strings (map (λ (id) (symbol->string (syntax-e id))) id-list)) + (define id-strings (map identifier->string ids)) (equal? id-strings (sort id-strings stringlist ids) - stringstring (syntax-e id))))) + (sort ids stringstring)) ;; Syntax class for matching a list expression with identifier elements