Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use shared dependency for rendering #820

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
868ca08
Add Box.BlockAdapter
avh4 Apr 2, 2023
a7989ab
Convert Render.ElmStructure to use Box.BlockAdapter (1)
avh4 Apr 2, 2023
4b3ba04
Convert Render.ElmStructure to use Box.BlockAdapter (2)
avh4 Apr 2, 2023
6db8f73
Convert Render.ElmStructure to use Box.BlockAdapter (3)
avh4 Apr 2, 2023
c969775
Convert Render.ElmStructure to use Box.BlockAdapter (4)
avh4 Apr 2, 2023
b58b019
Convert Render.ElmStructure to use Box.BlockAdapter (5)
avh4 Apr 2, 2023
8e3d78b
Render.Box: use Block type alias instead of Box
avh4 Apr 2, 2023
137aee5
Render.Box.parens: use Box.BlockAdapter
avh4 Apr 2, 2023
dcb3d0e
Render.Box: fix warnings
avh4 Apr 2, 2023
a7c9686
Render.Box.formatModuleLine_0_16: use Box.BlockAdapter
avh4 Apr 2, 2023
a4b451e
Render.Box.formatModuleLine: use Box.BlockAdapter
avh4 Apr 2, 2023
85339f8
Allow Lines to join when the last is MustBreak
avh4 Apr 2, 2023
450436e
Remove uses of Box.mustBreak
avh4 Apr 3, 2023
378f9f9
Render.Box.formatDeclaration.Datatype: use Box.BlockAdapter
avh4 Apr 3, 2023
6510959
Render.Box.formatImport: use Box.BlockAdapter
avh4 Apr 3, 2023
469e001
Render.Box.formatVarValue: use Box.BlockAdapter
avh4 Apr 3, 2023
42de1ab
ElmStructure: use NonEmpty, and clean up naming
avh4 Apr 3, 2023
1a9c5c3
Render.Box.formatDeclaration.Fixity_until_0_18: use Box.BlockAdapter
avh4 Apr 3, 2023
1851657
Render.Box.formatPattern.Alias: use Box.BlockAdapter
avh4 Apr 3, 2023
172a5ba
Render.Box.formatExpression.Lambda: use Box.BlockAdapter
avh4 Apr 3, 2023
f9bb4b0
Render.Box.formatExpression.If: use Box.BlockAdapter
avh4 Apr 3, 2023
6a78f32
Render.Box.formatExpression.Case: use Box.BlockAdapter
avh4 Apr 3, 2023
b3f9b0a
Render.Box.formatUnit: use Box.BlockAdapter
avh4 Apr 3, 2023
045f80b
Remove unused code
avh4 Apr 3, 2023
c09b429
Render.Box: use Box.BlockAdapter for functions that match those in Box
avh4 Apr 3, 2023
413547d
Render.Box: Remove use of Box.stack1
avh4 Apr 3, 2023
f46685b
Render.Box: Remove use of Box.stack'
avh4 Apr 3, 2023
bfb59c9
Render.Box: Remove use of Box.row
avh4 Apr 3, 2023
0c435b8
Merge remote-tracking branch 'origin/main' into prettyprint-avh4
avh4 Apr 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .hlint.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
- ignore: {name: "Avoid lambda using `infix`"}
- ignore: {name: "Eta reduce"}
- ignore: {name: "Use :"}
- ignore: {name: "Use <$>"}
- ignore: {name: "Use record patterns"}
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## dev

Format changes:
- Multi-line `import` statements are now formatted slightly different (and with less indentation)


## 0.8.7

New features:
Expand Down Expand Up @@ -117,7 +123,7 @@ Bug fixes:
- On Windows, special folders are now correctly skipped when traversing the filesystem
- Initial comments in doc comment code blocks are no longer removed

Syntax changes:
Format changes:
- Infix operator precedence and associativity declarations are now grouped together
- `if` expressions now have blank lines between clauses
- Comments immediately following `import`s now have spacing consistent with other top-level comments
Expand Down Expand Up @@ -161,7 +167,7 @@ Other changes:
Notes:
- Support for Elm 0.16 is deprecated (but is still available with the `--elm-version=0.16` option).

Syntax changes:
Format changes:
- Removed a workaround for an Elm 0.16 compiler bug that added extra parenthesis to qualified type tags in pattern matches
- End-of-line `--` comments are now kept on their original line when appropriate
- `--` comments in the middle of binary operator sequences no longer push the following expression to the next line
Expand Down Expand Up @@ -210,7 +216,7 @@ Bug fixes:

## 0.4.0-alpha

Syntax changes:
Format changes:
- multiline expressions with long infix operators now indent in a more appropriate way
- The `<|` operator is now handled specially and is placed at the end of the preceding line
- line breaks are now allowed before the first arguments to functions
Expand Down
3 changes: 3 additions & 0 deletions elm-format-lib/elm-format-lib.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ library
other-modules:
AST.Helpers
Box
Box.BlockAdapter
Data.Utf8
Elm.String
ElmFormat.AST.BinaryOperatorPrecedence
Expand Down Expand Up @@ -111,6 +112,7 @@ test-suite efl-tests
BoxTest
ElmFormat.AST.BinaryOperatorPrecedenceTest
ElmFormat.ImportInfoTest
ElmFormat.Render.BoxTest
ElmFormat.Render.ElmStructureTest
Parse.ExpressionTest
Parse.HelpersTest
Expand All @@ -126,6 +128,7 @@ test-suite efl-tests
AST.Structure
AST.V0_16
Box
Box.BlockAdapter
CommandLine.InfoFormatter
CommandLine.Program
CommandLine.ResolveFiles
Expand Down
4 changes: 1 addition & 3 deletions elm-format-lib/src/AST/Structure.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}

Expand Down Expand Up @@ -88,7 +86,7 @@ foldReferences ftype fctor fvar =
Parens e -> extract e
ExplicitList terms _ _ -> fold terms
Range left right _ -> extract left <> extract right
Tuple terms _ -> mconcat $ fmap extract terms
Tuple terms _ _ -> fold terms
TupleFunction _ -> mempty
Record _ fields _ _ -> foldMap (extract . _value) fields
Access e _ -> e
Expand Down
8 changes: 5 additions & 3 deletions elm-format-lib/src/AST/V0_16.hs
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,10 @@ data AST typeRef ctorRef varRef (getType :: NodeKind -> Type) (kind :: NodeKind)
-> AST typeRef ctorRef varRef getType 'ExpressionNK

Tuple ::
[C2 'BeforeTerm 'AfterTerm (getType 'ExpressionNK)]
-> Bool
{ terms :: Sequence (getType 'ExpressionNK)
, trailingComments_t :: Comments
, forceMultiline_t :: ForceMultiline
}
-> AST typeRef ctorRef varRef getType 'ExpressionNK
TupleFunction ::
Int -- will be 2 or greater, indicating the number of elements in the tuple
Expand Down Expand Up @@ -579,7 +581,7 @@ mapAll ftyp fctor fvar fast = \case
Parens e -> Parens (fmap fast e)
ExplicitList terms c ml -> ExplicitList (fmap fast terms) c ml
Range left right ml -> Range (fmap fast left) (fmap fast right) ml
Tuple terms ml -> Tuple (fmap (fmap fast) terms) ml
Tuple terms c ml -> Tuple (fmap fast terms) c ml
TupleFunction n -> TupleFunction n
Record base fields c ml -> Record base (fmap (fmap fast) fields) c ml
Access e field -> Access (fast e) field
Expand Down
101 changes: 92 additions & 9 deletions elm-format-lib/src/Box.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
{-# OPTIONS_GHC -Wall #-}
module Box
( Line, identifier, keyword, punc, literal, row, space
, Box(SingleLine, MustBreak), blankLine, line, mustBreak, stack', stack1, andThen
, Box(SingleLine, MustBreak), blankLine, line, mustBreak, stack1, andThen
, isLine, allSingles, lineLength
, indent, prefix, addSuffix
, render
, render, renderLine
, joinMustBreak, prefixOrIndent, rowOrStackForce, rowOrIndentForce
) where

import Elm.Utils ((|>))

import qualified Data.Text as T
import qualified Data.List.NonEmpty as NonEmpty
import Data.List.NonEmpty (NonEmpty(..))
import Data.List (intersperse)


{-
Expand All @@ -25,6 +29,10 @@ data Line
| Row [Line]
| Space
| Tab
deriving (Eq, Show)

instance Semigroup Line where
(<>) a b = Row [ a, b ]


identifier :: String -> Line
Expand Down Expand Up @@ -77,6 +85,7 @@ data Box
= SingleLine Line
| Stack Line Line [Line]
| MustBreak Line
deriving (Eq, Show)


blankLine :: Box
Expand Down Expand Up @@ -163,13 +172,20 @@ destructure b =
(l1, [])


allSingles :: [Box] -> Either [Box] [Line]
allSingles :: [Box] -> Either [Box] ([Line], Bool)
allSingles boxes =
case sequence $ map isLine boxes of
Right lines' ->
Right lines'
_ ->
Left boxes
allSingles' ([], True, False) (reverse boxes)
where
allSingles' (acc, _, isMustBreak) [] =
Right (acc, isMustBreak)
allSingles' (acc, isLast, isMustBreak) (next:rest) =
case next of
SingleLine l -> allSingles' (l:acc, False, isMustBreak) rest
MustBreak l ->
if isLast
then allSingles' (l:acc, False, True) rest
else Left boxes
Stack _ _ _ -> Left boxes


{-
Expand Down Expand Up @@ -205,6 +221,73 @@ addSuffix suffix b =
|> andThen [ line $ row [ last ls, suffix ] ]


joinMustBreak :: Box -> Box -> Box
joinMustBreak inner eol =
case (inner, eol) of
(SingleLine inner', SingleLine eol') ->
SingleLine $ Row [ inner', space, eol' ]
(SingleLine inner', MustBreak eol') ->
MustBreak $ Row [ inner', space, eol' ]
_ ->
stack' inner eol


prefixOrIndent :: Maybe Line -> Line -> Box -> Box
prefixOrIndent joiner a b =
case b of
SingleLine b' ->
line $ join a b'
MustBreak b' ->
mustBreak $ join a b'
_ ->
stack' (line a) (indent b)
where
join a_ b_ =
case joiner of
Nothing -> Row [ a_, b_ ]
Just j -> Row [ a_, j, b_ ]


rowOrStackForce :: Bool -> Maybe Line -> NonEmpty Box -> Box
rowOrStackForce _ _ (single :| []) = single
rowOrStackForce forceMultiline joiner blocks =
case allSingles $ NonEmpty.toList blocks of
Right (lines_, isMustBreak)
| not forceMultiline ->
mkBlock $ mkRow lines_
where
mkBlock =
if isMustBreak
then mustBreak
else line
mkRow =
case joiner of
Just j -> Row . intersperse j
Nothing -> Row
_ ->
stack1 $ NonEmpty.toList blocks


rowOrIndentForce :: Bool -> Maybe Line -> NonEmpty Box -> Box
rowOrIndentForce _ _ (single :| []) = single
rowOrIndentForce forceMultiline joiner blocks@(b1 :| rest) =
case allSingles $ NonEmpty.toList blocks of
Right (lines_, isMustBreak)
| not forceMultiline ->
mkBlock $ mkRow lines_
where
mkBlock =
if isMustBreak
then mustBreak
else line
mkRow =
case joiner of
Just j -> Row . intersperse j
Nothing -> Row
_ ->
stack1 $ b1 : (indent <$> rest)


renderLine :: Int -> Line -> T.Text
renderLine startColumn line' =
case line' of
Expand Down Expand Up @@ -255,7 +338,7 @@ spacesToNextTab startColumn =

tabLength :: Int -> Int
tabLength startColumn =
spacesInTab - (spacesToNextTab startColumn)
spacesInTab - spacesToNextTab startColumn

{-
What happens here is we take a row and start building its contents
Expand Down
80 changes: 80 additions & 0 deletions elm-format-lib/src/Box/BlockAdapter.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
-- | This is a temporary module that mimics the https://hackage.haskell.org/package/prettyprint-avh4
-- API using the current `Box` module.
module Box.BlockAdapter where

import qualified Box
import Data.ByteString (ByteString)
import qualified Data.ByteString.Builder as B
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.Text.Lazy as Lazy
import qualified Data.Text.Lazy.Encoding as Lazy

type Line = Box.Line

space :: Line
space = Box.space

string7 :: String -> Line
string7 = Box.literal

char7 :: Char -> Line
char7 = Box.literal . pure

stringUtf8 :: String -> Line
stringUtf8 = Box.literal

lineFromBuilder :: B.Builder -> Line
lineFromBuilder = Box.literal . Lazy.unpack . Lazy.decodeUtf8 . B.toLazyByteString

commentByteString :: ByteString -> Line
commentByteString = Box.literal . Text.unpack . Text.decodeUtf8

type Block = Box.Box

render :: Block -> B.Builder
render = Text.encodeUtf8Builder . Box.render

blankLine :: Block
blankLine = Box.blankLine

line :: Line -> Block
line = Box.line

mustBreak :: Line -> Block
mustBreak = Box.mustBreak

stack :: NonEmpty Block -> Block
stack = Box.stack1 . NonEmpty.toList

andThen :: [Block] -> Block -> Block
andThen = Box.andThen

indent :: Block -> Block
indent = Box.indent

prefix :: Word -> Line -> Block -> Block
prefix _ = Box.prefix

addSuffix :: Line -> Block -> Block
addSuffix = Box.addSuffix

joinMustBreak :: Block -> Block -> Block
joinMustBreak = Box.joinMustBreak

prefixOrIndent :: Maybe Line -> Line -> Block -> Block
prefixOrIndent = Box.prefixOrIndent

rowOrStack :: Maybe Line -> NonEmpty Block -> Block
rowOrStack = rowOrStackForce False

rowOrStackForce :: Bool -> Maybe Line -> NonEmpty Block -> Block
rowOrStackForce = Box.rowOrStackForce

rowOrIndent :: Maybe Line -> NonEmpty Block -> Block
rowOrIndent = rowOrIndentForce False

rowOrIndentForce :: Bool -> Maybe Line -> NonEmpty Block -> Block
rowOrIndentForce = Box.rowOrIndentForce
9 changes: 5 additions & 4 deletions elm-format-lib/src/ElmFormat/AST/PublicAST/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ instance ToPublicAST 'ExpressionNK where
ListLiteral
((\(C comments a) -> fromRawAST config a) <$> AST.toCommentedList terms)

AST.Tuple terms multiline ->
AST.Tuple terms comments multiline ->
TupleLiteral
(fmap (\(C comments a) -> fromRawAST config a) terms)
((\(C comments a) -> fromRawAST config a) <$> AST.toCommentedList terms)

AST.TupleFunction n | n <= 1 ->
error ("INVALID TUPLE CONSTRUCTOR: " ++ show n)
Expand Down Expand Up @@ -339,8 +339,9 @@ instance FromPublicAST 'ExpressionNK where

TupleLiteral terms ->
AST.Tuple
(C ([], []) . toRawAST <$> terms)
True
(Either.fromRight undefined $ AST.fromCommentedList $ C ([], [], Nothing) . toRawAST <$> terms)
[]
(AST.ForceMultiline True)

RecordLiteral base fields display ->
AST.Record
Expand Down
Loading