chore(lsprotocol): migrate to 2025.0.0 and cleanup artifacts
The changes align the project with the 2025.0.0 lsprotocol release, removing the old backport and updating type hints in the protocol hooks to use Sequence where appropriate. The dist-info and packaging metadata for older lsprotocol versions are replaced with the new 2025.0.0 artifacts. - Remove exceptiongroup backport used on Python <3.11 - Use Sequence instead of List in LS protocol hooks - Replace old dist-info with 2025.0.0 metadata
This commit is contained in:
@@ -1,97 +1,11 @@
|
||||
from typing import List
|
||||
import warnings
|
||||
|
||||
from lsprotocol import types
|
||||
|
||||
from .workspace import Workspace
|
||||
from .text_document import TextDocument
|
||||
from .position_codec import PositionCodec
|
||||
|
||||
# For backwards compatibility
|
||||
Document = TextDocument
|
||||
|
||||
|
||||
def utf16_unit_offset(chars: str):
|
||||
warnings.warn(
|
||||
"'utf16_unit_offset' has been deprecated, instead use "
|
||||
"'PositionCodec.utf16_unit_offset' via 'workspace.position_codec' "
|
||||
"or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.utf16_unit_offset(chars)
|
||||
|
||||
|
||||
def utf16_num_units(chars: str):
|
||||
warnings.warn(
|
||||
"'utf16_num_units' has been deprecated, instead use "
|
||||
"'PositionCodec.client_num_units' via 'workspace.position_codec' "
|
||||
"or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.client_num_units(chars)
|
||||
|
||||
|
||||
def position_from_utf16(lines: List[str], position: types.Position):
|
||||
warnings.warn(
|
||||
"'position_from_utf16' has been deprecated, instead use "
|
||||
"'PositionCodec.position_from_client_units' via "
|
||||
"'workspace.position_codec' or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.position_from_client_units(lines, position)
|
||||
|
||||
|
||||
def position_to_utf16(lines: List[str], position: types.Position):
|
||||
warnings.warn(
|
||||
"'position_to_utf16' has been deprecated, instead use "
|
||||
"'PositionCodec.position_to_client_units' via "
|
||||
"'workspace.position_codec' or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.position_to_client_units(lines, position)
|
||||
|
||||
|
||||
def range_from_utf16(lines: List[str], range: types.Range):
|
||||
warnings.warn(
|
||||
"'range_from_utf16' has been deprecated, instead use "
|
||||
"'PositionCodec.range_from_client_units' via "
|
||||
"'workspace.position_codec' or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.range_from_client_units(lines, range)
|
||||
|
||||
|
||||
def range_to_utf16(lines: List[str], range: types.Range):
|
||||
warnings.warn(
|
||||
"'range_to_utf16' has been deprecated, instead use "
|
||||
"'PositionCodec.range_to_client_units' via 'workspace.position_codec' "
|
||||
"or 'text_document.position_codec'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_codec = PositionCodec()
|
||||
return _codec.range_to_client_units(lines, range)
|
||||
|
||||
from .position_codec import PositionCodec, ServerTextPosition, ServerTextRange
|
||||
|
||||
__all__ = (
|
||||
"Workspace",
|
||||
"TextDocument",
|
||||
"PositionCodec",
|
||||
"Document",
|
||||
"utf16_unit_offset",
|
||||
"utf16_num_units",
|
||||
"position_from_utf16",
|
||||
"position_to_utf16",
|
||||
"range_from_utf16",
|
||||
"range_to_utf16",
|
||||
"ServerTextPosition",
|
||||
"ServerTextRange",
|
||||
)
|
||||
|
||||
@@ -17,14 +17,113 @@
|
||||
# limitations under the License. #
|
||||
############################################################################
|
||||
import logging
|
||||
from typing import List, Optional, Union
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Union, Sequence, Any
|
||||
|
||||
from lsprotocol import types
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass(order=True)
|
||||
class ServerTextPosition:
|
||||
line: int
|
||||
character: int
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.line}:{self.character}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ServerTextRange:
|
||||
start: ServerTextPosition
|
||||
end: ServerTextPosition
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.start}-{self.end}"
|
||||
|
||||
def __contains__(self, position: Any) -> bool:
|
||||
if not isinstance(position, ServerTextPosition):
|
||||
raise TypeError("ServerTextRanges can only contain ServerTextPositions.")
|
||||
return self.start <= position <= self.end
|
||||
|
||||
def includes(self, inner: "ServerTextRange") -> bool:
|
||||
"""
|
||||
Returns whether `inner` is entirely contained within self, i.e. all
|
||||
positions in `inner` are also in `self`.
|
||||
"""
|
||||
return self.start <= inner.start and inner.end <= self.end
|
||||
|
||||
def overlaps(self, other: "ServerTextRange") -> bool:
|
||||
"""
|
||||
Returns whether `self` and `other` overlap, i.e. any positions exist that
|
||||
are included in both self and other.
|
||||
"""
|
||||
return self.start <= other.end and other.start <= self.end
|
||||
|
||||
|
||||
class UnitCounter:
|
||||
def code_units_for_char(self, char: str) -> int:
|
||||
"""
|
||||
Get the number of code units used to encode the given single character.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def num_units(self, chars: str) -> int:
|
||||
"""
|
||||
Get the number of code units used to encode the given string.
|
||||
"""
|
||||
return sum(self.code_units_for_char(c) for c in chars)
|
||||
|
||||
def column_from_utf32(self, line: str, column: int) -> int:
|
||||
"""
|
||||
Convert the codepoint index `column` into code units.
|
||||
"""
|
||||
return sum(self.code_units_for_char(c) for c in line[:column])
|
||||
|
||||
|
||||
class Utf32(UnitCounter):
|
||||
def code_units_for_char(self, char: str) -> int:
|
||||
return 1
|
||||
|
||||
def num_units(self, chars: str) -> int:
|
||||
# We can avoid the loop needed for other encodings here
|
||||
return len(chars)
|
||||
|
||||
def column_from_utf32(self, line: str, column: int) -> int:
|
||||
return column
|
||||
|
||||
|
||||
def is_beyond_basic_multilingual_plane(char: str) -> bool:
|
||||
return ord(char) > 0xFFFF
|
||||
|
||||
|
||||
class Utf16(UnitCounter):
|
||||
def code_units_for_char(self, char: str) -> int:
|
||||
if is_beyond_basic_multilingual_plane(char):
|
||||
return 2
|
||||
return 1
|
||||
|
||||
|
||||
class Utf8(UnitCounter):
|
||||
def code_units_for_char(self, char: str) -> int:
|
||||
codepoint = ord(char)
|
||||
if codepoint < 0x80:
|
||||
return 1
|
||||
if codepoint < 0x800:
|
||||
return 2
|
||||
if codepoint < 0x10000:
|
||||
return 3
|
||||
return 4
|
||||
|
||||
|
||||
impls: dict["str | types.PositionEncodingKind | None", UnitCounter] = {
|
||||
types.PositionEncodingKind.Utf8: Utf8(),
|
||||
types.PositionEncodingKind.Utf16: Utf16(),
|
||||
types.PositionEncodingKind.Utf32: Utf32(),
|
||||
}
|
||||
|
||||
|
||||
class PositionCodec:
|
||||
def __init__(
|
||||
self,
|
||||
@@ -33,39 +132,17 @@ class PositionCodec:
|
||||
] = types.PositionEncodingKind.Utf16,
|
||||
):
|
||||
self.encoding = encoding
|
||||
self.impl = impls.get(encoding, Utf16())
|
||||
|
||||
@classmethod
|
||||
def is_char_beyond_multilingual_plane(cls, char: str) -> bool:
|
||||
return ord(char) > 0xFFFF
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__}, encoding {self.encoding}>"
|
||||
|
||||
def utf16_unit_offset(self, chars: str):
|
||||
"""
|
||||
Calculate the number of characters which need two utf-16 code units.
|
||||
|
||||
Arguments:
|
||||
chars (str): The string to count occurrences of utf-16 code units for.
|
||||
"""
|
||||
return sum(self.is_char_beyond_multilingual_plane(ch) for ch in chars)
|
||||
|
||||
def client_num_units(self, chars: str):
|
||||
"""
|
||||
Calculate the length of `str` in client-supported UTF-[32|16|8] code units.
|
||||
|
||||
Arguments:
|
||||
chars (str): The string to return the length in UTF-[32|16|8] code units for.
|
||||
"""
|
||||
utf32_units = len(chars)
|
||||
if self.encoding == types.PositionEncodingKind.Utf32:
|
||||
return utf32_units
|
||||
|
||||
if self.encoding == types.PositionEncodingKind.Utf8:
|
||||
return utf32_units + (self.utf16_unit_offset(chars) * 2)
|
||||
|
||||
return utf32_units + self.utf16_unit_offset(chars)
|
||||
def client_num_units(self, string: str):
|
||||
return self.impl.num_units(string)
|
||||
|
||||
def position_from_client_units(
|
||||
self, lines: List[str], position: types.Position
|
||||
) -> types.Position:
|
||||
self, lines: Sequence[str], position: types.Position
|
||||
) -> ServerTextPosition:
|
||||
"""
|
||||
Convert the position.character from UTF-[32|16|8] code units to UTF-32.
|
||||
|
||||
@@ -84,7 +161,7 @@ class PositionCodec:
|
||||
see: https://github.com/microsoft/language-server-protocol/issues/376
|
||||
|
||||
Arguments:
|
||||
lines (list):
|
||||
lines (sequence):
|
||||
The content of the document which the position refers to.
|
||||
position (Position):
|
||||
The line and character offset in UTF-[32|16|8] code units.
|
||||
@@ -93,59 +170,42 @@ class PositionCodec:
|
||||
The position with `character` being converted to UTF-32 code units.
|
||||
"""
|
||||
if len(lines) == 0:
|
||||
return types.Position(0, 0)
|
||||
return ServerTextPosition(0, 0)
|
||||
if position.line >= len(lines):
|
||||
return types.Position(len(lines) - 1, self.client_num_units(lines[-1]))
|
||||
return ServerTextPosition(len(lines) - 1, self.impl.num_units(lines[-1]))
|
||||
|
||||
_line = lines[position.line]
|
||||
_line = _line.replace("\r\n", "\n") # TODO: it's a bit of a hack
|
||||
_client_len = self.client_num_units(_line)
|
||||
_utf32_len = len(_line)
|
||||
_client_len = self.impl.num_units(_line)
|
||||
|
||||
if _client_len == 0:
|
||||
return types.Position(position.line, 0)
|
||||
return ServerTextPosition(position.line, 0)
|
||||
|
||||
_client_end_of_line = self.client_num_units(_line)
|
||||
if position.character > _client_end_of_line:
|
||||
position.character = _client_end_of_line - 1
|
||||
if position.character > _client_len:
|
||||
position.character = _client_len - 1
|
||||
|
||||
_client_index = 0
|
||||
client_position = 0
|
||||
utf32_index = 0
|
||||
while True:
|
||||
_is_searching_queried_position = _client_index < position.character
|
||||
_is_before_end_of_line = utf32_index < _utf32_len
|
||||
_is_searching_for_position = (
|
||||
_is_searching_queried_position and _is_before_end_of_line
|
||||
)
|
||||
if not _is_searching_for_position:
|
||||
for c in _line:
|
||||
if client_position >= position.character:
|
||||
break
|
||||
|
||||
_current_char = _line[utf32_index]
|
||||
_is_double_width = PositionCodec.is_char_beyond_multilingual_plane(
|
||||
_current_char
|
||||
)
|
||||
if _is_double_width:
|
||||
if self.encoding == types.PositionEncodingKind.Utf32:
|
||||
_client_index += 1
|
||||
if self.encoding == types.PositionEncodingKind.Utf8:
|
||||
_client_index += 4
|
||||
_client_index += 2
|
||||
else:
|
||||
_client_index += 1
|
||||
client_position += self.impl.code_units_for_char(c)
|
||||
utf32_index += 1
|
||||
|
||||
position = types.Position(line=position.line, character=utf32_index)
|
||||
return position
|
||||
if client_position < position.character:
|
||||
utf32_index = len(_line)
|
||||
|
||||
return ServerTextPosition(line=position.line, character=utf32_index)
|
||||
|
||||
def position_to_client_units(
|
||||
self, lines: List[str], position: types.Position
|
||||
self, lines: Sequence[str], position: "ServerTextPosition | types.Position"
|
||||
) -> types.Position:
|
||||
"""
|
||||
Convert the position.character from its internal UTF-32 representation
|
||||
to client-supported UTF-[32|16|8] code units.
|
||||
|
||||
Arguments:
|
||||
lines (list):
|
||||
lines (sequence):
|
||||
The content of the document which the position refers to.
|
||||
position (Position):
|
||||
The line and character offset in UTF-32 code units.
|
||||
@@ -154,9 +214,7 @@ class PositionCodec:
|
||||
The position with `character` being converted to UTF-[32|16|8] code units.
|
||||
"""
|
||||
try:
|
||||
character = self.client_num_units(
|
||||
lines[position.line][: position.character]
|
||||
)
|
||||
character = self.impl.num_units(lines[position.line][: position.character])
|
||||
return types.Position(
|
||||
line=position.line,
|
||||
character=character,
|
||||
@@ -165,13 +223,13 @@ class PositionCodec:
|
||||
return types.Position(line=len(lines), character=0)
|
||||
|
||||
def range_from_client_units(
|
||||
self, lines: List[str], range: types.Range
|
||||
) -> types.Range:
|
||||
self, lines: Sequence[str], range: types.Range
|
||||
) -> ServerTextRange:
|
||||
"""
|
||||
Convert range.[start|end].character from UTF-[32|16|8] code units to UTF-32.
|
||||
|
||||
Arguments:
|
||||
lines (list):
|
||||
lines (sequence):
|
||||
The content of the document which the range refers to.
|
||||
range (Range):
|
||||
The line and character offset in UTF-[32|16|8] code units.
|
||||
@@ -179,26 +237,25 @@ class PositionCodec:
|
||||
Returns:
|
||||
The range with `character` offsets being converted to UTF-32 code units.
|
||||
"""
|
||||
range_new = types.Range(
|
||||
return ServerTextRange(
|
||||
start=self.position_from_client_units(lines, range.start),
|
||||
end=self.position_from_client_units(lines, range.end),
|
||||
)
|
||||
return range_new
|
||||
|
||||
def range_to_client_units(
|
||||
self, lines: List[str], range: types.Range
|
||||
self, lines: Sequence[str], range: "ServerTextRange | types.Range"
|
||||
) -> types.Range:
|
||||
"""
|
||||
Convert range.[start|end].character from UTF-32 to UTF-[32|16|8] code units.
|
||||
|
||||
Arguments:
|
||||
lines (list):
|
||||
lines (sequence):
|
||||
The content of the document which the range refers to.
|
||||
range (Range):
|
||||
The line and character offset in code units.
|
||||
The line and character offset in code points.
|
||||
|
||||
Returns:
|
||||
The range with `character` offsets being converted to UTF-[32|16|8] code units.
|
||||
The range with `character` offsets converted to UTF-[32|16|8] code units.
|
||||
"""
|
||||
return types.Range(
|
||||
start=self.position_to_client_units(lines, range.start),
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
from typing import List, Optional, Pattern
|
||||
from typing import Optional, Pattern, Sequence
|
||||
|
||||
from lsprotocol import types
|
||||
|
||||
from pygls.uris import to_fs_path
|
||||
from .position_codec import PositionCodec
|
||||
from pygls.uris import urlparse, to_fs_path
|
||||
from .position_codec import PositionCodec, ServerTextPosition, ServerTextRange
|
||||
|
||||
# TODO: this is not the best e.g. we capture numbers
|
||||
RE_END_WORD = re.compile("^[A-Za-z_0-9]*")
|
||||
@@ -47,9 +48,10 @@ class TextDocument(object):
|
||||
):
|
||||
self.uri = uri
|
||||
self.version = version
|
||||
path = to_fs_path(uri)
|
||||
if path is None:
|
||||
raise Exception("`path` cannot be None")
|
||||
|
||||
if (path := to_fs_path(uri)) is None:
|
||||
_, _, path, *_ = urlparse(uri)
|
||||
|
||||
self.path = path
|
||||
self.language_id = language_id
|
||||
self.filename: Optional[str] = os.path.basename(self.path)
|
||||
@@ -73,7 +75,7 @@ class TextDocument(object):
|
||||
return self._position_codec
|
||||
|
||||
def _apply_incremental_change(
|
||||
self, change: types.TextDocumentContentChangeEvent_Type1
|
||||
self, change: types.TextDocumentContentChangePartial
|
||||
) -> None:
|
||||
"""Apply an ``Incremental`` text change to the document"""
|
||||
lines = self.lines
|
||||
@@ -142,7 +144,7 @@ class TextDocument(object):
|
||||
content update client requests in the pygls Python library.
|
||||
|
||||
"""
|
||||
if isinstance(change, types.TextDocumentContentChangeEvent_Type1):
|
||||
if isinstance(change, types.TextDocumentContentChangePartial):
|
||||
if self._is_sync_kind_incremental:
|
||||
self._apply_incremental_change(change)
|
||||
return
|
||||
@@ -161,26 +163,101 @@ class TextDocument(object):
|
||||
self._apply_full_change(change)
|
||||
|
||||
@property
|
||||
def lines(self) -> List[str]:
|
||||
return self.source.splitlines(True)
|
||||
def lines(self) -> Sequence[str]:
|
||||
return tuple(self.source.splitlines(True))
|
||||
|
||||
def offset_at_server_position(self, server_position: ServerTextPosition) -> int:
|
||||
"""
|
||||
Convert server_position to an index into self.source.
|
||||
|
||||
The index is the number of code points preceding the client_position in self.source.
|
||||
"""
|
||||
row, col = server_position.line, server_position.character
|
||||
return col + sum(len(line) for line in self.lines[:row])
|
||||
|
||||
def offset_at_position(self, client_position: types.Position) -> int:
|
||||
"""Return the character offset pointed at by the given client_position."""
|
||||
"""
|
||||
Convert client_position to an index into self.source.
|
||||
|
||||
The index is the number of code points preceding the client_position in self.source.
|
||||
|
||||
Example in a code action request handler:
|
||||
selected_string = document.source[
|
||||
document.offset_at_position(params.range.start) : document.offset_at_position(params.range.end)
|
||||
]
|
||||
"""
|
||||
lines = self.lines
|
||||
server_position = self._position_codec.position_from_client_units(
|
||||
lines, client_position
|
||||
)
|
||||
row, col = server_position.line, server_position.character
|
||||
return col + sum(
|
||||
self._position_codec.client_num_units(line) for line in lines[:row]
|
||||
)
|
||||
return self.offset_at_server_position(server_position)
|
||||
|
||||
def server_position_at_offset(self, offset: int) -> ServerTextPosition:
|
||||
"""
|
||||
Convert a numeric character offset (index into self.source) into a line-column position.
|
||||
"""
|
||||
remaining_offset = offset
|
||||
for lineno, line in enumerate(self.lines):
|
||||
if remaining_offset < len(line):
|
||||
return ServerTextPosition(lineno, remaining_offset)
|
||||
remaining_offset -= len(line)
|
||||
# The desired position is beyond the end of the last line.
|
||||
return ServerTextPosition(lineno + 1, 0)
|
||||
|
||||
def client_position_at_offset(self, offset: int) -> types.Position:
|
||||
"""
|
||||
Convert a numeric character offset (index into self.source) into a line-column position in client units.
|
||||
"""
|
||||
return self.position_to_client_units(self.server_position_at_offset(offset))
|
||||
|
||||
def range_from_client_units(self, range: types.Range) -> ServerTextRange:
|
||||
"""
|
||||
Convert a range from client units into code points, suitable for indexing into `self.lines`.
|
||||
"""
|
||||
return self.position_codec.range_from_client_units(self.lines, range)
|
||||
|
||||
def position_from_client_units(
|
||||
self, position: types.Position
|
||||
) -> ServerTextPosition:
|
||||
"""
|
||||
Convert a position from client units into code points, suitable for indexing into `self.lines`.
|
||||
"""
|
||||
return self.position_codec.position_from_client_units(self.lines, position)
|
||||
|
||||
def range_to_client_units(self, range: ServerTextRange) -> types.Range:
|
||||
"""
|
||||
Convert a range from code points into client units, suitable for sending to the client.
|
||||
"""
|
||||
return self.position_codec.range_to_client_units(self.lines, range)
|
||||
|
||||
def position_to_client_units(self, position: ServerTextPosition) -> types.Position:
|
||||
"""
|
||||
Convert a position from code points into client units, suitable for sending to the client.
|
||||
"""
|
||||
return self.position_codec.position_to_client_units(self.lines, position)
|
||||
|
||||
def text_in_client_range(self, range: types.Range) -> str:
|
||||
"""
|
||||
Given a range in client units, return the text in this range in this document.
|
||||
"""
|
||||
return self.text_in_server_range(self.range_from_client_units(range))
|
||||
|
||||
def text_in_server_range(self, range: ServerTextRange) -> str:
|
||||
"""
|
||||
Given a range in server units, return the text in this range in this document.
|
||||
"""
|
||||
return self.source[
|
||||
self.offset_at_server_position(
|
||||
range.start
|
||||
) : self.offset_at_server_position(range.end)
|
||||
]
|
||||
|
||||
@property
|
||||
def source(self) -> str:
|
||||
if self._source is None:
|
||||
with io.open(self.path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
return self._source
|
||||
if self._source is None and self.path is not None:
|
||||
return pathlib.Path(self.path).read_text(encoding="utf-8")
|
||||
|
||||
return self._source or ""
|
||||
|
||||
def word_at_position(
|
||||
self,
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
import warnings
|
||||
from typing import Dict, List, Optional, Union
|
||||
from typing import Dict, Optional, Sequence, Union
|
||||
from urllib.parse import unquote
|
||||
|
||||
from lsprotocol import types
|
||||
from lsprotocol.types import (
|
||||
@@ -40,7 +40,7 @@ class Workspace(object):
|
||||
self,
|
||||
root_uri: Optional[str],
|
||||
sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental,
|
||||
workspace_folders: Optional[List[WorkspaceFolder]] = None,
|
||||
workspace_folders: Optional[Sequence[WorkspaceFolder]] = None,
|
||||
position_encoding: Optional[
|
||||
Union[PositionEncodingKind, str]
|
||||
] = PositionEncodingKind.Utf16,
|
||||
@@ -48,10 +48,7 @@ class Workspace(object):
|
||||
self._root_uri = root_uri
|
||||
if self._root_uri is not None:
|
||||
self._root_uri_scheme = uri_scheme(self._root_uri)
|
||||
root_path = to_fs_path(self._root_uri)
|
||||
if root_path is None:
|
||||
raise Exception("Couldn't get `root_path` from `root_uri`")
|
||||
self._root_path = root_path
|
||||
self._root_path = to_fs_path(self._root_uri)
|
||||
else:
|
||||
self._root_path = None
|
||||
self._sync_kind = sync_kind
|
||||
@@ -94,17 +91,7 @@ class Workspace(object):
|
||||
)
|
||||
|
||||
def add_folder(self, folder: WorkspaceFolder):
|
||||
self._folders[folder.uri] = folder
|
||||
|
||||
@property
|
||||
def documents(self):
|
||||
warnings.warn(
|
||||
"'workspace.documents' has been deprecated, use "
|
||||
"'workspace.text_documents' instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.text_documents
|
||||
self._folders[unquote(folder.uri)] = folder
|
||||
|
||||
@property
|
||||
def notebook_documents(self):
|
||||
@@ -141,10 +128,10 @@ class Workspace(object):
|
||||
The requested notebook document if found, ``None`` otherwise.
|
||||
"""
|
||||
if notebook_uri is not None:
|
||||
return self._notebook_documents.get(notebook_uri)
|
||||
return self._notebook_documents.get(unquote(notebook_uri))
|
||||
|
||||
if cell_uri is not None:
|
||||
notebook_uri = self._cell_in_notebook.get(cell_uri)
|
||||
notebook_uri = self._cell_in_notebook.get(unquote(cell_uri))
|
||||
if notebook_uri is None:
|
||||
return None
|
||||
|
||||
@@ -159,18 +146,25 @@ class Workspace(object):
|
||||
|
||||
See https://github.com/Microsoft/language-server-protocol/issues/177
|
||||
"""
|
||||
return self._text_documents.get(doc_uri) or self._create_text_document(doc_uri)
|
||||
return self._text_documents.get(unquote(doc_uri)) or self._create_text_document(
|
||||
doc_uri
|
||||
)
|
||||
|
||||
def is_local(self):
|
||||
return (
|
||||
self._root_uri_scheme == "" or self._root_uri_scheme == "file"
|
||||
) and os.path.exists(self._root_path)
|
||||
|
||||
if self._root_uri_scheme not in {"", "file"}:
|
||||
return False
|
||||
|
||||
if (path := self._root_path) is None:
|
||||
return False
|
||||
|
||||
return os.path.exists(path)
|
||||
|
||||
def put_notebook_document(self, params: types.DidOpenNotebookDocumentParams):
|
||||
notebook = params.notebook_document
|
||||
|
||||
# Create a fresh instance to ensure our copy cannot be accidentally modified.
|
||||
self._notebook_documents[notebook.uri] = copy.deepcopy(notebook)
|
||||
self._notebook_documents[unquote(notebook.uri)] = copy.deepcopy(notebook)
|
||||
|
||||
for cell_document in params.cell_text_documents:
|
||||
self.put_text_document(cell_document, notebook_uri=notebook.uri)
|
||||
@@ -193,7 +187,7 @@ class Workspace(object):
|
||||
"""
|
||||
doc_uri = text_document.uri
|
||||
|
||||
self._text_documents[doc_uri] = self._create_text_document(
|
||||
self._text_documents[unquote(doc_uri)] = self._create_text_document(
|
||||
doc_uri,
|
||||
source=text_document.text,
|
||||
version=text_document.version,
|
||||
@@ -201,23 +195,23 @@ class Workspace(object):
|
||||
)
|
||||
|
||||
if notebook_uri:
|
||||
self._cell_in_notebook[doc_uri] = notebook_uri
|
||||
self._cell_in_notebook[unquote(doc_uri)] = unquote(notebook_uri)
|
||||
|
||||
def remove_notebook_document(self, params: types.DidCloseNotebookDocumentParams):
|
||||
notebook_uri = params.notebook_document.uri
|
||||
self._notebook_documents.pop(notebook_uri, None)
|
||||
self._notebook_documents.pop(unquote(notebook_uri), None)
|
||||
|
||||
for cell_document in params.cell_text_documents:
|
||||
self.remove_text_document(cell_document.uri)
|
||||
|
||||
def remove_text_document(self, doc_uri: str):
|
||||
self._text_documents.pop(doc_uri, None)
|
||||
self._cell_in_notebook.pop(doc_uri, None)
|
||||
self._text_documents.pop(unquote(doc_uri), None)
|
||||
self._cell_in_notebook.pop(unquote(doc_uri), None)
|
||||
|
||||
def remove_folder(self, folder_uri: str):
|
||||
self._folders.pop(folder_uri, None)
|
||||
self._folders.pop(unquote(folder_uri), None)
|
||||
try:
|
||||
del self._folders[folder_uri]
|
||||
del self._folders[unquote(folder_uri)]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
@@ -231,7 +225,7 @@ class Workspace(object):
|
||||
|
||||
def update_notebook_document(self, params: types.DidChangeNotebookDocumentParams):
|
||||
uri = params.notebook_document.uri
|
||||
notebook = self._notebook_documents[uri]
|
||||
notebook = self._notebook_documents[unquote(uri)]
|
||||
notebook.version = params.notebook_document.version
|
||||
|
||||
if params.change.metadata:
|
||||
@@ -283,41 +277,5 @@ class Workspace(object):
|
||||
change: types.TextDocumentContentChangeEvent,
|
||||
):
|
||||
doc_uri = text_doc.uri
|
||||
self._text_documents[doc_uri].apply_change(change)
|
||||
self._text_documents[doc_uri].version = text_doc.version
|
||||
|
||||
def get_document(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"'workspace.get_document' has been deprecated, use "
|
||||
"'workspace.get_text_document' instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.get_text_document(*args, **kwargs)
|
||||
|
||||
def remove_document(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"'workspace.remove_document' has been deprecated, use "
|
||||
"'workspace.remove_text_document' instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.remove_text_document(*args, **kwargs)
|
||||
|
||||
def put_document(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"'workspace.put_document' has been deprecated, use "
|
||||
"'workspace.put_text_document' instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.put_text_document(*args, **kwargs)
|
||||
|
||||
def update_document(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"'workspace.update_document' has been deprecated, use "
|
||||
"'workspace.update_text_document' instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.update_text_document(*args, **kwargs)
|
||||
self._text_documents[unquote(doc_uri)].apply_change(change)
|
||||
self._text_documents[unquote(doc_uri)].version = text_doc.version
|
||||
|
||||
Reference in New Issue
Block a user