[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/haskell-tng-mode a830fcb 135/385: reindention test
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/haskell-tng-mode a830fcb 135/385: reindention test |
Date: |
Tue, 5 Oct 2021 23:59:16 -0400 (EDT) |
branch: elpa/haskell-tng-mode
commit a830fcbc12ca37b200cc9f102103c0f9b3012539
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>
reindention test
---
haskell-tng-smie.el | 15 ++-
test/haskell-tng-indent-test.el | 80 ++++++-----
test/src/layout.hs.reindent | 38 ++++++
test/src/medley.hs.reindent | 292 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 386 insertions(+), 39 deletions(-)
diff --git a/haskell-tng-smie.el b/haskell-tng-smie.el
index 0d10bc3..06067fe 100644
--- a/haskell-tng-smie.el
+++ b/haskell-tng-smie.el
@@ -106,6 +106,13 @@ information, to aid in the creation of new rules."
(haskell-tng-smie:debug #'indent-for-tab-command))
;;
https://www.gnu.org/software/emacs/manual/html_mono/elisp.html#SMIE-Indentation
+;;
+;; The concept of "virtual indentation" can be confusing. This function is
+;; called multiple times for a single indentation command. `:before' does not
+;; always mean that we are indenting the next token, but could be a request for
+;; the virtual indentation of the previous token. For example, consider a `do'
+;; block, we will get an `:after' and a `:before' on the `do' which may be at
+;; column 20 but virtually at column 0.
(defun haskell-tng-smie:rules (method arg)
;; see docs for `smie-rules-function'
(when haskell-tng-smie:debug
@@ -117,9 +124,7 @@ information, to aid in the creation of new rules."
('basic smie-indent-basic)
))
- ;; TODO implement more indentation rules
-
- ;; 1. when writing do notation, should we align with the last do line or
aim for continuations? sync with alts
+ ;; FIXME implement the core indentation rules
(:after
(pcase arg
("where"
@@ -152,8 +157,10 @@ information, to aid in the creation of new rules."
;; TAB+TAB and RETURN+TAB
(eq this-command last-command)
(member last-command haskell-tng-smie:return)))
- ;; avoid recalculating the prime indentation level
+ ;; avoid recalculating the prime indentation level (application of smie
rules)
(let ((prime (current-column)))
+ ;; Note that reindenting loses the original indentation level. This is
+ ;; by design: users can always undo / revert.
(setq haskell-tng-smie:indentations
(append
;; TODO backtab, does the cycle in reverse (use a local flag)
diff --git a/test/haskell-tng-indent-test.el b/test/haskell-tng-indent-test.el
index d8d6d14..08da3b0 100644
--- a/test/haskell-tng-indent-test.el
+++ b/test/haskell-tng-indent-test.el
@@ -12,7 +12,6 @@
(require 'haskell-tng-testutils
"test/haskell-tng-testutils.el")
-(ert-deftest haskell-tng-indent-file-tests ()
;; Three indentation regression tests are possible:
;;
;; 1. newline-and-indent with the rest of the file deleted (append)
@@ -26,75 +25,74 @@
;;
;; 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/layout.hs")))
(should (have-expected-newline-indent-insert (testdata "src/medley.hs")))
;; TODO more tests
;;
https://raw.githubusercontent.com/kadena-io/chainweb-node/master/test/Chainweb/Test/TreeDB.hs
-
- ;; FIXME type 3 tests without alternatives
)
-;; TODO enable this test and get it passing, which requires a TAB command that
-;; will insert whitespace and move point to end. Workaround is to use abbrevs
or
-;; yasnippets for things like "import" that have fixed indentations.
-;;
-;; (ert-deftest haskell-tng-indent-custom-tests ()
-;; (with-temp-buffer
-;; (insert-file-contents (testdata "src/medley.hs"))
-;; (haskell-tng-mode)
-;; ;; import TAB should jump to column 17
-;; (goto-char 511)
-;; (ert-simulate-command '(forward-word))
-;; (ert-simulate-command '(indent-for-tab-command))
-;; (ert-simulate-command '(indent-for-tab-command))
-;; (should (equal (point) 528))
-;; ))
+(ert-deftest haskell-tng-reindent-file-tests ()
+ (should (have-expected-reindent-insert (testdata "src/layout.hs")))
+ (should (have-expected-reindent-insert (testdata "src/medley.hs")))
+
+ ;; FIXME a test file specifically for common indentation situations to
+ ;; define a spec.
+ )
(defun current-line-string ()
(buffer-substring-no-properties
(line-beginning-position)
(- (line-beginning-position 2) 1)))
-(defun haskell-tng-indent-test:newline-indent-insert ()
+(defun haskell-tng-indent-test:indent-insert (return-mode)
(let (indents)
(while (not (eobp))
- (end-of-line)
;; the command loop is necessary for this/last-command
(cl-flet ((RET ()
+ (end-of-line)
(ert-simulate-command '(newline-and-indent))
(current-column))
(TAB ()
(ert-simulate-command '(indent-for-tab-command))
(current-column)))
- (let ((line (current-line-string))
- (prime (RET))
+ (let ((orig (current-indentation))
+ (line (current-line-string))
+ (prime (if return-mode (RET) (TAB)))
alts)
(while (and (TAB)
(not (eq (current-column) prime))
(not (member (current-column) alts)))
(push (current-column) alts))
- (push `(,line . (,prime . ,(reverse alts))) indents)
- ;; unfortunately killing resets this-command so we don't test double
+ (push `(, return-mode ,line . (,prime . ,(reverse alts))) indents)
+ ;; unfortunately killing resets this-command so we can't test double
;; newline insertions, which could accidentally trigger alts only.
- (kill-whole-line))))
+ (if return-mode
+ (kill-whole-line)
+ (indent-line-to orig)
+ (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 (LINE . (INDENT . ALTS)) where LINE
-is the string line of code before the indentation, INDENT is the
-integer suggested next line indentation column and ALTS is a list
-of integer alternative indentations."
+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 the integer suggested next line indentation column and
+ALTS is a list of integer alternative indentations."
(s-join "\n" (-flatten
(-map #'haskell-tng-indent-test:indent-to-string indents))))
(defun haskell-tng-indent-test:indent-to-string (indent)
- (let* ((line (car indent))
- (prime (cadr indent))
- (alts (cddr indent))
- (widest (-max (cdr indent)))
+ (let* ((return-mode (car indent))
+ (line (cadr indent))
+ (prime (caddr indent))
+ (alts (cdddr indent))
+ (widest (-max (cddr indent)))
repr)
(--dotimes (+ 1 widest)
(push
@@ -107,7 +105,10 @@ of integer alternative indentations."
".")))
(t " "))
repr))
- (list line (s-join "" (reverse repr)))))
+ (let ((indents (s-join "" (reverse repr))))
+ (if return-mode
+ (list line indents)
+ (list indents line)))))
(defun have-expected-newline-indent-insert (file)
(haskell-tng-testutils:assert-file-contents
@@ -115,7 +116,16 @@ of integer alternative indentations."
#'haskell-tng-mode
(lambda ()
(haskell-tng-indent-test:indents-to-string
- (haskell-tng-indent-test:newline-indent-insert)))
+ (haskell-tng-indent-test:indent-insert t)))
"insert.indent"))
+(defun have-expected-reindent-insert (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)))
+ "reindent"))
+
;;; haskell-tng-indent-test.el ends here
diff --git a/test/src/layout.hs.reindent b/test/src/layout.hs.reindent
new file mode 100644
index 0000000..d690dfc
--- /dev/null
+++ b/test/src/layout.hs.reindent
@@ -0,0 +1,38 @@
+v
+-- Figure 2.1 from the Haskell2010 report
+v 1
+module AStack( Stack, push, pop, top, size ) where
+2 v 1 3
+data Stack a = Empty
+1 2 v
+ | MkStack a (Stack a)
+v 1 2
+
+v 1 2
+push :: a -> Stack a -> Stack a
+v 1
+push x s = MkStack x s
+v 1
+
+v 1
+size :: Stack a -> Int
+v 2 1
+size s = length (stkToLst s) where
+2 3 1 v 4
+ stkToLst Empty = []
+v 1 2 3
+ stkToLst (MkStack x s) = x:xs where xs = stkToLst s
+1 2 3 4 v
+
+v 1 2
+pop :: Stack a -> (a, Stack a)
+v 1
+pop (MkStack x s)
+v 1
+ = (x, case s of r -> i r where i x = x) -- (pop Empty) is an error
+v 1 2 3
+
+v 1
+top :: Stack a -> a
+v 1
+top (MkStack x s) = x -- (top Empty) is an error
\ No newline at end of file
diff --git a/test/src/medley.hs.reindent b/test/src/medley.hs.reindent
new file mode 100644
index 0000000..481b99b
--- /dev/null
+++ b/test/src/medley.hs.reindent
@@ -0,0 +1,292 @@
+v
+{-# LANGUAGE OverloadedStrings #-}
+v 1
+{-# LANGUAGE ScopedTypeVariables #-}
+v 1
+
+v 1
+-- | This file is a medley of various constructs and some corner cases
+v 1
+module Foo.Bar.Main
+2 1 v
+ ( Wibble(..), Wobble(Wobb, (!!!)), Woo
+2 1 v
+ -- * Operations
+2 1 v
+ , getFooByBar, getWibbleByWobble
+1 v 2
+ , module Bloo.Foo
+1 v 2
+) where
+v 1 2
+
+1 v
+import Control.Applicative (many, optional, pure, (<*>), (<|>))
+v 1
+import Data.Foldable (traverse_)
+v 1
+import Data.Functor ((<$>))
+v 1
+import Data.List (intercalate)
+v 1
+import Data.Monoid ((<>))
+v 1
+import qualified Options.Monad
+v 1
+import qualified Options.Applicative as Opts
+v 21
+import qualified Options.Divisible -- wibble (wobble)
+1 2 v
+ as Div
+v 1 2
+import qualified ProfFile.App hiding (as, hiding, qualified)
+v 1
+import ProfFile.App (as, hiding, qualified)
+v 1
+import ProfFile.App hiding (as, hiding, qualified)
+v 1
+import qualified ProfFile.App (as, hiding, qualified)
+v 2 1
+import System.Exit (ExitCode (..), exitFailure, qualified,
+1 2 v
+ Typey,
+1 v 2
+ wibble,
+1 v 2
+ Wibble)
+v 1 2
+import System.FilePath (replaceExtension, Foo(Bar, (:<)))
+v 2 1
+import System.IO (IOMode (..), hClose, hGetContents,
+1 2 v
+ hPutStr, hPutStrLn, openFile, stderr,
+1 v 2
+ stdout, MoarTypey)
+v 1 2
+import System.Process (CreateProcess (..), StdStream (..),
+1 2 v
+ createProcess, proc, waitForProcess)
+1 v 2 3
+
+v 1 2
+-- some chars that should be propertized
+v 1 2
+chars = ['c', '\n', '\'']
+v 1
+
+v 1
+strings = ["", "\"\"", "\n\\ ", "\\"]
+v 1
+-- knownWrongEscape = "foo"\\"bar"
+v 1
+
+v 2 1
+multiline1 = "\
+1 2 v 3
+ \ "
+3 v 425 1
+multiline2 = "\
+1 2 v 3
+ \"
+2 v 3 4 1
+
+v 1 2
+difficult = foo' 'a' 2
+v 1
+
+v 1
+foo = "wobble (wibble)"
+v 1
+
+v 1
+class Get a s where
+1 2 v 3
+ get :: Set s -> a
+1 v 2 3
+
+v 1
+instance {-# OVERLAPS #-} Get a (a ': s) where
+1 2 v 3
+ get (Ext a _) = a
+1 v 2 3
+
+v 1
+instance {-# OVERLAPPABLE #-} Get a s => Get a (b ': s) where
+1 2 v 3
+ get (Ext _ xs) = get xs
+1 v 2 3
+
+v 1
+data Options = Options
+2 1 v
+ { optionsReportType :: ReportType
+2 1 v
+ , optionsProfFile :: Maybe FilePath
+1 v 2
+ , optionsOutputFile :: Maybe FilePath
+1 v 2
+ , optionsFlamegraphFlags :: [String]
+1 v 2
+ } deriving (Eq, Show)
+v 1 2
+
+v 1
+class (Eq a) => Ord a where
+2 1 v 3
+ (<), (<=), (>=), (>) :: a -> a -> Bool
+v 1 2 3
+ max @Foo, min :: a -> a -> a
+1 v 2 3
+
+v 1
+instance (Eq a) => Eq (Tree a) where
+2 1 v 3
+ Leaf a == Leaf b = a == b
+v 1 2 3
+ (Branch l1 r1) == (Branch l2 r2) = (l1==l2) && (r1==r2)
+v 1 2 3
+ _ == _ = False
+1 v 2 3
+
+v 2 1
+data ReportType = Alloc -- ^ Report allocations, percent
+2 3 1 v
+ | Entries -- ^ Report entries, number
+1 v 2
+ | Time -- ^ Report time spent in closure, percent
+1 v 2
+ | Ticks -- ^ Report ticks, number
+1 v 2
+ | Bytes -- ^ Report bytes allocated, number
+1 v 2
+ deriving (Eq, Show)
+v 1 2
+
+v 1 2
+type family G a where
+2 1 v 3
+ G Int = Bool
+v 1 2 3
+ G a = Char
+1 v 2 3
+
+v 1
+data Flobble = Flobble
+2 1 v
+ deriving (Eq) via (NonNegative (Large Int))
+1 v 2
+ deriving stock (Floo)
+1 v 2
+ deriving anyclass (WibblyWoo, OtherlyWoo)
+v 1 2
+
+v 1
+newtype Flobby = Flobby
+v 1
+
+v12
+foo ::
+1 2 v
+ Wibble -- wibble
+v2 31
+ -> Wobble -- wobble
+v2 1 3
+ -> Wobble -- wobble
+v2 1 3
+ -> Wobble -- wobble
+v2 1 3
+ -> (wob :: Wobble)
+v2 1 3
+ -> (Wobble -- wobble
+12 3 4 v
+ a b c)
+v1 2 3
+
+v 1 2
+(foo :: (Wibble Wobble)) foo
+v 1 2
+
+v 21
+newtype TestApp
+2 31 v
+ (logger :: TestLogger)
+1 v 2
+ (scribe :: TestScribe)
+1 v 2
+ config
+1 v 2
+ a
+v 1 2
+ = TestApp a
+v 1 2
+
+v 12
+optionsParser :: Opts.Parser Options
+v 1
+optionsParser = Options
+2 3 1 v
+ <$> (Opts.flag' Alloc (Opts.long "alloc" <> Opts.help "wibble")
+2 3 4 1 v
+ <|> Opts.flag' Entries (Opts.long "entry" <> Opts.help "wobble")
+2 1 v 3
+ <|> Opts.flag' Bytes (Opts.long "bytes" <> Opts.help "i'm a fish"))
+2 v 314
+ <*> optional
+2 3 4 5v 1
+ (Opts.strArgument
+2 3 45 61 v
+ (Opts.metavar "MY-FILE" <>
+1 2 34 5 6 v
+ Opts.help "meh"))
+1 2 v34 56 7
+
+v 1 2
+type PhantomThing
+v 1
+
+v 2 1
+type SomeApi =
+2 v 1
+ "thing" :> Capture "bar" Index :> QueryParam "wibble" Text
+2 3 4 v 1
+ :> QueryParam "wobble" Natural
+1 2 v 3
+ :> Header TracingHeader
TracingId
+1 2 v 3
+ :> ThingHeader
+2 1 3 v 4
+ :> Get '[JSON] (The ReadResult)
+2 3 1 v 4
+ :<|> "thing" :> ReqBody '[JSON] Request
+2 v 3 4 1 5
+ :> Header TracingHeader TracingId
+1 2 3 v 4 5
+ :> SpecialHeader
+1 2 3 v 4 5
+ :> Post '[JSON] (The Response)
+v 1 2 3 4 5
+
+v 1 2
+deriving instance FromJSONKey StateName
+v 1
+deriving anyclass instance FromJSON Base
+v 1
+deriving newtype instance FromJSON Treble
+v 1
+
+v 1
+foo = do
+2 1 v 3
+ bar :: Wibble <- baz
+v 2 3 1
+ where baz = _
+1 2 3 v
+ -- checking that comments are ignored in layout
+1 2 3 v
+ -- and that a starting syntax entry is ok
+v 1 2
+ (+) = _
+1 2 3 4 5 v
+
+v 1 2
+test = 1 `shouldBe` 1
\ No newline at end of file
- [nongnu] elpa/haskell-tng-mode bfc3841 193/385: remove bind-key dependency, (continued)
- [nongnu] elpa/haskell-tng-mode bfc3841 193/385: remove bind-key dependency, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 6acba95 206/385: better insertion indentation on toplevels, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 9bfc6bf 215/385: really basic imenu, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode f648cf9 212/385: fallback to current directory (e.g. for cabal scripts), ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 5bdf688 211/385: better in-line indentation of parens, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 1cdf901 120/385: better escape syntax detection, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode c40c6e6 125/385: fix explicit export fontification bug, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 82312a2 126/385: working compilation matchers, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 794c80b 131/385: better indentation alts, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode d43fd73 141/385: more efficient indentation 'insert test, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode a830fcb 135/385: reindention test,
ELPA Syncer <=
- [nongnu] elpa/haskell-tng-mode aa2a0ad 146/385: prefer --enable-tests, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode a754020 144/385: indent alts will suggest based on previous <- lines, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 9023dc6 164/385: don't rely on line-based indentation rules, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode fdaaf38 148/385: indent after "in", ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode e2c60a9 161/385: prep for records, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 8e4f438 184/385: don't continue indenting one liner types, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 5251477 186/385: thots, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 41f1ad5 191/385: document fast-tags, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 4ec6259 185/385: prefer the lexer, ELPA Syncer, 2021/10/06
- [nongnu] elpa/haskell-tng-mode 1475f31 196/385: workaround bad indentation at the end of files, ELPA Syncer, 2021/10/06