diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
 Changelog for record-dot-preprocessor
 
+0.2.10, released 2021-03-01
+    #40, compatibility with qualified QuasiQuotes
+    Emit LINE pragmas slightly earlier in some cases
+    #37, do a better job at HLint clean
 0.2.9, released 2021-02-27
     #37, make the output HLint clean
     Don't add the OverloadedLabels extension
diff --git a/preprocessor/Edit.hs b/preprocessor/Edit.hs
--- a/preprocessor/Edit.hs
+++ b/preprocessor/Edit.hs
@@ -58,8 +58,17 @@
 -- instead relying on lack of whitespace in the opener and existence of a paired
 -- closed (@|]@)
 isQuasiQuotation :: PL -> Bool
-isQuasiQuotation (Paren (L "[") inner@(Item qq : Item (L "|") : _) (L "]"))
-    | Item close@(L "|") <- last inner = null (whitespace qq) && null (whitespace close)
+isQuasiQuotation (Paren open@(L "[") inner@(_:_) (L "]"))
+    | null (whitespace open)
+    , qname inner
+    , Item close@(L "|") <- last inner
+    , null (whitespace close)
+    = True
+    where
+        -- a (potentially) qualified name with no whitespace near it, ending with |
+        qname (Item a@(L _) : Item b@(L ".") : c) | null (whitespace a), null (whitespace b) = qname c
+        qname (Item a@(L _) : Item (L x):_) = "|" `isPrefixOf` x
+        qname _ = False
 isQuasiQuotation _ = False
 
 isField (x:_) = x == '_' || isLower x
@@ -86,12 +95,12 @@
         prefix = "{-# LANGUAGE DuplicateRecordFields, DataKinds, FlexibleInstances, TypeApplications, FlexibleContexts, MultiParamTypeClasses, TypeFamilies, TypeOperators, GADTs, UndecidableInstances #-}\n" ++
                  -- it's too hard to avoid generating excessive brackets, so just ignore the code
                  -- only really applies to people using it through Haskell Language Server (see #37)
-                 "{- HLINT module ignore Redundant bracket -}"
+                 "{- HLINT ignore \"Redundant bracket\" -}"
         imports = "import qualified GHC.Records.Extra as Z"
         -- if you import two things that have preprocessor_unused, and export them as modules, you don't want them to clash
-        trailing modName = "_recordDotPreprocessorUnused_" ++ uniq ++ " :: Z.HasField \"\" r a => r -> a;" ++
-                           "_recordDotPreprocessorUnused_" ++ uniq ++ " = Z.getField @\"\""
-            where uniq = map (\x -> if isAlphaNum x then x else '_') $ concat $ take 19 $ takeWhile modPart $ map lexeme $ unparens modName
+        trailing modName = "_recordDotPreprocessorUnused" ++ uniq ++ " :: Z.HasField \"\" r a => r -> a;" ++
+                           "_recordDotPreprocessorUnused" ++ uniq ++ " = Z.getField @\"\""
+            where uniq = filter isAlphaNum $ concat $ take 19 $ takeWhile modPart $ map lexeme $ unparens modName
         modPart x = x == "." || all isUpper (take 1 x)
 
 
diff --git a/preprocessor/Lexer.hs b/preprocessor/Lexer.hs
--- a/preprocessor/Lexer.hs
+++ b/preprocessor/Lexer.hs
@@ -114,7 +114,10 @@
         go ghcLine startLine ((i, x):xs) =
             (if emitDropping then dropping i else "") ++
             x ++
-            go ((if emitDropping then i else ghcLine) + length (filter (== '\n') x)) ("\n" `isSuffixOf` x) xs
+            go
+                ((if emitDropping then i else ghcLine) + length (filter (== '\n') x))
+                (if null x then startLine else "\n" `isSuffixOf` x)
+                xs
             where emitDropping = ghcLine /= i && i /= 0 && startLine
         go _ _ [] = ""
 
diff --git a/record-dot-preprocessor.cabal b/record-dot-preprocessor.cabal
--- a/record-dot-preprocessor.cabal
+++ b/record-dot-preprocessor.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.18
 build-type:         Simple
 name:               record-dot-preprocessor
-version:            0.2.9
+version:            0.2.10
 license:            BSD3
 x-license:          BSD-3-Clause OR Apache-2.0
 license-file:       LICENSE
