-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hey.
I wrote this a while back and have been steadily improving it. I have other
code which relies on this so I would like to see it integrated into the JDE.
The main difference is that none of the methods here use a JVM... so they are
very fast.
Kevin
;;; jde-guess.el --- guess information about java buffers.
;; $Id: jde-guess.el,v 1.4 2001/03/17 09:42:35 burton Exp $
;; Copyright (C) 1997-2000 Free Software Foundation, Inc.
;; Author: Kevin A. Burton ([EMAIL PROTECTED])
;; Maintainer: Kevin A. Burton ([EMAIL PROTECTED])
;; Location: http://relativity.yi.org
;; Keywords:
;; Version: 1.0.0
;; This file is [not yet] part of GNU Emacs.
;; 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 of the License, or 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; if not, write to the Free Software Foundation, Inc., 59 Temple
;; Place - Suite 330, Boston, MA 02111-1307, USA.
;;; Commentary:
;;; TODO:
;; - By default all functions should be silent. If we what to display
;; information we should call -show. If we want then fixed we should call -fix
;; or -setup functions.
;;
;; - this package should also function as a library. Most methods would take
;; parameters.
;;
;; - test all these functions with .java files that have no package.
;;
;; - classname guessing doesn't work with "public abstract class"
;;; History:
;;; Code:
(defvar jde-guess-package-buffer "*jde-guess-package-buffer*"
"Temp buffer for guessing.")
(defvar jde-guess-sourcepath nil "Sourcepath for java buffers. This should not
be used directly but by the function (jde-guess-sourcepath).")
(defvar jde-guess-imports '() "Additional imports required for .java files.
Should be a list of packages classes (import qualifiers) to import. Example:
java.util.* java.lang.String")
(defun jde-guess-base-directory()
"Guess the base directory of a java file based on its package. Example. If a
file were stored in '/home/foo/projects/java/lang/String.java' the package would
be removed and this would return '/home/foo/projects'."
(assert (equal major-mode
'jde-mode) nil "Not a java buffer.")
(save-excursion
(let((directory nil)
(package nil)
(package-path nil)
(java-file (buffer-file-name)))
(setq package (jde-guess-package))
(set-buffer (get-buffer-create jde-guess-package-buffer))
(erase-buffer)
;;get the path section as the package...
(insert package)
(beginning-of-buffer)
(jde-guess-replace-string "." "/")
(setq package-path (buffer-substring (point-min) (point-max)))
(erase-buffer)
(insert java-file)
(jde-guess-replace-string ".java" "")
(end-of-buffer)
(if (search-backward package-path)
(replace-match ""))
(jde-guess-replace-string (concat "/" (file-name-nondirectory java-file)) "")
(setq directory (buffer-substring (point-min) (point-max)))
directory)))
(defun jde-guess-packages( directory &optional root)
"Given a directory, go through all sub-directories and find packages. The
given directory is assumed to be the based for the packages."
(if (null root)
(setq root directory))
(let((packages '())
new-package
current-file
files
(still-need-package t)
(index 0))
(setq files (directory-files directory t))
(while (< index (length files))
(setq current-file (elt files index))
;;figure out what to do based on the filename
;;ignore certain directories
(if (and (not (string-match "CVS$" directory))
(not (string-match "\\.$" directory))
(not (string-match "\\.\\.$" directory)))
(progn
;;if it is a directory... dive into it.
(if (and (file-directory-p current-file)
(not (string-equal directory current-file)))
(let(next-level-packages)
(setq next-level-packages (jde-guess-packages current-file
root))
(setq packages (append packages next-level-packages))))
(if (and still-need-package
(string-match "\\.java$" current-file))
(progn
(set-buffer (get-buffer-create jde-guess-package-buffer))
(erase-buffer)
(insert current-file)
(beginning-of-buffer)
(jde-guess-replace-string root "")
(jde-guess-replace-string (concat "/" (file-name-nondirectory
current-file)) "")
(beginning-of-buffer)
(jde-guess-replace-string "/" ".")
(setq new-package (buffer-substring (point-min) (point-max)))
(setq still-need-package nil)
(add-to-list 'packages new-package)))))
(setq index (1+ index)))
packages))
(defun jde-guess-setup-class-interface()
"Setup the java class or interface correctly."
(interactive)
(save-excursion
(beginning-of-buffer)
(let(class)
(setq class (jde-guess-class))
(if (re-search-forward "^public \\(class\\|interface\\) " nil t)
(progn
;;now replace find the class.
(re-search-forward "[a-zA-Z0-9]+" nil t)
(replace-match class))
(error "Unable to find class or interface")))))
(defun jde-guess-setup-import()
"Setup java class imports... Require that java.util.*, java.net.* and
java.io.* are imported and then sort the imports."
(interactive)
;;FIXME: make sure there is at least one line before and after the imports.
(assert (equal major-mode
'jde-mode) nil "Not a java buffer.")
(if jde-guess-imports
(let((import nil)
(index 0))
(assert (listp jde-guess-imports)
nil "jde-guess-imports must be a list.")
(while (< index (length jde-guess-imports))
(setq import (elt jde-guess-imports index))
(jde-guess-import-require-import import)
(setq index (1+ index)))))
(jde-guess-import-require-import "java.util.*")
(jde-guess-import-require-import "java.io.*")
(jde-guess-import-require-import "java.net.*")
;;now sort the imports
(jde-import-sort))
(defun jde-guess-import-require-import( target )
"Require that the given target is imported within this java class."
(assert (equal major-mode
'jde-mode) nil "Not a java buffer.")
(save-excursion
(let(class-begin import-begin)
(beginning-of-buffer)
(save-excursion
(if (re-search-forward "^import" nil t)
(setq import-begin (match-beginning 0)))
;;is no imports... to find the package and use the next line.
(if (and (null import-begin)
(re-search-forward "^package" nil t))
(progn
(forward-line 2)
(setq import-begin (point))))
;;find the class or interface
(if (re-search-forward "^public \\(class\\|interface\\)" nil t)
(setq class-begin (match-beginning 0)))
(assert import-begin
nil "Could not find import statement")
(assert class-begin
nil "Could not find class statement"))
(if (not (re-search-forward (concat "^import " target ) class-begin t))
(progn
;;insert this required class
(goto-char import-begin)
(insert (concat "import " target ";\n")))))))
(defun jde-guess-setup-buffer()
"Guess certain values about the current buffer and update it so that it is
correct. This will correct import statements by calling `jde-guess-import-setup'
and will also update the classname. It will also setup the correct package."
(interactive)
(if (= (buffer-size) 0)
(insert "package UNKNOWN;\n\nimport java.util.*;\n\n public class UNKNOWN { "))
;;fix imports.
(jde-guess-setup-import)
;;fix the package statement
(jde-guess-setup-package)
;;fix the public class declaration
(jde-guess-setup-class-interface))
(defun jde-guess-setup-package()
"Find the correct package (if possible) and then update the 'package'
statement."
(interactive)
(let (real-package)
(setq real-package (jde-guess-package))
(save-excursion
(beginning-of-buffer)
(if (re-search-forward "^package .*$" nil t)
(replace-match (concat (format "package %s;" real-package)))
(error "Package declaration not found")))))
(defun jde-guess-package-incorrect()
"Determine if the 'package' statement in this .java buffer is incorrect."
(interactive)
(assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")
(let(default-package real-package)
(setq default-package (jde-guess-current-package))
(setq real-package (jde-guess-package))
(if (not (string-equal default-package
real-package))
(error "The package declaration in this buffer is incorrect, it should be: %s"
real-package))))
(defun jde-guess-current-package()
"Get the current package or nil if there is no package statement. This just
looks for the 'package NAME;' statement in the current buffer and just parses
that."
(save-excursion
(beginning-of-buffer)
(if (re-search-forward "^package " nil t)
(let(begin end package)
(setq begin (match-end 0))
(if (re-search-forward ";$"nil t)
(setq end (match-beginning 0)))
(assert (and begin end) nil "Unable to determine begin and end of package")
(setq package (buffer-substring begin end))
package)
(message "No package found")
nil)))
(defun jde-guess-package()
"This should try to determine the package based on the filename and
java sourcepath."
(interactive)
(assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")
(save-excursion
(let((package-name nil)
(classname nil))
(setq package-name (jde-guess-classname))
(assert package-name
nil "Unable to determine package name.")
(set-buffer (get-buffer-create jde-guess-package-buffer))
(erase-buffer)
(insert package-name)
(beginning-of-buffer)
(end-of-line)
(search-backward ".")
(setq package-name (buffer-substring (point-min) (point)))
(message "Package: %s" package-name)
package-name)))
(defun jde-guess-class()
"This should try to determine the class based on the filename."
(interactive)
(assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")
(save-excursion
(let((class (buffer-name)))
(set-buffer (get-buffer-create jde-guess-package-buffer))
(erase-buffer)
(insert class)
(beginning-of-buffer)
(jde-guess-replace-string ".java" "")
(end-of-line)
(setq class (buffer-substring (point-min) (point-max)))
(message "Class: %s" class)
class)))
(defun jde-guess-sourcepath()
"Use `jde-db-source-directories' and java sourcepath to determine the correct
sourcepath to use. "
(if (null jde-guess-sourcepath)
(let((current-entry nil)
(index 0))
(setq jde-guess-sourcepath jde-compile-option-sourcepath)
;;loop through jde-compile-option-sourcepath and if an item isn't in the
;;list, add it.
(while (< index (length jde-db-source-directories))
(setq current-entry (elt jde-db-source-directories index))
(if (not (assoc current-entry jde-guess-sourcepath))
(add-to-list 'jde-guess-sourcepath current-entry))
(setq index (1+ index)))))
jde-guess-sourcepath)
(defun jde-guess-classname()
"This should try to determine the fully qualified classname (FQCN) based on
the filename and the java sourcepath."
(interactive)
(let((sourcepath (jde-guess-sourcepath)))
(assert (and sourcepath
(listp sourcepath))
nil "sourcepath must have a value and should be a list")
(assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")
(save-excursion
(let((match nil)
(classname nil)
(current-directory nil)
(index 0)
(found nil)
(file-name (file-truename (buffer-file-name))))
(while (and (not found)
(< index (length sourcepath)))
(setq current-directory (file-truename (elt sourcepath index)))
(setq match (string-match current-directory file-name))
(if (and match
(= match 0))
(progn
;;mark as found
(setq found t)
;;rip the directory off, rip .java off and replace all "/" chars
;;with "."
(set-buffer (get-buffer-create jde-guess-package-buffer))
(erase-buffer)
(insert file-name)
(beginning-of-buffer)
;;add a trailing / to the dir just in case.
(jde-guess-replace-string (concat current-directory "/" ) "")
(jde-guess-replace-string current-directory "")
(beginning-of-buffer)
(jde-guess-replace-string ".java" "")
(beginning-of-buffer)
(jde-guess-replace-string "/" ".")
(setq classname (buffer-substring (point-min) (point-max)))))
(setq index (1+ index)))
(assert found
nil "Unable to find the filename within the current sourcepath")
(message "Classname: %s" classname)
classname))))
(defun jde-guess-replace-string(from-string to-string)
"Replace strings"
(while (search-forward from-string nil t)
(replace-match to-string)))
(provide 'jde-guess)
- --
Kevin A. Burton ( [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] )
Cell: 408-910-6145 URL: http://relativity.yi.org ICQ: 73488596
Free Software. Join the conspiracy!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: Get my public key at: http://relativity.yi.org/pgpkey.txt
iD8DBQE63gTXAwM6xb2dfE0RAswMAJsEcvAN8IeFnvvL0vJruTKtQqnY9QCfTSvw
GuFQFK85VcDoIduXEisB90g=
=i99W
-----END PGP SIGNATURE-----