on master help sign in
Fix add suggested import for operators (#428)
commitfd01d20cc92dce83e3e807e2db4c9532a6108cd1 authorPepe Iborra <pepeiborra@gmail.com> dateFri 14 Feb 2020, 13:41 (7 years ago) parent71ecd10
3 files changed+51−11
src/Development/IDE/GHC/Util.hs+9 src/Development/IDE/Plugin/CodeAction.hs+22−11 test/exe/Main.hs+20
src/Development/IDE/GHC/Util.hs+9
@@ -9,6 +9,7 @@ module Development.IDE.GHC.Util(
99 runGhcEnv,
1010 -- * GHC wrappers
1111 prettyPrint,
12+ ParseResult(..), runParser,
1213 lookupPackageConfig,
1314 moduleImportPath,
1415 cgGutsToCoreModule,
@@ -47,6 +48,7 @@ import qualified Data.Text as T
4748import qualified Data.Text.Encoding as T
4849import qualified Data.Text.Encoding.Error as T
4950import qualified Data.ByteString as BS
51+import Lexer
5052import StringBuffer
5153import System.FilePath
5254
@@ -82,6 +84,13 @@ lookupPackageConfig unitId env =
8284textToStringBuffer :: T.Text -> StringBuffer
8385textToStringBuffer = stringToStringBuffer . T.unpack
8486
87+runParser :: DynFlags -> String -> P a -> ParseResult a
88+runParser flags str parser = unP parser parseState
89+ where
90+ filename = "<interactive>"
91+ location = mkRealSrcLoc (mkFastString filename) 1 1
92+ buffer = stringToStringBuffer str
93+ parseState = mkPState flags buffer location
8594
8695-- | Pretty print a GHC value using 'unsafeGlobalDynFlags '.
8796prettyPrint :: Outputable a => a -> String
src/Development/IDE/Plugin/CodeAction.hs+22−11
@@ -17,6 +17,7 @@ import Development.IDE.Core.RuleTypes
1717import Development.IDE.Core.Service
1818import Development.IDE.Core.Shake
1919import Development.IDE.GHC.Error
20+import Development.IDE.GHC.Util
2021import Development.IDE.LSP.Server
2122import Development.IDE.Types.Location
2223import Development.IDE.Types.Options
@@ -32,9 +33,13 @@ import Data.Maybe
3233import Data.List.Extra
3334import qualified Data.Text as T
3435import Data.Tuple.Extra ((&&&))
36+import HscTypes
37+import OccName
38+import Parser
39+import RdrName
3540import Text.Regex.TDFA ((=~), (=~~))
3641import Text.Regex.TDFA.Text()
37−import Outputable (ppr, showSDocUnsafe)
42+import Outputable (showSDoc, ppr, showSDocUnsafe)
3843import DynFlags (xFlags, FlagSpec(..))
3944import GHC.LanguageExtensions.Type (Extension)
4045
@@ -54,12 +59,15 @@ codeAction lsp state (TextDocumentIdentifier uri) _range CodeActionContext{_diag
5459 -- logInfo (ideLogger ide) $ T.pack $ "Code action req: " ++ show arg
5560 contents <- LSP.getVirtualFileFunc lsp $ toNormalizedUri uri
5661 let text = Rope.toText . (_text :: VirtualFile -> Rope.Rope) <$> contents
57− (ideOptions, parsedModule) <- runAction state $
58− (,) <$> getIdeOptions
59− <*> (getParsedModule . toNormalizedFilePath) `traverse` uriToFilePath uri
62+ mbFile = toNormalizedFilePath <$> uriToFilePath uri
63+ (ideOptions, parsedModule, env) <- runAction state $
64+ (,,) <$> getIdeOptions
65+ <*> getParsedModule `traverse` mbFile
66+ <*> use_ GhcSession `traverse` mbFile
67+ let dflags = hsc_dflags . hscEnv <$> env
6068 pure $ Right
6169 [ CACodeAction $ CodeAction title (Just CodeActionQuickFix) (Just $ List [x]) (Just edit) Nothing
62− | x <- xs, (title, tedit) <- suggestAction ideOptions ( join parsedModule ) text x
70+ | x <- xs, (title, tedit) <- suggestAction dflags ideOptions ( join parsedModule ) text x
6371 , let edit = WorkspaceEdit (Just $ Map.singleton uri $ List tedit) Nothing
6472 ]
6573
@@ -98,10 +106,10 @@ executeAddSignatureCommand _lsp _ideState ExecuteCommandParams{..}
98106 | otherwise
99107 = return (Null, Nothing)
100108
101−suggestAction :: IdeOptions -> Maybe ParsedModule -> Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]
102−suggestAction ideOptions parsedModule text diag = concat
109+suggestAction :: Maybe DynFlags -> IdeOptions -> Maybe ParsedModule -> Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]
110+suggestAction dflags ideOptions parsedModule text diag = concat
103111 [ suggestAddExtension diag
104− , suggestExtendImport text diag
112+ , suggestExtendImport dflags text diag
105113 , suggestFillHole diag
106114 , suggestFillTypeWildcard diag
107115 , suggestFixConstructorImport text diag
@@ -268,20 +276,23 @@ suggestFillHole Diagnostic{_range=_range,..}
268276
269277 | otherwise = []
270278
271−suggestExtendImport :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]
272−suggestExtendImport contents Diagnostic{_range=_range,..}
279+suggestExtendImport :: Maybe DynFlags -> Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]
280+suggestExtendImport (Just dflags) contents Diagnostic{_range=_range,..}
273281 | Just [binding, mod, srcspan] <-
274282 matchRegex _message
275283 "Perhaps you want to add ‘([^’]*)’ to the import list in the import of ‘([^’]*)’ *\\((.*)\\).$"
276284 , Just c <- contents
285+ , POk _ (L _ name) <- runParser dflags (T.unpack binding) parseIdentifier
277286 = let range = case [ x | (x,"") <- readSrcSpan (T.unpack srcspan)] of
278287 [s] -> let x = srcSpanToRange s
279288 in x{_end = (_end x){_character = succ (_character (_end x))}}
280289 _ -> error "bug in srcspan parser"
281290 importLine = textInRange range c
291+ printedName = let rn = rdrNameOcc name in showSDoc dflags $ parenSymOcc rn (ppr rn)
282292 in [("Add " <> binding <> " to the import list of " <> mod
283− , [TextEdit range (addBindingToImportList binding importLine)])]
293+ , [TextEdit range (addBindingToImportList (T.pack printedName) importLine)])]
284294 | otherwise = []
295+suggestExtendImport Nothing _ _ = []
285296
286297suggestFixConstructorImport :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]
287298suggestFixConstructorImport _ Diagnostic{_range=_range,..}
test/exe/Main.hs+20
@@ -752,6 +752,26 @@ extendImportTests = testGroup "extend import actions"
752752 , "import ModuleA as A (stuffA, stuffB)"
753753 , "main = print (stuffA, stuffB)"
754754 ])
755+ , testSession "extend single line import with operator" $ template
756+ (T.unlines
757+ [ "module ModuleA where"
758+ , "(.*) :: Integer -> Integer -> Integer"
759+ , "x .* y = x * y"
760+ , "stuffB :: Integer"
761+ , "stuffB = 123"
762+ ])
763+ (T.unlines
764+ [ "module ModuleB where"
765+ , "import ModuleA as A (stuffB)"
766+ , "main = print (stuffB .* stuffB)"
767+ ])
768+ (Range (Position 3 17) (Position 3 18))
769+ "Add .* to the import list of ModuleA"
770+ (T.unlines
771+ [ "module ModuleB where"
772+ , "import ModuleA as A ((.*), stuffB)"
773+ , "main = print (stuffB .* stuffB)"
774+ ])
755775 , testSession "extend single line import with type" $ template
756776 (T.unlines
757777 [ "module ModuleA where"