branch: externals/matlab-mode
commit 340fcd85920b9abcd692f84de31d4aa4e6d4d150
Author: John Ciolfi <[email protected]>
Commit: John Ciolfi <[email protected]>

    matlab-ts-mode.el: on load add a final newline if needed to non-empty *.m 
files
---
 matlab-ts-mode.el                                  | 33 ++++++++++++++++++----
 .../parser_no_final_newline.m                      |  4 +++
 .../parser_no_final_newline_expected.txt           | 11 ++++++++
 tests/test-matlab-ts-mode-parser.el                |  7 +++++
 4 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el
index 6aa7150085..2ab2c27ae4 100644
--- a/matlab-ts-mode.el
+++ b/matlab-ts-mode.el
@@ -258,7 +258,7 @@ content can crash Emacs via the matlab tree-sitter parser."
       (goto-char bad-char-point)
       (user-error
        "Not entering matlab-ts-mode due to non-printable utf8 character \"%c\" 
at point %d"
-       (char-before) bad-char-point ))))
+       (char-before) bad-char-point))))
 
 ;;; Syntax table
 
@@ -3560,6 +3560,28 @@ THERE-END MISMATCH) or nil."
                                            unread-command-events))
         ))))
 
+(defun matlab-ts-mode--add-final-newline (&optional restore-readonly)
+  "Add a final newline to non-empty buffer to make tree-sitter happy.
+If a final new-line is missing, matlab tree-sitter can generate a parse
+error because it looks for the newline to finish statements.
+
+If optional RESTORE-READONLY is non-nil, then if the buffer is read-only
+upon calling this function, it will be restored back to read-only if a
+final newline was inserted."
+  (save-excursion
+    (goto-char (point-max))
+    (when (and (< (point-min) (point-max))
+               (not (= (char-before) ?\n)))
+      (let ((is-read-only buffer-read-only))
+        (when is-read-only
+          (read-only-mode 0))
+        (insert "\n")
+        (when (and restore-readonly
+                   is-read-only)
+          (set-buffer-modified-p nil))
+        (when is-read-only
+          (read-only-mode 1))))))
+
 (defun matlab-ts-mode--post-insert-callback ()
   "Callback attached to `post-self-insert-hook'.
 
@@ -3575,11 +3597,7 @@ This callback also implements 
`matlab-ts-mode-electric-ends'."
   (when (eq major-mode 'matlab-ts-mode)
     (let ((ret-typed (eq last-command-event ?\n)))
 
-      ;; Add final newline to the buffer?
-      (save-excursion
-        (goto-char (point-max))
-        (when (not (= (char-before) ?\n))
-          (insert "\n")))
+      (matlab-ts-mode--add-final-newline)
 
       ;; Add "end" (for `matlab-ts-mode-electric-ends')
       (when (and ret-typed
@@ -4062,6 +4080,9 @@ so configuration variables of that mode, do not affect 
this mode.
   (matlab-ts-mode--check-file-encoding)
 
   (when (treesit-ready-p 'matlab)
+
+    (matlab-ts-mode--add-final-newline 'restore-readonly)
+
     (treesit-parser-create 'matlab)
 
     ;; Syntax table - think of this as a "language character descriptor". It 
tells us what
diff --git a/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m 
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m
new file mode 100644
index 0000000000..bc28fd1bbf
--- /dev/null
+++ b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m
@@ -0,0 +1,4 @@
+% -*- matlab-ts -*-
+if a
+    disp('b')
+end
\ No newline at end of file
diff --git 
a/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt 
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt
new file mode 100644
index 0000000000..877dcb3517
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt
@@ -0,0 +1,11 @@
+# -*- t-utils-ts-parse-tree -*-
+(source_file (comment[1,20]@{% -*- matlab-ts -*-}@)
+ (if_statement if[21,23] condition: (identifier[24,25]@{a}@)
+  (block
+   (function_call name: (identifier[30,34]@{disp}@) ([34,35]
+    (arguments
+     argument: (string '[35,36] (string_content[36,37]@{b}@) '[37,38]))
+    )[38,39])
+   \n[39,40])
+  end[40,43])
+ \n[43,44])
diff --git a/tests/test-matlab-ts-mode-parser.el 
b/tests/test-matlab-ts-mode-parser.el
index 09b6d614c8..763313b3de 100644
--- a/tests/test-matlab-ts-mode-parser.el
+++ b/tests/test-matlab-ts-mode-parser.el
@@ -60,6 +60,13 @@ To understand the format of NAME_expected.txt files, see
 
   (should (equal (test-matlab-ts-mode-parser--all-files) ""))
 
+  ;; Validate following file does not have a final newline. matlab tree-sitter 
requires a final
+  ;; newline for a valid parse because it uses newlines to identify the end of 
statements.
+  (with-temp-buffer
+    (insert-file-contents-literally 
"test-matlab-ts-mode-parser-files/parser_no_final_newline.m")
+    (goto-char (point-max))
+    (should (equal (= (char-before) ?\n) nil)))
+
   (let* ((test-name "test-matlab-ts-mode-parser")
          (m-files (t-utils-get-files test-name
                                      :recursively t

Reply via email to