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

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

[elpa] externals/javaimp 62d9fca: Add javaimp-parse.el


From: Filipp Gunbin
Subject: [elpa] externals/javaimp 62d9fca: Add javaimp-parse.el
Date: Mon, 31 May 2021 21:58:26 -0400 (EDT)

branch: externals/javaimp
commit 62d9fcaae4c667ecb6644ad8befbd94081b086a0
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>

    Add javaimp-parse.el
---
 javaimp-parse.el | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 javaimp-tests.el |   8 +--
 javaimp-util.el  |  52 --------------------
 javaimp.el       |   5 +-
 4 files changed, 152 insertions(+), 58 deletions(-)

diff --git a/javaimp-parse.el b/javaimp-parse.el
new file mode 100644
index 0000000..7c29794
--- /dev/null
+++ b/javaimp-parse.el
@@ -0,0 +1,145 @@
+;;; javaimp-parse.el --- javaimp parsing  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; Author: Filipp Gunbin <fgunbin@fastmail.fm>
+;; Maintainer: Filipp Gunbin <fgunbin@fastmail.fm>
+
+;; 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 3 of the License, or
+;; (at your option) 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, see <http://www.gnu.org/licenses/>.
+
+(require 'cl-lib)
+(require 'seq)
+
+(cl-defstruct javaimp-scope
+  type ; one of anonymous-class, class, interface, enum, local-class, unknown
+  name
+  start
+  open-brace)
+
+(defsubst javaimp--parse-is-class (scope)
+  (memq (javaimp-scope-type scope) '(class interface enum)))
+
+(defconst javaimp--parse-class-re
+  (concat
+   (regexp-opt '("class" "interface" "enum") 'words)
+   (rx (and (+ (syntax whitespace))
+            (group (+ (any alnum ?_)))))))
+
+
+(defun javaimp--parse-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)))))))))
+
+
+(defvar javaimp--parse-scope-hook
+  '(javaimp--parse-scope-class
+    javaimp--parse-scope-anonymous-class
+    javaimp--parse-scope-unknown      ;fallback
+    ))
+
+(defun javaimp--parse-scope-class (state)
+  (save-excursion
+    (if (and (re-search-backward javaimp--parse-class-re nil t)
+             ;; if there's no paren in between - assume we're looking at
+             ;; class declaration
+             (not (save-match-data
+                    (search-forward "(" (nth 1 state) t))))
+        (make-javaimp-scope :type (intern (match-string 1))
+                            :name (match-string 2)
+                            :start (match-beginning 1)
+                            :open-brace (nth 1 state)))))
+
+(defun javaimp--parse-scope-anonymous-class (state)
+  (save-excursion
+    (let (end)
+      (if (and (re-search-backward "\\<new\\s +" nil t)
+               ;; skip arg list and ws
+               (setq end (save-excursion
+                           (ignore-errors
+                             (goto-char
+                              (scan-lists (nth 1 state) -1 0))
+                             (skip-syntax-backward "-")
+                             (point))))
+               (not (save-match-data
+                      (search-forward "(" end t))))
+          (make-javaimp-scope :type 'anonymous-class
+                              :name (concat
+                                     "Anon_"
+                                     (buffer-substring-no-properties
+                                      (match-end 0) end))
+                              :start (match-beginning 0)
+                              :open-brace (nth 1 state))))))
+
+(defun javaimp--parse-scope-unknown (state)
+  (make-javaimp-scope :type 'unknown
+                      :name "unknown"
+                      :start nil
+                      :open-brace (nth 1 state)))
+
+(defun javaimp--parse-scopes (count)
+  (let ((state (syntax-ppss))
+        res)
+    (unless (syntax-ppss-context state)
+      (save-excursion
+        (while (and (nth 1 state)
+                    (or (not count)
+                        (>= (setq count (1- count)) 0)))
+          ;; find innermost enclosing open-bracket
+          (goto-char (nth 1 state))
+          (when (= (char-after) ?{)
+            (let ((scope (run-hook-with-args-until-success
+                          'javaimp--parse-scope-hook state)))
+              (push scope res)
+              (if (javaimp-scope-start scope)
+                  (goto-char (javaimp-scope-start scope)))))
+          (setq state (syntax-ppss)))))
+    ;; if a class is enclosed in anything other than a class, then it
+    ;; should be local
+    (let ((tmp res)
+          in-local)
+      (while tmp
+        (if (javaimp--parse-is-class (car tmp))
+            (if in-local
+                (setf (javaimp-scope-type (car tmp)) 'local-class))
+          (setq in-local t))
+        (setq tmp (cdr tmp))))
+    res))
+
+(defun javaimp--parse-get-file-classes (file)
+  (with-temp-buffer
+    (insert-file-contents file)
+    (let ((parse-sexp-ignore-comments t)
+          (package (javaimp--parse-get-package))
+          res)
+      (while (re-search-forward javaimp--parse-class-re nil t)
+        (when (and (ignore-errors
+                     (goto-char (scan-lists (point) 1 -1)))
+                   (= (char-before) ?{))
+          (let ((scopes (javaimp--parse-scopes nil))
+                curr)
+            (when (seq-every-p #'javaimp--parse-is-class scopes)
+              (setq curr (mapconcat #'javaimp-scope-name scopes "."))
+              (if package
+                  (setq curr (concat package "." curr)))
+              (push curr res)))))
+      (nreverse res))))
+
+(provide 'javaimp-parse)
diff --git a/javaimp-tests.el b/javaimp-tests.el
index 36b4686..9951a81 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -23,15 +23,15 @@
       (should (eql (length projects) 2)))))
 
 
-(ert-deftest javaimp-test--get-package ()
+(ert-deftest javaimp-test--parse-get-package ()
   (with-temp-buffer
     (insert "//package org.commented1;
 /*package org.commented2;*/
   package org.foo;")
-    (should (equal (javaimp--get-package) "org.foo"))))
+    (should (equal (javaimp--parse-get-package) "org.foo"))))
 
-(ert-deftest javaimp-test--get-file-classes ()
-  (should (equal (javaimp--get-file-classes
+(ert-deftest javaimp-test--parse-get-file-classes ()
+  (should (equal (javaimp--parse-get-file-classes
                   (concat javaimp--basedir 
"testdata/test-get-file-classes-1.java"))
                  '("org.foo.Top"
                    "org.foo.Top.CInner1"
diff --git a/javaimp-util.el b/javaimp-util.el
index f2f4c00..9304fce 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -157,56 +157,4 @@ 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 8b368ea..a0dd555 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -77,6 +77,7 @@
 
 (require 'javaimp-maven)
 (require 'javaimp-gradle)
+(require 'javaimp-parse)
 
 
 
@@ -444,7 +445,7 @@ prefix arg is given, don't do this filtering."
                javaimp-additional-source-dirs)))
 
 (defun javaimp--dir-above-current-package ()
-  (let ((package (javaimp--get-package)))
+  (let ((package (javaimp--parse-get-package)))
     (when package
       (string-remove-suffix
        (mapconcat #'file-name-as-directory
@@ -453,7 +454,7 @@ prefix arg is given, don't do this filtering."
 
 (defun javaimp--get-directory-classes (dir)
   (if (file-accessible-directory-p dir)
-      (seq-mapcat #'javaimp--get-file-classes
+      (seq-mapcat #'javaimp--parse-get-file-classes
                   (seq-filter (lambda (file)
                                 (not (file-symlink-p file)))
                               (directory-files-recursively dir 
"\\.java\\'")))))



reply via email to

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