16 Commits

Author SHA1 Message Date
Regen
5d916b6989 Merge pull request #19 from regen100/release-v0.1.2
Release v0.1.2
2020-06-07 22:01:20 +09:00
Regen
1c606ee8a8 Release v0.1.2 2020-06-07 21:50:21 +09:00
Regen
cdb62adce3 Merge pull request #18 from regen100/fix-ci
Fix CI
2020-06-07 20:17:27 +09:00
Regen
6ac3b1d17f Fix CI 2020-06-07 19:52:24 +09:00
Regen
ce2c3a21db Merge pull request #17 from regen100/update-doc
Update README
2020-06-06 15:23:44 +09:00
Regen
3697fae2d3 Update README 2020-06-06 14:52:03 +09:00
Regen
48d5980a36 Merge pull request #13 from regen100/fix-vim-lsp
Fix vim lsp
2020-04-29 23:45:46 +09:00
Regen
e07b3242c8 Add test 2020-04-29 22:57:43 +09:00
Regen
2d36887b26 Support no TriggerCharacter 2020-04-29 19:25:51 +09:00
Regen
67aced6544 Add encoding 2020-04-29 18:04:23 +09:00
Regen
3c171b9e25 Fix CompletionItem for vim-lsp 2020-04-29 17:56:09 +09:00
Regen
c8c284e061 Merge pull request #12 from regen100/fix-completion
Fix error without completion context
2020-04-29 16:09:21 +09:00
Regen
6bf08e0f14 Fix error without completion context 2020-04-29 15:57:25 +09:00
Regen
40d93525d9 Merge pull request #8 from regen100/add-version
Add --version to cmake-language-server
2020-03-07 00:26:36 +09:00
Regen
f8136d6dbc Disable patch status 2020-03-07 00:21:50 +09:00
Regen
5af6555d3c Add --version to cmake-language-server 2020-03-07 00:09:43 +09:00
8 changed files with 116 additions and 69 deletions

View File

@@ -10,7 +10,7 @@ jobs:
python: [3.6, 3.7, 3.8]
os: [ubuntu-18.04, windows-2016]
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v1
with:
@@ -21,12 +21,13 @@ jobs:
- name: Install CMake
if: contains(matrix.os, 'ubuntu')
run: |
CMAKE_VERSION=3.14.7
CMAKE_VERSION=3.17.3
curl -sSL https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz | tar xz
sudo cp -rT cmake-$CMAKE_VERSION-Linux-x86_64 /usr/local
rm -rf cmake-$CMAKE_VERSION-Linux-x86_64
- name: Install dependencies
run: |
cmake --version
python -m pip install --upgrade setuptools pip wheel
python -m pip install poetry tox-gh-actions
- name: Test with tox
@@ -38,4 +39,4 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
name: Python ${{ matrix.python }} on ${{ matrix.os }}
fail_ci_if_error: true
fail_ci_if_error: false

View File

@@ -25,12 +25,14 @@ Alpha Stage, work in progress.
$ pip install cmake-language-server
```
### Clients
### Tested Clients
- Neovim ([neoclide/coc.nvim][coc.nvim])
- Neovim ([neoclide/coc.nvim][coc.nvim], [prabirshrestha/vim-lsp][vim-lsp])
#### Neovim
##### coc.nvim
```jsonc
"languageserver": {
"cmake": {
@@ -46,5 +48,21 @@ $ pip install cmake-language-server
}
```
##### vim-lsp
```vim
if executable('cmake-language-server')
au User lsp_setup call lsp#register_server({
\ 'name': 'cmake',
\ 'cmd': {server_info->['cmake-language-server']},
\ 'root_uri': {server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), 'build/'))},
\ 'whitelist': ['cmake'],
\ 'initialization_options': {
\ 'buildDirectory': 'build',
\ }
\})
endif
```
[coc.nvim]: https://github.com/neoclide/coc.nvim
[vim-lsp]: https://github.com/prabirshrestha/vim-lsp

View File

@@ -4,5 +4,4 @@ coverage:
default:
threshold: 10%
patch:
default:
threshold: 20%
default: off

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "cmake-language-server"
version = "0.1.1"
version = "0.1.2"
description = "CMake LSP Implementation"
license = "MIT"
authors = ["regen"]

View File

@@ -1 +1 @@
__version__ = '0.1.1'
__version__ = '0.1.2'

View File

@@ -60,9 +60,10 @@ class API(object):
}''')
proc = subprocess.run([self._cmake, str(self._build)],
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stderr=subprocess.PIPE,
encoding='utf-8',
universal_newlines=True)
self.query_json.unlink()
self.query_json.parent.rmdir()
if proc.returncode != 0:
@@ -144,10 +145,11 @@ endforeach()
''')
p = subprocess.run(
[self._cmake, '-P', str(tmplist)],
cwd=cmake_files['paths']['source'],
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stderr=subprocess.PIPE,
cwd=cmake_files['paths']['source'],
encoding='utf-8',
universal_newlines=True)
if p.returncode != 0:
return
@@ -190,6 +192,7 @@ endforeach()
def _parse_commands(self) -> None:
p = subprocess.run([self._cmake, '--help-commands'],
stdout=subprocess.PIPE,
encoding='utf-8',
universal_newlines=True)
if p.returncode != 0:
@@ -213,6 +216,7 @@ endforeach()
def _parse_variables(self) -> None:
p = subprocess.run([self._cmake, '--help-variables'],
stdout=subprocess.PIPE,
encoding='utf-8',
universal_newlines=True)
if p.returncode != 0:
@@ -241,6 +245,7 @@ endforeach()
def _parse_modules(self) -> None:
p = subprocess.run([self._cmake, '--help-modules'],
stdout=subprocess.PIPE,
encoding='utf-8',
universal_newlines=True)
if p.returncode != 0:

View File

@@ -40,12 +40,21 @@ class CMakeLanguageServer(LanguageServer):
self._api = API(cmake, Path(builddir))
self._api.parse_doc()
@self.feature(COMPLETION, trigger_characters=['{', '('])
trigger_characters = ['{', '(']
@self.feature(COMPLETION, trigger_characters=trigger_characters)
def completions(params: CompletionParams):
if (params.context.triggerKind ==
if (hasattr(params, 'context') and params.context.triggerKind ==
CompletionTriggerKind.TriggerCharacter):
token = ''
trigger = params.context.triggerCharacter
else:
line = self._cursor_line(params.textDocument.uri,
params.position)
idx = params.position.character - 1
if 0 <= idx < len(line) and line[idx] in trigger_characters:
token = ''
trigger = line[idx]
else:
word = self._cursor_word(params.textDocument.uri,
params.position, False)
@@ -59,21 +68,21 @@ class CMakeLanguageServer(LanguageServer):
items.extend(
CompletionItem(x,
CompletionItemKind.Function,
documentation=self._api.get_command_doc(x))
for x in commands)
documentation=self._api.get_command_doc(x),
insert_text=x) for x in commands)
if trigger is None or trigger == '{':
variables = self._api.search_variable(token)
items.extend(
CompletionItem(x,
CompletionItemKind.Variable,
documentation=self._api.get_variable_doc(x))
for x in variables)
documentation=self._api.get_variable_doc(x),
insert_text=x) for x in variables)
if trigger is None:
targets = self._api.search_target(token)
items.extend(
CompletionItem(x, CompletionItemKind.Class)
CompletionItem(x, CompletionItemKind.Class, insert_text=x)
for x in targets)
if trigger == '(':
@@ -87,16 +96,16 @@ class CMakeLanguageServer(LanguageServer):
CompletionItem(x,
CompletionItemKind.Module,
documentation=self._api.
get_module_doc(x, False))
for x in modules)
get_module_doc(x, False),
insert_text=x) for x in modules)
elif func == 'find_package':
modules = self._api.search_module(token, True)
items.extend(
CompletionItem(x,
CompletionItemKind.Module,
documentation=self._api.
get_module_doc(x, True))
for x in modules)
get_module_doc(x, True),
insert_text=x) for x in modules)
return CompletionList(False, items)
@@ -172,7 +181,16 @@ class CMakeLanguageServer(LanguageServer):
return None
def main():
def main(args=None):
from argparse import ArgumentParser
from . import __version__
parser = ArgumentParser(description='CMake Language Server')
parser.add_argument('--version',
action='version',
version=f'%(prog)s {__version__}')
args = parser.parse_args(args)
logging.basicConfig(level=logging.INFO)
logging.getLogger('pygls').setLevel(logging.WARNING)
CMakeLanguageServer().start_io()

View File

@@ -40,6 +40,21 @@ def _open(client: LanguageServer, path: Path, text: Optional[str] = None):
TextDocumentItem(path.as_uri(), 'cmake', 1, text)))
def _test_completion(client_server, datadir, content: str,
context: Optional[CompletionContext]):
client, server = client_server
_init(client, datadir)
path = datadir / 'CMakeLists.txt'
_open(client, path, content)
params = CompletionParams(TextDocumentIdentifier(path.as_uri()),
Position(0, len(content)), context)
if context is None:
# some clients do not send context
del params.context
return client.lsp.send_request(COMPLETION,
params).result(timeout=CALL_TIMEOUT)
def test_initialize(client_server, datadir):
client, server = client_server
@@ -49,61 +64,52 @@ def test_initialize(client_server, datadir):
def test_completions_invoked(client_server, datadir):
client, server = client_server
_init(client, datadir)
path = datadir / 'CMakeLists.txt'
_open(client, path, 'projec')
response = client.lsp.send_request(
COMPLETION,
CompletionParams(TextDocumentIdentifier(path.as_uri()), Position(
0, 6), CompletionContext(
CompletionTriggerKind.Invoked))).result(timeout=CALL_TIMEOUT)
response = _test_completion(
client_server, datadir, 'projec',
CompletionContext(CompletionTriggerKind.Invoked))
item = next(filter(lambda x: x.label == 'project', response.items), None)
assert item is not None
assert '<PROJECT-NAME>' in item.documentation
def test_completions_nocontext(client_server, datadir):
response = _test_completion(client_server, datadir, 'projec', None)
item = next(filter(lambda x: x.label == 'project', response.items), None)
assert item is not None
assert '<PROJECT-NAME>' in item.documentation
def test_completions_triggercharacter_variable(client_server, datadir):
client, server = client_server
_init(client, datadir)
path = datadir / 'CMakeLists.txt'
_open(client, path, '${')
response = client.lsp.send_request(
COMPLETION,
CompletionParams(
TextDocumentIdentifier(path.as_uri()), Position(0, 2),
CompletionContext(CompletionTriggerKind.TriggerCharacter,
'{'))).result(timeout=CALL_TIMEOUT)
response = _test_completion(
client_server, datadir, '${',
CompletionContext(CompletionTriggerKind.TriggerCharacter, '{'))
assert 'PROJECT_VERSION' in [x.label for x in response.items]
response_nocontext = _test_completion(client_server, datadir, '${', None)
assert response == response_nocontext
def test_completions_triggercharacter_module(client_server, datadir):
client, server = client_server
_init(client, datadir)
path = datadir / 'CMakeLists.txt'
_open(client, path, 'include(')
response = client.lsp.send_request(
COMPLETION,
CompletionParams(
TextDocumentIdentifier(path.as_uri()), Position(0, 8),
CompletionContext(CompletionTriggerKind.TriggerCharacter,
'('))).result(timeout=CALL_TIMEOUT)
response = _test_completion(
client_server, datadir, 'include(',
CompletionContext(CompletionTriggerKind.TriggerCharacter, '('))
assert 'GoogleTest' in [x.label for x in response.items]
response_nocontext = _test_completion(client_server, datadir, 'include(',
None)
assert response == response_nocontext
def test_completions_triggercharacter_package(client_server, datadir):
client, server = client_server
_init(client, datadir)
path = datadir / 'CMakeLists.txt'
_open(client, path, 'find_package(')
response = client.lsp.send_request(
COMPLETION,
CompletionParams(
TextDocumentIdentifier(path.as_uri()), Position(0, 13),
CompletionContext(CompletionTriggerKind.TriggerCharacter,
'('))).result(timeout=CALL_TIMEOUT)
response = _test_completion(
client_server, datadir, 'find_package(',
CompletionContext(CompletionTriggerKind.TriggerCharacter, '('))
assert 'Boost' in [x.label for x in response.items]
response_nocontext = _test_completion(client_server, datadir,
'find_package(', None)
assert response == response_nocontext
def test_formatting(client_server, datadir):
client, server = client_server