Skip to content

Merge in ghc-lib-parser patches #307

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

Closed
wants to merge 136 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
3946b64
Add initial parsing logic for using ghc-lib-parser instead of haskell…
felixmulder Jul 13, 2020
e9f63dc
Add comments parsing capability
felixmulder Jul 14, 2020
4278c11
Restructure interface to be a bit more similar to old stylish
felixmulder Jul 14, 2020
0005bba
Only do module header in stylish step
felixmulder Jul 14, 2020
97a9c57
Print both imports and module header in stylish regular path
felixmulder Jul 14, 2020
dc92f92
Hook up old stylish to new one
felixmulder Jul 15, 2020
03e3e39
Finish implemntation of module header
felixmulder Jul 15, 2020
bf38e53
Print more helpful error message when encountering a parser error
felixmulder Jul 15, 2020
196f445
Implement missing printer for IEThingWith
felixmulder Jul 15, 2020
f2a0cd6
Make sure that imports respect grouping
felixmulder Jul 15, 2020
58424cd
Fix issue where 'where' might be repeated due to not being a part of AST
felixmulder Jul 16, 2020
0c7072f
Start moving printers into steps
felixmulder Jul 17, 2020
627448a
Remove unused decl printer
felixmulder Jul 17, 2020
bb8e157
Move imports printer to step
felixmulder Jul 17, 2020
5ea2bbe
Enable more of the old steps and list which one need to be fixed
felixmulder Jul 17, 2020
f66b9f2
Make sure that module imports don't bother rest of file
felixmulder Jul 17, 2020
d36cced
Factor out function to associate comments with groups of expressions
felixmulder Jul 17, 2020
b989066
Make sure imports respect groups and preserve comments
felixmulder Jul 17, 2020
8032ebb
Add ability to save return value of running printer
felixmulder Jul 18, 2020
da96a3b
Add GHC module for utility functions
felixmulder Jul 18, 2020
a1e7cf9
Make sure imports step respects groupings
felixmulder Jul 18, 2020
0516749
Fix hiding getting an extra space
felixmulder Jul 18, 2020
9e72c96
Move baseDynFlags to GHC util module
felixmulder Jul 18, 2020
30c68a0
Fix printing of exports that are symbolic
felixmulder Jul 18, 2020
d02f0b6
Add span to error message for hint on where error is
felixmulder Jul 18, 2020
f555e4f
Add config option to emit non-zero exit code when reformatting
felixmulder Jul 19, 2020
3beaf57
Implement data decl step
felixmulder Jul 21, 2020
abae160
Add records step to list of finished steps
felixmulder Jul 21, 2020
afb226e
Implement deriving via printing
felixmulder Jul 21, 2020
be7cdb9
Fix indentation on enums with deriving clauses
felixmulder Jul 21, 2020
db7c1fa
Fix multi decl formatting and newtype formatting
felixmulder Jul 22, 2020
2e9a291
Handle infix constructors when printing data decls
felixmulder Jul 22, 2020
24e7c44
Make sure docstrings are included if they precede `=` sign
felixmulder Jul 22, 2020
257e24a
Homogenize handling of comments between type name and `=` sign
felixmulder Jul 22, 2020
92068f0
Make sure newtypes are broken before `=` sign if indent eq is set
felixmulder Jul 22, 2020
cdcd2c5
Add support for indenting via clauses
felixmulder Jul 22, 2020
9152671
Fix function printing in data decl step
felixmulder Jul 23, 2020
5d63611
Print type literals in a uniform way
felixmulder Jul 23, 2020
137d048
Print type operators in a uniform way
felixmulder Jul 23, 2020
f022ac2
Make sure nested type literals are properly printed
felixmulder Jul 23, 2020
01a8dbd
Fix printing of promoted constructors
felixmulder Jul 23, 2020
4be10fa
Move type printing to printer module
felixmulder Jul 23, 2020
34c5c2b
Move around and document a few functions
felixmulder Jul 23, 2020
2822e25
Fix double space after infix type name
felixmulder Jul 23, 2020
6b636c8
Allow old steps to be run alongside new ones
felixmulder Jul 23, 2020
b8677cd
Fix issue where comment is not printed after type name and newline
felixmulder Jul 23, 2020
8826da3
Add missing EOL comment printing to constructors
felixmulder Jul 23, 2020
126577e
Rename step to show that it's using ghc-lib-parser
felixmulder Jul 23, 2020
1749866
Fix incorrect error string in parseModuleHSE
felixmulder Jul 23, 2020
0271e8a
Fix off-by-one error
felixmulder Jul 23, 2020
e406fa1
Work around edge-case where there are comments _in_ a deriving block
felixmulder Jul 23, 2020
a8f91c9
Make sure previous fix is idempotent
felixmulder Jul 23, 2020
ecb69c9
Reformulate predicate for inserting comments before eq to single binding
felixmulder Jul 24, 2020
a9d6248
Implement language pragma step with ghc-lib-parser
felixmulder Jul 24, 2020
58a12b4
Add SYB query function for `Module`
felixmulder Jul 25, 2020
ff3990c
Implement redundant view/bang pattern functions using SYB query API
felixmulder Jul 25, 2020
313bc77
Fix remaining configuration tests
felixmulder Jul 25, 2020
3b77027
Bump haskell docker image to get newer version of stack
felixmulder Jul 25, 2020
32385f4
Remove outputable helper export from printer module
felixmulder Jul 25, 2020
0250597
Document Module module
felixmulder Jul 25, 2020
e39bfd1
Correct comment on language string length
felixmulder Jul 25, 2020
e5d5a0e
Add comment for `putAllSpanComments`
felixmulder Jul 25, 2020
ff35fb3
Rename `putModulePrefix` to `putModuleName`
felixmulder Jul 25, 2020
0dda96b
Document new configuration options
felixmulder Jul 25, 2020
115325a
Fix issue with incomplete pattern match on AST
felixmulder Jul 25, 2020
b47d606
Add missing documentation on how to enable module header formatting
felixmulder Jul 25, 2020
46ca865
Add configurability on curried context and implement simple GADT support
felixmulder Jul 26, 2020
3f16447
Fix typo in config file: 'parsre' -> 'parse'
felixmulder Jul 28, 2020
0611d91
Remove redundant '$'
felixmulder Jul 28, 2020
b46676d
Use `on` for compare function
felixmulder Jul 29, 2020
99ceb58
Rename `Imports'` to `ImportsGHC`
felixmulder Jul 29, 2020
98e82ee
Use CPP to get rid of monoid warning for newer GHC versions
felixmulder Jul 29, 2020
34f333b
Implement equality for `Import` decl
felixmulder Jul 29, 2020
a556f59
Implement ability to merge imports in ImportsGHC
felixmulder Jul 29, 2020
e1b7a64
Add formatting for long deriving clauses
felixmulder Aug 24, 2020
18f96cb
Pass max columns to ImportsGHC step
felixmulder Aug 24, 2020
fe97c30
Add ability to split import lines that are too long
felixmulder Aug 24, 2020
f9d5d77
Add testing function that has sane expected/got for long lines
felixmulder Aug 25, 2020
14cc117
Fix issue with multiple groups in due to abusing editor functions
felixmulder Aug 25, 2020
4208e1b
Don't split 'hiding' imports since it changes the scope
felixmulder Aug 25, 2020
d11358a
Make sure that nullary imports are not deleted
felixmulder Aug 25, 2020
ade14f9
Integrate Squash and Align steps
VBeatrice Aug 4, 2020
5875a53
Change error msg in test
VBeatrice Aug 27, 2020
ab99534
Implementated some options (align, pad_module_names, separate_lists, …
VBeatrice Aug 31, 2020
0a8e4a4
Squash warnings
jaspervdj Sep 12, 2020
32756fc
Backwards-compatible import thing sort
jaspervdj Sep 12, 2020
ddba4c8
Backwards-compatible module grouping
jaspervdj Sep 14, 2020
c61dc9d
Merge branch 'master' into ghc-lib-parser/merge
jaspervdj Sep 14, 2020
35dcc94
Restore global/file alignment
jaspervdj Sep 14, 2020
dac6f3b
Add a wrapping combinator
jaspervdj Sep 17, 2020
70cbdfd
Fix test
jaspervdj Sep 17, 2020
091aaef
Refactor & fix off-by-one error
jaspervdj Sep 18, 2020
95bb2cc
list_align: add 'repeat' & restore options
jaspervdj Sep 19, 2020
27e9cc2
ImportsGHC: old tests 1-7 working
jaspervdj Sep 19, 2020
3d40d66
Fix more tests
jaspervdj Sep 19, 2020
9e70a88
patchForRepeatHiding
jaspervdj Sep 20, 2020
a19d167
long_list_align: multiline
jaspervdj Sep 20, 2020
f3ab35f
Fix spaces issue in long_list_align: multiline
jaspervdj Sep 20, 2020
d08024e
Snippet for pretty diff
jaspervdj Sep 20, 2020
33a9d28
Fix some list_align: newline issues
jaspervdj Sep 20, 2020
1a05d46
Stub InlineWithBreak
jaspervdj Sep 20, 2020
d4a146b
Fix long_list_align: newline issue
jaspervdj Sep 20, 2020
32dd4d2
long_list_align: newline: try single line first
jaspervdj Sep 20, 2020
acec94c
sortImportList: sort inner list, too
jaspervdj Sep 20, 2020
81de6c8
long_list_align: new_line_multiline
jaspervdj Sep 20, 2020
142e45b
empty_list_align: right_after
jaspervdj Sep 20, 2020
9fa9755
Fix list_padding: module_name
jaspervdj Sep 20, 2020
c915316
Unique import items, still needs merging
jaspervdj Sep 21, 2020
40c38ff
Stub out proper import item merging
jaspervdj Sep 21, 2020
514da21
Refactor with ImportStats
jaspervdj Sep 21, 2020
11530cf
Working package imports
jaspervdj Sep 21, 2020
1492fd4
space_surround subtleties
jaspervdj Sep 23, 2020
1d4c9ed
space_surround subtleties
jaspervdj Sep 23, 2020
9df19ab
space_surround subtleties
jaspervdj Sep 23, 2020
4885b95
All import tests passing
jaspervdj Sep 23, 2020
d1d474b
Refactor old tests a little
jaspervdj Sep 23, 2020
8b7d807
Rip out old imports module
jaspervdj Sep 24, 2020
6e1220b
WIP: operate on groups in SimpleAlign
jaspervdj Sep 25, 2020
706694a
WIP: operate on groups in SimpleAlign
jaspervdj Sep 25, 2020
cab57f3
Clean up Align module
jaspervdj Sep 25, 2020
012deaf
Improve Show instance for Snippet
jaspervdj Sep 26, 2020
eccacb0
Remove ghc_lib_parser option
jaspervdj Sep 26, 2020
9078e35
Make indent in ModuleHeader configurable
jaspervdj Sep 26, 2020
5eab669
Make module_header sorting optional
jaspervdj Sep 30, 2020
1621745
Add a consistent ordering module
jaspervdj Sep 30, 2020
6274090
Rewrite UnicodeSyntax.hs to use ghc-lib-parser
lukasz-golebiewski Sep 26, 2020
2adfb29
Remove redundant import
lukasz-golebiewski Sep 30, 2020
a34ab85
Fix addLanguagePragma
lukasz-golebiewski Sep 30, 2020
265db5e
Remove obsolete code from Util.hs
lukasz-golebiewski Sep 30, 2020
60526d8
Remove OldStep and OldModule
lukasz-golebiewski Sep 30, 2020
1edd838
Remove last remnants of Haskell.Exts
lukasz-golebiewski Sep 30, 2020
642be11
Remove haskell-src-exts dependency
lukasz-golebiewski Sep 30, 2020
b8274f8
Tickle CI cache
jaspervdj Oct 1, 2020
d1a4e51
Clean up LanguagePragmas tests
jaspervdj Oct 1, 2020
a229a2f
BangPatterns is removed when it shouldn't be
jaspervdj Oct 1, 2020
79a1643
Also check for ! in Hs.Match
jaspervdj Oct 1, 2020
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: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

- uses: actions/checkout@v2

- uses: actions/setup-haskell@v1.1
- uses: actions/setup-haskell@v1.1.2
name: Setup Haskell Stack
with:
ghc-version: ${{ matrix.ghc }}
Expand All @@ -29,7 +29,7 @@ jobs:
name: Cache ~/.stack
with:
path: ~/.stack
key: ${{ runner.os }}-${{ matrix.ghc }}-v2
key: ${{ runner.os }}-${{ matrix.ghc }}-v3

- name: Add ~/.local/bin to PATH
run: echo "::add-path::$HOME/.local/bin"
Expand Down
59 changes: 59 additions & 0 deletions data/stylish-haskell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ steps:
# # true.
# add_language_pragma: true

# Format module header
#
# Currently, this option is not configurable and will format all exports and
# module declarations to minimize diffs
#
# - module_header:
# # How many spaces use for indentation in the module header.
# indent: 4
#
# # Should export lists be sorted? Sorting is only performed within the
# # export section, as delineated by Haddock comments.
# sort: true

# Format record definitions. This is disabled by default.
#
# You can control the layout of record fields. The only rules that can't be configured
Expand Down Expand Up @@ -42,6 +55,31 @@ steps:
#
# # How many spaces to insert before "deriving" clause. Deriving clauses are always on separate lines.
# deriving: 2
#
# # How many spaces to insert before "via" clause counted from indentation of deriving clause
# # Possible values:
# # - "same_line" -- "{" and first field goes on the same line as the data constructor.
# # - "indent N" -- insert a new line and N spaces from the beginning of the data constructor
# via: "indent 2"
#
# # Wheter or not to break enums onto several lines
# #
# # Default: false
# break_enums: false
#
# # Whether or not to break single constructor data types before `=` sign
# #
# # Default: true
# break_single_constructors: true
#
# # Whether or not to curry constraints on function.
# #
# # E.g: @allValues :: Enum a => Bounded a => Proxy a -> [a]@
# #
# # Instead of @allValues :: (Enum a, Bounded a) => Proxy a -> [a]@
# #
# # Default: false
# curried_context: false

# Align the right hand side of some elements. This is quite conservative
# and only applies to statements where each element occupies a single
Expand Down Expand Up @@ -101,6 +139,11 @@ steps:
# > import qualified Data.List as List
# > (concat, foldl, foldr, head, init, last, length)
#
# - repeat: Repeat the module name to align the import list.
#
# > import qualified Data.List as List (concat, foldl, foldr, head)
# > import qualified Data.List as List (init, last, length)
#
# Default: after_alias
list_align: after_alias

Expand Down Expand Up @@ -203,6 +246,22 @@ steps:
# Default: false
space_surround: false

# Enabling this argument will use the new GHC lib parse to format imports.
#
# This currently assumes a few things, it will assume that you want post
# qualified imports. It is also not as feature complete as the old
# imports formatting.
#
# It does not remove redundant lines or merge lines. As such, the full
# feature scope is still pending.
#
# It _is_ however, a fine alternative if you are using features that are
# not parseable by haskell src extensions and you're comfortable with the
# presets.
#
# Default: false
ghc_lib_parser: false

# Language pragmas
- language_pragmas:
# We can generate different styles of language pragma lists.
Expand Down
17 changes: 11 additions & 6 deletions lib/Language/Haskell/Stylish.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,19 @@ unicodeSyntax = UnicodeSyntax.step

--------------------------------------------------------------------------------
runStep :: Extensions -> Maybe FilePath -> Lines -> Step -> Either String Lines
runStep exts mfp ls step =
stepFilter step ls <$> parseModule exts mfp (unlines ls)

runStep exts mfp ls = \case
Step _name step ->
step ls <$> parseModule exts mfp (unlines ls)

--------------------------------------------------------------------------------
runSteps :: Extensions -> Maybe FilePath -> [Step] -> Lines
-> Either String Lines
runSteps exts mfp steps ls = foldM (runStep exts mfp) ls steps
runSteps ::
Extensions
-> Maybe FilePath
-> [Step]
-> Lines
-> Either String Lines
runSteps exts mfp steps ls =
foldM (runStep exts mfp) ls steps

newtype ConfigPath = ConfigPath { unConfigPath :: FilePath }

Expand Down
53 changes: 26 additions & 27 deletions lib/Language/Haskell/Stylish/Align.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Language.Haskell.Stylish.Align

--------------------------------------------------------------------------------
import Data.List (nub)
import qualified Language.Haskell.Exts as H
import qualified SrcLoc as S


--------------------------------------------------------------------------------
Expand Down Expand Up @@ -51,49 +51,48 @@ data Alignable a = Alignable
, aRightLead :: !Int
} deriving (Show)


--------------------------------------------------------------------------------
-- | Create changes that perform the alignment.

align
:: Maybe Int -- ^ Max columns
-> [Alignable H.SrcSpan] -- ^ Alignables
-> [Change String] -- ^ Changes performing the alignment.
:: Maybe Int -- ^ Max columns
-> [Alignable S.RealSrcSpan] -- ^ Alignables
-> [Change String] -- ^ Changes performing the alignment
align _ [] = []
align maxColumns alignment
-- Do not make any change if we would go past the maximum number of columns.
| exceedsColumns (longestLeft + longestRight) = []
| not (fixable alignment) = []
| otherwise = map align' alignment
-- Do not make an changes if we would go past the maximum number of columns
| exceedsColumns (longestLeft + longestRight) = []
| not (fixable alignment) = []
| otherwise = map align' alignment
where
exceedsColumns i = case maxColumns of
Nothing -> False -- No number exceeds a maximum column count of
-- Nothing, because there is no limit to exceed.
Just c -> i > c
Nothing -> False
Just c -> i > c

-- The longest thing in the left column.
longestLeft = maximum $ map (H.srcSpanEndColumn . aLeft) alignment
-- The longest thing in the left column
longestLeft = maximum $ map (S.srcSpanEndCol . aLeft) alignment

-- The longest thing in the right column.
-- The longest thing in the right column
longestRight = maximum
[ H.srcSpanEndColumn (aRight a) - H.srcSpanStartColumn (aRight a)
+ aRightLead a
| a <- alignment
]

align' a = changeLine (H.srcSpanStartLine $ aContainer a) $ \str ->
let column = H.srcSpanEndColumn $ aLeft a
(pre, post) = splitAt column str
in [padRight longestLeft (trimRight pre) ++ trimLeft post]
[ S.srcSpanEndCol (aRight a) - S.srcSpanStartCol (aRight a)
+ aRightLead a
| a <- alignment
]

align' a = changeLine (S.srcSpanStartLine $ aContainer a) $ \str ->
let column = S.srcSpanEndCol $ aLeft a
(pre, post) = splitAt column str
in [padRight longestLeft (trimRight pre) ++ trimLeft post]

--------------------------------------------------------------------------------
-- | Checks that all the alignables appear on a single line, and that they do
-- not overlap.
fixable :: [Alignable H.SrcSpan] -> Bool

fixable :: [Alignable S.RealSrcSpan] -> Bool
fixable [] = False
fixable [_] = False
fixable fields = all singleLine containers && nonOverlapping containers
where
containers = map aContainer fields
singleLine s = H.srcSpanStartLine s == H.srcSpanEndLine s
nonOverlapping ss = length ss == length (nub $ map H.srcSpanStartLine ss)
singleLine s = S.srcSpanStartLine s == S.srcSpanEndLine s
nonOverlapping ss = length ss == length (nub $ map S.srcSpanStartLine ss)
30 changes: 9 additions & 21 deletions lib/Language/Haskell/Stylish/Block.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,26 @@ module Language.Haskell.Stylish.Block
, LineBlock
, SpanBlock
, blockLength
, linesFromSrcSpan
, spanFromSrcSpan
, moveBlock
, adjacent
, merge
, mergeAdjacent
, overlapping
, groupAdjacent
) where


--------------------------------------------------------------------------------
import Control.Arrow (arr, (&&&), (>>>))
import qualified Data.IntSet as IS
import qualified Language.Haskell.Exts as H
import qualified Data.IntSet as IS


--------------------------------------------------------------------------------
-- | Indicates a line span
data Block a = Block
{ blockStart :: Int
, blockEnd :: Int
} deriving (Eq, Ord, Show)
}
deriving (Eq, Ord, Show)


--------------------------------------------------------------------------------
Expand All @@ -40,21 +38,6 @@ type SpanBlock = Block Char
blockLength :: Block a -> Int
blockLength (Block start end) = end - start + 1


--------------------------------------------------------------------------------
linesFromSrcSpan :: H.SrcSpanInfo -> LineBlock
linesFromSrcSpan = H.srcInfoSpan >>>
H.srcSpanStartLine &&& H.srcSpanEndLine >>>
arr (uncurry Block)


--------------------------------------------------------------------------------
spanFromSrcSpan :: H.SrcSpanInfo -> SpanBlock
spanFromSrcSpan = H.srcInfoSpan >>>
H.srcSpanStartColumn &&& H.srcSpanEndColumn >>>
arr (uncurry Block)


--------------------------------------------------------------------------------
moveBlock :: Int -> Block a -> Block a
moveBlock offset (Block start end) = Block (start + offset) (end + offset)
Expand Down Expand Up @@ -94,3 +77,8 @@ groupAdjacent = foldr go []
go (b1, x) gs = case break (adjacent b1 . fst) gs of
(_, []) -> (b1, [x]) : gs
(ys, ((b2, xs) : zs)) -> (merge b1 b2, x : xs) : (ys ++ zs)

mergeAdjacent :: [Block a] -> [Block a]
mergeAdjacent (a : b : rest) | a `adjacent` b = merge a b : mergeAdjacent rest
mergeAdjacent (a : rest) = a : mergeAdjacent rest
mergeAdjacent [] = []
Loading