1
- {-# LANGUAGE DerivingStrategies #-}
2
- {-# LANGUAGE DuplicateRecordFields #-}
3
- {-# LANGUAGE TypeOperators #-}
1
+ {-# LANGUAGE DerivingStrategies #-}
2
+ {-# LANGUAGE DuplicateRecordFields #-}
3
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4
+ {-# LANGUAGE TypeOperators #-}
5
+
4
6
module Ide.TypesTests
5
7
( tests
6
8
) where
7
- import Control.Lens ((?~) )
9
+ import Control.Lens (preview , (?~) , (^?) )
10
+ import Control.Monad ((>=>) )
8
11
import Data.Default (Default (def ))
9
12
import Data.Function ((&) )
10
13
import Data.List.NonEmpty (NonEmpty ((:|) ), nonEmpty )
14
+ import Data.Maybe (isJust )
11
15
import qualified Data.Text as Text
12
16
import Ide.Types (Config (Config ),
13
17
PluginRequestMethod (combineResponses ))
@@ -26,11 +30,19 @@ import Language.LSP.Protocol.Types (ClientCapabilities,
26
30
Range (Range ),
27
31
TextDocumentClientCapabilities (TextDocumentClientCapabilities , _definition ),
28
32
TextDocumentIdentifier (TextDocumentIdentifier ),
33
+ TypeDefinitionClientCapabilities (TypeDefinitionClientCapabilities , _dynamicRegistration , _linkSupport ),
29
34
TypeDefinitionParams (.. ),
30
- Uri (Uri ), filePathToUri ,
35
+ Uri (Uri ), _L , _R ,
36
+ _typeDefinition , filePathToUri ,
31
37
type (|? ) (.. ))
32
38
import Test.Tasty (TestTree , testGroup )
33
39
import Test.Tasty.HUnit (assertBool , testCase , (@=?) )
40
+ import Test.Tasty.QuickCheck (ASCIIString (ASCIIString ),
41
+ Arbitrary (arbitrary ), Gen ,
42
+ NonEmptyList (NonEmpty ),
43
+ arbitraryBoundedEnum , cover ,
44
+ listOf1 , oneof , testProperty ,
45
+ (===) )
34
46
35
47
tests :: TestTree
36
48
tests = testGroup " PluginTypes"
@@ -50,21 +62,22 @@ combineResponsesTextDocumentTypeDefinitionTests :: TestTree
50
62
combineResponsesTextDocumentTypeDefinitionTests = testGroup " TextDocumentTypeDefinition" $
51
63
defAndTypeDefSharedTests SMethod_TextDocumentTypeDefinition typeDefinitionParams
52
64
53
- defAndTypeDefSharedTests message params = [ testCase " merges all single location responses into one response with all locations and upgrades them into links (with link support)" $ do
65
+ defAndTypeDefSharedTests message params =
66
+ [ testCase " merges all single location responses into one response with all locations (without upgrading to links)" $ do
54
67
let pluginResponses :: NonEmpty (Definition |? ([DefinitionLink ] |? Null ))
55
68
pluginResponses =
56
69
(InL . Definition . InL . Location testFileUri $ range1) :|
57
70
[ InL . Definition . InL . Location testFileUri $ range2
58
71
, InL . Definition . InL . Location testFileUri $ range3
59
72
]
60
73
61
- result = combineResponses message def supportsLinkInDefinitionCaps params pluginResponses
74
+ result = combineResponses message def supportsLinkInAllDefinitionCaps params pluginResponses
62
75
63
76
expectedResult :: Definition |? ([DefinitionLink ] |? Null )
64
- expectedResult = InR . InL $
65
- [ DefinitionLink $ LocationLink Nothing testFileUri range1 range1
66
- , DefinitionLink $ LocationLink Nothing testFileUri range2 range2
67
- , DefinitionLink $ LocationLink Nothing testFileUri range3 range3
77
+ expectedResult = InL . Definition . InR $
78
+ [ Location testFileUri range1
79
+ , Location testFileUri range2
80
+ , Location testFileUri range3
68
81
]
69
82
expectedResult @=? result
70
83
@@ -78,7 +91,7 @@ defAndTypeDefSharedTests message params = [ testCase "merges all single location
78
91
]
79
92
]
80
93
81
- result = combineResponses message def supportsLinkInDefinitionCaps params pluginResponses
94
+ result = combineResponses message def supportsLinkInAllDefinitionCaps params pluginResponses
82
95
83
96
expectedResult :: Definition |? ([DefinitionLink ] |? Null )
84
97
expectedResult = InR . InL $
@@ -96,7 +109,7 @@ defAndTypeDefSharedTests message params = [ testCase "merges all single location
96
109
, InL . Definition . InR $ [Location testFileUri range3]
97
110
]
98
111
99
- result = combineResponses message def supportsLinkInDefinitionCaps params pluginResponses
112
+ result = combineResponses message def supportsLinkInAllDefinitionCaps params pluginResponses
100
113
101
114
expectedResult :: Definition |? ([DefinitionLink ] |? Null )
102
115
expectedResult = InR . InL $
@@ -111,10 +124,10 @@ defAndTypeDefSharedTests message params = [ testCase "merges all single location
111
124
pluginResponses =
112
125
(InL . Definition . InL . Location testFileUri $ range1) :|
113
126
[ InR . InR $ Null
114
- , InL . Definition . InR $ [ Location testFileUri range3]
127
+ , InR . InL $ [ DefinitionLink $ LocationLink Nothing testFileUri range3 range3]
115
128
]
116
129
117
- result = combineResponses message def supportsLinkInDefinitionCaps params pluginResponses
130
+ result = combineResponses message def supportsLinkInAllDefinitionCaps params pluginResponses
118
131
119
132
expectedResult :: Definition |? ([DefinitionLink ] |? Null )
120
133
expectedResult = InR . InL $
@@ -131,20 +144,33 @@ defAndTypeDefSharedTests message params = [ testCase "merges all single location
131
144
, InR . InR $ Null
132
145
]
133
146
134
- result = combineResponses message def supportsLinkInDefinitionCaps params pluginResponses
147
+ result = combineResponses message def supportsLinkInAllDefinitionCaps params pluginResponses
135
148
136
149
expectedResult :: Definition |? ([DefinitionLink ] |? Null )
137
150
expectedResult = InR . InR $ Null
138
151
expectedResult @=? result
152
+
153
+ , testProperty " downgrades all locationLinks to locations when missing link support in capabilities" $ \ (MkGeneratedNonEmpty responses) -> do
154
+ let pluginResponses = fmap (\ (MkGeneratedDefinition definition) -> definition) responses
155
+
156
+ result = combineResponses message def def params pluginResponses
157
+
158
+ cover 70 (any (isJust . (>>= (^? _L)) . (^? _R)) pluginResponses) " Has at least one response with links" $
159
+ cover 10 (any (isJust . (^? _L)) pluginResponses) " Has at least one response with locations" $
160
+ cover 10 (any (isJust . (>>= (^? _R)) . (^? _R)) pluginResponses) " Has at least one response with Null" $
161
+ (isJust (result ^? _L) || isJust (result ^? _R >>= (^? _R))) === True
139
162
]
140
163
141
164
(range1, range2, range3) = (Range (Position 3 0 ) $ Position 3 5 , Range (Position 5 7 ) $ Position 5 13 , Range (Position 24 30 ) $ Position 24 40 )
142
165
143
- supportsLinkInDefinitionCaps :: ClientCapabilities
144
- supportsLinkInDefinitionCaps = def & L. textDocument ?~ textDocumentCaps
166
+ supportsLinkInAllDefinitionCaps :: ClientCapabilities
167
+ supportsLinkInAllDefinitionCaps = def & L. textDocument ?~ textDocumentCaps
145
168
where
146
169
textDocumentCaps :: TextDocumentClientCapabilities
147
- textDocumentCaps = def { _definition = Just DefinitionClientCapabilities { _linkSupport = Just True , _dynamicRegistration = Nothing }}
170
+ textDocumentCaps = def
171
+ { _definition = Just DefinitionClientCapabilities { _linkSupport = Just True , _dynamicRegistration = Nothing }
172
+ , _typeDefinition = Just TypeDefinitionClientCapabilities { _linkSupport = Just True , _dynamicRegistration = Nothing }
173
+ }
148
174
149
175
definitionParams :: DefinitionParams
150
176
definitionParams = DefinitionParams
@@ -164,3 +190,40 @@ typeDefinitionParams = TypeDefinitionParams
164
190
165
191
testFileUri :: Uri
166
192
testFileUri = filePathToUri " file://tester/Test.hs"
193
+
194
+ newtype GeneratedDefinition = MkGeneratedDefinition (Definition |? ([DefinitionLink ] |? Null )) deriving newtype (Show )
195
+
196
+ instance Arbitrary GeneratedDefinition where
197
+ arbitrary = MkGeneratedDefinition <$> oneof
198
+ [ InL . Definition . InL <$> generateLocation
199
+ , InL . Definition . InR <$> listOf1 generateLocation
200
+ , InR . InL . map DefinitionLink <$> listOf1 generateLocationLink
201
+ , pure . InR . InR $ Null
202
+ ]
203
+ where
204
+ generateLocation :: Gen Location
205
+ generateLocation = do
206
+ (LocationLink _ uri range _) <- generateLocationLink
207
+ pure $ Location uri range
208
+
209
+ generateLocationLink :: Gen LocationLink
210
+ generateLocationLink = LocationLink <$> generateMaybe generateRange <*> generateUri <*> generateRange <*> generateRange
211
+
212
+ generateMaybe :: Gen a -> Gen (Maybe a )
213
+ generateMaybe gen = oneof [Just <$> gen, pure Nothing ]
214
+
215
+ generateUri :: Gen Uri
216
+ generateUri = do
217
+ (ASCIIString str) <- arbitrary
218
+ pure . Uri . Text. pack $ str
219
+
220
+ generateRange :: Gen Range
221
+ generateRange = Range <$> generatePosition <*> generatePosition
222
+
223
+ generatePosition :: Gen Position
224
+ generatePosition = Position <$> arbitraryBoundedEnum <*> arbitraryBoundedEnum
225
+
226
+ newtype GeneratedNonEmpty a = MkGeneratedNonEmpty (NonEmpty a ) deriving newtype (Show )
227
+
228
+ instance Arbitrary a => Arbitrary (GeneratedNonEmpty a ) where
229
+ arbitrary = MkGeneratedNonEmpty <$> ((:|) <$> arbitrary <*> arbitrary)
0 commit comments