-----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-----

Reply via email to