Skip to content

Commit 3746332

Browse files
committed
Added documentation
1 parent 25be42a commit 3746332

File tree

1 file changed

+36
-23
lines changed

1 file changed

+36
-23
lines changed

plugins/hls-overloaded-record-dot-plugin/src/Ide/Plugin/OverloadedRecordDot.hs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,16 @@ instance Show CollectRecordSelectorsResult where
107107

108108
type instance RuleResult CollectRecordSelectors = CollectRecordSelectorsResult
109109

110-
111-
data RecordSelectorExpr = RecordSelectorExpr { location :: Range,
112-
selectorExpr :: LHsExpr (GhcPass 'Renamed),
113-
recordExpr :: LHsExpr (GhcPass 'Renamed) }
110+
-- | Where we store our collected record selectors
111+
data RecordSelectorExpr =
112+
RecordSelectorExpr { -- | the location of the matched record selector, and record
113+
location :: Range,
114+
-- | the record selector, this is found in front of recordExpr, but
115+
-- | get's placed after it when converted into record dot syntax
116+
selectorExpr :: LHsExpr (GhcPass 'Renamed),
117+
-- | the record. Whereas it can be many different structures, the only
118+
-- | requirement is that it evaluates to a record in the end
119+
recordExpr :: LHsExpr (GhcPass 'Renamed) }
114120

115121
instance Pretty RecordSelectorExpr where
116122
pretty (RecordSelectorExpr l rs se) = pretty (printOutputable rs) <> ":" <+> pretty (printOutputable se)
@@ -133,10 +139,14 @@ codeActionProvider ideState pId (CodeActionParams _ _ caDocId caRange _) = plugi
133139
pragmaEdit = if OverloadedRecordDot `elem` exts
134140
then Nothing
135141
else Just $ insertNewPragma pragma OverloadedRecordDot
136-
edits crs = maybeToList (convertRecordSelectors crs) <> maybeToList pragmaEdit
142+
edits crs = convertRecordSelectors crs : maybeToList pragmaEdit
137143
changes crs = Just $ HashMap.singleton (fromNormalizedUri (normalizedFilePathToUri nfp)) (List (edits crs))
138144
mkCodeAction crs = InR CodeAction
139-
{ _title = mkCodeActionTitle exts crs
145+
{ -- we pass the record selector to the title function, so that it con be used to generate the file
146+
-- the advantage of that is that the user can easily distinguish between the the different code actions
147+
-- with nested record selectors, the disadvantage is we need to print out the name of the record selector
148+
-- which may decrease performance
149+
_title = mkCodeActionTitle exts crs
140150
, _kind = Just CodeActionRefactorRewrite
141151
, _diagnostics = Nothing
142152
, _isPreferred = Nothing
@@ -162,42 +172,45 @@ collectRecSelsRule recorder = define (cmapWithPrio LogShake recorder) $ \Collect
162172
use TypeCheck nfp >>= \case
163173
Nothing -> pure ([], Nothing)
164174
Just tmr -> do
165-
let exts = getEnabledExtensions tmr
166-
recSels = getRecordSelectors tmr
175+
let exts = getEnabledExtensions tmr -- We need the extensions to check whether we need to add OverloadedRecordDot
176+
recSels = getRecordSelectors tmr -- And we need the record selectors for obvious reasons
167177
logWith recorder Debug (LogCollectedRecordSelectors recSels)
168178
let crsMap :: RangeMap RecordSelectorExpr
169-
crsMap = RangeMap.fromList location recSels
179+
crsMap = RangeMap.fromList location recSels -- We need the rangeMap to be able to filter by range later
170180
pure ([], CRSR <$> Just crsMap <*> Just exts)
171181
where
172182
getEnabledExtensions :: TcModuleResult -> [Extension]
173183
getEnabledExtensions = getExtensions . tmrParsed
184+
getRecordSelectors :: TcModuleResult -> [RecordSelectorExpr]
185+
getRecordSelectors (tmrRenamed -> (hs_valds -> valBinds,_,_,_)) =
186+
collectRecordSelectors valBinds
174187

175-
getRecordSelectors :: TcModuleResult -> [RecordSelectorExpr]
176-
getRecordSelectors (tmrRenamed -> (hs_valds -> valBinds,_,_,_)) =
177-
collectRecordSelectors valBinds
178-
179-
convertRecordSelectors :: RecordSelectorExpr -> Maybe TextEdit
180-
convertRecordSelectors (RecordSelectorExpr l se re) = TextEdit l <$> convertRecSel se re
188+
convertRecordSelectors :: RecordSelectorExpr -> TextEdit
189+
convertRecordSelectors (RecordSelectorExpr l se re) = TextEdit l $ convertRecSel se re
181190

182-
convertRecSel :: Outputable (LHsExpr (GhcPass 'Renamed)) => LHsExpr (GhcPass 'Renamed) -> LHsExpr (GhcPass 'Renamed) -> Maybe Text
183-
convertRecSel se re =
184-
Just $ printOutputable (parenthesizeHsExpr appPrec re) <> "." <> printOutputable se
191+
-- | Converts a record selector expression into record dot syntax,
192+
-- | currently we are using printOutputable to do it. We are also letting GHC
193+
-- | decide when to parenthesizing the record expression
194+
convertRecSel :: Outputable (LHsExpr (GhcPass 'Renamed)) => LHsExpr (GhcPass 'Renamed) -> LHsExpr (GhcPass 'Renamed) -> Text
195+
convertRecSel se re = printOutputable (parenthesizeHsExpr appPrec re) <> "." <> printOutputable se
185196

186197
-- It's important that we use everthingBut here, because if we used everything we would
187-
-- get duplicates for every case that occures inside a HsExpanded expression.
198+
-- get duplicates for every case that occurs inside a HsExpanded expression.
188199
collectRecordSelectors :: GenericQ [RecordSelectorExpr]
189200
collectRecordSelectors = everythingBut (<>) (([], False) `mkQ` getRecSels)
190201

202+
-- | We want to return a list here, because on the occasion that we encounter a HsExpanded expression,
203+
-- | we want to return all the results from recursing on one branch, which could be multiple matches
191204
getRecSels :: LHsExpr (GhcPass 'Renamed) -> ([RecordSelectorExpr], Bool)
192-
-- When we stumble upon an occurance of HsExpanded, we only want to follow one branch
193-
-- we do this here, by explicitly returning occurances from traversing the original branch,
205+
-- When we stumble upon an occurrence of HsExpanded, we only want to follow one branch
206+
-- we do this here, by explicitly returning occurrences from traversing the original branch,
194207
-- and returning True, which keeps syb from implicitly continuing to traverse.
195208
getRecSels (unLoc -> XExpr (HsExpanded a _)) = (collectRecordSelectors a, True)
196209
#if __GLASGOW_HASKELL__ >= 903
197-
-- applied record selection: "field record" or "field (record)" or "field field.record"
210+
-- applied record selection: "selector record" or "selector (record)" or "selector selector2.record2"
198211
getRecSels e@(unLoc -> HsApp _ se@(unLoc -> HsRecSel _ _) re) =
199212
( [ RecordSelectorExpr (realSrcSpanToRange realSpan') se re | RealSrcSpan realSpan' _ <- [ getLoc e ]], False)
200-
-- Record selection where the field is being applied with the "$" operator: "field $ record"
213+
-- Record selection where the field is being applied with the "$" operator: "selector $ record"
201214
getRecSels e@(unLoc -> OpApp _ se@(unLoc -> HsRecSel _ _) (unLoc -> HsVar _ (unLoc -> d)) re)
202215
| d == dollarName = ( [ RecordSelectorExpr (realSrcSpanToRange realSpan') se re | RealSrcSpan realSpan' _ <- [ getLoc e ]], False)
203216
#else

0 commit comments

Comments
 (0)