Skip to content

Commit da9c643

Browse files
authored
Merge pull request #1739 from bstaletic/inlay_hints_tests
[READY] Add inlay hints tests
2 parents 743b729 + a05ad3d commit da9c643

File tree

6 files changed

+432
-2
lines changed

6 files changed

+432
-2
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Copyright (C) 2024 ycmd contributors
2+
#
3+
# This file is part of ycmd.
4+
#
5+
# ycmd is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# ycmd is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with ycmd. If not, see <http://www.gnu.org/licenses/>.
17+
18+
import json
19+
import requests
20+
from unittest import TestCase
21+
from hamcrest import assert_that, contains, empty, equal_to, has_entries
22+
23+
from ycmd.tests.clangd import setUpModule, tearDownModule # noqa
24+
from ycmd.tests.clangd import PathToTestFile, SharedYcmd
25+
from ycmd.tests.test_utils import ( BuildRequest,
26+
CombineRequest,
27+
LocationMatcher,
28+
WaitUntilCompleterServerReady )
29+
from ycmd.utils import ReadFile
30+
31+
32+
def RunTest( app, test ):
33+
"""
34+
Method to run a simple completion test and verify the result
35+
36+
Note: Compile commands are extracted from a compile_flags.txt file by clangd
37+
by iteratively looking at the directory containing the source file and its
38+
ancestors.
39+
40+
test is a dictionary containing:
41+
'request': kwargs for BuildRequest
42+
'expect': {
43+
'response': server response code (e.g. requests.codes.ok)
44+
'data': matcher for the server response json
45+
}
46+
"""
47+
48+
request = test[ 'request' ]
49+
filetype = request.get( 'filetype', 'cpp' )
50+
if 'contents' not in request:
51+
contents = ReadFile( request[ 'filepath' ] )
52+
request[ 'contents' ] = contents
53+
request[ 'filetype' ] = filetype
54+
55+
# Because we aren't testing this command, we *always* ignore errors. This
56+
# is mainly because we (may) want to test scenarios where the completer
57+
# throws an exception and the easiest way to do that is to throw from
58+
# within the Settings function.
59+
app.post_json( '/event_notification',
60+
CombineRequest( request, {
61+
'event_name': 'FileReadyToParse',
62+
'filetype': filetype
63+
} ),
64+
expect_errors = True )
65+
WaitUntilCompleterServerReady( app, filetype )
66+
67+
# We also ignore errors here, but then we check the response code ourself.
68+
# This is to allow testing of requests returning errors.
69+
response = app.post_json( '/inlay_hints',
70+
BuildRequest( **request ),
71+
expect_errors = True )
72+
73+
assert_that( response.status_code,
74+
equal_to( test[ 'expect' ][ 'response' ] ) )
75+
76+
print( f'Completer response: { json.dumps( response.json, indent = 2 ) }' )
77+
78+
assert_that( response.json, test[ 'expect' ][ 'data' ] )
79+
80+
81+
class SignatureHelpTest( TestCase ):
82+
@SharedYcmd
83+
def test_none( self, app ):
84+
filepath = PathToTestFile( 'template.cc' )
85+
RunTest( app, {
86+
'request': {
87+
'filetype': 'cpp',
88+
'filepath': filepath,
89+
'range': {
90+
'start': {
91+
'line_num': 0,
92+
'column_num': 0,
93+
'filepath': filepath
94+
},
95+
'end': {
96+
'line_num': 2,
97+
'column_num': 0,
98+
'filepath': filepath
99+
},
100+
}
101+
},
102+
'expect': {
103+
'response': requests.codes.ok,
104+
'data': has_entries( {
105+
'errors': empty(),
106+
'inlay_hints': empty(),
107+
} )
108+
},
109+
} )
110+
111+
112+
@SharedYcmd
113+
def test_basic( self, app ):
114+
filepath = PathToTestFile( 'inlay_hints_basic.cpp' )
115+
RunTest( app, {
116+
'request': {
117+
'filetype' : 'cpp',
118+
'filepath': filepath,
119+
'range': {
120+
'start': {
121+
'line_num': 0,
122+
'column_num': 0,
123+
'filepath': filepath
124+
},
125+
'end': {
126+
'line_num': 2,
127+
'column_num': 0,
128+
'filepath': filepath
129+
},
130+
}
131+
},
132+
'expect': {
133+
'response': requests.codes.ok,
134+
'data': has_entries( {
135+
'errors': empty(),
136+
'inlay_hints': contains(
137+
has_entries( {
138+
'kind': 'Parameter',
139+
'position': LocationMatcher( filepath, 2, 16 ),
140+
'label': 'b:'
141+
} ),
142+
),
143+
} )
144+
},
145+
} )
146+
147+
148+
@SharedYcmd
149+
def test_multiple( self, app ):
150+
filepath = PathToTestFile( 'inlay_hints_multiple.cpp' )
151+
RunTest( app, {
152+
'request': {
153+
'filetype' : 'cpp',
154+
'filepath': filepath,
155+
'range': {
156+
'start': {
157+
'line_num': 0,
158+
'column_num': 0,
159+
'filepath': filepath
160+
},
161+
'end': {
162+
'line_num': 2,
163+
'column_num': 0,
164+
'filepath': filepath
165+
},
166+
}
167+
},
168+
'expect': {
169+
'response': requests.codes.ok,
170+
'data': has_entries( {
171+
'errors': empty(),
172+
'inlay_hints': contains(
173+
has_entries( {
174+
'kind': 'Parameter',
175+
'position': LocationMatcher( filepath, 2, 16 ),
176+
'label': 'a:'
177+
} ),
178+
has_entries( {
179+
'kind': 'Parameter',
180+
'position': LocationMatcher( filepath, 2, 19 ),
181+
'label': 'b:'
182+
} )
183+
),
184+
} )
185+
},
186+
} )

ycmd/tests/clangd/semantic_highlighting_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2021 ycmd contributors
1+
# Copyright (C) 2024 ycmd contributors
22
#
33
# This file is part of ycmd.
44
#
@@ -79,7 +79,7 @@ def RunTest( app, test ):
7979

8080

8181
class SignatureHelpTest( TestCase ):
82-
@IsolatedYcmd
82+
@IsolatedYcmd()
8383
def test_none( self, app ):
8484
RunTest( app, {
8585
'request': {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void f(int b);
2+
int main() { f(2); }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void f(int a, int b);
2+
int main() { f(5, 2); }

ycmd/tests/go/inlay_hints_test.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Copyright (C) 2024 ycmd contributors
2+
#
3+
# This file is part of ycmd.
4+
#
5+
# ycmd is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# ycmd is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with ycmd. If not, see <http://www.gnu.org/licenses/>.
17+
18+
import json
19+
import requests
20+
from unittest import TestCase
21+
from hamcrest import assert_that, contains, empty, equal_to, has_entries
22+
23+
from ycmd.tests.go import setUpModule, tearDownModule # noqa
24+
from ycmd.tests.go import PathToTestFile, SharedYcmd
25+
from ycmd.tests.test_utils import ( BuildRequest,
26+
CombineRequest,
27+
LocationMatcher,
28+
WaitUntilCompleterServerReady )
29+
from ycmd.utils import ReadFile
30+
31+
32+
def RunTest( app, test ):
33+
"""
34+
Method to run a simple completion test and verify the result
35+
36+
Note: Compile commands are extracted from a compile_flags.txt file by go
37+
by iteratively looking at the directory containing the source file and its
38+
ancestors.
39+
40+
test is a dictionary containing:
41+
'request': kwargs for BuildRequest
42+
'expect': {
43+
'response': server response code (e.g. requests.codes.ok)
44+
'data': matcher for the server response json
45+
}
46+
"""
47+
48+
request = test[ 'request' ]
49+
filetype = request.get( 'filetype', 'go' )
50+
if 'contents' not in request:
51+
contents = ReadFile( request[ 'filepath' ] )
52+
request[ 'contents' ] = contents
53+
request[ 'filetype' ] = filetype
54+
55+
# Because we aren't testing this command, we *always* ignore errors. This
56+
# is mainly because we (may) want to test scenarios where the completer
57+
# throws an exception and the easiest way to do that is to throw from
58+
# within the Settings function.
59+
app.post_json( '/event_notification',
60+
CombineRequest( request, {
61+
'event_name': 'FileReadyToParse',
62+
'filetype': filetype
63+
} ),
64+
expect_errors = True )
65+
WaitUntilCompleterServerReady( app, filetype )
66+
67+
# We also ignore errors here, but then we check the response code ourself.
68+
# This is to allow testing of requests returning errors.
69+
response = app.post_json( '/inlay_hints',
70+
BuildRequest( **request ),
71+
expect_errors = True )
72+
73+
assert_that( response.status_code,
74+
equal_to( test[ 'expect' ][ 'response' ] ) )
75+
76+
print( f'Completer response: { json.dumps( response.json, indent = 2 ) }' )
77+
78+
assert_that( response.json, test[ 'expect' ][ 'data' ] )
79+
80+
81+
class SignatureHelpTest( TestCase ):
82+
@SharedYcmd
83+
def test_basic( self, app ):
84+
filepath = PathToTestFile( 'td', 'signature_help.go' )
85+
RunTest( app, {
86+
'request': {
87+
'filetype' : 'go',
88+
'filepath': filepath,
89+
'range': {
90+
'start': {
91+
'line_num': 1,
92+
'column_num': 1,
93+
'filepath': filepath
94+
},
95+
'end': {
96+
'line_num': 14,
97+
'column_num': 1,
98+
'filepath': filepath
99+
},
100+
}
101+
},
102+
'expect': {
103+
'response': requests.codes.ok,
104+
'data': has_entries( {
105+
'errors': empty(),
106+
'inlay_hints': contains(
107+
has_entries( {
108+
'kind': 'Parameter',
109+
'position': LocationMatcher( filepath, 10, 14 ),
110+
'label': 'a...:'
111+
} ),
112+
has_entries( {
113+
'kind': 'Parameter',
114+
'position': LocationMatcher( filepath, 10, 18 ),
115+
'label': 'x:'
116+
} ),
117+
has_entries( {
118+
'kind': 'Parameter',
119+
'position': LocationMatcher( filepath, 10, 22 ),
120+
'label': 'y:'
121+
} ),
122+
),
123+
} )
124+
},
125+
} )

0 commit comments

Comments
 (0)