Subject: Re: ANN: JDE 2.2.7beta2 available at ...
From: [email-masked] (Kevin A. Burton)
To: Paul Kinnucan <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked], [email-masked], [email-masked]
Date: 24 Feb 2001 22:06:08 -0800

Paul Kinnucan <[email-masked]> writes:

<snip>

> * Adds jde-package-update command.
> 
>   This command generates or updates the package statement at
>   the head of the current Java source buffer based on the
>   location of the buffer directory in the classpath.
> 
>   Thanks to David Ponce for providing this command.
<snip>

I have been working on a package called jde-guess which does a lot of this
stuff... updates classname, updates imports, updates package, etc.  It is called
'jde-guess'.  Here is my current impl if anyone is interested.  It works 99% of
the time but I am not ready to release it officially.

I guess the goal is to have all file updating like this in on package.  There is
also a generic function jde-guess-setup-buffer which does all of the above.

Kevin

;;; jde-guess.el --- guess information about java buffers.

;; $Id: jde-guess.el,v 1.2 2001/02/21 00:00:53 burton Exp $

;; Copyright (C) 1997-2000 Free Software Foundation, Inc.

;; Author: Kevin A. Burton ([email-masked])
;; Maintainer: Kevin A. Burton ([email-masked])
;; 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:

;;;
;; FIXME: test all these functions with .java files that have no package.

;; FIXME: classname guessing doesn't work with "public abstract class"

(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)
      (replace-string "."  "/")
      (setq package-path (buffer-substring (point-min) (point-max)))

      (erase-buffer)
      (insert java-file)
      (replace-string ".java" "")
      (end-of-buffer)
      (if (search-backward package-path)
          (replace-match ""))
      (replace-string (concat "/" (file-name-nondirectory java-file)) "")

      (setq directory (buffer-substring (point-min) (point-max)))
      
      directory)))
  
(defun jde-guess-get-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-get-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)
                  (replace-string root "")
                  (replace-string (concat "/" (file-name-nondirectory current-file)) "")
                  (beginning-of-buffer)
                  (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-get-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-get-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-insert()
  "Guess the package and insert the appropriate package declaration line."
  (interactive)

  (assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")
  
  (beginning-of-line)
  (insert (format "package %s;" (jde-guess-package))))

(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-insert()
  "Guess the class and then insert an appropriate class declaration."
  (interactive)

  (assert (equal major-mode 'jde-mode) nil "Must be run from jde-mode")

  (insert (format "public class %s " (jde-guess-class))))

(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)
      (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.
                (replace-string (concat current-directory "/" ) "")
                (replace-string current-directory "")
                (beginning-of-buffer)
                (replace-string ".java" "")
                (beginning-of-buffer)
                (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))))

(provide 'jde-guess)

- -- 
Kevin A. Burton ( [email-masked], [email-masked], [email-masked] )
        Cell: 408-910-6145 URL: http://relativity.yi.org ICQ: 73488596 

Given the price-conscious nature of this sector, Linux would be the odds-on
favorite, since it typically costs no more than a fifth the price of Windows
2000. 

Uzi smuggle radar Delta Force Semtex terrorist arrangements $400 million in gold
bullion assassination World Trade Center South Africa Ortega Mossad security
Legion of Doom

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple