Initial Commit
[packages] / xemacs-packages / jde / lisp / jde-import.el
1 ;; jde-import.el --- Organize Java imports
2
3 ;; Copyright (C) 2000, 2001, 2002, 2003, 2004 by David Ponce
4 ;; Copyright (C) 2004 by Philip Lord
5
6 ;; Authors:     David Ponce <david@dponce.com>
7 ;;              Paul Kinnucan <paulk@mathworks.com>
8 ;; Maintainers: David Ponce <david@dponce.com>
9 ;;              Paul Kinnucan <paulk@mathworks.com>
10 ;;              Martin Schwamberger <mschw@web.de>
11 ;; Created: 15 Nov 2000
12 ;; Version: $Revision: 1.46 $
13 ;; Keywords: java, tools
14 ;; VC: $Id: jde-import.el,v 1.46 2004/12/12 14:27:02 paulk Exp $
15
16 ;; This file is not part of Emacs
17
18 ;; This program is free software; you can redistribute it and/or
19 ;; modify it under the terms of the GNU General Public License as
20 ;; published by the Free Software Foundation; either version 2, or (at
21 ;; your option) any later version.
22
23 ;; This program is distributed in the hope that it will be useful, but
24 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26 ;; General Public License for more details.
27
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with this program; see the file COPYING.  If not, write to
30 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
31 ;; Boston, MA 02111-1307, USA.
32
33 ;;; Commentary:
34 ;; 
35 ;; This library adds commands to the JDE to insert and organize Java import
36 ;; statements.
37
38 ;;; Code:
39
40 (require 'efc)
41 (require 'semantic-fw)
42 (require 'semantic-find)
43 (require 'semantic-util)
44 (jde-require 'sregex)
45
46 ;;;;
47 ;;;; Customization
48 ;;;;
49
50 ;; (makunbound 'jde-import-excluded-classes)
51 (defcustom jde-import-excluded-classes
52   '(("^bsh\\..*" . nil)
53     ("^java\\.lang\\.[^.]*$" . t)
54     ("^sun\\..*" . nil)
55     ("^com\\.sun\\..*" . nil)
56     (jde-import-current-package-p . t))
57   "*Specifies classes that should not be imported into a source file.
58 \"Exclude test\" should be either a regular expression or a function
59 whose only argument is the fully qualified class name.
60 Import commands excludes any classes whose fully qualified name matches
61 \"Regexp\" and any classes for which the \"Test function\" returns non-nil.
62 If \"Exclude synonyms\" is non-nil, all classes with the same unqualified name
63 will also be excluded. This is useful for classes of packages which will be
64 imported implicitly (i.e. java.lang.* and the package of the importing class).
65 If more than one fully qualified class names match the unqualified name that you specify,
66 the command prompts you to select only the classes that are not excluded."
67   :group 'jde-project
68   :type '(repeat
69           (cons :tag "Exclude rule"
70                 (choice :tag "Exclude test"
71                         (regexp :tag "Regexp")
72                         (function :tag "Test function"))
73                 (boolean :tag "Exclude synonyms"))))
74
75 ;; auto sorting of import statements
76 (defcustom jde-import-auto-sort nil
77   "*Automatically resort import statements after a `jde-import-import'.
78 If non-nil, the JDE automatically resorts the import statements when a new import statement is added using `jde-import-import' or `jde-import-find-and-import'."
79   :group 'jde-project
80   :type 'boolean
81 )
82
83 (defcustom jde-import-auto-sort-function 'jde-import-sort
84   "*Function to call to automatically  sort imports statements after a `jde-import-import'.  
85 Usually `jde-import-sort' or `jde-import-organize'.  Enabled if  `jde-import-auto-sort' is not nil."
86   :group 'jde-project
87   :type 'function)
88
89 (defcustom jde-import-reverse-sort-group nil
90   "*Non-nil to sort each import group's packages in reverse alphabetic
91 order.  See command `jde-import-organize'.  Note: For sorting the
92 groups, see variable `jde-import-sorted-groups'."
93   :group 'jde-project
94   :type 'boolean)
95
96 (defcustom jde-import-sorted-groups nil
97   "*Non-nil to sort import groups in alphabetic order. Order may
98 be specified as alphabetic, reverse alphabetical or as implicitly 
99 specified by `jde-import-group-of-rules'. In the latter case the
100 order of groups is the same as their appearance in 
101 `jde-import-group-of-rules'.
102 See command `jde-import-organize'. Note: For sorting the packages
103 within each group, see variable `jde-import-reverse-sort-group'."
104   :group 'jde-project
105   :type '(choice :tag "Order"
106                  (const :tag "No sort"                  nil)
107                  (const :tag "group-of-rules order"     gor)
108                  (const :tag "alphabetic order"         asc)
109                  (const :tag "reverse alphabetic order" desc)))
110
111 (defcustom jde-import-group-function 'jde-import-group-of
112   "*Function used to associate an import token to a group.
113 It receives one argument, the import token and must return a group
114 name string or nil if the import does not belong to any group.  The
115 function `jde-import-group-of' is the default value."
116   :group 'jde-project
117   :type 'function)
118
119 (defcustom jde-import-group-of-rules
120   '(
121     ("^javax?\\.")
122     )
123   "*Import group definitions used by `jde-import-group-of'.
124 Each group definition is a pair (REGEXP . GROUP) where:
125 - - REGEXP is a regexp that import names of this group must match.
126 - - GROUP is a group name or the index of the match data returned as
127     group name or nil if REGEXP is the group name."
128   :group 'jde-project
129   :type '(repeat
130           (cons :tag "Group Rule"
131                 regexp
132                 (choice :tag "Group Name"
133                         (string  :tag "A String")
134                         (integer :tag "Match data at")
135                         (const   :tag "The Regexp" nil))))
136   :set '(lambda (sym val)
137           ;; delete empty entries!
138           (set-default sym (delete '("") val))))
139
140 (defcustom jde-import-default-group-name nil
141   "*Default group name if no group name is found.
142 If a group name is not found in `jde-import-group-of-rules' then this
143 group name is used.  If nil no default group name is used."
144   :group 'jde-project
145   :type '(choice (string  :tag "A String")
146                  (const :tag "none" nil)))
147
148 (defcustom jde-import-insert-group-names nil
149   "*If non-nil `jde-import-organize' inserts group name before imports.
150 See also the options `jde-import-group-of-rules' and
151 `jde-import-default-group-name'."
152   :group 'jde-project
153   :type 'boolean)
154
155 ;; (makunbound 'jde-import-blank-line-between-groups)
156 (defcustom jde-import-blank-line-between-groups t
157   "*If non-nil `jde-import-organize' inserts a blank line between groups.
158 See also the options `jde-import-group-of-rules' and
159 `jde-import-default-group-name'."
160   :group 'jde-project
161   :type 'boolean)
162
163 (defcustom jde-import-auto-collapse-imports nil
164   "*If non-nil jde will automatically collapse imports when imports are
165 inserted."
166   :group 'jde-project
167   :type 'boolean)
168
169 (defun jde-import-current-package-p (class)
170   "Returns non-nil if the fully qualified classname CLASS belongs to
171 the same package as the class in the current buffer."
172   (if (jde-parse-get-package-name)
173       (string-match
174        (concat (regexp-quote (jde-parse-get-package-name)) "\\.[^.]*$")
175        class)))
176
177 (defun jde-import-get-qualified-names (unqualified-class)
178   "Returns a list containing all qualified name for UNQUALIFIED-CLASS."
179   (jde-jeval-r
180    (concat  
181     "jde.util.JdeUtilities.getQualifiedName(\""
182     unqualified-class "\");")))
183
184 (defun jde-import-get-imports ()
185   "Returns a list containing all imported classes."
186   (let* (imports
187          (tags  (semantic-fetch-tags))
188          (import-tags (semantic-brute-find-tag-by-class 'include tags)))
189     (dolist (import-tag import-tags)
190       (setq imports
191             (cons
192              (semantic-tag-name import-tag)
193              imports)))
194     (nreverse imports)))
195
196 (defun jde-import-get-import (unqualified-class)
197   "Get imported name for unqualified name UNQUALIFIED-CLASS.
198 This name may have the form \"package.*\". Returns nil,
199 if there is no import statement for UNQUALIFIED-CLASS."
200   (let (import
201         (imports (jde-import-get-imports))
202         (qualified-names (jde-import-get-qualified-names unqualified-class)))
203     (catch 'found
204       (dolist (class qualified-names)
205         (if (setq import (jde-import-already-imports-class class imports))
206             (throw 'found import))))))
207
208 (defun jde-import-get-import-insertion-point ()
209    "Determine where to insert an import statement.
210 If the buffer contains an import statement, return
211 the beginning of the next line; otherwise, if
212 the buffer contains a package statement, insert
213 three empty lines and return the beginning of
214 the second empty line; otherwise, if the buffer
215 contains a class definition, return the beginning
216 of the line before the class definition; otherwise,
217 return the beginning of the buffer."
218    (let* ((tags (semantic-fetch-tags))
219           (import-tag
220            (car (last (semantic-brute-find-tag-by-class
221                        'include tags))))
222           (package-tag (car (semantic-brute-find-tag-by-class
223                              'package tags)))
224           (class-tag (car (semantic-brute-find-tag-by-class
225                            'type tags)))
226           insertion-point)
227      (cond (import-tag
228             (setq insertion-point (+ (semantic-tag-end import-tag) 1)))
229            (package-tag
230             (save-excursion
231               (goto-char (semantic-tag-end package-tag))
232               (forward-line)
233               (insert "\n")
234               (setq insertion-point (point))))
235            (class-tag
236             (setq insertion-point
237                   (let ((comment-token (semantic-documentation-for-tag
238                                         class-tag 'lex)))
239                     (if comment-token
240                         (semantic-lex-token-start comment-token)
241                       (semantic-tag-start class-tag)))))
242            (t
243             (setq insertion-point 1)))
244      (save-excursion
245        (goto-char insertion-point)
246        (unless (and (bolp) (eolp)) (insert "\n")))
247      insertion-point))
248
249 (defun jde-import-import (class) 
250   "*Insert an import statement for a class in the current buffer.
251 CLASS is the fully qualified name of the class to be imported. This
252 function allows you to enter an import at the head of your buffer
253 from any point in the buffer. The function does nothing if an
254 import statement for the specified class already exists.
255 The function does not exclude classes defined by `jde-import-excluded-classes'."
256   (interactive
257    "sClass: ")
258   (jde-import-insert-import (list class)))
259
260 (defun jde-import-one-class (class)
261   "Insert an import into the buffer if not already there."
262   (interactive "s")
263   (if (not (jde-import-already-imports-class class (jde-import-get-imports)))
264       (jde-import-insert-imports-into-buffer (list class))))
265
266 ;; Contributed by David Ponce <david_ponce@mail.schneider.fr>
267 (defun jde-import-sort (&optional reverse)
268   "Sort Java import statements alphabetically. In reverse order if
269 REVERSE is non-nil.
270
271 Usage:
272   \\[jde-import-sort] sort import statements ascending.
273   \\[universal-argument] \\[jde-import-sort] sort descending.
274
275 The the current buffer must be in `jde-mode'. This command uses the
276 semantic Java parser and requires JDE 2.1.6-beta24 and above."
277   (interactive "P")
278   (or (eq major-mode 'jde-mode)
279       (error "Invalid major mode found. Must be 'jde-mode'."))
280   (or (and (local-variable-p 'semantic--parse-table (current-buffer))
281            (symbol-value 'semantic--parse-table))
282       (error "Semantic Java parser not found."))
283   (and (interactive-p)
284        (consp current-prefix-arg)
285        (setq reverse t))
286   (let* ((tags  (semantic-fetch-tags))
287          (depends (semantic-brute-find-tag-by-class 'include tags)))
288     (if depends
289         (let* ((first-import-tag (car depends))
290                (last-import-tag  (nth (1- (length depends)) depends))
291                (start (semantic-tag-start first-import-tag))
292                (end   (semantic-tag-end   last-import-tag)))
293           (when (and start end)
294             (require 'sort)
295             (let (sort-fold-case)
296                 (sort-lines reverse start end)
297                 (goto-char start)))))))
298
299 (defun jde-import-find-and-import (class &optional no-errors no-exclude)
300   "*Insert an import statement for a class in the current buffer.
301 CLASS is an unqualified class name. This function searches
302 the classpath for a class (or classes) that match CLASS. If it
303 finds only one, it inserts an import statements for the class at the
304 head of the current buffer. If it finds more than one class that matches
305 CLASS, it prompts you to select which class to import. You can customize
306 the variable `jde-import-excluded-classes' to prevent specified classes
307 from being imported or considered for import. If the prefix argument NO-EXCLUDE
308 is non-nil, jde-import-excluded-classes will be ignored.
309 This command uses the JDE's BeanShell interpreter. It starts the interpreter
310 if it is not already running so there may be a short delay generating the first
311 import statement in the session. Note that you must explicitly include
312 any directories or jars that you want the command to search in your
313 classpath, except jars implicitly included by the jvm, e.g.,
314 rt.jar. The NO-ERRORS is used to avoid showing erros to the user."
315   (interactive
316    (list (read-from-minibuffer "Class: "
317                                (thing-at-point 'symbol))
318          nil
319          current-prefix-arg))
320   (let (existing-import)
321     (setq existing-import (jde-import-get-import class))
322     (if (not (null existing-import))
323         (message "Skipping: already imported %s" existing-import)
324       (let ((imports (jde-import-get-qualified-names class)))
325         (setq imports (remove-duplicates imports :test 'equal))
326         (if imports
327             (jde-import-insert-import imports (not no-exclude))
328           (if (not no-errors)
329               (message "Error: could not find %s." class)))))))
330
331 (defun jde-import-exclude-imports (imports)
332   "Remove imports from IMPORTS according to `jde-import-excluded-classes'."
333   (if jde-import-excluded-classes
334       (let (synonym-list ; synonyms to be excluded
335             remaining-imports)
336         ;; Exclude all imports matching an element of jde-import-excluded-classes
337         ;; and collect all synonyms to be excluded.
338         (setq remaining-imports
339               (mapcar
340                (lambda (import)
341                  (catch 'found
342                    (dolist (rule jde-import-excluded-classes)
343                      (when (and 
344                             (string-match "[.]" import)
345                             (if (functionp (car rule))
346                                 (funcall (car rule) import)
347                               (string-match (car rule) import)))
348                        (message "Excluding %s." import)
349                        (when (cdr rule)    ; exclude all classes having same name?
350                          (setq synonym-list
351                                (cons (jde-parse-get-unqualified-name import) synonym-list)))
352                        (throw 'found nil)))
353                    import))
354                imports))
355         ;; Exclude all synonyms contained in synonym-list.
356         (setq remaining-imports
357               (mapcar
358                (lambda (import)
359                  (if import
360                      (catch 'found
361                        (dolist (synonym synonym-list)
362                          (when (string-match (concat (regexp-quote synonym) "$") import)
363                            (message "Excluding synonym %s." import)
364                            (throw 'found nil)))
365                        import)))
366                remaining-imports))
367         ;; Remove all nil inserted instead of excluded classes.
368         (delq nil remaining-imports))
369     imports))
370
371 (defun jde-import-insert-import (new-imports &optional exclude)
372   "Asks user, if necessary, to choose one of NEW-IMPORTS and
373 inserts the selected import in the buffer."
374   (let* ((existing-imports (jde-import-get-imports))
375          (candidate-imports (if exclude
376                                 (jde-import-exclude-imports new-imports)
377                               new-imports))
378          (new-import
379           (if (> (length candidate-imports) 1)
380               (jde-import-choose-import candidate-imports)
381             (car candidate-imports))))
382     (if new-import
383         (if (jde-import-already-imports-class new-import existing-imports)
384             (message "This buffer already imports %s" new-import)
385           (jde-import-insert-imports-into-buffer (list new-import))))))
386  
387 (defun jde-import-insert-imports-into-buffer (new-imports &optional exclude)
388   "Inserts imports into the correct place in the buffer."
389   (save-excursion
390     (goto-char (jde-import-get-import-insertion-point))
391     (if (not jde-xemacsp) (deactivate-mark))
392     (if exclude
393       (setq new-imports (jde-import-exclude-imports new-imports)))
394     (loop for new-import in new-imports do
395           (when (> (length new-import) 0) ;; added to avoid insert empty import statements.
396             (insert
397              (concat "import " new-import ";\n"))
398             (message "Imported %s" new-import)))
399     (if jde-import-auto-collapse-imports
400         (let (jde-import-auto-collapse-imports) ;; setting this to avoid infinite recursion
401           (jde-import-collapse-imports)))
402     (if jde-import-auto-sort
403         (funcall jde-import-auto-sort-function))))
404
405
406 (defun jde-import-already-imports-class (class-name existing-imports)
407   "Determine if a class is already being imported."
408   (find
409    class-name
410    existing-imports
411    :test (lambda (new existing)
412                    (let ((new-package (jde-parse-get-package-from-name new))
413                          (new-class (jde-parse-get-unqualified-name new))
414                          (existing-package (jde-parse-get-package-from-name existing))
415                          (existing-class (jde-parse-get-unqualified-name existing)))
416                      (and
417                       (string= new-package existing-package)
418                       (or
419                        (string= new-class existing-class)
420                        (string= existing-class "*")))))))
421
422 (defun jde-import-strip-existing-imports (new-imports existing-imports)
423   "Exclude classes that have already been imported."
424   (delq 
425    nil
426    (mapcar
427     (lambda (new-import)
428       (unless  (jde-import-already-imports-class new-import existing-imports)
429         new-import)
430     new-imports))))
431
432 (defun jde-import-choose-import (new-imports)
433   "Prompts the user to select a class to import from a list of similarly
434  named candidates."
435   (efc-query-options
436          new-imports
437          "Select import to insert."
438          "Classes name dialog"))
439
440 (defun jde-import-kill-extra-imports (&optional comment)
441   "Delete extra Java import statements.
442 An import statement is considered extra if it is a duplicate,
443 imports a class from the package to which this file belongs,
444 it is not referenced in the file, 
445 or imports a class belonging to an already imported package, i.e.,
446 a package already imported by an import statement ending in .*.
447 If optional argument COMMENT is non-nil, the extra import statements
448 are commented out instead of deleted. 
449
450 Usage:
451   \\[jde-import-kill-extra-imports]
452   to kills extra imports.
453   \\[universal-argument] \\[jde-import-kill-extra-imports]
454   to comment out extra imports.
455
456 The current buffer must be in `jde-mode'."
457   (interactive "P")
458   (or (eq major-mode 'jde-mode)
459       (error "Major mode must be 'jde-mode'"))
460   (and (interactive-p)
461        (consp current-prefix-arg)
462        (setq comment t))
463   (let* ((tags    (semantic-fetch-tags))
464          (imports (semantic-brute-find-tag-by-class 'include tags)))
465     (if (not imports)
466         (message "No import found")
467       (let* ((packages (semantic-brute-find-tag-by-class 'package tags))
468              (package-imports
469               (append
470                (mapcar 
471                 (lambda (package)
472                   ;; Return a global import name from PACKAGE tag.
473                   ;; That is add ".*" at end of tag name.
474                   (concat (semantic-tag-name package) ".*"))
475                 packages)
476                (delq nil 
477                      (mapcar 
478                       (lambda (import)
479                         ;; Return tag name if IMPORT is global or nil if not.
480                         ;; IMPORT is global if its name ends with ".*".
481                         (let ((name (semantic-tag-name import)))
482                           (and (string-match "[.][*]\\'" name)
483                                name)))
484                       imports))))
485              (first-import (car imports))
486              extra-imports 
487              required-imports)
488         (save-excursion
489           ;; Get the list of extra imports
490           ;; Going to character zero so the the count-matches method work.
491           (goto-char 0)
492           (while imports
493             (let* ((import (car imports))
494                    (name (semantic-tag-name import))
495                    (classname (jde-import-get-classname name))
496                    (case-fold-search nil)
497                    (number-of-matches 
498                     (substring (count-matches 
499                                 (concat "\\b" classname "\\b")) 0 2)))
500               (if (or 
501                    ;; If name is already listed in the set
502                    ;; of required imports...
503                    (member name required-imports)
504                    ;;or the class is not reference in the file
505                    ;;and is not an import of the whole package i.e. .*
506                    (and (< (string-to-number number-of-matches) 2)
507                         (not (string= classname "*")))
508                    ;; or imports a class in the current package...
509                    (and
510                     ;; make sure name is not a package import, e.g., foo.bar.*
511                     (not (string-match "[.][*]\\'" name))
512                     (member 
513                      ;; convert class import to equivalent package import
514                      ;; e.g., foo.barClass to foo.*
515                      (concat
516                       (substring 
517                        name 
518                        0
519                        (or (string-match "[.][^.]+\\'" name)
520                            (length name)))
521                       ".*")
522                      package-imports)))
523                   ;; add name to the list of extra imports...
524                   (setq extra-imports (cons import extra-imports))
525                 ;; otherwise add to the list or required  imports
526                 (setq required-imports (cons name required-imports))))
527             (setq imports (cdr imports)))
528           (if (not extra-imports)
529               (message "No extra imports found")
530             (let ((count 0))
531               ;; Move the point at the beginning of the first import
532               (goto-char (semantic-tag-start first-import))
533               ;; Kill or comment out extra imports
534               (while extra-imports
535                 (let* ((extra-import (car extra-imports))
536                        (start (semantic-tag-start extra-import))
537                        (end (semantic-tag-end extra-import)))
538                   (setq count  (1+ count))
539                   (if comment
540                       (comment-region start end)
541                     ;; The following assumes that there is only one import
542                     ;; statement on the same line. Line end comments are deleted
543                     ;; too.
544                     (kill-region start
545                                  (progn
546                                    (goto-char end)
547                                    (forward-line)
548                                    (point))))
549                   (setq extra-imports (cdr extra-imports))))
550               (message "%d extra import%s removed"
551                        count (if (= count 1) "" "s")))))))))
552
553 ;;;;
554 ;;;; Helper functions
555 ;;;;
556
557 (defun jde-import-get-classname(import)
558   "Takes as an argument an import i.e. java.util.Vector.
559 And returns the class name. In the above example it will
560 return Vector"
561   (let ((pieces (split-string import "\\.")) class)
562     (setq class (car (last pieces)))
563     (setq pieces (split-string class "\\$")) 
564     (setq class (car (last pieces)))
565     class))
566
567 (defun jde-import-group-of (import-tag)
568   "Return the group IMPORT-TAG belongs to or nil if not found.
569 A group is found as soon as the import name matches a regexp in
570 `jde-import-group-of-rules'.  The returned group name depends on the
571 corresponding group definition in `jde-import-group-of-rules'."
572   (let ((import-name (semantic-tag-name import-tag))
573         (groups      jde-import-group-of-rules)
574         match rule regexp group)
575     (while (and groups (not match))
576       (setq rule    (car groups)
577             groups  (cdr groups)
578             regexp  (car rule)
579             group   (cdr rule)
580             match   (and (string-match regexp import-name)
581                          (cond ((stringp  group)
582                                 group)
583                                ((integerp group)
584                                 (match-string group import-name))
585                                (t
586                                 regexp)))))
587     match))
588
589 (defun jde-import-bucketize (imports)
590   "Bucketize IMPORTS tags.
591 Return a vector of buckets.  Each bucket is sorted alphabetically by
592 import name or in reverse order if `jde-import-reverse-sort-group' is
593 non-nil.  There is a bucket for each different group the function
594 specified by `jde-import-group-function' returns.  The last extra
595 bucket contains imports that do not belong to any group."
596   (let (import group others bins bin i n)
597     ;; Sort imports into an alist of groups.  Build a separate list
598     ;; for imports not in any group.
599     (while imports
600       (setq import  (car imports)
601             imports (cdr imports)
602             group   (funcall (or jde-import-group-function
603                                  #'jde-import-group-of)
604                              import))
605       (if (not group)
606           (setq others (cons import others))
607         (setq bin (assoc group bins))
608         (if bin
609             (setcdr bin (cons import (cdr bin)))
610           (setq bins (cons (cons group (list import)) bins)))))
611     ;; If required sort the bins by group name
612     ;; Remember that bins are in reverse order at this point.
613     (cond ((eq jde-import-sorted-groups 'asc)
614            (setq bins (sort bins
615                             (function
616                              (lambda (bin1 bin2)
617                                (string-lessp (car bin2)
618                                              (car bin1)))))))
619           ((eq jde-import-sorted-groups 'desc)
620            (setq bins (sort bins
621                             (function
622                              (lambda (bin1 bin2)
623                                (string-lessp (car bin1)
624                                              (car bin2)))))))
625           ((eq jde-import-sorted-groups 'gor)
626            (let* ((group-list (mapcar (function
627                                        (lambda (item) (cdr item)))
628                                       jde-import-group-of-rules)))
629              (setq bins 
630                    (sort bins 
631                          (function
632                           (lambda (bin1 bin2)
633                             (let* ((name1 (car bin1))
634                                    (name2 (car bin2))
635                                    (idx1 (length (member name1 group-list)))
636                                    (idx2 (length (member name2 group-list))))
637                               (< idx1 idx2)))))))))
638     ;; Build the vector of buckets.
639     (setq bins (vconcat
640                 (delq nil
641                       (nreverse
642                        (cons (cons jde-import-default-group-name
643                                    others)
644                              bins))))
645           n    (length bins)
646           i    0)
647     ;; Sort each bucket.
648     (while (< i n)
649       (setq bin (aref bins i))
650       (setcdr bin (if jde-import-reverse-sort-group
651                       (semantic-sort-tags-by-name-decreasing (cdr bin))
652                     (semantic-sort-tags-by-name-increasing (cdr bin))))
653       (setq i (1+ i)))
654     bins))
655
656 (defun jde-import-insert-group (group &optional skip-line name)
657   "Insert a GROUP of import texts in the current buffer.
658 If optional SKIP-LINE is non-nil skip a line before the group.
659 If optional NAME is non-nil add it as comment just before the group."
660   (when group
661     (when skip-line
662       (newline)
663       (if jde-import-blank-line-between-groups
664           (newline)))
665     (when (and jde-import-insert-group-names name)
666       (insert comment-start name)
667       (newline))
668     (insert (car group))
669     (setq group (cdr group))
670     (while group
671       (newline)
672       (insert (car group))
673       (setq group (cdr group)))))
674
675 ;;;;
676 ;;;; Commands
677 ;;;;
678
679 ;;;###autoload
680 (defun jde-import-organize (&optional force)
681   "Organize import statements of the current Java source buffer.
682 If optional FORCE is non-nil force reordering even if imports are
683 already organized.
684
685 Imports are organized into groups returned by the function specified
686 by `jde-import-group-function'.  Groups are inserted in the order they
687 are found unless `jde-import-sorted-groups' requires that they must be
688 alphabetically sorted.  In each group imports are sorted by name
689 alphabetically or in reverse order if `jde-import-reverse-sort-group'
690 is non-nil.  A blank line is inserted between groups.
691
692 Usage:
693   \\[jde-import-organize] group and sort import statements.
694   \\[universal-argument] \\[jde-import-organize] to force reordering.
695
696 The current buffer must be in `jde-mode'.  This command requires a
697 version of the JDE with the semantic parser."
698   (interactive "P")
699   (or (eq major-mode 'jde-mode)
700       (error "Major mode must be 'jde-mode'"))
701   (and (interactive-p)
702        (consp current-prefix-arg)
703        (setq force t))
704   (save-excursion
705     (let* ((tags  (semantic-fetch-tags))
706            (imports (semantic-brute-find-tag-by-class 'include tags)))
707       (if imports
708           (let* ((bins (jde-import-bucketize imports))
709                  (n    (length bins))
710                  i l sl changed group bin)
711             (if force
712                 (setq changed t)
713               ;; Check if imports already ordered
714               (setq sl (apply #'append (mapcar #'cdr bins))
715                     l  imports)
716               (while (and (not changed) l)
717                 (setq changed (not (string-equal
718                                     (semantic-tag-name (car l))
719                                     (semantic-tag-name (car sl))))
720                       l  (cdr l)
721                       sl (cdr sl))))
722             (if (not changed)
723                 (message "Import statements already ordered")
724               ;; Imports need to be reordered.
725               ;; 1- Get ordered import texts
726               (setq i 0)
727               (while (< i n)
728                 (setq bin (aref bins i))
729                 (setcdr bin (mapcar (function
730                                      (lambda (import)
731                                        (buffer-substring-no-properties
732                                         (semantic-tag-start import)
733                                         (progn
734                                           (goto-char (semantic-tag-end import))
735                                           (end-of-line) ; keep any line comment
736                                           (point)))))
737                                     (cdr bin)))
738                 (setq i (1+ i)))
739               ;; 2- Keep the point at the beginning of the first import
740               (goto-char (semantic-tag-start (car imports)))
741               ;; 2b- But check if the previous line already contains the
742               ;; group name for the first group
743               (when jde-import-insert-group-names
744                 (setq i 0)
745                 (while (and (< i n) (not group))
746                   (setq group (aref bins i)
747                         i     (1+ i)))
748                 (when (car group)
749                   (previous-line 1)
750                   (if (not (string< (concat comment-start (car group))
751                                     (thing-at-point 'line)))
752                       (next-line 1)))
753                 (setq group nil))
754               ;; 3- Kill current imports
755               (kill-region (point)
756                            (progn
757                              (goto-char (semantic-tag-end
758                                          (car (reverse imports))))
759                              (end-of-line)
760                              (point)))
761               ;; 4- Insert ordered imports
762               ;; Insert the first group found
763               (setq i 0)
764               (while (and (< i n) (not group))
765                 (setq group (aref bins i)
766                       i     (1+ i)))
767               (jde-import-insert-group (cdr group) nil (car group))
768               ;; Insert the others with a blank line before each group
769               (while (< i n)
770                 (setq group (aref bins i)
771                       i (1+ i))
772                 (jde-import-insert-group (cdr group) 'skip-line (car group)))))))))
773
774 (defcustom jde-import-collapse-imports-threshold 2
775   "Threshold level used by `jde-import-collapse-imports' to decide when a
776 package star import is used instead of single imports. If N is the number of
777 classes imported by the current buffer from a package and N is >= to the
778 threshhold, the JDEE replaces the class imports with a package import.
779 Setting the threshold to 0 causes the JDE to not collapse anything at
780 all."
781   :group 'jde-project
782   :type 'number)
783
784 (defun jde-import-collapse-imports (&optional comments)
785 "Function that collapse multiple class imports from the same package
786 into a single .* package import. Uses
787 `jde-import-collapse-imports-threshold' to decide when a .* statement
788 is generated. Implemented by adding the package statements and then
789 invoking `jde-import-kill-extra-imports' to clean up."
790   (interactive "P")
791   (or (eq major-mode 'jde-mode)
792       (error "Major mode must be 'jde-mode'"))
793   (let* ((tags    (semantic-fetch-tags))
794          (imports (semantic-brute-find-tag-by-class 'include tags)))
795     (if (<= jde-import-collapse-imports-threshold 0)
796         (message "Collapse threshold set to zero. No collapsing will occur.")
797     (if (not imports)
798         (message "No import found")
799       (let* ((package-buckets (jde-import-collapse-imports-bucketize imports))
800              (extra-imports   nil)
801              (required-imports nil)
802              (new-imports nil))
803         (while package-buckets
804           (let*
805               ((bucket (car package-buckets)))
806             (if (>= (length bucket) jde-import-collapse-imports-threshold)
807                 (progn
808                   (add-to-list 'extra-imports (cdr bucket))
809                   ;; Add the collapsing package statement
810                   (add-to-list 'new-imports (concat (car bucket) ".*")))
811               (add-to-list 'required-imports (cdr bucket))))
812           (setq package-buckets (cdr package-buckets)))
813         (jde-import-insert-imports-into-buffer new-imports)
814         (jde-import-kill-extra-imports comments))))))
815
816
817 ;; Contributed by Martin Schwamberger.
818 (defun jde-import-expand-imports (&optional no-exclude)
819    "Delete all package imports and replace them by their respective
820 class imports. The replacement is done by `jde-import-all'.
821 `jde-import-auto-collapse-imports' is temporarily disabled during the
822 execution of `jde-import-all'. The optional prefix argumet NO-EXCLUDE
823 is used by `jde-import-all'. This function is roughly the opposite of
824 `jde-import-collapse-imports'."
825    (interactive "P")
826    (let* ((tags  (semantic-fetch-tags))
827           (imports (semantic-brute-find-tag-by-class 'include tags))
828           import-all
829           package-import-start
830           package-import-end
831           jde-import-auto-collapse-imports) ; disable auto collapse
832      (dolist (import imports)
833        (when package-import-start
834          ;; kill from start of package-import to beginning of following import
835          (kill-region package-import-start (semantic-tag-start import))
836          (setq import-all t)
837          (setq package-import-start nil))
838        (when (string-match "\\.\\*" (semantic-tag-name import)) ; package-import?
839          (setq package-import-start (semantic-tag-start import))
840          (setq package-import-end (semantic-tag-end import))))
841      ;; kill last import?
842      (when package-import-start
843        ;; kill from start of package-import to end of line
844        (kill-region package-import-start
845                     (save-excursion
846                       (goto-char package-import-end)
847                       (end-of-line)
848                       (or (eobp) (forward-char))
849                       (point)))
850        (setq import-all t))
851      (if import-all
852          (jde-import-all no-exclude))))
853
854
855 (defun jde-import-collapse-imports-bucketize (imports)
856   "Put all imports into a bucket named as the package they belong to."
857   (let ((package-buckets))
858     (while imports
859       (let* ((import (car imports))
860              (name (semantic-tag-name import))
861              (packagename (jde-parse-get-package-from-name name))
862              (packagebin))
863         (setq packagebin (assoc packagename package-buckets))
864         (if packagebin
865             (setcdr packagebin (cons import (cdr packagebin)))
866           (setq package-buckets (cons (cons packagename (list import)) package-buckets)))
867         (setq imports (cdr imports))))
868   package-buckets))
869
870 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
871 ;;                                                                                   ;;
872 ;;  Import All                                                                       ;;
873 ;;                                                                                   ;;
874 ;;  Thanks to Philip Lord for the original idea for this command and for             ;;
875 ;;  contributing the initial implementation.                                         ;;
876 ;;                                                                                   ;;
877 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
878
879 (defun jde-import-all-find-classes-to-import ()
880   "Returns a list of unqualified class names to import into this
881 buffer. This function returns all the identifiers in the current
882 buffer that start with an uppercase character, have at least one lower
883 case character, and that are not included in an import statement and
884 are not the names of inner or outer classes declared in this buffer."
885   (let (declared-classes
886         imported-classes
887         classes-to-import)
888
889     ;; Get the names of classes that are already imported into this buffer.
890     (let ((import-tags (semantic-brute-find-tag-by-class 'include (current-buffer))))
891       (setq
892         imported-classes
893         (mapcar
894          (lambda (import-tag)
895            (jde-parse-get-unqualified-name (semantic-tag-name import-tag)))
896          import-tags)))
897
898     ;; Get the names of classes declared in this buffer.
899     (let ((buffer-class-tags (semantic-brute-find-tag-by-class 'type (current-buffer)))) 
900       (flet ((find-declared-classes 
901               (class-tag)
902               (let ((members (semantic-tag-get-attribute class-tag :members)))
903                 (dolist (member members)
904                   (if (eq (semantic-tag-class member) 'type)
905                       (progn
906                         (setq declared-classes 
907                               (append declared-classes (list (semantic-tag-name member))))
908                         (find-declared-classes member)))))))
909       (dolist (class-tag buffer-class-tags)
910          (setq declared-classes (append declared-classes  (list (semantic-tag-name class-tag))))
911          (find-declared-classes class-tag))))
912       
913     ;; Sort through the Java tokens in this buffer, looking
914     ;; for identifiers that start with an uppercase character and
915     ;; do not appear in an import statement or a toplevel
916     ;; class declaration.
917     (let ((tokens (semantic-lex-buffer 1000)))
918              (dolist (token tokens classes-to-import)
919       (let ((type (car token))
920             (start (cadr token))
921             (end (cddr token)))
922         (if (eq type 'IDENTIFIER)
923             (let (case-fold-search
924                   (name (buffer-substring-no-properties start end)))
925               (unless (or
926                        (string-match "^[a-z]" name)
927                        (not (string-match "[a-z]" name))
928                        (member name declared-classes)
929                        (member name imported-classes))
930                 (add-to-list 'classes-to-import  name t)))))))))
931
932 (defun jde-import-all-show ()
933   "Display a list of the class names referenced in this 
934 buffer that are not declared or explicitly imported into this
935 buffer and hence may need to be imported."
936   (interactive)
937   (let ((candidate-imports
938          (jde-import-all-find-classes-to-import)))
939     (with-output-to-temp-buffer "*jde import*"
940       (mapcar
941        (lambda(match)
942          (princ match)
943          (princ "\n"))
944        candidate-imports))))
945
946 (defun jde-import-all-filter (unqualified-imports &optional no-exclude)
947   "Generate a list of fully qualified names of classes to
948 import from UNQUALIFIED-IMPORTS, excluding classes specified
949 by `jde-import-exclude-imports' if NO-EXCLUDE is nil."
950   (mapcar
951    (lambda (unqualified-class)
952      (let ((qualified-imports (jde-import-get-qualified-names unqualified-class)))
953        (if no-exclude
954            qualified-imports
955          (jde-import-exclude-imports qualified-imports))))
956    unqualified-imports))
957
958 (defun jde-import-all-unique ()
959   "Import all classes uniquely referenced by unqualified class
960 names in the current buffer, i.e., all referenced classes for
961 which there is only one fully qualified name on the current
962 classpath."
963   (interactive)
964   (let ((list
965          (jde-import-all-filter (jde-import-all-find-classes-to-import)))
966         (retn))
967     (delq nil
968           ;; take single length sublists, and return item..
969           (mapcar
970            (lambda(item)
971              (if (= 1 (length item))
972                  (add-to-list 'retn
973                               (car item))))
974            list))
975     (if (< 0 (length retn))
976         (jde-import-insert-imports-into-buffer retn))))
977                    
978 (defclass jde-import-all-dialog(efc-multi-option-dialog) nil)
979
980 (defmethod initialize-instance ((this jde-import-all-dialog) &rest fields)
981   "Dialog constructor."
982   (call-next-method))
983
984 (defmethod efc-multi-option-dialog-sort ((this jde-import-all-dialog) list)
985   "Sort the options."
986   ;; sort the ones with the most options first...
987   (sort list
988         (lambda(a b)
989           ;; sort lexically
990           (if (= (length a)
991                  (length b))
992               (string< (car a)
993                        (car b))
994             ;; or by length
995             (> (length a)
996                (length b))))))       
997
998 (defun jde-import-all (&optional no-exclude)
999   "Imports all classes that need to be imported into the current buffer. 
1000 If any of the required imports are ambiguous, this command displays a dialog
1001 box that allows you to disambiguate the references.
1002 Classes specified by `jde-import-excluded-classes' will be excluded,
1003 unless the prefix argument NO-EXCLUDE is non-nil."
1004   (interactive "P")
1005   (let* ((imports 
1006           (jde-import-all-filter 
1007            (jde-import-all-find-classes-to-import) no-exclude))
1008          (unique-imports
1009           (delq 
1010            nil 
1011            (mapcar 
1012            (lambda (import) (if (= (length import) 1) (car import)))
1013            imports)))
1014          (ambiguous-imports
1015           (delq 
1016            nil
1017            (mapcar 
1018            (lambda (import) (if (> (length import) 1) import))
1019            imports)))
1020          (dialog
1021           (if ambiguous-imports
1022               (jde-import-all-dialog
1023                "Multi Classes Option"
1024                :options ambiguous-imports
1025                :text "Select imports to insert."))))
1026     (if dialog
1027         (progn
1028           (efc-dialog-show dialog)
1029           (setq unique-imports
1030                 (append unique-imports (oref dialog selection)))))
1031     (jde-import-insert-imports-into-buffer unique-imports)))
1032
1033
1034 (provide 'jde-import)
1035
1036
1037 ;;; History:
1038 ;;
1039 ;; $Log: jde-import.el,v $
1040 ;; Revision 1.46  2004/12/12 14:27:02  paulk
1041 ;; Add templates provided by Ole Arndt.
1042 ;;
1043 ;; Revision 1.45  2004/09/30 04:25:46  paulk
1044 ;; Change the default threshhold for collapsing imports to two classes. This causes the JDEE to collapse imports for any package from which the current buffer imports at least two classes.
1045 ;;
1046 ;; Revision 1.44  2004/09/30 04:18:21  paulk
1047 ;; Expand and fix documentation for jde-import-collapse-import command.
1048 ;;
1049 ;; Revision 1.43  2004/09/21 04:50:36  paulk
1050 ;; Include Martin Schwamberger's jde-import-expand-imports command.
1051 ;;
1052 ;; Revision 1.42  2004/08/11 04:24:00  paulk
1053 ;; Includes enhancements contributed by Martin Schwamberger.
1054 ;;
1055 ;; Revision 1.41  2004/05/19 04:17:45  paulk
1056 ;; Wrap all of jde-import-organize in a save-excursion form.
1057 ;;
1058 ;; Revision 1.40  2004/05/17 14:09:21  paulk
1059 ;; Cedet compatibility fix: change reference to semantic-toplevel-bovine-table to semantic--parse-table.
1060 ;;
1061 ;; Revision 1.39  2004/05/04 04:40:36  paulk
1062 ;; Force reparsing with semantic 1.4.
1063 ;;
1064 ;; Revision 1.38  2004/05/03 17:55:12  paulk
1065 ;; (jde-require 'sregex) to avoid shadowing standard version. Thanks to David Ponce.
1066 ;;
1067 ;; Revision 1.37  2004/03/22 06:23:10  paulk
1068 ;; jde-import-get-import-insertion-point takes class documention into account.
1069 ;; It no longer destroys class documentation. Also improved insertion of newlines.
1070 ;; Thanks to Martin Schwarmberger.
1071 ;;
1072 ;; Revision 1.36  2004/03/21 03:26:50  paulk
1073 ;; Removed Philip Lord's prototype code.
1074 ;;
1075 ;; Revision 1.35  2004/03/16 07:49:34  paulk
1076 ;; Add a jde-import-all command contributed by Philip Lord.
1077 ;;
1078 ;; Revision 1.34  2004/03/02 06:34:50  paulk
1079 ;; Update jde-import-excluded-packages to exclude packages that start with sun and com.sun. This classes contain classes named i and packages named e, confusing the JDEE when it tries to complete Iterator instances named i and Exception instances named e.
1080 ;;
1081 ;; Revision 1.33  2003/09/22 02:56:24  paulk
1082 ;; Cosmetic changes.
1083 ;;
1084 ;; Revision 1.32  2003/09/07 05:19:28  paulk
1085 ;; Extend jde-import-excluded-classes to exclude classes that
1086 ;; belong to the same package as the importing class. Thanks to
1087 ;; Martin Schwamberger.
1088 ;;
1089 ;; Revision 1.31  2003/04/09 01:25:19  jslopez
1090 ;; Updates method call from jde-import-insert-imports to jde-import-insert-import.
1091 ;;
1092 ;; Revision 1.30  2003/04/06 08:17:12  paulk
1093 ;; Fixed regression caused by Andy's efc XEmacs compatibility
1094 ;; changes. The regression was caused by the plural in the name
1095 ;; jde-import-choose-imports which implies that it should return a list
1096 ;; of imports selected by a user when in fact it should return only
1097 ;; one. The plural misled Andy to enclose the import selected by the user
1098 ;; in a list. I removed the enclosing list and I renamed the function and
1099 ;; a set of other similarly misnamed functions to the singular, e.g.,
1100 ;; jde-import-choose-import, to reflect the fact that they actually
1101 ;; insert only a single import.
1102 ;;
1103 ;; Revision 1.29  2003/03/28 05:33:29  andyp
1104 ;; XEmacs optimizations for JDEbug and efc.
1105 ;;
1106 ;; Revision 1.28  2003/02/28 14:53:08  jslopez
1107 ;; Fixes bug in jde-import-insert-imports.
1108 ;; If new-imports contain only one import and this import is excluded the
1109 ;; code was importing a nil value.
1110 ;;
1111 ;; Revision 1.27  2003/02/26 02:59:38  jslopez
1112 ;; Supresses more error messages when completing.
1113 ;;
1114 ;; Revision 1.26  2003/02/25 05:20:25  paulk
1115 ;; Fix bug that causes jde-import-organize to insert the group name
1116 ;; multiple times when called repeatedly.
1117 ;; Thanks to Joshua Spiewak <JSpiewak@axeda.com>
1118 ;;
1119 ;; Revision 1.25  2003/02/18 02:09:40  jslopez
1120 ;; Fixes regression bugs.
1121 ;;
1122 ;; Revision 1.24  2003/01/17 20:58:06  jslopez
1123 ;; Fixes regression bug causing excluded imports to show in the
1124 ;; import list.
1125 ;; Fixes typo in jde-import-insert-imports. It was using new-imports instead
1126 ;; of candidate-imports.
1127 ;;
1128 ;; Revision 1.23  2003/01/12 20:05:26  paulk
1129 ;; - Check whether import already exists AFTER the user selects the
1130 ;;   import. This is to prevent the JDE from importing a class that
1131 ;;   is already imported but from a different package.
1132 ;; - Display message when the buffer already imports the specified class.
1133 ;; - Clean up the code.
1134 ;;
1135 ;; Revision 1.22  2003/01/10 13:27:01  paulk
1136 ;; Fix jde-import-strip-existing-imports so that it handles package import statements.
1137 ;;
1138 ;; Revision 1.21  2002/09/06 13:07:12  jslopez
1139 ;; Fixes jde-import-get-classname to handle inner classes.
1140 ;;
1141 ;; Revision 1.20  2002/08/07 06:36:17  paulk
1142 ;; Removed code intended to eliminate spurious warnings when byte-compiling the JDEE. The
1143 ;; removed code now resides in a separate package, jde-compat.el. Thanks to Andy Piper
1144 ;; for suggesting this restructuring. Also fixed a number of compiler warnings caused
1145 ;; by genuine bugs.
1146 ;;
1147 ;; Revision 1.19  2002/05/31 18:55:08  mnl
1148 ;; Added sorting of import statements according to their occurance in the
1149 ;; group-of-rules.
1150 ;;
1151 ;; Revision 1.18  2002/05/30 04:43:31  paulk
1152 ;; Fixes bug in jde-import-get-import-insertion-point that
1153 ;; caused it to mishandle insertion of import statements
1154 ;; after package statements. Thanks to Phillip Lord <p.lord@russet.org.uk>.
1155 ;;
1156 ;; Revision 1.17  2002/02/03 07:01:39  paulk
1157 ;; Adds support for inserting group names before groups. Thanks to
1158 ;; Brian Paulsmeyer and David Ponce.
1159 ;;
1160 ;; Revision 1.16  2002/01/28 07:07:50  paulk
1161 ;; * Adds jde-import-auto-collapse-imports variable. Customizing this variable to a nonnil value
1162 ;;   causes the JDE to run jde-import-collapse-imports after importing a class. Thanks to
1163 ;;   "Max Rydahl Andersen" <max@eos.dk>.
1164 ;;
1165 ;; * Also cleaned up the code to jde-import-insert-imports-into-buffer.
1166 ;;
1167 ;; Revision 1.15  2002/01/27 04:09:57  paulk
1168 ;; Remove duplicates from import list. Thanks to Stephen Molitar.
1169 ;;
1170 ;; Revision 1.14  2002/01/06 06:56:09  paulk
1171 ;; jde-import-choose-imports now checks for the case where the user cancels
1172 ;; the class selection dialog.
1173 ;;
1174 ;; Revision 1.13  2001/12/08 13:55:29  jslopez
1175 ;; Updates the function jde-import-choose-imports to use
1176 ;; efc-option-dialog.
1177 ;;
1178 ;; Revision 1.12  2001/11/30 11:13:43  jslopez
1179 ;; Rolling back my previous changes to
1180 ;; jde-import-choose-imports, to fix regression bug.
1181 ;;
1182 ;; Revision 1.11  2001/11/28 22:50:24  jslopez
1183 ;; Fixes compilation messages.
1184 ;;
1185 ;; Revision 1.10  2001/10/19 08:57:27  paulk
1186 ;; Adds the customization variable jde-import-auto-sort-function.
1187 ;; This variable allows you to specify the function used by
1188 ;; the JDE to sort imports. Thanks to Hugh Emberson.
1189 ;;
1190 ;; Revision 1.9  2001/07/31 05:22:48  paulk
1191 ;; Adds jde-import-collapse-imports command. Thanks to Max Rydahl Andersen.
1192 ;;
1193 ;; Revision 1.8  2001/07/06 02:10:43  paulk
1194 ;; Bug fix in removing unneeded import statements.
1195 ;;
1196 ;; Revision 1.7  2001/06/07 03:35:01  paulk
1197 ;; Further fine-tuned import insertion point function.
1198 ;;
1199 ;; Revision 1.6  2001/06/06 05:19:28  paulk
1200 ;; Improved calculation of import insertion point.
1201 ;;
1202 ;; Revision 1.5  2001/04/27 01:33:42  paulk
1203 ;; jde-import-sort now refreshes parse cache. Thanks to Robert Mecklenburg <mecklen@cimsoft.com> for tthis fix.
1204 ;;
1205 ;; Revision 1.4  2001/04/26 09:06:07  paulk
1206 ;; -- jde-import-kill-extra-imports now refreshes the buffer's parse cache. This fixes a bug where successive calls to the function would incorrectly remove imports.
1207 ;;
1208 ;; -- jde-import-kill-extra-imports now removes fully qualified imports that are not referenced in the code.
1209 ;;
1210 ;; Thanks to "Javier Lopez" <jlopez@cellexchange.com>.
1211 ;;
1212 ;; Revision 1.3  2001/03/13 04:19:45  paulk
1213 ;; Cosmetic changes.
1214 ;;
1215 ;; Revision 1.2  2000/11/27 06:18:40  paulk
1216 ;; Miscellaneous bug fixes and minor enhancements.
1217 ;;
1218 ;; Revision 1.1  2000/11/20 05:15:15  paulk
1219 ;; Added jde-import-organize command. Moved all import-related code from
1220 ;; jde-wiz.el to a new package named jde-import.el.
1221 ;;
1222 ;; Revision 1.2  2000/11/17 11:52:54  david_ponce
1223 ;; - New `jde-import-group-function' option to specify the function used
1224 ;;   to associate import token to group. The default one is
1225 ;;   `jde-import-group-of'. This let the user to completely handle the
1226 ;;   way imports are grouped.
1227 ;;
1228 ;; - New `jde-import-sorted-groups' option to specify if groups will be
1229 ;;   sorted. Notice that the *default* group (the one that contains
1230 ;;   imports not belonging to any specific group) is allways the last
1231 ;;   group.
1232 ;;
1233 ;; - Improvement of the function `jde-import-group-of'. For consistency
1234 ;;   `jde-import-group-rules' is now `jde-import-group-of-rules' and it
1235 ;;   is now possible to associate a group regexp to a particular name.
1236 ;;
1237 ;; Revision 1.1  2000/11/17 11:48:31  david_ponce
1238 ;; Initial Revision.
1239 ;;
1240
1241 ;;; jde-import.el ends here