packages feed

haskell-tools-builtin-refactorings 1.0.1.1 → 1.1.0.0

raw patch · 94 files changed

+1354/−320 lines, 94 filesdep +portable-linesdep ~basedep ~ghcdep ~haskell-tools-ast

Dependencies added: portable-lines

Dependency ranges changed: base, ghc, haskell-tools-ast, haskell-tools-backend-ghc, haskell-tools-prettyprint, haskell-tools-refactor, haskell-tools-rewrite, template-haskell

Files

Language/Haskell/Tools/Refactor/Builtin.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds #-}
+{-# LANGUAGE MonoLocalBinds #-}
 
 module Language.Haskell.Tools.Refactor.Builtin ( builtinRefactorings, builtinQueries ) where
 
@@ -8,7 +8,7 @@ import Language.Haskell.Tools.Refactor.Builtin.GenerateExports (generateExportsRefactoring)
 import Language.Haskell.Tools.Refactor.Builtin.GenerateTypeSignature (generateTypeSignatureRefactoring)
 import Language.Haskell.Tools.Refactor.Builtin.InlineBinding (inlineBindingRefactoring)
-import Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions (organizeExtensionsRefactoring, projectOrganizeExtensionsRefactoring)
+import Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions (organizeExtensionsRefactoring, projectOrganizeExtensionsRefactoring, highlightExtensionsQuery)
 import Language.Haskell.Tools.Refactor.Builtin.OrganizeImports (organizeImportsRefactoring, projectOrganizeImportsRefactoring)
 import Language.Haskell.Tools.Refactor.Builtin.RenameDefinition (renameDefinitionRefactoring)
 import Language.Haskell.Tools.Refactor.Builtin.GetMatches (getMatchesQuery)
@@ -30,4 +30,4 @@     ]
 
 builtinQueries :: [QueryChoice]
-builtinQueries = [ getMatchesQuery ]+builtinQueries = [ getMatchesQuery, highlightExtensionsQuery ]
Language/Haskell/Tools/Refactor/Builtin/AutoCorrect.hs view
@@ -1,4 +1,8 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds, ScopedTypeVariables, TupleSections, ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.AutoCorrect (autoCorrect, tryItOut, autoCorrectRefactoring) where
 
@@ -6,14 +10,14 @@ import GHC
 import Type
 -- import Outputable
--- 
+--
 import Control.Monad.State
 import Control.Reference
 import Data.List
 import Data.Maybe
--- 
+--
 import Language.Haskell.Tools.Refactor as HT
--- 
+--
 import Language.Haskell.Tools.PrettyPrint
 
 autoCorrectRefactoring :: RefactoringChoice
@@ -46,7 +50,7 @@        if not (isJust (appTypeMatches insts funTy [arg1Ty, arg2Ty])) && isJust (appTypeMatches insts funTy [arg2Ty, arg1Ty])
           then put True >> return (exprArg .= a1 $ exprFun&exprArg .= a2 $ e)
           else return e
-reOrderExpr insts e@(InfixApp lhs op rhs) 
+reOrderExpr insts e@(InfixApp lhs op rhs)
   = do let funTy = idType $ semanticsId (op ^. operatorName)
        lhsTy <- lift $ typeExpr lhs
        rhsTy <- lift $ typeExpr rhs
@@ -86,9 +90,9 @@ 
 extractAtoms :: Expr -> Ghc [(GHC.Type, Atom)]
 extractAtoms e = do lits <- mapM (\l -> (, LiteralA l) <$> literalType l) (e ^? biplateRef)
-                    return $ sortOn (srcSpanStart . atomRange . snd) 
-                           $ map (\n -> (idType $ semanticsId (n ^. simpleName), NameA n)) (e ^? biplateRef) 
-                               ++ map (\o -> (idType $ semanticsId (o ^. operatorName), OperatorA o)) (e ^? biplateRef) 
+                    return $ sortOn (srcSpanStart . atomRange . snd)
+                           $ map (\n -> (idType $ semanticsId (n ^. simpleName), NameA n)) (e ^? biplateRef)
+                               ++ map (\o -> (idType $ semanticsId (o ^. operatorName), OperatorA o)) (e ^? biplateRef)
                                ++ lits
 
 atomRange :: Atom -> SrcSpan
@@ -116,17 +120,17 @@   where reduceFunctionApp ls i | Just (funT, fun) <- lookup i ls
                                , Just (argT, arg) <- lookup (i+1) ls
                                , Just (subst, resTyp) <- appTypeMatches insts funT [argT]
-          = Just $ map ((_1 .- substTy subst) . snd) (take i ls) 
-                     ++ [(resTyp, mkParen' (mkApp' fun arg))] 
+          = Just $ map ((_1 .- substTy subst) . snd) (take i ls)
+                     ++ [(resTyp, mkParen' (mkApp' fun arg))]
                      ++ map ((_1 .- substTy subst) . snd) (drop (i + 2) ls)
         reduceFunctionApp _ _ = Nothing
-        
+
         reduceOperatorApp ls i | Just (opT, Left (OperatorA op)) <- lookup i ls
                                , Just (lArgT, lArg) <- lookup (i-1) ls
                                , Just (rArgT, rArg) <- lookup (i+1) ls
                                , Just (subst, resTyp) <- appTypeMatches insts opT [lArgT, rArgT]
-          = Just $ map ((_1 .- substTy subst) . snd) (take (i - 1) ls) 
-                     ++ [(resTyp, mkParen' (mkInfixApp' lArg op rArg))] 
+          = Just $ map ((_1 .- substTy subst) . snd) (take (i - 1) ls)
+                     ++ [(resTyp, mkParen' (mkInfixApp' lArg op rArg))]
                      ++ map ((_1 .- substTy subst) . snd) (drop (i + 2) ls)
         reduceOperatorApp _ _ = Nothing
 
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers.hs view
@@ -6,11 +6,13 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.BangPatternsChecker            as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ConstraintKindsChecker         as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ConstrainedClassMethodsChecker as X
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.CPPChecker                     as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DefaultSignaturesChecker       as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DerivingsChecker               as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ExplicitForAllChecker          as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ExplicitNamespacesChecker      as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker       as X
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleContextsChecker        as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FunctionalDependenciesChecker  as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.GADTsChecker                   as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.KindSignaturesChecker          as X
@@ -29,4 +31,5 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeOperatorsChecker           as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeSynonymInstancesChecker    as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UnboxedTuplesChecker           as X
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UndecidableInstancesChecker    as X
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ViewPatternsChecker            as X
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ArrowsChecker.hs view
@@ -4,9 +4,9 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
 chkArrowsExpr :: CheckNode Expr
--- chkArrowsExpr e@Proc{}     = addOccurence Arrows e
-chkArrowsExpr e@ArrowApp{} = addOccurence Arrows e
+-- chkArrowsExpr e@Proc{}     = addEvidence Arrows e
+chkArrowsExpr e@ArrowApp{} = addEvidence Arrows e
 chkArrowsExpr e            = return e
 
 chkArrowsCmd :: CheckNode Cmd
-chkArrowsCmd = addOccurence Arrows
+chkArrowsCmd = addEvidence Arrows
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/BangPatternsChecker.hs view
@@ -7,7 +7,7 @@ chkBangPatterns = conditional chkBangPatterns' BangPatterns
 
 chkBangPatterns' :: CheckNode Pattern
-chkBangPatterns' p@(BangPat _) = addOccurence BangPatterns p
+chkBangPatterns' p@(BangPat _) = addEvidence BangPatterns p
 chkBangPatterns' x = return x
 
 {-
+ Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/CPPChecker.hs view
@@ -0,0 +1,45 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.CPPChecker where
+
+import GHC hiding (Module)
+import StringBuffer
+
+import Data.List (isSubsequenceOf)
+import Data.String (fromString)
+import Text.PortableLines.ByteString.Lazy (lines8)
+
+import Language.Haskell.Tools.PrettyPrint
+import Language.Haskell.Tools.Refactor
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
+
+gblChkCPP :: CheckNode Module
+gblChkCPP = conditional gblChkCPP' Cpp
+
+-- TODO (after GHC upgrade): Rewrite this with mgLookupModule
+gblChkCPP' :: CheckNode Module
+gblChkCPP' m = do
+  ms <- getModSummary . moduleName . semanticsModule $ m
+  let cppSrc = preprocessedSrc ms
+  case ml_hs_file . ms_location $ ms of
+    Just fp -> do
+      let lines'  = lines8 . fromString
+          cppSrc' = lines' . rmDefaultIncludes fp $ cppSrc
+          origSrc = lines' . prettyPrint $ m
+      when (cppSrc' /= origSrc) (addEvidenceLoc Cpp noSrcSpan)
+    _ -> addEvidenceLoc Cpp noSrcSpan
+  return m
+
+-- CPP inserts a line before and after the default includes,
+-- that contain the filepath of the module.
+-- We want to remove these lines, and everything between them.
+rmDefaultIncludes :: FilePath -> String -> String
+rmDefaultIncludes fp = unlines . tail
+                     . dropWhile (not . (fp `isSubsequenceOf`))
+                     . tail . lines
+
+-- | Returns the preprocessed source code.
+-- If it is not present, it returns an empty string.
+preprocessedSrc :: ModSummary -> String
+preprocessedSrc = maybe "" strBufToStr . ms_hspp_buf
+
+strBufToStr :: StringBuffer -> String
+strBufToStr sb@(StringBuffer _ len _) = lexemeToString sb len
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ConstrainedClassMethodsChecker.hs view
@@ -22,7 +22,7 @@   mNeedsCCM <- runMaybeT . chkCCMDeclHead' $ dh
   case mNeedsCCM of
     Just False -> return dh
-    _          -> addOccurence ConstrainedClassMethods dh
+    _          -> addEvidence ConstrainedClassMethods dh
 
 
 -- | Helper function for chkCCMDeclHead.
@@ -31,7 +31,7 @@ -- fails <=> Lookup is unsuccesful (either name or type lookup)
 chkCCMDeclHead' :: DeclHead -> MaybeT ExtMonad Bool
 chkCCMDeclHead' dh = do
-  sname   <- declHeadSemName dh
+  sname   <- liftMaybe . declHeadSemName $ dh
   tything <- MaybeT . GHC.lookupName $ sname
   case tything of
     GHC.ATyCon tc | GHC.isClassTyCon tc -> liftMaybe . fmap classNeedsCCM . GHC.tyConClass_maybe $ tc
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ConstraintKindsChecker.hs view
@@ -20,12 +20,12 @@   -- Has any constraints of form (x t1 t2)
   | ctxts <- universeBi rhs :: [Context]
   , any hasTyVarHeadAsserts ctxts
-  = addOccurence ConstraintKinds d
+  = addEvidence ConstraintKinds d
   -- Right-hand side has kind Constraint
   | otherwise = do
   let ty = typeOrKindFromId . declHeadQName $ dh
   if hasConstraintKind ty || returnsConstraintKind ty
-     then addOccurence ConstraintKinds d
+     then addEvidence ConstraintKinds d
      else return d
 chkConstraintKindsDecl' d = return d
 
@@ -40,9 +40,3 @@   | Just assertions <- ta ^? innerAsserts & annListElems
   = any hasAnyTyVarHeads assertions
 hasAnyTyVarHeads _ = False
-
-declHeadQName :: DeclHead -> QualifiedName
-declHeadQName (NameDeclHead n)       = n ^. simpleName
-declHeadQName (ParenDeclHead dh)     = declHeadQName dh
-declHeadQName (DeclHeadApp dh _)     = declHeadQName dh
-declHeadQName (InfixDeclHead _ op _) = op ^. operatorName
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/DefaultSignaturesChecker.hs view
@@ -4,5 +4,5 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
 chkDefaultSigs :: CheckNode ClassElement
-chkDefaultSigs ce@ClsDefaultSig{} = addOccurence DefaultSignatures ce
+chkDefaultSigs ce@ClsDefaultSig{} = addEvidence DefaultSignatures ce
 chkDefaultSigs x = return x
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/DerivingsChecker.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE FlexibleContexts, MultiWayIf, ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE ViewPatterns #-}
 
 
 {-
@@ -130,14 +132,14 @@ 
 chkGADTDataDecl :: CheckNode Decl
 chkGADTDataDecl d@(GADTDataDecl keyw _ _ _ _ derivs) = do
-  addOccurence_ GADTs d
+  addEvidence_ GADTs d
   annList !~ separateByKeyword keyw $ derivs
   return d
 chkGADTDataDecl d = return d
 
 chkDataInstance :: CheckNode Decl
 chkDataInstance d@(DataInstance keyw _ _ derivs) = do
-  addOccurence_ TypeFamilies d
+  addEvidence_ TypeFamilies d
   annList !~ separateByKeyword keyw $ derivs
   return d
 chkDataInstance d = return d
@@ -158,7 +160,7 @@ addExtension :: (MonadState ExtMap m, HasRange node) =>
                  GHC.Name -> node -> m node
 addExtension sname
-  | Just ext <- whichExtension sname = addOccurence ext
+  | Just ext <- whichExtension sname = addEvidence ext
   | otherwise                        = return
 
 addStockExtension :: CheckNode InstanceHead
@@ -169,15 +171,15 @@ chkByStrat :: CheckNode InstanceHead -> CheckNode Deriving
 chkByStrat checker d
   | Just strat <- getStrategy d = do
-    addOccurence DerivingStrategies d
+    addEvidence DerivingStrategies d
     chkDerivingClause (chkStrat strat) d
   | otherwise =
     chkDerivingClause checker d
 
 chkStrat :: DeriveStrategy -> CheckNode InstanceHead
 chkStrat (_element -> UStockStrategy)    = addStockExtension
-chkStrat (_element -> UNewtypeStrategy)  = addOccurence GeneralizedNewtypeDeriving
-chkStrat (_element -> UAnyClassStrategy) = addOccurence DeriveAnyClass
+chkStrat (_element -> UNewtypeStrategy)  = addEvidence GeneralizedNewtypeDeriving
+chkStrat (_element -> UAnyClassStrategy) = addEvidence DeriveAnyClass
 
 chkDerivingClause :: CheckNode InstanceHead -> CheckNode Deriving
 chkDerivingClause checker d@(DerivingOne   x)  = checker x               >> return d
@@ -195,21 +197,21 @@ chkClassForData :: CheckNode InstanceHead
 chkClassForData x
   | Just sname <- nameFromStock x = addExtension sname x
-  | otherwise = addOccurence DeriveAnyClass x
+  | otherwise = addEvidence DeriveAnyClass x
 
 -- performs check in case no explicit strategy is given
 chkClassForNewtype :: CheckNode InstanceHead
 chkClassForNewtype x
   | Just sname <- nameFromStock x
     = if | gndNotNeeded  sname -> return x
-         | gndNeeded     sname -> addOccurence GeneralizedNewtypeDeriving x
+         | gndNeeded     sname -> addEvidence GeneralizedNewtypeDeriving x
          | gndNotAllowed sname -> addExtension sname x
   | otherwise = do
       gndOn       <- isTurnedOn GeneralizedNewtypeDeriving
       deriveAnyOn <- isTurnedOn DeriveAnyClass
-      if | gndOn && deriveAnyOn -> addOccurence_ DeriveAnyClass x
-         | deriveAnyOn          -> addOccurence_ DeriveAnyClass x
-         | gndOn                -> addOccurence_ GeneralizedNewtypeDeriving x
+      if | gndOn && deriveAnyOn -> addEvidence_ DeriveAnyClass x
+         | deriveAnyOn          -> addEvidence_ DeriveAnyClass x
+         | gndOn                -> addEvidence_ GeneralizedNewtypeDeriving x
          | otherwise             -> return ()
       return x
 
@@ -220,12 +222,12 @@ chkStandaloneDeriving :: CheckNode Decl
 chkStandaloneDeriving d@(Refact.StandaloneDeriving strat _ (decompRule -> (cls,ty)))
   | Just strat' <- strat = do
-    addOccurence_  Ext.DerivingStrategies d
-    addOccurence_  Ext.StandaloneDeriving d
+    addEvidence_  Ext.DerivingStrategies d
+    addEvidence_  Ext.StandaloneDeriving d
     chkStrat strat' cls
     return d
   | otherwise = do
-    addOccurence_  Ext.StandaloneDeriving d
+    addEvidence_  Ext.StandaloneDeriving d
     itIsNewType    <- isNewtype ty
     itIsSynNewType <- isSynNewType ty
     if itIsNewType || itIsSynNewType
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ExplicitForAllChecker.hs view
@@ -11,7 +11,7 @@   where chkType :: CheckNode Type
         chkType t
           | UTyForall{} <- t ^. element
-          = addOccurence ExplicitForAll t
+          = addEvidence ExplicitForAll t
           | otherwise = return t
 
 chkExplicitForAllConDecl :: CheckNode ConDecl
@@ -23,5 +23,5 @@ chkQuantifiedTyVarsWith :: HasRange a => (a -> TyVarList) -> CheckNode a
 chkQuantifiedTyVarsWith getTyVars conDecl =
   if (annLength . getTyVars $ conDecl) > 0
-    then addOccurence ExplicitForAll conDecl
+    then addEvidence ExplicitForAll conDecl
     else return conDecl
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ExplicitNamespacesChecker.hs view
@@ -10,5 +10,5 @@ chkExplicitNamespacesIESpec = conditional chkIESpec ExplicitNamespaces
   where chkIESpec :: CheckNode IESpec
         chkIESpec x@(IESpec (AnnJust imod) _ _)
-          | UImportType <- imod ^. element = addOccurence ExplicitNamespaces x
+          | UImportType <- imod ^. element = addEvidence ExplicitNamespaces x
         chkIESpec x = return x
+ Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/FlexibleContextsChecker.hs view
@@ -0,0 +1,162 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleContextsChecker where
+
+import Kind (returnsConstraintKind)
+import TcType (tcSplitNestedSigmaTys, checkValidClsArgs)
+import Type hiding (Type(..))
+import PrelNames (eqTyConName, eqTyConKey)
+import Unique (hasKey)
+import qualified Name as GHC
+import qualified GHC
+
+import Data.List
+import Data.Generics.Uniplate.Data()
+import Data.Generics.Uniplate.Operations
+
+import Control.Reference ((^.))
+
+import Language.Haskell.Tools.AST
+import Language.Haskell.Tools.Refactor
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
+
+gblChkQNamesForFC :: CheckNode Module
+gblChkQNamesForFC = conditional gblChkQNamesForFC' FlexibleContexts
+
+chkFlexibleContexts :: CheckNode Context
+chkFlexibleContexts = conditional chkFlexibleContexts' FlexibleContexts
+
+chkFlexibleContexts' :: CheckNode Context
+chkFlexibleContexts' ctx@(Context a) = chkAssertion a >> return ctx
+
+chkAssertion :: CheckNode Assertion
+chkAssertion a@(ClassAssert con annTys) = do
+  -- If a lookup fails, add MissingInformation FlexibleContexts
+  let errDefault = addMI FlexibleContexts a >> return False
+  isClass <- fromMaybeTM errDefault (isClassTyConNameM con)
+  if not isClass || all hasTyVarHead (annTys ^. annListElems)
+    then return a
+    else addEvidence FlexibleContexts a
+chkAssertion a@(InfixAssert lhs op rhs)
+  -- If the constraint is of form a ~ b, then we dont need to check
+  | Just name <- semanticsName op
+  , name == eqTyConName
+  = return a
+  -- If the constraint has only type variable heads, it doesn't need FlexibleContexts
+  | hasTyVarHead lhs && hasTyVarHead rhs = return a
+  -- In any other case, we keep FlexibleContexts
+  | otherwise = addEvidence FlexibleContexts a
+chkAssertion a@(TupleAssert xs) = do
+  mapM_ chkAssertion xs
+  return a
+chkAssertion a@ImplicitAssert{} = return a
+
+chkFlexibleContextsDecl :: CheckNode Decl
+chkFlexibleContextsDecl = conditional chkFlexibleContextsDecl' FlexibleContexts
+
+chkFlexibleContextsDecl' :: CheckNode Decl
+chkFlexibleContextsDecl' d@(TypeDecl dh rhs) = do
+  let ty = typeOrKindFromId . declHeadQName $ dh
+  when (hasConstraintKind ty || returnsConstraintKind ty)
+       (chkClassesInside rhs)
+  return d
+chkFlexibleContextsDecl' d = return d
+
+-- | Checks whether all type class applications in a type synonym rhs
+-- (that has kind Constraint) have only type variable heads.
+-- Returns False if a lookup inside is not succesful.
+-- If it isn't applied to a type that has kind Constraint, it may give
+-- false positive results.
+chkClassesInside :: Type -> ExtMonad ()
+chkClassesInside (TupleType annTys) =
+  mapM_ chkClassesInside (annTys ^. annListElems)
+chkClassesInside t = maybe (addFC t) f (splitTypeAppMaybe t)
+  where
+    addFC :: Type -> ExtMonad ()
+    addFC = addEvidence_ FlexibleContexts
+
+    f :: (GHC.Name, [Type]) -> ExtMonad ()
+    f (n,args) = do
+       isClass <- isJustT . lookupClass $ n
+       when (n /= eqTyConName && isClass && any (not . hasTyVarHead) args)
+            (addFC t)
+
+    -- Separates the type into its head and its arguments.
+    -- This functions should only be applied to types that have kind Constraint.
+    splitTypeAppMaybe :: Type -> Maybe (GHC.Name, [Type])
+    splitTypeAppMaybe (TypeApp f arg) = do
+      (f', args) <- splitTypeAppMaybe f
+      return (f', args ++ [arg])
+    splitTypeAppMaybe (InfixTypeApp lhs op rhs) = do
+      opName <- semanticsName op
+      return (opName, [lhs,rhs])
+    splitTypeAppMaybe (VarType n) = do
+      sname <- semanticsName n
+      return (sname, [])
+    splitTypeAppMaybe (ParenType t) = splitTypeAppMaybe t
+    splitTypeAppMaybe (KindedType t _) = splitTypeAppMaybe t
+    splitTypeAppMaybe _ = Nothing
+
+
+chkQNameForFC :: QualifiedName -> ExtMonad Bool
+chkQNameForFC name = do
+  mty <- runMaybeT . lookupTypeFromId $ name
+  case mty of
+    Just ty -> do
+      -- First we get all subtypes of the given type, while expanding all type synonyms,
+      -- then we remove all implicit predicates,
+      -- and partition the types into predicate types and theta types.
+      let expanded = expandTypeSynonyms ty
+          subTys = universeBi expanded :: [GHC.Type]
+          (preds, tys) = partition isPredTy . filter (not . isIPPred) $ subTys
+
+          -- We don't need type equalities, so we get rid of them and their children.
+          -- Then we extract the constraints from the types.
+          nomEqs = universeBi (filter isNominalEqPred preds) :: [GHC.Type]
+          preds' = preds \\ nomEqs
+          thetas = concatMap (snd' . tcSplitNestedSigmaTys) tys
+
+          -- We split each theta type into its class tycon and its arguments.
+          -- We also filter out tuple constraints
+          -- (we already have the constraints in it).
+          xs = mapMaybe getClassPredTys_maybe (thetas ++ preds')
+          xs' = filter (not . isCTupleClass . fst) xs
+
+      if all (uncurry hasValidClsArgs) xs' then return False
+                                           else return True
+    Nothing -> return False
+  where
+    hasValidClsArgs :: GHC.Class -> [GHC.Type] -> Bool
+    hasValidClsArgs cls args = cls `hasKey` eqTyConKey
+                            || isIPClass cls
+                            || checkValidClsArgs False cls args
+
+    snd' :: (a,b,c) -> b
+    snd' (_,x,_) = x
+
+    isNominalEqPred :: GHC.Type -> Bool
+    isNominalEqPred ty
+      | Just (tc,_) <- splitTyConApp_maybe ty = tc `hasKey` eqTyConKey
+      | otherwise = False
+
+gblChkQNamesForFC' :: CheckNode Module
+gblChkQNamesForFC' m = do
+  -- Names appearing on the rhs of bindings are just hints,
+  -- they don't necessarily require FlexibleContexts.
+  let allNames   = universeBi (m ^. modDecl) :: [QualifiedName]
+      rhs        = universeBi (m ^. modDecl) :: [Rhs]
+      hints      = universeBi rhs            :: [QualifiedName]
+
+      -- Separating hints from evidence,
+      -- and grouping them together based on their GHC.Name
+      evidence  = filter (isJust . semanticsName) (allNames \\ hints)
+      hints'    = filter (isJust . semanticsName) hints
+      groupedEs = equivalenceGroupsBy semanticsName evidence
+      groupedHs = equivalenceGroupsBy semanticsName hints'
+
+  -- Checking the representative elements, whether they need FC,
+  -- if they do, add occurences for every node in their group.
+  es <- filterM (chkQNameForFC . fst) groupedEs
+  hs <- filterM (chkQNameForFC . fst) groupedHs
+  mapM_ (addEvidence FlexibleContexts) (concatMap snd es)
+  mapM_ (addHint     FlexibleContexts) (concatMap snd hs)
+
+  return m
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/FlexibleInstancesChecker.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE FlexibleContexts, GADTs, MultiWayIf #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiWayIf #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker where
 
@@ -48,7 +50,7 @@   mCls <- runMaybeT . lookupClassFromInstance $ ih
   case mCls of
     Just cls -> mapM_ (chkTypeArg cls) types >> return ih
-    Nothing  -> addOccurence FlexibleInstances ih
+    Nothing  -> addMI FlexibleInstances ih
 
 -- | Checks a type argument of class whether it needs FlexibleInstances
 -- First checks the structure of the type argument opaquely
@@ -56,8 +58,8 @@ -- needs the extension.
 --
 -- Might find false positive occurences for phantom types:
--- > type Phatom a b = [a]
--- > instance C (Phatnom a a)
+-- > type Phantom a b = [a]
+-- > instance C (Phantom a a)
 -- > instance C (Phantom a Int)
 chkTypeArg :: GHC.Class -> Type -> ExtMonad Type
 chkTypeArg cls ty = do
@@ -65,7 +67,7 @@   maybeTM (return ty) (chkSynonymTypeArg cls) (semanticsTypeSynRhs ty)
   where chkSynonymTypeArg :: GHC.Class -> GHC.Type -> ExtMonad Type
         chkSynonymTypeArg cls' ty'
-          | tyArgNeedsFI cls' ty' = addOccurence FlexibleInstances ty
+          | tyArgNeedsFI cls' ty' = addEvidence FlexibleInstances ty
           | otherwise             = return ty
 
 -- | Checks a type argument of class whether it has only (distinct) type variable arguments.
@@ -77,7 +79,7 @@           case isOk of
             Just isOk ->
               unless (isOk && length vs == (length . nubBy ((==) `on` (semanticsName . (^. simpleName))) $ vs)) --tyvars are different
-                (addOccurence_ FlexibleInstances vars)
+                (addEvidence_ FlexibleInstances vars)
             Nothing   -> error "chkNormalTypeArg: Couldn't look up something"
           return vars
 
@@ -153,7 +155,7 @@ rmTypeMisc (ParenType x)    = x
 rmTypeMisc x                = x
 
--- Decides whether a type argument of a type class constructor need FlexibleInstances
+-- Decides whether a type argument of a type class constructor needs FlexibleInstances
 tyArgNeedsFI :: GHC.Class -> GHC.Type -> Bool
 tyArgNeedsFI cls arg = not . hasOnlyDistinctTyVars $ tyArg
   where [tyArg] = GHC.filterOutInvisibleTypes (GHC.classTyCon cls) [arg]
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/FunctionalDependenciesChecker.hs view
@@ -4,4 +4,4 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
 chkFunDeps :: CheckNode FunDepList
-chkFunDeps = addOccurence FunctionalDependencies
+chkFunDeps = addEvidence FunctionalDependencies
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/GADTsChecker.hs view
@@ -1,6 +1,7 @@+{-# LANGUAGE MultiWayIf #-}
+
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.GADTsChecker where
 
-import Data.Maybe (catMaybes, fromMaybe)
 import Control.Reference ((^.), (&))
 import Control.Monad.Trans.Maybe (MaybeT(..))
 
@@ -20,20 +21,26 @@ chkConDeclForExistentials :: CheckNode ConDecl
 chkConDeclForExistentials = conditionalAny chkConDeclForExistentials' [GADTs, ExistentialQuantification]
 
--- If all data constructors are vanilla Haskell 98 data constructors, then only GADTSyntax is needed.
+-- | Checks whether a GADTs-style constructor declaration requires GADTs.
+-- If all data constructors are vanilla Haskell 98 data constructors
+-- , then only GADTSyntax is needed. If any constructor's lookup fails
+-- , we add MissingInformation.
 chkGADTsGadtConDecl' :: CheckNode GadtConDecl
 chkGADTsGadtConDecl' conDecl = do
-  let conNames = conDecl ^. (gadtConNames & annListElems)
+  let conNames   = conDecl ^. (gadtConNames & annListElems)
   mres <- mapM (runMaybeT . isVanillaDataConNameM) conNames
-  if and . catMaybes $ mres
-    then addOccurence GADTSyntax conDecl
-    else do addOccurence GADTSyntax conDecl
-            addRelation (GADTs `lOr` ExistentialQuantification) conDecl
+  addEvidence_ GADTSyntax conDecl
+  if | any isNothing mres ->
+       addRelationMI (GADTs `lOr` ExistentialQuantification) conDecl
+     | any (not . fromJust) mres ->
+       addRelation (GADTs `lOr` ExistentialQuantification) conDecl
+     | otherwise -> return conDecl
 
--- Extracts the name from a ConDecl, and checks whether it is a vanilla
--- data constructor.
+-- | Extracts the name from a ConDecl, and checks whether it is a vanilla
+-- data constructor. Ifthe lookup fails, adds MissingInformation.
 chkConDeclForExistentials' :: CheckNode ConDecl
-chkConDeclForExistentials' conDecl = liftM (fromMaybe conDecl) . runMaybeT $
+chkConDeclForExistentials' conDecl =
+  fromMaybeTM (addRelationMI (GADTs `lOr` ExistentialQuantification) conDecl) $
   case conDecl ^. element of
     UConDecl _ _ n _         -> chkName n
     URecordDecl _ _ n _      -> chkName n
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/KindSignaturesChecker.hs view
@@ -5,4 +5,4 @@ 
 chkKindSignaturesKind :: CheckNode Kind
 chkKindSignaturesKind = conditional chkKind KindSignatures
-  where chkKind = addOccurence KindSignatures
+  where chkKind = addEvidence KindSignatures
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/LambdaCaseChecker.hs view
@@ -7,7 +7,7 @@ chkLambdaCase = conditional chkLambdaCase' Ext.LambdaCase
 
 chkLambdaCase' :: CheckNode Expr
-chkLambdaCase' e@(Refact.LambdaCase _) = addOccurence Ext.LambdaCase e
+chkLambdaCase' e@(Refact.LambdaCase _) = addEvidence Ext.LambdaCase e
 chkLambdaCase' e = return e
 
 
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/MagicHashChecker.hs view
@@ -18,23 +18,23 @@ 
 
 chkMagicHashLiteral' :: CheckNode Literal
-chkMagicHashLiteral' l@(PrimIntLit _)    = addOccurence MagicHash l
-chkMagicHashLiteral' l@(PrimWordLit _)   = addOccurence MagicHash l
-chkMagicHashLiteral' l@(PrimFloatLit _)  = addOccurence MagicHash l
-chkMagicHashLiteral' l@(PrimDoubleLit _) = addOccurence MagicHash l
-chkMagicHashLiteral' l@(PrimCharLit _)   = addOccurence MagicHash l
-chkMagicHashLiteral' l@(PrimStringLit _) = addOccurence MagicHash l
+chkMagicHashLiteral' l@(PrimIntLit _)    = addEvidence MagicHash l
+chkMagicHashLiteral' l@(PrimWordLit _)   = addEvidence MagicHash l
+chkMagicHashLiteral' l@(PrimFloatLit _)  = addEvidence MagicHash l
+chkMagicHashLiteral' l@(PrimDoubleLit _) = addEvidence MagicHash l
+chkMagicHashLiteral' l@(PrimCharLit _)   = addEvidence MagicHash l
+chkMagicHashLiteral' l@(PrimStringLit _) = addEvidence MagicHash l
 chkMagicHashLiteral' l = return l
 
 
 chkMagicHashNamePart' :: CheckNode NamePart
 chkMagicHashNamePart' n@(NamePart name) =
-  if (last name == '#') then addOccurence MagicHash n
+  if (last name == '#') then addEvidence MagicHash n
                         else return n
 
 -- NOTE: is this really needed?
 chkMagicHashKind' :: CheckNode Kind
-chkMagicHashKind' k@UnboxKind = addOccurence MagicHash k
+chkMagicHashKind' k@UnboxKind = addEvidence MagicHash k
 chkMagicHashKind' k = return k
 
 {- Name can be reached from:
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/MultiParamTypeClassesChecker.hs view
@@ -14,10 +14,10 @@ chkMultiParamTypeClassesDecl' :: CheckNode Decl
 chkMultiParamTypeClassesDecl' cd@(ClassDecl _ dh _ _)
   | n <- length . collectTyVars $ dh
-  , n /= 1 = addOccurence MultiParamTypeClasses dh >> return cd
+  , n /= 1 = addEvidence MultiParamTypeClasses dh >> return cd
 chkMultiParamTypeClassesDecl' i@(InstanceDecl rule _)
   | isMultiParamNeeded (rule ^. irHead)
-  = addOccurence MultiParamTypeClasses rule >> return i
+  = addEvidence MultiParamTypeClasses rule >> return i
 chkMultiParamTypeClassesDecl' d = return d
 
 
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/MultiWayIfChecker.hs view
@@ -7,5 +7,5 @@ chkMultiWayIfExpr = conditional chkMultiWayIfExpr' MultiWayIf
 
 chkMultiWayIfExpr' :: CheckNode Expr
-chkMultiWayIfExpr' e@(MultiIf _) = addOccurence MultiWayIf e
+chkMultiWayIfExpr' e@(MultiIf _) = addEvidence MultiWayIf e
 chkMultiWayIfExpr' x = return x
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/OverloadedStringsChecker.hs view
@@ -15,5 +15,5 @@         chkLit lit
           | UStringLit _ <- lit ^. element
           , not . GHC.eqType GHC.stringTy $ semanticsLiteralType lit
-          = addOccurence OverloadedStrings lit
+          = addEvidence OverloadedStrings lit
           | otherwise = return lit
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ParallelListCompChecker.hs view
@@ -6,5 +6,5 @@ 
 chkParallelListComp :: CheckNode Expr
 chkParallelListComp e@(ListComp _ body)
-  | annLength body > 1 = addOccurence ParallelListComp e
+  | annLength body > 1 = addEvidence ParallelListComp e
 chkParallelListComp e = return e
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/PatternSynonymsChecker.hs view
@@ -10,7 +10,7 @@ chkPatternSynonymsSyn = conditional chkPatternSynonymsSyn' PatternSynonyms
 
 chkPatternSynonymsSyn' :: CheckNode PatternSynonym
-chkPatternSynonymsSyn' = addOccurence PatternSynonyms
+chkPatternSynonymsSyn' = addEvidence PatternSynonyms
 
 chkPatternSynonymsTypeSig :: CheckNode PatternSignature
-chkPatternSynonymsTypeSig = conditional (addOccurence PatternSynonyms) PatternSynonyms
+chkPatternSynonymsTypeSig = conditional (addEvidence PatternSynonyms) PatternSynonyms
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/RecordWildCardsChecker.hs view
@@ -7,9 +7,9 @@ --       but we don't really need any contraint.
 
 chkRecordWildCardsPatField :: CheckNode PatternField
-chkRecordWildCardsPatField p@(FieldWildcardPattern {}) = addOccurence RecordWildCards p
+chkRecordWildCardsPatField p@(FieldWildcardPattern {}) = addEvidence RecordWildCards p
 chkRecordWildCardsPatField p = return p
 
 chkRecordWildCardsFieldUpdate :: CheckNode FieldUpdate
-chkRecordWildCardsFieldUpdate e@(FieldWildcard {}) = addOccurence RecordWildCards e
+chkRecordWildCardsFieldUpdate e@(FieldWildcard {}) = addEvidence RecordWildCards e
 chkRecordWildCardsFieldUpdate e = return e
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/RecursiveDoChecker.hs view
@@ -4,9 +4,9 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
 chkRecursiveDoExpr :: CheckNode Expr
-chkRecursiveDoExpr e@MDo{} = addOccurence RecursiveDo e
+chkRecursiveDoExpr e@MDo{} = addEvidence RecursiveDo e
 chkRecursiveDoExpr e = return e
 
 chkRecursiveDoStmt :: CheckNode Stmt
-chkRecursiveDoStmt s@RecStmt{} = addOccurence RecursiveDo s
+chkRecursiveDoStmt s@RecStmt{} = addEvidence RecursiveDo s
 chkRecursiveDoStmt s = return s
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TemplateHaskellChecker.hs view
@@ -8,15 +8,15 @@ 
 -- can be reached from: Decl, Type, Expr, Pattern
 chkTemplateHaskellSplice :: CheckNode Splice
-chkTemplateHaskellSplice = addOccurence TemplateHaskell
+chkTemplateHaskellSplice = addEvidence TemplateHaskell
 
 -- can be reached from: Type, Expr, Pattern
 chkTemplateHaskellQuasiQuote :: CheckNode QuasiQuote
-chkTemplateHaskellQuasiQuote = addOccurence QuasiQuotes
+chkTemplateHaskellQuasiQuote = addEvidence QuasiQuotes
 
 -- can be reached from: Expr
 chkTemplateHaskellBracket :: CheckNode Bracket
-chkTemplateHaskellBracket = addOccurence TemplateHaskellQuotes
+chkTemplateHaskellBracket = addEvidence TemplateHaskellQuotes
 
 chkTemplateHaskellhNamePart :: CheckNode NamePart
 chkTemplateHaskellhNamePart = conditional chkTemplateHaskellNamePart' TemplateHaskellQuotes
@@ -25,5 +25,5 @@ -- should be THQuotes OR DataKinds
 chkTemplateHaskellNamePart' :: CheckNode NamePart
 chkTemplateHaskellNamePart' n@(NamePart name) =
-  if (head name == '\'') then addOccurence TemplateHaskellQuotes n
+  if (head name == '\'') then addEvidence TemplateHaskellQuotes n
                          else return n
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TupleSectionsChecker.hs view
@@ -7,7 +7,7 @@ chkTupleSections = conditional chkTupleSections' TupleSections
 
 chkTupleSections' :: CheckNode Expr
-chkTupleSections' e@(TupleSection        _) = addOccurence TupleSections e
-chkTupleSections' e@(UnboxedTupleSection _) = addOccurence TupleSections e
-                                           >> addOccurence UnboxedTuples e
+chkTupleSections' e@(TupleSection        _) = addEvidence TupleSections e
+chkTupleSections' e@(UnboxedTupleSection _) = addEvidence TupleSections e
+                                           >> addEvidence UnboxedTuples e
 chkTupleSections' e = return e
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TypeFamiliesChecker.hs view
@@ -3,24 +3,22 @@ import TyCon          as GHC (TyCon())
 import PrelNames      as GHC
 import Unique         as GHC (hasKey)
+import Var            as GHC (isTyVar, isId)
 import qualified Type as GHC (expandTypeSynonyms)
 
 import Control.Reference ((^.))
-import Control.Monad.Trans.Maybe (MaybeT(..))
 
-import Data.List (zipWith)
-import Data.Maybe (catMaybes)
+import Data.List ((\\))
 import Data.Generics.Uniplate.Data()
 import Data.Generics.Uniplate.Operations
-import qualified Data.Map.Strict as SMap
 
 import Language.Haskell.Tools.Refactor
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
 
 -- | Checks whether any name's corresponding type in the module contains a type equality.
-globalChkNamesForTypeEq :: CheckNode Module
-globalChkNamesForTypeEq = conditionalAny globalChkNamesForTypeEq' [TypeFamilies, GADTs]
+gblChkQNamesForTypeEq :: CheckNode Module
+gblChkQNamesForTypeEq = conditionalAny gblChkQNamesForTypeEq' [TypeFamilies, GADTs]
 
 -- | Checks an operator for syntactic evidence of a ~ b type equality if TypeFamilies or GADTs is turned on.
 chkOperatorForTypeEq :: CheckNode Operator
@@ -42,24 +40,24 @@ 
 
 chkTypeFamiliesDecl' :: CheckNode Decl
-chkTypeFamiliesDecl' d@TypeFamily{}       = addOccurence TypeFamilies d
-chkTypeFamiliesDecl' d@DataFamily{}       = addOccurence TypeFamilies d
-chkTypeFamiliesDecl' d@ClosedTypeFamily{} = addOccurence TypeFamilies d
-chkTypeFamiliesDecl' d@TypeInstance{}     = addOccurence TypeFamilies d
-chkTypeFamiliesDecl' d@DataInstance{}     = addOccurence TypeFamilies d
-chkTypeFamiliesDecl' d@GadtDataInstance{} = addOccurence TypeFamilies d
+chkTypeFamiliesDecl' d@TypeFamily{}       = addEvidence TypeFamilies d
+chkTypeFamiliesDecl' d@DataFamily{}       = addEvidence TypeFamilies d
+chkTypeFamiliesDecl' d@ClosedTypeFamily{} = addEvidence TypeFamilies d
+chkTypeFamiliesDecl' d@TypeInstance{}     = addEvidence TypeFamilies d
+chkTypeFamiliesDecl' d@DataInstance{}     = addEvidence TypeFamilies d
+chkTypeFamiliesDecl' d@GadtDataInstance{} = addEvidence TypeFamilies d
 chkTypeFamiliesDecl' d                    = return d
 
 chkTypeFamiliesClassElement' :: CheckNode ClassElement
-chkTypeFamiliesClassElement' ce@ClassElemTypeFam{} = addOccurence TypeFamilies ce
-chkTypeFamiliesClassElement' ce@ClassElemDataFam{} = addOccurence TypeFamilies ce
-chkTypeFamiliesClassElement' ce@ClsDefaultType{}   = addOccurence TypeFamilies ce
+chkTypeFamiliesClassElement' ce@ClassElemTypeFam{} = addEvidence TypeFamilies ce
+chkTypeFamiliesClassElement' ce@ClassElemDataFam{} = addEvidence TypeFamilies ce
+chkTypeFamiliesClassElement' ce@ClsDefaultType{}   = addEvidence TypeFamilies ce
 chkTypeFamiliesClassElement' ce                    = return ce
 
 chkTypeFamiliesInstBodyDecl' :: CheckNode InstBodyDecl
-chkTypeFamiliesInstBodyDecl' b@InstanceTypeFamilyDef{}     = addOccurence TypeFamilies b
-chkTypeFamiliesInstBodyDecl' b@InstanceDataFamilyDef{}     = addOccurence TypeFamilies b
-chkTypeFamiliesInstBodyDecl' b@InstanceDataFamilyGADTDef{} = addOccurence TypeFamilies b
+chkTypeFamiliesInstBodyDecl' b@InstanceTypeFamilyDef{}     = addEvidence TypeFamilies b
+chkTypeFamiliesInstBodyDecl' b@InstanceDataFamilyDef{}     = addEvidence TypeFamilies b
+chkTypeFamiliesInstBodyDecl' b@InstanceDataFamilyGADTDef{} = addEvidence TypeFamilies b
 chkTypeFamiliesInstBodyDecl' b                             = return b
 
 
@@ -70,31 +68,59 @@   = addRelation (TypeFamilies `lOr` GADTs) op
   | otherwise = return op
 
-chkNameForTyEqn :: CheckNode Name
-chkNameForTyEqn name = do
-  mty <- runMaybeT . lookupTypeFromId $ name
-  case mty of
-    Just ty -> do
+-- | Checks whether a given name's has a type equality operator in it.
+-- If the type lookup fails, it returns Nothing. If given a type variable,
+-- it returns False.
+chkQNameForTyEqn :: QualifiedName -> MaybeT ExtMonad Bool
+chkQNameForTyEqn name =
+  if not . isId . semanticsId $ name
+    then return False
+    else do
+      ty <- lookupTypeFromId name
       let ty'    = GHC.expandTypeSynonyms ty
           tycons = universeBi ty' :: [GHC.TyCon]
-      if any isEqTyCon tycons then addRelation (TypeFamilies `lOr` GADTs) name
-                              else return name
-    Nothing -> return name
+      if any isEqTyCon tycons then return True
+                              else return False
+      where isEqTyCon tc = tc `hasKey` eqTyConKey
+                        || tc `hasKey` heqTyConKey
+                        || tc `hasKey` eqPrimTyConKey
+                        || tc `hasKey` eqReprPrimTyConKey
+                        || tc `hasKey` eqPhantPrimTyConKey
 
-  --traceShow (showName name ++ " -- " ++ showOutputable ty') $
+gblChkQNamesForTypeEq' :: CheckNode Module
+gblChkQNamesForTypeEq' m = do
+  -- Names appearing on the rhs of bindings are just hints,
+  -- they don't necessarily require TypeFamilies.
+  let allNames   = universeBi (m ^. modDecl) :: [QualifiedName]
+      rhs        = universeBi (m ^. modDecl) :: [Rhs]
+      hints      = universeBi rhs            :: [QualifiedName]
 
-  where isEqTyCon tc = tc `hasKey` eqTyConKey
-                    || tc `hasKey` heqTyConKey
-                    || tc `hasKey` eqPrimTyConKey
-                    || tc `hasKey` eqReprPrimTyConKey
-                    || tc `hasKey` eqPhantPrimTyConKey
+      -- Separating hints from evidence,
+      -- and grouping them together based on their GHC.Name
+      evidence  = filter (isJust . semanticsName) (allNames \\ hints)
+      hints'    = filter (isJust . semanticsName) hints
+      groupedEs = equivalenceGroupsBy semanticsName evidence
+      groupedHs = equivalenceGroupsBy semanticsName hints'
 
-globalChkNamesForTypeEq' :: CheckNode Module
-globalChkNamesForTypeEq' m = do
-  let origNames   = universeBi (m ^. modDecl) :: [Name]
-      pairedNames = catMaybes . zipWith zf (map semanticsName origNames) $ origNames
-      uniqueNames = SMap.elems . SMap.fromList . reverse $ pairedNames
-  mapM_ chkNameForTyEqn uniqueNames
+      -- names failed at the semanticsName lookup
+      nmFailedNames = filter (isNothing . semanticsName) allNames
+
+  -- Checking the representative elements, whether they need FC,
+  -- if they do, add occurences for every node in their group.
+  -- If chkQNameForTyEqn fails, we add MissingInformation.
+  let hasTypeEq    = fromMaybeT False . chkQNameForTyEqn
+      failedLookup = isNothingT       . chkQNameForTyEqn
+
+  es <- filterM (hasTypeEq . fst) groupedEs
+  hs <- filterM (hasTypeEq . fst) groupedHs
+  mapM_ (addRelation     (TypeFamilies `lOr` GADTs)) (concatMap snd es)
+  mapM_ (addRelationHint (TypeFamilies `lOr` GADTs)) (concatMap snd hs)
+
+  mapM_ (addRelationMI (TypeFamilies `lOr` GADTs)) nmFailedNames
+
+  -- NOTE: this would result in many false positive results
+  -- names failed at the chkQNameForTyEqn (lookupTypeFromId) stage
+  -- idFailedNames <- filterM failedLookup allNames
+  -- mapM_ (addRelationMI (TypeFamilies `lOr` GADTs)) idFailedNames
+
   return m
-  where zf (Just x) y = Just (x,y)
-        zf _ _        = Nothing
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TypeOperatorsChecker.hs view
@@ -1,13 +1,12 @@ module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeOperatorsChecker where
 
+import PrelNames (eqTyConName)
 import qualified Name    as GHC (nameOccName)
 import qualified OccName as GHC (isTcOcc, isSymOcc)
 
 import Data.Generics.Uniplate.Data()
 import Data.Generics.Uniplate.Operations
 
-import Control.Monad.Trans.Maybe (MaybeT(..))
-
 import Language.Haskell.Tools.Refactor
 import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
 
@@ -32,22 +31,26 @@ 
 
 chkTypeOperatorsType' :: CheckNode Type
-chkTypeOperatorsType' t@InfixTypeApp{} = addOccurence TypeOperators t
+chkTypeOperatorsType' t@(InfixTypeApp _ op _)
+  | Just name <- semanticsName op
+  , name == eqTyConName
+  = return t
+  | otherwise = addEvidence TypeOperators t
 chkTypeOperatorsType' t = return t
 
 chkTypeOperatorsAssertion' :: CheckNode Assertion
-chkTypeOperatorsAssertion' a@InfixAssert{} = addOccurence TypeOperators a
+chkTypeOperatorsAssertion' a@InfixAssert{} = addEvidence TypeOperators a
 chkTypeOperatorsAssertion' a = return a
 
 chkTypeOperatorsInstHead' :: CheckNode InstanceHead
-chkTypeOperatorsInstHead' ih@InfixInstanceHead{} = addOccurence TypeOperators ih
+chkTypeOperatorsInstHead' ih@InfixInstanceHead{} = addEvidence TypeOperators ih
 chkTypeOperatorsInstHead' ih = return ih
 
 chkTypeOperatorsDecl' :: CheckNode Decl
 chkTypeOperatorsDecl' d = do
   let dhs = universeBi d :: [DeclHead]
   anyNeedsTO <- liftM or $ mapM isOperatorM dhs
-  if anyNeedsTO then addOccurence TypeOperators d
+  if anyNeedsTO then addEvidence TypeOperators d
                 else return d
 
 -- OccName: [Type and class operator definitions]
@@ -55,7 +58,7 @@   -- but one that uses an operator OccName.
 isOperatorM :: DeclHead -> ExtMonad Bool
 isOperatorM dh = do
-  mSemName <- runMaybeT . declHeadSemName $ dh
+  let mSemName = declHeadSemName dh
   case mSemName of
     Just semName
       | occ <- GHC.nameOccName semName
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/TypeSynonymInstancesChecker.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MonoLocalBinds #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeSynonymInstancesChecker
   ( chkTypeSynonymInstancesDecl, chkInstancesDeclWith, chkInstanceRuleWith, collectTyArgs) where
@@ -37,7 +38,7 @@ -- | Checks a type argument of class whether it is a synonym
 chkTypeArg :: Type -> ExtMonad Type
 chkTypeArg ty =
-  maybeTM (return ty) (const . addOccurence TypeSynonymInstances $ ty) (semanticsTypeSynRhs ty)
+  maybeTM (return ty) (const . addEvidence TypeSynonymInstances $ ty) (semanticsTypeSynRhs ty)
 
 -- | Collects the type arguments in an instance declaration
 -- Type arguments are the the types that the class is being instantiated with
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/UnboxedTuplesChecker.hs view
@@ -14,14 +14,14 @@ 
 
 chkUnboxedTuplesExpr' :: CheckNode Expr
-chkUnboxedTuplesExpr' e@(UnboxedTuple        _) = addOccurence UnboxedTuples e
-chkUnboxedTuplesExpr' e@(UnboxedTupleSection _) = addOccurence UnboxedTuples e
+chkUnboxedTuplesExpr' e@(UnboxedTuple        _) = addEvidence UnboxedTuples e
+chkUnboxedTuplesExpr' e@(UnboxedTupleSection _) = addEvidence UnboxedTuples e
 chkUnboxedTuplesExpr' e = return e
 
 chkUnboxedTuplesPat' :: CheckNode Pattern
-chkUnboxedTuplesPat' p@(UnboxTuplePat _) = addOccurence UnboxedTuples p
+chkUnboxedTuplesPat' p@(UnboxTuplePat _) = addEvidence UnboxedTuples p
 chkUnboxedTuplesPat' p = return p
 
 chkUnboxedTuplesType' :: CheckNode Type
-chkUnboxedTuplesType' t@(UnboxedTupleType _) = addOccurence UnboxedTuples t
+chkUnboxedTuplesType' t@(UnboxedTupleType _) = addEvidence UnboxedTuples t
 chkUnboxedTuplesType' t = return t
+ Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/UndecidableInstancesChecker.hs view
@@ -0,0 +1,98 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UndecidableInstancesChecker where
+
+import Name
+import CoAxiom
+import FamInstEnv
+import InstEnv
+import TcType
+import GHC hiding (Module, ClassDecl, ClosedTypeFamily)
+
+import Data.Maybe (isJust)
+
+import Control.Reference ((^.))
+import Control.Monad.Trans.Maybe (MaybeT(..))
+
+import Language.Haskell.Tools.AST
+import Language.Haskell.Tools.Refactor
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
+import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.GHCHelpers
+
+
+-- | If UndecidableInstances is turned on,
+-- it checks whether any type class or type family instances needs
+-- UndecidableInstances in the module.
+gblChkUndecidableInstances :: CheckNode Module
+gblChkUndecidableInstances = conditional gblChkUndecidableInstances' UndecidableInstances
+
+-- | Checks whether any type class or type family instances needs
+-- UndecidableInstances in the module.
+gblChkUndecidableInstances' :: CheckNode Module
+gblChkUndecidableInstances' m = do
+  (clsInsts, famInsts) <- getInstances [semanticsModule m]
+  mapM_ chkClsInst clsInsts
+  mapM_ chkFamInst famInsts
+  return m
+
+-- | If the type class instance requires UndecidableInstances,
+-- it adds the occurence with location of the instance.
+chkClsInst :: ClsInst -> ExtMonad ()
+chkClsInst inst = when (clsInstNeedsUD inst)
+                       (addEvidenceLoc UndecidableInstances (getSrcSpan inst))
+
+-- | Decides whether a type class instance requires UndecidableInstances.
+clsInstNeedsUD :: ClsInst -> Bool
+clsInstNeedsUD inst = checkInstTermination args theta
+  where (_, theta, _, args) = instanceSig inst
+
+-- | If the type class instance requires UndecidableInstances,
+-- it adds the occurence with location of the instance.
+chkFamInst :: FamInst -> ExtMonad ()
+chkFamInst inst = when (famInstNeedsUD inst)
+                       (addEvidenceLoc UndecidableInstances (getSrcSpan inst))
+
+-- | Decides whether a family instance requires UndecidableInstances.
+-- If it is a data family instance, it does not need the extension.
+famInstNeedsUD :: FamInst -> Bool
+famInstNeedsUD inst
+  | isTyFamInst inst
+  , lhs <- fi_tys inst
+  , rhs <- tcTyFamInsts . fi_rhs $ inst
+  = checkFamEq lhs rhs
+  | otherwise = False
+
+-- | Checks a declaration whether it needs UndecidableInstances.
+-- (If the extension is turned on)
+chkUndecidableInstancesDecl :: CheckNode Decl
+chkUndecidableInstancesDecl = conditional chkUndecidableInstancesDecl' UndecidableInstances
+
+-- | Checks a declaration whether it needs UndecidableInstances.
+-- If a lookup is not successful, it keeps the extension.
+chkUndecidableInstancesDecl' :: CheckNode Decl
+chkUndecidableInstancesDecl' d = do
+  mDecl <- runMaybeT (chkUndecidableInstancesDeclMaybe d)
+  maybe (addEvidence UndecidableInstances d) return mDecl
+
+-- | Checks a class declaration whether it has a type function in its context,
+-- or a closed type family declaration needs UndecidableInstances.
+-- For more information on the family check, see checkFamInstRhs.
+-- May fail on lookup.
+chkUndecidableInstancesDeclMaybe :: Decl -> MaybeT ExtMonad Decl
+chkUndecidableInstancesDeclMaybe d@(ClassDecl mCtx _ _ _)
+  | isJust (mCtx ^. annMaybe) = do
+    ctx <- liftMaybe $ mCtx ^. annMaybe
+    let assert = ctx ^. contextAssertion
+        names  = assertionQNames assert
+    types <- mapM lookupTypeFromId names
+    if any hasTyFunHead types then addEvidence UndecidableInstances d
+                              else return d
+  | otherwise = return d
+chkUndecidableInstancesDeclMaybe d@(ClosedTypeFamily dh _ _) = do
+  tyFam <- lookupClosedTyFam dh
+  let brs    = fromBranches . coAxiomBranches $ tyFam
+      famEqs = map ((,) <$> coAxBranchLHS <*> tcTyFamInsts . coAxBranchRHS) brs
+  mapM_ (lift . uncurry chkFamEqM) famEqs >> return d
+  where
+    chkFamEqM :: [GHC.Type] -> [(GHC.TyCon, [GHC.Type])] -> ExtMonad ()
+    chkFamEqM lhs rhs = when (checkFamEq lhs rhs)
+                             (addEvidence_ UndecidableInstances d)
+chkUndecidableInstancesDeclMaybe d = return d
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Checkers/ViewPatternsChecker.hs view
@@ -7,5 +7,5 @@ chkViewPatterns = conditional chkViewPatterns' ViewPatterns
 
 chkViewPatterns' :: CheckNode Pattern
-chkViewPatterns' p@(ViewPat _ _) = addOccurence ViewPatterns p
+chkViewPatterns' p@(ViewPat _ _) = addEvidence ViewPatterns p
 chkViewPatterns' p = return p
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/ExtMap.hs view
@@ -1,4 +1,7 @@-{-# LANGUAGE DeriveAnyClass, DeriveGeneric, StandaloneDeriving #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE StandaloneDeriving #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMap
   ( module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMap
@@ -36,8 +39,31 @@ 
 type LogicalRelation a = Formula a
 
-type ExtMap = SMap.Map (LogicalRelation Extension) [SrcSpan]
+prettyPrintFormula :: Show a => LogicalRelation a -> String
+prettyPrintFormula (Var x) = show x
+prettyPrintFormula (x :||: y) = prettyPrintFormula x ++ " OR " ++ prettyPrintFormula y
+prettyPrintFormula (x :&&: y) = prettyPrintFormula x ++ " AND " ++ prettyPrintFormula y
+prettyPrintFormula (x :++: y) = prettyPrintFormula x ++ " XOR " ++ prettyPrintFormula y
+prettyPrintFormula (x :->: y) = prettyPrintFormula x ++ " => " ++ prettyPrintFormula y
+prettyPrintFormula (x :<->: y) = prettyPrintFormula x ++ " <=> " ++ prettyPrintFormula y
+prettyPrintFormula (All xs) = "All [" ++ (intercalate ", " . map prettyPrintFormula $ xs) ++ "]"
+prettyPrintFormula (Some xs) = "Some [" ++ (intercalate ", " . map prettyPrintFormula $ xs) ++ "]"
+prettyPrintFormula (None xs) = "None [" ++ (intercalate ", " . map prettyPrintFormula $ xs) ++ "]"
+prettyPrintFormula (ExactlyOne xs) = "ExactlyOne [" ++ (intercalate ", " . map prettyPrintFormula $ xs) ++ "]"
+prettyPrintFormula (AtMostOne xs) = "AtMostOne [" ++ (intercalate ", " . map prettyPrintFormula $ xs) ++ "]"
+prettyPrintFormula (Not x) = "Not " ++ prettyPrintFormula x
+prettyPrintFormula Yes = "True"
+prettyPrintFormula No = "False"
+prettyPrintFormula Let{} = "Let ..."
+prettyPrintFormula Bound{} = error "Bound is for internal use only"
 
+data Occurence a = Hint               { unOcc :: a }
+                 | Evidence           { unOcc :: a }
+                 | MissingInformation { unOcc :: a }
+  deriving (Show, Eq, Ord, Functor)
+
+type ExtMap = SMap.Map (LogicalRelation Extension) [Occurence SrcSpan]
+
 lVar :: a -> LogicalRelation a
 lVar = Var
 
@@ -57,11 +83,23 @@ lAll = All
 
 complexity :: Extension -> Int
-complexity = length . expandExtension
+complexity = length . expandExtension'
 
+-- | Completely expand extension
+expandExtension' :: Extension -> [Extension]
+expandExtension' e = findFixedPoint (nub . expand) [e]
+  where expand = concatMap expandExtension
+
+-- | Terminating variant of Control.Monad.Fix.fix
+-- It tries to find the fixpoint of a function with a given starting value.
+-- It terminates if a value repeats itself.
+findFixedPoint :: Eq a => (a -> a) -> a -> a
+findFixedPoint f x = findFix' f (f x) x
+  where findFix' f cur prev = if cur == prev then cur else findFix' f (f cur) cur
+
 determineExtensions :: SMap.Map (LogicalRelation Extension) v -> [Extension]
 {- NOTE:
- We calculate all the possible extension set that satisfy the logical relation,
+ We calculate all possible extension sets that satisfy the logical relation,
  then for each extension we remove all the extensions implied by it, (mergeImplied)
  finally we select the minimal extension set.
 
@@ -69,6 +107,8 @@   - it contains the least amount of extensions
   - it contains extension with minimal complexity
   - it is lexicographically the first one (based on the Ord instance of Extension)
+
+  TODO: Comparing on length might be unnecessary
 -}
 determineExtensions x = minimal . map toExts $ solution
   where solution = solve_all . All . LMap.keys $ x
@@ -77,7 +117,7 @@ 
 rmImplied :: Extension -> [Extension] -> [Extension]
 rmImplied e = flip (\\) implied
-  where implied = delete e $ expandExtension e
+  where implied = delete e . expandExtension' $ e
 
 mergeImplied :: [Extension] -> [Extension]
 mergeImplied exts = foldl (flip rmImplied) exts exts
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/ExtMonad.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds, RankNTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE RankNTypes #-}
 
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.ExtMonad
@@ -35,32 +37,86 @@ class Checkable node where
   check :: CheckNode node
 
-addOccurence' :: (Ord k, HasRange a) =>
-                 k -> a -> SMap.Map k [SrcSpan] -> SMap.Map k [SrcSpan]
-addOccurence' key node = SMap.insertWith (++) key [getRange node]
+addHint' :: (Ord k, HasRange a) =>
+                 k -> a -> SMap.Map k [Occurence SrcSpan] -> SMap.Map k [Occurence SrcSpan]
+addHint' key node = SMap.insertWith (++) key [Hint (getRange node)]
 
--- TODO: add isTurnedOn check
-addOccurence_ :: (MonadState ExtMap m, HasRange node) =>
-                  Extension -> node -> m ()
-addOccurence_ extension element = modify $ addOccurence' (lVar extension) element
+addHint_ :: (MonadState ExtMap m, HasRange node) =>
+             Extension -> node -> m ()
+addHint_ extension element = modify $ addHint' (lVar extension) element
 
-addOccurence :: (MonadState ExtMap m, HasRange node) =>
-                 Extension -> node -> m node
-addOccurence ext node = addOccurence_ ext node >> return node
+addHint :: (MonadState ExtMap m, HasRange node) =>
+            Extension -> node -> m node
+addHint ext node = addHint_ ext node >> return node
 
+addRelationHint_ :: (MonadState ExtMap m, HasRange node) =>
+                     LogicalRelation Extension -> node -> m ()
+addRelationHint_ rel element = modify $ addHint' rel element
+
+addRelationHint :: (MonadState ExtMap m, HasRange node) =>
+                    LogicalRelation Extension -> node -> m node
+addRelationHint rel node = addRelationHint_ rel node >> return node
+
+
+addMI' :: (Ord k, HasRange a) =>
+                 k -> a -> SMap.Map k [Occurence SrcSpan] -> SMap.Map k [Occurence SrcSpan]
+addMI' key node = SMap.insertWith (++) key [MissingInformation (getRange node)]
+
+addMI_ :: (MonadState ExtMap m, HasRange node) =>
+             Extension -> node -> m ()
+addMI_ extension element = modify $ addMI' (lVar extension) element
+
+addMI :: (MonadState ExtMap m, HasRange node) =>
+            Extension -> node -> m node
+addMI ext node = addMI_ ext node >> return node
+
+addRelationMI_ :: (MonadState ExtMap m, HasRange node) =>
+                     LogicalRelation Extension -> node -> m ()
+addRelationMI_ rel element = modify $ addMI' rel element
+
+addRelationMI :: (MonadState ExtMap m, HasRange node) =>
+                    LogicalRelation Extension -> node -> m node
+addRelationMI rel node = addRelationMI_ rel node >> return node
+
+
+addEvidence' :: (Ord k, HasRange a) =>
+                 k -> a -> SMap.Map k [Occurence SrcSpan] -> SMap.Map k [Occurence SrcSpan]
+addEvidence' key node = SMap.insertWith (++) key [Evidence (getRange node)]
+
+addEvidence_ :: (MonadState ExtMap m, HasRange node) =>
+                 Extension -> node -> m ()
+addEvidence_ extension element = modify $ addEvidence' (lVar extension) element
+
+addEvidence :: (MonadState ExtMap m, HasRange node) =>
+                Extension -> node -> m node
+addEvidence ext node = addEvidence_ ext node >> return node
+
 addRelation_ :: (MonadState ExtMap m, HasRange node) =>
                  LogicalRelation Extension -> node -> m ()
-addRelation_ rel element = modify $ addOccurence' rel element
+addRelation_ rel element = modify $ addEvidence' rel element
 
 addRelation :: (MonadState ExtMap m, HasRange node) =>
                 LogicalRelation Extension -> node -> m node
 addRelation rel node = addRelation_ rel node >> return node
 
+
+addEvidenceLoc' :: Ord k => k -> SrcSpan -> SMap.Map k [Occurence SrcSpan] -> SMap.Map k [Occurence SrcSpan]
+addEvidenceLoc' k loc = SMap.insertWith (++) k [Evidence loc]
+
+addEvidenceLoc :: MonadState ExtMap m => Extension -> SrcSpan -> m ()
+addEvidenceLoc ext loc = modify $ addEvidenceLoc' (lVar ext) loc
+
+addRelationLoc :: MonadState ExtMap m => LogicalRelation Extension -> SrcSpan -> m ()
+addRelationLoc rel loc = modify $ addEvidenceLoc' rel loc
+
 isTurnedOn :: Extension -> ExtMonad Bool
 isTurnedOn ext = do
   defaults <- ask
   return $! ext `elem` defaults
 
+isTurnedOff :: Extension -> ExtMonad Bool
+isTurnedOff ext = not <$> isTurnedOn ext
+
 conditional :: (node -> ExtMonad node) ->
                Extension ->
                node ->
@@ -84,7 +140,7 @@   if or bs then checker node else return node
 
 conditionalAdd :: HasRange node => Extension -> node -> ExtMonad node
-conditionalAdd ext = conditional (addOccurence ext) ext
+conditionalAdd ext = conditional (addEvidence ext) ext
 
 runExtMonadIO :: ExtMonad a -> IO a
 runExtMonadIO = runGhc (Just libdir) . runExtMonadGHC
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Instances/AppSelector.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE DataKinds, TypeFamilies #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeFamilies #-}
 
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Instances.AppSelector where
@@ -37,6 +38,7 @@   HasChecker ConDecl          = 'True
   HasChecker Assertion        = 'True
   HasChecker InstanceHead     = 'True
+  HasChecker Context          = 'True
   HasChecker _                = 'False
 
 type instance AppSelector Checkable node = HasChecker node
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Instances/Checkable.hs view
@@ -9,7 +9,10 @@ 
 -- | Global checks
 instance Checkable Module where
-  check = globalChkNamesForTypeEq
+  check = gblChkQNamesForTypeEq
+      >=> gblChkUndecidableInstances
+      >=> gblChkQNamesForFC
+      >=> gblChkCPP
 
 instance Checkable Decl where
   check = chkFlexibleInstancesDecl
@@ -19,7 +22,9 @@       >=> chkConstraintKindsDecl
       >=> chkConstrainedClassMethodsDecl
       >=> chkTypeSynonymInstancesDecl
-      >=> chkTypeOperatorsDecl'
+      >=> chkTypeOperatorsDecl
+      >=> chkUndecidableInstancesDecl
+      >=> chkFlexibleContextsDecl
 
 instance Checkable Pattern where
   check = chkBangPatterns
@@ -108,3 +113,6 @@ 
 instance Checkable InstanceHead where
   check = chkTypeOperatorsInstHead
+
+instance Checkable Context where
+  check = chkFlexibleContexts
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/SupportedExtensions.hs view
@@ -10,10 +10,13 @@                       ++ derivingExtensions
                       ++ typeClassExtensions
                       ++ typeSystemExtensions
+                      ++ thExtensions
+                      ++ [Cpp]
+                      ++ [OverloadedStrings]
 
 syntacticExtensions :: [Extension]
-syntacticExtensions = [ RecordWildCards, TemplateHaskell, BangPatterns
-                      , PatternSynonyms, TupleSections, LambdaCase, QuasiQuotes
+syntacticExtensions = [ RecordWildCards, BangPatterns
+                      , PatternSynonyms, TupleSections, LambdaCase
                       , ViewPatterns, MagicHash, UnboxedTuples
                       , FunctionalDependencies, DefaultSignatures
                       , RecursiveDo, Arrows, ParallelListComp
@@ -30,8 +33,12 @@ typeClassExtensions :: [Extension]
 typeClassExtensions = [ MultiParamTypeClasses, ConstrainedClassMethods
                       , FlexibleInstances, TypeSynonymInstances
+                      , FlexibleContexts
                       ]
 
 typeSystemExtensions :: [Extension]
 typeSystemExtensions = [ TypeFamilies, GADTs, ExistentialQuantification
-                       , ConstraintKinds ]
+                       , ConstraintKinds, UndecidableInstances ]
+
+thExtensions :: [Extension]
+thExtensions = [TemplateHaskell, TemplateHaskellQuotes, QuasiQuotes]
Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/TraverseAST.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds, RankNTypes, TypeApplications #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TypeApplications #-}
 
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.TraverseAST
@@ -14,5 +16,5 @@ import Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Instances.AppSelector()
 
 
-traverseModule :: CheckNode UnnamedModule
+traverseModule :: CheckNode Module
 traverseModule = topDownM @Checkable check
− Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Utils/Debug.hs
@@ -1,40 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}
-
-
-module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.Debug
-  ( module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.Debug
-  , module Debug.Trace
-  ) where
-
-import Data.Maybe (isJust)
-import Control.Monad.Trans.Maybe
-import Control.Reference ((^.), (&))
-
-import Debug.Trace
-import qualified Outputable as GHC
-
-import Language.Haskell.Tools.Refactor
-
-
-debugM :: (Monad m, Show a) => m a -> m a
-debugM m = do
-  x <- m
-  traceShow x m
-
-debug :: Show a => a -> a
-debug x = traceShow x x
-
--- | Displays True iff the wrapped value is a Just
-debugMaybeT :: Monad m => MaybeT m a -> MaybeT m a
-debugMaybeT m = MaybeT $ do
-  x <- runMaybeT m
-  traceShow (isJust x) (return x)
-
-showOutputable :: GHC.Outputable a => a -> String
-showOutputable = GHC.showSDocUnsafe . GHC.ppr
-
-showName :: Name -> String
-showName = (^. simpleName & unqualifiedName & simpleNameStr)
-
-showOp :: Operator -> String
-showOp = (^. operatorName & unqualifiedName & simpleNameStr)
+ Language/Haskell/Tools/Refactor/Builtin/ExtensionOrganizer/Utils/GHCHelpers.hs view
@@ -0,0 +1,128 @@+module Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.GHCHelpers where
+
+import Class
+import FamInstEnv (FamFlavor(..),FamInst(..))
+import PrelNames
+import TcType hiding (sizeType, sizeTypes)
+import TyCoRep
+import Type
+import Var
+import GHC
+
+import Data.List
+
+-- This module contains private helper functions from GHC (mostly from TcValidity).
+-- There are other similar functions that are accessible through the API,
+-- but these ones have slighty different behaviour.
+
+-- Free variables of a type, retaining repetitions, and expanding synonyms
+fvType :: Type -> [TyCoVar]
+fvType ty | Just exp_ty <- tcView ty = fvType exp_ty
+fvType (TyVarTy tv)          = [tv]
+fvType (TyConApp _ tys)      = fvTypes tys
+fvType LitTy{}               = []
+fvType (AppTy fun arg)       = fvType fun ++ fvType arg
+fvType (FunTy arg res)       = fvType arg ++ fvType res
+fvType (ForAllTy (TvBndr tv _) ty)
+  = fvType (tyVarKind tv) ++
+    filter (/= tv) (fvType ty)
+fvType (CastTy ty co)        = fvType ty ++ fvCo co
+fvType (CoercionTy co)       = fvCo co
+
+fvTypes :: [Type] -> [TyVar]
+fvTypes = concatMap fvType
+
+fvCo :: Coercion -> [TyCoVar]
+fvCo (Refl _ ty)            = fvType ty
+fvCo (TyConAppCo _ _ args)  = concatMap fvCo args
+fvCo (AppCo co arg)         = fvCo co ++ fvCo arg
+fvCo (ForAllCo tv h co)     = filter (/= tv) (fvCo co) ++ fvCo h
+fvCo (FunCo _ co1 co2)      = fvCo co1 ++ fvCo co2
+fvCo (CoVarCo v)            = [v]
+fvCo (AxiomInstCo _ _ args) = concatMap fvCo args
+fvCo (UnivCo p _ t1 t2)     = fvProv p ++ fvType t1 ++ fvType t2
+fvCo (SymCo co)             = fvCo co
+fvCo (TransCo co1 co2)      = fvCo co1 ++ fvCo co2
+fvCo (NthCo _ co)           = fvCo co
+fvCo (LRCo _ co)            = fvCo co
+fvCo (InstCo co arg)        = fvCo co ++ fvCo arg
+fvCo (CoherenceCo co1 co2)  = fvCo co1 ++ fvCo co2
+fvCo (KindCo co)            = fvCo co
+fvCo (SubCo co)             = fvCo co
+fvCo (AxiomRuleCo _ cs)     = concatMap fvCo cs
+
+fvProv :: UnivCoProvenance -> [TyCoVar]
+fvProv UnsafeCoerceProv    = []
+fvProv (PhantomProv co)    = fvCo co
+fvProv (ProofIrrelProv co) = fvCo co
+fvProv (PluginProv _)      = []
+
+sizeType :: Type -> Int
+-- Size of a type: the number of variables and constructors
+sizeType ty | Just exp_ty <- tcView ty = sizeType exp_ty
+sizeType TyVarTy{}         = 1
+sizeType (TyConApp _ tys)  = sizeTypes tys + 1
+sizeType LitTy{}           = 1
+sizeType (AppTy fun arg)   = sizeType fun + sizeType arg
+sizeType (FunTy arg res)   = sizeType arg + sizeType res + 1
+sizeType (ForAllTy _ ty)   = sizeType ty
+sizeType (CastTy ty _)     = sizeType ty
+sizeType (CoercionTy _)    = 1
+
+sizeTypes :: [Type] -> Int
+sizeTypes = sum . map sizeType
+
+
+checkInstTermination :: [TcType] -> ThetaType -> Bool
+checkInstTermination tys = checkPreds
+  where
+   headFvs  = fvTypes tys
+   headSize = sizeTypes tys
+
+   checkPreds :: [PredType] -> Bool
+   checkPreds = any check
+
+   check :: PredType -> Bool
+   check predTy
+     = case classifyPredType predTy of
+         EqPred {}    -> False
+         IrredPred {} -> check2 predTy (sizeType predTy)
+         ClassPred cls tys
+           | isTerminatingClass cls -> False
+           | isCTupleClass cls -> checkPreds tys
+           | otherwise
+           -> check2 predTy (sizeTypes . filterOutInvisibleTypes (classTyCon cls) $ tys)
+
+   check2 predTy predSize = not (null badTvs) || predSize >= headSize
+     where badTvs = fvType predTy \\ headFvs
+     -- Tyvars occurring more often in the context than in the head
+
+isTerminatingClass :: Class -> Bool
+isTerminatingClass cls = isIPClass cls
+  || cls `hasKey` typeableClassKey
+  || cls `hasKey` coercibleTyConKey
+  || cls `hasKey` eqTyConKey
+  || cls `hasKey` heqTyConKey
+
+
+-- | Checks whether a Type has a type function application in its head.
+hasTyFunHead :: Type -> Bool
+hasTyFunHead ty = case tcSplitTyConApp_maybe ty of
+                    Just (tc, _) -> isTypeFamilyTyCon tc
+                    Nothing      -> False
+
+-- | Given the lhs type arguments and rhs tycon and its arguments
+-- of a type family instance, it determines whether it needs UndecidableInstances.
+checkFamEq :: [Type] -> [(TyCon, [Type])] -> Bool
+checkFamEq lhsTys = any check
+  where
+   size = sizeTypes lhsTys
+   fvs  = fvTypes lhsTys
+   check (_, tys)
+     | bad_tvs <- fvTypes tys \\ fvs
+     = not (all isTyFamFree tys) || not (null bad_tvs) || size <= sizeTypes tys
+
+isTyFamInst :: FamInst -> Bool
+isTyFamInst inst
+  | SynFamilyInst <- fi_flavor inst = True
+  | otherwise                       = False
Language/Haskell/Tools/Refactor/Builtin/ExtractBinding.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds, MultiWayIf, RankNTypes, ScopedTypeVariables, TypeApplications, ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.ExtractBinding
   (extractBinding', tryItOut, extractBindingRefactoring) where
Language/Haskell/Tools/Refactor/Builtin/FloatOut.hs view
@@ -1,4 +1,8 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, ScopedTypeVariables, TypeApplications #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.FloatOut
   (floatOut, floatOutRefactoring) where
Language/Haskell/Tools/Refactor/Builtin/GenerateExports.hs view
@@ -1,4 +1,7 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, TupleSections #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE TupleSections #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.GenerateExports
   (generateExports, generateExportsRefactoring) where
Language/Haskell/Tools/Refactor/Builtin/GenerateTypeSignature.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE FlexibleContexts, GADTs, RankNTypes, ScopedTypeVariables, TupleSections, TypeApplications, ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.GenerateTypeSignature
   ( generateTypeSignature, generateTypeSignature', tryItOut
Language/Haskell/Tools/Refactor/Builtin/GetMatches.hs view
@@ -2,7 +2,6 @@ 
 import Language.Haskell.Tools.Refactor
 
-import Control.Monad.Writer
 import Control.Reference
 import Data.Aeson
 
@@ -16,10 +15,9 @@ getMatchesQuery :: QueryChoice
 getMatchesQuery = LocationQuery "GetMatches" getMatches
 
-getMatches :: RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad Value
+getMatches :: RealSrcSpan -> ModuleDom -> [ModuleDom] -> QueryMonad QueryValue
 getMatches sp (_,mod) _
-  = case selectedName of [n] -> do ctors <- getCtors $ idType $ semanticsId n
-                                   return $ toJSON ctors
+  = case selectedName of [n] -> fmap (GeneralQuery . toJSON) . getCtors . idType . semanticsId $ n
                          []  -> queryError "No name is selected."
                          _   -> queryError "Multiple names are selected."
   where
Language/Haskell/Tools/Refactor/Builtin/InlineBinding.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, MultiWayIf, RankNTypes, ScopedTypeVariables, TypeApplications #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
 
 -- | Defines the inline binding refactoring that removes a value binding and replaces all occurences
 -- with an expression equivalent to the body of the binding.
Language/Haskell/Tools/Refactor/Builtin/OrganizeExtensions.hs view
@@ -1,4 +1,8 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, RankNTypes, TupleSections #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TupleSections #-}
 
 
 module Language.Haskell.Tools.Refactor.Builtin.OrganizeExtensions
@@ -16,11 +20,11 @@ import GHC (Ghc(..))
 
 import Control.Reference
-import Data.Char (isAlpha)
+import Data.Char (isAlphaNum)
 import Data.Function (on)
 import Data.Maybe (mapMaybe)
 import Data.List
-import qualified Data.Map.Strict as SMap (empty)
+import qualified Data.Map.Strict as SMap (empty, toList)
 
 -- NOTE: When working on the entire AST, we should build a monad,
 --       that will will avoid unnecessary checks.
@@ -28,6 +32,11 @@ 
 --       Pretty easy now. Chcek wheter it is already in the ExtMap.
 
+highlightExtensionsQuery :: QueryChoice
+highlightExtensionsQuery = GlobalQuery "HighlightExtensions" extQuery
+  where extQuery :: ModuleDom -> [ModuleDom] -> QueryMonad QueryValue
+        extQuery (_,m) _ = lift . fmap MarkerQuery . extensionMarkers $ m
+
 organizeExtensionsRefactoring :: RefactoringChoice
 organizeExtensionsRefactoring = ModuleRefactoring "OrganizeExtensions" (localRefactoring organizeExtensions)
 
@@ -44,12 +53,18 @@ organizeExtensions :: LocalRefactoring
 organizeExtensions moduleAST = do
   exts <- liftGhc $ reduceExtensions moduleAST
-  let langExts = mkLanguagePragma . map show $ exts
+  let langExts = map (mkLanguagePragma . pure . serializeExt . show) exts
       ghcOpts  = moduleAST ^? filePragmas & annList & opStr & stringNodeStr
       ghcOpts' = map (mkOptionsGHC . unwords . filter (isPrefixOf "-") . words) ghcOpts
 
-      newPragmas = mkFilePragmas $ langExts:ghcOpts'
+      offExts  = map (mkLanguagePragma . pure)
+               . sort
+               . map (("No" ++) . serializeExt . show)
+               . collectTurnedOffExtensions
+               $ moduleAST
 
+      newPragmas = mkFilePragmas $ offExts ++ langExts ++ ghcOpts'
+
   (filePragmas != newPragmas)
     -- remove empty {-# LANGUAGE #-} pragmas
     >=> filePragmas !~ filterListSt (\case LanguagePragma (AnnList []) -> False; _ -> True)
@@ -61,20 +76,29 @@   let defaults = map replaceDeprecated . collectDefaultExtensions $ moduleAST
       expanded = expandExtensions defaults
       (xs, ys) = partition isSupported expanded
-  -- we can't say anything about generated code
-  if TemplateHaskell `notElem` expanded
-    then do
-      xs' <- flip execStateT SMap.empty . flip runReaderT xs . traverseModule $ moduleAST
-      -- Merging is needed because there might be unsopported extensions
-      -- that are implied by supported extensions (TypeFamilies -> MonoLocalBinds)
-      return . sortBy (compare `on` show) . nub . mergeImplied $ (determineExtensions xs' ++ ys)
-    else
-      return . mergeImplied $ defaults
 
+  xs' <- flip execStateT SMap.empty . flip runReaderT xs . traverseModule $ moduleAST
+  let filteredExts = nub . mergeImplied $ (determineExtensions xs' ++ ys)
+  if any (`elem` filteredExts) [Cpp, TemplateHaskell, TemplateHaskellQuotes, QuasiQuotes]
+    -- We can't say anything about generated code
+    then return . mergeImplied $ defaults
+    -- Merging is needed because there might be unsopported extensions
+    -- that are implied by supported extensions (TypeFamilies -> MonoLocalBinds)
+    else return . sortBy (compare `on` show) $ filteredExts
+
+-- | Collect the required extensions in a module and returns a markers associated with them
+extensionMarkers :: UnnamedModule -> Ghc [Marker]
+extensionMarkers = fmap (concatMap toMarkers . SMap.toList) . collectExtensions
+  where toMarkers (rel, occs) = map (toMarker rel) occs
+        toMarker  rel occ     = Marker (unOcc occ) Info (showWithLevel rel occ)
+        showWithLevel rel occ = (head . words . show $ occ) ++ ": " ++ prettyPrintFormula rel
+
 -- | Collects extensions induced by the source code (with location info)
 collectExtensions :: UnnamedModule -> Ghc ExtMap
 collectExtensions = collectExtensionsWith traverseModule
 
+
+-- | Collects the required extensions from a module using the given traversal method
 collectExtensionsWith :: CheckNode UnnamedModule -> UnnamedModule -> Ghc ExtMap
 collectExtensionsWith trvModule moduleAST = do
   let expanded = expandExtensions . collectDefaultExtensions $ moduleAST
@@ -88,11 +112,18 @@ -- | Collects extensions enabled by default
 collectDefaultExtensions :: UnnamedModule -> [Extension]
 collectDefaultExtensions = mapMaybe toExt . getExtensions
-  where
-  getExtensions :: UnnamedModule -> [String]
-  getExtensions = flip (^?) (filePragmas & annList & lpPragmas & annList & langExt)
 
+-- | Collects extensions enabled by default
+collectTurnedOffExtensions :: UnnamedModule -> [Extension]
+collectTurnedOffExtensions = mapMaybe (toExt . drop 2)
+                           . filter (isPrefixOf "No")
+                           . getExtensions
+
+-- | Collects the string representation of the extensions in the module
+getExtensions :: UnnamedModule -> [String]
+getExtensions = flip (^?) (filePragmas & annList & lpPragmas & annList & langExt)
+
 toExt :: String -> Maybe Extension
-toExt str = case map fst . reads . canonExt . takeWhile isAlpha $ str of
+toExt str = case map fst . reads . canonExt . takeWhile isAlphaNum $ str of
               e:_ -> Just e
-              []  -> fail $ "Extension '" ++ takeWhile isAlpha str ++ "' is not known."
+              []  -> fail $ "Extension '" ++ takeWhile isAlphaNum str ++ "' is not known."
Language/Haskell/Tools/Refactor/Builtin/OrganizeImports.hs view
@@ -1,4 +1,9 @@-{-# LANGUAGE FlexibleContexts, LambdaCase, MonoLocalBinds, ScopedTypeVariables, TupleSections, TypeApplications #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeApplications #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.OrganizeImports
   ( organizeImports, projectOrganizeImports
Language/Haskell/Tools/Refactor/Builtin/RenameDefinition.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE FlexibleContexts, MonoLocalBinds, MultiWayIf, ScopedTypeVariables, TupleSections, TypeApplications, ViewPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE ViewPatterns #-}
 
 module Language.Haskell.Tools.Refactor.Builtin.RenameDefinition
   (renameDefinition, renameDefinition', renameDefinitionRefactoring) where
examples/Refactor/GenerateTypeSignature/PolymorphSubMulti_res.hs view
@@ -2,5 +2,5 @@ 
 f :: (Num a, Ord a) => a -> a
 f a = g a where
-  g :: (Num p, Ord p) => p -> p
+  g :: (Ord p, Num p) => p -> p
   g a = if a > 0 then a + 1 else a
examples/Refactor/OrganizeImports/MakeExplicit/ImportThree_res.hs view
@@ -1,5 +1,5 @@ module Refactor.OrganizeImports.MakeExplicit.ImportThree where
 
-import Refactor.OrganizeImports.MakeExplicit.Source (g, e, a)
+import Refactor.OrganizeImports.MakeExplicit.Source (a, e, g)
 
 x = (a,e,g)
examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount_res.hs view
@@ -1,6 +1,6 @@ module Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount where
 
-import Refactor.OrganizeImports.MakeExplicit.Source (A(..), e, a)
+import Refactor.OrganizeImports.MakeExplicit.Source (a, e, A(..))
 
 x = B ()
 y = b x
examples/Refactor/OrganizeImports/NarrowType_res.hs view
@@ -1,6 +1,6 @@ module Refactor.OrganizeImports.NarrowType where
 
-import Control.Monad.State (StateT(..), State)
+import Control.Monad.State (State, StateT(..))
 
 type St = State ()
 type StT = StateT () IO
examples/Refactor/RenameDefinition/ParenName.hs view
@@ -1,6 +1,6 @@ module Refactor.RenameDefinition.ParenName where
 
-(<>) :: Int -> Int -> Int
-a <> b = a + b
+(<->) :: Int -> Int -> Int
+a <-> b = a + b
 
-x = (<>) 3 4+x = (<->) 3 4
examples/Refactor/RenameDefinition/ParenName_res.hs view
@@ -1,6 +1,6 @@ module Refactor.RenameDefinition.ParenName where
 
-(<->) :: Int -> Int -> Int
-a <-> b = a + b
+(<-->) :: Int -> Int -> Int
+a <--> b = a + b
 
-x = (<->) 3 4+x = (<-->) 3 4
haskell-tools-builtin-refactorings.cabal view
@@ -1,5 +1,5 @@ name:                haskell-tools-builtin-refactorings
-version:             1.0.1.1
+version:             1.1.0.0
 synopsis:            Refactoring Tool for Haskell
 description:         Contains a set of refactorings based on the Haskell-Tools framework to easily transform a Haskell program. For the descriptions of the implemented refactorings, see the homepage.
 homepage:            https://github.com/haskell-tools/haskell-tools
@@ -43,6 +43,7 @@                   , test/ExtensionOrganizerTest/DerivingsTest/*.hs
                   , test/ExtensionOrganizerTest/ExistentialQuantificationTest/*.hs
                   , test/ExtensionOrganizerTest/ExplicitNamespacesTest/*.hs
+                  , test/ExtensionOrganizerTest/FlexibleContextsTest/*.hs
                   , test/ExtensionOrganizerTest/FlexibleInstancesTest/*.hs
                   , test/ExtensionOrganizerTest/FunctionalDependenciesTest/*.hs
                   , test/ExtensionOrganizerTest/GADTsTest/*.hs
@@ -61,6 +62,7 @@                   , test/ExtensionOrganizerTest/TupleSectionsTest/*.hs
                   , test/ExtensionOrganizerTest/TypeFamiliesTest/*.hs
                   , test/ExtensionOrganizerTest/TypeOperatorsTest/*.hs
+                  , test/ExtensionOrganizerTest/UndecidableInstancesTest/*.hs
                   , test/ExtensionOrganizerTest/ViewPatternsTest/*.hs
 
 library
@@ -88,10 +90,12 @@                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.BangPatternsChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ConstrainedClassMethodsChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ConstraintKindsChecker
+                     , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.CPPChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DefaultSignaturesChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.DerivingsChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ExplicitForAllChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ExplicitNamespacesChecker
+                     , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleContextsChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FlexibleInstancesChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.FunctionalDependenciesChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.GADTsChecker
@@ -111,11 +115,12 @@                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeOperatorsChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.TypeSynonymInstancesChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UnboxedTuplesChecker
+                     , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.UndecidableInstancesChecker
                      , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Checkers.ViewPatternsChecker
-                     , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.Debug
+                     , Language.Haskell.Tools.Refactor.Builtin.ExtensionOrganizer.Utils.GHCHelpers
 
 
-  build-depends:       base                      >= 4.10  && < 4.11
+  build-depends:       base                      >= 4.11  && < 4.12
                      , mtl                       >= 2.2  && < 2.3
                      , aeson                     >= 1.0 && < 1.4
                      , uniplate                  >= 1.6  && < 1.7
@@ -128,15 +133,15 @@                      , references                >= 0.3  && < 0.4
                      , split                     >= 0.2  && < 0.3
                      , filepath                  >= 1.4  && < 1.5
-                     , template-haskell          >= 2.12 && < 2.13
+                     , template-haskell          >= 2.13 && < 2.14
                      , minisat-solver            >= 0.1  && < 0.2
-                     , ghc                       >= 8.2  && < 8.3
-                     , Cabal                     >= 2.0  && < 2.3
-                     , haskell-tools-ast         >= 1.0  && < 1.1
-                     , haskell-tools-backend-ghc >= 1.0  && < 1.1
-                     , haskell-tools-rewrite     >= 1.0  && < 1.1
-                     , haskell-tools-prettyprint >= 1.0  && < 1.1
-                     , haskell-tools-refactor    >= 1.0  && < 1.1
+                     , ghc                       >= 8.4  && < 8.5
+                     , portable-lines            >= 0.1  && < 0.2                     , Cabal                     >= 2.0  && < 2.3
+                     , haskell-tools-ast         >= 1.1  && < 1.2
+                     , haskell-tools-backend-ghc >= 1.1  && < 1.2
+                     , haskell-tools-rewrite     >= 1.1  && < 1.2
+                     , haskell-tools-prettyprint >= 1.1  && < 1.2
+                     , haskell-tools-refactor    >= 1.1  && < 1.2
   default-language:    Haskell2010
 
 test-suite haskell-tools-builtin-refactorings-test
@@ -144,7 +149,7 @@   ghc-options:         -with-rtsopts=-M2g
   hs-source-dirs:      test
   main-is:             Main.hs
-  build-depends:       base                      >= 4.10 && < 4.11
+  build-depends:       base                      >= 4.11 && < 4.12
                      , tasty                     >= 0.11 && < 1.1
                      , tasty-hunit               >= 0.9  && < 0.11
                      , transformers              >= 0.5  && < 0.6
@@ -157,15 +162,15 @@                      , references                >= 0.3  && < 0.4
                      , split                     >= 0.2  && < 0.3
                      , time                      >= 1.8  && < 1.9
-                     , template-haskell          >= 2.12 && < 2.13
-                     , ghc                       >= 8.2  && < 8.3
+                     , template-haskell          >= 2.13 && < 2.14
+                     , ghc                       >= 8.4  && < 8.5
                      , ghc-paths                 >= 0.1  && < 0.2
                      , Cabal                     >= 2.0  && < 2.3
-                     , haskell-tools-ast         >= 1.0  && < 1.1
-                     , haskell-tools-backend-ghc >= 1.0  && < 1.1
-                     , haskell-tools-rewrite     >= 1.0  && < 1.1
-                     , haskell-tools-prettyprint >= 1.0  && < 1.1
-                     , haskell-tools-refactor    >= 1.0  && < 1.1
+                     , haskell-tools-ast         >= 1.1  && < 1.2
+                     , haskell-tools-backend-ghc >= 1.1  && < 1.2
+                     , haskell-tools-rewrite     >= 1.1  && < 1.2
+                     , haskell-tools-prettyprint >= 1.1  && < 1.2
+                     , haskell-tools-refactor    >= 1.1  && < 1.2
                      , haskell-tools-builtin-refactorings
   default-language:    Haskell2010
 
@@ -177,7 +182,7 @@                      , ExtensionOrganizerTest.Parser
   hs-source-dirs:      test
   main-is:             ExtensionOrganizerTest/Main.hs
-  build-depends:       base                      >= 4.10 && < 4.11
+  build-depends:       base                      >= 4.11 && < 4.12
                      , tasty                     >= 0.11 && < 1.1
                      , tasty-hunit               >= 0.9  && < 0.11
                      , transformers              >= 0.5  && < 0.6
@@ -190,15 +195,15 @@                      , references                >= 0.3  && < 0.4
                      , split                     >= 0.2  && < 0.3
                      , time                      >= 1.8  && < 1.9
-                     , template-haskell          >= 2.12 && < 2.13
-                     , ghc                       >= 8.2  && < 8.3
+                     , template-haskell          >= 2.13 && < 2.14
+                     , ghc                       >= 8.4  && < 8.5
                      , ghc-paths                 >= 0.1  && < 0.2
                      , Cabal                     >= 2.0  && < 2.3
-                     , haskell-tools-ast         >= 1.0  && < 1.1
-                     , haskell-tools-backend-ghc >= 1.0  && < 1.1
-                     , haskell-tools-rewrite     >= 1.0  && < 1.1
-                     , haskell-tools-prettyprint >= 1.0  && < 1.1
-                     , haskell-tools-refactor    >= 1.0  && < 1.1
+                     , haskell-tools-ast         >= 1.1  && < 1.2
+                     , haskell-tools-backend-ghc >= 1.1  && < 1.2
+                     , haskell-tools-rewrite     >= 1.1  && < 1.2
+                     , haskell-tools-prettyprint >= 1.1  && < 1.2
+                     , haskell-tools-refactor    >= 1.1  && < 1.2
                      , haskell-tools-builtin-refactorings
 
   default-language:    Haskell2010
@@ -210,7 +215,7 @@ --                      , ExtensionOrganizerBenchmark.UniPlateTraversal
 --   hs-source-dirs:      benchmark
 --   main-is:             ExtensionOrganizerBenchmark/Main.hs
---   build-depends:       base                      >= 4.10 && < 4.11
+--   build-depends:       base                      >= 4.11 && < 4.12
 --                      , criterion                 >= 1.2  && < 1.3
 --                      , silently                  >= 1.2  && < 1.3
 --                      , transformers              >= 0.5  && < 0.6
@@ -223,8 +228,8 @@ --                      , references                >= 0.3  && < 0.4
 --                      , split                     >= 0.2  && < 0.3
 --                      , time                      >= 1.8  && < 1.9
---                      , template-haskell          >= 2.12 && < 2.13
---                      , ghc                       >= 8.2  && < 8.3
+--                      , template-haskell          >= 2.13 && < 2.14
+--                      , ghc                       >= 8.4  && < 8.5
 --                      , ghc-paths                 >= 0.1  && < 0.2
 --                      , Cabal                     >= 2.0  && < 2.3
 --                      , haskell-tools-ast         >= 1.0  && < 1.1
test/ExtensionOrganizerTest/AnnotationParser.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE LambdaCase #-}
+
 module ExtensionOrganizerTest.AnnotationParser
   -- (getLocalExtensionAnnotations, getGlobalExtensionAnnotations)
   where
@@ -18,21 +20,40 @@   | [] <- getGlobalAnnot s = []
   | otherwise              = parseGlobalAnnot . getGlobalAnnot $ s
 
-getLocalExtensionAnnotations :: String -> SMap.Map (LogicalRelation Extension) [Int]
+-- | Parses a file, collects occurences mapped to extension formulas
+-- , transform them into formulas mapped to occurences.
+getLocalExtensionAnnotations :: String -> SMap.Map (LogicalRelation Extension) [Occurence Int]
 getLocalExtensionAnnotations s = foldl f SMap.empty (parseFile s)
-  where f m (num, exts) = foldl (g num) m exts
-        g num m' ext = SMap.insertWith (++) ext [num] m'
+  where f m (occ, exts) = foldl (g occ) m exts
+        g occ m' ext    = SMap.insertWith (++) ext [occ] m'
 
-parseFile :: String -> [(Int, [LogicalRelation Extension])] -- SMap.Map Extension [Int]
-parseFile = map parseLine . zip [1..] . lines
+parseFile :: String -> [(Occurence Int, [LogicalRelation Extension])] -- SMap.Map Extension [Int]
+parseFile = concatMap (separateOccurences . parseLine) . zip [1..] . lines
 
-parseLine :: (Int, String) -> (Int, [LogicalRelation Extension])
+-- | Separates the occurences into hints and evidence.
+-- The resulting list will always contain three elements
+separateOccurences :: (Int, [Occurence (LogicalRelation Extension)]) ->
+                      [(Occurence Int, [LogicalRelation Extension])]
+separateOccurences (ln, occs) = [(Evidence ln, evs'), (Hint ln, hints'), (Hint ln, mis')]
+  where evs   = filter (\case Evidence{}           -> True; _ -> False;) occs
+        hints = filter (\case Hint{}               -> True; _ -> False;) occs
+        mis   = filter (\case MissingInformation{} -> True; _ -> False;) occs
+
+        evs'   = map fromOcc evs
+        hints' = map fromOcc hints
+        mis'   = map fromOcc mis
+
+        fromOcc (Evidence x)           = x
+        fromOcc (Hint x)               = x
+        fromOcc (MissingInformation x) = x
+
+parseLine :: (Int, String) -> (Int, [Occurence (LogicalRelation Extension)])
 parseLine (num, line) = (num, parseLocalAnnot . getLocalAnnot $ line)
 
-parseLocalAnnot :: String -> [LogicalRelation Extension]
+parseLocalAnnot :: String -> [Occurence (LogicalRelation Extension)]
 parseLocalAnnot = map parseRelation . prepareAnnot
 
-parseRelation :: String -> LogicalRelation Extension
+parseRelation :: String -> Occurence (LogicalRelation Extension)
 parseRelation = execParser relation
 
 parseGlobalAnnot :: String -> [Extension]
@@ -71,17 +92,22 @@ crop :: String -> String
 crop = dropWhile isSpace . reverse . dropWhile isSpace . reverse
 
+relation :: Parser (Occurence (LogicalRelation Extension))
+relation = Hint               <$> (token "(" *> relation' <* token ")")
+       <|> MissingInformation <$> (token "[" *> relation' <* token "]")
+       <|> Evidence           <$> relation'
+
 -- | A relation parser that tries to reduce the left-hand side of operators,
 -- before applíing the left-recursive rules.
 -- Also the rules are a bit convoluted in order to respect the precedence
 -- of the operators
-relation :: Parser (LogicalRelation Extension)
-relation = primRel
+relation' :: Parser (LogicalRelation Extension)
+relation' = primRel
        <|> (:&&:) <$> primRel  <*> (token "*" *> primRel)
-       <|> (:||:) <$> primRel  <*> (token "+" *> relation)
-       <|> (:||:) <$> relation <*> (token "+" *> relation)
-       <|> (:&&:) <$> relation <*> (token "*" *> relation)
-       <|> Not    <$> (token "~" *> relation)
+       <|> (:||:) <$> primRel  <*> (token "+" *> relation')
+       <|> (:||:) <$> relation' <*> (token "+" *> relation')
+       <|> (:&&:) <$> relation' <*> (token "*" *> relation')
+       <|> Not    <$> (token "~" *> relation')
 
   where primRel = (lVar . readExt) <$> word
               <|> Not <$> (token "~" *> primRel)
test/ExtensionOrganizerTest/ConstrainedClassMethodsTest/MixedTyVars.hs view
@@ -5,5 +5,5 @@ import Definitions
 
 class C a where
-  op1 :: D (a, b) => a -> b
+  op1 :: D (a, b) => a -> b  {-* FlexibleContexts, FlexibleContexts *-}
   op2 :: D b      => b -> a
+ test/ExtensionOrganizerTest/FlexibleContextsTest/Definitions.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE MultiParamTypeClasses, TypeOperators, TypeFamilies, ConstraintKinds, FlexibleContexts, RankNTypes #-}
+
+module Definitions where
+
+import GHC.Exts
+
+data T a = T a
+
+class C a where
+  foo :: a -> ()
+
+class a :?: b where
+  q :: a -> b -> ()
+
+class (a :!: b) c where
+  e :: a -> b -> c -> ()
+
+type family TF a :: Constraint
+
+instance C [a] where
+  foo = const ()
+
+type Ctxt a = C [a]
+type FunWCtxt a = Ctxt a => a -> ()
+
+fCtxt :: FunWCtxt a
+fCtxt = const ()
+
+fNestedCtxt :: a -> FunWCtxt a -> ()
+fNestedCtxt x f = f x
+
+
+type SimpleEq a = Eq a
+ test/ExtensionOrganizerTest/FlexibleContextsTest/ForAll.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE ExplicitForAll, FlexibleContexts, TypeOperators #-}
+
+module ForAll where
+
+import Definitions
+
+f :: forall a . C [a] => [a] -> ()  {-* FlexibleContexts, FlexibleContexts, ExplicitForAll *-}
+f = foo                             {-* FlexibleContexts *-}
+
+g :: forall a . (C [a], [a] :?: [a]) => [a] -> ()  {-* FlexibleContexts, FlexibleContexts, FlexibleContexts, ExplicitForAll, TypeOperators *-}
+g = foo                                            {-* FlexibleContexts *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/NestedCtx.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE RankNTypes, FlexibleContexts, TypeOperators #-}
+
+module NestedCtx where
+
+import Definitions
+
+f :: (C [a] => [a] -> ()) -> ()  {-* FlexibleContexts, FlexibleContexts *-}
+f = undefined                    {-* FlexibleContexts *-}
+
+g :: ((C [a], [a] :?: [a]) => [a] -> ()) -> ()  {-* FlexibleContexts, FlexibleContexts, FlexibleContexts, TypeOperators *-}
+g = undefined                                   {-* FlexibleContexts *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/Synonyms.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE FlexibleContexts #-}
+
+module Synonyms where
+
+import Definitions
+
+f1 = fCtxt                 {-* (FlexibleContexts) *-}
+
+f2 = fNestedCtxt           {-* (FlexibleContexts), FlexibleContexts  *-}
+
+f3 :: Ctxt a => a -> ()    {-* FlexibleContexts, FlexibleContexts *-}
+f3 = const ()              {-* FlexibleContexts *-}
+
+f4 :: FunWCtxt a           {-* FlexibleContexts, FlexibleContexts *-}
+f4 = const ()              {-* FlexibleContexts *-}
+
+f5 :: SimpleEq a => a -> ()
+f5 = const ()
+
+f6 :: Eq a => a -> ()
+f6 = id fCtxt :: FunWCtxt a    {-* (FlexibleContexts), (FlexibleContexts) *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/TyFamConstraints.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+
+module TyFamConstraints where
+
+import Definitions
+
+f1 :: TF [a] => a -> ()
+f1 = const ()
+
+f2 :: [a] ~ [Int] => a -> Int  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
+f2 = id                        {-* TypeFamilies + GADTs *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/TySynConstraints.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE FlexibleContexts, ConstraintKinds, TypeOperators, TypeFamilies, RankNTypes #-}
+
+module TySynConstraints where
+
+import GHC.Exts
+import Definitions
+
+type CT1 a = Eq [a]             {-* FlexibleContexts, FlexibleContexts, ConstraintKinds *-}
+type CT2 a = (Eq [a])           {-* FlexibleContexts, FlexibleContexts, ConstraintKinds *-}
+type CT3 a = (Eq a, Ord [a])    {-* FlexibleContexts, FlexibleContexts, ConstraintKinds *-}
+type CT4 a = (Eq a, Ord [a])    {-* FlexibleContexts, FlexibleContexts, ConstraintKinds *-}
+type CT5 a = a :?: T a          {-* FlexibleContexts, FlexibleContexts, ConstraintKinds, TypeOperators *-}
+type CT6 a = (a :!: a) (T a)    {-* FlexibleContexts, FlexibleContexts, ConstraintKinds, TypeOperators *-}
+type CT7 a = Eq [a] => a        {-* FlexibleContexts, FlexibleContexts *-}
+type CT8 a = (Ctxt a, Ord a)    {-* FlexibleContexts, FlexibleContexts, ConstraintKinds *-}
+
+
+type CTTF1 a b = [a] ~ b                          {-* TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
+type CTTF2 a = (TF [a], TF (T a), TF a ~ Eq [a])  {-* TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
+
+type CTTyVarHeads (f :: * -> Constraint) a = f a  {-* KindSignatures, KindSignatures, KindSignatures, ConstraintKinds *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/TypeApp.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleContexts, TypeOperators #-}
+
+module TypeApp where
+
+import Definitions
+
+f :: C (T a) => T a -> ()  {-* FlexibleContexts, FlexibleContexts *-}
+f = foo                    {-* FlexibleContexts *-}
+
+g :: (C (T a), (T a) :?: (T a)) => T a -> ()  {-* FlexibleContexts, FlexibleContexts, FlexibleContexts, TypeOperators *-}
+g = foo                                       {-* FlexibleContexts *-}
+ test/ExtensionOrganizerTest/FlexibleContextsTest/VarType.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleContexts, ExplicitForAll, KindSignatures, TypeOperators #-}
+
+module VarType where
+
+import Definitions
+
+f :: forall (f :: * -> *) a . C (f a) => f a -> ()  {-* ExplicitForAll, KindSignatures, KindSignatures, KindSignatures *-}
+f = foo
+
+g :: forall (f :: * -> *) a . (C (f a), (f a) :?: a) => f a -> ()  {-* ExplicitForAll, KindSignatures, KindSignatures, KindSignatures, TypeOperators *-}
+g = foo
+ test/ExtensionOrganizerTest/FlexibleContextsTest/WithScopedTyVarsMagic.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
+
+module WithScopedTyVarsMagic where
+
+import Definitions
+
+f :: Eq a => a -> ()
+f = id fCtxt :: C [a] => a -> ()  {-* (FlexibleContexts), FlexibleContexts *-}
test/ExtensionOrganizerTest/Main.hs view
@@ -55,6 +55,8 @@   , mkTests constrainedClassMethodsTest
   , mkTests multiWayIfTest
   , mkTests typeOperatorsTest
+  , mkTests undecidableInstancesTest
+  , mkTests flexibleContextsTest
   ]
 
 testRoot = "test/ExtensionOrganizerTest"
@@ -67,13 +69,14 @@ type TestName        = String
 type ModuleName      = String
 type Line            = Int
-type SimpleMap       = SMap.Map (LogicalRelation Extension) [Line]
+type SimpleMap       = SMap.Map (LogicalRelation Extension) [Occurence Line]
 
 spanToLine :: SrcSpan -> Line
-spanToLine (RealSrcSpan s) = srcSpanEndLine s
+spanToLine (RealSrcSpan s)   = srcSpanEndLine s
+spanToLine (UnhelpfulSpan _) = 0
 
 simplifyExtMap :: ExtMap -> SimpleMap
-simplifyExtMap = SMap.map (map spanToLine)
+simplifyExtMap = SMap.map (map (fmap spanToLine))
 
 getExtensionsFrom :: FilePath -> ModuleName -> IO SimpleMap
 getExtensionsFrom dir moduleName = runGhc (Just libdir) $ do
@@ -178,7 +181,7 @@                       , "InAlt"
                       , "InExpr"
                       , "InMatchLhs"
-                      , "InPatSynRhs"
+                      -- , "InPatSynRhs"
                       , "InPattern"
                       , "InRhsGuard"
                       , "InStmt"
@@ -422,4 +425,37 @@             , "NormalClassDecl"
             , "NormalDataDecl"
             , "NormalInstance"
+            ]
+
+undecidableInstancesTest :: TestSuite
+undecidableInstancesTest = (udRoot, udModules)
+udRoot = "UndecidableInstancesTest"
+udModules = [ "BadTyVars"
+            , "GNDForAssociatedTypes"
+            , "NoSmallerPred"
+            , "SynBadTyVars"
+            , "SynNoSmallerPred"
+            , "SynTupleConstraint"
+            , "SynTyFamBadTyVars"
+            , "SynTyFamNestedTyFun"
+            , "SynTyFamNoSmaller"
+            , "SynTyFunInSuperClass"
+            , "TupleConstraint"
+            , "TyFamBadTyVars"
+            , "TyFamNestedTyFun"
+            , "TyFamNoSmaller"
+            , "TyFunInSuperClass"
+            ]
+
+flexibleContextsTest :: TestSuite
+flexibleContextsTest = (fcRoot, fcModules)
+fcRoot = "FlexibleContextsTest"
+fcModules = [ "ForAll"
+            , "NestedCtx"
+            , "Synonyms"
+            , "TyFamConstraints"
+            , "TypeApp"
+            , "TySynConstraints"
+            , "VarType"
+            , "WithScopedTyVarsMagic"
             ]
test/ExtensionOrganizerTest/TypeFamiliesTest/Definitions.hs view
@@ -17,8 +17,11 @@ type HiddenEqRel a b = EqRel a b
 
 type ComplexEqRelType a =
-  Eq a => a -> a -> (forall c . HiddenEqRel a c => c -> c -> Bool) -> Bool  
+  Eq a => a -> a -> (forall c . HiddenEqRel a c => c -> c -> Bool) -> Bool
 
 
 eqRelName :: EqRel a b => a -> b
 eqRelName = id
+
+nestedEqRelName :: a -> (forall a b . EqRel a b => a -> b) -> a
+nestedEqRelName x f = f x
test/ExtensionOrganizerTest/TypeFamiliesTest/NestedTypeEqualityContextSynonyms.hs view
@@ -7,7 +7,7 @@ {-@ GADTs @-}
 
 f :: HiddenEqRel a b => a -> b  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
-f = id
+f = id                          {-* TypeFamilies + GADTs *-}
 
 g :: ComplexEqRelType a  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
-g x y h = h x y          {-* TypeFamilies + GADTs *-}
+g x y h = h x y          {-* TypeFamilies + GADTs, TypeFamilies + GADTs, (TypeFamilies + GADTs) *-}
test/ExtensionOrganizerTest/TypeFamiliesTest/NestedTypeEqualitySynonyms.hs view
@@ -6,4 +6,4 @@ 
 {-@ GADTs, ConstraintKinds @-}
 
-type TripleEq a b c = (HiddenEqRel a b, HiddenEqRel b c) {-* TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
+type TripleEq a b c = (HiddenEqRel a b, HiddenEqRel b c) {-* TypeFamilies + GADTs, TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
test/ExtensionOrganizerTest/TypeFamiliesTest/TypeEqualityContext.hs view
@@ -5,4 +5,4 @@ {-@ GADTs @-}
 
 f :: a ~ b => a -> b  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
-f = id
+f = id                {-* TypeFamilies + GADTs *-}
test/ExtensionOrganizerTest/TypeFamiliesTest/TypeEqualityContextSynonyms.hs view
@@ -7,7 +7,7 @@ {-@ GADTs @-}
 
 f :: EqRel a b => a -> b  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
-f = id
+f = id                    {-* TypeFamilies + GADTs *-}
 
 g :: TrfAB a b  {-* TypeFamilies + GADTs, TypeFamilies + GADTs *-}
-g = id
+g = id          {-* TypeFamilies + GADTs *-}
test/ExtensionOrganizerTest/TypeFamiliesTest/TypeEqualityInName.hs view
@@ -6,4 +6,10 @@ 
 {-@ GADTs @-}
 
-g = eqRelName {-* TypeFamilies + GADTs *-}
+g1 = eqRelName                  {-* (TypeFamilies + GADTs) *-}
+
+g2 = nestedEqRelName            {-* TypeFamilies + GADTs, (TypeFamilies + GADTs) *-}
+
+x <+> y = nestedEqRelName       {-* TypeFamilies + GADTs, (TypeFamilies + GADTs) *-}
+
+x <-> y = nestedEqRelName 5 id  {-* (TypeFamilies + GADTs) *-}
test/ExtensionOrganizerTest/TypeFamiliesTest/TypeEqualitySynonyms.hs view
@@ -6,4 +6,4 @@ 
 {-@ GADTs, ConstraintKinds @-}
 
-type DoubleEq a b c = (EqRel a b, EqRel b c) {-* TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
+type DoubleEq a b c = (EqRel a b, EqRel b c) {-* TypeFamilies + GADTs, TypeFamilies + GADTs, TypeFamilies + GADTs, ConstraintKinds *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/BadTyVars.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE UndecidableInstances, FlexibleInstances #-}
+
+module BadTyVars where
+
+import Definitions
+
+
+-- NOTE: This instance need FlexibleContexts, but if UndecidableInstances
+-- is turned on, it compiles. Watch out for this!
+instance C (a,a) => C a  {-* UndecidableInstances, FlexibleInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/Definitions.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE TypeFamilies #-}
+
+module Definitions where
+
+class C a where
+  type T a :: *
+
+class C2 a
+class C3 a
+class C4 a
+class C5 a
+
+type family T1 a
+
+type family CT a where
+  CT a = Eq a
+
+data D a b = D a b
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/GNDForAssociatedTypes.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE UndecidableInstances, GeneralizedNewtypeDeriving, TypeFamilies #-}
+
+module GNDForAssociatedTypes where
+
+class C a where
+  type T a :: *                 {-* TypeFamilies, KindSignatures *-}
+
+newtype Loop = MkLoop Loop
+  deriving C                    {-* GeneralizedNewtypeDeriving, UndecidableInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/NoSmallerPred.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleInstances, UndecidableInstances, ExplicitForAll #-}
+
+module NoSmallerPred where
+
+import Definitions
+
+instance Eq a => C a                           {-* UndecidableInstances, FlexibleInstances *-}
+-- these definitions need FlexibleContexts, but they compile anyway ...
+instance Eq (D [a] b) => C2 (a,b)              {-* UndecidableInstances *-}
+instance forall a b . Eq (D [a] b) => C3 (a,b) {-* UndecidableInstances *-}
+instance Eq (D Int Int) => C4 (Int,Int)        {-* UndecidableInstances, FlexibleInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynBadTyVars.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE ConstraintKinds, UndecidableInstances, FlexibleInstances, FlexibleContexts #-}
+
+module SynBadTyVars where
+
+import Definitions
+
+
+type SynC a = C (a,a)  {-* ConstraintKinds, FlexibleContexts, FlexibleContexts *-}
+
+instance SynC (a,a) => C a  {-* UndecidableInstances, FlexibleInstances, FlexibleContexts *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynNoSmallerPred.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE ConstraintKinds, FlexibleInstances, FlexibleContexts, UndecidableInstances, ExplicitForAll #-}
+
+module SynNoSmallerPred where
+
+import Definitions
+
+type Syn1 a   = Eq a                       {-* ConstraintKinds *-}
+type Syn2 a b = Eq (D [a] b)               {-* ConstraintKinds, FlexibleContexts, FlexibleContexts *-}
+type Syn3     = Syn2 Int Int               {-* ConstraintKinds, FlexibleContexts, FlexibleContexts *-}
+
+instance Syn1 a => C a                     {-* UndecidableInstances, FlexibleInstances *-}
+instance Syn2 a b => C2 (a,b)              {-* UndecidableInstances, FlexibleContexts *-}
+instance forall a b . Syn2 a b => C3 (a,b) {-* UndecidableInstances, FlexibleContexts *-}
+instance Syn3 => C4 (Int,Int)              {-* UndecidableInstances, FlexibleInstances, FlexibleContexts *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynTupleConstraint.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE ConstraintKinds, FlexibleInstances, UndecidableInstances #-}
+
+module SynTupleConstraint where
+
+import Definitions
+
+type Syn a = (Ord a, Eq a)  {-* ConstraintKinds *-}
+
+instance Syn a => C a       {-* UndecidableInstances, FlexibleInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynTyFamBadTyVars.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module SynTyFamBadTyVars where
+
+import Definitions hiding (CT)
+
+type Syn0 a     = [a]
+type Syn1 a b   = [(a,b)]
+type Syn2 a     = (a,a)
+type Syn3 a b c = (a,b,c)
+type Syn4 a     = Syn3 a a a
+type Syn5 a b   = (a,b)
+
+
+type instance T1 (Syn0 a) = T1 (Syn2 a)   {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT (Syn1 a b)   = CT (Syn2 a)
+  CT (Syn3 a b c) = CT (Syn4 a)         {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C (a,b) where
+  type T (Syn5 a b) = T (Syn2 a)          {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynTyFamNestedTyFun.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module SynTyFamNestedTyFun where
+
+import Definitions hiding (CT)
+
+type Syn1 a = T1 (T1 a)
+type Syn2 a = CT (CT a)
+
+type instance T1 [a] = Syn1 a  {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT [[a]] = Syn2 a
+  CT a     = Syn2 a            {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C [a] where
+  type T [a] = Syn1 a          {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynTyFamNoSmaller.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module SynTyFamNoSmaller where
+
+import Definitions hiding (CT)
+
+type Syn1 a = T1 a
+type Syn2 a = CT [a]
+type Syn3 a = CT a
+type Syn4 a = T [[a]]
+
+type instance T1 a = Syn1 a         {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT [a] = Syn2 a
+  CT a   = Syn3 a                   {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C [a] where
+  type T [a] = Syn4 a            {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/SynTyFunInSuperClass.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, ConstraintKinds #-}
+
+module SynTyFunInSuperClass where
+
+import Definitions (CT)
+
+type Syn a = CT a   {-* ConstraintKinds *-}
+
+class Syn a => C a  {-* UndecidableInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/TupleConstraint.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
+
+module TupleConstraint where
+
+import Definitions
+
+instance (Ord a, Eq a) => C a  {-* UndecidableInstances, FlexibleInstances *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/TyFamBadTyVars.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module TyFamBadTyVars where
+
+import Definitions hiding (CT)
+
+type instance T1 [a] = T1 (a,a)   {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT [(a,b)] = CT (a,a)
+  CT (a,b,c) = CT (a,a,a)         {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C (a,b) where
+  type T (a,b) = T (a,a)          {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/TyFamNestedTyFun.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module TyFamNestedTyFun where
+
+import Definitions hiding (CT)
+
+type instance T1 [a] = T1 (T1 a)  {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT [[a]] = CT (CT a)
+  CT a     = CT (CT a)            {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C [a] where
+  type T [a] = T (T [a])          {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/TyFamNoSmaller.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
+
+module TyFamNoSmaller where
+
+import Definitions hiding (CT)
+
+type instance T1 a = T1 a         {-* UndecidableInstances, TypeFamilies *-}
+
+type family CT a where
+  CT [a] = CT [a]
+  CT a   = CT a                   {-* UndecidableInstances, UndecidableInstances, TypeFamilies *-}
+
+instance C [a] where
+  type T [a] = T [[a]]            {-* UndecidableInstances, TypeFamilies *-}
+ test/ExtensionOrganizerTest/UndecidableInstancesTest/TyFunInSuperClass.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses #-}
+
+module TyFunInSuperClass where
+
+import Definitions (CT)
+
+class CT a => C a  {-* UndecidableInstances *-}
test/Main.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE LambdaCase, MonoLocalBinds #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE MonoLocalBinds #-}
 
-           
+
 module Main where
 
 import Test.Tasty (TestTree, testGroup, defaultMain)
@@ -142,7 +143,7 @@   , ("Refactor.RenameDefinition.AccentName", "3:1-3:2", "á")
   , ("Refactor.RenameDefinition.QualName", "3:1-3:2", "q")
   , ("Refactor.RenameDefinition.BacktickName", "3:1-3:2", "g")
-  , ("Refactor.RenameDefinition.ParenName", "4:3-4:5", "<->")
+  , ("Refactor.RenameDefinition.ParenName", "4:3-4:5", "<-->")
   , ("Refactor.RenameDefinition.RecordWildcards", "4:32-4:33", "yy")
   , ("Refactor.RenameDefinition.RecordPatternSynonyms", "4:16-4:17", "xx")
   , ("Refactor.RenameDefinition.ClassMember", "7:3-7:4", "q")
@@ -277,7 +278,7 @@ wrongMultiModuleTests =
   [ ("InlineBinding 3:1-3:2", "A", "Refactor" </> "InlineBinding" </> "AppearsInAnother", [])
   ]
-  
+
 autoCorrectTests =
   [ ("Refactor.AutoCorrect.SimpleReParen", "3:5-3:12")
   , ("Refactor.AutoCorrect.ExternalInstanceReParen", "4:5-4:15")
@@ -412,7 +413,7 @@       load LoadAllTargets
       allMods <- getModuleGraph
       selectedMod <- getModSummary (GHC.mkModuleName target)
-      let otherModules = filter (not . (\ms -> ms_mod ms == ms_mod selectedMod && ms_hsc_src ms == ms_hsc_src selectedMod)) allMods
+      let otherModules = filter (not . (\ms -> ms_mod ms == ms_mod selectedMod && ms_hsc_src ms == ms_hsc_src selectedMod)) (mgModSummaries allMods)
       targetMod <- parseTyped selectedMod
       otherMods <- mapM parseTyped otherModules
       res <- performCommand builtinRefactorings (splitOn " " command)
@@ -425,7 +426,7 @@                       Left l -> Left l)
              $ res
 
-type ParsedModule = Ann AST.UModule (Dom RdrName) SrcTemplateStage
+type ParsedModule = Ann AST.UModule (Dom GhcPs) SrcTemplateStage
 
 parseAST :: ModSummary -> Ghc ParsedModule
 parseAST modSum = do
@@ -439,7 +440,7 @@   (if hasCppExtension then prepareASTCpp else prepareAST) sourceOrigin . placeComments (fst annots) (getNormalComments $ snd annots)
      <$> (runTrf (fst annots) (getPragmaComments $ snd annots) $ trfModule ms $ pm_parsed_source p)
 
-type RenamedModule = Ann AST.UModule (Dom GHC.Name) SrcTemplateStage
+type RenamedModule = Ann AST.UModule (Dom GhcRn) SrcTemplateStage
 
 parseRenamed :: ModSummary -> Ghc RenamedModule
 parseRenamed modSum = do