@@ -1,7 +1,7 @@
11module Format (format) where
22
33import Prelude
4−import Data.Array (any, foldl)
4+import Data.Array (any, foldl, intercalate, intersperse)
55import Data.Array as Array
66import Data.Array.NonEmpty as NE
77import Data.Array.NonEmpty.Internal (NonEmptyArray)
@@ -11,6 +11,7 @@ import Data.Maybe (Maybe(..), fromMaybe, maybe)
1111import Data.Monoid.Additive (Additive(..))
1212import Data.Newtype (ala)
1313import Data.Semigroup.Foldable (intercalateMap)
14+import Data.String (Pattern(..), split)
1415import Data.String.CodeUnits (lastIndexOf)
1516import Data.String.CodeUnits as String
1617import Data.Tuple (fst, snd)
@@ -40,6 +41,7 @@ isPrecededByBlankLines ∷ ∀ t. TokensOf t ⇒ t → Boolean
4041isPrecededByBlankLines x =
4142 precedingEmptyLines (unsafeFirstTokenOf x).leadingComments > 1
4243
44+unsafeFirstTokenOf ∷ ∀ a. TokensOf a ⇒ a → CST.SourceToken
4345unsafeFirstTokenOf x = case TokensOf.head (tokensOf x) of
4446 Just sourceToken → sourceToken
4547 Nothing → unsafeCrashWith "Unexpectedly got no tokens"
@@ -57,6 +59,14 @@ hasNonWhitespaceTrailingComment =
5759 CST.Comment _ → true
5860 _ → false
5961
62+hasNonWhitespaceLeadingComment ∷ CST.SourceToken → Boolean
63+hasNonWhitespaceLeadingComment =
64+ _.leadingComments
65+ >>> any case _ of
66+ CST.Comment "" → false -- Don't think this should happen
67+ CST.Comment _ → true
68+ _ → false
69+
6070commentIsSpaceOrLineFeed ∷ ∀ c. CST.Comment c → Boolean
6171commentIsSpaceOrLineFeed = case _ of
6272 CST.Space _ → true
@@ -423,7 +433,8 @@ formatDeclaration settings@{ indentation } indent followedByBlankLines declarati
423433 <> space
424434 <> formatLabeledNameType settings indent labeled
425435
426− CST.DeclSignature labeled → formatLabeledNameType settings indent labeled
436+ CST.DeclSignature labeled →
437+ formatLabeledNameType settings indent labeled
427438
428439 CST.DeclValue valueBindingFields →
429440 formatValueBindingFields settings indent valueBindingFields
@@ -637,6 +648,7 @@ formatBinder ∷
637648 CST.Binder Void →
638649 String
639650formatBinder settings@{ indentation } indent' binder = case binder of
651+
640652 CST.BinderArray delimited →
641653 formatArray
642654 settings
@@ -644,10 +656,13 @@ formatBinder settings@{ indentation } indent' binder = case binder of
644656 indent'
645657 (formatBinder settings indent')
646658 delimited
659+
647660 CST.BinderBoolean boolean _ →
648661 formatSourceToken settings indent' blank boolean
662+
649663 CST.BinderChar char _ →
650664 formatSourceToken settings indent' blank char
665+
651666 CST.BinderConstructor name' binders → do
652667 let
653668 prefix = case singleOrMultiline binder of
@@ -657,14 +672,17 @@ formatBinder settings@{ indentation } indent' binder = case binder of
657672 <> foldMap
658673 (\binder' → prefix <> formatBinder settings indent' binder')
659674 binders
675+
660676 -- with @ sign
661677 CST.BinderNamed name' at binder' →
662678 formatName settings indent' blank name'
663679 <> formatSourceToken settings indent' blank at
664680 <> formatBinder settings indent' binder'
681+
665682 CST.BinderNumber negative number _ →
666683 foldMap (formatSourceToken settings indent' blank) negative
667684 <> formatSourceToken settings indent' blank number
685+
668686 CST.BinderOp binder1 binders →
669687 formatBinder (settings { indentation = indent' }) prefix binder1
670688 <> foldMap formatNamedBinder binders
@@ -677,8 +695,10 @@ formatBinder settings@{ indentation } indent' binder = case binder of
677695 formatQualifiedName settings indent' prefix name
678696 <> prefix
679697 <> formatBinder settings indent binder
698+
680699 CST.BinderParens wrapped → do
681700 formatParens lines settings indent' (formatBinder settings) wrapped
701+
682702 CST.BinderRecord delimited → do
683703 formatRecord
684704 settings
@@ -689,8 +709,10 @@ formatBinder settings@{ indentation } indent' binder = case binder of
689709 (formatBinder settings)
690710 )
691711 delimited
712+
692713 CST.BinderString string _ → do
693714 formatSourceToken settings indent' blank string
715+
694716 CST.BinderTyped binder' colons type'' → do
695717 let
696718 indentTrick = indent' <> indentation
@@ -701,13 +723,18 @@ formatBinder settings@{ indentation } indent' binder = case binder of
701723 <> formatSourceToken settings indent' space colons
702724 <> prefix
703725 <> formatType settings indent lines type''
726+
704727 CST.BinderVar name → formatName settings indent' blank name
728+
705729 CST.BinderWildcard wildcard →
706730 formatSourceToken settings indent' blank wildcard
731+
707732 CST.BinderInt negative int _ →
708733 foldMap (formatSourceToken settings indent' blank) negative
709734 <> formatSourceToken settings indent' blank int
735+
710736 CST.BinderError x → absurd x
737+
711738 where
712739 lines = singleOrMultiline binder
713740
@@ -729,7 +756,7 @@ formatGuarded settings@{ indentation } indent' = case _ of
729756 formatSourceToken settings indent' space separator
730757 <> formatWhere settings indent' whereToken
731758
732−-- | This is also regular expressions that *can* have a where
759+-- | This is also code blocks that *can* have a where
733760formatWhere ∷
734761 Settings →
735762 Indent →
@@ -969,33 +996,47 @@ formatExpr settings@{ indentation } indent'' expr'' = case expr'' of
969996
970997 CST.ExprOp expr1 expressions → do
971998 let
972− indent /\ indent' /\ prefix = case lines of
973− MultipleLines → (indent'' <> indentation <> indentation) /\ (indent'' <> indentation) /\ (newline <> indent'' <> indentation)
974− SingleLine → (indent'' <> indentation) /\ indent'' /\ space
999+ indent /\ indent' = case lines of
1000+ MultipleLines → (indent'' <> indentation <> indentation) /\ (indent'' <> indentation)
1001+ SingleLine → (indent'' <> indentation) /\ indent''
1002+ operatorPrefix = case lines of
1003+ MultipleLines → (newline <> indent'' <> indentation)
1004+ SingleLine → space
9751005 formatExpr settings indent'' expr1
9761006 <> foldMap
977− ( \(op /\ expr) → do
1007+ ( \(operator /\ expr) → do
9781008 let
9791009 -- To preserve alignment of brackets, commas, etc.
9801010 -- we need to add a newline if there's a multiline record,
9811011 -- array, etc.
982− prefix' = case expr of
1012+ expressionPrefix = case expr of
9831013 CST.ExprRecord _ → case singleOrMultiline expr of
9841014 MultipleLines →
9851015 (newline <> indent'' <> indentation <> indentation)
9861016 SingleLine → space
1017+
9871018 CST.ExprRecordUpdate _ _ → case singleOrMultiline expr of
9881019 MultipleLines →
9891020 (newline <> indent'' <> indentation <> indentation)
9901021 SingleLine → space
1022+
9911023 CST.ExprArray _ → case singleOrMultiline expr of
9921024 MultipleLines →
9931025 (newline <> indent'' <> indentation <> indentation)
9941026 SingleLine → space
995− _ → space
996− prefix
997− <> formatQualifiedName settings indent' blank op
998− <> prefix'
1027+
1028+ _ →
1029+ space
1030+
1031+ operatorSuffix = do
1032+ if hasNonWhitespaceTrailingComment (unsafeFirstTokenOf operator) then
1033+ newline <> indent' <> space
1034+ else
1035+ blank
1036+ operatorPrefix
1037+ <> formatQualifiedName settings indent' blank operator
1038+ <> operatorSuffix
1039+ <> expressionPrefix
9991040 <> formatExpr settings indent expr
10001041 )
10011042 expressions
@@ -1906,8 +1947,7 @@ formatCommentLeading ∷
19061947 CST.Comment CST.LineFeed →
19071948 String
19081949formatCommentLeading indent prefix = case _ of
1909− CST.Comment comment → do
1910− prefix <> comment <> newline <> indent
1950+ CST.Comment comment → prefix <> comment <> newline <> indent
19111951 CST.Line _ _ → blank
19121952 CST.Space _ → blank
19131953
@@ -1942,17 +1982,17 @@ formatCommentsTrailingModule ∷
19421982 String
19431983formatCommentsTrailingModule commentsTrailing' = do
19441984 let
1945− comments = map formatComment commentsTrailing'
1946− case NE.fromArray (Array.catMaybes comments) of
1985+ formattedComments = map formatComment commentsTrailing'
1986+ case NE.fromArray (Array.catMaybes formattedComments) of
19471987 Nothing → blank
19481988 Just comments →
19491989 newline <> fold (NE.intersperse newline comments) <> newline
1950−
1951−formatComment ∷ ∀ lf. CST.Comment lf → Maybe String
1952−formatComment = case _ of
1953− CST.Comment comment → Just comment
1954− CST.Space _ → Nothing
1955− CST.Line _ _ → Nothing
1990+ where
1991+ formatComment ∷ ∀ lf. CST.Comment lf → Maybe String
1992+ formatComment = case _ of
1993+ CST.Comment comment → Just comment
1994+ CST.Space _ → Nothing
1995+ CST.Line _ _ → Nothing
19561996
19571997formatWrapped ∷
19581998 ∀ a.