Update pygls (#38)
This commit is contained in:
72
poetry.lock
generated
72
poetry.lock
generated
@@ -107,7 +107,7 @@ dev = ["pytest (>=5)", "pytest-cov", "coveralls", "black", "mypy", "pylint"]
|
|||||||
name = "dataclasses"
|
name = "dataclasses"
|
||||||
version = "0.8"
|
version = "0.8"
|
||||||
description = "A backport of the dataclasses module for Python 3.6"
|
description = "A backport of the dataclasses module for Python 3.6"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6, <3.7"
|
python-versions = ">=3.6, <3.7"
|
||||||
|
|
||||||
@@ -279,6 +279,22 @@ category = "dev"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "1.7.3"
|
||||||
|
description = "Data validation and settings management using python 3.6 type hinting"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dotenv = ["python-dotenv (>=0.10.4)"]
|
||||||
|
email = ["email-validator (>=1.0.3)"]
|
||||||
|
typing_extensions = ["typing-extensions (>=3.7.2)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyflakes"
|
name = "pyflakes"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
@@ -289,14 +305,18 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygls"
|
name = "pygls"
|
||||||
version = "0.8.1"
|
version = "0.10.2"
|
||||||
description = "a pythonic generic language server (pronounced like \"pie glass\")."
|
description = "a pythonic generic language server (pronounced like \"pie glass\")."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pydantic = ">=1.7,<1.9"
|
||||||
|
typeguard = ">=2.10.0,<3"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["bandit (==1.6.0)", "flake8 (==3.7.7)"]
|
dev = ["bandit (==1.6.0)", "flake8 (==3.7.7)", "mypy (==0.761)"]
|
||||||
docs = ["sphinx (==2.0.1)", "sphinx-rtd-theme (==0.4.3)"]
|
docs = ["sphinx (==2.0.1)", "sphinx-rtd-theme (==0.4.3)"]
|
||||||
test = ["mock (==3.0.5)", "pytest (==4.5.0)", "pytest-asyncio (==0.10.0)"]
|
test = ["mock (==3.0.5)", "pytest (==4.5.0)", "pytest-asyncio (==0.10.0)"]
|
||||||
|
|
||||||
@@ -420,6 +440,18 @@ category = "dev"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typeguard"
|
||||||
|
version = "2.11.1"
|
||||||
|
description = "Run-time type checker for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5.3"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
|
||||||
|
test = ["pytest", "typing-extensions", "mypy"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "3.7.4.3"
|
version = "3.7.4.3"
|
||||||
@@ -451,7 +483,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
content-hash = "5229f57c9b176620cb76a80eab1496d77ca9d7905e3b549bb5011b0a2dd80590"
|
content-hash = "6037b077354199ce39ee1631aec9ab7d6aac7c0c93dde7398d376120e382006f"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
appdirs = [
|
appdirs = [
|
||||||
@@ -615,13 +647,37 @@ pycodestyle = [
|
|||||||
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
|
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
|
||||||
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
|
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
|
||||||
]
|
]
|
||||||
|
pydantic = [
|
||||||
|
{file = "pydantic-1.7.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c59ea046aea25be14dc22d69c97bee629e6d48d2b2ecb724d7fe8806bf5f61cd"},
|
||||||
|
{file = "pydantic-1.7.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a4143c8d0c456a093387b96e0f5ee941a950992904d88bc816b4f0e72c9a0009"},
|
||||||
|
{file = "pydantic-1.7.3-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:d8df4b9090b595511906fa48deda47af04e7d092318bfb291f4d45dfb6bb2127"},
|
||||||
|
{file = "pydantic-1.7.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:514b473d264671a5c672dfb28bdfe1bf1afd390f6b206aa2ec9fed7fc592c48e"},
|
||||||
|
{file = "pydantic-1.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:dba5c1f0a3aeea5083e75db9660935da90216f8a81b6d68e67f54e135ed5eb23"},
|
||||||
|
{file = "pydantic-1.7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:59e45f3b694b05a69032a0d603c32d453a23f0de80844fb14d55ab0c6c78ff2f"},
|
||||||
|
{file = "pydantic-1.7.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:5b24e8a572e4b4c18f614004dda8c9f2c07328cb5b6e314d6e1bbd536cb1a6c1"},
|
||||||
|
{file = "pydantic-1.7.3-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:b2b054d095b6431cdda2f852a6d2f0fdec77686b305c57961b4c5dd6d863bf3c"},
|
||||||
|
{file = "pydantic-1.7.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:025bf13ce27990acc059d0c5be46f416fc9b293f45363b3d19855165fee1874f"},
|
||||||
|
{file = "pydantic-1.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:6e3874aa7e8babd37b40c4504e3a94cc2023696ced5a0500949f3347664ff8e2"},
|
||||||
|
{file = "pydantic-1.7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e682f6442ebe4e50cb5e1cfde7dda6766fb586631c3e5569f6aa1951fd1a76ef"},
|
||||||
|
{file = "pydantic-1.7.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:185e18134bec5ef43351149fe34fda4758e53d05bb8ea4d5928f0720997b79ef"},
|
||||||
|
{file = "pydantic-1.7.3-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:f5b06f5099e163295b8ff5b1b71132ecf5866cc6e7f586d78d7d3fd6e8084608"},
|
||||||
|
{file = "pydantic-1.7.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:24ca47365be2a5a3cc3f4a26dcc755bcdc9f0036f55dcedbd55663662ba145ec"},
|
||||||
|
{file = "pydantic-1.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:d1fe3f0df8ac0f3a9792666c69a7cd70530f329036426d06b4f899c025aca74e"},
|
||||||
|
{file = "pydantic-1.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f6864844b039805add62ebe8a8c676286340ba0c6d043ae5dea24114b82a319e"},
|
||||||
|
{file = "pydantic-1.7.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ecb54491f98544c12c66ff3d15e701612fc388161fd455242447083350904730"},
|
||||||
|
{file = "pydantic-1.7.3-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:ffd180ebd5dd2a9ac0da4e8b995c9c99e7c74c31f985ba090ee01d681b1c4b95"},
|
||||||
|
{file = "pydantic-1.7.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8d72e814c7821125b16f1553124d12faba88e85405b0864328899aceaad7282b"},
|
||||||
|
{file = "pydantic-1.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:475f2fa134cf272d6631072554f845d0630907fce053926ff634cc6bc45bf1af"},
|
||||||
|
{file = "pydantic-1.7.3-py3-none-any.whl", hash = "sha256:38be427ea01a78206bcaf9a56f835784afcba9e5b88fbdce33bbbfbcd7841229"},
|
||||||
|
{file = "pydantic-1.7.3.tar.gz", hash = "sha256:213125b7e9e64713d16d988d10997dabc6a1f73f3991e1ff8e35ebb1409c7dc9"},
|
||||||
|
]
|
||||||
pyflakes = [
|
pyflakes = [
|
||||||
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
|
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
|
||||||
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
|
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
|
||||||
]
|
]
|
||||||
pygls = [
|
pygls = [
|
||||||
{file = "pygls-0.8.1-py3-none-any.whl", hash = "sha256:3ee878a828b7bc0873a2ea44208d6846a91aa7dbbbdc052e7fe8cc689f6644fa"},
|
{file = "pygls-0.10.2-py3-none-any.whl", hash = "sha256:bb3e287693bb06a4edfdfb0bd5bfb550b582654c39803e6fc4cd82e08d85a240"},
|
||||||
{file = "pygls-0.8.1.tar.gz", hash = "sha256:780fd0c5ae95ad02ecaf70b071e43ff8ced8384b7d6bed19311a7b431d26fb88"},
|
{file = "pygls-0.10.2.tar.gz", hash = "sha256:5b50a1931613f36af446b16c644a85b52ceb2beceb09bddd05f9ce054f13e9ab"},
|
||||||
]
|
]
|
||||||
pyparsing = [
|
pyparsing = [
|
||||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||||
@@ -730,6 +786,10 @@ typed-ast = [
|
|||||||
{file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"},
|
{file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"},
|
||||||
{file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"},
|
{file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"},
|
||||||
]
|
]
|
||||||
|
typeguard = [
|
||||||
|
{file = "typeguard-2.11.1-py3-none-any.whl", hash = "sha256:c62706201ec6c14962162fa67d70bd2762753247533d70ff2442e5ac08f94fa2"},
|
||||||
|
{file = "typeguard-2.11.1.tar.gz", hash = "sha256:33243c1cbfcb9736a06c6db22dd08876b5f297e6344aa272a2862c0f8e669f64"},
|
||||||
|
]
|
||||||
typing-extensions = [
|
typing-extensions = [
|
||||||
{file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
|
{file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
|
||||||
{file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
|
{file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ classifiers = [
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.6"
|
||||||
pygls = "^0.8.1"
|
pygls = "^0.10"
|
||||||
pyparsing = "^2.4"
|
pyparsing = "^2.4"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import re
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, List, Optional, Tuple
|
from typing import Any, Callable, List, Optional, Tuple
|
||||||
|
|
||||||
from pygls.features import (
|
from pygls.lsp.methods import (
|
||||||
COMPLETION,
|
COMPLETION,
|
||||||
FORMATTING,
|
FORMATTING,
|
||||||
HOVER,
|
HOVER,
|
||||||
@@ -11,11 +11,11 @@ from pygls.features import (
|
|||||||
INITIALIZED,
|
INITIALIZED,
|
||||||
TEXT_DOCUMENT_DID_SAVE,
|
TEXT_DOCUMENT_DID_SAVE,
|
||||||
)
|
)
|
||||||
from pygls.server import LanguageServer
|
from pygls.lsp.types import (
|
||||||
from pygls.types import (
|
|
||||||
CompletionItem,
|
CompletionItem,
|
||||||
CompletionItemKind,
|
CompletionItemKind,
|
||||||
CompletionList,
|
CompletionList,
|
||||||
|
CompletionOptions,
|
||||||
CompletionParams,
|
CompletionParams,
|
||||||
CompletionTriggerKind,
|
CompletionTriggerKind,
|
||||||
DocumentFormattingParams,
|
DocumentFormattingParams,
|
||||||
@@ -26,8 +26,10 @@ from pygls.types import (
|
|||||||
Position,
|
Position,
|
||||||
Range,
|
Range,
|
||||||
TextDocumentPositionParams,
|
TextDocumentPositionParams,
|
||||||
|
TextDocumentSaveRegistrationOptions,
|
||||||
TextEdit,
|
TextEdit,
|
||||||
)
|
)
|
||||||
|
from pygls.server import LanguageServer
|
||||||
|
|
||||||
from .api import API
|
from .api import API
|
||||||
from .formatter import Formatter
|
from .formatter import Formatter
|
||||||
@@ -36,7 +38,7 @@ from .parser import ListParser
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CMakeLanguageServer(LanguageServer): # type: ignore
|
class CMakeLanguageServer(LanguageServer):
|
||||||
_parser: ListParser
|
_parser: ListParser
|
||||||
_api: Optional[API]
|
_api: Optional[API]
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
|
|
||||||
@self.feature(INITIALIZE)
|
@self.feature(INITIALIZE)
|
||||||
def initialize(params: InitializeParams) -> None:
|
def initialize(params: InitializeParams) -> None:
|
||||||
opts = params.initializationOptions
|
opts = params.initialization_options
|
||||||
|
|
||||||
cmake = getattr(opts, "cmakeExecutable", "cmake")
|
cmake = getattr(opts, "cmakeExecutable", "cmake")
|
||||||
builddir = getattr(opts, "buildDirectory", "")
|
builddir = getattr(opts, "buildDirectory", "")
|
||||||
@@ -59,25 +61,28 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
|
|
||||||
trigger_characters = ["{", "("]
|
trigger_characters = ["{", "("]
|
||||||
|
|
||||||
@self.feature(COMPLETION, trigger_characters=trigger_characters)
|
@self.feature(
|
||||||
|
COMPLETION, CompletionOptions(trigger_characters=trigger_characters)
|
||||||
|
)
|
||||||
def completions(params: CompletionParams) -> CompletionList:
|
def completions(params: CompletionParams) -> CompletionList:
|
||||||
assert self._api is not None
|
assert self._api is not None
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasattr(params, "context")
|
params.context is not None
|
||||||
and params.context.triggerKind == CompletionTriggerKind.TriggerCharacter
|
and params.context.trigger_kind
|
||||||
|
== CompletionTriggerKind.TriggerCharacter
|
||||||
):
|
):
|
||||||
token = ""
|
token = ""
|
||||||
trigger = params.context.triggerCharacter
|
trigger = params.context.trigger_character
|
||||||
else:
|
else:
|
||||||
line = self._cursor_line(params.textDocument.uri, params.position)
|
line = self._cursor_line(params.text_document.uri, params.position)
|
||||||
idx = params.position.character - 1
|
idx = params.position.character - 1
|
||||||
if 0 <= idx < len(line) and line[idx] in trigger_characters:
|
if 0 <= idx < len(line) and line[idx] in trigger_characters:
|
||||||
token = ""
|
token = ""
|
||||||
trigger = line[idx]
|
trigger = line[idx]
|
||||||
else:
|
else:
|
||||||
word = self._cursor_word(
|
word = self._cursor_word(
|
||||||
params.textDocument.uri, params.position, False
|
params.text_document.uri, params.position, False
|
||||||
)
|
)
|
||||||
token = "" if word is None else word[0]
|
token = "" if word is None else word[0]
|
||||||
trigger = None
|
trigger = None
|
||||||
@@ -88,8 +93,8 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
commands = self._api.search_command(token)
|
commands = self._api.search_command(token)
|
||||||
items.extend(
|
items.extend(
|
||||||
CompletionItem(
|
CompletionItem(
|
||||||
x,
|
label=x,
|
||||||
CompletionItemKind.Function,
|
kind=CompletionItemKind.Function,
|
||||||
documentation=self._api.get_command_doc(x),
|
documentation=self._api.get_command_doc(x),
|
||||||
insert_text=x,
|
insert_text=x,
|
||||||
)
|
)
|
||||||
@@ -100,8 +105,8 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
variables = self._api.search_variable(token)
|
variables = self._api.search_variable(token)
|
||||||
items.extend(
|
items.extend(
|
||||||
CompletionItem(
|
CompletionItem(
|
||||||
x,
|
label=x,
|
||||||
CompletionItemKind.Variable,
|
kind=CompletionItemKind.Variable,
|
||||||
documentation=self._api.get_variable_doc(x),
|
documentation=self._api.get_variable_doc(x),
|
||||||
insert_text=x,
|
insert_text=x,
|
||||||
)
|
)
|
||||||
@@ -111,20 +116,22 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
if trigger is None:
|
if trigger is None:
|
||||||
targets = self._api.search_target(token)
|
targets = self._api.search_target(token)
|
||||||
items.extend(
|
items.extend(
|
||||||
CompletionItem(x, CompletionItemKind.Class, insert_text=x)
|
CompletionItem(
|
||||||
|
lable=x, kind=CompletionItemKind.Class, insert_text=x
|
||||||
|
)
|
||||||
for x in targets
|
for x in targets
|
||||||
)
|
)
|
||||||
|
|
||||||
if trigger == "(":
|
if trigger == "(":
|
||||||
func = self._cursor_function(params.textDocument.uri, params.position)
|
func = self._cursor_function(params.text_document.uri, params.position)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
func = func.lower()
|
func = func.lower()
|
||||||
if func == "include":
|
if func == "include":
|
||||||
modules = self._api.search_module(token, False)
|
modules = self._api.search_module(token, False)
|
||||||
items.extend(
|
items.extend(
|
||||||
CompletionItem(
|
CompletionItem(
|
||||||
x,
|
label=x,
|
||||||
CompletionItemKind.Module,
|
kind=CompletionItemKind.Module,
|
||||||
documentation=self._api.get_module_doc(x, False),
|
documentation=self._api.get_module_doc(x, False),
|
||||||
insert_text=x,
|
insert_text=x,
|
||||||
)
|
)
|
||||||
@@ -134,19 +141,19 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
modules = self._api.search_module(token, True)
|
modules = self._api.search_module(token, True)
|
||||||
items.extend(
|
items.extend(
|
||||||
CompletionItem(
|
CompletionItem(
|
||||||
x,
|
label=x,
|
||||||
CompletionItemKind.Module,
|
kind=CompletionItemKind.Module,
|
||||||
documentation=self._api.get_module_doc(x, True),
|
documentation=self._api.get_module_doc(x, True),
|
||||||
insert_text=x,
|
insert_text=x,
|
||||||
)
|
)
|
||||||
for x in modules
|
for x in modules
|
||||||
)
|
)
|
||||||
|
|
||||||
return CompletionList(False, items)
|
return CompletionList(is_incomplete=False, items=items)
|
||||||
|
|
||||||
@self.feature(FORMATTING)
|
@self.feature(FORMATTING)
|
||||||
def formatting(params: DocumentFormattingParams) -> Optional[List[TextEdit]]:
|
def formatting(params: DocumentFormattingParams) -> Optional[List[TextEdit]]:
|
||||||
doc = self.workspace.get_document(params.textDocument.uri)
|
doc = self.workspace.get_document(params.text_document.uri)
|
||||||
content = doc.source
|
content = doc.source
|
||||||
tokens, remain = self._parser.parse(content)
|
tokens, remain = self._parser.parse(content)
|
||||||
if remain:
|
if remain:
|
||||||
@@ -155,14 +162,22 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
|
|
||||||
formatted = Formatter().format(tokens)
|
formatted = Formatter().format(tokens)
|
||||||
lines = content.count("\n")
|
lines = content.count("\n")
|
||||||
return [TextEdit(Range(Position(0, 0), Position(lines + 1, 0)), formatted)]
|
return [
|
||||||
|
TextEdit(
|
||||||
|
range=Range(
|
||||||
|
start=Position(line=0, character=0),
|
||||||
|
end=Position(line=lines + 1, character=0),
|
||||||
|
),
|
||||||
|
new_text=formatted,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
@self.feature(HOVER)
|
@self.feature(HOVER)
|
||||||
def hover(params: TextDocumentPositionParams) -> Optional[Hover]:
|
def hover(params: TextDocumentPositionParams) -> Optional[Hover]:
|
||||||
assert self._api is not None
|
assert self._api is not None
|
||||||
api = self._api
|
api = self._api
|
||||||
|
|
||||||
word = self._cursor_word(params.textDocument.uri, params.position, True)
|
word = self._cursor_word(params.text_document.uri, params.position, True)
|
||||||
if not word:
|
if not word:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -176,11 +191,17 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
doc = c(word[0])
|
doc = c(word[0])
|
||||||
if doc is None:
|
if doc is None:
|
||||||
continue
|
continue
|
||||||
return Hover(MarkupContent(MarkupKind.Markdown, doc), word[1])
|
return Hover(
|
||||||
|
contents=MarkupContent(kind=MarkupKind.Markdown, value=doc),
|
||||||
|
range=word[1],
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@self.thread()
|
@self.thread()
|
||||||
@self.feature(TEXT_DOCUMENT_DID_SAVE, includeText=False)
|
@self.feature(
|
||||||
|
TEXT_DOCUMENT_DID_SAVE,
|
||||||
|
TextDocumentSaveRegistrationOptions(include_text=False),
|
||||||
|
)
|
||||||
@self.feature(INITIALIZED)
|
@self.feature(INITIALIZED)
|
||||||
def run_cmake(*args: Any) -> None:
|
def run_cmake(*args: Any) -> None:
|
||||||
assert self._api is not None
|
assert self._api is not None
|
||||||
@@ -212,7 +233,8 @@ class CMakeLanguageServer(LanguageServer): # type: ignore
|
|||||||
word = (
|
word = (
|
||||||
line[m.start() : end],
|
line[m.start() : end],
|
||||||
Range(
|
Range(
|
||||||
Position(position.line, m.start()), Position(position.line, end)
|
start=Position(line=position.line, character=m.start()),
|
||||||
|
end=Position(line=position.line, character=end),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return word
|
return word
|
||||||
@@ -232,4 +254,4 @@ def main() -> None:
|
|||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logging.getLogger("pygls").setLevel(logging.WARNING)
|
logging.getLogger("pygls").setLevel(logging.WARNING)
|
||||||
CMakeLanguageServer().start_io()
|
CMakeLanguageServer().start_io() # type: ignore
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from typing import Iterable, Tuple
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from cmake_language_server.server import CMakeLanguageServer
|
from cmake_language_server.server import CMakeLanguageServer
|
||||||
from pygls import features
|
from pygls.lsp.methods import EXIT
|
||||||
from pygls.server import LanguageServer
|
from pygls.server import LanguageServer
|
||||||
|
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@ def client_server() -> Iterable[Tuple[LanguageServer, CMakeLanguageServer]]:
|
|||||||
# TODO: better patch is needed
|
# TODO: better patch is needed
|
||||||
# disable `close()` to avoid error messages
|
# disable `close()` to avoid error messages
|
||||||
close = ls.loop.close
|
close = ls.loop.close
|
||||||
ls.loop.close = lambda: None
|
ls.loop.close = lambda: None # type: ignore
|
||||||
ls.start_io(os.fdopen(fdr, "rb"), os.fdopen(fdw, "wb"))
|
ls.start_io(os.fdopen(fdr, "rb"), os.fdopen(fdw, "wb")) # type: ignore
|
||||||
ls.loop.close = close
|
ls.loop.close = close # type: ignore
|
||||||
|
|
||||||
server = CMakeLanguageServer(asyncio.new_event_loop())
|
server = CMakeLanguageServer(asyncio.new_event_loop())
|
||||||
server_thread = Thread(target=start, args=(server, c2s_r, s2c_w))
|
server_thread = Thread(target=start, args=(server, c2s_r, s2c_w))
|
||||||
@@ -56,7 +56,7 @@ def client_server() -> Iterable[Tuple[LanguageServer, CMakeLanguageServer]]:
|
|||||||
|
|
||||||
yield client, server
|
yield client, server
|
||||||
|
|
||||||
client.send_notification(features.EXIT)
|
client.send_notification(EXIT)
|
||||||
server.send_notification(features.EXIT)
|
server.send_notification(EXIT)
|
||||||
server_thread.join()
|
server_thread.join()
|
||||||
client_thread.join()
|
client_thread.join()
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Tuple
|
from typing import Any, Dict, Optional, Tuple
|
||||||
|
|
||||||
from cmake_language_server.server import CMakeLanguageServer
|
from cmake_language_server.server import CMakeLanguageServer
|
||||||
from pygls.features import (
|
from pygls.lsp.methods import (
|
||||||
COMPLETION,
|
COMPLETION,
|
||||||
FORMATTING,
|
FORMATTING,
|
||||||
HOVER,
|
HOVER,
|
||||||
INITIALIZE,
|
INITIALIZE,
|
||||||
TEXT_DOCUMENT_DID_OPEN,
|
TEXT_DOCUMENT_DID_OPEN,
|
||||||
)
|
)
|
||||||
from pygls.server import LanguageServer
|
from pygls.lsp.types import (
|
||||||
from pygls.types import (
|
ClientCapabilities,
|
||||||
CompletionContext,
|
CompletionContext,
|
||||||
CompletionList,
|
|
||||||
CompletionParams,
|
CompletionParams,
|
||||||
CompletionTriggerKind,
|
CompletionTriggerKind,
|
||||||
DidOpenTextDocumentParams,
|
DidOpenTextDocumentParams,
|
||||||
@@ -25,6 +24,7 @@ from pygls.types import (
|
|||||||
TextDocumentItem,
|
TextDocumentItem,
|
||||||
TextDocumentPositionParams,
|
TextDocumentPositionParams,
|
||||||
)
|
)
|
||||||
|
from pygls.server import LanguageServer
|
||||||
|
|
||||||
CALL_TIMEOUT = 2
|
CALL_TIMEOUT = 2
|
||||||
|
|
||||||
@@ -36,7 +36,9 @@ def _init(client: LanguageServer, root: Path) -> None:
|
|||||||
client.lsp.send_request(
|
client.lsp.send_request(
|
||||||
INITIALIZE,
|
INITIALIZE,
|
||||||
InitializeParams(
|
InitializeParams(
|
||||||
process_id=1234, root_uri=root.as_uri(), capabilities=None
|
process_id=1234,
|
||||||
|
root_uri=root.as_uri(),
|
||||||
|
capabilities=ClientCapabilities(),
|
||||||
),
|
),
|
||||||
).result(timeout=CALL_TIMEOUT)
|
).result(timeout=CALL_TIMEOUT)
|
||||||
except futures.TimeoutError:
|
except futures.TimeoutError:
|
||||||
@@ -52,7 +54,11 @@ def _open(client: LanguageServer, path: Path, text: Optional[str] = None) -> Non
|
|||||||
|
|
||||||
client.lsp.notify(
|
client.lsp.notify(
|
||||||
TEXT_DOCUMENT_DID_OPEN,
|
TEXT_DOCUMENT_DID_OPEN,
|
||||||
DidOpenTextDocumentParams(TextDocumentItem(path.as_uri(), "cmake", 1, text)),
|
DidOpenTextDocumentParams(
|
||||||
|
text_document=TextDocumentItem(
|
||||||
|
uri=path.as_uri(), language_id="cmake", version=1, text=text
|
||||||
|
)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -61,18 +67,22 @@ def _test_completion(
|
|||||||
datadir: Path,
|
datadir: Path,
|
||||||
content: str,
|
content: str,
|
||||||
context: Optional[CompletionContext],
|
context: Optional[CompletionContext],
|
||||||
) -> CompletionList:
|
) -> Dict[str, Any]:
|
||||||
client, server = client_server
|
client, server = client_server
|
||||||
_init(client, datadir)
|
_init(client, datadir)
|
||||||
path = datadir / "CMakeLists.txt"
|
path = datadir / "CMakeLists.txt"
|
||||||
_open(client, path, content)
|
_open(client, path, content)
|
||||||
params = CompletionParams(
|
params = CompletionParams(
|
||||||
TextDocumentIdentifier(path.as_uri()), Position(0, len(content)), context
|
text_document=TextDocumentIdentifier(uri=path.as_uri()),
|
||||||
|
position=Position(line=0, character=len(content)),
|
||||||
|
context=context,
|
||||||
)
|
)
|
||||||
if context is None:
|
if context is None:
|
||||||
# some clients do not send context
|
# some clients do not send context
|
||||||
del params.context
|
del params.context
|
||||||
return client.lsp.send_request(COMPLETION, params).result(timeout=CALL_TIMEOUT)
|
ret = client.lsp.send_request(COMPLETION, params).result(timeout=CALL_TIMEOUT)
|
||||||
|
assert isinstance(ret, dict)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def test_initialize(
|
def test_initialize(
|
||||||
@@ -92,20 +102,22 @@ def test_completions_invoked(
|
|||||||
client_server,
|
client_server,
|
||||||
datadir,
|
datadir,
|
||||||
"projec",
|
"projec",
|
||||||
CompletionContext(CompletionTriggerKind.Invoked),
|
CompletionContext(trigger_kind=CompletionTriggerKind.Invoked),
|
||||||
)
|
)
|
||||||
item = next(filter(lambda x: x.label == "project", response.items), None)
|
item = next(filter(lambda x: x["label"] == "project", response["items"]), None)
|
||||||
assert item is not None
|
assert item is not None
|
||||||
assert "<PROJECT-NAME>" in item.documentation
|
assert isinstance(item["documentation"], str)
|
||||||
|
assert "<PROJECT-NAME>" in item["documentation"]
|
||||||
|
|
||||||
|
|
||||||
def test_completions_nocontext(
|
def test_completions_nocontext(
|
||||||
client_server: Tuple[LanguageServer, CMakeLanguageServer], datadir: Path
|
client_server: Tuple[LanguageServer, CMakeLanguageServer], datadir: Path
|
||||||
) -> None:
|
) -> None:
|
||||||
response = _test_completion(client_server, datadir, "projec", None)
|
response = _test_completion(client_server, datadir, "projec", None)
|
||||||
item = next(filter(lambda x: x.label == "project", response.items), None)
|
item = next(filter(lambda x: x["label"] == "project", response["items"]), None)
|
||||||
assert item is not None
|
assert item is not None
|
||||||
assert "<PROJECT-NAME>" in item.documentation
|
assert isinstance(item["documentation"], str)
|
||||||
|
assert "<PROJECT-NAME>" in item["documentation"]
|
||||||
|
|
||||||
|
|
||||||
def test_completions_triggercharacter_variable(
|
def test_completions_triggercharacter_variable(
|
||||||
@@ -115,9 +127,11 @@ def test_completions_triggercharacter_variable(
|
|||||||
client_server,
|
client_server,
|
||||||
datadir,
|
datadir,
|
||||||
"${",
|
"${",
|
||||||
CompletionContext(CompletionTriggerKind.TriggerCharacter, "{"),
|
CompletionContext(
|
||||||
|
trigger_kind=CompletionTriggerKind.TriggerCharacter, trigger_character="{"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assert "PROJECT_VERSION" in [x.label for x in response.items]
|
assert "PROJECT_VERSION" in [x["label"] for x in response["items"]]
|
||||||
|
|
||||||
response_nocontext = _test_completion(client_server, datadir, "${", None)
|
response_nocontext = _test_completion(client_server, datadir, "${", None)
|
||||||
assert response == response_nocontext
|
assert response == response_nocontext
|
||||||
@@ -130,9 +144,11 @@ def test_completions_triggercharacter_module(
|
|||||||
client_server,
|
client_server,
|
||||||
datadir,
|
datadir,
|
||||||
"include(",
|
"include(",
|
||||||
CompletionContext(CompletionTriggerKind.TriggerCharacter, "("),
|
CompletionContext(
|
||||||
|
trigger_kind=CompletionTriggerKind.TriggerCharacter, trigger_character="("
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assert "GoogleTest" in [x.label for x in response.items]
|
assert "GoogleTest" in [x["label"] for x in response["items"]]
|
||||||
|
|
||||||
response_nocontext = _test_completion(client_server, datadir, "include(", None)
|
response_nocontext = _test_completion(client_server, datadir, "include(", None)
|
||||||
assert response == response_nocontext
|
assert response == response_nocontext
|
||||||
@@ -145,9 +161,11 @@ def test_completions_triggercharacter_package(
|
|||||||
client_server,
|
client_server,
|
||||||
datadir,
|
datadir,
|
||||||
"find_package(",
|
"find_package(",
|
||||||
CompletionContext(CompletionTriggerKind.TriggerCharacter, "("),
|
CompletionContext(
|
||||||
|
trigger_kind=CompletionTriggerKind.TriggerCharacter, trigger_character="("
|
||||||
|
),
|
||||||
)
|
)
|
||||||
assert "Boost" in [x.label for x in response.items]
|
assert "Boost" in [x["label"] for x in response["items"]]
|
||||||
|
|
||||||
response_nocontext = _test_completion(client_server, datadir, "find_package(", None)
|
response_nocontext = _test_completion(client_server, datadir, "find_package(", None)
|
||||||
assert response == response_nocontext
|
assert response == response_nocontext
|
||||||
@@ -163,10 +181,11 @@ def test_formatting(
|
|||||||
response = client.lsp.send_request(
|
response = client.lsp.send_request(
|
||||||
FORMATTING,
|
FORMATTING,
|
||||||
DocumentFormattingParams(
|
DocumentFormattingParams(
|
||||||
TextDocumentIdentifier(path.as_uri()), FormattingOptions(2, True)
|
text_document=TextDocumentIdentifier(uri=path.as_uri()),
|
||||||
|
options=FormattingOptions(tab_size=2, insert_spaces=True),
|
||||||
),
|
),
|
||||||
).result(timeout=CALL_TIMEOUT)
|
).result(timeout=CALL_TIMEOUT)
|
||||||
assert response[0].newText == "a(b c)\n"
|
assert response[0]["newText"] == "a(b c)\n"
|
||||||
|
|
||||||
|
|
||||||
def test_hover(
|
def test_hover(
|
||||||
@@ -178,6 +197,9 @@ def test_hover(
|
|||||||
_open(client, path, "project()")
|
_open(client, path, "project()")
|
||||||
response = client.lsp.send_request(
|
response = client.lsp.send_request(
|
||||||
HOVER,
|
HOVER,
|
||||||
TextDocumentPositionParams(TextDocumentIdentifier(path.as_uri()), Position()),
|
TextDocumentPositionParams(
|
||||||
|
text_document=TextDocumentIdentifier(uri=path.as_uri()),
|
||||||
|
position=Position(line=0, character=0),
|
||||||
|
),
|
||||||
).result(timeout=CALL_TIMEOUT)
|
).result(timeout=CALL_TIMEOUT)
|
||||||
assert "<PROJECT-NAME>" in response.contents.value
|
assert "<PROJECT-NAME>" in response["contents"]["value"]
|
||||||
|
|||||||
5
tox.ini
5
tox.ini
@@ -2,7 +2,6 @@
|
|||||||
isolated_build = True
|
isolated_build = True
|
||||||
skipsdist = True
|
skipsdist = True
|
||||||
envlist = py36, py37, py38, py39, lint
|
envlist = py36, py37, py38, py39, lint
|
||||||
allowlist_externals = git
|
|
||||||
|
|
||||||
[gh-actions]
|
[gh-actions]
|
||||||
python =
|
python =
|
||||||
@@ -12,7 +11,9 @@ python =
|
|||||||
3.9: py39
|
3.9: py39
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
whitelist_externals = poetry
|
allowlist_externals =
|
||||||
|
poetry
|
||||||
|
git
|
||||||
skip_install = true
|
skip_install = true
|
||||||
passenv = INCLUDE LIB LIBPATH Platform VCTools* VSCMD_* WindowsSDK*
|
passenv = INCLUDE LIB LIBPATH Platform VCTools* VSCMD_* WindowsSDK*
|
||||||
commands_pre =
|
commands_pre =
|
||||||
|
|||||||
Reference in New Issue
Block a user