@@ -21,7 +21,7 @@ import Control.Applicative
2121import Control.Exception
2222import Control.Monad
2323import Control.Monad.Trans.Maybe
24- import Data.Char (isAlpha )
24+ import Data.Char (isAlpha , isDigit )
2525import Data.IORef
2626import Data.List
2727import Data.List.Split
@@ -44,6 +44,7 @@ import Language.Haskell.GhcMod.SrcUtils (listifySpans)
4444import Outputable
4545import System.Directory
4646import System.FilePath
47+ import Text.ParserCombinators.ReadP ((+++) )
4748
4849import qualified Data.Map as M
4950import qualified Data.Set as Set
@@ -207,7 +208,6 @@ toImportDecl dflags idecl = NiceImportDecl
207208-- False
208209-- >>> postfixMatch "bar" "bar"
209210-- True
210-
211211postfixMatch :: String -> QualifiedName -> Bool
212212postfixMatch originalSymbol qName = endTerm `isSuffixOf` qName
213213 where endTerm = Safe. lastNote
@@ -439,22 +439,44 @@ refineRemoveHiding exports = map (\e -> e { qualifiedExports = f e }) exports
439439
440440 qualifyName :: [QualifiedName ] -> String -> QualifiedName
441441 qualifyName qualifiedNames name
442- -- = case filter (postfixMatch name) qualifiedNames of
443- = case nub' (filter (name `f` ) qualifiedNames) of
442+ = case nub' (filter (postfixMatch' name) qualifiedNames) of
444443 [match] -> match
445444 m -> fail $ " ImportedFrom: could not qualify "
446445 ++ name ++ " from these exports: "
447446 ++ show qualifiedNames ++ " \n matches: "
448447 ++ show m
449448
450- -- Time for some stringly typed rubbish. The previous test used
451- -- postfixMatch but this failed on an import that had "hiding (lines, unlines)" since
452- -- both lines and unlines matched. Prepending a dot doesn't work due to things like ".=" from
453- -- Control.Lens. So we manually check that the suffix matches, that the next symbol is a dot,
454- -- and then an alpha character, which hopefully is the end of a module name. Such a mess.
455- where f n qn = if length qn - length n - 2 >= 0
456- then n `isSuffixOf` qn && isAlpha (qn !! (length qn - length n - 2 )) && (qn !! (length qn - length n - 1 )) == ' .'
457- else throw $ GMEString $ " ImportedFrom internal error: trying to check if \" " ++ n ++ " \" is a match for \" " ++ qn ++ " \" "
449+ postfixMatch' n qn
450+ | n == qn = True
451+ | otherwise = case runRP (f $ reverse n) (reverse qn) of
452+ Left _ -> False
453+ Right () -> True
454+ where
455+ f n = do
456+ _ <- RP. string n
457+ _ <- RP. char ' .'
458+ _ <- RP. manyTill nameThenDot (nameThenEnd +++ nameThenEnd')
459+ return ()
460+
461+ -- Valid chars in a haskell module name:
462+ -- https://www.haskell.org/onlinereport/syntax-iso.html
463+ modChar c = isAlpha c || isDigit c || (c == ' \' ' )
464+
465+ nameThenEnd = do
466+ RP. many1 $ RP. satisfy modChar
467+ RP. eof
468+
469+ nameThenEnd' = do
470+ RP. many1 $ RP. satisfy modChar
471+ RP. char ' :'
472+ RP. manyTill RP. get RP. eof
473+ RP. eof
474+
475+ nameThenDot = do
476+ RP. many1 $ RP. satisfy modChar
477+ RP. char ' .'
478+ return ()
479+
458480
459481refineExportsIt :: MySymbol -> [ModuleExports ] -> [ModuleExports ]
460482refineExportsIt mysymbol exports = map (\ e -> e { qualifiedExports = f symbol e }) exports
0 commit comments