-
Notifications
You must be signed in to change notification settings - Fork 55
/
jdee-wiz.el
1166 lines (1042 loc) · 47.1 KB
/
jdee-wiz.el
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; jdee-wiz.el -- generate Java code by interactive input and Java reflection
;; Author: Paul Kinnucan <[email protected]>
;; Maintainer: Paul Landes <landes <at> mailc dt net>
;; Keywords: java, tools
;; Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004 Paul Kinnucan.
;; Copyright (C) 2009 by Paul Landes
;; GNU Emacs 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 2, or (at your option)
;; any later version.
;; GNU Emacs 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 Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;; Code:
(require 'cc-cmds)
(require 'cl-lib)
(require 'efc)
(require 'jdee-backend)
(require 'jdee-complete)
(require 'jdee-gen)
(require 'jdee-import)
(require 'jdee-parse)
(require 'semantic/idle)
(require 'semantic/util)
(defgroup jdee-wiz nil
"JDEE Wizards"
:group 'jdee
:prefix "jdee-wiz-")
(defun jdee-wiz-escape-backslashes-in-path (path)
(mapconcat
(lambda (char)
(if (eq char ?\\) "\\\\" (char-to-string char)))
path ""))
(defun jdee-wiz-get-package-name ()
(let ((package-re "^[ \t]*package[ \t]+\\(.*\\)[ \t]*;"))
(save-excursion
(goto-char (point-max))
(when (re-search-backward package-re (point-min) t)
(looking-at package-re)
(buffer-substring-no-properties
(match-beginning 1)
(match-end 1))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Method Interface Implementation wizard ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun jdee-wiz-get-unqualified-name (name)
(string-match "[^.]+$" name)
(substring name (match-beginning 0) (match-end 0)))
(defun jdee-wiz-update-implements-clause (interface-name &optional extends)
"Updates the implements clause unless extends is non-nil. In that case the
extends clause is updated"
(interactive
"sEnter interface: ")
(let (keyword
(interface
(jdee-wiz-get-unqualified-name interface-name)))
(if extends
(setq keyword "extends")
(setq keyword "implements"))
(save-excursion
(let* ((class-re "class[ \t]+\\([a-zA-z]+[a-zA-Z0-9._]*\\).*[ \n]*")
(open-brace-pos
(ignore-errors (scan-lists (point) -1 1)))
(class-name-end-pos
(when open-brace-pos
(goto-char open-brace-pos)
(when (re-search-backward class-re (point-min) t)
(looking-at class-re)
(match-end 1))))
(implements-keyword-end-pos
(when (and open-brace-pos class-name-end-pos)
(goto-char open-brace-pos)
(if (re-search-backward keyword class-name-end-pos t)
(match-end 0)))))
(if implements-keyword-end-pos
(progn
(goto-char implements-keyword-end-pos)
(insert (concat " " interface ",")))
(when class-name-end-pos
(goto-char (- open-brace-pos 1))
(if (looking-at " {")
(delete-char 1) ;; if we don't delete, we end up with 2 spaces
(forward-char))
(insert (concat " " keyword " " interface " "))))))))
(defun jdee-dollar-name (name)
"Convert pkg[.Outer].Inner[$Inner] to pkg[.Outer]$Inner[$Inner]"
;; change last '.' to '$'
(jdee-replace-in-string name "[.]\\([^.]+$\\)" "$\\1"))
(defun jdee-wiz-generate-interface (interface-name)
"*Generate a skeleton implementation of a specified interface."
(let* ((code
(jdee-backend-make-interface-expr interface-name)))
(if code
(let ((required-imports (jdee-backend-get-interface-imports)))
(eval code) ;error may be thrown if bad intf name
(if required-imports
(jdee-import-insert-imports-into-buffer required-imports t))
(jdee-wiz-update-implements-clause interface-name)))))
(defun jdee-wiz-gen-implementation-methods (gen-list)
"Executes the given list of generation statements. Generation statements
are either strings that may be used as introductory comment for the
subsequent method(s) or invocations of `jdee-wiz-gen-method'."
(let ((items gen-list))
(while (car items)
(let ((to-end (- (point-max) (point))))
(if (stringp (car items))
(progn
(tempo-save-named 'comment-line (car items))
(jdee-gen-section-comment))
(eval (car items)))
(goto-char (- (point-max) to-end)))
(setq items (cdr items)))))
(defun jdee-wiz-implement-interface-internal (interface-name)
"*Generate a skeleton implementation of a specified interface.
This command works only for interfaces defined by `jdee-global-classpath', if
set, otherwise the CLASSPATH environment variable."
(interactive
"sInterface name: ")
(let ((names (jdee-backend-get-qualified-name interface-name)))
(if names
(if (> (length names) 1)
(jdee-wiz-generate-interface
(efc-query-options
names
"Select interface to implement."
"Class Name dialog"))
(jdee-wiz-generate-interface (car names)))
(error "Cannot find interface %s on the current classpath."
interface-name))))
(defun jdee-wiz-implement-interface (interface-name)
"*Generate a skeleton implementation of a specified interface.
This command works only for interfaces that exist on the classpath
defined by `jdee-global-classpath', if set, otherwise
by the CLASSPATH environment variable. This command uses
`jdee-gen-method-template' as a template for generating the
code for each of the skeleton methods required to implement
the interface. You can thus customize the format of the skeleton
methods by customizing `jdee-gen-method-template' The template
in turn invokes the `jdee-javadoc-autodoc-at-line' function to
generate the skeleton javadoc for each skeleton method. This function
uses various templates that you can customize to customize
the skeleton javadoc. See the function's documentation for
more information."
(interactive
"sInterface name: ")
(condition-case err
(let ((pos (point)))
(jdee-wiz-implement-interface-internal interface-name)
(jdee-wiz-indent pos))
(error
(message "%s" (error-message-string err)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; EventSource wizard ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun jdee-wiz-generate-event-source (event-listener-interface-name)
"*Generate a skeleton implementation of a source of events for the event listener
INTERFACE-NAME. This command will generate methods to add and remove listeners
and fire every method of all listeners registered. It creates a data structure
to store the listeners too."
(condition-case err
(let* ((pos (point))
(code (jdee-backend-make-event-source-expr
event-listener-interface-name)))
(if code
(let ((required-imports
(jdee-backend-get-event-source-imports)))
(message "%s" "evaluating")
(eval code)
(message "%s" "eval done")
(jdee-wiz-indent pos)
(if required-imports
(jdee-import-insert-imports-into-buffer required-imports t)
(message "%s" "no imports"))
)))
(error
(message "%s" (error-message-string err)))))
(defun jdee-wiz-gen-event-source (gen-list)
"Executes the given list of generation statements. Generation statements
are either strings that may be used as introductory comment for the
subsequent method(s) or invocations of `jdee-wiz-gen-listener-registry',
`jdee-wiz-gen-method'."
(let ((items gen-list))
(while (car items)
(let ((to-end (- (point-max) (point))))
(if (stringp (car items))
(progn
(tempo-save-named 'comment-line (car items))
(jdee-gen-section-comment))
(eval (car items)))
(goto-char (- (point-max) to-end)))
(setq items (cdr items))
))
)
(defun jdee-wiz-gen-listener-registry (listener-class)
"Generates a method by setting the tempo named tags and
invoking `jdee-gen-listener-registry'. This method is usually
called by an expression generated in the beanshell."
(tempo-save-named 'listenerFQN listener-class)
(jdee-gen-listener-registry)
)
(defun jdee-wiz-gen-event-source-fire-method
(listener-class method ret-type params)
"Generates a method by setting the tempo named tags and
invoking `jdee-gen-event-source-fire-method'. This method is usually
called by an expression generated in the beanshell."
(tempo-save-named 'listenerFQN listener-class)
(tempo-save-named 'method-name method)
(tempo-save-named 'return-type ret-type)
(tempo-save-named 'params params)
(jdee-gen-event-source-fire-method)
)
(defun jdee-wiz-implement-event-source-internal (interface-name)
"*Generate a skeleton implementation of a source of events for the event listener
INTERFACE-NAME. This command will generate methods to add and remove listeners
and fire every method of all listeners registered. It creates a data structure
to store the listeners too. This command works only for interfaces defined by `jdee-global-classpath', if
set, otherwise the CLASSPATH environment variable."
(interactive
"sListener Interface name: ")
(condition-case err
(let ((names (jdee-backend-get-qualified-name interface-name)))
(if names
(if (> (length names) 1)
(jdee-wiz-generate-event-source
(efc-query-options names
"Select interface to implement."
"class name dialog"))
(jdee-wiz-generate-event-source (car names)))
(error "Cannot find listener interface %s on the current classpath." interface-name)))
(error
(message "%s" (error-message-string err)))))
(defun jdee-wiz-implement-event-source (interface-name)
"*Generate a skeleton implementation of a source of events for the event listener
INTERFACE-NAME. This command will generate methods to add and remove listeners
and fire every method of all listeners registered. It creates a data structure
to store the listeners too. This command works only for interfaces that exist on the classpath
defined by `jdee-global-classpath', if set, otherwise
by the CLASSPATH environment variable."
(interactive
"sListener Interface name: ")
(jdee-wiz-implement-event-source-internal interface-name))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Method override wizard ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun jdee-wiz-override-method ()
"Overrides a method whose name you specify, using
completion, in the minibuffer. Press space at the
prompt to see a list of all methods that can be overriden
or type the first few letters of the name of the method
and press space to see a list of all methods that
complete the name.
This command creates a skeleton implementation of the
overridden method at point. This command infers the
qualified name of the class of the overriden method by
prepending the package name of the current buffer to
the class containing point. If the class defines
more than one method of the same name, this command
prompts you to select the desired method from a list
of method prototypes.
This command also generates import statements for
the parameter and return types of the overridden method.
The import statements are inserted after the last
existing import statement or the package statement
or the first blank line in the source file. Import
statements are generated only for types for which an
import statement does not already exist in the file.
NOTE: this command works only if the overriding class
has been previously compiled."
(interactive)
(condition-case err
(let* ((super-class (jdee-parse-get-super-class-at-point))
(qualified-super-class
(jdee-parse-get-qualified-name super-class t))
(classinfo
(jdee-complete-get-classinfo qualified-super-class jdee-complete-protected))
pair pos class-name qualified-class-name method-name)
(setq pair
(assoc
(completing-read "Method to overwrite: " classinfo nil t)
classinfo))
(if (not pair)
(error "No method specified for completion."))
(setq pos (string-match " : " (car pair)))
(setq method-name
(if pos
(substring (car pair) 0 pos)
(cdr pair)))
(setq class-name
(jdee-parse-get-super-class-at-point))
(setq qualified-class-name
(jdee-parse-get-qualified-name class-name t))
(setq pos (string-match "(" method-name))
(if qualified-super-class
(let ((signatures (jdee-backend-get-candidate-signatures
qualified-class-name
(substring method-name 0 pos))))
(jdee-wiz-override-method-internal method-name
signatures))
(error "Cannot find parent class %s" super-class)))
(error
(message "%s" (error-message-string err)))))
(defun jdee-wiz-override-method-internal (selected-method methods)
(let* ((selected-method-args (jdee-wiz-number-of-arguments selected-method))
(pos (point))
(variant 0) skeleton required-imports
(index 0))
(while methods
(if (jdee-wiz-check-signatures selected-method (car methods))
(progn
(setq variant index)
(setq methods nil))
(progn
(setq index (+ 1 index))
(setq methods (cdr methods)))))
(jdee-backend-make-method-skeleton-expr (int-to-string variant))
(setq required-imports (jdee-backend-get-method-override-imports))
(if required-imports
(jdee-import-insert-imports-into-buffer required-imports t))))
(defun jdee-wiz-gen-method (modifiers return-type name parameters exceptions
default-body)
"Generates a method by setting the tempo named tags and
invoking `jdee-gen-method'. This method is usually
called by an expression generated in the beanshell."
(tempo-save-named 'modifiers modifiers)
(tempo-save-named 'return-type return-type)
(tempo-save-named 'name name)
(tempo-save-named 'parameters parameters)
(tempo-save-named 'exceptions exceptions)
(tempo-save-named 'default-body default-body)
(jdee-gen-method)
)
(defun jdee-wiz-gen-delegation-methods (gen-list)
"Executes the given list of generation statements. Generation statements
are either strings that may be used as introductory comment for the
subsequent method(s) or invocations of `jdee-wiz-gen-method'."
(let ((items gen-list))
(while (car items)
(let ((to-end (- (point-max) (point))))
(if (stringp (car items))
(progn
(tempo-save-named 'comment-line (car items))
(jdee-gen-section-comment))
(eval (car items)))
(goto-char (- (point-max) to-end)))
(setq items (cdr items))
))
)
(defun jdee-wiz-check-signatures (sign1 sign2)
"Checks the signatures for equality"
(while (string-match "java.lang." sign1)
(setq sign1 (replace-match "" nil nil sign1)))
(while (string-match " param." sign2)
(setq sign2 (replace-match "" nil nil sign2)))
(string= sign1 sign2))
(defun jdee-wiz-number-of-arguments (signature)
"Returns the number of arguments in this signature"
(let (pos (number-of-arguments 0))
(if (string-match "()" signature)
number-of-arguments
(if (not (string-match "," signature))
(setq number-of-arguments (+ 1 number-of-arguments))
(progn
(setq number-of-arguments 1)
(while (string-match "," signature)
(setq pos (string-match "," signature))
(setq number-of-arguments (+ 1 number-of-arguments))
(setq signature (substring signature (+ pos 1)))))))
number-of-arguments))
(defun jdee-wiz-indent (pos)
"Indents the just inserted region without moving
the cursor"
(goto-char (scan-lists (point) -1 1))
(c-indent-exp)
(goto-char pos))
;;
;; Contributed by Javier Lopez and Paul Kinnucan
;;
(defun jdee-browse-class(&optional class-name)
"Browse class in the beanshell class browser"
(interactive)
(let* ((class
(or class-name
(read-from-minibuffer "Class: " (thing-at-point 'symbol))))
(fq-class-name
(jdee-parse-select-qualified-class-name class)))
(if fq-class-name
(jdee-backend-browse-class fq-class-name))))
(defun jdee-wiz-delegate (delegee)
"*Generate methods for the class in the current source buffer
that delegate tasks to an instance of another class. The delegator
class must have a field that references an instance of the delegee
class. DELEGEE is the name of the field in the delegator class that
references the delegee. This command generates methods in the current
buffer that invoke identically named methods of DELEGEE. For example,
if the current buffer contains class A and A has a field named b that
references an instance of class B, this command generates methods for
A that have the same signatures as the public methods of B. Each of
the generated A methods invokes the corresponding B method.
This function uses `jdee-gen-method-template' as a template for
generating the skeleton code for each of the the delegated methods.
You can thus customize the format of the skeleton methods by
customizing `jdee-gen-method-template' The template in turn invokes the
`jdee-javadoc-autodoc-at-line' function to generate the skeleton
javadoc for each skeleton method. This function uses various templates
that you can customize to customize the skeleton javadoc. See the
function's documentation for more information."
(interactive
"sDelegee name: ")
(condition-case err
(let* ((pos (point))
(start nil)
(class-name
(or (jdee-parse-get-qualified-name
(car (jdee-parse-declared-type-of delegee)) t)
(read-string (concat "Enter fully qualified class name of "
delegee ": "))))
(code (jdee-backend-make-delegator-methods delegee class-name)))
(if code
(let ((required-imports (jdee-backend-get-delegate-imports)))
(font-lock-mode -1)
(setq start (point))
(eval code)
;;indenting the new code
(jdee-wiz-indent pos)
(if required-imports
(jdee-import-insert-imports-into-buffer required-imports t))
(font-lock-mode)
)))
(error
(message "%s" (error-message-string err)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Method Abstract Implementation wizard ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun jdee-wiz-generate-abstract-class (class-name)
"*Generate a skeleton implementation of a specified abstract class."
(condition-case err
(let* ((code (jdee-backend-maket-abstract-class-expr class-name)))
(if code
(let ((required-imports
(jdee-backend-get-abstract-class-imports)))
(eval code)
(if required-imports
(jdee-import-insert-imports-into-buffer required-imports t))
(jdee-wiz-update-implements-clause class-name t))))
(message "%s" (error-message-string err))))
(defun jdee-wiz-extend-abstract-class-internal (class-name)
"*Generate a skeleton implementation of the specified abstract class.
This command works only for interfaces defined by `jdee-global-classpath', if
set, otherwise the CLASSPATH environment variable."
(interactive
"sAbstract classname: ")
(condition-case err
(let ((names (jdee-backend-get-qualified-name class-name)))
(if names
(if (> (length names) 1)
(jdee-wiz-generate-abstract-class
(efc-query-options names nil
"class name dialog"))
(jdee-wiz-generate-abstract-class (car names)))
(message "Cannot find abstract class %s on the current classpath."
class-name)))
(message "%s" (error-message-string err))))
(defun jdee-wiz-extend-abstract-class (class-name)
"*Generate a skeleton implementation of the abstract methods of the
a specified class. This command works only for abstract classes that exist
on the classpath defined by `jdee-global-classpath', if set, otherwise
by the CLASSPATH environment variable.
This command uses `jdee-gen-method-template' as a template for
generating the skeleton code for each of the abstract methods. You can
thus customize the format of the skeleton methods by customizing
`jdee-gen-method-template' The template in turn invokes the
`jdee-javadoc-autodoc-at-line' function to generate the skeleton
javadoc for each skeleton method. This function uses various templates
that you can customize to customize the skeleton javadoc. See the
function's documentation for more information."
(interactive
"sAbstract class name: ")
(jdee-wiz-extend-abstract-class-internal class-name))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Get Set Method Implementation wizard ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom jdee-wiz-include-javadoc t
"This variables specifies whether javadoc comments should be included in
skeletons created by the `jdee-wiz-get-set-methods' function."
:group 'jdee-wiz
:type 'boolean)
(defcustom jdee-wiz-get-set-variable-prefix "arg"
"This variable defines a prefix to be added to argmument names
for the funtion `jdee-wiz-get-set-methods'. For example if this
variable is set to \"arg\" the following variable
String name; will produce this method signature:
public String get(String argName)"
:group 'jdee-wiz
:type 'string)
(defcustom jdee-wiz-get-javadoc-template
(list "/**"
"* Gets the value of %n"
"*"
"* @return the value of %n"
"*/")
"Template used by `jdee-wiz-get-set-method' to add the javadoc
to a get method. The %n are replaced by the variable name and
%t by the variable."
:group 'jdee-wiz
:type '(repeat string))
(defcustom jdee-wiz-set-javadoc-template
(list "/**"
"* Sets the value of %n"
"*"
"* @param %p Value to assign to this.%n"
"*/")
"Template used by `jdee-wiz-get-set-method' to add the javadoc to a
set method. The %n are replaced by the variable name, %t by the variable
type and %p for the argument name. In most cases %n and %p are the same
except when `jdee-wiz-get-set-variable-prefix' is non nil; in this case the
%p will pick up those changes as well."
:group 'jdee-wiz
:type '(repeat string))
(defcustom jdee-wiz-show-report t
"A non nil value will show a report of the existing get set methods
and the ones added"
:group 'jdee-wiz
:type 'boolean)
(defcustom jdee-wiz-get-set-variable-convention (cons "" nil)
"Use this variable to specify your coding conventions. This variable is used
by the `jdee-wiz-get-set-method' to filter the convention from the variable
declared in the buffer from the name of the method. The are 3 options a prefix,
a postfix, and the first uppercase letter. For example, choosing a prefix and
setting it to '_' means that the '_' will be filtered from all the variable
containing it. So this variable private String _name; will produce this get
method:
public getName(String name) {
this._name = name
}
A postfix works in a similar way, the third option behaves slighlty different.
For example if the variable is String _strName; this will get filter to name.
It will take everything after the first capitalize letter. A nil value will use
the variable name as it is defined in the buffer."
:group 'jdee-wiz
:type '(cons (string :tag "Enter either the prefix or postfix")
(radio-button-choice (const "Prefix")
(const "Postfix")
(const "Everything after the first upcase letter")
(const nil))))
(defcustom jdee-wiz-get-set-methods-include (list "Both")
"Use this variable to set what methods `jdee-wiz-get-set-methods' will
insert in the buffer. The options are get methods only, set methods only,
and both."
:group 'jdee-wiz
:type '(list (radio-button-choice (const "Get only")
(const "Set only")
(const "Both"))))
(defcustom jdee-wiz-get-set-static-members t
"If on (nonnil), `jdee-wiz-get-set-methods' generates getter/setter methods for
private static members of the class in the current buffer."
:group 'jdee-wiz
:type 'boolean)
(defcustom jdee-wiz-get-set-methods-order (list "Get followed by set for each field")
"Use this variable to set the order in which the
get and set methods are going to be inserted by
`jdee-wiz-get-set-methods'"
:group 'jdee-wiz
:type '(list (radio-button-choice
(const "Get followed by set for each field")
(const "Set followed by get for each field")
(const "All get methods followed by all set methods")
(const "All set methods followed by all get methods"))))
(defun jdee-wiz-downcase-initials (obj)
"It downcase the first letter of obj"
(concat (downcase (substring obj 0 1)) (substring obj 1)))
(defun jdee-wiz-get-class-parts (class-name tokens)
"Recurse through all the tokens in `tokens' looking for
the tokens of `class-name', returns nil if no token are found"
(let ((parts (jdee-wiz-get-class-parts-helper class-name tokens))
temp-parts inner-classes)
(if (not parts)
(while tokens
(setq temp-parts (semantic-tag-type-members (car tokens)))
(setq inner-classes (semantic-brute-find-tag-by-class 'type temp-parts))
(setq parts (jdee-wiz-get-class-parts class-name inner-classes))
(if parts
(setq tokens nil)
(setq tokens (cdr tokens)))))
parts))
(defun jdee-wiz-get-class-parts-helper (class-name tokens)
"Checks the top level for the class name `class-name'
if one is found it returns the parts of it, nil is
return otherwise"
(let (parts current-class)
(while tokens
(setq current-class (car tokens))
(if (string= class-name (semantic-tag-name current-class))
(progn
(setq parts (semantic-tag-type-members current-class))
(setq tokens nil)))
(setq tokens (cdr tokens)))
parts))
(defun jdee-wiz-get-member-p (name functions)
"Returns t if the variable name has a get method defined in the
current buffer. Functions are semantic tokens for the functions
defined in the current buffer."
(or (member
(concat
"get"
(upcase-initials (jdee-wiz-get-name name))) functions)
(member
(concat
"is"
(upcase-initials (jdee-wiz-get-name name))) functions)))
(defun jdee-wiz-set-member-p (name functions)
"Returns t if the variable name has a set method defined in the current buffer.
Functions are semantic tokens for the functions defined in the current buffer."
(member (concat "set" (upcase-initials (jdee-wiz-get-name name))) functions))
(defun jdee-wiz-get-set-methods()
"Generates get and set methods for all the private fields
defined in the current buffer."
(interactive)
(let* ((include (car jdee-wiz-get-set-methods-include))
;;Indicates if both get and set should be inserted
(bothp (string= "Both" include))
;;only get methods should be inserted
(get-onlyp (string= "Get only" include))
;;only set methods should be inserted
(set-onlyp (string= "Set only" include))
(order (car jdee-wiz-get-set-methods-order))
(get-firstp
(or (string= "All get methods followed by all set methods" order)
(string= "Get followed by set for each field" order)))
(class (jdee-parse-get-class-at-point));;class name
(classes (split-string class "\\."))
(class-name (nth (- (length classes) 1) classes))
(tokens (semantic-fetch-tags));;buffer tokens
(type (semantic-brute-find-tag-by-class 'type tokens));;class tokens
(parts (jdee-wiz-get-class-parts class-name type))
(variables (semantic-brute-find-tag-by-class 'variable parts));;declared variables
;;non public variables
(non-public-variables (jdee-wiz-filter-variables-by-typemodifier variables))
(functions (semantic-brute-find-tag-by-class 'function parts));;functions
(set-get-functions (jdee-wiz-get-get-set-methods functions));;get,set,is functions
var name staticp finalp report temp pos)
(setq
report
(concat
(format "%-60.60s" "Field")
(if get-firstp "\tGetter \tSetter\n" "\tSetter \tGetter\n")))
(setq
report
(concat
report
(format "%-60.60s" "------------------------------------------------------------")
"\t--------\t--------\n"))
(while non-public-variables
(setq var (car non-public-variables))
(setq name (semantic-tag-name var));;variable name
(setq type (semantic-tag-type var));;variable type i.e. boolean
(setq staticp (member "static" (semantic-tag-modifiers var)));;is it static
(setq finalp (member "final" (semantic-tag-modifiers var)));;is it final
(setq
report
(concat
report
(format
"%-60.60s"
(concat
type " " name " "
(and (semantic-tag-modifiers var)
;; only if some modifiers are present
;; print them
(format "%s" (semantic-tag-modifiers var)))))))
(setq report (concat report "\t"))
;;order in which the methods should be inserted
(cond ((string= "Get followed by set for each field" order)
;;get method followed by its set method
;;getting the get method if it does not exist in the buffer
(if (not (jdee-wiz-get-member-p name set-get-functions))
(if (and (or bothp get-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-get-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(setq report (concat report "[Exists ]")))
(setq report (concat report "\t"))
;;getting the set method if it does not exist in the buffer
(if (and (not finalp);; it is final - can not have a setter
(not (jdee-wiz-set-member-p name set-get-functions)))
(if (and (or bothp set-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-set-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(if (jdee-wiz-set-member-p name set-get-functions)
(setq report (concat report "[Exists ]"))
(if finalp
(setq report (concat report "[N/A ]"))))))
;;set method followed by its get method
((string= "Set followed by get for each field" order)
;;getting the set method if it does not exist in the buffer
(if (and (not finalp);; it is final - can not have a setter
(not (jdee-wiz-set-member-p name set-get-functions)))
(if (and (or bothp set-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-set-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(if (jdee-wiz-set-member-p name set-get-functions)
(setq report (concat report "[Exists ]"))
(if finalp
(setq report (concat report "[N/A ]")))))
(setq report (concat report "\t"))
;;getting the get method if it does not exist in the buffer
(if (not (jdee-wiz-get-member-p name set-get-functions))
(if (and (or bothp get-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-get-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(setq report (concat report "[Exists ]"))))
;;all the get method first
((string= "All get methods followed by all set methods" order)
;;getting the get method if it does not exist in the buffer
(if (not (jdee-wiz-get-member-p name set-get-functions))
(if (and (or bothp get-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-get-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(setq report (concat report "[Exists ]")))
(setq report (concat report "\t"))
;;getting the set method if it does not exist in the buffer
(if (and (not finalp);; it is final - can not have a setter
(not (jdee-wiz-set-member-p name set-get-functions)))
(if (and (or bothp set-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(setq temp (concat temp (jdee-wiz-get-set-method type name staticp class)))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(if (jdee-wiz-set-member-p name set-get-functions)
(setq report (concat report "[Exists ]"))
(if finalp
(setq report (concat report "[N/A ]"))))))
;;all the set method first
((string= "All set methods followed by all get methods" order)
;;getting the set method if it does not exist in the buffer
(if (and (not finalp);; it is final - can not have a setter
(not (jdee-wiz-set-member-p name set-get-functions)))
(if (and (or bothp set-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(insert (jdee-wiz-get-set-method type name staticp class))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(if (jdee-wiz-set-member-p name set-get-functions)
(setq report (concat report "[Exists ]"))
(if finalp
(setq report (concat report "[N/A ]")))))
(setq report (concat report "\t"))
;;getting the get method if it does not exist in the buffer
(if (not (jdee-wiz-get-member-p name set-get-functions))
(if (and (or bothp get-onlyp)
(or (not staticp) jdee-wiz-get-set-static-members))
(progn
(setq temp (concat temp (jdee-wiz-get-get-method type name staticp class)))
(setq report (concat report "[Added ]")))
(setq report (concat report "[Skipped]")))
(setq report (concat report "[Exists ]")))))
(setq report (concat report "\n"))
(setq non-public-variables (cdr non-public-variables)))
(setq pos (point))
(if temp (insert temp))
(if jdee-wiz-show-report
(with-output-to-temp-buffer (concat "*jdee-wiz-get-set-methods report for " class "*")
(princ report)))
;;indenting the new code
(jdee-wiz-indent pos)))
(defun jdee-wiz-get-get-set-methods(tokens)
"Returns a list of the methods that start with set, get or is."
(let (token name filtered-methods)
(while tokens
(setq token (car tokens))
(setq name (semantic-tag-name token))
(if (or (string-match "^get" name)
(string-match "^set" name)
(string-match "^is" name))
(setq filtered-methods (append filtered-methods (list name))))
(setq tokens (cdr tokens)))
filtered-methods))
(defun jdee-wiz-filter-variables-by-typemodifier(tokens)
"Returns a subsets of tokens. It returns the tokens that contains either private or
protected modifiers"
(let (token modifiers filtered-tokens)
(while tokens
(setq token (car tokens))
(setq modifiers (semantic-tag-modifiers token))
(if (not (member "public" modifiers))
(setq filtered-tokens (append filtered-tokens (list token))))
(setq tokens (cdr tokens)))
filtered-tokens))
(defun jdee-wiz-get-name (variable)
"Gets the name of variable to be used in generation the get set
method templates. For Example if the variable is \"_Name\" and the variable
`jdee-wiz-get-set-variable-convention' is set to prefix _ this method will
return \"Name\"."
(let (answer
(cfs case-fold-search)
(fix (car jdee-wiz-get-set-variable-convention))
(convention (cdr jdee-wiz-get-set-variable-convention)))
(setq case-fold-search nil)
(cond ((not convention)
(setq answer variable))
((string= "Prefix" convention)
(progn
(if fix
(let ((pos (string-match (concat "^" fix) variable)))
(if pos
(setq answer (substring variable (+ pos (length fix))))
(setq answer variable)))
(setq answer variable))))
((string= "Postfix" convention)
(progn
(if fix
(let ((pos (string-match (concat fix "$") variable)))
(if pos
(setq answer (substring variable 0 pos))
(setq answer variable)))
(setq answer variable))))
(t
(let ((pos (string-match "[A-Z]." variable)))
(if pos
(let ((ans (substring variable pos)))
(if ans
(setq answer ans)
(setq answer variable)))
(setq answer variable)))))
(setq case-fold-search cfs)
answer))
(defun jdee-wiz-get-get-method(type name &optional staticp class-name)
"Returns a string representing a get method"
(let ((filtered-name (jdee-wiz-get-name name))
get (javadoc "") temp temp2)
(setq
get
(concat
"\n"
(if jdee-wiz-include-javadoc
(progn
(setq temp2 jdee-wiz-get-javadoc-template)
(while temp2
(setq temp (car temp2))
(while (string-match "%n" temp)
(setq
temp
(replace-match
(jdee-wiz-downcase-initials filtered-name) nil nil temp)))
(while (string-match "%t" temp)
(setq temp (replace-match type nil nil temp)))
(setq javadoc (concat javadoc temp "\n"))
(setq temp2 (cdr temp2)))
javadoc))
(jdee-gen-method-signature
(concat "public" (if staticp " static"))
type
(concat
(if (string= type "boolean") "is" "get")
(upcase-initials filtered-name))
nil)
(if jdee-gen-k&r "{" "\n{") "\n"
"return " (if staticp (concat class-name ".") "this.")
name ";\n}\n"))
get))
(defun jdee-wiz-get-set-method(type name &optional staticp class-name)
"Returns a string representing a set method"
(let ((filtered-name (jdee-wiz-get-name name))
set (javadoc "") arg-name temp temp2)
(if jdee-wiz-get-set-variable-prefix
(setq
arg-name
(jdee-wiz-downcase-initials
(concat jdee-wiz-get-set-variable-prefix (upcase-initials filtered-name))))
(setq arg-name (jdee-wiz-downcase-initials filtered-name)))
(setq
set
(concat
"\n"
(if jdee-wiz-include-javadoc
(progn
(setq temp2 jdee-wiz-set-javadoc-template)
(while temp2
(setq temp (car temp2))
(while (string-match "%n" temp)
(setq temp
(replace-match