summaryrefslogtreecommitdiff
path: root/compiler/GHC/Parser/Annotation.hs
diff options
context:
space:
mode:
authorAlan Zimmerman <alan.zimm@gmail.com>2021-10-11 23:05:08 +0100
committerAlan Zimmerman <alan.zimm@gmail.com>2021-10-14 08:51:26 +0100
commit81d65ed2b1b688240741fa5ca70d6a738db1c873 (patch)
treecbb62c1165af33303f5bec4aadc277859d052d0a /compiler/GHC/Parser/Annotation.hs
parent245ab1662edd91a82c17de110c79450fec3f7b82 (diff)
downloadhaskell-81d65ed2b1b688240741fa5ca70d6a738db1c873.tar.gz
EPA: Preserve semicolon order in annotationswip/az/epa-semis-order
Ensure the AddSemiAnn items appear in increasing order, so that if they are converted to delta format they are still in the correct order. Prior to this the exact printer sorted by Span, which is meaningless for EpaDelta locations.
Diffstat (limited to 'compiler/GHC/Parser/Annotation.hs')
-rw-r--r--compiler/GHC/Parser/Annotation.hs36
1 files changed, 31 insertions, 5 deletions
diff --git a/compiler/GHC/Parser/Annotation.hs b/compiler/GHC/Parser/Annotation.hs
index 1692d394b5..9555291530 100644
--- a/compiler/GHC/Parser/Annotation.hs
+++ b/compiler/GHC/Parser/Annotation.hs
@@ -100,7 +100,7 @@ import qualified GHC.Data.Strict as Strict
{-
Note [exact print annotations]
-~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Given a parse tree of a Haskell module, how can we reconstruct
the original Haskell source code, retaining all whitespace and
source code comments? We need to track the locations of all
@@ -394,7 +394,7 @@ instance Outputable EpaComment where
-- The usual way an 'AddEpAnn' is created is using the 'mj' ("make
-- jump") function, and then it can be inserted into the appropriate
-- annotation.
-data AddEpAnn = AddEpAnn AnnKeywordId EpaLocation deriving (Data,Eq,Ord)
+data AddEpAnn = AddEpAnn AnnKeywordId EpaLocation deriving (Data,Eq)
-- | The anchor for an @'AnnKeywordId'@. The Parser inserts the
-- @'EpaSpan'@ variant, giving the exact location of the original item
@@ -460,6 +460,9 @@ instance Outputable EpaLocation where
instance Outputable AddEpAnn where
ppr (AddEpAnn kw ss) = text "AddEpAnn" <+> ppr kw <+> ppr ss
+instance Ord AddEpAnn where
+ compare (AddEpAnn kw1 loc1) (AddEpAnn kw2 loc2) = compare (loc1, kw1) (loc2,kw2)
+
-- ---------------------------------------------------------------------
-- | The exact print annotations (EPAs) are kept in the HsSyn AST for
@@ -802,7 +805,8 @@ addTrailingAnnToL s t cs EpAnnNotUsed
addTrailingAnnToL _ t cs n = n { anns = addTrailing (anns n)
, comments = comments n <> cs }
where
- addTrailing n = n { al_trailing = t : al_trailing n }
+ -- See Note [list append in addTrailing*]
+ addTrailing n = n { al_trailing = al_trailing n ++ [t]}
-- | Helper function used in the parser to add a 'TrailingAnn' items
-- to an existing annotation.
@@ -813,7 +817,8 @@ addTrailingAnnToA s t cs EpAnnNotUsed
addTrailingAnnToA _ t cs n = n { anns = addTrailing (anns n)
, comments = comments n <> cs }
where
- addTrailing n = n { lann_trailing = t : lann_trailing n }
+ -- See Note [list append in addTrailing*]
+ addTrailing n = n { lann_trailing = lann_trailing n ++ [t] }
-- | Helper function used in the parser to add a comma location to an
-- existing annotation.
@@ -822,8 +827,29 @@ addTrailingCommaToN s EpAnnNotUsed l
= EpAnn (spanAsAnchor s) (NameAnnTrailing [AddCommaAnn l]) emptyComments
addTrailingCommaToN _ n l = n { anns = addTrailing (anns n) l }
where
+ -- See Note [list append in addTrailing*]
addTrailing :: NameAnn -> EpaLocation -> NameAnn
- addTrailing n l = n { nann_trailing = AddCommaAnn l : nann_trailing n }
+ addTrailing n l = n { nann_trailing = nann_trailing n ++ [AddCommaAnn l]}
+
+{-
+Note [list append in addTrailing*]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The addTrailingAnnToL, addTrailingAnnToA and addTrailingCommaToN
+functions are used to add a separator for an item when it occurs in a
+list. So they are used to capture a comma, vbar, semicolon and similar.
+
+In general, a given element will have zero or one of these. In
+extreme (test) cases, there may be multiple semicolons.
+
+In exact printing we sometimes convert the EpaLocation variant for an
+trailing annotation to the EpaDelta variant, which cannot be sorted.
+
+Hence it is critical that these annotations are captured in the order
+they appear in the original source file.
+
+And so we use the less efficient list append to preserve the order,
+knowing that in most cases the original list is empty.
+-}
-- ---------------------------------------------------------------------