|
| 1 | +{-# LANGUAGE OverloadedStrings #-} |
| 2 | +{-# LANGUAGE TypeFamilies #-} |
1 | 3 |
|
2 | 4 | module OutlineTests (tests) where
|
3 | 5 |
|
| 6 | +import Config |
4 | 7 | import Control.Monad.IO.Class (liftIO)
|
| 8 | +import Data.Text (Text) |
5 | 9 | import qualified Data.Text as T
|
6 | 10 | import Language.LSP.Protocol.Types hiding (SemanticTokenAbsolute (..),
|
7 | 11 | SemanticTokenRelative (..),
|
8 | 12 | SemanticTokensEdit (..), mkRange)
|
9 | 13 | import Language.LSP.Test
|
| 14 | +import Test.Hls.FileSystem (file, text) |
10 | 15 | import Test.Tasty
|
11 | 16 | import Test.Tasty.HUnit
|
12 |
| -import TestUtils |
13 | 17 |
|
14 |
| -tests :: TestTree |
15 |
| -tests = testGroup |
16 |
| - "outline" |
17 |
| - [ testSessionWait "type class" $ do |
18 |
| - let source = T.unlines ["module A where", "class A a where a :: a -> Bool"] |
19 |
| - docId <- createDoc "A.hs" "haskell" source |
20 |
| - symbols <- getDocumentSymbols docId |
21 |
| - liftIO $ symbols @?= Right |
22 |
| - [ moduleSymbol |
23 |
| - "A" |
24 |
| - (R 0 7 0 8) |
25 |
| - [ classSymbol "A a" |
26 |
| - (R 1 0 1 30) |
27 |
| - [docSymbol' "a" SymbolKind_Method (R 1 16 1 30) (R 1 16 1 17)] |
28 |
| - ] |
29 |
| - ] |
30 |
| - , testSessionWait "type class instance " $ do |
31 |
| - let source = T.unlines ["class A a where", "instance A () where"] |
32 |
| - docId <- createDoc "A.hs" "haskell" source |
33 |
| - symbols <- getDocumentSymbols docId |
34 |
| - liftIO $ symbols @?= Right |
35 |
| - [ classSymbol "A a" (R 0 0 0 15) [] |
36 |
| - , docSymbol "A ()" SymbolKind_Interface (R 1 0 1 19) |
37 |
| - ] |
38 |
| - , testSessionWait "type family" $ do |
39 |
| - let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"] |
40 |
| - docId <- createDoc "A.hs" "haskell" source |
41 |
| - symbols <- getDocumentSymbols docId |
42 |
| - liftIO $ symbols @?= Right [docSymbolD "A" "type family" SymbolKind_Function (R 1 0 1 13)] |
43 |
| - , testSessionWait "type family instance " $ do |
44 |
| - let source = T.unlines |
45 |
| - [ "{-# language TypeFamilies #-}" |
46 |
| - , "type family A a" |
47 |
| - , "type instance A () = ()" |
48 |
| - ] |
49 |
| - docId <- createDoc "A.hs" "haskell" source |
50 |
| - symbols <- getDocumentSymbols docId |
51 |
| - liftIO $ symbols @?= Right |
52 |
| - [ docSymbolD "A a" "type family" SymbolKind_Function (R 1 0 1 15) |
53 |
| - , docSymbol "A ()" SymbolKind_Interface (R 2 0 2 23) |
54 |
| - ] |
55 |
| - , testSessionWait "data family" $ do |
56 |
| - let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"] |
57 |
| - docId <- createDoc "A.hs" "haskell" source |
58 |
| - symbols <- getDocumentSymbols docId |
59 |
| - liftIO $ symbols @?= Right [docSymbolD "A" "data family" SymbolKind_Function (R 1 0 1 11)] |
60 |
| - , testSessionWait "data family instance " $ do |
61 |
| - let source = T.unlines |
62 |
| - [ "{-# language TypeFamilies #-}" |
63 |
| - , "data family A a" |
64 |
| - , "data instance A () = A ()" |
65 |
| - ] |
66 |
| - docId <- createDoc "A.hs" "haskell" source |
67 |
| - symbols <- getDocumentSymbols docId |
68 |
| - liftIO $ symbols @?= Right |
69 |
| - [ docSymbolD "A a" "data family" SymbolKind_Function (R 1 0 1 11) |
70 |
| - , docSymbol "A ()" SymbolKind_Interface (R 2 0 2 25) |
71 |
| - ] |
72 |
| - , testSessionWait "constant" $ do |
73 |
| - let source = T.unlines ["a = ()"] |
74 |
| - docId <- createDoc "A.hs" "haskell" source |
75 |
| - symbols <- getDocumentSymbols docId |
76 |
| - liftIO $ symbols @?= Right |
77 |
| - [docSymbol "a" SymbolKind_Function (R 0 0 0 6)] |
78 |
| - , testSessionWait "pattern" $ do |
79 |
| - let source = T.unlines ["Just foo = Just 21"] |
80 |
| - docId <- createDoc "A.hs" "haskell" source |
81 |
| - symbols <- getDocumentSymbols docId |
82 |
| - liftIO $ symbols @?= Right |
83 |
| - [docSymbol "Just foo" SymbolKind_Function (R 0 0 0 18)] |
84 |
| - , testSessionWait "pattern with type signature" $ do |
85 |
| - let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"] |
86 |
| - docId <- createDoc "A.hs" "haskell" source |
87 |
| - symbols <- getDocumentSymbols docId |
88 |
| - liftIO $ symbols @?= Right |
89 |
| - [docSymbol "a :: ()" SymbolKind_Function (R 1 0 1 12)] |
90 |
| - , testSessionWait "function" $ do |
91 |
| - let source = T.unlines ["a _x = ()"] |
92 |
| - docId <- createDoc "A.hs" "haskell" source |
93 |
| - symbols <- getDocumentSymbols docId |
94 |
| - liftIO $ symbols @?= Right [docSymbol "a" SymbolKind_Function (R 0 0 0 9)] |
95 |
| - , testSessionWait "type synonym" $ do |
96 |
| - let source = T.unlines ["type A = Bool"] |
97 |
| - docId <- createDoc "A.hs" "haskell" source |
98 |
| - symbols <- getDocumentSymbols docId |
99 |
| - liftIO $ symbols @?= Right |
100 |
| - [docSymbol' "A" SymbolKind_TypeParameter (R 0 0 0 13) (R 0 5 0 6)] |
101 |
| - , testSessionWait "datatype" $ do |
102 |
| - let source = T.unlines ["data A = C"] |
103 |
| - docId <- createDoc "A.hs" "haskell" source |
| 18 | +testSymbols :: (HasCallStack) => TestName -> FilePath -> [Text] -> [DocumentSymbol] -> TestTree |
| 19 | +testSymbols testName path content expectedSymbols = |
| 20 | + testCase testName $ runWithDummyPlugin (mkIdeTestFs [file path (text $ T.unlines content)]) $ do |
| 21 | + docId <- openDoc path "haskell" |
104 | 22 | symbols <- getDocumentSymbols docId
|
105 |
| - liftIO $ symbols @?= Right |
106 |
| - [ docSymbolWithChildren "A" |
107 |
| - SymbolKind_Struct |
108 |
| - (R 0 0 0 10) |
109 |
| - [docSymbol "C" SymbolKind_Constructor (R 0 9 0 10)] |
110 |
| - ] |
111 |
| - , testSessionWait "record fields" $ do |
112 |
| - let source = T.unlines ["data A = B {", " x :: Int", " , y :: Int}"] |
113 |
| - docId <- createDoc "A.hs" "haskell" source |
114 |
| - symbols <- getDocumentSymbols docId |
115 |
| - liftIO $ symbols @?= Right |
116 |
| - [ docSymbolWithChildren "A" SymbolKind_Struct (R 0 0 2 13) |
117 |
| - [ docSymbolWithChildren' "B" SymbolKind_Constructor (R 0 9 2 13) (R 0 9 0 10) |
118 |
| - [ docSymbol "x" SymbolKind_Field (R 1 2 1 3) |
119 |
| - , docSymbol "y" SymbolKind_Field (R 2 4 2 5) |
| 23 | + liftIO $ symbols @?= Right expectedSymbols |
| 24 | + |
| 25 | +testSymbolsA :: (HasCallStack) => TestName -> [Text] -> [DocumentSymbol] -> TestTree |
| 26 | +testSymbolsA testName content expectedSymbols = |
| 27 | + testSymbols testName "A.hs" content expectedSymbols |
| 28 | + |
| 29 | +tests :: TestTree |
| 30 | +tests = |
| 31 | + testGroup |
| 32 | + "outline" |
| 33 | + [ testSymbolsA |
| 34 | + "type class:" |
| 35 | + ["module A where", "class A a where a :: a -> Bool"] |
| 36 | + [ moduleSymbol |
| 37 | + "A" |
| 38 | + (R 0 7 0 8) |
| 39 | + [ classSymbol |
| 40 | + "A a" |
| 41 | + (R 1 0 1 30) |
| 42 | + [docSymbol' "a" SymbolKind_Method (R 1 16 1 30) (R 1 16 1 17)] |
120 | 43 | ]
|
121 |
| - ] |
122 |
| - ] |
123 |
| - , testSessionWait "import" $ do |
124 |
| - let source = T.unlines ["import Data.Maybe ()"] |
125 |
| - docId <- createDoc "A.hs" "haskell" source |
126 |
| - symbols <- getDocumentSymbols docId |
127 |
| - liftIO $ symbols @?= Right |
128 |
| - [docSymbolWithChildren "imports" |
129 |
| - SymbolKind_Module |
130 |
| - (R 0 0 0 20) |
131 |
| - [ docSymbol "import Data.Maybe" SymbolKind_Module (R 0 0 0 20) |
132 |
| - ] |
133 |
| - ] |
134 |
| - , testSessionWait "multiple import" $ do |
135 |
| - let source = T.unlines ["", "import Data.Maybe ()", "", "import Control.Exception ()", ""] |
136 |
| - docId <- createDoc "A.hs" "haskell" source |
137 |
| - symbols <- getDocumentSymbols docId |
138 |
| - liftIO $ symbols @?= Right |
139 |
| - [docSymbolWithChildren "imports" |
140 |
| - SymbolKind_Module |
141 |
| - (R 1 0 3 27) |
142 |
| - [ docSymbol "import Data.Maybe" SymbolKind_Module (R 1 0 1 20) |
143 |
| - , docSymbol "import Control.Exception" SymbolKind_Module (R 3 0 3 27) |
144 |
| - ] |
145 |
| - ] |
146 |
| - , testSessionWait "foreign import" $ do |
147 |
| - let source = T.unlines |
148 |
| - [ "{-# language ForeignFunctionInterface #-}" |
149 |
| - , "foreign import ccall \"a\" a :: Int" |
150 |
| - ] |
151 |
| - docId <- createDoc "A.hs" "haskell" source |
152 |
| - symbols <- getDocumentSymbols docId |
153 |
| - liftIO $ symbols @?= Right [docSymbolD "a" "import" SymbolKind_Object (R 1 0 1 33)] |
154 |
| - , testSessionWait "foreign export" $ do |
155 |
| - let source = T.unlines |
156 |
| - [ "{-# language ForeignFunctionInterface #-}" |
157 |
| - , "foreign export ccall odd :: Int -> Bool" |
158 |
| - ] |
159 |
| - docId <- createDoc "A.hs" "haskell" source |
160 |
| - symbols <- getDocumentSymbols docId |
161 |
| - liftIO $ symbols @?= Right [docSymbolD "odd" "export" SymbolKind_Object (R 1 0 1 39)] |
162 |
| - ] |
163 |
| - where |
164 |
| - docSymbol name kind loc = |
165 |
| - DocumentSymbol name Nothing kind Nothing Nothing loc loc Nothing |
166 |
| - docSymbol' name kind loc selectionLoc = |
167 |
| - DocumentSymbol name Nothing kind Nothing Nothing loc selectionLoc Nothing |
168 |
| - docSymbolD name detail kind loc = |
169 |
| - DocumentSymbol name (Just detail) kind Nothing Nothing loc loc Nothing |
170 |
| - docSymbolWithChildren name kind loc cc = |
171 |
| - DocumentSymbol name Nothing kind Nothing Nothing loc loc (Just cc) |
172 |
| - docSymbolWithChildren' name kind loc selectionLoc cc = |
173 |
| - DocumentSymbol name Nothing kind Nothing Nothing loc selectionLoc (Just cc) |
174 |
| - moduleSymbol name loc cc = DocumentSymbol name |
175 |
| - Nothing |
176 |
| - SymbolKind_File |
177 |
| - Nothing |
178 |
| - Nothing |
179 |
| - (R 0 0 maxBound 0) |
180 |
| - loc |
181 |
| - (Just cc) |
182 |
| - classSymbol name loc cc = DocumentSymbol name |
183 |
| - (Just "class") |
184 |
| - SymbolKind_Interface |
185 |
| - Nothing |
186 |
| - Nothing |
187 |
| - loc |
188 |
| - loc |
189 |
| - (Just cc) |
| 44 | + ], |
| 45 | + testSymbolsA |
| 46 | + "type class instance " |
| 47 | + ["class A a where", "instance A () where"] |
| 48 | + [ classSymbol "A a" (R 0 0 0 15) [], |
| 49 | + docSymbol "A ()" SymbolKind_Interface (R 1 0 1 19) |
| 50 | + ], |
| 51 | + testSymbolsA "type family" ["{-# language TypeFamilies #-}", "type family A"] [docSymbolD "A" "type family" SymbolKind_Function (R 1 0 1 13)], |
| 52 | + testSymbolsA |
| 53 | + "type family instance " |
| 54 | + ["{-# language TypeFamilies #-}", "type family A a", "type instance A () = ()"] |
| 55 | + [ docSymbolD "A a" "type family" SymbolKind_Function (R 1 0 1 15), |
| 56 | + docSymbol "A ()" SymbolKind_Interface (R 2 0 2 23) |
| 57 | + ], |
| 58 | + testSymbolsA "data family" ["{-# language TypeFamilies #-}", "data family A"] [docSymbolD "A" "data family" SymbolKind_Function (R 1 0 1 11)], |
| 59 | + testSymbolsA |
| 60 | + "data family instance " |
| 61 | + ["{-# language TypeFamilies #-}", "data family A a", "data instance A () = A ()"] |
| 62 | + [ docSymbolD "A a" "data family" SymbolKind_Function (R 1 0 1 11), |
| 63 | + docSymbol "A ()" SymbolKind_Interface (R 2 0 2 25) |
| 64 | + ], |
| 65 | + testSymbolsA "constant" ["a = ()"] [docSymbol "a" SymbolKind_Function (R 0 0 0 6)], |
| 66 | + testSymbolsA "pattern" ["Just foo = Just 21"] [docSymbol "Just foo" SymbolKind_Function (R 0 0 0 18)], |
| 67 | + testSymbolsA "pattern with type signature" ["{-# language ScopedTypeVariables #-}", "a :: () = ()"] [docSymbol "a :: ()" SymbolKind_Function (R 1 0 1 12)], |
| 68 | + testSymbolsA "function" ["a _x = ()"] [docSymbol "a" SymbolKind_Function (R 0 0 0 9)], |
| 69 | + testSymbolsA "type synonym" ["type A = Bool"] [docSymbol' "A" SymbolKind_TypeParameter (R 0 0 0 13) (R 0 5 0 6)], |
| 70 | + testSymbolsA "datatype" ["data A = C"] [docSymbolWithChildren "A" SymbolKind_Struct (R 0 0 0 10) [docSymbol "C" SymbolKind_Constructor (R 0 9 0 10)]], |
| 71 | + testSymbolsA |
| 72 | + "record fields" |
| 73 | + ["data A = B {", " x :: Int", " , y :: Int}"] |
| 74 | + [ docSymbolWithChildren |
| 75 | + "A" |
| 76 | + SymbolKind_Struct |
| 77 | + (R 0 0 2 13) |
| 78 | + [ docSymbolWithChildren' |
| 79 | + "B" |
| 80 | + SymbolKind_Constructor |
| 81 | + (R 0 9 2 13) |
| 82 | + (R 0 9 0 10) |
| 83 | + [ docSymbol "x" SymbolKind_Field (R 1 2 1 3), |
| 84 | + docSymbol "y" SymbolKind_Field (R 2 4 2 5) |
| 85 | + ] |
| 86 | + ] |
| 87 | + ], |
| 88 | + testSymbolsA |
| 89 | + "import" |
| 90 | + ["import Data.Maybe ()"] |
| 91 | + [ docSymbolWithChildren |
| 92 | + "imports" |
| 93 | + SymbolKind_Module |
| 94 | + (R 0 0 0 20) |
| 95 | + [ docSymbol "import Data.Maybe" SymbolKind_Module (R 0 0 0 20) |
| 96 | + ] |
| 97 | + ], |
| 98 | + testSymbolsA |
| 99 | + "multiple import" |
| 100 | + ["", "import Data.Maybe ()", "", "import Control.Exception ()", ""] |
| 101 | + [ docSymbolWithChildren |
| 102 | + "imports" |
| 103 | + SymbolKind_Module |
| 104 | + (R 1 0 3 27) |
| 105 | + [ docSymbol "import Data.Maybe" SymbolKind_Module (R 1 0 1 20), |
| 106 | + docSymbol "import Control.Exception" SymbolKind_Module (R 3 0 3 27) |
| 107 | + ] |
| 108 | + ], |
| 109 | + testSymbolsA |
| 110 | + "foreign import" |
| 111 | + [ "{-# language ForeignFunctionInterface #-}", |
| 112 | + "foreign import ccall \"a\" a :: Int" |
| 113 | + ] |
| 114 | + [docSymbolD "a" "import" SymbolKind_Object (R 1 0 1 33)], |
| 115 | + testSymbolsA |
| 116 | + "foreign export" |
| 117 | + [ "{-# language ForeignFunctionInterface #-}", |
| 118 | + "foreign export ccall odd :: Int -> Bool" |
| 119 | + ] |
| 120 | + [docSymbolD "odd" "export" SymbolKind_Object (R 1 0 1 39)] |
| 121 | + ] |
| 122 | + where |
| 123 | + docSymbol name kind loc = |
| 124 | + DocumentSymbol name Nothing kind Nothing Nothing loc loc Nothing |
| 125 | + docSymbol' name kind loc selectionLoc = |
| 126 | + DocumentSymbol name Nothing kind Nothing Nothing loc selectionLoc Nothing |
| 127 | + docSymbolD name detail kind loc = |
| 128 | + DocumentSymbol name (Just detail) kind Nothing Nothing loc loc Nothing |
| 129 | + docSymbolWithChildren name kind loc cc = |
| 130 | + DocumentSymbol name Nothing kind Nothing Nothing loc loc (Just cc) |
| 131 | + docSymbolWithChildren' name kind loc selectionLoc cc = |
| 132 | + DocumentSymbol name Nothing kind Nothing Nothing loc selectionLoc (Just cc) |
| 133 | + moduleSymbol name loc cc = |
| 134 | + DocumentSymbol |
| 135 | + name |
| 136 | + Nothing |
| 137 | + SymbolKind_File |
| 138 | + Nothing |
| 139 | + Nothing |
| 140 | + (R 0 0 maxBound 0) |
| 141 | + loc |
| 142 | + (Just cc) |
| 143 | + classSymbol name loc cc = |
| 144 | + DocumentSymbol |
| 145 | + name |
| 146 | + (Just "class") |
| 147 | + SymbolKind_Interface |
| 148 | + Nothing |
| 149 | + Nothing |
| 150 | + loc |
| 151 | + loc |
| 152 | + (Just cc) |
0 commit comments