summaryrefslogtreecommitdiff
path: root/guix/deprecation.scm
blob: 2f7c05894026db9784d07b109b628466e7932251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (guix deprecation)
  #:use-module (guix i18n)
  #:use-module (ice-9 format)
  #:export (define-deprecated
            define-deprecated/alias
            deprecation-warning-port))

;;; Commentary:
;;;
;;; Provide a mechanism to mark bindings as deprecated.
;;;
;;; We don't reuse (guix ui) mostly to avoid pulling in too many things.
;;;
;;; Code:

(define deprecation-warning-port
  ;; Port where deprecation warnings go.
  (make-parameter (current-error-port)))

(define (source-properties->location-string properties)
  "Return a human-friendly, GNU-standard representation of PROPERTIES, a
source property alist."
  (let ((file   (assq-ref properties 'filename))
        (line   (assq-ref properties 'line))
        (column (assq-ref properties 'column)))
    (if (and file line column)
        (format #f "~a:~a:~a" file (+ 1 line) column)
        (G_ "<unknown location>"))))

(define* (warn-about-deprecation variable properties
                                 #:key replacement)
  (format (deprecation-warning-port)
          (G_ "~a: warning: '~a' is deprecated~@[, use '~a' instead~]~%")
          (source-properties->location-string properties)
          variable replacement))

(define-syntax define-deprecated
  (lambda (s)
    "Define a deprecated variable or procedure, along these lines:

  (define-deprecated foo bar 42)
  (define-deprecated (baz x y) qux (qux y x))

This will write a deprecation warning to DEPRECATION-WARNING-PORT."
    (syntax-case s ()
      ((_ (proc formals ...) replacement body ...)
       #'(define-deprecated proc replacement
           (lambda* (formals ...) body ...)))
      ((_ variable replacement exp)
       (identifier? #'variable)
       (with-syntax ((real (datum->syntax
                            #'variable
                            (symbol-append '%
                                           (syntax->datum #'variable)
                                           '/deprecated))))
         #`(begin
             (define real
               (begin
                 (lambda () replacement)          ;just to ensure it's bound
                 exp))

             (define-syntax variable
               (lambda (s)
                 (warn-about-deprecation 'variable (syntax-source s)
                                         #:replacement 'replacement)
                 (syntax-case s ()
                   ((_ args (... ...))
                    #'(real args (... ...)))
                   (id
                    (identifier? #'id)
                    #'real))))))))))

(define-syntax-rule (define-deprecated/alias deprecated replacement)
  "Define as an alias a deprecated variable, procedure, or macro, along
these lines:

  (define-deprecated/alias nix-server? store-connection?)

where 'nix-server?' is the deprecated name for 'store-connection?'.

This will write a deprecation warning to DEPRECATION-WARNING-PORT."
  (define-syntax deprecated
    (lambda (s)
      (warn-about-deprecation 'deprecated (syntax-source s)
                              #:replacement 'replacement)
      (syntax-case s ()
        ((_ args (... ...))
         #'(replacement args (... ...)))
        (id
         (identifier? #'id)
         #'replacement)))))