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

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

[elpa] javaimp_devel 2f8450a 1/2: in progress


From: Filipp Gunbin
Subject: [elpa] javaimp_devel 2f8450a 1/2: in progress
Date: Fri, 08 Apr 2016 19:23:01 +0000

branch: javaimp_devel
commit 2f8450a2b4cdf0297b11a929aeeb90753506d7d9
Author: Filipp Gunbin <address@hidden>
Commit: Filipp Gunbin <address@hidden>

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

diff --git a/packages/javaimp/javaimp.el b/packages/javaimp/javaimp.el
index 6a50e76..3bf11e3 100644
--- a/packages/javaimp/javaimp.el
+++ b/packages/javaimp/javaimp.el
@@ -11,26 +11,45 @@
 
 ;; Allows to manage Java import statements in Maven projects.
 ;;
-;;   Quick start: customize `javaimp-import-group-alist', `javaimp-jdk-home'
-;; 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
-;; you'll get if you hit `M-n' in the minibuffer) is the symbol under point,
-;; so usually it's enough to hit `M-n', then add some starting letters of a
-;; package and hit `TAB'.  The module does not add all needed imports
-;; automatically!  It only helps you to quickly add imports when stepping
-;; through compilation errors.
+;;   Quick start:
+;;
+;; - customize `javaimp-import-group-alist'
+;;
+;; - call `javaimp-maven-visit-project', giving it the top-level project
+;; directory where pom.xml resides
+;;
+;; Then in a Java buffer visiting a file under that project or one of its
+;; submodules call `javaimp-organize-imports' or `javaimp-add-import'.
+;;
+;;
+;;   Details:
+;; 
+;; `javaimp-add-import' will provide you a helpful completion with the list
+;; of classes taken from this module's dependencies.  Completion default
+;; value (the one you'll get if you hit `M-n' in the minibuffer) is the
+;; symbol under point, so usually it's enough to hit `M-n', then add some
+;; starting letters of a package and hit `TAB'.
+;;
+;; This module does not add all needed imports automatically!  It only helps
+;; you to quickly add imports when stepping through compilation errors.
 ;;
 ;; If Maven failed, you can see its output in the buffer named by
 ;; `javaimp-debug-buf-name' (default is "*javaimp-debug*").
 ;;
 ;; Contents of jar files and Maven project structures (pom.xml) are cached,
 ;; so usually only first command should take a considerable amount of time
-;; to complete.  When it is detected that a particular jar or pom.xml file's
-;; timestamp changed, it is re-read and cache is updated.
+;; to complete.  If a modules's pom.xml or any of its parents pom.xml was
+;; changed (modification timestamp is checked), `mvn
+;; dependency:build-classpath' is re-run on the current module.  If a jar
+;; file was changed, its contents is reloaded.
+;;
+;; If you make some changes which change project hierarchy, you should
+;; re-visit the parent again with `javaimp-maven-visit-project'.
+;;
+;; May work unreliable with inner classes, but you can always import
+;; top-level class and use qualified name.
 ;;
-;; Details on variables.
+;; User options:
 ;; 
 ;;   `javaimp-import-group-alist' defines the order of import statement
 ;; groups.  By default java.* and javax.* imports are assigned an order of
@@ -38,33 +57,40 @@
 ;; project's imports typically should come after, so the sample config below
 ;; sets 80 for them.
 ;; 
-;;  `javaimp-jdk-home' is a path for JDK.  It is used to scan JDK jars.
-;; Usually you will need to set this.
+;;  `javaimp-jdk-home' is a path for JDK.  It is used to scan JDK jars.  By
+;;  default, it is set from the JAVA_HOME environment variable.
 ;;
 ;;  `javaimp-additional-source-dirs' is a list specifying directories where
 ;; additional (e.g. generated) source files reside.  Each directory is a
 ;; relative path from ${project.build.directory} project property value.
 ;; 
-;;  `javaimp-mvn-program' defines path of the `mvn' program.  Use if it's
-;; not on `exec-path'.
+;;  `javaimp-mvn-program' defines path to the `mvn' program.  Customize it
+;; if `mvn' is not on `exec-path'.
 ;;
-;;  `javaimp-cygpath-program' defines path of the `cygpath' program (applies
-;; to Cygwin only, of course).  Use if it's not on `exec-path'.
+;;  `javaimp-cygpath-program' defines path to the `cygpath' program (Cygwin
+;; only).  Customize it if `cygpath' is not on `exec-path'
 ;;
-;;  `javaimp-jar-program' defines path of the `jar' program.  Use if it's
-;; not on `exec-path'.
+;;  `javaimp-jar-program' defines path to the `jar' program.  Customize it
+;;  if `jar' is not on `exec-path'.
 ;;  
-;; Details on commands.
+;; Commands:
 ;;
-;;   `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.
+;;   `javaimp-maven-visit-project' asks for the project directory, calls
+;; `mvn help:effective-pom' on the pom.xml in that directory, reads project
+;; structure from the output and records which files belong to which
+;; (sub)modules and other information about the modules.  Then the project
+;; becomes known to javaimp and `javaimp-add-import' may be called inside
+;; project's files.
 ;;
-;;   `javaimp-organize-imports' groups import statement and writes those
-;; group according to the value of `javaimp-import-group-alist'.  Imports
+;;   `javaimp-add-import' asks for a class to import, adds import statement
+;; for the selected class and calls `javaimp-organize-imports'.  It provides
+;; completion alternatives made from all this module dependencies' classes.
+;; 
+;;   `javaimp-organize-imports' rearranges import statements so that they
+;; are listed in groups according to the value of
+;; `javaimp-import-group-alist', with blank lines between groups.  Imports
 ;; which are not matched by any regexp in that variable are assigned a
-;; default order defined by `javaimp-import-default-order' (50 by default).
+;; default order defined by `javaimp-import-default-order'.
 ;;
 ;; Sample .emacs initialization:
 ;; 
@@ -73,8 +99,6 @@
 ;; (add-to-list 'javaimp-import-group-alist
 ;;   '("\\`\\(my\\.company\\.\\|my\\.company2\\.\\)" . 80))
 ;; 
-;; (setq javaimp-jdk-home (getenv "JAVA_HOME"))
-;; (setq javaimp-include-current-module-classes t)
 ;; (setq javaimp-additional-source-dirs '("generated-sources/thrift"))
 ;; 
 ;; (add-hook 'java-mode-hook
@@ -118,7 +142,7 @@
 (require 'seq)
 
 
-;;; User options
+;; User options
 
 (defgroup javaimp ()
   "Add and reorder Java import statements in Maven projects")
@@ -138,11 +162,9 @@ The order of classes which were not matched is defined by
   "Defines the order of classes which were not matched by
 `javaimp-import-group-alist'")
 
-(defcustom javaimp-jdk-home nil
-  "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-jdk-home (getenv "JAVA_HOME")
+  "Path to the JDK.  By default, it is set from the JAVA_HOME
+environment variable."
 
 (defcustom javaimp-additional-source-dirs nil
   "List of directories where additional (e.g. generated)
@@ -172,13 +194,13 @@ supported yet.")
   "Path to the `jar' program")
 
 (defcustom javaimp-include-current-module-classes t
-  "If non-nil, current project's classes are included into completion
-alternatives.
-
-Only top-level classes are included.")
+  "If non-nil, current module's classes are included into
+completion alternatives.  `javaimp-add-import' will find all java
+files in the current project and add their fully-qualified names
+to the completion alternatives list.")
 
 
-;;; Variables and constants
+;; Variables and constants
 
 (defvar javaimp-project-forest nil
   "Visited projects")
@@ -188,8 +210,31 @@ Only top-level classes are included.")
 
 (defconst javaimp-debug-buf-name "*javaimp-debug*")
 
+;; Structs
+
+(cl-defstruct javaimp-node
+  parent children contents)
+
+(cl-defstruct javaimp-module
+  id parent-id file file-ts final-name packaging
+  source-dir test-source-dir build-dir
+  modules
+  dep-jars)
+
+(defun javaimp-print-id (id)
+  (format "%s:%s:%s"
+         (javaimp-id-artifact id)
+         (javaimp-id-group id)
+         (javaimp-id-version id)))
+
+(cl-defstruct (javaimp-id
+              (:print-function #'javaimp-print-id))
+  group artifact version)
+
+(cl-defstruct javaimp-jar
+  file file-ts classes)
+
 
-;;; XML routines
 
 (defun javaimp-xml-child-list (xml-tree child-name)
   "Returns list of children of XML-TREE filtered by CHILD-NAME"
@@ -207,8 +252,6 @@ Only top-level classes are included.")
   "Returns a first child of EL"
   (car (cddr el)))
 
-
-;; Cygwin
 
 (defun javaimp-cygpath-convert-maybe (path)
   (if (eq system-type 'cygwin) 
@@ -216,31 +259,7 @@ Only top-level classes are included.")
     path))
 
 
-;; Structs
-
-(cl-defstruct javaimp-node
-  parent children contents)
-
-(cl-defstruct javaimp-module
-  id parent-id file file-ts final-name packaging
-  source-dir test-source-dir build-dir
-  dep-jars)
-
-(defun javaimp-print-id (id)
-  (format "%s:%s:%s"
-         (javaimp-id-artifact id)
-         (javaimp-id-group id)
-         (javaimp-id-version id)))
-
-(cl-defstruct (javaimp-id
-              (:print-function #'javaimp-print-id))
-  group artifact version)
-
-(cl-defstruct javaimp-jar
-  file file-ts classes)
-
-
-;;; Maven
+;; Project loading
 
 ;; TODO what if it's already there?
 
@@ -253,39 +272,45 @@ directory containing pom.xml."
               (concat (file-name-as-directory path) "pom.xml"))))
     (unless (file-readable-p file)
       (error "Cannot read file: %s" file))
-    (let ((tree (javaimp--maven-load-tree file)))
+    (let ((tree (javaimp--maven-xml-load-tree file)))
       (if tree
          (push tree javaimp-project-forest)))
     (message "Loaded tree for %s" file)))
 
-(defun javaimp--maven-load-tree (file)
+;; TODO file should start to sink down from there; at each step append 
directory
+;; from <module> to it
+
+(defun javaimp--maven-xml-load-tree (file)
   "Invokes `mvn help:effective-pom' on FILE and using its output
 creates a tree of Maven projects starting from FILE.  Children
 which link to the parent via the <parent> element are inheriting
 children and are also included.  Subordinate modules with no
 inheritance are not included."
-  (let ((xml-tree (javaimp--maven-read-effective-pom file)))
+  (let ((xml-tree (javaimp--maven-xml-read-effective-pom file)))
     (cond ((assq 'project xml-tree)
           ;; no real children
-          (let ((project-elt (assq 'project xml-tree)))
-            (message "Independent submodules: %s"
-                     (mapconcat #'javaimp-xml-first-child
-                                (javaimp--maven-get-module-elts project-elt)
-                                ", "))
-            (let ((module (javaimp--maven-parse-module project-elt)))
-              (javaimp--build-tree (javaimp-module-id module) nil (list 
module)))))
+          (let ((project-elt (assq 'project xml-tree))
+                (submodules (javaimp-xml-child-list
+                          (javaimp-xml-child 'modules project-elt) 'module)))
+            (and submodules
+                 (message "Independent submodules: %s"
+                          (mapconcat #'javaimp-xml-first-child submodules ", 
")))
+            (let ((module (javaimp--maven-xml-parse-module project-elt)))
+              (javaimp--maven-build-tree
+               (javaimp-module-id module) nil (list module) file))))
          ((assq 'projects xml-tree)
           ;; we have are inheriting children - they and their children, if
           ;; any, are listed in a linear list
           (let* ((project-elts (javaimp-xml-child-list
                                 (assq 'projects xml-tree) 'project))
-                 (all-modules (mapcar #'javaimp--maven-parse-module 
project-elts)))
-            (javaimp--build-tree (javaimp-module-id (car all-modules)) nil 
all-modules)))
+                 (all-modules (mapcar #'javaimp--maven-xml-parse-module 
project-elts)))
+            (javaimp--maven-build-tree
+             (javaimp-module-id (car all-modules)) nil all-modules file)))
          (t
           ;; neither <project> nor <projects> - error
           (error "Invalid `help:effective-pom' output")))))
 
-(defun javaimp--maven-read-effective-pom (pom)
+(defun javaimp--maven-xml-read-effective-pom (pom)
   "Calls `mvn help:effective:pom and returns XML parse tree"
   (message "Loading root pom %s..." pom)
   (javaimp--maven-call
@@ -314,7 +339,7 @@ the temporary buffer and returns its result"
   (with-temp-buffer
     (let* ((pom-file (javaimp-cygpath-convert-maybe pom-file))
           (status
-           ;; FIXME check Maven output on Gnu/Linux
+           ;; TODO check 
 in 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)))
@@ -327,12 +352,10 @@ the temporary buffer and returns its result"
       (goto-char (point-min))
       (funcall handler))))
 
-(defun javaimp--maven-get-module-elts (project-elt)
-  (javaimp-xml-child-list
-   (javaimp-xml-child 'modules project-elt) 'module))
 
-(defun javaimp--maven-parse-module (elt)
-  ;; TODO file - instead of javaimp-fill-pom-file-paths
+(defun javaimp--maven-xml-parse-module (elt)
+  ;; we set `file' slot later because raw <project> element does not contain
+  ;; pom file path, so we need to construct it during tree construction
   ;; 
   ;; TODO javaimp-maven-process-projects
   ;; 
@@ -366,32 +389,62 @@ the temporary buffer and returns its result"
    projects-elts))
 
 (defun javaimp--maven-extract-id (elt)
-  (javaimp-make-artifact
+  (make-javaimp-id
    (javaimp-xml-first-child (javaimp-xml-child 'groupId elt))
    (javaimp-xml-first-child (javaimp-xml-child 'artifactId elt))
    (javaimp-xml-first-child (javaimp-xml-child 'version elt))))
 
-;; Module tree
-
-(defun javaimp--build-tree (id parent-node all-modules)
+(defun javaimp--maven-build-tree (id parent-node all-modules file)
   (let ((this (or (javaimp--find-by-id id all-modules)
                  (error "Cannot find module %s!" id)))
-       ;; although each real parent has <modules> section, better way to
-       ;; build hirarchy is to analyze <parent> node in each child
+       ;; although each real parent has <modules> section, more reliable
+       ;; way to build hirarchy is to analyze <parent> node in each child
        (children (javaimp--find-by-parent-id id all-modules)))
     (if (and (null children)
-            (string= (javaimp-module-packaging module) "pom")) ;TODO remove 
mvn specifics
+            (string= (javaimp-module-packaging module) "pom"))
        ;; this module is a pure aggregate module - it has neither real
        ;; children nor source files, so skip it
        nil
-      ;; otherwise, make node
+      ;; here we can finally set the `file' slot as the path is known at
+      ;; this time
+      (setf (javaimp-module-file this) file)
+      ;; make node
       (let ((this-node (make-javaimp-node parent-node nil this)))
        (setf (javaimp-node-children this-node)
              (mapcar (lambda (child)
-                       (javaimp--build-tree (javaimp-module-id child) 
this-node all-modules))
+                       (let ((child-file
+                              (javaimp--maven-get-submodule-file
+                               child file (javaimp-module-modules this))))
+                         (javaimp--maven-build-tree
+                          (javaimp-module-id child) this-node all-modules 
child-file)))
                      children))
        this-node))))
-  
+
+(defun javaimp--maven-get-submodule-file (module parent-file parent-rel-paths)
+  ;; seems that the only reliable way to match a module parsed from
+  ;; <project> element with module relative path taken from <modules> is to
+  ;; visit pom and check that id and parent-id matche
+  (let* ((parent-dir (file-name-directory parent-file))
+        (files (mapcar (lambda (rel-path)
+                         (concat parent-dir
+                                 (file-name-as-directory rel-path)
+                                 "pom.xml"))
+                       parent-rel-paths)))
+    (or (seq-find
+        (lambda (file)
+          (let* ((xml-tree (with-temp-buffer
+                             (insert-file-contents file)
+                             (xml-parse-region (point-min) (point-max))))
+                 (project-elt (assq 'project xml-tree))
+                 (id (javaimp--maven-extract-id project-elt))
+                 (parent-id (javaimp--maven-extract-id (assq 'parent 
project-elt))))
+            ;; TODO we need lax matching because some id
+            ;; components may be missing
+            (and (equal (javaimp-module-id module) id)
+                 (equal (javaimp-module-parent-id module) parent-id)))))
+        files)
+       (error "Cannot find file for module: %s" (javaimp-module-id module))))
+
 (defun javaimp--find-by-id (id modules)
   ;; TODO seq-find
   )
@@ -401,80 +454,6 @@ the temporary buffer and returns its result"
   )
 
 
-;; pom file parsing - this will not be needed?
-
-(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-mod-artifact module))
-            (path
-             (cdr (or (seq-find (lambda (el)
-                                  (equal artifact (car el)))
-                                artifact-alist)
-                      ;; Compare just id if comparison by all fields failed
-                      (seq-find (lambda (el)
-                                  (equal (javaimp-artifact-artifact-id 
artifact)
-                                         (javaimp-artifact-artifact-id (car 
el))))
-                                artifact-alist)
-                      (error "Cannot find path for artifact: %s" artifact)))))
-       (javaimp-set-mod-pom-file module path)))))
-
-
-(defun javaimp-parse-pom-file (pom-file)
-  "Subroutine of `javaimp-traverse-pom-tree'.  Parses POM-FILE.
-Car of result is artifact info.  Cdr of result is submodules
-relative path list."
-  (message "Parsing pom file mapping for %s" pom-file)
-  (let* ((xml-tree (with-temp-buffer
-                    (insert-file-contents pom-file)
-                    (xml-parse-region (point-min) (point-max))))
-        (project-elt (cond ((assq 'top xml-tree)
-                            (javaimp-xml-child 'project (assq 'top xml-tree)))
-                           ((assq 'project xml-tree)
-                            (assq 'project xml-tree))
-                           (t
-                            (error "Cannot find <project> element in pom %s!" 
pom-file)))))
-    (cons (javaimp--maven-extract-id project-elt)
-         (mapcar #'javaimp-xml-first-child
-                 (javaimp--maven-get-module-elts project-elt)))))
-
-(defun javaimp-traverse-pom-tree (pom-file-list)
-  "Traverses pom tree and returns alist where each element is of
-the form (\"ARTIFACT\" . \"POM-FILE-PATH\").  Result paths are in
-platform default format."
-  (if pom-file-list
-      (append
-       ;; this item
-       (let* ((this-pom (car pom-file-list))
-             (pom-file-data (javaimp-parse-pom-file this-pom)))
-        (append
-         ;; this pom itself
-         (list (cons (car pom-file-data) this-pom))
-         ;; children of this pom
-         (javaimp-traverse-pom-tree
-          (javaimp-create-absolute-submodules-paths
-           this-pom (cdr pom-file-data)))))
-       ;; rest items
-       (javaimp-traverse-pom-tree (cdr pom-file-list)))))
-
-(defun javaimp-create-absolute-submodules-paths (base-pom paths)
-  "Subroutine of `javaimp-traverse-pom-tree'"
-  (mapcar
-   (lambda (rel-path)
-     (expand-file-name
-      (concat
-       ;; base path
-       (file-name-directory base-pom)
-       ;; submodule relative path
-       (file-name-as-directory
-       (javaimp-cygpath-convert-maybe rel-path))
-       ;; well-known pom name
-       "pom.xml")))
-   paths))
-
-
-
 ;;; Working with module dependency JARs
 
 (defun javaimp-maven-fetch-module-deps (module)



reply via email to

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