emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] javaimp_devel 4b918c0: in progress


From: Filipp Gunbin
Subject: [elpa] javaimp_devel 4b918c0: in progress
Date: Thu, 07 Apr 2016 20:13:30 +0000

branch: javaimp_devel
commit 4b918c0bc257c6d3f608c7514051826051b0cc42
Author: Filipp Gunbin <address@hidden>
Commit: Filipp Gunbin <address@hidden>

    in progress
---
 packages/javaimp/javaimp.el |  371 ++++++++++++++++++-------------------------
 1 files changed, 152 insertions(+), 219 deletions(-)

diff --git a/packages/javaimp/javaimp.el b/packages/javaimp/javaimp.el
index fcca837..a2ab7c4 100644
--- a/packages/javaimp/javaimp.el
+++ b/packages/javaimp/javaimp.el
@@ -12,7 +12,7 @@
 ;; Allows to manage Java import statements in Maven projects.
 ;;
 ;;   Quick start: customize `javaimp-import-group-alist', `javaimp-jdk-home'
-;; and call `javaimp-maven-visit-root', then in a Java buffer visiting a
+;; and call `javaimp-maven-visit-project', then in a Java buffer visiting a
 ;; file under that module or one of its submodules call
 ;; `javaimp-organize-imports' or `javaimp-add-import'.  `javaimp-add-import'
 ;; will provide you a helpful completion, and the default value (the one
@@ -56,7 +56,7 @@
 ;;  
 ;; Details on commands.
 ;;
-;;   `javaimp-maven-visit-root' is the first command you should issue to
+;;   `javaimp-maven-visit-project' is the first command you should issue to
 ;; use this module.  It reads the pom structure recursively and records
 ;; which files belong to which module.  Maven help:effective-pom command is
 ;; used to do that.
@@ -74,7 +74,7 @@
 ;;   '("\\`\\(my\\.company\\.\\|my\\.company2\\.\\)" . 80))
 ;; 
 ;; (setq javaimp-jdk-home (getenv "JAVA_HOME"))
-;; (setq javaimp-include-current-project-classes t)
+;; (setq javaimp-include-current-module-classes t)
 ;; (setq javaimp-additional-source-dirs '("generated-sources/thrift"))
 ;; 
 ;; (add-hook 'java-mode-hook
@@ -85,10 +85,10 @@
 ;; 
 ;; TODO before version 1.0:
 ;; 
-;; - correct submodule tree for each top-level project (now top-level projects
-;; hold linear submodule list and this prevents modification checking for 
parent
-;; poms).  If a project doesn't have any children, then it should be in the 
list
-;; by itself.
+;; - correct submodule tree for each top-level project (now top-level
+;; projects hold linear submodule list and this prevents modification
+;; checking for parent poms).  Each project should represented as (NAME
+;; OBJECT . CHILDREN).
 ;; 
 ;; - cl-defstruct for data
 ;; 
@@ -102,17 +102,26 @@
 ;; calling `cygpath'.  See https://cygwin.com/ml/cygwin/2013-03/msg00228.html.
 ;;
 ;; - include <packaging> into module info
+;;
+;; - each module's parent should be set according to its "parent" node
+;; 
+;; - when a module has a parent but do not inherits, its jars are not added
+;;
+;; - save/restore state
+;;
+;; - API functions should check pom file modifications and refresh if needed
 ;; 
 
 ;;; Code:
 
+(require 'cl-macs)
 (require 'seq)
 
 
 ;;; User options
 
 (defgroup javaimp ()
-  "Add and reorder Java import statements in Maven projects.")
+  "Add and reorder Java import statements in Maven projects")
 
 (defcustom javaimp-import-group-alist '(("\\`javax?\\." . 10))
   "Specifies how to group classes and how to order resulting
@@ -130,7 +139,10 @@ The order of classes which were not matched is defined by
 `javaimp-import-group-alist'")
 
 (defcustom javaimp-jdk-home nil
-  "Path to the JDK")
+  "Path to the JDK.  If you have JAVA_HOME environment variable
+set up, this variable can be set like this:
+
+(setq javaimp-jdk-home (getenv \"JAVA_HOME\"))")
 
 (defcustom javaimp-additional-source-dirs nil
   "List of directories where additional (e.g. generated)
@@ -152,13 +164,14 @@ supported yet.")
 (defcustom javaimp-mvn-program "mvn"
   "Path to the `mvn' program")
 
-(defcustom javaimp-cygpath-program "cygpath"
+(defcustom javaimp-cygpath-program
+  (if (eq system-type 'cygwin) "cygpath")
   "Path to the `cygpath' program")
 
 (defcustom javaimp-jar-program "jar"
   "Path to the `jar' program")
 
-(defcustom javaimp-include-current-project-classes t
+(defcustom javaimp-include-current-module-classes t
   "If non-nil, current project's classes are included into completion
 alternatives.
 
@@ -167,11 +180,11 @@ Only top-level classes are included.")
 
 ;;; Variables and constants
 
-(defvar javaimp-maven-root-modules nil
-  "Loaded root Maven modules")
+(defvar javaimp-project-forest nil
+  "Visited projects")
 
-(defvar javaimp-jar-classes-cache nil
-  "Jar classes cache")
+(defvar javaimp-jar-cache nil
+  "Cache for jar contents")
 
 (defconst javaimp-debug-buf-name "*javaimp-debug*")
 
@@ -195,121 +208,60 @@ Only top-level classes are included.")
   (car (cddr el)))
 
 
-;;; Data representation
-
-;; FIXME: use cl-defstruct!
-
-;; Module
-
-(defsubst javaimp-make-mod (artifact pom-file source-dir test-source-dir 
build-dir
-                                    pom-file-mod-ts jars-list parent parent-ts 
final-name)
-  (list artifact pom-file source-dir test-source-dir build-dir
-       pom-file-mod-ts jars-list parent parent-ts final-name))
-
-(defsubst javaimp-get-mod-artifact (module)
-  (nth 0 module))
-
-(defsubst javaimp-get-mod-pom-file (module)
-  (nth 1 module))
-(defsubst javaimp-set-mod-pom-file (module value)
-  (setcar (nthcdr 1 module) value))
-
-(defsubst javaimp-get-mod-source-dir (module)
-  (nth 2 module))
-
-(defsubst javaimp-get-mod-test-source-dir (module)
-  (nth 3 module))
-
-(defsubst javaimp-get-mod-build-dir (module)
-  (nth 4 module))
-
-(defsubst javaimp-get-mod-pom-mod-ts (module)
-  (nth 5 module))
-(defsubst javaimp-set-mod-pom-mod-ts (module value)
-  (setcar (nthcdr 5 module) value))
-
-(defsubst javaimp-get-mod-pom-deps (module)
-  (nth 6 module))
-(defsubst javaimp-set-mod-pom-deps (module value)
-  (setcar (nthcdr 6 module) value))
-
-(defsubst javaimp-get-mod-parent (module)
-  (nth 7 module))
-(defsubst javaimp-set-mod-parent (module value)
-  (setcar (nthcdr 7 module) value))
-
-(defsubst javaimp-get-mod-parent-ts (module)
-  (nth 8 module))
-(defsubst javaimp-set-mod-parent-ts (module value)
-  (setcar (nthcdr 8 module) value))
-
-(defsubst javaimp-get-mod-final-name (module)
-  (nth 9 module))
-(defsubst javaimp-set-mod-final-name (module value)
-  (setcar (nthcdr 9 module) value))
+;; Structs
 
-;; Artifact
+(cl-defstruct javaimp-node
+  parent children contents)
 
-(defsubst javaimp-make-artifact (group-id artifact-id version)
-  (list group-id artifact-id version))
+(cl-defstruct javaimp-module
+  id file file-ts final-name
+  source-dir test-source-dir build-dir
+  dep-jars)
 
-(defsubst javaimp-artifact-group-id (artifact)
-  (car artifact))
-
-(defsubst javaimp-artifact-artifact-id (artifact)
-  (cadr artifact))
-
-(defsubst javaimp-artifact-version (artifact)
-  (nth 2 artifact))
-
-(defun javaimp-artifact-to-string (artifact)
+(defun javaimp-print-id (id)
   (format "%s:%s:%s"
-         (javaimp-artifact-artifact-id artifact)
-         (javaimp-artifact-group-id artifact)
-         (javaimp-artifact-version artifact))) ;FIXME: `artifact' is not a 
function!
-
-(defun javaimp-parse-artifact (artifact)
-  (apply #'javaimp-make-artifact (split-string artifact ":")))
-
-
-;; JAR
-
-(defsubst javaimp-make-jar (jar-path jar-mod-ts classes-list)
-  (cons jar-path (cons jar-mod-ts classes-list)))
-
-(defsubst javaimp-get-jar-path (jar)
-  (car jar))
-
-(defsubst javaimp-get-jar-mod-ts (jar)
-  (cadr jar))
+         (javaimp-id-artifact id)
+         (javaimp-id-group id)
+         (javaimp-id-version id)))
 
-(defsubst javaimp-set-jar-mod-ts (jar value)
-  (setcar (cdr jar) value))
+(cl-defstruct (javaimp-id
+              (:print-function #'javaimp-print-id))
+  group artifact version)
 
-(defsubst javaimp-get-jar-classes-list (jar)
-  (cddr jar))
-
-(defsubst javaimp-set-jar-classes-list (jar value)
-  (setcdr (cdr jar) value))
+(cl-defstruct javaimp-jar
+  file file-ts classes)
 
 
-;;; Loading Maven projects tree
+;;; Loading Maven projects
+
+;; TODO if it's already there?
 
 ;;;###autoload
-(defun javaimp-maven-visit-root (path)
-  "Loads all modules starting from root module identified by
-PATH.  PATH should point to a directory containing pom.xml."
-  (interactive "DVisit maven root project: ")
-  (let* ((root-pom (expand-file-name
-                   (concat (file-name-as-directory path) "pom.xml")))
-        (modules (if (file-readable-p root-pom)
-                     (javaimp-maven-load-module-tree root-pom)
-                   (error "Cannot read root pom: %s" root-pom)))
-        (root-project (assoc root-pom javaimp-maven-root-modules)))
-    (if root-project
-       (setcdr root-project modules)
-      (push (cons root-pom modules) javaimp-maven-root-modules))
-    (message "Loaded modules for %s" path)))
+(defun javaimp-maven-visit-project (path)
+  "Loads a project and its submodules.  PATH should point to a
+directory containing pom.xml."
+  (interactive "DVisit maven project: ")
+  (let ((file (expand-file-name
+              (concat (file-name-as-directory path) "pom.xml"))))
+    (unless (file-readable-p file)
+      (error "Cannot read file: %s" file))
+    (push (javaimp-maven-load-tree file) javaimp-project-forest)
+    (message "Loaded tree for %s" file)))
+
+(defun javaimp-maven-load-tree (file)
+  ;; TODO 
+  "Creates a tree of Maven projects starting from FILE"
+  (let* ((effective-pom (javaimp-parse-effective-pom pom))
+        (project-elts
+         (cond ((assq 'projects effective-pom) ;project contains <module> 
tag(s)
+                (javaimp-xml-child-list (assq 'projects effective-pom) 
'project))
+               ((assq 'project effective-pom) ;single-module project
+                (list (assq 'project effective-pom)))
+               (t
+                (error "Cannot find projects in XML tree"))))
+        (modules-alist (javaimp-maven-process-projects project-elts)))
+    (javaimp-fill-pom-file-paths modules-alist pom)
+    modules-alist))
 
 (defun javaimp-parse-effective-pom (pom)
   "Calls `mvn help:effective:pom and returns XML parse tree"
@@ -333,26 +285,13 @@ PATH.  PATH should point to a directory containing 
pom.xml."
                (match-end 0)))))
        (xml-parse-region xml-start-pos xml-end-pos)))))
 
-(defun javaimp-maven-load-module-tree (pom)
-  "Returns an alist of all Maven modules in a hierarchy starting
-with POM"
-  (let* ((effective-pom (javaimp-parse-effective-pom pom))
-        (project-elts
-         (cond ((assq 'projects effective-pom) ;project contains <module> 
tag(s)
-                (javaimp-xml-child-list (assq 'projects effective-pom) 
'project))
-               ((assq 'project effective-pom) ;single-module project
-                (list (assq 'project effective-pom)))
-               (t
-                (error "Cannot find projects in XML tree"))))
-        (modules-alist (javaimp-maven-process-projects project-elts)))
-    (javaimp-fill-pom-file-paths modules-alist pom)
-    modules-alist))
+
 
 (defun javaimp-fill-pom-file-paths (modules pom)
   "Subroutine of `javaimp-maven-load-module-tree'"
   (let ((artifact-alist (javaimp-traverse-pom-tree (list pom))))
     (dolist (module modules)
-      (let* ((artifact (javaimp-get-mod-artifact module))
+      (let* ((artifact (javaimp-mod-artifact module))
             (path
              (cdr (or (seq-find (lambda (el)
                                   (equal artifact (car el)))
@@ -376,6 +315,8 @@ with POM"
       (car (process-lines javaimp-cygpath-program "-u" path))
     path))
 
+;; todo set everything immediately
+
 (defun javaimp-maven-process-projects (projects-elts)
   (mapcar
    (lambda (project-elt)
@@ -462,22 +403,18 @@ platform default format."
 the temporary buffer and returns its result"
   (message "Calling \"mvn %s\" on pom: %s" target pom-file)
   (with-temp-buffer
-    (let* ((pom-file (if (eq system-type 'cygwin) 
-                        (car (process-lines javaimp-cygpath-program 
-                                            "-m" pom-file))
-                      pom-file))
+    (let* ((pom-file (javaimp-cygpath-convert-maybe pom-file))
           (status
-           ;; FIXME on GNU/Linux Maven strangely outputs ^M chars. Check
-           ;; also jar output with the same var binding below.
-           (let ((coding-system-for-read (when (eq system-type 'cygwin) 
'utf-8-dos)))
+           ;; FIXME check Maven output on Gnu/Linux
+           (let ((coding-system-for-read
+                  (if (eq system-type 'cygwin) 'utf-8-dos)))
              (process-file javaimp-mvn-program nil t nil "-f" pom-file 
target)))
-          (output-buf (current-buffer)))
+          (b (current-buffer)))
       (with-current-buffer (get-buffer-create javaimp-debug-buf-name)
        (erase-buffer)
-       (insert-buffer-substring output-buf))
+       (insert-buffer-substring b))
       (or (and (numberp status) (= status 0))
-         (error "Maven target \"%s\" failed with status \"%s\""
-                target status))
+         (error "Maven target \"%s\" failed with status \"%s\"" target status))
       (goto-char (point-min))
       (funcall handler))))
 
@@ -487,7 +424,7 @@ the temporary buffer and returns its result"
 (defun javaimp-maven-fetch-module-deps (module)
   "Returns list of dependency jars for MODULE"
   (javaimp-call-mvn
-   (javaimp-get-mod-pom-file module) "dependency:build-classpath"
+   (javaimp-mod-pom-file module) "dependency:build-classpath"
    (lambda ()
      (let (deps-line)
        (goto-char (point-min))
@@ -512,51 +449,44 @@ the temporary buffer and returns its result"
          (not (equal (float-time curr-ts) (float-time last-ts)))
          (javaimp-any-file-ts-updated (cdr files))))))
 
-(defun javaimp-get-dep-jars-cached (module parent)
+(defun javaimp-get-deps-cached (module parent)
   "Returns a list of dependency jar file paths for a MODULE.
 Both MODULE and PARENT poms are checked for updates because
 PARENT pom may have some versions which are inherited by the
 MODULE."
   (when (javaimp-any-file-ts-updated
-        (remq nil (list (cons (javaimp-get-mod-pom-file module)
-                              (javaimp-get-mod-pom-mod-ts module))
+        (remq nil (list (cons (javaimp-mod-pom-file module)
+                              (javaimp-mod-pom-mod-ts module))
                         (when parent
                           (cons
-                           (javaimp-get-mod-pom-file parent)
+                           (javaimp-mod-pom-file parent)
                            ;; here we check the saved parent ts because it
                            ;; matters what version we had when we were
                            ;; reloading this pom the last time
-                           (javaimp-get-mod-parent-ts module))))))
+                           (javaimp-mod-parent-ts module))))))
     ;; (re-)fetch dependencies
     (javaimp-set-mod-pom-deps
      module (javaimp-maven-fetch-module-deps module))
     ;; update timestamps
     (javaimp-set-mod-pom-mod-ts
-     module (javaimp-get-file-ts (javaimp-get-mod-pom-file module)))
+     module (javaimp-get-file-ts (javaimp-mod-pom-file module)))
     (when parent
       (javaimp-set-mod-parent-ts
-       module (javaimp-get-file-ts (javaimp-get-mod-pom-file parent)))))
-  (javaimp-get-mod-pom-deps module))
+       module (javaimp-get-file-ts (javaimp-mod-pom-file parent)))))
+  (javaimp-mod-pom-deps module))
 
 (defun javaimp-get-jdk-jars ()
-  "Returns list of jars from the jre/lib subdirectory of the JDK
-directory"
-  (when javaimp-jdk-home
-    (directory-files (concat (file-name-as-directory javaimp-jdk-home)
-                            (file-name-as-directory "jre/lib"))
-                    t "\\.jar$")))
+  (if javaimp-jdk-home
+      (let ((jre-lib-dir
+            (concat (file-name-as-directory javaimp-jdk-home)
+                    (file-name-as-directory "jre")
+                    (file-name-as-directory "lib"))))
+      (directory-files jre-lib-dir t "\\.jar\\'"))))
 
-(defun javaimp-get-jar-classes-cached (jar)
-  (let ((current-jar-mod-ts
-        (nth 5 (file-attributes (javaimp-get-jar-path jar)))))
-    (unless (equal (float-time (javaimp-get-jar-mod-ts jar))
-                  (float-time current-jar-mod-ts))
-      (javaimp-set-jar-classes-list jar (javaimp-fetch-jar-classes jar))
-      (javaimp-set-jar-mod-ts jar current-jar-mod-ts))
-    (javaimp-get-jar-classes-list jar)))
+;; Working with jar and its cache
 
 (defun javaimp-fetch-jar-classes (jar)
-  (let ((jar-file (javaimp-get-jar-path jar))
+  (let ((jar-file (javaimp-jar-path jar))
        result)
     (message "Reading classes in jar: %s" jar-file)
     (with-temp-buffer
@@ -572,42 +502,41 @@ directory"
              result))
       result)))
 
-(defun javaimp-collect-jar-classes (jar-paths)
+(defun javaimp-get-jar-classes-cached (jar)
+  (let ((current-jar-mod-ts
+        (nth 5 (file-attributes (javaimp-jar-path jar)))))
+    (unless (equal (float-time (javaimp-jar-mod-ts jar))
+                  (float-time current-jar-mod-ts))
+      (javaimp-set-jar-classes-list jar (javaimp-fetch-jar-classes jar))
+      (javaimp-set-jar-mod-ts jar current-jar-mod-ts))
+    (javaimp-jar-classes-list jar)))
+
+(defun javaimp-collect-classes (jar-paths)
   (let (result jar)
     (dolist (jar-path jar-paths result)
-      (setq jar (assoc jar-path javaimp-jar-classes-cache))
+      (setq jar (assoc jar-path javaimp-jar-cache))
       (unless jar
        (setq jar (javaimp-make-jar jar-path nil nil))
-       (push jar javaimp-jar-classes-cache))
+       (push jar javaimp-jar-cache))
       (setq result (append (javaimp-get-jar-classes-cached jar) result)))))
 
-(defun javaimp-get-module-from-root (roots predicate)
-  (if (null roots)
-      nil
-    (let ((result (javaimp-get-module (cdr (car roots)) predicate)))
-      (or result
-         (javaimp-get-module-from-root (cdr roots) predicate)))))
-
-(defun javaimp-get-module (modules predicate)
-  (cond ((null modules)
-        nil)
-       ((funcall predicate (car modules))
-        (car modules))
-       (t
-        (javaimp-get-module (cdr modules) predicate))))
-
-(defun javaimp-get-module-by-file (file)
-  (javaimp-get-module-from-root
-   javaimp-maven-root-modules
-   (lambda (mod)
-     (or (string-prefix-p (javaimp-get-mod-source-dir mod) file)
-        (string-prefix-p (javaimp-get-mod-test-source-dir mod) file)))))
-
-(defun javaimp-get-module-by-artifact (artifact)
-  (javaimp-get-module-from-root
-   javaimp-maven-root-modules
-   (lambda (mod)
-     (equal (javaimp-get-mod-artifact mod) artifact))))
+;; Searching and navigating through projects
+
+(defun javaimp-find-module (predicate)
+  (javaimp--find-module javaimp-project-forest predicate))
+
+(defun javaimp--find-module (projects predicate)
+  (if projects
+      (let ((project (car projects)))
+       (or (javaimp--get-module (cdr project) predicate)
+           (javaimp--find-module (cdr projects) predicate)))))
+
+(defun javaimp--get-module (modules predicate)
+  (if modules
+      (let ((module (car modules)))
+       (if (funcall predicate module)
+           module
+         (javaimp--get-module (cdr modules) predicate)))))
 
 
 ;;; Some functions for use in other programs
@@ -615,17 +544,20 @@ directory"
 (defun javaimp-get-source-directories ()
   (append
    (mapcar (lambda (root)
-            (mapcar #'javaimp-get-mod-source-dir (cdr root)))
-          javaimp-maven-root-modules)))
+            (mapcar #'javaimp-mod-source-dir (cdr root)))
+          javaimp-project-forest)))
 
 (defun javaimp-get-all-modules ()
   "Returns flat list of all child modules."
   (apply #'seq-concatenate 'list
-        (mapcar #'cdr javaimp-maven-root-modules)))
+        (mapcar #'cdr javaimp-project-forest)))
 
 
 ;;; Adding and organizing imports
 
+;; TODO without prefix arg narrow alternatives by local name; with prefix
+;; arg - include all classes in alternatives
+
 ;;;###autoload
 (defun javaimp-add-import (classname)
   "Imports CLASSNAME in the current file.  Interactively,
@@ -636,27 +568,28 @@ module."
    (let* ((file (expand-file-name
                 (or buffer-file-name
                     (error "Buffer is not visiting a file!"))))
-         (module (or (javaimp-get-module-by-file file)
-                     (error "Cannot determine module for file: %s" file)))
-         (parent (javaimp-get-module-by-artifact
-                  (javaimp-get-mod-parent module))))
+         (module (or (javaimp-find-module
+                      (lambda (m)
+                        (or (string-prefix-p (javaimp-mod-source-dir m) file)
+                            (string-prefix-p (javaimp-mod-test-source-dir m) 
file))))
+                     (error "Cannot find module by file: %s" file))))
      (list (completing-read
            "Import: "
            (append
-            (javaimp-collect-jar-classes
-             (append (javaimp-get-dep-jars-cached module parent)
-                     (javaimp-get-jdk-jars)))
-            (and javaimp-include-current-project-classes
-                 (javaimp-get-module-classes module)))
+            (let ((jars (append (javaimp-get-deps-cached module)
+                                (javaimp-get-jdk-jars))))
+              (javaimp-collect-classes jars))
+            (and javaimp-include-current-module-classes
+                 (javaimp-classes-from-source module)))
            nil t nil nil (symbol-name (symbol-at-point))))))
   (javaimp-organize-imports classname))
 
-(defun javaimp-get-module-classes (module)
+(defun javaimp-classes-from-source (module)
   "Scans current project and returns a list of top-level classes in both the
 source directory and test source directory"
-  (let ((src-dir (javaimp-get-mod-source-dir module))
-       (test-src-dir (javaimp-get-mod-test-source-dir module))
-       (build-dir (javaimp-get-mod-build-dir module)))
+  (let ((src-dir (javaimp-mod-source-dir module))
+       (test-src-dir (javaimp-mod-test-source-dir module))
+       (build-dir (javaimp-mod-build-dir module)))
     (append
      (and javaimp-additional-source-dirs
          (seq-mapcat
@@ -774,12 +707,12 @@ argument is a list of additional classes to import."
 (defun javaimp-invalidate-jar-classes-cache ()
   "Resets jar classes cache (debugging only)"
   (interactive)
-  (setq javaimp-jar-classes-cache nil))
+  (setq javaimp-jar-cache nil))
 
 (defun javaimp-forget-all-visited-modules ()
-  "Resets `javaimp-maven-root-modules' (debugging only)"
+  "Resets `javaimp-project-forest' (debugging only)"
   (interactive)
-  (setq javaimp-maven-root-modules nil))
+  (setq javaimp-project-forest nil))
 
 (defun javaimp-reset ()
   "Resets all data (debugging only)"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]