guix-more/more/build/maven/plugin.scm

plugin.scm

1
;;; GNU Guix --- Functional package management for GNU
2
;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
3
;;;
4
;;; This file is part of GNU Guix.
5
;;;
6
;;; GNU Guix is free software; you can redistribute it and/or modify it
7
;;; under the terms of the GNU General Public License as published by
8
;;; the Free Software Foundation; either version 3 of the License, or (at
9
;;; your option) any later version.
10
;;;
11
;;; GNU Guix is distributed in the hope that it will be useful, but
12
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
;;; GNU General Public License for more details.
15
;;;
16
;;; You should have received a copy of the GNU General Public License
17
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
18
19
(define-module (more build maven plugin)
20
  #:use-module (more build maven java)
21
  #:use-module (ice-9 textual-ports)
22
  #:use-module (ice-9 match)
23
  #:use-module (srfi srfi-9)
24
  #:export (generate-mojo-from-files
25
	    default-convert-type
26
	    maven-convert-type))
27
28
(define-record-type mojo
29
  (make-mojo package name goal description requires-direct-invocation?
30
             requires-project? requires-reports? aggregator?
31
             requires-online? inherited-by-default? instantiation-strategy
32
             execution-strategy since thread-safe? phase parameters components)
33
  mojo?
34
  (package mojo-package)
35
  (name mojo-name)
36
  (goal mojo-goal)
37
  (description mojo-description)
38
  (requires-direct-invocation? mojo-requires-direct-invocation?)
39
  (requires-project? mojo-requires-project?)
40
  (requires-reports? mojo-requires-reports?)
41
  (aggregator? mojo-aggregator?)
42
  (requires-online? mojo-requires-online?)
43
  (inherited-by-default? mojo-inherited-by-default?)
44
  (instantiation-strategy mojo-instantiation-strategy)
45
  (execution-strategy mojo-execution-strategy)
46
  (since mojo-since)
47
  (thread-safe? mojo-thread-safe?)
48
  (phase mojo-phase)
49
  (parameters mojo-parameters)
50
  (components mojo-components))
51
52
(define* (update-mojo mojo
53
           #:key
54
           (package (mojo-package mojo))
55
           (name (mojo-name mojo))
56
           (goal (mojo-goal mojo))
57
           (description (mojo-description mojo))
58
           (requires-direct-invocation? (mojo-requires-direct-invocation? mojo))
59
           (requires-project? (mojo-requires-project? mojo))
60
           (requires-reports? (mojo-requires-reports? mojo))
61
           (aggregator? (mojo-aggregator? mojo))
62
           (requires-online? (mojo-requires-online? mojo))
63
           (inherited-by-default? (mojo-inherited-by-default? mojo))
64
           (instantiation-strategy (mojo-instantiation-strategy mojo))
65
           (execution-strategy (mojo-execution-strategy mojo))
66
           (since (mojo-since mojo))
67
           (thread-safe? (mojo-thread-safe? mojo))
68
           (phase (mojo-phase mojo))
69
           (parameters (mojo-parameters mojo))
70
           (components (mojo-components mojo)))
71
  (make-mojo package name goal description requires-direct-invocation?
72
             requires-project? requires-reports? aggregator?
73
             requires-online? inherited-by-default? instantiation-strategy
74
             execution-strategy since thread-safe? phase parameters components))
75
76
(define-record-type mojo-parameter
77
  (make-mojo-parameter name type since required editable description
78
                       configuration)
79
  mojo-parameter?
80
  (name          mojo-parameter-name)
81
  (type          mojo-parameter-type)
82
  (since         mojo-parameter-since)
83
  (required      mojo-parameter-required)
84
  (editable      mojo-parameter-editable)
85
  (description   mojo-parameter-description)
86
  (configuration mojo-parameter-configuration))
87
88
(define* (update-mojo-parameter mojo-parameter
89
           #:key (name (mojo-parameter-name mojo-parameter))
90
                 (type (mojo-parameter-type mojo-parameter))
91
                 (since (mojo-parameter-since mojo-parameter))
92
                 (required (mojo-parameter-required mojo-parameter))
93
                 (editable (mojo-parameter-editable mojo-parameter))
94
                 (description (mojo-parameter-description mojo-parameter))
95
                 (configuration (mojo-parameter-configuration mojo-parameter)))
96
  (make-mojo-parameter name type since required editable description
97
                       configuration))
98
99
(define-record-type mojo-component
100
  (make-mojo-component field role hint)
101
  mojo-component?
102
  (field mojo-component-field)
103
  (role  mojo-component-role)
104
  (hint  mojo-component-hint))
105
106
(define* (update-mojo-component mojo-component
107
           #:key (field (mojo-component-field mojo-component))
108
                 (role (mojo-component-role mojo-component))
109
                 (hint (mojo-component-hint mojo-component)))
110
  (make-mojo-component field role hint))
111
112
(define (generate-mojo-parameter mojo-parameter)
113
  `(parameter (name ,(mojo-parameter-name mojo-parameter))
114
              (type ,(mojo-parameter-type mojo-parameter))
115
              ,@(if (mojo-parameter-since mojo-parameter)
116
                    `(since (mojo-parameter-since mojo-parameter))
117
                    '())
118
              (required ,(if (mojo-parameter-required mojo-parameter) "true" "false"))
119
              (editable ,(if (mojo-parameter-editable mojo-parameter) "true" "false"))
120
              (description ,(mojo-parameter-description mojo-parameter))))
121
122
(define (generate-mojo-configuration mojo-parameter)
123
  (let ((config (mojo-parameter-configuration mojo-parameter)))
124
    (if config
125
        `(,(string->symbol (mojo-parameter-name mojo-parameter))
126
           (@ ,@config))
127
        #f)))
128
129
(define (generate-mojo-component mojo-component)
130
  `(requirement
131
     (role ,(mojo-component-role mojo-component))
132
     (role-hint ,(mojo-component-hint mojo-component))
133
     (field-name ,(mojo-component-field mojo-component))))
134
135
(define (generate-mojo mojo)
136
  `(mojo
137
     (goal ,(mojo-goal mojo))
138
     (description ,(mojo-description mojo))
139
     ,@(let ((val (mojo-requires-direct-invocation? mojo)))
140
         (if val
141
             `((requiresDirectInvocation ,val))
142
             '()))
143
     ,@(let ((val (mojo-requires-project? mojo)))
144
         (if val
145
             `((requiresProject ,val))
146
             '()))
147
     ,@(let ((val (mojo-requires-reports? mojo)))
148
         (if val
149
             `((requiresReports ,val))
150
             '()))
151
     ,@(let ((val (mojo-aggregator? mojo)))
152
         (if val
153
             `((aggregator ,val))
154
             '()))
155
     ,@(let ((val (mojo-requires-online? mojo)))
156
         (if val
157
             `((requiresOnline ,val))
158
             '()))
159
     ,@(let ((val (mojo-inherited-by-default? mojo)))
160
         (if val
161
             `((inheritedByDefault ,val))
162
             '()))
163
     ,@(let ((phase (mojo-phase mojo)))
164
             (if phase
165
                 `((phase ,phase))
166
                 '()))
167
     (implementation ,(string-append (mojo-package mojo) "." (mojo-name mojo)))
168
     (language "java")
169
     (instantiationStrategy ,(mojo-instantiation-strategy mojo))
170
     (executionStrategy ,(mojo-execution-strategy mojo))
171
     ,@(let ((since (mojo-since mojo)))
172
             (if since
173
                 `((since ,since))
174
                 '()))
175
     ,@(let ((val (mojo-thread-safe? mojo)))
176
         (if val
177
             `((threadSafe ,val))
178
             '()))
179
     (parameters
180
       ,(map generate-mojo-parameter (mojo-parameters mojo)))
181
     (configuration
182
       ,@(filter (lambda (a) a) (map generate-mojo-configuration (mojo-parameters mojo))))
183
     (requirements
184
       ,@(map generate-mojo-component (mojo-components mojo)))))
185
186
187
(define (default-convert-type type)
188
  (cond
189
    ((equal? type "String") "java.lang.String")
190
    ((equal? type "File") "java.io.File")
191
    ((and (> (string-length type) 6)
192
          (equal? (substring type 0 5) "List<"))
193
     "java.util.List")
194
    ((and (> (string-length type) 15)
195
          (equal? (substring type 0 14) "LinkedHashSet<"))
196
     "java.util.LinkedHashSet")
197
    (else type)))
198
199
(define (maven-convert-type type)
200
  (cond
201
    ((equal? type "MavenProject")
202
     "org.apache.maven.project.MavenProject")
203
    (else (default-convert-type type))))
204
205
(define (update-mojo-from-file mojo file convert-type)
206
  (define parse-tree (parse-java-file file))
207
208
  (define (update-mojo-from-attrs mojo attrs)
209
    (let loop ((mojo mojo) (attrs attrs))
210
      (match attrs
211
        ('() mojo)
212
        ((attr attrs ...)
213
         (match attr
214
           (('annotation-attr ('attr-name name) ('attr-value value))
215
            (cond
216
              ((equal? name "name")
217
               (loop (update-mojo mojo #:goal value) attrs))
218
              ((equal? name "defaultPhase")
219
               (loop (update-mojo mojo #:phase value) attrs))
220
              ((equal? name "requiresProject")
221
               (loop (update-mojo mojo #:requires-project? value) attrs))
222
              ((equal? name "threadSafe")
223
               (loop (update-mojo mojo #:thread-safe? value) attrs))
224
              (else
225
                (raise `(not-found-attr ,name)))))
226
           (_ (loop mojo attrs)))))))
227
228
  (define (update-mojo-parameter-from-attrs mojo-parameter attrs)
229
    (match attrs
230
      ('() mojo-parameter)
231
      (('annotation-attr ('attr-name name) ('attr-value value))
232
       (cond
233
         ((equal? name "editable")
234
          (update-mojo-parameter mojo-parameter #:editable value))
235
         ((equal? name "required")
236
          (update-mojo-parameter mojo-parameter #:required value))
237
         (else
238
           (update-mojo-parameter mojo-parameter
239
                                  #:configuration
240
                                  (cons
241
                                    (list (string->symbol name) value)
242
                                    (or
243
				      (mojo-parameter-configuration mojo-parameter)
244
				      '()))))))
245
      ((attr attrs ...)
246
       (match attr
247
         (('annotation-attr ('attr-name name) ('attr-value value))
248
          (cond
249
            ((equal? name "editable")
250
             (update-mojo-parameter-from-attrs
251
               (update-mojo-parameter mojo-parameter #:editable value)
252
               attrs))
253
            ((equal? name "required")
254
             (update-mojo-parameter-from-attrs
255
               (update-mojo-parameter mojo-parameter #:required value)
256
               attrs))
257
            (else (update-mojo-parameter-from-attrs
258
                    (update-mojo-parameter mojo-parameter
259
                                           #:configuration
260
                                           (cons
261
                                             (list (string->symbol name) value)
262
                                             (or
263
					       (mojo-parameter-configuration mojo-parameter)
264
					       '())))
265
                    attrs))))
266
         ((attrss ...)
267
          (update-mojo-parameter-from-attrs mojo-parameter (append attrss attrs)))))))
268
269
  (define (update-mojo-component-from-attrs mojo-component attrs)
270
    (match attrs
271
      ('() mojo-component)
272
      ((attr attrs ...)
273
       (match attr
274
         (('annotation-attr ('attr-name name) ('attr-value value))
275
          (cond
276
            ((equal? name "role")
277
             (update-mojo-component-from-attrs
278
               (update-mojo-component mojo-component #:role value)
279
               attrs))
280
            ((equal? name "hint")
281
             (update-mojo-component-from-attrs
282
               (update-mojo-component mojo-component #:hint value)
283
               attrs))
284
            (else (raise `(not-found-attr ,name)))))
285
         ((attrss ...)
286
          (update-mojo-component-from-attrs mojo-component (append attrss attrs)))))))
287
288
  (define (update-mojo-from-class-content mojo content)
289
    (let loop ((content content)
290
               (mojo mojo)
291
               (last-comment #f))
292
      (match content
293
        ('() mojo)
294
        ((('comment last-comment) content ...)
295
         (loop content mojo last-comment))
296
        ((('param-pat ('annotation-pat annot-name attrs ...) ('type-name type)
297
           ('param-name name)) content ...)
298
         (cond
299
           ((equal? annot-name "Parameter")
300
            (loop content
301
                  (update-mojo mojo
302
                               #:parameters
303
                               (cons (update-mojo-parameter-from-attrs
304
                                       (make-mojo-parameter
305
                                         name (convert-type type) #f #f #f last-comment #f)
306
                                       attrs)
307
                                     (mojo-parameters mojo)))
308
                  #f))
309
           ((equal? annot-name "Component")
310
            (loop content
311
                  (update-mojo mojo
312
                               #:components
313
                               (cons (update-mojo-component-from-attrs
314
                                       (make-mojo-component name #f #f)
315
                                       attrs)
316
                                     (mojo-components mojo)))
317
                  #f))
318
           (else (raise `(not-found-annot ,annot-name)))))
319
        ((('param-pat _ ...) content ...)
320
         (loop content mojo #f))
321
        ((('method-pat _ ...) content ...)
322
         (loop content mojo #f)))))
323
324
  (let loop ((content parse-tree)
325
             (mojo mojo)
326
             (last-comment #f))
327
    (if (null? content)
328
        mojo
329
        (match content
330
          ((tls content ...)
331
           (match tls
332
             (('package package)
333
              (loop content (update-mojo mojo #:package package) last-comment))
334
             (('comment last-comment)
335
              (loop content mojo last-comment))
336
             (('class-pat ('annotation-pat annot-name (attrs ...)) name ('extends extend)
337
               ('class-body class-content ...))
338
              (loop content
339
                    (update-mojo-from-class-content
340
                      (update-mojo-from-attrs
341
                        (update-mojo mojo
342
                                     #:name name
343
                                     #:description last-comment)
344
                        attrs)
345
                      class-content)
346
                    #f))
347
             (('class-pat ('annotation-pat annot-name (attrs ...)) name ('extends extend)
348
               ('implements implement) ('class-body class-content ...))
349
              (loop content
350
                    (update-mojo-from-class-content
351
                      (update-mojo-from-attrs
352
                        (update-mojo mojo
353
                                     #:name name
354
                                     #:description last-comment)
355
                        attrs)
356
                      class-content)
357
                    #f))
358
             (_
359
              (loop content mojo last-comment))))))))
360
361
(define (generate-mojo-from-files convert-type . files)
362
  (let ((mojo (make-mojo #f #f #f #f #f #f #f #f #f #f "per-lookup"
363
                         "once-per-session" #f #f #f '() '())))
364
    (let loop ((files files) (mojo mojo))
365
      (if (null? files)
366
          (generate-mojo mojo)
367
          (loop
368
            (cdr files)
369
            (update-mojo-from-file
370
              (update-mojo mojo
371
                #:package #f
372
                #:name #f
373
                #:goal #f
374
                #:description #f
375
                #:requires-direct-invocation? #f
376
                #:requires-project? #f
377
                #:requires-reports? #f
378
                #:aggregator? #f
379
                #:requires-online? #f
380
                #:inherited-by-default? #f
381
                #:instantiation-strategy "per-lookup"
382
                #:execution-strategy "once-per-session"
383
                #:since #f
384
                #:thread-safe? #f
385
                #:phase #f)
386
              (car files)
387
	      convert-type))))))
388