-
-
Notifications
You must be signed in to change notification settings - Fork 378
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Fix Completion document format #2848
Changes from 4 commits
0fb01e1
5936154
8f9ce65
7b1b262
9175fbe
ac3e4da
68cbc2c
3185091
28fb83b
1a92067
31ac60b
6405c2c
5977d32
016b5b4
e40a39b
5debde8
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 | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -4615,6 +4615,7 @@ completionTests | |||||||||||||||||||||||||||||||||||||||
, testGroup "package" packageCompletionTests | ||||||||||||||||||||||||||||||||||||||||
, testGroup "project" projectCompletionTests | ||||||||||||||||||||||||||||||||||||||||
, testGroup "other" otherCompletionTests | ||||||||||||||||||||||||||||||||||||||||
, testGroup "doc" completionDocTests | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
completionTest :: String -> [T.Text] -> Position -> [(T.Text, CompletionItemKind, T.Text, Bool, Bool, Maybe (List TextEdit))] -> TestTree | ||||||||||||||||||||||||||||||||||||||||
|
@@ -5067,7 +5068,7 @@ packageCompletionTests = | |||||||||||||||||||||||||||||||||||||||
_ <- waitForDiagnostics | ||||||||||||||||||||||||||||||||||||||||
compls <- getCompletions doc (Position 2 12) | ||||||||||||||||||||||||||||||||||||||||
let compls' = | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 10 d | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 3 d | ||||||||||||||||||||||||||||||||||||||||
| CompletionItem {_documentation = Just (CompletionDocMarkup (MarkupContent MkMarkdown d)), _label} | ||||||||||||||||||||||||||||||||||||||||
<- compls | ||||||||||||||||||||||||||||||||||||||||
, _label == "fromList" | ||||||||||||||||||||||||||||||||||||||||
|
@@ -5087,7 +5088,7 @@ packageCompletionTests = | |||||||||||||||||||||||||||||||||||||||
_ <- waitForDiagnostics | ||||||||||||||||||||||||||||||||||||||||
compls <- getCompletions doc (Position 2 7) | ||||||||||||||||||||||||||||||||||||||||
let compls' = | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 10 d | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 3 d | ||||||||||||||||||||||||||||||||||||||||
| CompletionItem {_documentation = Just (CompletionDocMarkup (MarkupContent MkMarkdown d)), _label} | ||||||||||||||||||||||||||||||||||||||||
<- compls | ||||||||||||||||||||||||||||||||||||||||
, _label == "Map" | ||||||||||||||||||||||||||||||||||||||||
|
@@ -5171,7 +5172,7 @@ projectCompletionTests = | |||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
compls <- getCompletions doc (Position 1 10) | ||||||||||||||||||||||||||||||||||||||||
let compls' = | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 10 d | ||||||||||||||||||||||||||||||||||||||||
[T.drop 1 $ T.dropEnd 3 d | ||||||||||||||||||||||||||||||||||||||||
| CompletionItem {_documentation = Just (CompletionDocMarkup (MarkupContent MkMarkdown d)), _label} | ||||||||||||||||||||||||||||||||||||||||
<- compls | ||||||||||||||||||||||||||||||||||||||||
, _label == "anidentifier" | ||||||||||||||||||||||||||||||||||||||||
|
@@ -5230,6 +5231,87 @@ projectCompletionTests = | |||||||||||||||||||||||||||||||||||||||
item ^. L.label @?= "anidentifier" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
completionDocTests :: [TestTree] | ||||||||||||||||||||||||||||||||||||||||
completionDocTests = | ||||||||||||||||||||||||||||||||||||||||
[ testSession "local define" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "foo = ()" | ||||||||||||||||||||||||||||||||||||||||
, "bar = fo" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
let expected = "*Defined at line 2, column 1 in this module*\n" | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 2 8) "foo" (Just $ T.length expected) [expected] | ||||||||||||||||||||||||||||||||||||||||
, testSession "local empty doc" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "foo = ()" | ||||||||||||||||||||||||||||||||||||||||
, "bar = fo" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 2 8) "foo" Nothing ["*Defined at line 2, column 1 in this module*\n"] | ||||||||||||||||||||||||||||||||||||||||
, broken $ testSession "local single line doc without '\\n'" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "-- |docdoc" | ||||||||||||||||||||||||||||||||||||||||
, "foo = ()" | ||||||||||||||||||||||||||||||||||||||||
, "bar = fo" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 3 8) "foo" Nothing ["*Defined at line 3, column 1 in this module*\n* * *\ndocdoc\n"] | ||||||||||||||||||||||||||||||||||||||||
, broken $ testSession "local multi line doc with '\\n'" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "-- | abcabc" | ||||||||||||||||||||||||||||||||||||||||
, "--" | ||||||||||||||||||||||||||||||||||||||||
, "foo = ()" | ||||||||||||||||||||||||||||||||||||||||
, "bar = fo" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 4 8) "foo" Nothing ["*Defined at line 4, column 1 in this module*\n* * *\n abcabc\n"] | ||||||||||||||||||||||||||||||||||||||||
, broken $ testSession "local multi line doc without '\\n'" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "-- | abcabc" | ||||||||||||||||||||||||||||||||||||||||
, "--" | ||||||||||||||||||||||||||||||||||||||||
, "--def" | ||||||||||||||||||||||||||||||||||||||||
, "foo = ()" | ||||||||||||||||||||||||||||||||||||||||
, "bar = fo" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 5 8) "foo" Nothing ["*Defined at line 5, column 1 in this module*\n* * *\n abcabc\n\ndef\n"] | ||||||||||||||||||||||||||||||||||||||||
, testSession "extern empty doc" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "foo = od" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
let expected = "*Imported from 'Prelude'*\n* * *\n[Documentation](file:" | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 1 8) "odd" (Just $ T.length expected) [expected] | ||||||||||||||||||||||||||||||||||||||||
, broken $ testSession "extern single line doc without '\\n'" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "foo = no" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
let expected = "*Imported from 'Prelude'*\n* * *\n\n\nBoolean \"not\"\n* * *\n[Documentation](file:" | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 1 8) "not" (Just $ T.length expected) [expected] | ||||||||||||||||||||||||||||||||||||||||
, broken $ testSession "extern mulit line doc" $ do | ||||||||||||||||||||||||||||||||||||||||
doc <- createDoc "A.hs" "haskell" $ T.unlines | ||||||||||||||||||||||||||||||||||||||||
[ "module A where" | ||||||||||||||||||||||||||||||||||||||||
, "foo = i" | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
let expected = "*Imported from 'Prelude'*\n* * *\n\n\nIdentity function. \n```haskell\nid x = x\n```\n* * *\n[Documentation](file:" | ||||||||||||||||||||||||||||||||||||||||
test doc (Position 1 7) "id" (Just $ T.length expected) [expected] | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
where | ||||||||||||||||||||||||||||||||||||||||
broken = knownBrokenForGhcVersions [GHC90, GHC92] "Completion doc doesn't support ghc9" | ||||||||||||||||||||||||||||||||||||||||
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. :o do we have a ticket for this? 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. No, I just found this haskell-language-server/ghcide/src/Development/IDE/Spans/Documentation.hs Lines 104 to 122 in da0379b
, ghc9.0 test fails on my machine, so I marked it as broken 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. Note that this code path is only used to get documentation for local completions (from the same module). I dont' think that it is being used in your test. Are you in Mac OS? Some ghc 9.x distributions are shipping without interface haddocks |
||||||||||||||||||||||||||||||||||||||||
test doc pos label mn expected = do | ||||||||||||||||||||||||||||||||||||||||
_ <- waitForDiagnostics | ||||||||||||||||||||||||||||||||||||||||
compls <- getCompletions doc pos | ||||||||||||||||||||||||||||||||||||||||
let compls' = [ | ||||||||||||||||||||||||||||||||||||||||
-- We ignore doc uris since it points to the local path which determined by specific machines | ||||||||||||||||||||||||||||||||||||||||
case mn of | ||||||||||||||||||||||||||||||||||||||||
Nothing -> txt | ||||||||||||||||||||||||||||||||||||||||
Just n -> T.take n txt | ||||||||||||||||||||||||||||||||||||||||
| CompletionItem {_documentation = Just (CompletionDocMarkup (MarkupContent MkMarkdown txt)), ..} <- compls | ||||||||||||||||||||||||||||||||||||||||
, _label == label | ||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||
liftIO $ compls' @?= expected | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
highlightTests :: TestTree | ||||||||||||||||||||||||||||||||||||||||
highlightTests = testGroup "highlight" | ||||||||||||||||||||||||||||||||||||||||
[ testSessionWait "value" $ do | ||||||||||||||||||||||||||||||||||||||||
|
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.
This logic is a bit confusing, because we have a collection of lines, some of them ending with newlines. The old comment is correct, we do need two newlines to get a paragraph break in markdown, but that works out here because
T.unlines [ "foo\n", "bar" ]
will end up with two newlines. Confusing.In fact, should the lines ever have trailing newlines? That seems odd.
I wonder if it would be simpler if this function just dealt with a single
Text
representing the whole piece of doc. AFAICT it would be fine ifspanDocToMarkdown
returned just aText
.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.
\n
is enough to get a section separator(xxx\n***\nxxx)\n
, so the separator can rendered correctly.haskell-language-server/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs
Lines 211 to 213 in da0379b
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.
Unfortunately,
spanDocToMarkdown
is both used in completion and hover, and they have different UI(completion uses section separator, hover uses new line), so we can't return aText
inspanDocToMarkdown
. Furthermore, the final documentation is the combination ofDefined in
, haddock, and source link.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.
Does it return a list of sections then? Please add a Haddock comment clarifying what
spanDocToMarkdown
returnsThere 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.
Done