Repository navigation
Add code action to remove redundant qualified in imports #5145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
1b3c6ab
7c17616
b7d3433
a3d1ba7
0339074
5b94fb0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,6 +177,7 @@ iePluginDescriptor recorder plId = | |
| let old = | ||
| mkGhcideCAsPlugin | ||
| [ wrap suggestModuleTypo | ||
| , wrap suggestRemoveDuplicateQualified | ||
| , wrap suggestFixConstructorImport | ||
| , wrap suggestExtendImport | ||
| , wrap suggestImportDisambiguation | ||
|
|
@@ -987,6 +988,67 @@ suggestModuleTypo Diagnostic{_range=_range,..} | |
| [modul, "(from", _] -> Just modul | ||
| _ -> Nothing | ||
|
|
||
| suggestRemoveDuplicateQualified :: Maybe DynFlags -> Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])] | ||
| suggestRemoveDuplicateQualified mbDf contents' Diagnostic{_range=_range, _message} | ||
| | "Multiple occurrences of 'qualified'" `T.isInfixOf` _message | ||
| , Just contents <- contents' | ||
| , Just edit <- redundantQualifiedEdit contents | ||
| = [("Remove redundant 'qualified'", [edit])] | ||
| | otherwise = [] | ||
| where | ||
| usePost = case mbDf of | ||
| Just df -> xopt Lang.ImportQualifiedPost df | ||
| -- The module could not be parsed and no DynFlags were available, so | ||
| -- fall back to the LANGUAGE/OPTIONS_GHC pragmas in the file itself. | ||
| Nothing -> maybe False importQualifiedPostFromPragmas contents' | ||
|
Comment on lines
+1001
to
+1003
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am in all honesty pretty much against this ad-hoc parsing of line pragmas. If there are no |
||
| redundantQualifiedEdit contents = do | ||
| let Position startLine _ = _start _range | ||
| line <- listToMaybe $ drop (fromIntegral startLine) $ T.lines contents | ||
| (preQual, postQual) <- case qualifiedOccurrences line of | ||
| a : b : _ -> Just (a, b) | ||
| _ -> Nothing | ||
| let (colStart, colEnd) | ||
| | usePost = preQual | ||
| | otherwise = postQual | ||
| baseRange = Range (Position startLine (fromIntegral colStart)) (Position startLine (fromIntegral colEnd)) | ||
| trailing = T.takeWhile isSpace (T.drop colEnd line) | ||
| leading = T.takeWhileEnd isSpace (T.take colStart line) | ||
| editRange | ||
| | usePost = baseRange { _end = Position startLine (fromIntegral (colEnd + T.length trailing)) } | ||
| | otherwise = baseRange { _start = Position startLine (fromIntegral (colStart - T.length leading)) } | ||
| pure $ TextEdit editRange "" | ||
|
Comment on lines
+1004
to
+1019
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might need a comment what this is trying to do. Seems very complicated. |
||
| importQualifiedPostFromPragmas :: T.Text -> Bool | ||
| importQualifiedPostFromPragmas contents = | ||
|
Comment on lines
+1020
to
+1021
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should implement this fall back behaviour, I think it is fine to not offer anything if we can't find the DynFlags. This ad-hoc parsing usually just leads to more tears down the line. |
||
| case enabledStates of | ||
| [] -> False | ||
| states -> last states | ||
| where | ||
| enabledStates = | ||
| [ token /= "NoImportQualifiedPost" | ||
| | line <- T.lines contents | ||
| , "{-# LANGUAGE" `T.isInfixOf` line || "{-# OPTIONS_GHC" `T.isInfixOf` line | ||
| , token <- map T.unpack $ extensionsIn line | ||
| , token == "ImportQualifiedPost" || token == "NoImportQualifiedPost" | ||
| ] | ||
| extensionsIn = | ||
| T.split (\c -> not (isAlphaNum c || c == '_' || c == '-')) . T.replace "-X" "" | ||
|
|
||
| qualifiedOccurrences :: T.Text -> [(Int, Int)] | ||
| qualifiedOccurrences = go 0 | ||
| where | ||
| kw = "qualified" | ||
| kwLen = T.length kw | ||
| go off t = case T.breakOn kw t of | ||
| (_, rest) | T.null rest -> [] | ||
| (pre, rest) -> | ||
| let start = off + T.length pre | ||
| after = T.drop kwLen rest | ||
| boundedBefore = T.null pre || not (isIdentChar (T.last pre)) | ||
| boundedAfter = T.null after || not (isIdentChar (T.head after)) | ||
| found = if boundedBefore && boundedAfter then ((start, start + kwLen) :) else id | ||
| in found (go (start + kwLen) after) | ||
| isIdentChar c = isAlphaNum c || c == '_' | ||
|
|
||
| suggestExtendImport :: ExportsMap -> ParsedSource -> Diagnostic -> [(T.Text, CodeActionKind, CodeActionPreferred, Rewrite)] | ||
| suggestExtendImport exportsMap (L _ HsModule {hsmodImports}) Diagnostic{_range=_range,..} | ||
| | Just [binding, mod, srcspan] <- | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use the structured diagnostic in
FileDiagnosticinstead of parsing the message?Also, the diagnostic has a source range, isn't that sufficient to calculate the edit?