diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+0.10.0
+------
+* Ensure that no imports are placed inbetween cpp directives
+
 0.9.0
 -----
 * Support haddock comments
diff --git a/hsimport.cabal b/hsimport.cabal
--- a/hsimport.cabal
+++ b/hsimport.cabal
@@ -1,13 +1,13 @@
-cabal-version: >=1.9.2
+cabal-version: 2.0
 name: hsimport
-version: 0.9.0
+version: 0.10.0
 license: BSD3
 license-file: LICENSE
 maintainer: daniel.trstenjak@gmail.com
 author: Daniel Trstenjak
 tested-with: ghc ==7.6.2 ghc ==7.6.3 ghc ==7.8.3 ghc ==7.10.1
              ghc ==7.10.2 ghc ==8.0.1 ghc ==8.2.1 ghc ==8.4.2 ghc ==8.6.3
-synopsis: A command line program for extending the import list of a Haskell source file.
+synopsis: Extend the import list of a Haskell source file
 description:
     A command line program for extending the import list of a Haskell source file.
 category: Utils, Development
@@ -37,11 +37,12 @@
         HsImport.ModuleImport
         HsImport.SymbolImport
         HsImport.ImportChange
-        HsImport.Parse
         HsImport.PrettyPrint
         HsImport.Utils
         HsImport.Types
+        HsImport.Parse
         Paths_hsimport
+    default-language: Haskell2010
     ghc-options: -W
     build-depends:
         base >=3 && <5,
@@ -56,20 +57,56 @@
         directory >=1.2.0.1 && <1.4,
         dyre ==0.8.*
 
+library library-internal
+    exposed-modules:
+        HsImport
+        HsImport.Main
+        HsImport.Config
+        HsImport.Args
+        HsImport.ImportPos
+        HsImport.HsImportSpec
+        HsImport.ModuleImport
+        HsImport.SymbolImport
+        HsImport.ImportChange
+        HsImport.PrettyPrint
+        HsImport.Utils
+        HsImport.Types
+        HsImport.Parse
+        Paths_hsimport
+    autogen-modules:
+        Paths_hsimport
+    cpp-options: -DCABAL
+    hs-source-dirs: lib
+    default-language: Haskell2010
+    ghc-options: -W
+    build-depends:
+        base -any,
+        cmdargs -any,
+        haskell-src-exts -any,
+        ilist -any,
+        microlens -any,
+        mtl -any,
+        text -any,
+        split -any,
+        attoparsec -any,
+        directory -any,
+        dyre -any
+
 executable hsimport
     main-is: Main.hs
     cpp-options: -DCABAL
     hs-source-dirs: exe
+    default-language: Haskell2010
     ghc-options: -W
-    ghc-prof-options: -fprof-auto -rtsopts
     build-depends:
         base >=3 && <5,
         hsimport -any
 
-test-suite hsimport-tests
+test-suite tests
     type: exitcode-stdio-1.0
     main-is: Main.hs
     hs-source-dirs: tests
+    default-language: Haskell2010
     ghc-options: -W
     build-depends:
         base >=3 && <5,
@@ -77,4 +114,4 @@
         tasty-golden >=2.2.0.1 && <2.4,
         filepath >=1.3.0.1 && <1.5,
         haskell-src-exts >=1.18.0 && <1.22,
-        hsimport -any
+        library-internal -any
diff --git a/lib/HsImport/HsImportSpec.hs b/lib/HsImport/HsImportSpec.hs
--- a/lib/HsImport/HsImportSpec.hs
+++ b/lib/HsImport/HsImportSpec.hs
@@ -29,7 +29,7 @@
    | otherwise = do
       result <- parseFile $ Args.inputSrcFile args
       case result of
-           Right (HS.ParseOk hsModule) -> return $ Right $
+           Right (ParseResult (HS.ParseOk hsModule) _) -> return $ Right $
               HsImportSpec { sourceFile    = Args.inputSrcFile args
                            , parsedSrcFile = hsModule
                            , moduleImport  = module_
@@ -37,7 +37,7 @@
                            , saveToFile    = saveToFile
                            }
 
-           Right (HS.ParseFailed srcLoc error) -> return $ Left (show srcLoc ++ error)
+           Right (ParseResult (HS.ParseFailed srcLoc error) _) -> return $ Left (show srcLoc ++ error)
 
            Left error -> return $ Left error
 
diff --git a/lib/HsImport/Parse.hs b/lib/HsImport/Parse.hs
--- a/lib/HsImport/Parse.hs
+++ b/lib/HsImport/Parse.hs
@@ -2,11 +2,11 @@
 
 module HsImport.Parse
    ( parseFile
+   , replaceCpp
    ) where
 
 import qualified Data.Text.IO as TIO
 import qualified Data.Text as T
-import Data.Maybe (fromMaybe)
 import Data.List (isPrefixOf)
 import qualified Language.Haskell.Exts as HS
 import Control.Exception (catch, SomeException)
@@ -19,53 +19,70 @@
 
 parseFile :: FilePath -> IO (Either Error ParseResult)
 parseFile file = do
-   srcFile <- unlines. replaceCPPByEmptyLine . lines . T.unpack <$> TIO.readFile file
+   srcFile <- replaceCpp . T.unpack <$> TIO.readFile file
    catch (do let result = parseFileContents srcFile
              case result of
-                  HS.ParseOk _ -> return $ Right result
+                  HS.ParseOk _ -> return . Right $ ParseResult result Nothing
 
                   HS.ParseFailed srcLoc _ -> do
                      srcResult <- parseInvalidSource (lines srcFile) (HS.srcLine srcLoc)
-                     return $ Right $ fromMaybe result srcResult)
+                     return $ case srcResult of
+                                   Just srcRes -> Right srcRes
+                                   Nothing -> Right $ ParseResult result Nothing)
 
          (\(e :: SomeException) -> do
             let srcLines = lines srcFile
             srcResult <- parseInvalidSource srcLines (length srcLines)
             return $ maybe (Left $ show e) Right srcResult)
+
+
+-- | replace the complete cpp directive, from #ifdef till #endif, by empty lines
+replaceCpp :: String -> String
+replaceCpp contents = unlines . reverse $ go (lines contents) [] 0
    where
-      -- | replace CPP directives by an empty line
-      replaceCPPByEmptyLine = map $ \line ->
-         if "#" `isPrefixOf` line
-            then ""
-            else line
+      go [] newLines _ = newLines
+      go lines newLines ifdefLevel = go lines' newLines' ifdefLevel'
+         where
+            currLine    = head lines
+            hasCpp      = "#" `isPrefixOf` currLine
+            hasIf       = "#if" `isPrefixOf` currLine
+            hasEndIf    = "#endif" `isPrefixOf` currLine
+            ifdefLevel' = ifdefLevel + (if hasIf then 1 else 0) - (if hasEndIf then 1 else 0)
+            lines'      = tail lines
+            inCpp       = hasCpp || (max ifdefLevel ifdefLevel') > 0
+            newLines'   = (if inCpp then "" else currLine) : newLines
 
 
+type HsParseResult = HS.ParseResult Module
+
+
 -- | tries to find the maximal part of the source file (from the beginning) that contains
 --   valid/complete Haskell code
 parseInvalidSource :: [String] -> Int -> IO (Maybe ParseResult)
 parseInvalidSource srcLines firstInvalidLine = do
    parseInvalidSource' 1 firstInvalidLine Nothing 0
    where
-      parseInvalidSource' :: Int -> Int -> Maybe (Int, ParseResult) -> Int -> IO (Maybe ParseResult)
+      parseInvalidSource' :: Int -> Int -> Maybe (Int, HsParseResult) -> Int -> IO (Maybe ParseResult)
       parseInvalidSource' lastValidLine currLastLine maxParseOk iteration
          | null srcLines || lastValidLine >= currLastLine
          = return Nothing
 
          | iteration >= 10
-         = return (snd <$> maxParseOk)
+         = return $ case maxParseOk of
+                         Just (lastLine, result) -> Just $ ParseResult result (Just lastLine)
+                         Nothing -> Nothing
 
          | otherwise = do
             catch (case parseFileContents source of
                         result@(HS.ParseOk _)
-                           | nextLine == currLastLine ->
-                              return $ Just result
-                           | otherwise                ->
-                              parseInvalidSource' nextLine currLastLine (maxParseOk' result) iteration'
+                           | nextLine == currLastLine -> return . Just $ ParseResult result (Just lastValidLine)
+                           | otherwise -> parseInvalidSource' nextLine currLastLine (maxParseOk' result) iteration'
 
                         HS.ParseFailed srcLoc _
                            | HS.srcLine srcLoc == firstInvalidLine ->
                               parseInvalidSource' lastValidLine nextLine maxParseOk iteration'
-                           | otherwise                             ->
+
+                           | otherwise ->
                               parseInvalidSource' nextLine currLastLine maxParseOk iteration')
 
                   (\(_ :: SomeException) -> parseInvalidSource' lastValidLine nextLine maxParseOk iteration')
@@ -83,7 +100,7 @@
                     _ -> Just (nextLine, nextResult)
 
 
-parseFileContents :: String -> ParseResult
+parseFileContents :: String -> HsParseResult
 parseFileContents contents =
    let result = HS.parseFileContentsWithComments parseMode contents
        in case result of
diff --git a/lib/HsImport/Types.hs b/lib/HsImport/Types.hs
--- a/lib/HsImport/Types.hs
+++ b/lib/HsImport/Types.hs
@@ -14,8 +14,17 @@
 type Name        = HS.Name Annotation
 type Module      = HS.Module Annotation
 type ModuleName  = String
-type ParseResult = HS.ParseResult Module
 type Error       = String
+
+data ParseResult = ParseResult
+   { -- | the parse result
+     result :: HS.ParseResult Module
+
+     -- | if the source file isn't completely parsable, because e.g.
+     --   it contains incomplete Haskell code, then 'lastValidLine'
+     --   contains the last line till the source is parsable
+   , lastValidLine :: Maybe Int
+   }
 
 firstSrcLine :: Annotation -> SrcLine
 firstSrcLine = minimum . map HS.srcSpanStartLine . srcSpans
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -8,11 +8,13 @@
 import Data.List (intercalate)
 import qualified Language.Haskell.Exts as HS
 import qualified HsImport as HI
+import qualified HsImport.Parse as HIP
+import HsImport.Types
 
 main = defaultMain tests
 
 tests :: TestTree
-tests = testGroup "Tests" [moduleTests, symbolTests]
+tests = testGroup "Tests" [moduleTests, symbolTests, replaceCppTests, parseTests]
 
 moduleTests :: TestTree
 moduleTests = testGroup "Module Tests"
@@ -43,16 +45,17 @@
    , test "ModuleTest24" $ HI.defaultArgs { HI.moduleName = "Control.Monad", HI.qualifiedName = "CM" }
    , test "ModuleTest25" $ HI.defaultArgs { HI.moduleName = "Control.Monad", HI.qualifiedName = "Control.Monad" }
    , test "ModuleTest26" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
-   , test_ "ModuleTest27" (HI.defaultConfig { HI.findImportPos = importPosBeforeFirst }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
-   , test_ "ModuleTest28" (HI.defaultConfig { HI.findImportPos = importPosAfterFirst }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
-   , test_ "ModuleTest29" (HI.defaultConfig { HI.findImportPos = importPosBeforeLast }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
-   , test_ "ModuleTest30" (HI.defaultConfig { HI.findImportPos = importPosAfterLast }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
+   , configTest "ModuleTest27" (HI.defaultConfig { HI.findImportPos = importPosBeforeFirst }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
+   , configTest "ModuleTest28" (HI.defaultConfig { HI.findImportPos = importPosAfterFirst }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
+   , configTest "ModuleTest29" (HI.defaultConfig { HI.findImportPos = importPosBeforeLast }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
+   , configTest "ModuleTest30" (HI.defaultConfig { HI.findImportPos = importPosAfterLast }) (HI.defaultArgs { HI.moduleName = "Control.Monad" })
    , test "ModuleTest31" $ HI.defaultArgs { HI.moduleName = "Control.Monad", HI.as = "CM" }
    , test "ModuleTest32" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
    , test "ModuleTest33" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
    , test "ModuleTest34" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
    , test "ModuleTest35" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
    , test "ModuleTest36" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
+   , test "ModuleTest37" $ HI.defaultArgs { HI.moduleName = "Control.Monad" }
    ]
 
 
@@ -87,19 +90,34 @@
    , test "SymbolTest26" $ HI.defaultArgs { HI.moduleName = "Foo", HI.symbolName = "bar" }
    , test "SymbolTest27" $ HI.defaultArgs { HI.moduleName = "Ugah.Blub", HI.symbolName = "g" }
    , test "SymbolTest28" $ HI.defaultArgs { HI.moduleName = "Ugah.Blub", HI.symbolName = "d" }
-   , test_ "SymbolTest29" (HI.defaultConfig { HI.prettyPrint = prettyPrint }) (HI.defaultArgs { HI.moduleName = "X.Y", HI.symbolName = "x" })
-   , test_ "SymbolTest30" (HI.defaultConfig { HI.prettyPrint = prettyPrint }) (HI.defaultArgs { HI.moduleName = "X.Y", HI.symbolName = "x" })
+   , configTest "SymbolTest29" (HI.defaultConfig { HI.prettyPrint = prettyPrint }) (HI.defaultArgs { HI.moduleName = "X.Y", HI.symbolName = "x" })
+   , configTest "SymbolTest30" (HI.defaultConfig { HI.prettyPrint = prettyPrint }) (HI.defaultArgs { HI.moduleName = "X.Y", HI.symbolName = "x" })
    , test "SymbolTest31" $ HI.defaultArgs { HI.moduleName = "Ugah.Blub", HI.symbolName = "d" }
    , test "SymbolTest32" $ HI.defaultArgs { HI.moduleName = "Control.Foo", HI.symbolName = "foo" }
    ]
 
 
+replaceCppTests :: TestTree
+replaceCppTests = testGroup "ReplaceCpp Tests"
+   [ replaceCppTest "ReplaceCppTest1"
+   , replaceCppTest "ReplaceCppTest2"
+   , replaceCppTest "ReplaceCppTest3"
+   ]
+
+
+parseTests :: TestTree
+parseTests = testGroup "Parse Tests"
+   [ parseTest "ParseTest1"
+   , parseTest "ParseTest2"
+   ]
+
+
 test :: String -> HI.HsImportArgs -> TestTree
-test testName args = test_ testName HI.defaultConfig args
+test testName args = configTest testName HI.defaultConfig args
 
 
-test_ :: String -> HI.Config -> HI.HsImportArgs -> TestTree
-test_ testName config args =
+configTest :: String -> HI.Config -> HI.HsImportArgs -> TestTree
+configTest testName config args =
    goldenVsFileDiff testName diff goldenFile outputFile command
    where
       command = do
@@ -107,6 +125,39 @@
          case maybeErr of
               Just err -> hPutStrLn stderr ("hsimport: " ++ err)
               _        -> return ()
+
+      diff ref new = ["diff", "-u", ref, new]
+
+      goldenFile = "tests" </> "goldenFiles" </> testName <.> "hs"
+      outputFile = "tests" </> "outputFiles" </> testName <.> "hs"
+      inputFile  = "tests" </> "inputFiles"  </> testName <.> "hs"
+
+
+replaceCppTest :: String -> TestTree
+replaceCppTest testName =
+   goldenVsFileDiff testName diff goldenFile outputFile command
+   where
+      command = do
+         contents <- readFile inputFile
+         writeFile outputFile $ HIP.replaceCpp contents
+
+      diff ref new = ["diff", "-u", ref, new]
+
+      goldenFile = "tests" </> "goldenFiles" </> testName <.> "hs"
+      outputFile = "tests" </> "outputFiles" </> testName <.> "hs"
+      inputFile  = "tests" </> "inputFiles"  </> testName <.> "hs"
+
+
+parseTest :: String -> TestTree
+parseTest testName =
+   goldenVsFileDiff testName diff goldenFile outputFile command
+   where
+      command = do
+         Right (ParseResult (HS.ParseOk _) lastValidLine) <- HIP.parseFile inputFile
+         contents <- readFile inputFile
+         case lastValidLine of
+              Just line -> writeFile outputFile $ unlines . take line . lines $ contents
+              Nothing -> writeFile outputFile contents
 
       diff ref new = ["diff", "-u", ref, new]
 
diff --git a/tests/goldenFiles/ModuleTest37.hs b/tests/goldenFiles/ModuleTest37.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ModuleTest37.hs
@@ -0,0 +1,22 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+#ifdef FOO
+import Control.Applicative
+#endif
+
+import Control.BiFunctor
+import Control.Monad
+
+f :: Int -> Int
+-- ^ Some Haddock doc
+--   One line more
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/goldenFiles/ParseTest1.hs b/tests/goldenFiles/ParseTest1.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ParseTest1.hs
@@ -0,0 +1,16 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
diff --git a/tests/goldenFiles/ParseTest2.hs b/tests/goldenFiles/ParseTest2.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ParseTest2.hs
@@ -0,0 +1,12 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( f
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f i = i + 3
diff --git a/tests/goldenFiles/ReplaceCppTest1.hs b/tests/goldenFiles/ReplaceCppTest1.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ReplaceCppTest1.hs
@@ -0,0 +1,18 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+
+import Ugah.Foo
+import Control.Applicative
+
+
+
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/goldenFiles/ReplaceCppTest2.hs b/tests/goldenFiles/ReplaceCppTest2.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ReplaceCppTest2.hs
@@ -0,0 +1,21 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+
+import Ugah.Foo
+import Control.Applicative
+
+
+
+
+
+
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/goldenFiles/ReplaceCppTest3.hs b/tests/goldenFiles/ReplaceCppTest3.hs
new file mode 100644
--- /dev/null
+++ b/tests/goldenFiles/ReplaceCppTest3.hs
@@ -0,0 +1,12 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( f
+   ) where
+
+import Ugah.Foo
+import Control.Applicative
+
+
+
+f :: Int -> Int
+f i = i + 3
diff --git a/tests/inputFiles/ModuleTest37.hs b/tests/inputFiles/ModuleTest37.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ModuleTest37.hs
@@ -0,0 +1,21 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+#ifdef FOO
+import Control.Applicative
+#endif
+
+import Control.BiFunctor
+
+f :: Int -> Int
+-- ^ Some Haddock doc
+--   One line more
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/inputFiles/ParseTest1.hs b/tests/inputFiles/ParseTest1.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ParseTest1.hs
@@ -0,0 +1,18 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/inputFiles/ParseTest2.hs b/tests/inputFiles/ParseTest2.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ParseTest2.hs
@@ -0,0 +1,12 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( f
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f i = i + 3
diff --git a/tests/inputFiles/ReplaceCppTest1.hs b/tests/inputFiles/ReplaceCppTest1.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ReplaceCppTest1.hs
@@ -0,0 +1,18 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/inputFiles/ReplaceCppTest2.hs b/tests/inputFiles/ReplaceCppTest2.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ReplaceCppTest2.hs
@@ -0,0 +1,21 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( blub
+   , foo
+   , bar
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#ifdef GOO
+import Ugah.Blub
+#endif
+#endif
+f :: Int -> Int
+f = (+ 3)
+
+g :: Int -> Int
+g =
+   where
diff --git a/tests/inputFiles/ReplaceCppTest3.hs b/tests/inputFiles/ReplaceCppTest3.hs
new file mode 100644
--- /dev/null
+++ b/tests/inputFiles/ReplaceCppTest3.hs
@@ -0,0 +1,12 @@
+{-# Language PatternGuards #-}
+module Blub
+   ( f
+   ) where
+#include "Foo.h"
+import Ugah.Foo
+import Control.Applicative
+#ifdef FOO
+import Ugah.Blub
+#endif
+f :: Int -> Int
+f i = i + 3
