@@ -339,7 +339,7 @@ codeActionProvider plId docId _ context = do
339
339
importModuleAction
340
340
:: SearchStyle -> ImportDiagnostic -> ModuleName -> SymbolName -> IdeM [J. CodeAction ]
341
341
importModuleAction searchStyle impDiagnostic moduleName symbolTerm =
342
- catMaybes <$> sequenceA codeActions
342
+ catMaybes <$> sequenceA importListActions
343
343
where
344
344
importListActions :: [IdeM (Maybe J. CodeAction )]
345
345
importListActions = case searchStyle of
@@ -353,34 +353,42 @@ codeActionProvider plId docId _ context = do
353
353
-- If the term to import is a simple symbol, such as a function,
354
354
-- import only this function
355
355
Symbol
356
- -> [ mkImportAction moduleName impDiagnostic . Just . Only
356
+ -> [ Just importModuleCodeAction
357
+ , mkImportAction moduleName impDiagnostic . Just . Only
357
358
<$> symName symbolTerm
358
- ]
359
+ ]
359
360
-- Constructors can be imported in two ways, either all
360
361
-- constructors of a type or only a subset.
361
362
-- We can only import a single constructor at a time though.
362
363
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
+ ]
370
377
-- If we are looking for a type, import it as just a symbol
371
378
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
384
392
385
393
-- | Retrieve the function signature of a term such as
386
394
-- >>> signatureOf "take :: Int -> [a] -> [a]"
@@ -391,6 +399,40 @@ codeActionProvider plId docId _ context = do
391
399
typeSig <- S. tailMay parts
392
400
S. headMay typeSig
393
401
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
+
394
436
-- | Retrieve the datatype name of a Constructor.
395
437
--
396
438
-- >>> datatypeName "Null :: Data.Aeson.Internal.Types.Value"
@@ -492,13 +534,13 @@ extractImportableTerm dirtyMsg = do
492
534
extractTerm prefix symTy =
493
535
importMsg
494
536
>>= T. stripPrefix prefix
537
+ >>= Just . Hie. extractTerm' . T. strip
495
538
>>= \ name -> Just (name, Import symTy)
496
539
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
499
542
500
543
extractedTerm = asum
501
544
[ extractTerm " Variable not in scope: " Symbol
502
- , extractType " ‘"
503
- , extractType " `" -- Needed for windows
545
+ , extractType
504
546
, extractTerm " Data constructor not in scope: " Constructor ]
0 commit comments