diff --git a/default-recommendations/syntax-shortcuts-test.rkt b/default-recommendations/syntax-shortcuts-test.rkt index 147ffdd..3cc1ced 100644 --- a/default-recommendations/syntax-shortcuts-test.rkt +++ b/default-recommendations/syntax-shortcuts-test.rkt @@ -53,3 +53,18 @@ test: "making a symbol with format from a keyword can be simplified to format-sy test: "making a symbol with format from a keyword syntax object can be simplified to format-symbol" - (string->symbol (format "make-~a" (keyword->string (syntax-e #'#:foo)))) - (format-symbol "make-~a" #'#:foo) + + +test: "flattening nested syntax templates with apply append can be simplified" +-------------------- +(require racket/syntax) +(define (f stx) + (with-syntax ([((a ...) ...) stx]) + (apply append + (map syntax->list (syntax->list #'((a ...) ...)))))) +==================== +(require racket/syntax) +(define (f stx) + (with-syntax ([((a ...) ...) stx]) + (syntax->list (syntax (a ... ...))))) +-------------------- diff --git a/default-recommendations/syntax-shortcuts.rkt b/default-recommendations/syntax-shortcuts.rkt index 2ff8ce1..7b4e29a 100644 --- a/default-recommendations/syntax-shortcuts.rkt +++ b/default-recommendations/syntax-shortcuts.rkt @@ -11,6 +11,7 @@ (require racket/string racket/syntax + racket/list rebellion/private/static-name resyntax/base syntax/parse) @@ -103,6 +104,28 @@ (format-symbol template (~replacement arg.simplified #:original arg) ...)) +(define-refactoring-rule flatten-apply-append-syntax-template + #:description + "Flattening nested syntax templates with `apply append` and `map syntax->list` can be simplified\ + by using a single `syntax->list` call on a flattened template." + #:literals (apply append map syntax->list syntax ...) + + (apply append (map syntax->list (syntax->list (syntax ((inner ...) ...))))) + + #:with flattened-template + (let* ([inner-attrs (attribute inner)] + ; When matching ((inner ...) ...), the inner attribute contains the elements from + ; within each nested list. If there's only one element, inner-attrs will be a single + ; syntax object, otherwise it's a list. We need a list for appending the ellipses. + [inner-list (if (list? inner-attrs) inner-attrs (list inner-attrs))] + [ellipsis-sym (datum->syntax #'here '...)]) + ; Construct (inner-elements ... ...) by appending two ellipsis symbols + (datum->syntax #'here (append inner-list (make-list 2 ellipsis-sym)))) + + (syntax->list #'flattened-template)) + + (define-refactoring-suite syntax-shortcuts - #:rules (format-string-to-format-symbol + #:rules (flatten-apply-append-syntax-template + format-string-to-format-symbol syntax-e-in-format-id-unnecessary))