[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/javaimp 8a25b39: Support Java 9+
From: |
Filipp Gunbin |
Subject: |
[elpa] externals/javaimp 8a25b39: Support Java 9+ |
Date: |
Fri, 2 Apr 2021 19:25:01 -0400 (EDT) |
branch: externals/javaimp
commit 8a25b3954ddd9904f8af46696a1fd5acbe66e438
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>
Support Java 9+
* javaimp.el (javaimp--get-jdk-classes): New function.
(javaimp--jdk-classes): New variable.
(javaimp-reset): Also reset it.
(javaimp-add-import): Improve javadoc, support basic completion on
top-level classes without Maven/Gradle. Narrow completion candidates
based on symbol-at-point.
(javaimp--get-directory-classes): Simplify using
directory-files-recursively.
(javaimp--dir-above-current-package): New function.
* javaimp-util.el (javaimp--get-jdk-jars): Remove.
* Update copyright year in all files.
---
javaimp-gradle.el | 2 +-
javaimp-maven.el | 2 +-
javaimp-tests.el | 2 +-
javaimp-util.el | 11 +---
javaimp.el | 178 ++++++++++++++++++++++++++++++++++++------------------
5 files changed, 124 insertions(+), 71 deletions(-)
diff --git a/javaimp-gradle.el b/javaimp-gradle.el
index 2241da5..4d683ab 100644
--- a/javaimp-gradle.el
+++ b/javaimp-gradle.el
@@ -1,6 +1,6 @@
;;; javaimp-gradle.el --- javaimp gradle support -*- lexical-binding: t; -*-
-;; Copyright (C) 2019 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
diff --git a/javaimp-maven.el b/javaimp-maven.el
index 524aa77..054bf11 100644
--- a/javaimp-maven.el
+++ b/javaimp-maven.el
@@ -1,6 +1,6 @@
;;; javaimp-maven.el --- javaimp maven support -*- lexical-binding: t; -*-
-;; Copyright (C) 2019 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
diff --git a/javaimp-tests.el b/javaimp-tests.el
index 0dbe86f..f382302 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -1,6 +1,6 @@
;;; javaimp-tests.el --- javaimp tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2021 Free Software Foundation, Inc.
;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
diff --git a/javaimp-util.el b/javaimp-util.el
index c03414d..303e43c 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -1,6 +1,6 @@
;;; javaimp-util.el --- javaimp util -*- lexical-binding: t; -*-
-;; Copyright (C) 2019 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2021 Free Software Foundation, Inc.
;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
@@ -83,15 +83,6 @@ the program is not on `exec-path'."
(javaimp-id-group id)
(javaimp-id-version id)))
-(defun javaimp--get-jdk-jars ()
- (and javaimp-java-home
- (file-accessible-directory-p javaimp-java-home)
- (let ((lib-dir
- (concat (file-name-as-directory javaimp-java-home)
- (file-name-as-directory "jre")
- (file-name-as-directory "lib"))))
- (directory-files lib-dir t "\\.jar\\'"))))
-
;; TODO use functions `cygwin-convert-file-name-from-windows' and
;; `cygwin-convert-file-name-to-windows' when they are available
diff --git a/javaimp.el b/javaimp.el
index cd340f4..aabb4a7 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -1,6 +1,6 @@
;;; javaimp.el --- Add and reorder Java import statements in Maven/Gradle
projects -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2019 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2021 Free Software Foundation, Inc.
;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
@@ -110,9 +110,9 @@ The order of classes which were not matched is defined by
:type 'integer)
(defcustom javaimp-java-home (getenv "JAVA_HOME")
- "Path to the JDK. Directory jre/lib underneath this path is
-searched for JDK libraries. By default, it is initialized from
-the JAVA_HOME environment variable."
+ "Path to the JDK. Should contain subdirectory
+\"jre/lib\" (pre-JDK9) or just \"lib\". By default, it is
+initialized from the JAVA_HOME environment variable."
:group 'javaimp
:type 'string)
@@ -159,6 +159,8 @@ to the completion alternatives list."
"Alist of cached jars. Each element is of the form (FILE
. CACHED-JAR).")
+(defvar javaimp--jdk-classes 'need-init)
+
;;;###autoload
@@ -212,7 +214,7 @@ any module file."
(float-time (javaimp--get-file-ts
(javaimp-module-file-orig cur)))
-1))
(float-time (javaimp-module-load-ts module)))
- (message "Reloading dependencies for %s (some build-file changed)"
+ (message "Will reload dependencies for %s (some build-file changed)"
(javaimp-module-id cur))
(setq need-update t)))
(setq tmp (javaimp-node-parent tmp))))
@@ -311,76 +313,134 @@ any module file."
;;; Adding imports
-;; TODO narrow alternatives by class local name
-
;;;###autoload
(defun javaimp-add-import (classname)
- "Imports classname in the current file. Interactively,
-asks for a class to import, adds import statement and calls
-`javaimp-organize-imports'. Import statements are not
-duplicated. Completion alternatives are constructed based on
-this module's dependencies' classes, JDK classes and top-level
-classes in the current module."
+ "Imports classname in the current file by asking for input (with
+completion) and calling `javaimp-organize-imports'.
+
+Completion alternatives are constructed as follows:
+
+- If `javaimp-java-home' is set then add JDK classes. lib-dir is
+\"jre/lib\" or \"lib\" subdirectory. First, attempt to read
+\"lib-dir/classlist\" file. If there's no such file - fallback
+to reading all jar files in lib-dir.
+
+- If current module can be determined, then add all classes from
+its dependencies.
+
+- If `javaimp-include-current-module-classes' is set, then add
+current module's top-level classes. If there's no current
+module, then add all top-level classes from the current file
+tree: if there's a \"package\" directive in the current file and
+it matches last components of the file name, then file tree
+starts in the parent directory of the package, otherwise just use
+current directory.
+
+- Keep only candidates whose class simple name (last component of
+a fully-qualified name) matches current `symbol-at-point'. If a
+prefix arg is given, don't do this filtering."
(interactive
(let* ((file (expand-file-name (or buffer-file-name
(error "Buffer is not visiting a
file!"))))
- (node (or (javaimp--find-node
- (lambda (m)
- (seq-some (lambda (dir)
- (string-prefix-p dir file))
- (javaimp-module-source-dirs m))))
- (error "Cannot find module by file: %s" file))))
- (javaimp--update-module-maybe node)
- (let ((module (javaimp-node-contents node)))
- (list (completing-read
- "Import: "
- (append
- ;; we're not caching full list of classes coming from module
- ;; dependencies because jars may change and we need to reload
- ;; them
- (let ((jars (append (javaimp-module-dep-jars module)
- (javaimp--get-jdk-jars))))
- (apply #'seq-concatenate 'list
- (mapcar #'javaimp--get-jar-classes jars)))
- (and javaimp-include-current-module-classes
- (javaimp--get-module-classes module)))
- nil t nil nil (symbol-name (symbol-at-point)))))))
- (barf-if-buffer-read-only)
+ (node (javaimp--find-node
+ (lambda (m)
+ (seq-some (lambda (dir)
+ (string-prefix-p dir file))
+ (javaimp-module-source-dirs m)))))
+ (module (when node
+ (javaimp--update-module-maybe node)
+ (javaimp-node-contents node)))
+ (classes
+ (append
+ ;; jdk
+ (progn
+ (when (eq javaimp--jdk-classes 'need-init)
+ (setq javaimp--jdk-classes (javaimp--get-jdk-classes)))
+ javaimp--jdk-classes)
+ ;; module dependencies
+ (when module
+ ;; We're not caching full list of classes coming from
+ ;; module dependencies because jars may change and we
+ ;; need to reload them
+ (apply #'append
+ (mapcar #'javaimp--get-jar-classes
+ (javaimp-module-dep-jars module))))
+ ;; current module or source tree
+ (when javaimp-include-current-module-classes
+ (if module
+ (javaimp--get-module-classes module)
+ (javaimp--get-directory-classes
+ (or (javaimp--dir-above-current-package) default-directory))))
+ ))
+ (completion-regexp-list
+ (and (not current-prefix-arg)
+ (symbol-at-point)
+ (let ((prefix (regexp-quote (symbol-name (symbol-at-point)))))
+ (list (concat "\\." prefix "[^.]*$\\|^" prefix "[^.]*$"))))))
+ (list (completing-read "Import: " classes nil t nil nil
+ (symbol-name (symbol-at-point))))))
(javaimp-organize-imports (cons classname 'ordinary)))
+(defun javaimp--get-jdk-classes ()
+ (when javaimp-java-home
+ (or (file-accessible-directory-p javaimp-java-home)
+ (user-error "Java home directory \"%s\" is not accessible"
javaimp-java-home))
+ (let ((lib-dir
+ (mapconcat #'file-name-as-directory
+ (list javaimp-java-home "jre" "lib") nil))) ;pre-java9
+ (unless (file-directory-p lib-dir)
+ (setq lib-dir
+ (mapconcat #'file-name-as-directory
+ (list javaimp-java-home "lib") nil)) ;java9 and later
+ (or (file-directory-p lib-dir)
+ (user-error "JDK lib dir \"%s\" doesn't exist" lib-dir)))
+ (if (file-exists-p (concat lib-dir "classlist"))
+ ;; If classlist exists, read it
+ (with-temp-buffer
+ (insert-file-contents (concat lib-dir "classlist"))
+ (while (search-forward "/" nil t)
+ (replace-match "."))
+ (split-string (buffer-string) "\n" t))
+ ;; Otherwise, read jars, if any. In pre-jdk9 versions, they
+ ;; used to contain actual classes.
+ (message "classlist file not found, fallback to reading jars from
\"%s\"" lib-dir)
+ (apply #'append
+ (mapcar #'javaimp--get-jar-classes
+ (directory-files lib-dir t "\\.jar\\'")))))))
+
(defun javaimp--get-module-classes (module)
"Returns list of top-level classes in current module"
(append
;; source dirs
(seq-mapcat (lambda (dir)
(and (file-accessible-directory-p dir)
- (javaimp--get-directory-classes dir nil)))
+ (javaimp--get-directory-classes dir)))
(javaimp-module-source-dirs module))
;; additional source dirs
(seq-mapcat (lambda (rel-dir)
(let ((dir (concat (javaimp-module-build-dir module)
(file-name-as-directory rel-dir))))
(and (file-accessible-directory-p dir)
- (javaimp--get-directory-classes dir nil))))
+ (javaimp--get-directory-classes dir))))
javaimp-additional-source-dirs)))
-(defun javaimp--get-directory-classes (dir prefix)
- (append
- ;; .java files in current directory
- (mapcar (lambda (file)
- (concat prefix (file-name-sans-extension (car file))))
- (seq-filter (lambda (file) (null (cadr file))) ;only files
- (directory-files-and-attributes dir nil "\\.java\\'" t)))
- ;; descend into subdirectories
- (apply #'seq-concatenate 'list
- (mapcar (lambda (subdir)
- (let ((name (car subdir)))
- (javaimp--get-directory-classes
- (concat dir (file-name-as-directory name)) (concat
prefix name "."))))
- (seq-filter (lambda (file)
- (and (eq (cadr file) t) ;only directories
- (null (member (car file) '("." "..")))))
- (directory-files-and-attributes dir nil nil
t))))))
+(defun javaimp--dir-above-current-package ()
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (when (re-search-forward "^\\s *package\\s +\\([^;]+\\)\\s *;" nil t)
+ (string-remove-suffix
+ (mapconcat #'file-name-as-directory
+ (split-string (match-string 1) "\\." t) nil)
+ default-directory)))))
+
+(defun javaimp--get-directory-classes (dir)
+ (mapcar (lambda (filename)
+ (replace-regexp-in-string
+ "[/\\]+" "."
+ (string-remove-prefix dir (file-name-sans-extension filename))))
+ (directory-files-recursively dir "\\.java\\'")))
;; Organizing imports
@@ -400,7 +460,7 @@ the beginning of buffer.
Classes within a single group are ordered in a lexicographic
order. Imports not matched by any regexp in `javaimp-import-group-alist'
are assigned a default order defined by
-`javaimp-import-default-order'.
+`javaimp-import-default-order'. Duplicate imports are squashed.
NEW-IMPORTS is a list of additional imports; each element should
be of the form (CLASS . TYPE), where CLASS is a string and TYPE
@@ -450,7 +510,7 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(defun javaimp--parse-imports ()
"Returns (FIRST LAST . IMPORTS)"
(let (first last imports)
- (while (re-search-forward
"^\\s-*import\\s-+\\(static\\s-+\\)?\\([._[:word:]]+\\)" nil t)
+ (while (re-search-forward "^\\s *import\\s +\\(static\\s
+\\)?\\([._[:word:]]+\\)" nil t)
(let ((type (if (match-string 1) 'static 'ordinary))
(class (match-string 2)))
(push (cons class type) imports))
@@ -462,7 +522,7 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(cond (start
;; if there were any imports, we start inserting at the same place
(goto-char start))
- ((re-search-forward "^\\s-*package\\s-" nil t)
+ ((re-search-forward "^\\s *package\\s " nil t)
;; if there's a package directive, insert one blank line below and
;; leave point after it
(end-of-line)
@@ -498,11 +558,13 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(insert (format pattern (caar import)) ?\n)
(setq last-order order)))))
+
(defun javaimp-reset (arg)
"Forget loaded trees state. With prefix arg, also reset jars
cache."
(interactive "P")
- (setq javaimp-project-forest nil)
+ (setq javaimp-project-forest nil
+ javaimp--jdk-classes 'need-init)
(when arg
(setq javaimp-cached-jars nil)))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/javaimp 8a25b39: Support Java 9+,
Filipp Gunbin <=