- remove
makeDeltaAst
, otherwise there will be noSrcSpan
anywhere in the AST (but when ready to make a change, using it to capture spacing of the local thing being edited may help) EpAnnNotUsed
is gone, usenoAnn
insteaduniqueSrcSpanT
is no longer needed, use an appropriateEpaDelta
location insteadEpaDelta (DifferentLine row col)
interpretscol
differently. You must add 1 to get the prior spacing.- If you add something to a list (possible via
hsDecls
/replaceDecls
), the following item only needs to havesetEntryDP
called on it, to get the spacing right
We have taken a more principled approach relating to the location and function of annotation types.
-
Located (EpAnn ann) a
carries positioning and comments, and some limited annotations, such as trailing ones. -
Annotations within
a
, no locations or comments, just keywords etc
EpAnnNotUsed
is gone
Anchor
is now EpaLocation
type LocatedAn an = GenLocated (EpAnn an)
SrcAnn
is gone
It provides a generalisation of getLoc
, and getLocA
is now defined as a synonym for it.
class HasLoc a where
-- ^ conveniently calculate locations for things without locations attached
getHasLoc :: a -> SrcSpan
getLocA :: (HasLoc a) => GenLocated a e -> SrcSpan
getLocA = getHasLoc
This also allowed getting rid of the zoo of conversion functions. All that remains is l2l
, la2la
, reLoc
.
Below are examples of the generalisations this allows (see NoAnn
details below)
sortLocatedA :: (HasLoc (EpAnn a)) => [GenLocated (EpAnn a) e] -> [GenLocated (EpAnn a) e]
sortLocatedA = sortBy (leftmost_smallest `on` getLocA)
mapLocA :: (NoAnn ann) => (a -> b) -> GenLocated SrcSpan a -> GenLocated (EpAnn ann) b
mapLocA f (L l a) = L (noAnnSrcSpan l) (f a)
combineLocsA :: Semigroup a => GenLocated (EpAnn a) e1 -> GenLocated (EpAnn a) e2 -> EpAnn a
combineLocsA (L a _) (L b _) = combineSrcSpansA a b
combineSrcSpansA :: Semigroup a => EpAnn a -> EpAnn a -> EpAnn a
combineSrcSpansA aa ab = aa <> ab
Where HasLoc
provides a way of getting a SrcSpan
out of a thing, HasAnnotation
does the reverse, creating a thing with a SrcSpan
in it.
class HasAnnotation e where
noAnnSrcSpan :: SrcSpan -> e
noLocA :: (HasAnnotation e) => a -> GenLocated e a
noLocA = L (noAnnSrcSpan noSrcSpan)
getLocA :: (HasLoc a) => GenLocated a e -> SrcSpan
getLocA = getHasLoc
noSrcSpanA :: (HasAnnotation e) => e
noSrcSpanA = noAnnSrcSpan noSrcSpan
class NoAnn a where
-- | equivalent of `mempty`, but does not need Semigroup
noAnn :: a
instance (Semigroup a) => Semigroup (EpAnn a) where
(EpAnn l1 a1 b1) <> (EpAnn l2 a2 b2) = EpAnn (l1 <> l2) (a1 <> a2) (b1 <> b2)
-- The critical part about the anchor is its left edge, and all
-- annotations must follow it. So we combine them which yields the
-- largest span
-- | A token stored in the syntax tree. For example, when parsing a
-- let-expression, we store @EpToken "let"@ and @EpToken "in"@.
-- The locations of those tokens can be used to faithfully reproduce
-- (exactprint) the original program text.
data EpToken (tok :: Symbol)
= NoEpTok
| EpTok !EpaLocation
-- | With @UnicodeSyntax@, there might be multiple ways to write the same
-- token. For example an arrow could be either @->@ or @→@. This choice must be
-- recorded in order to exactprint such tokens, so instead of @EpToken "->"@ we
-- introduce @EpUniToken "->" "→"@.
data EpUniToken (tok :: Symbol) (utok :: Symbol)
= NoEpUniTok
| EpUniTok !EpaLocation !IsUnicodeSyntax
deriving instance Eq (EpToken tok)
deriving instance KnownSymbol tok => Data (EpToken tok)
deriving instance (KnownSymbol tok, KnownSymbol utok) => Data (EpUniToken tok utok)
If this is meant as a complement to the migration guide, it could be helpful to add "use
noAnn
instead" next to "EpAnnNotUsed
is gone" :)