Hi.
Attached is the first version of jde-import 1.1
This is a small package who provides two utilities functions for Java
import statements. `jde-import-sort-imports' performs an alphabetic
sort of the imports, whilst `jde-import-remove-unused-imports' checks
that the import statements are actually required in the class.
These functions may be useful for those developers who likes to use
`jde-wiz-find-and-import', and doesn't like the use of "import Foo.*;"
sentences. The docs explains how to get your import sorted after every
`jde-wiz-find-and-import' use.
Many thanks to Phillip Lord. Not only his feedback was very valuable,
in fact he wrote most of the code.
I've run that functions to the java files of my project without
finding any problem (If you don't count the problem of work with some
java programmers who likes to cut-and-paste huge block of imports :)
You feedback (comments, bug reports) will be welcome.
--
Leon
;;; jde-import.el --- Utility functions for Java import statements.
;; $Revision: 1.1 $
;; $Date: 2000/05/27 21:38:13 $
;; This file is not part of Emacs
;; Author: Juan Leon Lahoz Garcia <[EMAIL PROTECTED]>
;; Author: Phillip Lord<[EMAIL PROTECTED]>
;; COPYRIGHT NOTICE
;;
;; This program 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.
;; This program 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 this program; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;
;; This package provides two utilities functions for Java import
;; statements. `jde-import-sort-imports' performs an alphabetic sort
;; of the imports, whilst `jde-import-remove-unused-imports' checks
;; that the import statements are actually required in the class.
;;; Limitations:
;;
;; 1) `jde-import-remove-unused-imports' requires some sort of
;; syntactic analysis of the class. As this would be rather
;; complicated to code, the only check done when searchin occurrences
;; of a class is to see if they are into a comment or a quoted string.
;; If there are variables or methods named as classes that are not
;; used but imported, some import sentences could be not removed. Good
;; naming conventions avoid this minor problem.
;;
;; 2) jde-import-remove-unused-imports can not cope with
;; imports with wildcard "*"'s in them.
;;; Tips & Tricks:
;;
;; An easy mode of having your import sentences always sorted (well,
;; if you use `jde-wiz-find-and-import') is to include this in one of
;; your configuration files:
;;
;; (defadvice jde-wiz-insert-imports-into-buffer
;; (after jde-wiz-find-and-import activate)
;; "Runs sort function after import so that functions are always sorted.
;; Would make more algorithmic sense to put the import at the right place,
;; but this is easiest"
;; (jde-import-sort-imports))
;;
;; If you wanna to use both functions at once you can use
;; `jde-import-clean-imports-sentences' or
;; `jde-import-clean-imports-sentences-in-file'. These functions are
;; very useful for batch processing lots of java files.
;;; History:
;;
;; First release
;;; Code:
(defvar jde-import-non-interactive-import-removing nil
"Non-niil means suppress the confirmation dialog.
This is meant for use in batch processing of import statements")
(defun jde-import-remove-some-unused-imports()
"Remove some import sentences of a java buffer. The sentences
removed are the imports of classes that are not used in the buffer.
Since this function uses `jde-import-class-used-maybe', not all the
unused imports are removed.
Note: this function doesn't works properly on \"import Foo.*\;\"
sentences, but if you don't care about using this type of import
sentences, then you don't care about unused imports and you'll never
use this function
See also `jde-import-class-used-maybe'"
(interactive)
(let((unused-imports nil))
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^import.*\\(\\.\\| \\)\\(\\w+\\);" nil t)
(let ((class (match-string 2))
(import-statement (match-string 0))
(used t))
(if (not (jde-import-class-used-maybe class))
(setq unused-imports (cons import-statement unused-imports))))))
(if (and (not jde-import-non-interactive-import-removing)
(not unused-imports))
(message "No unused imports detected")
(if jde-import-non-interactive-import-removing
(jde-import-remove-imports-from-buffer unused-imports (current-buffer))
(jde-import-remove-imports-dialog unused-imports (current-buffer))))))
(defun jde-import-class-used-maybe (class)
"Check if a CLASS is used in a java buffer.
The check is not perfect: if the class is used (and if there isn't a
bug) the function returns true, but if the class is not used this
function may be fooled if there is an instance of any class called
like the class."
(save-excursion
(let ((founded nil)
(classregexp
(concat "\\b" class "\\b" )))
;;now check all the other times the type occurs as a word
(while (and (not founded) (re-search-forward classregexp nil t))
(setq founded
;;if we are not in a comment or quoted then we have what
;;we need
(not (jde-import-comment-or-quoted-p))))
founded)))
; (defun jde-import-comment-or-string-p()
; "Are we on a string or a comment?"
; (let ((faces (get-text-property (point) 'face)))
; ;;I can never get the hang of whether faces is returning a
; ;;list or what. Make sure that it is
; (if (not (listp faces))
; (setq faces (list faces)))
; (or (memq 'font-lock-comment-face faces)
; (memq 'font-lock-string-face faces))))
;; This function was stolen from jde-cflow...!
(defun jde-import-comment-or-quoted-p ()
"Returns t if point is in a comment or a quoted string. nil otherwise"
(interactive "p")
;; limit our analysis to the current line.
(let ((beg (save-excursion (beginning-of-line) (point))))
(if
(or
;; are we in a javadoc comment?
(save-excursion
(re-search-backward
"^[ \t]*/?\\*"
beg t))
;; are we in a '//' or a '/*' style comment?
;; note that /* or /** on a line with only leading whitespace
;; will have matched in the previous regex. We check again here
;; because the above case needs to allow for a line with
;; the continuation of a comment (using only a '*') whereas this
;; requires the presence of a '/' in front of the '*' so as to
;; distinguish a comment from a '*' operator.
;; To make a long story short,
;; the first regex matches
;; /* a comment */
;; and
;; /**
;; * a comment
;; */
;; while the second one matches
;; System.out.println(foo); /* a comment */
;; but not
;; i = 3 * 5;
;; if you do something like following, you're on your own:
;; i = 3
;; * 5;
;; Suggestions for improving the robustness of this algorithm
;; gratefully accepted.
(save-excursion
(re-search-backward
"\\(//\\|/\\*\\)"
beg t))
;; are we in a quoted string?
(save-excursion
(re-search-backward
"\"" ;;
beg t)))
t ;; return true if we had any matches; nil otherwise
nil)))
(defvar jde-import-remove-import-imports nil)
(defvar jde-import-remove-import-buffer nil)
(defun jde-import-remove-imports-dialog (unused-imports buffer)
"Prompts the user with all the imports that it is intended to remove.
Argument UNUSED-IMPORTS imports to remove.
Argument BUFFER buffer from which to remove."
(let ((buf (get-buffer-create "*Confirm Import Removal*")))
(setq jde-import-remove-import-imports unused-imports)
(setq jde-import-remove-import-buffer buffer)
(set-buffer buf)
(erase-buffer)
(widget-insert "The following import statements have been marked \n" )
(widget-insert "for removal. Please deselect any that you want to retain \n" )
(widget-insert "and then click the OK button. \n" )
(let (i n)
(setq i 0)
(setq n (length jde-import-remove-import-imports))
(while (< i n)
(let* ((import-to-kill (nth i jde-import-remove-import-imports))
(args (list
;;type of widget
'checkbox
;;properties of this widget
:value import-to-kill
:format "\n %[%v%] %t"
:tag import-to-kill
;;what to do on activate/deactivate
:notify (lambda (widget &rest ignore)
(let ((value (widget-get widget ':tag)))
;;if its there remove it
(if (find value jde-import-remove-import-imports)
(progn (setq jde-import-remove-import-imports
(delq value
jde-import-remove-import-imports))
(message "You have deselected: %s" value))
;else we need to add it
(progn (setq jde-import-remove-import-imports
(nconc (list value)
jde-import-remove-import-imports))
(message "You have selected: %s"
value))))))))
(apply 'widget-create args)
(setq i (+ i 1)))))
(widget-insert "\n")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(let ((dialog-buffer
(current-buffer)))
(delete-window)
(kill-buffer dialog-buffer)
(if jde-import-remove-import-imports
(progn (jde-import-remove-imports-from-buffer
jde-import-remove-import-imports
jde-import-remove-import-buffer)
(message "Removed imports"))
(message "No imports removed" ))))
"Ok")
(widget-create 'push-button
:notify (lambda (&rest ignore)
(let ((dialog-buffer
(current-buffer)))
(delete-window)
(kill-buffer dialog-buffer)))
"Cancel")
(use-local-map widget-keymap)
(widget-setup)
;;default to "Ok"
(beginning-of-line)
(pop-to-buffer buf)))
(defun jde-import-remove-imports-from-buffer (imports buffer)
"Actually kill IMPORTS statements from BUFFER."
(save-excursion
(set-buffer buffer)
(jde-import-log-removal-new-buffer buffer)
(let (i n)
(setq i 0)
(setq n (length imports))
(while (< i n)
(goto-char (point-min))
(search-forward (nth i imports) nil t)
(beginning-of-line)
(kill-line 1)
(jde-import-log-remove-import (nth i imports))
(setq i (+ 1 i))))))
(defun jde-import-log-removal-new-buffer (buffer)
"Reports import removal from a new BUFFER."
(save-excursion
(set-buffer (get-buffer-create "*Jde Imports Removal Log*"))
(goto-char (point-max))
(insert "Removing Imports from " (buffer-file-name buffer) "\n")))
(defun jde-import-log-remove-import (import)
"Reports removal of IMPORT from a file."
(save-excursion
(set-buffer (get-buffer-create "*Jde Imports Removal Log*"))
(goto-char (point-max))
(insert "Removing " import "\n")))
(defun jde-import-sort-imports()
"Sort the \"import\" sentences in a file"
(interactive)
(save-excursion
(goto-char (point-min))
(search-forward-regexp "^import.*;")
(let ((beg-imports (match-beginning 0)))
(goto-char (point-max))
(search-backward-regexp "^import.*;")
(let ((end-imports (match-end 0)))
(sort-lines nil beg-imports end-imports)))))
(defun jde-import-clean-imports-sentences()
"Do some cleanup in current buffer's import sentences"
(interactive)
(if noninteractive
(setq jde-import-non-interactive-import-removing t))
(jde-import-sort-imports)
(jde-import-remove-some-unused-imports))
(defun jde-import-clean-imports-sentences-in-file(file)
"Do some cleanup in a file import sentences. Useful for batch
processing files"
(interactive)
(find-file file)
(jde-import-clean-imports-sentences)
(save-buffer))
(provide 'jde-import)
;;; jde-import.el ends here