diff --git a/Language/Haskell/Tools/AST/FromGHC/Base.hs b/Language/Haskell/Tools/AST/FromGHC/Base.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Base.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Base.hs
@@ -10,6 +10,7 @@
            , AllowAmbiguousTypes
            , TypeApplications
            #-}
+-- | Functions that convert the basic elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Base where
 
 import Control.Monad.Reader
@@ -48,8 +49,8 @@
 
 trfOperator' :: TransformName n r => n -> Trf (AST.Operator (Dom r) RangeStage)
 trfOperator' n
-  | isSymOcc (occName n) = AST.NormalOp <$> (annCont (createNameInfo (transformName n)) (trfSimpleName' n))
-  | otherwise = AST.BacktickOp <$> (annLoc (createNameInfo (transformName n)) loc (trfSimpleName' n))
+  | isSymOcc (occName n) = AST.NormalOp <$> (annCont (createNameInfo (transformName n)) (trfQualifiedName' n))
+  | otherwise = AST.BacktickOp <$> (annLoc (createNameInfo (transformName n)) loc (trfQualifiedName' n))
      where loc = mkSrcSpan <$> (updateCol (+1) <$> atTheStart) <*> (updateCol (subtract 1) <$> atTheEnd)
 
 trfName :: TransformName n r => Located n -> Trf (Ann AST.Name (Dom r) RangeStage)
@@ -57,8 +58,8 @@
 
 trfName' :: TransformName n r => n -> Trf (AST.Name (Dom r) RangeStage)
 trfName' n
-  | isSymOcc (occName n) = AST.ParenName <$> (annLoc (createNameInfo (transformName n)) loc (trfSimpleName' n))
-  | otherwise = AST.NormalName <$> (annCont (createNameInfo (transformName n)) (trfSimpleName' n))
+  | isSymOcc (occName n) = AST.ParenName <$> (annLoc (createNameInfo (transformName n)) loc (trfQualifiedName' n))
+  | otherwise = AST.NormalName <$> (annCont (createNameInfo (transformName n)) (trfQualifiedName' n))
      where loc = mkSrcSpan <$> (updateCol (+1) <$> atTheStart) <*> (updateCol (subtract 1) <$> atTheEnd)
 
 trfAmbiguousFieldName :: TransformName n r => Located (AmbiguousFieldOcc n) -> Trf (Ann AST.Name (Dom r) RangeStage)
@@ -76,14 +77,17 @@
 
 class (DataId n, Eq n, GHCName n) => TransformableName n where
   correctNameString :: n -> Trf String
+  getDeclSplices :: Trf [Located (HsSplice n)]
   fromGHCName :: GHC.Name -> n 
 
 instance TransformableName RdrName where
   correctNameString = pure . rdrNameStr
+  getDeclSplices = pure []
   fromGHCName = rdrName
 
 instance TransformableName GHC.Name where
   correctNameString n = getOriginalName (rdrName n)
+  getDeclSplices = asks declSplices
   fromGHCName = id
 
 -- | This class allows us to use the same transformation code for multiple variants of the GHC AST.
@@ -99,11 +103,18 @@
 instance {-# OVERLAPS #-} (TransformableName res, GHCName res, HsHasName res) => TransformName GHC.Name res where
   transformName = fromGHCName
 
-trfSimpleName :: TransformName n r => Located n -> Trf (Ann AST.SimpleName (Dom r) RangeStage)
-trfSimpleName name@(L l n) = annLoc (createNameInfo (transformName n)) (pure l) (trfSimpleName' n)
+trfImplicitName :: HsIPName -> Trf (Ann AST.Name (Dom r) RangeStage)
+trfImplicitName (HsIPName fs) 
+  = let nstr = unpackFS fs 
+     in do rng <- asks contRange
+           let rng' = mkSrcSpan (updateCol (+1) (srcSpanStart rng)) (srcSpanEnd rng)
+           annContNoSema (AST.ImplicitName <$> annLoc (createImplicitNameInfo nstr) (pure rng') (AST.nameFromList <$> trfNameStr nstr))
 
-trfSimpleName' :: TransformName n r => n -> Trf (AST.SimpleName (Dom r) RangeStage)
-trfSimpleName' n = AST.nameFromList <$> (trfNameStr =<< correctNameString n)
+trfQualifiedName :: TransformName n r => Located n -> Trf (Ann AST.QualifiedName (Dom r) RangeStage)
+trfQualifiedName name@(L l n) = annLoc (createNameInfo (transformName n)) (pure l) (trfQualifiedName' n)
+
+trfQualifiedName' :: TransformName n r => n -> Trf (AST.QualifiedName (Dom r) RangeStage)
+trfQualifiedName' n = AST.nameFromList <$> (trfNameStr =<< correctNameString n)
 
 -- | Creates a qualified name from a name string
 trfNameStr :: String -> Trf (AnnList AST.UnqualName (Dom r) RangeStage)
diff --git a/Language/Haskell/Tools/AST/FromGHC/Binds.hs b/Language/Haskell/Tools/AST/FromGHC/Binds.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Binds.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Binds.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE LambdaCase
            , ViewPatterns
            #-}
+-- | Functions that convert the value and function definitions of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Binds where
 
 import Control.Monad.Reader
@@ -97,6 +98,7 @@
 getBindLocs :: HsLocalBinds n -> SrcSpan
 getBindLocs (HsValBinds (ValBindsIn binds sigs)) = foldLocs $ map getLoc (bagToList binds) ++ map getLoc sigs
 getBindLocs (HsValBinds (ValBindsOut binds sigs)) = foldLocs $ map getLoc (concatMap (bagToList . snd) binds) ++ map getLoc sigs
+getBindLocs (HsIPBinds (IPBinds binds _)) = foldLocs $ map getLoc binds
   
 trfLocalBinds :: TransformName n r => HsLocalBinds n -> Trf (AnnList AST.LocalBind (Dom r) RangeStage)
 trfLocalBinds (HsValBinds (ValBindsIn binds sigs)) 
@@ -107,6 +109,14 @@
   = makeIndentedList (after AnnWhere)
       (orderDefs <$> ((++) <$> (concat <$> mapM (mapM (copyAnnot AST.LocalValBind . trfBind) . bagToList . snd) binds)
                            <*> mapM trfLocalSig sigs))
+trfLocalBinds (HsIPBinds (IPBinds binds _))
+  = makeIndentedList (after AnnWhere) (mapM trfIpBind binds)
+
+trfIpBind :: TransformName n r => Located (IPBind n) -> Trf (Ann AST.LocalBind (Dom r) RangeStage)
+trfIpBind = trfLocNoSema $ \case
+  IPBind (Left (L l ipname)) expr -> AST.LocalValBind <$> (annContNoSema $ AST.SimpleBind <$> focusOn l (annContNoSema (AST.VarPat <$> define (trfImplicitName ipname)))
+                                                                                          <*> annFromNoSema AnnEqual (AST.UnguardedRhs <$> trfExpr expr)
+                                                                                          <*> nothing " " "" atTheEnd)
              
 trfLocalSig :: TransformName n r => Located (Sig n) -> Trf (Ann AST.LocalBind (Dom r) RangeStage)
 trfLocalSig = trfLocNoSema $ \case
diff --git a/Language/Haskell/Tools/AST/FromGHC/Decls.hs b/Language/Haskell/Tools/AST/FromGHC/Decls.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Decls.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Decls.hs
@@ -2,8 +2,10 @@
            , ViewPatterns
            , ScopedTypeVariables
            #-}
+-- | Functions that convert the declarations of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Decls where
 
+import qualified GHC
 import RdrName as GHC
 import Class as GHC
 import HsSyn as GHC
@@ -17,10 +19,14 @@
 import Bag as GHC
 import ForeignCall as GHC
 import Outputable as GHC
+import Unique as GHC
 
 import Control.Monad.Reader
 import Control.Reference
+import Data.Function (on)
+import Data.List
 import Data.Maybe
+import qualified Data.Map as Map
 import Data.Data (toConstr)
 import Data.Generics.Uniplate.Data
 
@@ -38,35 +44,53 @@
 import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..), getRange, Dom, RangeStage)
 import qualified Language.Haskell.Tools.AST as AST
 
+import Data.Dynamic
 import Debug.Trace
 
 trfDecls :: TransformName n r => [LHsDecl n] -> Trf (AnnList AST.Decl (Dom r) RangeStage)
 -- TODO: filter documentation comments
-trfDecls decls = addToScope decls $ makeIndentedListNewlineBefore atTheEnd (mapM trfDecl decls)
+trfDecls decls = addToCurrentScope decls $ makeIndentedListNewlineBefore atTheEnd (mapM trfDecl decls)
 
 trfDeclsGroup :: forall n r . TransformName n r => HsGroup n -> Trf (AnnList AST.Decl (Dom r) RangeStage)
 trfDeclsGroup (HsGroup vals splices tycls insts derivs fixities defaults foreigns warns anns rules vects docs) 
-  = addAllToScope $ makeIndentedListNewlineBefore atTheEnd (fmap (orderDefs . concat) $ sequence $
-      [ trfBindOrSig vals
-      , concat <$> mapM (mapM (trfDecl . (fmap TyClD)) . group_tyclds) tycls
-      , mapM (trfDecl . (fmap SpliceD)) splices
-      , mapM (trfDecl . (fmap InstD)) insts
-      , mapM (trfDecl . (fmap DerivD)) derivs
-      , mapM (trfDecl . (fmap (SigD . FixSig))) (mergeFixityDefs fixities)
-      , mapM (trfDecl . (fmap DefD)) defaults
-      , mapM (trfDecl . (fmap ForD)) foreigns
-      , mapM (trfDecl . (fmap WarningD)) warns
-      , mapM (trfDecl . (fmap AnnD)) anns
-      , mapM (trfDecl . (fmap RuleD)) rules
-      , mapM (trfDecl . (fmap VectD)) vects
-      -- , mapM (trfDecl . (fmap DocD)) docs
-      ])
-  where trfBindOrSig :: HsValBinds n -> Trf [Ann AST.Decl (Dom r) RangeStage]
-        trfBindOrSig (getBindsAndSigs -> (sigs, binds))
-          = (++) <$> mapM (trfLocNoSema trfVal) (bagToList binds)
-                 <*> mapM (trfLocNoSema trfSig) sigs
-        addAllToScope = addToCurrentScope vals . addToCurrentScope tycls . addToCurrentScope foreigns
-           
+  = do spls <- getDeclSplices
+       let (sigs, bagToList -> binds) = getBindsAndSigs vals
+           alldecls :: [Located (HsDecl n)]
+           alldecls = (map (fmap SpliceD) splices)
+                        ++ (map (fmap ValD) binds)
+                        ++ (map (fmap SigD) sigs)
+                        ++ (map (fmap TyClD) (concat $ map group_tyclds tycls))
+                        ++ (map (fmap InstD) insts)
+                        ++ (map (fmap DerivD) derivs)
+                        ++ (map (fmap (SigD . FixSig)) (mergeFixityDefs fixities)) 
+                        ++ (map (fmap DefD) defaults)
+                        ++ (map (fmap ForD) foreigns)
+                        ++ (map (fmap WarningD) warns)
+                        ++ (map (fmap AnnD) anns)
+                        ++ (map (fmap RuleD) rules)
+                        ++ (map (fmap VectD) vects)
+       let actualDefinitions = replaceSpliceDecls spls alldecls
+       addToCurrentScope actualDefinitions $ makeIndentedListNewlineBefore atTheEnd (orderDefs <$> ((++) <$> getDeclsToInsert <*> (mapM trfDecl actualDefinitions)))
+  where 
+    replaceSpliceDecls :: [Located (HsSplice n)] -> [Located (HsDecl n)] -> [Located (HsDecl n)]
+    replaceSpliceDecls splices decls = foldl mergeSplice decls splices
+    
+    mergeSplice :: [Located (HsDecl n)] -> Located (HsSplice n) -> [Located (HsDecl n)]
+    mergeSplice decls spl@(L spLoc@(RealSrcSpan rss) _)
+      = L spLoc (SpliceD (SpliceDecl spl ExplicitSplice)) : filter (\(L (RealSrcSpan rdsp) _) -> not (rss `containsSpan` rdsp)) decls
+    
+    getDeclsToInsert :: Trf [Ann AST.Decl (Dom r) RangeStage]
+    getDeclsToInsert = do decls <- asks declsToInsert
+                          locals <- asks (head . localsInScope)
+                          liftGhc $ mapM (loadIdsForDecls locals) decls
+       where loadIdsForDecls :: [GHC.Name] -> Ann AST.Decl (Dom RdrName) RangeStage -> GHC.Ghc (Ann AST.Decl (Dom r) RangeStage)
+             loadIdsForDecls locals = AST.semaTraverse $
+                AST.SemaTrf (AST.nameInfo !~ findName) pure 
+                            (\(AST.ImportInfo mod avail actual) -> AST.ImportInfo mod <$> mapM findName avail <*> mapM findName actual)
+                            pure pure pure
+               where findName rdr = pure $ fromGHCName $ fromMaybe (error $ "Data definition name not found: " ++ showSDocUnsafe (ppr rdr) 
+                                                                              ++ ", locals: " ++ (concat $ intersperse ", " $ map (showSDocUnsafe . ppr) locals)) 
+                                                       $ find ((occNameString (rdrNameOcc rdr) ==) . occNameString . nameOccName) locals
            
 trfDecl :: TransformName n r => Located (HsDecl n) -> Trf (Ann AST.Decl (Dom r) RangeStage)
 trfDecl = trfLocNoSema $ \case
@@ -102,10 +126,10 @@
     -> AST.TypeInstDecl <$> between AnnInstance AnnEqual (makeInstanceRuleTyVars con pats) <*> trfType rhs
   ValD bind -> trfVal bind
   SigD sig -> trfSig sig
-  DerivD (DerivDecl t overlap) -> AST.DerivDecl <$> trfMaybe "" "" trfOverlap overlap <*> trfInstanceRule (hsib_body t)
+  DerivD (DerivDecl t overlap) -> AST.DerivDecl <$> trfMaybeDefault " " "" trfOverlap (after AnnInstance) overlap <*> trfInstanceRule (hsib_body t)
   -- TODO: INLINE, SPECIALIZE, MINIMAL, VECTORISE pragmas, Warnings, Annotations, rewrite rules, role annotations
   RuleD (HsRules _ rules) -> AST.PragmaDecl <$> annContNoSema (AST.RulePragma <$> makeIndentedList (before AnnClose) (mapM trfRewriteRule rules))
-  RoleAnnotD (RoleAnnotDecl name roles) -> AST.RoleDecl <$> trfSimpleName name <*> makeList " " atTheEnd (mapM trfRole roles)
+  RoleAnnotD (RoleAnnotDecl name roles) -> AST.RoleDecl <$> trfQualifiedName name <*> makeList " " atTheEnd (mapM trfRole roles)
   DefD (DefaultDecl types) -> AST.DefaultDecl . nonemptyAnnList <$> mapM trfType types
   ForD (ForeignImport name (hsib_body -> typ) _ (CImport ccall safe _ _ _)) 
     -> AST.ForeignImport <$> trfCallConv ccall <*> trfSafety (getLoc ccall) safe <*> define (trfName name) <*> trfType typ
diff --git a/Language/Haskell/Tools/AST/FromGHC/Exprs.hs b/Language/Haskell/Tools/AST/FromGHC/Exprs.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Exprs.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Exprs.hs
@@ -4,9 +4,11 @@
            , TypeApplications
            , AllowAmbiguousTypes
            #-}
+-- | Functions that convert the expression-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Exprs where
 
 import Data.Maybe
+import Data.List (partition, find)
 import Data.Data (toConstr)
 import Control.Monad.Reader
 import Control.Reference
@@ -24,6 +26,7 @@
 import FastString as GHC
 import Outputable as GHC
 import PrelNames as GHC
+import DataCon as GHC
 
 import Language.Haskell.Tools.AST.FromGHC.Base
 import Language.Haskell.Tools.AST.FromGHC.Types
@@ -42,10 +45,20 @@
 import Debug.Trace
 
 trfExpr :: forall n r . TransformName n r => Located (HsExpr n) -> Trf (Ann AST.Expr (Dom r) RangeStage)
--- correction for empty cases (TODO: put of and {} inside)
+-- correction for empty cases
 trfExpr (L l cs@(HsCase expr (unLoc . mg_alts -> []))) 
-  = annLoc createScopeInfo (pure $ combineSrcSpans l (getLoc expr)) (trfExpr' cs)
-trfExpr e = trfLoc trfExpr' createScopeInfo e
+  = do let realSpan = combineSrcSpans l (getLoc expr)
+       tokensAfter <- allTokensAfter (srcSpanEnd realSpan)
+       let actualSpan = case take 3 tokensAfter of 
+                          [(_, AnnOf), (_, AnnOpenC), (endSpan, AnnCloseC)] -> realSpan `combineSrcSpans` endSpan
+                          ((endSpan, AnnOf) : _) -> realSpan `combineSrcSpans` endSpan
+       annLoc createScopeInfo (pure actualSpan) (trfExpr' cs)
+trfExpr e = do exprSpls <- asks exprSplices
+               let RealSrcSpan loce = getLoc e
+                   contSplice = find (\sp -> case getSpliceLoc sp of (RealSrcSpan spLoc) -> spLoc `containsSpan` loce; _ -> False) exprSpls
+               case contSplice of Just sp -> case sp of HsQuasiQuote {} -> exprSpliceInserted sp (annCont createScopeInfo (AST.QuasiQuoteExpr <$> annLocNoSema (pure $ getSpliceLoc sp) (trfQuasiQuotation' sp)))
+                                                        _               -> exprSpliceInserted sp (annCont createScopeInfo (AST.Splice <$> annLocNoSema (pure $ getSpliceLoc sp) (trfSplice' sp)))
+                                  Nothing -> trfLoc trfExpr' createScopeInfo e
 
 createScopeInfo :: Trf AST.ScopeInfo
 createScopeInfo = do scope <- asks localsInScope
@@ -54,7 +67,7 @@
 trfExpr' :: TransformName n r => HsExpr n -> Trf (AST.Expr (Dom r) RangeStage)
 trfExpr' (HsVar name) = AST.Var <$> trfName name
 trfExpr' (HsRecFld fld) = AST.Var <$> (asks contRange >>= \l -> trfAmbiguousFieldName' l fld)
-trfExpr' (HsIPVar (HsIPName ip)) = AST.Var <$> annContNoSema (AST.NormalName <$> annCont (createImplicitNameInfo (unpackFS ip)) (AST.nameFromList <$> trfNameStr (unpackFS ip)))
+trfExpr' (HsIPVar ip) = AST.Var <$> trfImplicitName ip
 trfExpr' (HsOverLit (ol_val -> val)) = AST.Lit <$> annContNoSema (trfOverloadedLit val)
 trfExpr' (HsLit val) = AST.Lit <$> annContNoSema (trfLiteral' val)
 trfExpr' (HsLam (unLoc . mg_alts -> [unLoc -> Match _ pats _ (GRHSs [unLoc -> GRHS [] expr] (unLoc -> EmptyLocalBinds))]))
@@ -66,7 +79,7 @@
 trfExpr' (NegApp e _) = AST.PrefixApp <$> annLocNoSema loc (AST.NormalOp <$> annLoc info loc (AST.nameFromList <$> trfNameStr "-"))
                                       <*> trfExpr e
   where loc = mkSrcSpan <$> atTheStart <*> (pure $ srcSpanStart (getLoc e))
-        info = createNameInfo =<< (fromMaybe (error "minus operation is not found") <$> lift negateOpName)
+        info = createNameInfo =<< (fromMaybe (error "minus operation is not found") <$> liftGhc negateOpName)
         negateOpName = getFromNameUsing (\n -> (\case Just (AnId id) -> Just id; _ -> Nothing) <$> lookupName n) negateName
 trfExpr' (HsPar (unLoc -> SectionL expr (unLoc -> HsVar op))) = AST.LeftSection <$> trfExpr expr <*> trfOperator op
 trfExpr' (HsPar (unLoc -> SectionR (unLoc -> HsVar op) expr)) = AST.RightSection <$> trfOperator op <*> trfExpr expr
@@ -136,18 +149,20 @@
 trfExpr' (HsBracket brack) = AST.BracketExpr <$> annContNoSema (trfBracket' brack)
 trfExpr' (HsSpliceE qq@(HsQuasiQuote {})) = AST.QuasiQuoteExpr <$> annContNoSema (trfQuasiQuotation' qq)
 trfExpr' (HsSpliceE splice) = AST.Splice <$> annContNoSema (trfSplice' splice)
+trfExpr' (HsRnBracketOut br _) = AST.BracketExpr <$> annContNoSema (trfBracket' br)
 trfExpr' (HsProc pat cmdTop) = AST.Proc <$> trfPattern pat <*> trfCmdTop cmdTop
 trfExpr' (HsStatic expr) = AST.StaticPtr <$> trfExpr expr
 trfExpr' (HsAppType expr typ) = AST.ExplTypeApp <$> trfExpr expr <*> trfType (hswc_body typ)
 trfExpr' t = error ("Illegal expression: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
   
 trfFieldInits :: TransformName n r => HsRecFields n (LHsExpr n) -> Trf (AnnList AST.FieldUpdate (Dom r) RangeStage)
-trfFieldInits (HsRecFields fields dotdot) 
+trfFieldInits (HsRecFields fields dotdot)
   = do cont <- asks contRange
+       let (normalFlds, implicitFlds) = partition ((cont /=) . getLoc) fields
        makeList ", " (before AnnCloseC)
-         $ ((++) <$> mapM trfFieldInit (filter ((cont /=) . getLoc) fields) 
+         $ ((++) <$> mapM trfFieldInit normalFlds
                   <*> (if isJust dotdot then (:[]) <$> annLocNoSema (tokenLoc AnnDotdot) 
-                                                                    (pure AST.FieldWildcard) 
+                                                                    (AST.FieldWildcard <$> (annCont (createImplicitFldInfo (unLoc . (\(HsVar n) -> n) . unLoc) (map unLoc implicitFlds)) (pure AST.FldWildcard))) 
                                         else pure []))
   
 trfFieldInit :: TransformName n r => Located (HsRecField n (LHsExpr n)) -> Trf (Ann AST.FieldUpdate (Dom r) RangeStage)
@@ -173,7 +188,8 @@
 trfCaseRhss = gTrfCaseRhss trfExpr
 
 gTrfCaseRhss :: TransformName n r => (Located (ge n) -> Trf (Ann ae (Dom r) RangeStage)) -> [Located (GRHS n (Located (ge n)))] -> Trf (Ann (AST.CaseRhs' ae) (Dom r) RangeStage)
-gTrfCaseRhss te [unLoc -> GRHS [] body] = annLocNoSema (combineSrcSpans (getLoc body) <$> tokenLocBack AnnRarrow) 
+gTrfCaseRhss te [unLoc -> GRHS [] body] = annLocNoSema (combineSrcSpans (getLoc body) <$> updateFocus (pure . updateEnd (const $ srcSpanStart $ getLoc body)) 
+                                                                                                      (tokenLocBack AnnRarrow)) 
                                                  (AST.UnguardedCaseRhs <$> te body)
 gTrfCaseRhss te rhss = annLocNoSema (pure $ collectLocs rhss) 
                               (AST.GuardedCaseRhss <$> trfAnnList ";" (gTrfGuardedCaseRhs' te) rhss)
diff --git a/Language/Haskell/Tools/AST/FromGHC/GHCUtils.hs b/Language/Haskell/Tools/AST/FromGHC/GHCUtils.hs
--- a/Language/Haskell/Tools/AST/FromGHC/GHCUtils.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/GHCUtils.hs
@@ -5,6 +5,7 @@
            , ViewPatterns
            , LambdaCase
            #-}
+-- | Utility functions defined on the GHC AST representation.
 module Language.Haskell.Tools.AST.FromGHC.GHCUtils where
 
 import Data.List
@@ -74,20 +75,7 @@
       Nothing -> return Nothing
   where createPatSynType patSyn = case patSynSig patSyn of (_, _, _, _, args, res) -> mkFunTys args res
 
--- | Loading ids for local ghc names
-getLocalId :: LHsBinds Id -> GHC.Name -> Ghc (Maybe GHC.Id)
-getLocalId bnds name = case Map.lookup name mapping of
-    Just id -> return (Just id)
-    Nothing | isTyVarName name
-               -- unit type is for cases we don't know the kind
-            -> return $ Just $ mkVanillaGlobal name unitTy
-    Nothing -> return Nothing
-  where mapping = Map.fromList $ map (\id -> (getName id, id)) $ extractTypes bnds
-        extractTypes :: LHsBinds Id -> [Id]
-        extractTypes = concatMap universeBi . bagToList
-
-
-
+-- | Get names from the GHC AST
 class HsHasName a where
   hsGetNames :: a -> [GHC.Name]
 
@@ -197,6 +185,9 @@
   hsGetNames (SigPatIn p _) = hsGetNames p
   hsGetNames (SigPatOut p _) = hsGetNames p
   hsGetNames _ = []
+
+instance (GHCName n, HsHasName n) => HsHasName (HsGroup n) where
+  hsGetNames (HsGroup vals _ clds _ _ _ _ foreigns _ _ _ _ _) = hsGetNames vals ++ hsGetNames clds ++ hsGetNames foreigns
 
 -- | Get the original form of a name
 rdrNameStr :: RdrName -> String
diff --git a/Language/Haskell/Tools/AST/FromGHC/Kinds.hs b/Language/Haskell/Tools/AST/FromGHC/Kinds.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Kinds.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Kinds.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE ViewPatterns
            , TypeFamilies 
            #-}
+-- | Functions that convert the kind-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Kinds where
 
 import SrcLoc as GHC
diff --git a/Language/Haskell/Tools/AST/FromGHC/Literals.hs b/Language/Haskell/Tools/AST/FromGHC/Literals.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Literals.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Literals.hs
@@ -1,3 +1,4 @@
+-- | Functions that convert the literals of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Literals where
 
 import qualified Data.ByteString.Char8 as BS
diff --git a/Language/Haskell/Tools/AST/FromGHC/Modules.hs b/Language/Haskell/Tools/AST/FromGHC/Modules.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Modules.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Modules.hs
@@ -3,12 +3,16 @@
            , FlexibleContexts
            , ScopedTypeVariables
            , TypeApplications
+           , TupleSections
            #-}
+-- | Functions that convert the module-related elements (modules, imports, exports) of the GHC AST to corresponding elements in the Haskell-tools AST representation
+-- Also contains the entry point of the transformation that collects the information from different GHC AST representations.
 module Language.Haskell.Tools.AST.FromGHC.Modules where
 
 import Control.Reference hiding (element)
 import Data.Maybe
-import Data.List
+import Data.Function (on)
+import Data.List as List
 import Data.Char
 import Data.Map as Map hiding (map, filter)
 import Data.IORef
@@ -16,6 +20,7 @@
 import Data.Generics.Uniplate.Operations
 import Data.Generics.Uniplate.Data
 import Control.Applicative
+import Control.Monad
 import Control.Monad.Reader
 import Control.Monad.Writer
 import Control.Monad.State
@@ -45,9 +50,22 @@
 import Unique as GHC
 import CoAxiom as GHC
 import DynFlags as GHC
+import TcEvidence as GHC
+import TcRnMonad as GHC
+import RnEnv as GHC
+import RnExpr as GHC
+import ErrUtils as GHC
+import PrelNames as GHC
+import NameEnv as GHC
+import TcRnDriver as GHC
+import TcExpr as GHC
+import TcType as GHC
+import UniqSupply as GHC
+import UniqFM as GHC
+import HeaderInfo as GHC
 import Language.Haskell.TH.LanguageExtensions
 
-import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..), Dom, IdDom, RangeStage, NoSemanticInfo(..), NameInfo(..), CNameInfo(..), ScopeInfo(..), ImportInfo(..), ModuleInfo(..)
+import Language.Haskell.Tools.AST (Ann(..), AnnMaybe(..), AnnList(..), Dom, IdDom, RangeStage, NoSemanticInfo(..), NameInfo(..), CNameInfo(..), ScopeInfo(..), ImportInfo(..), ModuleInfo(..), ImplicitFieldInfo(..)
                                   , semanticInfo, sourceInfo, semantics, annotation, nameInfo, nodeSpan, semaTraverse)
 import qualified Language.Haskell.Tools.AST as AST
 
@@ -57,29 +75,79 @@
 import Language.Haskell.Tools.AST.FromGHC.Utils
 import Language.Haskell.Tools.AST.FromGHC.GHCUtils
 
+import Debug.Trace
+
 addTypeInfos :: LHsBinds Id -> Ann AST.Module (Dom GHC.Name) RangeStage -> Ghc (Ann AST.Module IdDom RangeStage)
-addTypeInfos bnds = semaTraverse 
-  (AST.SemaTrf
-    (\case (NameInfo sc def ni) -> CNameInfo sc def <$> getType' ni 
-           (AmbiguousNameInfo sc d rdr l) -> return $ CNameInfo sc d (locMapping ! l))
-    pure
-    (\(ImportInfo mod access used) -> ImportInfo mod <$> mapM getType' access <*> mapM getType' used)
-    (\(ModuleInfo mod imps) -> ModuleInfo mod <$> mapM getType' imps)
-    pure)
+addTypeInfos bnds mod = do
+  ut <- liftIO mkUnknownType
+  let getType = getType' ut
+  fixities <- getFixities
+  let createCName sc def id = CNameInfo sc def id fixity
+        where fixity = if any (any ((getOccName id ==) . getOccName)) (init sc) 
+                          then Nothing 
+                          else fmap (snd . snd) $ List.find (\(mod,(occ,_)) -> mod == (nameModule $ varName id) && occ == getOccName id) fixities
+  evalStateT (semaTraverse 
+    (AST.SemaTrf
+      (\case (NameInfo sc def ni) -> lift $ createCName sc def <$> getType ni 
+             (AmbiguousNameInfo sc d rdr l) | Just id <- Map.lookup l locMapping -> return $ createCName sc d id
+             (AmbiguousNameInfo sc d rdr l) | otherwise -> error $ "Ambiguous name missing: " ++ showSDocUnsafe (ppr rdr) ++ ", at: " ++ show l
+             (ImplicitNameInfo sc d str l) | Just id <- Map.lookup l locMapping -> return $ createCName sc d id
+             (ImplicitNameInfo sc d str (RealSrcSpan l)) | otherwise
+                -> do (none,rest) <- gets (break ((\(RealSrcSpan sp) -> sp `containsSpan` l) . fst))
+                      case rest of [] -> error $ "Implicit name missing: " ++ str ++ ", at: " ++ show l
+                                   ((_,id):more) -> do put (none ++ more)
+                                                       return $ createCName sc d id)
+      pure
+      (\(ImportInfo mod access used) -> lift $ ImportInfo mod <$> mapM getType access <*> mapM getType used)
+      (\(ModuleInfo mod isboot imps) -> lift $ ModuleInfo mod isboot <$> mapM getType imps)
+      (\(ImplicitFieldInfo wcbinds) -> return $ ImplicitFieldInfo wcbinds)
+        pure) mod) (extractSigIds bnds ++ extractSigBindIds bnds)
   where locMapping = Map.fromList $ map (\(L l id) -> (l, id)) $ extractExprIds bnds
-        getType' name = fromMaybe (error $ "Type of name '" ++ showSDocUnsafe (ppr name) ++ "' cannot be found")
-                            <$> ((<|>) <$> getTopLevelId name <*> getLocalId bnds name)
+        getType' ut name = fromMaybe (mkVanillaGlobal name ut) <$> ((<|> Map.lookup name ids) <$> getTopLevelId name)
+        ids = Map.fromList $ map (\id -> (getName id, id)) $ extractTypes bnds
+        extractTypes :: LHsBinds Id -> [Id]
+        extractTypes = concatMap universeBi . bagToList
 
+        mkUnknownType :: IO Type
+        mkUnknownType = do 
+          tUnique <- mkSplitUniqSupply 'x'
+          return $ mkTyVarTy $ mkVanillaGlobal (mkSystemName (uniqFromSupply tUnique) (mkDataOcc "TypeNotFound")) (mkTyConTy starKindTyCon)
+
+        getFixities :: Ghc [(Module, (OccName, GHC.Fixity))]
+        getFixities = do env <- getSession
+                         pit <- liftIO $ eps_PIT <$> hscEPS env
+                         let hpt = hsc_HPT env
+                             ifaces = moduleEnvElts pit ++ map hm_iface (eltsUFM hpt)
+                         return $ concatMap (\mi -> map (mi_module mi, ) $ mi_fixities mi) ifaces
+
 extractExprIds :: LHsBinds Id -> [Located Id]
         -- expressions like HsRecFld are removed from the typechecked representation, they are replaced by HsVar
-extractExprIds = catMaybes . map (\case (L l (HsVar (L _ n))) -> Just (L l n); _ -> Nothing) . concatMap universeBi . bagToList
+extractExprIds = catMaybes . map (\case L l (HsVar (L _ n)) -> Just (L l n)
+                                        L l (HsWrap _ (HsVar (L _ n))) -> Just (L l n)
+                                        _ -> Nothing
+                                 ) . concatMap universeBi . bagToList
 
-createModuleInfo :: Module -> Trf (AST.ModuleInfo GHC.Name)
-createModuleInfo mod = do prelude <- lift (xopt ImplicitPrelude . ms_hspp_opts <$> getModSummary (moduleName mod))
-                          (_,preludeImports) <- if prelude then getImportedNames "Prelude" Nothing else return (mod, [])
-                          return $ AST.ModuleInfo mod preludeImports
+extractSigIds :: LHsBinds Id -> [(SrcSpan,Id)]
+extractSigIds = concat . map (\case L l bs@(AbsBindsSig {} :: HsBind Id) -> map (l,) $ getImplVars (abs_sig_ev_bind bs)
+                                    _                                    -> []
+                             ) . concatMap universeBi . bagToList
+  where getImplVars (EvBinds evbnds) = catMaybes $ map getEvVar $ bagToList evbnds
+        getEvVar (EvBind lhs _ False) = Just lhs
+        getEvVar _                    = Nothing
 
-trfModule :: Module -> Located (HsModule RdrName) -> Trf (Ann AST.Module (Dom RdrName) RangeStage)
+extractSigBindIds :: LHsBinds Id -> [(SrcSpan,Id)]
+extractSigBindIds = catMaybes . map (\case L l bs@(IPBind (Right id) _) -> Just (l,id)
+                                           _                            -> Nothing
+                                    ) . concatMap universeBi . bagToList
+
+
+
+createModuleInfo :: ModSummary -> Trf (AST.ModuleInfo GHC.Name)
+createModuleInfo mod = do let prelude = xopt ImplicitPrelude $ ms_hspp_opts mod
+                          (_,preludeImports) <- if prelude then getImportedNames "Prelude" Nothing else return (ms_mod mod, [])
+                          return $ AST.ModuleInfo (ms_mod mod) (case ms_hsc_src mod of HsSrcFile -> False; _ -> True) preludeImports
+
+trfModule :: ModSummary -> Located (HsModule RdrName) -> Trf (Ann AST.Module (Dom RdrName) RangeStage)
 trfModule mod = trfLocCorrect (createModuleInfo mod) (\sr -> combineSrcSpans sr <$> (uniqueTokenAnywhere AnnEofPos)) $ 
                   \(HsModule name exports imports decls deprec _) -> 
                     AST.Module <$> trfFilePragmas
@@ -87,26 +155,60 @@
                                <*> trfImports imports
                                <*> trfDecls decls
        
-trfModuleRename :: Module -> Ann AST.Module (Dom RdrName) RangeStage 
-                          -> (HsGroup Name, [LImportDecl Name], Maybe [LIE Name], Maybe LHsDocString) 
-                          -> Located (HsModule RdrName) 
-                          -> Trf (Ann AST.Module (Dom GHC.Name) RangeStage)
+trfModuleRename :: ModSummary -> Ann AST.Module (Dom RdrName) RangeStage 
+                              -> (HsGroup Name, [LImportDecl Name], Maybe [LIE Name], Maybe LHsDocString) 
+                              -> Located (HsModule RdrName) 
+                              -> Trf (Ann AST.Module (Dom GHC.Name) RangeStage)
 trfModuleRename mod rangeMod (gr,imports,exps,_) hsMod 
     = do info <- createModuleInfo mod
          trfLocCorrect (pure info) (\sr -> combineSrcSpans sr <$> (uniqueTokenAnywhere AnnEofPos)) (trfModuleRename' (info ^. AST.implicitNames)) hsMod      
-  where originalNames = Map.fromList $ catMaybes $ map getSourceAndInfo (rangeMod ^? biplateRef) 
-        getSourceAndInfo :: Ann AST.SimpleName (Dom RdrName) RangeStage -> Maybe (SrcSpan, RdrName)
+  where roleAnnots = rangeMod ^? AST.element&AST.modDecl&AST.annList&filtered ((\case AST.RoleDecl {} -> True; _ -> False) . (^. AST.element))
+        originalNames = Map.fromList $ catMaybes $ map getSourceAndInfo (rangeMod ^? biplateRef) 
+        getSourceAndInfo :: Ann AST.QualifiedName (Dom RdrName) RangeStage -> Maybe (SrcSpan, RdrName)
         getSourceAndInfo n = (,) <$> (n ^? annotation&sourceInfo&nodeSpan) <*> (n ^? semantics&nameInfo)
         
         trfModuleRename' preludeImports hsMod@(HsModule name exports _ decls deprec _) = do
           transformedImports <- orderAnnList <$> (trfImports imports)
-          setOriginalNames originalNames
-            $ AST.Module <$> trfFilePragmas
-                         <*> trfModuleHead name (case (exports, exps) of (Just (L l _), Just ie) -> Just (L l ie)
-                                                                         _                       -> Nothing) deprec
-                         <*> return transformedImports
-                         <*> addToScope (concat @[] (transformedImports ^? AST.annList&semantics&AST.importedNames) ++ preludeImports) (trfDeclsGroup gr)
+           
+          addToScope (concat @[] (transformedImports ^? AST.annList&semantics&AST.importedNames) ++ preludeImports)
+            $ loadSplices mod hsMod gr $ setOriginalNames originalNames . setDeclsToInsert roleAnnots
+              $ AST.Module <$> trfFilePragmas
+                           <*> trfModuleHead name (case (exports, exps) of (Just (L l _), Just ie) -> Just (L l ie)
+                                                                           _                       -> Nothing) deprec
+                           <*> return transformedImports
+                           <*> trfDeclsGroup gr
 
+loadSplices :: ModSummary -> HsModule RdrName -> HsGroup Name -> Trf a -> Trf a
+loadSplices mod hsMod group trf = do 
+    let declSpls = map (\(SpliceDecl sp _) -> sp) $ hsMod ^? biplateRef :: [Located (HsSplice RdrName)]
+        declLocs = map getLoc declSpls
+    let exprSpls = catMaybes $ map (\case HsSpliceE sp -> Just sp; _ -> Nothing) $ hsMod ^? biplateRef :: [HsSplice RdrName]
+        typeSpls = catMaybes $ map (\case HsSpliceTy sp _ -> Just sp; _ -> Nothing) $ hsMod ^? biplateRef :: [HsSplice RdrName]
+    -- initialize reader environment
+    env <- liftGhc getSession
+
+    locals <- asks ((hsGetNames group ++) . concat . localsInScope)
+    let readEnv = mkOccEnv (map (\n -> (GHC.occName n, [GRE n NoParent False [ImpSpec (ImpDeclSpec (moduleName $ nameModule n) (moduleName $ nameModule n) False noSrcSpan) ImpAll]])) locals)
+
+    tcdSplices <- liftIO $ runTcInteractive env { hsc_dflags = xopt_set (hsc_dflags env) TemplateHaskellQuotes }
+      $ updGblEnv (\gbl -> gbl { tcg_rdr_env = readEnv }) 
+      $ (,,) <$> mapM tcHsSplice declSpls <*> mapM tcHsSplice' typeSpls <*> mapM tcHsSplice' exprSpls
+    let (declSplices, typeSplices, exprSplices) 
+          = fromMaybe (error $ "Splice expression could not be typechecked: " 
+                                 ++ showSDocUnsafe (vcat (pprErrMsgBagWithLoc (fst (fst tcdSplices))) 
+                                                      <+> vcat (pprErrMsgBagWithLoc (snd (fst tcdSplices))))) 
+                      (snd tcdSplices)
+    setSplices declSplices typeSplices exprSplices trf
+  where
+    tcHsSplice :: Located (HsSplice RdrName) -> RnM (Located (HsSplice Name))
+    tcHsSplice (L l s) = L l <$> tcHsSplice' s
+    tcHsSplice' (HsTypedSplice id e) 
+      = HsTypedSplice (mkUnboundNameRdr id) <$> (fst <$> rnLExpr e)
+    tcHsSplice' (HsUntypedSplice id e) 
+      = HsUntypedSplice (mkUnboundNameRdr id) <$> (fst <$> rnLExpr e)
+    tcHsSplice' (HsQuasiQuote id1 id2 sp fs) 
+      = pure $ HsQuasiQuote (mkUnboundNameRdr id1) (mkUnboundNameRdr id2) sp fs
+
 trfModuleHead :: TransformName n r => Maybe (Located ModuleName) -> Maybe (Located [LIE n]) -> Maybe (Located WarningTxt) -> Trf (AnnMaybe AST.ModuleHead (Dom r) RangeStage) 
 trfModuleHead (Just mn) exports modPrag
   = makeJust <$> (annLocNoSema (tokensLoc [AnnModule, AnnWhere])
@@ -157,7 +259,7 @@
 trfImports :: TransformName n r => [LImportDecl n] -> Trf (AnnList AST.ImportDecl (Dom r) RangeStage)
 trfImports (filter (not . ideclImplicit . unLoc) -> imps) 
   = AnnList <$> importDefaultLoc <*> mapM trfImport imps
-  where importDefaultLoc = noSemaInfo . AST.ListPos (if Data.List.null imps then "\n" else "") "" "\n" True . srcSpanEnd 
+  where importDefaultLoc = noSemaInfo . AST.ListPos (if List.null imps then "\n" else "") "" "\n" True . srcSpanEnd 
                              <$> (combineSrcSpans <$> asks (srcLocSpan . srcSpanStart . contRange) 
                                                   <*> (srcLocSpan . srcSpanEnd <$> tokenLoc AnnWhere))
 trfImport :: TransformName n r => LImportDecl n -> Trf (Ann AST.ImportDecl (Dom r) RangeStage)
@@ -166,7 +268,6 @@
       annBeforeQual = if isSrc then AnnClose else AnnImport
       annBeforeSafe = if isQual then AnnQualified else annBeforeQual
       annBeforePkg = if isSafe then AnnSafe else annBeforeSafe
-      atAsPos = if isJust declHiding then before AnnOpenP else atTheEnd
   in (\impdecl -> annLoc (createImportData =<< impdecl) (pure l) impdecl) $ AST.ImportDecl 
        <$> (if isSrc then makeJust <$> annLocNoSema (tokensLoc [AnnOpen, AnnClose]) (pure AST.ImportSource)
                      else nothing " " "" (after AnnImport))
@@ -177,7 +278,7 @@
        <*> maybe (nothing " " "" (after annBeforePkg)) 
                  (\str -> makeJust <$> (annLocNoSema (tokenLoc AnnPackageName) (pure (AST.StringNode (unpackFS $ sl_fs str))))) pkg
        <*> trfModuleName name 
-       <*> maybe (nothing " " "" atAsPos) (\mn -> makeJust <$> (trfRenaming mn)) declAs
+       <*> maybe (nothing " " "" (pure $ srcSpanEnd (getLoc name))) (\mn -> makeJust <$> (trfRenaming mn)) declAs
        <*> trfImportSpecs declHiding 
   where trfRenaming mn
           = annLocNoSema (tokensLoc [AnnAs,AnnVal])
diff --git a/Language/Haskell/Tools/AST/FromGHC/Monad.hs b/Language/Haskell/Tools/AST/FromGHC/Monad.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Monad.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Monad.hs
@@ -11,7 +11,9 @@
 import Language.Haskell.Tools.AST.FromGHC.SourceMap
 import Language.Haskell.Tools.AST.FromGHC.GHCUtils
 import Data.Map as Map
+import Data.Function (on)
 import Data.Maybe
+import Language.Haskell.Tools.AST
 
 import Debug.Trace
 
@@ -22,24 +24,36 @@
 data TrfInput
   = TrfInput { srcMap :: SourceMap -- ^ The lexical tokens of the source file
              , pragmaComms :: Map String [Located String] -- ^ Pragma comments
+             , declsToInsert :: [Ann Decl (Dom RdrName) RangeStage] -- ^ Declarations that are from the parsed AST
              , contRange :: SrcSpan -- ^ The focus of the transformation
              , localsInScope :: [[GHC.Name]] -- ^ Local names visible
              , defining :: Bool -- ^ True, if names are defined in the transformed AST element.
              , definingTypeVars :: Bool -- ^ True, if type variable names are defined in the transformed AST element.
              , originalNames :: Map SrcSpan RdrName -- ^ Stores the original format of names.
+             , declSplices :: [Located (HsSplice GHC.Name)] -- ^ Location of the TH splices for extracting declarations from the renamed AST. 
+                 -- ^ It is possible that multiple declarations stand in the place of the declaration splice or none at all.
+             , typeSplices :: [HsSplice GHC.Name] -- ^ Other types of splices (expressions, types). 
+             , exprSplices :: [HsSplice GHC.Name] -- ^ Other types of splices (expressions, types). 
              }
       
 trfInit :: Map ApiAnnKey [SrcSpan] -> Map String [Located String] -> TrfInput
 trfInit annots comments 
   = TrfInput { srcMap = annotationsToSrcMap annots
              , pragmaComms = comments
+             , declsToInsert = []
              , contRange = noSrcSpan
              , localsInScope = []
              , defining = False
              , definingTypeVars = False
              , originalNames = empty
+             , declSplices = []
+             , typeSplices = []
+             , exprSplices = []
              }
 
+liftGhc :: Ghc a -> Trf a
+liftGhc = lift
+
 -- | Perform the transformation taking names as defined.
 define :: Trf a -> Trf a
 define = local (\s -> s { defining = True })
@@ -78,3 +92,26 @@
 getOriginalName :: RdrName -> Trf String
 getOriginalName n = do sp <- asks contRange
                        asks (rdrNameStr . fromMaybe n . (Map.lookup sp) . originalNames)
+
+-- | Set splices that must replace the elements that are generated into the AST representation.
+setSplices :: [Located (HsSplice GHC.Name)] -> [HsSplice GHC.Name] -> [HsSplice GHC.Name] -> Trf a -> Trf a
+setSplices declSpls typeSpls exprSpls 
+  = local (\s -> s { typeSplices = typeSpls, exprSplices = exprSpls, declSplices = declSpls })
+
+-- | Set the list of declarations that will be missing from AST
+setDeclsToInsert :: [Ann Decl (Dom RdrName) RangeStage] -> Trf a -> Trf a
+setDeclsToInsert decls = local (\s -> s {declsToInsert = decls})
+
+-- Remove the splice that has already been added
+exprSpliceInserted :: HsSplice GHC.Name -> Trf a -> Trf a
+exprSpliceInserted spl = local (\s -> s { exprSplices = Prelude.filter (((/=) `on` getSpliceLoc) spl) (exprSplices s) })
+
+-- Remove the splice that has already been added
+typeSpliceInserted :: HsSplice GHC.Name -> Trf a -> Trf a
+typeSpliceInserted spl = local (\s -> s { typeSplices = Prelude.filter (((/=) `on` getSpliceLoc) spl) (typeSplices s) })
+
+
+getSpliceLoc :: HsSplice a -> SrcSpan
+getSpliceLoc (HsTypedSplice _ e) = getLoc e
+getSpliceLoc (HsUntypedSplice _ e) = getLoc e
+getSpliceLoc (HsQuasiQuote _ _ sp _) = sp
diff --git a/Language/Haskell/Tools/AST/FromGHC/Patterns.hs b/Language/Haskell/Tools/AST/FromGHC/Patterns.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Patterns.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Patterns.hs
@@ -3,6 +3,7 @@
            , ScopedTypeVariables
            , AllowAmbiguousTypes
            #-}
+-- | Functions that convert the pattern-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Patterns where
 
 import SrcLoc as GHC
@@ -33,7 +34,7 @@
 trfPattern (L l (ConPatIn name (RecCon (HsRecFields flds _)))) | any ((l ==) . getLoc) flds 
   = do let (fromWC, notWC) = partition ((l ==) . getLoc) flds
        normalFields <- mapM (trfLocNoSema trfPatternField') notWC
-       wildc <- annLocNoSema (tokenLoc AnnDotdot) (pure AST.FieldWildcardPattern)
+       wildc <- annLocNoSema (tokenLoc AnnDotdot) (AST.FieldWildcardPattern <$> annCont (createImplicitFldInfo (unLoc . (\(VarPat n) -> n) . unLoc) (map unLoc fromWC)) (pure AST.FldWildcard))
        annLocNoSema (pure l) (AST.RecPat <$> trfName name <*> makeNonemptyList ", " (pure (normalFields ++ [wildc])))
 trfPattern p | otherwise = trfLocNoSema trfPattern' (correctPatternLoc p)
 
diff --git a/Language/Haskell/Tools/AST/FromGHC/SourceMap.hs b/Language/Haskell/Tools/AST/FromGHC/SourceMap.hs
--- a/Language/Haskell/Tools/AST/FromGHC/SourceMap.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/SourceMap.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE TupleSections #-}
 -- | A representation of the tokens that build up the source file.
 module Language.Haskell.Tools.AST.FromGHC.SourceMap where
 
 import ApiAnnotation
+import Data.Maybe
 import Data.Map as Map
 import Data.List as List
 import Safe
@@ -10,35 +12,50 @@
 import FastString as GHC
 
 -- We store tokens in the source map so it is not a problem that they cannot overlap
-type SourceMap = Map AnnKeywordId (Map SrcLoc SrcLoc)
+type SourceMap = (Map AnnKeywordId (Map SrcLoc SrcLoc), Map SrcLoc (SrcSpan, AnnKeywordId))
 
 -- | Returns the first occurrence of the keyword in the whole source file
 getKeywordAnywhere :: AnnKeywordId -> SourceMap -> Maybe SrcSpan
-getKeywordAnywhere keyw srcmap = return . uncurry mkSrcSpan =<< headMay . assocs =<< (Map.lookup keyw srcmap)
+getKeywordAnywhere keyw srcmap = return . uncurry mkSrcSpan =<< headMay . assocs =<< (Map.lookup keyw (fst srcmap))
 
 -- | Get the source location of a token restricted to a certain source span
 getKeywordInside :: AnnKeywordId -> SrcSpan -> SourceMap -> Maybe SrcSpan
-getKeywordInside keyw sr srcmap = getSourceElementInside True sr =<< Map.lookup keyw srcmap
+getKeywordInside keyw sr srcmap = getSourceElementInside True sr =<< Map.lookup keyw (fst srcmap)
 
 getKeywordsInside :: AnnKeywordId -> SrcSpan -> SourceMap -> [SrcSpan]
 getKeywordsInside keyw sr srcmap 
-  = maybe [] (List.map (uncurry mkSrcSpan) . assocs . fst . Map.split (srcSpanEnd sr) . snd . Map.split (srcSpanStart sr)) (Map.lookup keyw srcmap)
+  = let tokensOfType = Map.lookup keyw (fst srcmap)
+        (_, startsAtBegin, startAfterBegin) = Map.splitLookup (srcSpanStart sr) $ fromMaybe empty tokensOfType
+        (startsBeforeEnd, _) = Map.split (srcSpanEnd sr) $ maybe id (Map.insert (srcSpanStart sr)) startsAtBegin startAfterBegin -- tokens are minimum 1 char long
+     in List.map (uncurry mkSrcSpan) $ List.filter (\(_, end) -> end <= srcSpanEnd sr) $ assocs startsBeforeEnd
 
 getKeywordInsideBack :: AnnKeywordId -> SrcSpan -> SourceMap -> Maybe SrcSpan
-getKeywordInsideBack keyw sr srcmap = getSourceElementInside False sr =<< Map.lookup keyw srcmap
+getKeywordInsideBack keyw sr srcmap = getSourceElementInside False sr =<< Map.lookup keyw (fst srcmap)
 
 getSourceElementInside :: Bool -> SrcSpan -> Map SrcLoc SrcLoc -> Maybe SrcSpan
 getSourceElementInside b sr srcmap = 
   case (if b then lookupGE (srcSpanStart sr) else lookupLT (srcSpanEnd sr)) srcmap of
     Just (k, v) -> let sp = mkSrcSpan k v in if sp `isSubspanOf` sr then Just sp else Nothing
     Nothing -> Nothing
+
+-- | Returns the next token on the token stream (including the token that starts on the given location)
+getNextToken :: SrcLoc -> SourceMap -> Maybe (SrcSpan, AnnKeywordId)
+getNextToken loc srcmap = fmap snd $ Map.lookupGE loc $ snd srcmap
+
+-- | Returns all subsequent tokens (including the token that starts on the given location)
+getTokensAfter :: SrcLoc -> SourceMap -> [(SrcSpan, AnnKeywordId)]
+getTokensAfter loc srcmap = case Map.splitLookup loc $ snd srcmap of 
+    (_, Just elem, after) -> elem : elems after
+    (_, Nothing, after) -> elems after
     
 -- | Converts GHC Annotations into a convenient format for looking up tokens
-annotationsToSrcMap :: Map ApiAnnKey [SrcSpan] -> Map AnnKeywordId (Map SrcLoc SrcLoc)
-annotationsToSrcMap anns = Map.map (List.foldr addToSrcRanges Map.empty) $ mapKeysWith (++) snd anns
+annotationsToSrcMap :: Map ApiAnnKey [SrcSpan] -> SourceMap
+annotationsToSrcMap anns = (Map.map (List.foldr addToSrcRanges Map.empty) $ mapKeysWith (++) snd anns, tokenMap)
   where 
     addToSrcRanges :: SrcSpan -> Map SrcLoc SrcLoc -> Map SrcLoc SrcLoc
     addToSrcRanges span srcmap = Map.insert (srcSpanStart span) (srcSpanEnd span) srcmap
+
+    tokenMap = Map.fromList $ List.map (\(k,v) -> (srcSpanStart k, (k, v))) $ concatMap (\(key,vals) -> List.map ((, snd key)) vals) $ Map.assocs anns
     
     
                 
diff --git a/Language/Haskell/Tools/AST/FromGHC/Stmts.hs b/Language/Haskell/Tools/AST/FromGHC/Stmts.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Stmts.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Stmts.hs
@@ -2,6 +2,7 @@
            , ViewPatterns
            , TypeFamilies
            #-}
+-- | Functions that convert the statement-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Stmts where
  
 import Data.Maybe
diff --git a/Language/Haskell/Tools/AST/FromGHC/TH.hs b/Language/Haskell/Tools/AST/FromGHC/TH.hs
--- a/Language/Haskell/Tools/AST/FromGHC/TH.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/TH.hs
@@ -1,5 +1,8 @@
+-- | Functions that convert the Template-Haskell-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.TH where
 
+import Control.Monad.Reader
+
 import SrcLoc as GHC
 import RdrName as GHC
 import HsTypes as GHC
@@ -18,7 +21,7 @@
 import Language.Haskell.Tools.AST.FromGHC.Base
 import Language.Haskell.Tools.AST.FromGHC.GHCUtils
 
-import Language.Haskell.Tools.AST (Dom, RangeStage)
+import Language.Haskell.Tools.AST (Ann, Dom, RangeStage)
 import qualified Language.Haskell.Tools.AST as AST
 
 trfQuasiQuotation' :: TransformName n r => HsSplice n -> Trf (AST.QuasiQuote (Dom r) RangeStage)
@@ -30,14 +33,27 @@
                               (updateCol (subtract 1) (srcSpanStart l))
         strLoc = mkSrcSpan (srcSpanStart l) (updateCol (subtract 2) (srcSpanEnd l))
 
+trfSplice :: TransformName n r => Located (HsSplice n) -> Trf (Ann AST.Splice (Dom r) RangeStage)
+trfSplice = trfLocNoSema trfSplice'
 
 trfSplice' :: TransformName n r => HsSplice n -> Trf (AST.Splice (Dom r) RangeStage)
-trfSplice' (HsTypedSplice _ expr) = AST.ParenSplice <$> trfExpr expr
+trfSplice' (HsTypedSplice _ expr) = AST.ParenSplice <$> trfCorrectDollar expr
+trfSplice' (HsUntypedSplice _ expr) = AST.ParenSplice <$> trfCorrectDollar expr
 
+trfCorrectDollar :: TransformName n r => Located (HsExpr n) -> Trf (Ann AST.Expr (Dom r) RangeStage)
+trfCorrectDollar expr = 
+  do isSplice <- allTokenLoc AnnThIdSplice
+     case isSplice of [] -> trfExpr expr
+                      _  -> let newSp = updateStart (updateCol (+1)) (getLoc expr) 
+                             in case expr of L _ (HsVar (L _ varName)) -> trfExpr $ L newSp (HsVar (L newSp varName))
+                                             L _ exp                   -> trfExpr $ L newSp exp
+
 trfBracket' :: TransformName n r => HsBracket n -> Trf (AST.Bracket (Dom r) RangeStage)
 trfBracket' (ExpBr expr) = AST.ExprBracket <$> trfExpr expr
 trfBracket' (TExpBr expr) = AST.ExprBracket <$> trfExpr expr
-trfBracket' (VarBr _ expr) = AST.ExprBracket <$> annCont createScopeInfo (AST.Var <$> (annContNoSema (trfName' expr)))
+trfBracket' (VarBr isSingle expr) 
+  = AST.ExprBracket <$> annLoc createScopeInfo (updateStart (updateCol (if isSingle then (+1) else (+2))) <$> asks contRange) 
+      (AST.Var <$> (annContNoSema (trfName' expr)))
 trfBracket' (PatBr pat) = AST.PatternBracket <$> trfPattern pat
 trfBracket' (DecBrL decls) = AST.DeclsBracket <$> trfDecls decls
 trfBracket' (DecBrG decls) = AST.DeclsBracket <$> trfDeclsGroup decls
diff --git a/Language/Haskell/Tools/AST/FromGHC/TH.hs-boot b/Language/Haskell/Tools/AST/FromGHC/TH.hs-boot
--- a/Language/Haskell/Tools/AST/FromGHC/TH.hs-boot
+++ b/Language/Haskell/Tools/AST/FromGHC/TH.hs-boot
@@ -11,5 +11,6 @@
 import qualified Language.Haskell.Tools.AST as AST
 
 trfQuasiQuotation' :: TransformName n r => HsSplice n -> Trf (AST.QuasiQuote (Dom r) RangeStage)
+trfSplice :: TransformName n r => Located (HsSplice n) -> Trf (Ann AST.Splice (Dom r) RangeStage)
 trfSplice' :: TransformName n r => HsSplice n -> Trf (AST.Splice (Dom r) RangeStage)
 trfBracket' :: TransformName n r => HsBracket n -> Trf (AST.Bracket (Dom r) RangeStage)
diff --git a/Language/Haskell/Tools/AST/FromGHC/Types.hs b/Language/Haskell/Tools/AST/FromGHC/Types.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Types.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Types.hs
@@ -2,6 +2,7 @@
            , ViewPatterns
            , ScopedTypeVariables
            #-}
+-- | Functions that convert the type-related elements of the GHC AST to corresponding elements in the Haskell-tools AST representation
 module Language.Haskell.Tools.AST.FromGHC.Types where
  
 import SrcLoc as GHC
@@ -19,6 +20,7 @@
 import Control.Applicative
 import Control.Reference
 import Data.Maybe
+import Data.List (find)
 import Data.Data (Data(..), toConstr)
 
 import Language.Haskell.Tools.AST.FromGHC.GHCUtils
@@ -34,7 +36,11 @@
 import Debug.Trace
 
 trfType :: TransformName n r => Located (HsType n) -> Trf (Ann AST.Type (Dom r) RangeStage)
-trfType = trfLocNoSema trfType'
+trfType typ = do othSplices <- asks typeSplices
+                 let RealSrcSpan loce = getLoc typ
+                     contSplice = find (\sp -> case getSpliceLoc sp of (RealSrcSpan spLoc) -> spLoc `containsSpan` loce; _ -> False) othSplices
+                 case contSplice of Just sp -> typeSpliceInserted sp (annLocNoSema (pure $ getSpliceLoc sp) (AST.TySplice <$> trfSplice' sp))
+                                    Nothing -> trfLocNoSema trfType' typ
 
 trfType' :: TransformName n r => HsType n -> Trf (AST.Type (Dom r) RangeStage)
 trfType' = trfType'' . cleanHsType where
@@ -101,6 +107,8 @@
 trfAssertion' (cleanHsType -> t) = case cleanHsType base of
    HsTyVar name -> AST.ClassAssert <$> trfName name <*> trfAnnList " " trfType' args
    HsEqTy t1 t2 -> AST.InfixAssert <$> trfType t1 <*> annLocNoSema (tokenLoc AnnTilde) (trfOperator' typeEq) <*> trfType t2
+   HsIParamTy name t -> do loc <- tokenLoc AnnVal
+                           AST.ImplicitAssert <$> define (focusOn loc (trfImplicitName name)) <*> trfType t
    t -> error ("Illegal trf assertion: " ++ showSDocUnsafe (ppr t) ++ " (ctor: " ++ show (toConstr t) ++ ")")
   where (args, sp, base) = getArgs t
         getArgs :: HsType n -> ([LHsType n], Maybe SrcSpan, HsType n)
diff --git a/Language/Haskell/Tools/AST/FromGHC/Utils.hs b/Language/Haskell/Tools/AST/FromGHC/Utils.hs
--- a/Language/Haskell/Tools/AST/FromGHC/Utils.hs
+++ b/Language/Haskell/Tools/AST/FromGHC/Utils.hs
@@ -19,6 +19,7 @@
 import HsSyn
 import Module
 import Name
+import NameSet
 import Outputable
 import FastString
 
@@ -52,21 +53,28 @@
 createImplicitNameInfo :: String -> Trf (NameInfo n)
 createImplicitNameInfo name = do locals <- asks localsInScope
                                  isDefining <- asks defining
-                                 return (ImplicitNameInfo locals isDefining name)
+                                 rng <- asks contRange
+                                 return (ImplicitNameInfo locals isDefining name rng)
 
+-- | Creates a semantic information for an implicit name
+createImplicitFldInfo :: (GHCName n, HsHasName n) => (a -> n) -> [HsRecField n a] -> Trf ImplicitFieldInfo
+createImplicitFldInfo select flds = return (ImplicitFieldInfo (map getLabelAndExpr flds))
+  where getLabelAndExpr fld = ( head $ hsGetNames $ unLoc (getFieldOccName (hsRecFieldLbl fld))
+                              , head $ hsGetNames $ select (hsRecFieldArg fld) )
+
 -- | Adds semantic information to an impord declaration. See ImportInfo.
 createImportData :: (HsHasName n, GHCName n) => AST.ImportDecl (Dom n) stage -> Trf (ImportInfo n)
 createImportData imp = 
   do (mod,importedNames) <- getImportedNames (imp ^. importModule&element&AST.moduleNameString)
                                              (imp ^? importPkg&annJust&element&stringNodeStr)
-     names <- lift $ filterM (checkImportVisible imp) importedNames
-     lookedUpNames <- lift $ mapM (getFromNameUsing getTopLevelId) names
-     lookedUpImported <- lift $ mapM (getFromNameUsing getTopLevelId) importedNames
+     names <- liftGhc $ filterM (checkImportVisible imp) importedNames
+     lookedUpNames <- liftGhc $ mapM (getFromNameUsing getTopLevelId) names
+     lookedUpImported <- liftGhc $ mapM (getFromNameUsing getTopLevelId) importedNames
      return $ ImportInfo mod (catMaybes lookedUpImported) (catMaybes lookedUpNames)
 
 -- | Get names that are imported from a given import
 getImportedNames :: String -> Maybe String -> Trf (GHC.Module, [GHC.Name])
-getImportedNames name pkg = lift $ do
+getImportedNames name pkg = liftGhc $ do
   eps <- getSession >>= liftIO . readIORef . hsc_EPS
   mod <- findModule (mkModuleName name) (fmap mkFastString pkg)
   -- load exported names from interface file
@@ -196,6 +204,10 @@
 focusOn :: SrcSpan -> Trf a -> Trf a
 focusOn sp = local (\s -> s { contRange = sp })
 
+updateFocus :: (SrcSpan -> Trf SrcSpan) -> Trf a -> Trf a
+updateFocus f trf = do newSpan <- f =<< asks contRange
+                       focusOn newSpan trf
+
 -- | Focuses the transformation to go between tokens. The tokens must be found inside the current range.
 between :: AnnKeywordId -> AnnKeywordId -> Trf a -> Trf a
 between firstTok lastTok = focusAfter firstTok . focusBefore lastTok
@@ -220,7 +232,7 @@
           then local (\s -> s { contRange = mkSrcSpan (srcSpanEnd firstToken) (srcSpanEnd (contRange s))}) trf
           else trf
 
--- | Focuses the transformation to be performed after the given token. The token must be found inside the current range.
+-- | Focuses the transformation to be performed before the given token. The token must be found inside the current range.
 focusBefore :: AnnKeywordId -> Trf a -> Trf a
 focusBefore lastTok trf
   = do lastToken <- tokenLocBack lastTok
@@ -248,6 +260,9 @@
 annFrom :: AnnKeywordId -> Trf (SemanticInfo (Dom n) e) -> Trf (e (Dom n) RangeStage) -> Trf (Ann e (Dom n) RangeStage)
 annFrom kw sema = annLoc sema (combineSrcSpans <$> tokenLoc kw <*> asks (srcLocSpan . srcSpanEnd . contRange))
 
+annFromNoSema :: SemanticInfo (Dom n) e ~ NoSemanticInfo => AnnKeywordId -> Trf (e (Dom n) RangeStage) -> Trf (Ann e (Dom n) RangeStage)
+annFromNoSema kw = annFrom kw (pure NoSemanticInfo)
+
 -- | Gets the position at the beginning of the focus       
 atTheStart :: Trf SrcLoc
 atTheStart = asks (srcSpanStart . contRange)
@@ -271,6 +286,9 @@
 tokenBefore loc keyw 
   = fromMaybe noSrcSpan <$> (getKeywordInsideBack keyw <$> (mkSrcSpan <$> (asks (srcSpanStart . contRange)) <*> pure loc) <*> asks srcMap)
 
+allTokensAfter :: SrcLoc -> Trf [(SrcSpan, AnnKeywordId)]
+allTokensAfter loc = getTokensAfter loc <$> asks srcMap
+
 -- | Searches for tokens in the given order inside the parent element and returns their combined location
 tokensLoc :: [AnnKeywordId] -> Trf SrcSpan
 tokensLoc keys = asks contRange >>= tokensLoc' keys
@@ -310,6 +328,14 @@
 updateCol :: (Int -> Int) -> SrcLoc -> SrcLoc
 updateCol f loc@(UnhelpfulLoc _) = loc
 updateCol f (RealSrcLoc loc) = mkSrcLoc (srcLocFile loc) (srcLocLine loc) (f $ srcLocCol loc)
+
+-- | Update the start of the src span
+updateStart :: (SrcLoc -> SrcLoc) -> SrcSpan -> SrcSpan
+updateStart f sp = mkSrcSpan (f (srcSpanStart sp)) (srcSpanEnd sp)
+
+-- | Update the end of the src span
+updateEnd :: (SrcLoc -> SrcLoc) -> SrcSpan -> SrcSpan
+updateEnd f sp = mkSrcSpan (srcSpanStart sp) (f (srcSpanEnd sp))
 
 -- | Combine source spans of elements into one that contains them all
 collectLocs :: [Located e] -> SrcSpan
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,2 @@
-import Distribution.Simple
+import Distribution.Simple
 main = defaultMain
diff --git a/haskell-tools-ast-fromghc.cabal b/haskell-tools-ast-fromghc.cabal
--- a/haskell-tools-ast-fromghc.cabal
+++ b/haskell-tools-ast-fromghc.cabal
@@ -1,7 +1,7 @@
 name:                haskell-tools-ast-fromghc
-version:             0.1.3.0
+version:             0.2.0.0
 synopsis:            Creating the Haskell-Tools AST from GHC's representations
-description:         This package collects information from various representations of a Haskell program in GHC 
+description:         This package collects information from various representations of a Haskell program in GHC. Basically GHC provides us with the parsed, the renamed and the type checked representation of the program, if it was type correct. Each version contains different information. For example, the renamed AST contains the unique names of the definitions, however, template haskell splices are already resolved and thus missing from that version of the AST. To get the final representation we perform a transformation on the parsed and renamed representation, and then use the type checked one to look up the types of the names. The whole transformation is defined in the `Modules` module. Other modules define the functions that convert elements of the GHC AST to our AST.
 homepage:            https://github.com/nboldi/haskell-tools
 license:             BSD3
 license-file:        LICENSE
@@ -14,7 +14,7 @@
 library
   exposed-modules:     Language.Haskell.Tools.AST.FromGHC   
                      , Language.Haskell.Tools.AST.FromGHC.GHCUtils                  
-  other-modules:       Language.Haskell.Tools.AST.FromGHC.Modules
+                     , Language.Haskell.Tools.AST.FromGHC.Modules
                      , Language.Haskell.Tools.AST.FromGHC.TH
                      , Language.Haskell.Tools.AST.FromGHC.Decls
                      , Language.Haskell.Tools.AST.FromGHC.Binds
@@ -31,7 +31,7 @@
 
   build-depends:       base              >=4.9   && <5.0
                      , ghc               >=8.0   && <8.1
-                     , haskell-tools-ast >=0.1.3 && <0.2
+                     , haskell-tools-ast >=0.2   && <0.3
                      , references        >=0.3.2 && <1.0
                      , bytestring        >=0.10  && <1.0
                      , safe              >=0.3   && <1.0
