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 |