Skip to content

Commit 6f70bf6

Browse files
committed
Abbreviate explicit import code lenses
The tests currently don't check anything about the titles, I'm unsure whether it's worth writing a test just for this. Fixes #2765.
1 parent 82c1535 commit 6f70bf6

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import qualified Data.Map.Strict as Map
2828
import Data.Maybe (catMaybes, fromMaybe,
2929
isJust)
3030
import qualified Data.Text as T
31+
import Data.String (fromString)
3132
import Development.IDE hiding (pluginHandlers,
3233
pluginRules)
3334
import Development.IDE.Core.PositionMapping
@@ -269,12 +270,41 @@ mkExplicitEdit pred posMapping (L (locA -> src) imp) explicit
269270
| otherwise =
270271
Nothing
271272

273+
-- This number is somewhat arbitrarily chosen. Ideally the protocol would tell us these things,
274+
-- but at the moment I don't believe we know it.
275+
-- 80 columns is traditional, but Haskellers tend to use longer lines (citation needed) and it's
276+
-- probably not too bad if the lens is a *bit* longer than normal lines.
277+
maxColumns :: Int
278+
maxColumns = 120
279+
272280
-- | Given an import declaration, generate a code lens unless it has an
273281
-- explicit import list or it's qualified
274282
generateLens :: PluginId -> Uri -> TextEdit -> IO (Maybe CodeLens)
275283
generateLens pId uri importEdit@TextEdit {_range, _newText} = do
276-
-- The title of the command is just the minimal explicit import decl
277-
let title = _newText
284+
let
285+
-- The title of the command is ideally the minimal explicit import decl, but
286+
-- we don't want to create a really massive code lens (and the decl can be extremely large!).
287+
-- So we abbreviate it to fit a max column size, and indicate how many more items are in the list
288+
-- after the abbreviation
289+
290+
-- For starters, we only want one line in the title
291+
oneLineText = T.unwords $ T.lines _newText
292+
-- Now, split at the max columns, leaving space for the suffix text we're going to add
293+
-- (conservatively assuming we won't need to print a number larger than 100)
294+
(prefix, suffix) = T.splitAt (maxColumns - (T.length (suffixText 100))) oneLineText
295+
-- We also want to truncate the last item so we get a "clean" break, rather than half way through
296+
-- something. The conditional here is just because 'breakOnEnd' doesn't give us quite the right thing
297+
-- if there are actually no commas.
298+
(actualPrefix, extraSuffix) = if T.count "," prefix > 0 then T.breakOnEnd "," prefix else (prefix, "")
299+
actualSuffix = extraSuffix <> suffix
300+
301+
-- The number of additional items is the number of commas+1
302+
numAdditionalItems = T.count "," actualSuffix + 1
303+
-- We want to make text like this: import Foo (AImport, BImport, ... (30 more items))
304+
-- Trailing paren is to match the opening paren from the import list
305+
suffixText n = " ... (" <> fromString (show n) <> " more items) )"
306+
title = if T.length oneLineText <= maxColumns then oneLineText else actualPrefix <> suffixText numAdditionalItems
307+
278308
-- the code lens has no extra data
279309
_xdata = Nothing
280310
-- an edit that replaces the whole declaration with the explicit one

plugins/hls-explicit-imports-plugin/test/Main.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ explicitImportsPlugin = ExplicitImports.descriptor mempty "explicitImports"
2222
main :: IO ()
2323
main = defaultTestRunner $
2424
testGroup
25-
"Refine Imports"
25+
"Make imports explicit"
2626
[ codeActionGoldenTest "UsualCase" 3 0
2727
, codeLensGoldenTest "UsualCase" 0
2828
, testCase "No CodeAction when exported" $

0 commit comments

Comments
 (0)