@@ -2,6 +2,7 @@
22-- SPDX-License-Identifier: Apache-2.0
33
44{-# LANGUAGE DuplicateRecordFields #-}
5+{-# LANGUAGE PatternSynonyms #-}
56{-# LANGUAGE CPP #-}
67#include "ghc-api-version.h"
78
@@ -42,6 +43,7 @@ main = defaultMain $ testGroup "HIE"
4243 , diagnosticTests
4344 , codeActionTests
4445 , codeLensesTests
46+ , outlineTests
4547 , findDefinitionAndHoverTests
4648 , pluginTests
4749 , preprocessorTests
@@ -68,7 +70,7 @@ initializeResponseTests = withResource acquire release tests where
6870 , chk "NO goto implementation" _implementationProvider (Just $ GotoOptionsStatic False)
6971 , chk "NO find references" _referencesProvider Nothing
7072 , chk "NO doc highlight" _documentHighlightProvider Nothing
71− , chk "NO doc symbol" _documentSymbolProvider Nothing
73+ , chk " doc symbol" _documentSymbolProvider (Just True)
7274 , chk "NO workspace symbol" _workspaceSymbolProvider Nothing
7375 , chk " code action" _codeActionProvider $ Just $ CodeActionOptionsStatic True
7476 , chk " code lens" _codeLensProvider $ Just $ CodeLensOptions Nothing
@@ -1067,6 +1069,153 @@ completionTests
10671069 , _xdata = Just (Aeson.toJSON (xdata :: [T.Text]))
10681070 }
10691071
1072+outlineTests :: TestTree
1073+outlineTests = testGroup
1074+ "outline"
1075+ [ testSessionWait "type class" $ do
1076+ let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1077+ docId <- openDoc' "A.hs" "haskell" source
1078+ symbols <- getDocumentSymbols docId
1079+ liftIO $ symbols @?= Left
1080+ [ moduleSymbol
1081+ "A"
1082+ (R 0 7 0 8)
1083+ [ classSymbol "A a"
1084+ (R 1 0 1 30)
1085+ [docSymbol' "a" SkMethod (R 1 16 1 30) (R 1 16 1 17)]
1086+ ]
1087+ ]
1088+ , testSessionWait "type class instance " $ do
1089+ let source = T.unlines ["class A a where", "instance A () where"]
1090+ docId <- openDoc' "A.hs" "haskell" source
1091+ symbols <- getDocumentSymbols docId
1092+ liftIO $ symbols @?= Left
1093+ [ classSymbol "A a" (R 0 0 0 15) []
1094+ , docSymbol "A ()" SkInterface (R 1 0 1 19)
1095+ ]
1096+ , testSessionWait "type family" $ do
1097+ let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1098+ docId <- openDoc' "A.hs" "haskell" source
1099+ symbols <- getDocumentSymbols docId
1100+ liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1101+ , testSessionWait "type family instance " $ do
1102+ let source = T.unlines
1103+ [ "{-# language TypeFamilies #-}"
1104+ , "type family A a"
1105+ , "type instance A () = ()"
1106+ ]
1107+ docId <- openDoc' "A.hs" "haskell" source
1108+ symbols <- getDocumentSymbols docId
1109+ liftIO $ symbols @?= Left
1110+ [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
1111+ , docSymbol "A ()" SkInterface (R 2 0 2 23)
1112+ ]
1113+ , testSessionWait "data family" $ do
1114+ let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1115+ docId <- openDoc' "A.hs" "haskell" source
1116+ symbols <- getDocumentSymbols docId
1117+ liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1118+ , testSessionWait "data family instance " $ do
1119+ let source = T.unlines
1120+ [ "{-# language TypeFamilies #-}"
1121+ , "data family A a"
1122+ , "data instance A () = A ()"
1123+ ]
1124+ docId <- openDoc' "A.hs" "haskell" source
1125+ symbols <- getDocumentSymbols docId
1126+ liftIO $ symbols @?= Left
1127+ [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
1128+ , docSymbol "A ()" SkInterface (R 2 0 2 25)
1129+ ]
1130+ , testSessionWait "constant" $ do
1131+ let source = T.unlines ["a = ()"]
1132+ docId <- openDoc' "A.hs" "haskell" source
1133+ symbols <- getDocumentSymbols docId
1134+ liftIO $ symbols @?= Left
1135+ [docSymbol "a" SkFunction (R 0 0 0 6)]
1136+ , testSessionWait "pattern" $ do
1137+ let source = T.unlines ["Just foo = Just 21"]
1138+ docId <- openDoc' "A.hs" "haskell" source
1139+ symbols <- getDocumentSymbols docId
1140+ liftIO $ symbols @?= Left
1141+ [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1142+ , testSessionWait "pattern with type signature" $ do
1143+ let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1144+ docId <- openDoc' "A.hs" "haskell" source
1145+ symbols <- getDocumentSymbols docId
1146+ liftIO $ symbols @?= Left
1147+ [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1148+ , testSessionWait "function" $ do
1149+ let source = T.unlines ["a x = ()"]
1150+ docId <- openDoc' "A.hs" "haskell" source
1151+ symbols <- getDocumentSymbols docId
1152+ liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1153+ , testSessionWait "type synonym" $ do
1154+ let source = T.unlines ["type A = Bool"]
1155+ docId <- openDoc' "A.hs" "haskell" source
1156+ symbols <- getDocumentSymbols docId
1157+ liftIO $ symbols @?= Left
1158+ [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1159+ , testSessionWait "datatype" $ do
1160+ let source = T.unlines ["data A = C"]
1161+ docId <- openDoc' "A.hs" "haskell" source
1162+ symbols <- getDocumentSymbols docId
1163+ liftIO $ symbols @?= Left
1164+ [ docSymbolWithChildren "A"
1165+ SkStruct
1166+ (R 0 0 0 10)
1167+ [docSymbol "C" SkConstructor (R 0 9 0 10)]
1168+ ]
1169+ , testSessionWait "import" $ do
1170+ let source = T.unlines ["import Data.Maybe"]
1171+ docId <- openDoc' "A.hs" "haskell" source
1172+ symbols <- getDocumentSymbols docId
1173+ liftIO $ symbols @?= Left
1174+ [docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)]
1175+ , testSessionWait "foreign import" $ do
1176+ let source = T.unlines
1177+ [ "{-# language ForeignFunctionInterface #-}"
1178+ , "foreign import ccall \"a\" a :: Int"
1179+ ]
1180+ docId <- openDoc' "A.hs" "haskell" source
1181+ symbols <- getDocumentSymbols docId
1182+ liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1183+ , testSessionWait "foreign export" $ do
1184+ let source = T.unlines
1185+ [ "{-# language ForeignFunctionInterface #-}"
1186+ , "foreign export ccall odd :: Int -> Bool"
1187+ ]
1188+ docId <- openDoc' "A.hs" "haskell" source
1189+ symbols <- getDocumentSymbols docId
1190+ liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
1191+ ]
1192+ where
1193+ docSymbol name kind loc =
1194+ DocumentSymbol name Nothing kind Nothing loc loc Nothing
1195+ docSymbol' name kind loc selectionLoc =
1196+ DocumentSymbol name Nothing kind Nothing loc selectionLoc Nothing
1197+ docSymbolD name detail kind loc =
1198+ DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1199+ docSymbolWithChildren name kind loc cc =
1200+ DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)
1201+ moduleSymbol name loc cc = DocumentSymbol name
1202+ Nothing
1203+ SkFile
1204+ Nothing
1205+ (R 0 0 maxBound 0)
1206+ loc
1207+ (Just $ List cc)
1208+ classSymbol name loc cc = DocumentSymbol name
1209+ (Just "class")
1210+ SkClass
1211+ Nothing
1212+ loc
1213+ loc
1214+ (Just $ List cc)
1215+
1216+pattern R :: Int -> Int -> Int -> Int -> Range
1217+pattern R x y x' y' = Range (Position x y) (Position x' y')
1218+
10701219xfail :: TestTree -> String -> TestTree
10711220xfail = flip expectFailBecause
10721221