Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 23bc8e8

Browse files
committed
Fix error message parsing to import types
Fix error message parsing to enable HsImport plugin to import Types. Moreover, fix generation of Code Actions to avoid cases where the same Code Action was displayed multiple times.
1 parent eae2e4b commit 23bc8e8

File tree

4 files changed

+91
-33
lines changed

4 files changed

+91
-33
lines changed

hie-plugin-api/Haskell/Ide/Engine/Cradle.hs

+6-6
Original file line numberDiff line numberDiff line change
@@ -786,22 +786,22 @@ isFilePathPrefixOf dir fp = isJust $ stripFilePath dir fp
786786
--
787787
-- >>> stripFilePath "app" "app/File.hs"
788788
-- Just "File.hs"
789-
789+
--
790790
-- >>> stripFilePath "src" "app/File.hs"
791791
-- Nothing
792-
792+
--
793793
-- >>> stripFilePath "src" "src-dir/File.hs"
794794
-- Nothing
795-
795+
--
796796
-- >>> stripFilePath "." "src/File.hs"
797797
-- Just "src/File.hs"
798-
798+
--
799799
-- >>> stripFilePath "app/" "./app/Lib/File.hs"
800800
-- Just "Lib/File.hs"
801-
801+
--
802802
-- >>> stripFilePath "/app/" "./app/Lib/File.hs"
803803
-- Nothing -- Nothing since '/app/' is absolute
804-
804+
--
805805
-- >>> stripFilePath "/app" "/app/Lib/File.hs"
806806
-- Just "Lib/File.hs"
807807
stripFilePath :: FilePath -> FilePath -> Maybe FilePath

src/Haskell/Ide/Engine/Plugin/HsImport.hs

+68-26
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ codeActionProvider plId docId _ context = do
339339
importModuleAction
340340
:: SearchStyle -> ImportDiagnostic -> ModuleName -> SymbolName -> IdeM [J.CodeAction]
341341
importModuleAction searchStyle impDiagnostic moduleName symbolTerm =
342-
catMaybes <$> sequenceA codeActions
342+
catMaybes <$> sequenceA importListActions
343343
where
344344
importListActions :: [IdeM (Maybe J.CodeAction)]
345345
importListActions = case searchStyle of
@@ -353,34 +353,42 @@ codeActionProvider plId docId _ context = do
353353
-- If the term to import is a simple symbol, such as a function,
354354
-- import only this function
355355
Symbol
356-
-> [ mkImportAction moduleName impDiagnostic . Just . Only
356+
-> [ Just importModuleCodeAction
357+
, mkImportAction moduleName impDiagnostic . Just . Only
357358
<$> symName symbolTerm
358-
]
359+
]
359360
-- Constructors can be imported in two ways, either all
360361
-- constructors of a type or only a subset.
361362
-- We can only import a single constructor at a time though.
362363
Constructor
363-
-> [ mkImportAction moduleName impDiagnostic . Just . AllOf
364-
<$> datatypeName symbolTerm
365-
, (\dt sym -> mkImportAction moduleName impDiagnostic . Just
366-
$ OneOf dt sym)
367-
<$> datatypeName symbolTerm
368-
<*> symName symbolTerm
369-
]
364+
-> case typeDeclaration symbolTerm of
365+
-- If the symbolTerm is actually a data declaration
366+
-- dont generate code actions for them.
367+
Just _ -> []
368+
Nothing ->
369+
[ Just importModuleCodeAction
370+
, mkImportAction moduleName impDiagnostic . Just . AllOf
371+
<$> datatypeName symbolTerm
372+
, (\dt sym -> mkImportAction moduleName impDiagnostic . Just
373+
$ OneOf dt sym)
374+
<$> datatypeName symbolTerm
375+
<*> symName symbolTerm
376+
]
370377
-- If we are looking for a type, import it as just a symbol
371378
Type
372-
-> [ mkImportAction moduleName impDiagnostic . Just . Only
373-
<$> symName symbolTerm]
374-
375-
-- | All code actions that may be available
376-
-- Currently, omits all
377-
codeActions :: [IdeM (Maybe J.CodeAction)]
378-
codeActions = case termType impDiagnostic of
379-
Hiding _ -> [] {- If we are hiding an import, we can not import
380-
a module hiding everything from it. -}
381-
-- Simple import, import the whole module
382-
Import _ -> [mkImportAction moduleName impDiagnostic Nothing]
383-
++ importListActions
379+
-> case typeDeclaration symbolTerm of
380+
Nothing -> []
381+
-- Only generate code actions,
382+
-- if the symbolTerm is actually a data declaration
383+
Just dataTerm ->
384+
[ Just importModuleCodeAction
385+
, Just $ mkImportAction moduleName impDiagnostic (Just $ Only dataTerm)
386+
, Just $ mkImportAction moduleName impDiagnostic (Just $ AllOf dataTerm)
387+
]
388+
389+
-- | Plain Code Action to import the given module as a whole.
390+
importModuleCodeAction :: IdeM (Maybe J.CodeAction)
391+
importModuleCodeAction = mkImportAction moduleName impDiagnostic Nothing
384392

385393
-- | Retrieve the function signature of a term such as
386394
-- >>> signatureOf "take :: Int -> [a] -> [a]"
@@ -391,6 +399,40 @@ codeActionProvider plId docId _ context = do
391399
typeSig <- S.tailMay parts
392400
S.headMay typeSig
393401

402+
-- | Given a term 'data Sum f g a', extract the name of the type 'Sum'.
403+
--
404+
-- Can be used to obtain the Type name.
405+
-- Can also be used to check whether the given term is from the
406+
-- Type level or Value level.
407+
-- Constructors and Types are sometimes indistinguishable,
408+
-- e.g. querying for 'Sum', possible results include:
409+
--
410+
-- * "data Sum f g a"
411+
-- * "Sum :: a -> Sum a"
412+
--
413+
-- Depending on whether we are looking for a Type or Value,
414+
-- we want to generate different Code Actions.
415+
-- Important to generate the correct Code Actions.
416+
--
417+
-- >>> typeDeclaration "data Sum f g a"
418+
-- Just "Sum"
419+
--
420+
-- >>> typeDeclaration "Sum :: Int -> Sum a"
421+
-- Nothing
422+
typeDeclaration :: T.Text -> Maybe T.Text
423+
typeDeclaration arg = do
424+
let parts = T.words arg
425+
case parts of
426+
declaration : typeName : _typeArgs
427+
| declaration `elem` typeDeclarations ->
428+
Just typeName
429+
_ ->
430+
Nothing
431+
432+
-- | Declarations for types in the Haskell language.
433+
typeDeclarations :: [T.Text]
434+
typeDeclarations = ["data", "newtype", "type"]
435+
394436
-- | Retrieve the datatype name of a Constructor.
395437
--
396438
-- >>> datatypeName "Null :: Data.Aeson.Internal.Types.Value"
@@ -492,13 +534,13 @@ extractImportableTerm dirtyMsg = do
492534
extractTerm prefix symTy =
493535
importMsg
494536
>>= T.stripPrefix prefix
537+
>>= Just . Hie.extractTerm' . T.strip
495538
>>= \name -> Just (name, Import symTy)
496539

497-
extractType b =
498-
extractTerm ("Not in scope: type constructor or class " <> b) Type
540+
extractType =
541+
extractTerm "Not in scope: type constructor or class" Type
499542

500543
extractedTerm = asum
501544
[ extractTerm "Variable not in scope: " Symbol
502-
, extractType ""
503-
, extractType "`" -- Needed for windows
545+
, extractType
504546
, extractTerm "Data constructor not in scope: " Constructor]

src/Haskell/Ide/Engine/Support/HieExtras.hs

+16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Haskell.Ide.Engine.Support.HieExtras
1414
, getReferencesInDoc
1515
, getModule
1616
, extractTerm
17+
, extractTerm'
1718
, findDef
1819
, findTypeDef
1920
, showName
@@ -239,6 +240,21 @@ extractTerm txt =
239240
. T.dropWhileEnd (== e)
240241
. T.dropAround (\c -> c /= b && c /= e)
241242

243+
-- | Extract a term from a compiler message.
244+
-- Removes whitespace and tries to extract a message between '‘' and '’' falling back to '`' and '\''
245+
-- (the used ones in Windows systems).
246+
-- Different to @extractTerm@, it does not require that the term is actually surrounded
247+
-- and can be used to sanitize the input.
248+
extractTerm' :: T.Text -> T.Text
249+
extractTerm' txt =
250+
case extract '' '' txt of
251+
"" -> extract '`' '\'' txt -- Needed for windows
252+
term -> term
253+
where extract b e = T.dropWhile (== b)
254+
. T.dropWhileEnd (== e)
255+
. T.strip
256+
257+
242258
-- ---------------------------------------------------------------------
243259

244260
-- | Return the type definition of the symbol at the given position.

src/Haskell/Ide/Engine/Support/Hoogle.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Data.Aeson
1111
import Data.Bifunctor
1212
import Data.Maybe
1313
import qualified Data.Text as T
14-
import Data.List
14+
import Data.List
1515
import Haskell.Ide.Engine.MonadTypes
1616
import Haskell.Ide.Engine.MonadFunctions
1717
import Hoogle

0 commit comments

Comments
 (0)