[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/javaimp 9b49ee1: Include inner classes in completion ca
From: |
Filipp Gunbin |
Subject: |
[elpa] externals/javaimp 9b49ee1: Include inner classes in completion candidates |
Date: |
Thu, 27 May 2021 16:05:00 -0400 (EDT) |
branch: externals/javaimp
commit 9b49ee123c652a5ef5630badbcc8ae91b240c457
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>
Include inner classes in completion candidates
---
javaimp-tests.el | 22 +++++++++-
javaimp-util.el | 52 +++++++++++++++++++++++
javaimp.el | 78 +++++++++++++++++------------------
testdata/test-get-file-classes-1.java | 60 +++++++++++++++++++++++++++
4 files changed, 170 insertions(+), 42 deletions(-)
diff --git a/javaimp-tests.el b/javaimp-tests.el
index f382302..36b4686 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -6,7 +6,7 @@
;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
(require 'ert)
-(require 'javaimp-maven)
+(require 'javaimp)
(ert-deftest javaimp-test--maven-projects-from-xml--project ()
(with-temp-buffer
@@ -21,3 +21,23 @@
(let ((projects (javaimp--maven-projects-from-xml
(xml-parse-region (point-min) (point-max)))))
(should (eql (length projects) 2)))))
+
+
+(ert-deftest javaimp-test--get-package ()
+ (with-temp-buffer
+ (insert "//package org.commented1;
+/*package org.commented2;*/
+ package org.foo;")
+ (should (equal (javaimp--get-package) "org.foo"))))
+
+(ert-deftest javaimp-test--get-file-classes ()
+ (should (equal (javaimp--get-file-classes
+ (concat javaimp--basedir
"testdata/test-get-file-classes-1.java"))
+ '("org.foo.Top"
+ "org.foo.Top.CInner1"
+ "org.foo.Top.CInner1.CInner1_CInner1"
+ "org.foo.Top.IInner1"
+ "org.foo.Top.IInner1.IInner1_IInner1"
+ "org.foo.Top.IInner1.IInner1_CInner1"
+ "org.foo.Top.EInner1"
+ "org.foo.Top.EInner1.EInner1_EInner1"))))
diff --git a/javaimp-util.el b/javaimp-util.el
index 9304fce..f2f4c00 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -157,4 +157,56 @@ buffer and returns its result"
(setf (javaimp-node-children this-node) child-nodes)
this-node)))
+
+;; Java source parsing
+
+(defun javaimp--get-package ()
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (catch 'found
+ (while (re-search-forward "^\\s *package\\s +\\([^;]+\\)\\s *;" nil t)
+ (let ((state (syntax-ppss)))
+ (unless (syntax-ppss-context state)
+ (throw 'found (match-string 1)))))))))
+
+(defun javaimp--get-file-classes (file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (let ((parse-sexp-ignore-comments t)
+ (class-re (concat
+ (regexp-opt '("class" "interface" "enum") 'words)
+ (rx (and (+ (syntax whitespace))
+ (group (+ (any alnum ?_)))))))
+ res)
+ (while (re-search-forward class-re nil t)
+ (let ((state (syntax-ppss))
+ curr)
+ (unless (syntax-ppss-context state)
+ (setq curr (list (match-string 2)))
+ ;; collect enclosing classes, if any
+ (save-excursion
+ (catch 'stop
+ (while (nth 1 state)
+ ;; find innermost enclosing open-bracket
+ (goto-char (nth 1 state))
+ (if (and (= (char-after) ?{)
+ (re-search-backward class-re nil t)
+ ;; if there's no paren in between - assume
+ ;; it's a valid class (not a method - this
+ ;; way we exclude local classes)
+ (not (save-match-data
+ (search-forward "(" (nth 1 state) t))))
+ (progn
+ (push (match-string 2) curr)
+ (setq state (syntax-ppss)))
+ (setq curr nil)
+ (throw 'stop nil)))))
+ (when curr
+ (let ((package (javaimp--get-package)))
+ (if package (push package curr)))
+ (push (mapconcat #'identity curr ".") res)))))
+ (nreverse res))))
+
(provide 'javaimp-util)
diff --git a/javaimp.el b/javaimp.el
index b3338c5..1ea804d 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -49,9 +49,6 @@
;; from the build tool again. If a jar file was changed, its contents
;; are re-read.
;;
-;; Currently inner classes are filtered out from completion alternatives.
-;; You can always import top-level class and use qualified name.
-;;
;;
;; Example:
;;
@@ -275,16 +272,24 @@ any module file."
;; needs to be converted appropriately.
(javaimp-cygpath-convert-maybe file 'windows)))
(goto-char (point-min))
- (save-excursion
- (while (re-search-forward "^classes/" nil t)
- (replace-match "")))
- (save-excursion
- (while (search-forward "/" nil t)
- (replace-match ".")))
- (let (result)
- (while (re-search-forward "^\\([[:alnum:]._]+\\)\\.class$" nil t)
- (push (match-string 1) result))
- result))))
+ (let (result curr)
+ (while (re-search-forward
+ (rx (and bol
+ (? "classes/") ; prefix output by jmod
+ (group (+ (any alnum "_/$")))
+ ".class"
+ eol))
+ nil t)
+ (setq curr (match-string 1))
+ (unless (or (string-suffix-p "module-info" curr)
+ (string-suffix-p "package-info" curr)
+ ;; like Provider$1.class
+ (string-match-p "\\$[[:digit:]]" curr))
+ (push
+ (string-replace "/" "."
+ (string-replace "$" "." curr))
+ result)))
+ result))))
;; Tree search routines
@@ -353,12 +358,11 @@ subdirectory - fallback to reading all jar files in
lib-dir.
sits 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.
+current module's classes. If there's no current module, then add
+all 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
@@ -426,38 +430,30 @@ prefix arg is given, don't do this filtering."
(user-error "JRE lib dir \"%s\" doesn't exist" dir))))))
(defun javaimp--get-module-classes (module)
- "Returns list of top-level classes in current module"
+ "Returns list of classes in current module"
(append
;; source dirs
- (seq-mapcat (lambda (dir)
- (and (file-accessible-directory-p dir)
- (javaimp--get-directory-classes dir)))
+ (seq-mapcat #'javaimp--get-directory-classes
(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))))
+ (javaimp--get-directory-classes
+ (concat (javaimp-module-build-dir module)
+ (file-name-as-directory rel-dir))))
javaimp-additional-source-dirs)))
(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)))))
+ (let ((package (javaimp--get-package)))
+ (when package
+ (string-remove-suffix
+ (mapconcat #'file-name-as-directory
+ (split-string package "\\." 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\\'")))
+ (if (file-accessible-directory-p dir)
+ (seq-mapcat #'javaimp--get-file-classes
+ (directory-files-recursively dir "\\.java\\'"))))
;; Organizing imports
diff --git a/testdata/test-get-file-classes-1.java
b/testdata/test-get-file-classes-1.java
new file mode 100644
index 0000000..ba36d31
--- /dev/null
+++ b/testdata/test-get-file-classes-1.java
@@ -0,0 +1,60 @@
+package org.foo;
+
+public class Top {
+ public static class CInner1<T, S> {
+ public void foo_bar() {
+ if (true) {
+ class CInner1_CLocal1 implements Serializable {
+ void foo_bar() {
+ System.out.println("");
+ if (true) {
+ class CInner1_CLocal1_CLocal1 extends Object {
+ public void foo_bar() {
+ System.out.println("");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ class CInner1_CLocal2 extends Object {
+ void foo_bar() {
+ System.out.println("");
+ }
+ }
+ }
+
+ private Object obj = new Object();
+ class CInner1_CInner1 {
+ }
+ }
+
+ interface IInner1 {
+ interface IInner1_IInner1 extends A<B, C>, Serializable {
+ void foo_bar();
+ }
+
+ static class IInner1_CInner1 {
+ public void foo_bar() {
+ if (true) {
+ System.out.println("");
+ }
+ }
+ }
+ }
+
+ enum EInner1 {
+ A("a"),
+ B("b");
+ private EInner1() {
+ }
+ public void foo_bar() {
+ System.out.println("");
+ }
+
+ enum EInner1_EInner1 {
+ C, D
+ }
+ }
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/javaimp 9b49ee1: Include inner classes in completion candidates,
Filipp Gunbin <=