From 21b33abd51e779e8231ff4760a2053cd5756b72a Mon Sep 17 00:00:00 2001 From: Eric Ludlam Date: Sat, 27 Mar 2021 13:58:07 -0400 Subject: [PATCH] matlab-complete.el: (matlab-find-recent-variable-list): Use new search APIs for keyword searches. Fix some misc bugs. (matlab--complete-compute-search-functions): New - pulled from below: (matlab-complete-symbol-local): Remove code for deriving which functions to use. Pulled out to support testing. matlab.el: (matlab-mcos-innerblock-regexp, matlab-mcos-regexp, matlab-block-beg-pre-if) (matlab-block-beg-pre-no-if, matlab-block-beg-pre): DELETED tests/metest.el: (matlab-complete): New require (metest-all-syntax-tests): Move stuff around. Add metest-complete-test. (met-complete-files, met-complete-tools, metest-complete-test): NEW tests/complete.m: New file for testing local completion stuff. --- matlab-complete.el | 80 ++++++++++++++++++++++++---------------------- matlab.el | 29 ----------------- tests/complete.m | 47 +++++++++++++++++++++++++++ tests/metest.el | 53 ++++++++++++++++++++++++++++-- 4 files changed, 139 insertions(+), 70 deletions(-) create mode 100644 tests/complete.m diff --git a/matlab-complete.el b/matlab-complete.el index 0643c31..0874f9b 100644 --- a/matlab-complete.el +++ b/matlab-complete.el @@ -248,28 +248,28 @@ If the list is empty, then searches continue backwards through the code." (nreverse lst))) (save-excursion (let ((lst nil)) - (while (and (re-search-backward - (concat "\\<\\(" matlab-block-beg-pre-no-if - "\\)\\s-+(?\\s-*\\(" prefix - "\\w+\\)\\>") - bounds t) - (< (length lst) 10)) - (setq lst (cons (match-string 2) lst))) + (while (and + (< (length lst) 10) + (matlab-re-search-keyword-backward (matlab-keyword-regex 'ctrl) bounds t)) + (when (looking-at (concat "\\w+\\s-+(?\\(" prefix "\\w+\\)\\_>")) + (setq lst (cons (match-string 1) lst)))) (nreverse lst))) (save-excursion - (if (re-search-backward "^\\s-*global\\s-+" bounds t) - (let ((lst nil) m e) + (let ((lst nil) m e) + (while (matlab-re-search-keyword-backward + (matlab-keyword-regex 'vardecl) bounds t) + (save-excursion (goto-char (match-end 0)) - (while (looking-at "\\(\\w+\\)\\([ \t]+\\|$\\)") + (while (looking-at "\\s-*\\(\\w+\\)\\([ \t]+\\|$\\)") (setq m (match-string 1) e (match-end 0)) (if (equal 0 (string-match prefix m)) (setq lst (cons m lst))) - (goto-char e)) - (nreverse lst)))) + (goto-char e)))) + (nreverse lst))) (save-excursion (if (and (re-search-backward "^\\s-*function\\>" bounds t) - (re-search-forward "\\<\\(\\w+\\)(" + (re-search-forward "\\_<\\(\\w+\\)\\s-*(" (matlab-point-at-eol) t)) (let ((lst nil) m e) (while (looking-at "\\(\\w+\\)\\s-*[,)]\\s-*") @@ -315,7 +315,7 @@ In NEXT is non-nil, than continue through the list of elements." (let ((lst nil)) (while (re-search-forward "^\\s-*function\\>" nil t) (if (re-search-forward - (concat "\\(" prefix "\\w+\\)\\s-*\\($\\|(\\)") + (concat "\\_<\\(" prefix "\\w+\\)\\s-*\\($\\|(\\)") (matlab-point-at-eol) t) (setq lst (cons (match-string 1) lst)))) (nreverse lst))) @@ -463,7 +463,33 @@ Use `completion-in-region' to support the completion behavior." (completion-in-region common-substr-start-pt common-substr-end-pt completions) )) ) - + +(defun matlab--complete-compute-search-functions (semantics) + "Return the search functions for context specified by SEMATNICS." + (cond ((eq semantics 'solo) + '(matlab-solo-completions + matlab-find-user-functions + matlab-find-recent-variable)) + ((eq semantics 'boolean) + '(matlab-find-recent-variable + matlab-boolean-completions + matlab-find-user-functions + matlab-value-completions)) + ((eq semantics 'value) + '(matlab-find-recent-variable + matlab-find-user-functions + matlab-value-completions + matlab-boolean-completions)) + ((eq semantics 'property) + '(matlab-property-completions + matlab-find-user-functions + matlab-find-recent-variable + matlab-value-completions)) + (t '(matlab-find-recent-variable + matlab-find-user-functions + matlab-value-completions + matlab-boolean-completions)))) + (defun matlab-complete-symbol-local (&optional arg) "Complete a partially typed symbol in a MATLAB mode buffer. If the previously entered command was also `matlab-complete-symbol' @@ -496,29 +522,7 @@ to change it temporarily." (setq matlab-last-prefix prefix matlab-last-semantic sem matlab-completion-search-state - (cond ((eq sem 'solo) - '(matlab-solo-completions - matlab-find-user-functions - matlab-find-recent-variable)) - ((eq sem 'boolean) - '(matlab-find-recent-variable - matlab-boolean-completions - matlab-find-user-functions - matlab-value-completions)) - ((eq sem 'value) - '(matlab-find-recent-variable - matlab-find-user-functions - matlab-value-completions - matlab-boolean-completions)) - ((eq sem 'property) - '(matlab-property-completions - matlab-find-user-functions - matlab-find-recent-variable - matlab-value-completions)) - (t '(matlab-find-recent-variable - matlab-find-user-functions - matlab-value-completions - matlab-boolean-completions))))) + (matlab--complete-compute-search-functions sem))) (cond ((eq matlab-completion-technique 'increment) (let ((r nil) (donext (eq last-command 'matlab-complete-symbol))) diff --git a/matlab.el b/matlab.el index 4711bc7..3967176 100644 --- a/matlab.el +++ b/matlab.el @@ -1447,35 +1447,6 @@ Ignore comments and whitespace." ;;; Regexps for MATLAB language =============================================== -;; "-pre" means "partial regular expression" -;; "-if" and "-no-if" means "[no] Indent Function" - -(defconst matlab-mcos-innerblock-regexp "properties\\|methods\\|events\\|enumeration\\|arguments" - "Keywords which mark the beginning of mcos blocks. -These keywords can be overriden as variables or functions in other contexts -asside from that which they declare their content.") - -(defconst matlab-mcos-regexp (concat "\\|classdef\\|" matlab-mcos-innerblock-regexp) - "Keywords which mark the beginning of mcos blocks.") - -(defconst matlab-block-beg-pre-if - (concat "function\\|parfor\\|spmd\\|for\\|while\\|if\\|switch\\|try" - matlab-mcos-regexp) - "Keywords which mark the beginning of an indented block. -Includes function.") - -(defconst matlab-block-beg-pre-no-if - (concat "parfor\\|for\\|spmd\\|while\\|if\\|switch\\|try" - matlab-mcos-regexp) - "Keywords which mark the beginning of an indented block. -Excludes function.") - -(defun matlab-block-beg-pre () - "Partial regular expression to recognize MATLAB block-begin keywords." - (if matlab-functions-have-end - matlab-block-beg-pre-if - matlab-block-beg-pre-no-if)) - (defun matlab-match-function-re () "Expression to match a function start line. There are no reliable numeric matches in this expression. diff --git a/tests/complete.m b/tests/complete.m new file mode 100644 index 0000000..3fd5e80 --- /dev/null +++ b/tests/complete.m @@ -0,0 +1,47 @@ +function complete (a_arg1, b_arg2) +% This function is for testing completion tools + + arguments + a_arg1 (1,1) double + b_arg2 (2,1) int + end + + global a_global + global b_global + + a_localvar = 1; + b_localvar = 1; + + for a_for=1:10 + end + + if bool_var + end + + switch a_switch + end + + a_ + % @@(solo var "a_localvar" "a_switch" "a_for" "a_global" "a_arg1") + % @@(solo fcn ) + + % Note: For b, there are other test files the completion + % engine will find, so they are included. + b + % @@(solo fcn "blocal_fcn" "blazy_fcn" "buggy" "blocks") + % @@(solo var "b_localvar" "bool_var" "b_global" "b_arg2") + + + % quiet mlint + blocal_fcn(a_arg1, b_arg2, a_localvar, b_localvar, a_global, b_global); +end + +function blocal_fcn(varargin) + + blazy_fcn(varargin{:}); + +end + +function blazy_fcn(varargin) +end + diff --git a/tests/metest.el b/tests/metest.el index 5d6d9b5..b5570ad 100644 --- a/tests/metest.el +++ b/tests/metest.el @@ -34,6 +34,7 @@ (require 'matlab-load) (require 'matlab) (require 'cedet-matlab) +(require 'matlab-complete) (require 'semantic-matlab) ;; Enable semantic @@ -52,6 +53,7 @@ (setq-default matlab-indent-function-body 'MathWorks-Standard) ;; put it back (metest-run 'metest-comment-string-syntax-test) + (metest-run 'metest-fontlock-test) (metest-run 'metest-sexp-counting-test) (metest-run 'metest-sexp-traversal-test) @@ -61,10 +63,10 @@ (metest-indents-randomize-files) (metest-run 'metest-indents-test) + ;; Parsing and completion are high level tools (metest-run 'metest-parse-test) + (metest-run 'metest-complete-test) - (metest-run 'metest-fontlock-test) - (metest-log-report (metest-log-write)) (matlab-scan-stats-print) @@ -446,7 +448,52 @@ ( "df" . nil ) ) "List of testing keywords and associated faces.") - + + +(defvar met-complete-files '("complete.m") + "List of files for running font completion tests.") + +(defvar met-complete-tools '((var . matlab-find-recent-variable) + (fcn . matlab-find-user-functions) + ) + "List of tools that generate completions.") + +(defvar metest-complete-test (cons "completion" met-complete-files)) +(defun metest-complete-test (F) + "Test the completion tools in matlab-complete.el" + (let ((buf (metest-find-file F)) + exp act + (cnt 0)) + (with-current-buffer buf + (goto-char (point-min)) + + (while (re-search-forward "%\\s-*@@" nil t) + (setq exp (read (buffer-substring-no-properties (point) (scan-sexps (point) 1)))) + ;; Move to end of previous line, and try to do a complete + (matlab-with-context-line (matlab-previous-code-line (matlab-compute-line-context 2)) + (end-of-line) + (let* ((prefix (buffer-substring-no-properties + (save-excursion (forward-word -1) (point)) + (point))) + (sem (matlab-lattr-semantics prefix)) + ) + ;; Did we get the expected semantics of this location? + (when (not (eq sem (car exp))) + (metest-error "Completion Semantic Missmatch: Expected %s but found %s" (car exp) sem)) + + (let* ((expR (nthcdr 2 exp)) + (fcn (assoc (nth 1 exp) met-complete-tools)) + (act (funcall (cdr fcn) prefix))) + (when (not (equal act expR)) + (metest-error "Completion Missmatch: Expected %S but found %S using function %S" + expR act fcn)) + ) + )) + (setq cnt (1+ cnt)) + ;; Skip this match, find the next. + (end-of-line))) + (list cnt "tests"))) + (defvar met-fontlock-files '("fontlock.m" "mclass.m" "blocks.m") "List of files for running font lock tests.")