@@ -151,10 +151,17 @@ descriptor recorder plId =
151
151
codeActionProvider :: PluginMethodHandler IdeState 'Method_TextDocumentCodeAction
152
152
codeActionProvider ideState _ (CodeActionParams _ _ docId range _) = do
153
153
nfp <- getNormalizedFilePathE (docId ^. L. uri)
154
- CRR {crCodeActions, enabledExtensions} <- runActionE " ExplicitFields.CollectRecords" ideState $ useE CollectRecords nfp
154
+ CRR {crCodeActions, crCodeActionResolve, enabledExtensions} <- runActionE " ExplicitFields.CollectRecords" ideState $ useE CollectRecords nfp
155
155
-- All we need to build a code action is the list of extensions, and a int to
156
156
-- allow us to resolve it later.
157
- let actions = map (mkCodeAction enabledExtensions) (RangeMap. filterByRange range crCodeActions)
157
+ let recordUids = [ uid
158
+ | uid <- RangeMap. filterByRange range crCodeActions
159
+ , Just record <- [IntMap. lookup uid crCodeActionResolve]
160
+ -- Only fully saturated constructor applications can be
161
+ -- converted to the record syntax through the code action
162
+ , isConvertible record
163
+ ]
164
+ let actions = map (mkCodeAction enabledExtensions) recordUids
158
165
pure $ InL actions
159
166
where
160
167
mkCodeAction :: [Extension ] -> Int -> Command |? CodeAction
@@ -169,6 +176,11 @@ codeActionProvider ideState _ (CodeActionParams _ _ docId range _) = do
169
176
, _data_ = Just $ toJSON uid
170
177
}
171
178
179
+ isConvertible :: RecordInfo -> Bool
180
+ isConvertible = \ case
181
+ RecordInfoApp _ (RecordAppExpr Unsaturated _ _) -> False
182
+ _ -> True
183
+
172
184
codeActionResolveProvider :: ResolveFunction IdeState Int 'Method_CodeActionResolve
173
185
codeActionResolveProvider ideState pId ca uri uid = do
174
186
nfp <- getNormalizedFilePathE uri
@@ -253,7 +265,7 @@ inlayHintPosRecProvider _ state _pId InlayHintParams {_textDocument = TextDocume
253
265
pure $ InL (concatMap (mkInlayHints nameMap pm) records)
254
266
where
255
267
mkInlayHints :: UniqFM Name [Name ] -> PositionMapping -> RecordInfo -> [InlayHint ]
256
- mkInlayHints nameMap pm record@ (RecordInfoApp _ (RecordAppExpr _ fla)) =
268
+ mkInlayHints nameMap pm record@ (RecordInfoApp _ (RecordAppExpr _ _ fla)) =
257
269
let textEdits = renderRecordInfoAsTextEdit nameMap record
258
270
in mapMaybe (mkInlayHint textEdits pm) fla
259
271
mkInlayHints _ _ _ = []
@@ -379,7 +391,16 @@ instance Show CollectNamesResult where
379
391
380
392
type instance RuleResult CollectNames = CollectNamesResult
381
393
382
- data RecordAppExpr = RecordAppExpr (LHsExpr GhcTc ) [(Located FieldLabel , HsExpr GhcTc )]
394
+ data Saturated = Saturated | Unsaturated
395
+ deriving (Generic )
396
+
397
+ instance NFData Saturated
398
+
399
+ data RecordAppExpr
400
+ = RecordAppExpr
401
+ Saturated -- ^ Is the DataCon application fully saturated or partially applied?
402
+ (LHsExpr GhcTc )
403
+ [(Located FieldLabel , HsExpr GhcTc )]
383
404
deriving (Generic )
384
405
385
406
data RecordInfo
@@ -391,7 +412,7 @@ data RecordInfo
391
412
instance Pretty RecordInfo where
392
413
pretty (RecordInfoPat ss p) = pretty (printOutputable ss) <> " :" <+> pretty (printOutputable p)
393
414
pretty (RecordInfoCon ss e) = pretty (printOutputable ss) <> " :" <+> pretty (printOutputable e)
394
- pretty (RecordInfoApp ss (RecordAppExpr _ fla))
415
+ pretty (RecordInfoApp ss (RecordAppExpr _ _ fla))
395
416
= pretty (printOutputable ss) <> " :" <+> hsep (map (pretty . printOutputable) fla)
396
417
397
418
recordInfoToRange :: RecordInfo -> Range
@@ -536,7 +557,7 @@ showRecordConFlds (RecordCon _ _ flds) =
536
557
showRecordConFlds _ = Nothing
537
558
538
559
showRecordApp :: RecordAppExpr -> Maybe Text
539
- showRecordApp (RecordAppExpr recConstr fla)
560
+ showRecordApp (RecordAppExpr _ recConstr fla)
540
561
= Just $ printOutputable recConstr <> " { "
541
562
<> T. intercalate " , " (showFieldWithArg <$> fla)
542
563
<> " }"
@@ -588,8 +609,14 @@ getRecCons expr@(unLoc -> app@(HsApp _ _ _)) =
588
609
589
610
getFields :: HsExpr GhcTc -> [LHsExpr GhcTc ] -> Maybe RecordAppExpr
590
611
getFields (HsApp _ constr@ (unLoc -> expr) arg) args
591
- | not (null fls)
592
- = Just (RecordAppExpr constr labelWithArgs)
612
+ | not (null fls) = Just $
613
+ -- Code action is only valid if the constructor application is fully
614
+ -- saturated, but we still want to display the inlay hints for partially
615
+ -- applied constructors
616
+ RecordAppExpr
617
+ (if length fls <= length args + 1 then Saturated else Unsaturated )
618
+ constr
619
+ labelWithArgs
593
620
where fls = getExprFields expr
594
621
labelWithArgs = zipWith mkLabelWithArg fls (arg : args)
595
622
mkLabelWithArg label arg = (L (getLoc arg) label, unLoc arg)
0 commit comments