diff --git a/Makefile b/Makefile index 4bfef7f..33a6dfa 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ ELFILES = \ purescript-decl-scan.el \ purescript-yas.el \ tests/purescript-sort-imports-tests.el \ + tests/purescript-indentation-tests.el \ tests/purescript-str-tests.el ELCFILES = $(ELFILES:.el=.elc) @@ -46,6 +47,7 @@ compile: $(ELCFILES) test: compile @$(BATCH) -l tests/purescript-sort-imports-tests.elc \ -l tests/purescript-str-tests.elc \ + -l tests/purescript-indentation-tests.elc \ -f ert-run-tests-batch-and-exit @echo "tests passed!" diff --git a/purescript-indentation.el b/purescript-indentation.el index cea6137..33bf8b2 100644 --- a/purescript-indentation.el +++ b/purescript-indentation.el @@ -111,13 +111,6 @@ :group 'purescript-indentation) -;; Avoid a global bogus definition (which the original run-time -;; `defun' made), and support Emacs 21 without the syntax.el add-on. -(eval-when-compile - (unless (fboundp 'syntax-ppss) - (defsubst syntax-ppss (&rest pos) - (parse-partial-sexp (point-min) (or pos (point)))))) - (defconst purescript-indentation-mode-map (let ((keymap (make-sparse-keymap))) (define-key keymap [?\r] 'purescript-newline-and-indent) diff --git a/tests/purescript-indentation-tests.el b/tests/purescript-indentation-tests.el new file mode 100644 index 0000000..f61c90d --- /dev/null +++ b/tests/purescript-indentation-tests.el @@ -0,0 +1,240 @@ +;;; purescript-indentation-tests.el --- Unit tests for purescript indentation -*- lexical-binding: t -*- + +;; Copyright (c) 2025 Konstantin Kharlamov. All rights reserved. + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Code: + +(require 'ert) +(require 'purescript-mode) +(require 'purescript-indentation) + +(defun purescript-test-indentation (before after &optional start-line) + (with-temp-buffer + (insert before) + (purescript-mode) + (turn-on-purescript-indentation) + (indent-region (if start-line start-line (point-min)) + (point-max)) + (should (string= after (buffer-string))))) + +(ert-deftest newtype-comma-first () + (purescript-test-indentation " +newtype Foo = Foo { field1 :: MyType +, field2 :: Int +, field3 :: HashMap ParType Foo }" + +" +newtype Foo = Foo { field1 :: MyType + , field2 :: Int + , field3 :: HashMap ParType Foo }")) + +(ert-deftest newtype-comma-end () + (purescript-test-indentation " +newtype Foo = Foo { field1 :: MyType, +field2 :: Int, +field3 :: HashMap ParType Foo }" + +" +newtype Foo = Foo { field1 :: MyType, + field2 :: Int, + field3 :: HashMap ParType Foo }")) + +(ert-deftest data-bar-first () + (purescript-test-indentation " +data Foo = Foo1 Bar +| Foo2 Bar2 +| Foo3 Unit" + +" +data Foo = Foo1 Bar + | Foo2 Bar2 + | Foo3 Unit")) + +(ert-deftest data-bar-end () + (purescript-test-indentation " +data Foo = Foo1 Bar | +Foo2 Bar2 | +Foo3 Unit" + +" +data Foo = Foo1 Bar | + Foo2 Bar2 | + Foo3 Unit")) + +(ert-deftest imports-zero-indented () + :expected-result :failed + (purescript-test-indentation " +module MyModule where + +import Prelude + + import Data.Array (many) + import Data.Array as Array + import Data.Either (Either(..))" + +" +module MyModule where + +import Prelude + +import Data.Array (many) +import Data.Array as Array +import Data.Either (Either(..))")) + +(ert-deftest imports-indented-forward () + "PureScript allows for imports to have indentation, but the + indentation must be the same. In this test we skip first indented + import, and test that further lines inherit indentation level." + :expected-result :failed + (purescript-test-indentation " +module MyModule where + + import Prelude + +import Data.Array (many) +import Data.Array as Array +import Data.Either (Either(..))" + +" +module MyModule where + + import Prelude + + import Data.Array (many) + import Data.Array as Array + import Data.Either (Either(..))" + 6)) + +(ert-deftest imports-qualified-newline-comma-first () + :expected-result :failed + (purescript-test-indentation " +import Data.List.NonEmpty (NonEmptyList) +import Data.Maybe (Maybe(..) +, fromMaybe)" + +" +import Data.List.NonEmpty (NonEmptyList) +import Data.Maybe ( Maybe(..) + , fromMaybe)")) + +(ert-deftest imports-qualified-newline-comma-end () + :expected-result :failed + (purescript-test-indentation " +import Data.List.NonEmpty (NonEmptyList) +import Data.Maybe (Maybe(..), +fromMaybe)" + +" +import Data.List.NonEmpty (NonEmptyList) +import Data.Maybe (Maybe(..), + fromMaybe)")) + +(ert-deftest do-impl () + (purescript-test-indentation " +main = do +pure unit" + +" +main = do + pure unit")) + +(ert-deftest let-bindings () + :expected-result :failed + (purescript-test-indentation " +main = do + let foo = 1 + bar = 2 + let + buzz = 1 + fuzz = 2 +pure unit" + +" +main = do + let foo = 1 + bar = 2 + let + buzz = 1 + fuzz = 2 + pure unit")) + +(ert-deftest module-exports-list () + :expected-result :failed + (purescript-test-indentation " +module MyModule ( class A +, b, c +, d) where" + +" +module MyModule ( class A + , b, c + , d) where")) + +(ert-deftest module-exports-next-line () + "Parentheses should get indented to the mode indentation size" + :expected-result :failed + (purescript-test-indentation " +module MyModule + (class A, b, c, d) where" + +" +module MyModule + (class A, b, c, d) where")) + +(ert-deftest keyword-record-values () + "PureScript allows keywords to be part of a Record declaration" + :expected-result :failed + (purescript-test-indentation " +type MyRec = { data :: Number +, where :: Number +, instance :: Number +}" + +" +type MyRec = { data :: Number + , where :: Number + , instance :: Number + }")) + +(ert-deftest func-with-do () + :expected-result :failed + (purescript-test-indentation " +foo :: Foo +foo = do + pure unit" + +" +foo :: Foo +foo = do + pure unit")) + +(ert-deftest do-bindings () + :expected-result :failed + (purescript-test-indentation " +foo :: Foo +foo = do +_ <- something +identifier :: Array String <- function call +_ <- another call +pure unit" + +" +foo :: Foo +foo = do + _ <- something + identifier :: Array String <- function call + _ <- another call + pure unit"))