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

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

[nongnu] elpa/haskell-tng-mode 1009082 140/385: append indentation test


From: ELPA Syncer
Subject: [nongnu] elpa/haskell-tng-mode 1009082 140/385: append indentation test
Date: Tue, 5 Oct 2021 23:59:18 -0400 (EDT)

branch: elpa/haskell-tng-mode
commit 10090824cd2998ad90625a4983e741cdb900b198
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>

    append indentation test
---
 haskell-tng-layout.el                 |  14 ++++
 haskell-tng-mode.el                   |   9 ++-
 haskell-tng-smie.el                   |   2 +-
 test/haskell-tng-indent-test.el       | 127 +++++++++++++++++++++++-----------
 test/src/indentation.hs.append.indent | 102 +++++++++++++++++++++++++++
 5 files changed, 210 insertions(+), 44 deletions(-)

diff --git a/haskell-tng-layout.el b/haskell-tng-layout.el
index 0a4f311..f4af977 100644
--- a/haskell-tng-layout.el
+++ b/haskell-tng-layout.el
@@ -32,8 +32,14 @@
 ;;
 ;; Anything more complicated that small brain needs improved testing.
 
+(require 'dash)
+
 (require 'haskell-tng-util)
 
+;; FIXME only search up to one line for the WLDO opener, otherwise close it out
+;; with {} This is not valid compiling Haskell code, but it allows SMIE to 
close
+;; off the s-expression.
+
 ;; Easiest cache... full buffer parse with full invalidation on any insertion.
 (defvar-local haskell-tng-layout:cache nil)
 
@@ -74,6 +80,14 @@ Designed to be called repeatedly, managing its own caching."
                   (push ";" breaks))))))
         (append (reverse closes) (reverse breaks))))))
 
+(defun haskell-tng-layout:has-virtual-at-point ()
+  "t if there is a virtual at POINT"
+  ;; avoids a measured performance hit (append indentation)
+  (unless haskell-tng-layout:cache
+    (haskell-tng-layout:rebuild-cache-full))
+  (--any (member (point) it)
+         haskell-tng-layout:cache))
+
 (defun haskell-tng-layout:rebuild-cache-full ()
   (let (case-fold-search
         cache)
diff --git a/haskell-tng-mode.el b/haskell-tng-mode.el
index fbc9e4f..86594bc 100644
--- a/haskell-tng-mode.el
+++ b/haskell-tng-mode.el
@@ -73,10 +73,13 @@ Load `prettify-symbols-mode' in `haskell-tng-mode-hook'."
    font-lock-multiline t
    font-lock-extend-region-functions haskell-tng:extend-region-functions
 
-   ;; whitespace is meaningful, no electric indentation
-   electric-indent-inhibit t
-
    prettify-symbols-alist haskell-tng-mode:prettify-symbols)
+
+  ;; whitespace is meaningful, disable electric indentation. Note that
+  ;; `electric-indent-inhibit' causes a performance regression in SMIE
+  ;; indentation, so it's best to just make sure it is disabled.
+  (electric-indent-mode 0)
+
   (setq-local projectile-tags-command "fast-tags -Re --exclude=dist-newstyle 
.")
   (setq-local smie-blink-matching-inners nil) ;; c.f. `smie-closer-alist'
 
diff --git a/haskell-tng-smie.el b/haskell-tng-smie.el
index 8caab9f..db485c9 100644
--- a/haskell-tng-smie.el
+++ b/haskell-tng-smie.el
@@ -242,7 +242,7 @@ current line."
       (forward-line))
     (goto-char start)
     (while (< (point) bound)
-      (when (haskell-tng-layout:virtuals-at-point)
+      (when (haskell-tng-layout:has-virtual-at-point)
         (push (current-column) relevant))
       (forward-char))
     relevant))
diff --git a/test/haskell-tng-indent-test.el b/test/haskell-tng-indent-test.el
index 07c3128..213de04 100644
--- a/test/haskell-tng-indent-test.el
+++ b/test/haskell-tng-indent-test.el
@@ -12,31 +12,48 @@
 (require 'haskell-tng-testutils
          "test/haskell-tng-testutils.el")
 
-  ;; Three indentation regression tests are possible:
-  ;;
-  ;;   1. newline-and-indent with the rest of the file deleted (append)
-  ;;   2. newline-and-indent with the rest of the file intact (insert)
-  ;;   3. indent-line-function at the beginning of each line (re-indent)
-  ;;
-  ;; each maybe with alternative indentation suggestions.
-  ;;
-  ;; Expectations could use lines of symbols such as | and . or digits to
-  ;; indicate where the indentation(s) go.
-  ;;
-  ;; Test 1 involves a lot of buffer refreshing and will be very slow.
-
-(ert-deftest haskell-tng-newline-indent-file-tests ()
-  (should (have-expected-newline-indent-insert (testdata 
"src/indentation.hs")))
-
-  ;; (should (have-expected-newline-indent-insert (testdata "src/layout.hs")))
-  ;; (should (have-expected-newline-indent-insert (testdata "src/medley.hs")))
+;; Three indentation regression tests are possible:
+;;
+;;   1. newline-and-indent with the rest of the file deleted (append)
+;;   2. newline-and-indent with the rest of the file intact (insert)
+;;   3. indent-line-function at the beginning of each line (re-indent)
+;;
+;; each maybe with alternative indentation suggestions.
+;;
+;; Expectations could use lines of symbols such as | and . or digits to
+;; indicate where the indentation(s) go.
+;;
+;; Test 1 involves a lot of buffer refreshing and will be very slow.
+
+(ert-deftest haskell-tng-append-indent-file-tests ()
+  ;; this is a very slow test
+
+  ;; (require 'profiler)
+  ;; (profiler-start 'cpu)
+
+  (should (have-expected-append-indent (testdata "src/indentation.hs")))
+
+  ;; (profiler-report)
+  ;; (profiler-report-write-profile "indentation.profile")
+  ;; (profiler-stop)
+
+  ;; To interactively inspect
+  ;; (profiler-find-profile "../indentation.profile")
+  )
+
+
+(ert-deftest haskell-tng-indent-file-tests ()
+  (should (have-expected-insert-indent (testdata "src/indentation.hs")))
+
+  ;; (should (have-expected-insert-indent (testdata "src/layout.hs")))
+  ;; (should (have-expected-insert-indent (testdata "src/medley.hs")))
   )
 
 (ert-deftest haskell-tng-reindent-file-tests ()
-  (should (have-expected-reindent-insert (testdata "src/indentation.hs")))
+  (should (have-expected-reindent (testdata "src/indentation.hs")))
 
-  ;; (should (have-expected-reindent-insert (testdata "src/layout.hs")))
-  ;; (should (have-expected-reindent-insert (testdata "src/medley.hs")))
+  ;; (should (have-expected-reindent (testdata "src/layout.hs")))
+  ;; (should (have-expected-reindent (testdata "src/medley.hs")))
   )
 
 (defun current-line-string ()
@@ -44,13 +61,22 @@
    (line-beginning-position)
    (- (line-beginning-position 2) 1)))
 
-(defun haskell-tng-indent-test:indent-insert (return-mode)
-  ;; FIXME the slow append test
-  (let (indents)
+(defun haskell-tng-indent-test:work (mode)
+  "MODE can be 'insert, 'reindent, or 'append.
+
+'append is VERY slow."
+  ;; each line could be done in parallel, if emacs allowed such a thing...
+  (let (indents kill)
     (while (not (eobp))
       ;; the command loop is necessary for this/last-command
       (cl-flet ((RET ()
                      (end-of-line)
+                     (pcase mode
+                       ('append
+                        (setq kill ;; kill-region/yank is noisy
+                              (buffer-substring-no-properties
+                               (point) (point-max)))
+                        (delete-region (point) (point-max))))
                      (ert-simulate-command '(newline-and-indent))
                      (current-column))
                 (TAB ()
@@ -59,28 +85,40 @@
 
         (let ((orig (current-indentation))
               (line (current-line-string))
-              (prime (if return-mode (RET) (TAB)))
+              (prime (pcase mode
+                       ((or 'insert 'append) (RET))
+                       ('reindent (TAB))))
               alts)
           (while (and (TAB)
                       (not (eq (current-column) prime))
                       (not (member (current-column) alts)))
             (push (current-column) alts))
-          (push `(, return-mode ,line . (,prime . ,(reverse alts))) indents)
+          (push `(,(pcase mode ((or 'insert 'append) t))
+                  ,line . (,prime . ,(reverse alts)))
+                indents)
           ;; unfortunately killing resets this-command so we can't test double
           ;; newline insertions, which could accidentally trigger alts only.
-          (if return-mode
-              (kill-whole-line)
-            (indent-line-to orig)
-            (ert-simulate-command '(forward-line))))))
+          (pcase mode
+            ('insert (kill-whole-line))
+            ('reindent
+             (indent-line-to orig)
+             (ert-simulate-command '(forward-line)))
+            ('append
+             (forward-line -1)
+             (end-of-line)
+             (save-excursion
+               (insert kill)
+               (delete-region (point) (point-max)))
+             (ert-simulate-command '(forward-line)))))))
     (reverse indents)))
 
 (defun haskell-tng-indent-test:indents-to-string (indents)
   "INDENTS is a list of INDENT.
 
-INDENT is a non-empty list of (RETURN-MODE . (LINE . (INDENT .
-ALTS))) where RETURN-MODE is t for newline insertions (i.e. LINE
-is a string of the previous line) and nil for reindent (i.e. LINE
-is a string of the current line).
+INDENT is a non-empty list of (RET . (LINE . (INDENT . ALTS)))
+where RET is t for newline insertions (i.e. LINE is a string of
+the previous line) and nil for reindent (i.e. LINE is a string of
+the current line).
 
 INDENT is the integer suggested next line indentation column and
 ALTS is a list of integer alternative indentations."
@@ -88,7 +126,7 @@ ALTS is a list of integer alternative indentations."
                 (-map #'haskell-tng-indent-test:indent-to-string indents))))
 
 (defun haskell-tng-indent-test:indent-to-string (indent)
-  (let* ((return-mode (car indent))
+  (let* ((ret (car indent))
          (line (cadr indent))
          (prime (caddr indent))
          (alts (cdddr indent))
@@ -106,26 +144,35 @@ ALTS is a list of integer alternative indentations."
         (t " "))
        repr))
     (let ((indents (s-join "" (reverse repr))))
-      (if return-mode
+      (if ret
           (list line indents)
         (list indents line)))))
 
-(defun have-expected-newline-indent-insert (file)
+(defun have-expected-insert-indent (file)
   (haskell-tng-testutils:assert-file-contents
    file
    #'haskell-tng-mode
    (lambda ()
      (haskell-tng-indent-test:indents-to-string
-      (haskell-tng-indent-test:indent-insert t)))
+      (haskell-tng-indent-test:work 'insert)))
    "insert.indent"))
 
-(defun have-expected-reindent-insert (file)
+(defun have-expected-reindent (file)
   (haskell-tng-testutils:assert-file-contents
    file
    #'haskell-tng-mode
    (lambda ()
      (haskell-tng-indent-test:indents-to-string
-      (haskell-tng-indent-test:indent-insert nil)))
+      (haskell-tng-indent-test:work 'reindent)))
    "reindent"))
 
+(defun have-expected-append-indent (file)
+  (haskell-tng-testutils:assert-file-contents
+   file
+   #'haskell-tng-mode
+   (lambda ()
+     (haskell-tng-indent-test:indents-to-string
+      (haskell-tng-indent-test:work 'append)))
+   "append.indent"))
+
 ;;; haskell-tng-indent-test.el ends here
diff --git a/test/src/indentation.hs.append.indent 
b/test/src/indentation.hs.append.indent
new file mode 100644
index 0000000..b630885
--- /dev/null
+++ b/test/src/indentation.hs.append.indent
@@ -0,0 +1,102 @@
+-- | Idealised indentation scenarios.
+v
+--
+v
+--   Bugs and unexpected behaviour in (re-)indentation may be documented here.
+v
+--
+v
+--   Lines marked "manual correction" indicate where we expect the user to
+v
+--   re-indent because it goes against our prediction. In some of these cases,
+v
+--   we could improve the guess with semantic information (e.g. if we know that
+v
+--   the RHS of a bind is only partially applied, then we probably mean to
+v
+--   continue that line instead of start a new one).
+v
+module Indentation where
+v
+
+v
+import Foo.Bar
+v
+import Foo.Baz hiding ( gaz,
+1                       v
+                        baz
+1                       v
+                      )
+v                     1 2
+
+v                     1 2
+basic_do = do
+v
+  foo <- blah blah blah
+v 1
+  bar <- blah blah
+v 1
+         blah -- manual correction
+v 2      1
+         blah -- manual correction
+v 2      1
+  sideeffect
+v 1      2
+  sideeffect' blah
+v 1      2
+  let baz = blah blah
+v 2   1  3
+            blah -- manual correction
+v 2   3  4  1
+      gaz = blah
+v 2   1  3  4
+      haz =
+v 2   1  3  4
+        blah
+v 2   3 14  5
+  pure faz -- manual correction
+v 1   2 34  5
+
+v 1   2 34  5
+nested_do = -- manual correction
+v
+  do foo <- blah
+v    1
+     do bar <- blah -- same level as foo
+v    2  1
+        baz -- same level as bar
+v    2  1
+
+v    1  2
+nested_where a b = foo a b
+v
+  where -- TODO 2
+v
+    foo = bar baz -- indented
+v   1
+    baz = blah blah -- same level as foo
+v   1
+      where -- manual correction
+v   1
+        gaz a = blah -- indented
+v   2   1
+        faz = blah -- same level as gaz
+v   2   1
+
+v   1   2
+-- TODO case statements
+v   1   2
+-- TODO let / in
+v   1   2
+
+v   1   2
+-- TODO coproduct definitions, the | should align with =
+v   1   2
+
+v   1   2
+-- TODO lists, records, tuples
+v   1   2
+
+v   1   2
+-- TODO long type signatures vs definitions
+v   1   2
\ No newline at end of file



reply via email to

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