branch: scratch/javaimp-parse commit cbf916981a29f6857a96d224d8d7ca3c1c52b2df Author: Filipp Gunbin <fgun...@fastmail.fm> Commit: Filipp Gunbin <fgun...@fastmail.fm>
wip --- javaimp-parse.el | 116 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/javaimp-parse.el b/javaimp-parse.el index 7c29794..b29b2e8 100644 --- a/javaimp-parse.el +++ b/javaimp-parse.el @@ -22,20 +22,31 @@ (require 'seq) (cl-defstruct javaimp-scope - type ; one of anonymous-class, class, interface, enum, local-class, unknown + type ; one of anonymous-class, class, interface, enum, local-class, + ; method, statement, unknown name start open-brace) -(defsubst javaimp--parse-is-class (scope) - (memq (javaimp-scope-type scope) '(class interface enum))) +(defconst javaimp--parse-class-keywords + '("class" "interface" "enum")) +(defconst javaimp--parse-stmt-keywords + '("if" "for" "while" "switch" "try" "catch")) -(defconst javaimp--parse-class-re +(defun javaimp--parse-block-re (keywords) (concat - (regexp-opt '("class" "interface" "enum") 'words) + (regexp-opt keywords 'words) (rx (and (+ (syntax whitespace)) (group (+ (any alnum ?_))))))) +(defconst javaimp--parse-class-re + (javaimp--parse-block-re javaimp--parse-class-keywords)) +(defconst javaimp--parse-stmt-re + (javaimp--parse-block-re javaimp--parse-stmt-keywords)) + +(defsubst javaimp--parse-is-class (scope) + (member (symbol-name (javaimp-scope-type scope)) javaimp--parse-class-keywords)) + (defun javaimp--parse-get-package () (save-excursion @@ -50,9 +61,12 @@ (defvar javaimp--parse-scope-hook - '(javaimp--parse-scope-class + '(;; should be before method/stmt because looks similar, but with + ;; "new " in front javaimp--parse-scope-anonymous-class - javaimp--parse-scope-unknown ;fallback + javaimp--parse-scope-method-or-stmt + javaimp--parse-scope-class + javaimp--parse-scope-unknown ; catch-all )) (defun javaimp--parse-scope-class (state) @@ -73,11 +87,13 @@ (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)))) + (and (ignore-errors + (goto-char + (scan-lists (nth 1 state) -1 0))) + (eq (char-after) ?\() + (progn + (skip-syntax-backward "-") + (point))))) (not (save-match-data (search-forward "(" end t)))) (make-javaimp-scope :type 'anonymous-class @@ -88,6 +104,82 @@ :start (match-beginning 0) :open-brace (nth 1 state)))))) +(defun javaimp--parse-scope-method-or-stmt (state) + (save-excursion + (when (and (ignore-errors + (goto-char ;skip over 1 list + (scan-lists (nth 1 state) -1 0))) + (eq (char-after) ?\()) + (let* ((arglist (buffer-substring-no-properties + (point) + (scan-lists (point) 1 0))) + (count (progn + (skip-syntax-backward "-") + (skip-syntax-backward "w_"))) + (name (and (< count 0) + (buffer-substring-no-properties + (point) (+ (point) (abs count))))) + (type (when name + (if (member name javaimp--parse-stmt-keywords) + 'statement 'method)))) + (when type + (make-javaimp-scope :type type + :name (if (eq type 'statement) + name + (concat name + ;; to distinguish overloaded methods + (javaimp--parse-arglist arglist))) + :start (point) + :open-brace (nth 1 state))))))) + +(defun javaimp--parse-arglist (arglist) + (with-temp-buffer + (with-syntax-table 'javaimp--arglist-syntax-table ;TODO <> + (condition-case nil + (let (name end res curr) + (insert arglist) + (backward-char) ; `)' + (while (not (bobp)) + (setq end (point)) + ;; name + (if (= 0 (skip-syntax-backward "w_")) + (error "No name") + (setq name (buffer-substring (point) end))) + (skip-syntax-backward "-") + (setq start nil + end (point)) + ;; type - allow anything but skip over angle brackets + (while (not start) + (cond ((bobp) + (error "Invalid type")) + ((= (char-before) ? ) + (setq start (point))) + ((= (char-before) ?>) + ;; skip over generics + (goto-char + (scan-lists (point) -1 0))) + (t + (backward-char)))) + (push (cons (buffer-substring start end) name) res) + (setq curr nil) + ;; TODO skip everything up to comma or open-paren + ) + res) + (t nil))))) + + +(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-unknown (state) (make-javaimp-scope :type 'unknown :name "unknown"