Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move 'SymbolInformation' to pydantic and add support for newer 'Docum… #42

Merged
merged 2 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions pylspclient/lsp_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pydantic import ValidationError
from pylspclient import lsp_structs
from pylspclient.lsp_pydantic_strcuts import TextDocumentItem
from pylspclient.lsp_pydantic_strcuts import TextDocumentItem, TextDocumentIdentifier, DocumentSymbol, SymbolInformation

class LspClient(object):
def __init__(self, lsp_endpoint):
Expand Down Expand Up @@ -100,15 +101,18 @@ def didChange(self, textDocument, contentChanges):
return self.lsp_endpoint.send_notification("textDocument/didChange", textDocument=textDocument, contentChanges=contentChanges)


def documentSymbol(self, textDocument):
def documentSymbol(self, textDocument: TextDocumentIdentifier) -> list[DocumentSymbol] | list[SymbolInformation]:
"""
The document symbol request is sent from the client to the server to return a flat list of all symbols found in a given text document.
Neither the symbol's location range nor the symbol's container name should be used to infer a hierarchy.

:param TextDocumentItem textDocument: The text document.
"""
result_dict = self.lsp_endpoint.call_method("textDocument/documentSymbol", textDocument=textDocument)
return [lsp_structs.SymbolInformation(**sym) for sym in result_dict]
result_dict = self.lsp_endpoint.call_method("textDocument/documentSymbol", textDocument=textDocument.dict())
try:
return [DocumentSymbol.parse_obj(sym) for sym in result_dict]
except ValidationError:
return [SymbolInformation.parse_obj(sym) for sym in result_dict]


def typeDefinition(self, textDocument, position):
Expand Down
81 changes: 80 additions & 1 deletion pylspclient/lsp_pydantic_strcuts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from enum import Enum
from typing import Optional, List
from enum import Enum, IntEnum
from pydantic import BaseModel


Expand Down Expand Up @@ -67,3 +68,81 @@ class TextDocumentItem(BaseModel):
languageId: LanguageIdentifier
version: int
text: str

class TextDocumentIdentifier(BaseModel):
"""
Identifies a text document using its URI.
"""
uri: str

class Position(BaseModel):
"""Represents a position in a text document."""
line: int
character: int

class Range(BaseModel):
"""Defines a range in a text document."""
start: Position
end: Position

class Location(BaseModel):
"""Represents a location inside a resource, such as a line inside a text file."""
uri: str
range: Range

class SymbolKind(IntEnum):
"""Represents various symbol kinds like File, Module, Namespace, Package, Class, Method, etc."""
File = 1
Module = 2
Namespace = 3
Package = 4
Class = 5
Method = 6
Property = 7
Field = 8
Constructor = 9
Enum = 10
Interface = 11
Function = 12
Variable = 13
Constant = 14
String = 15
Number = 16
Boolean = 17
Array = 18
Object = 19
Key = 20
Null = 21
EnumMember = 22
Struct = 23
Event = 24
Operator = 25
TypeParameter = 26

class SymbolTag(Enum):
"""Represents additional information about the symbol."""
# Define the symbol tags as per your specification, for example:
Deprecated = 1

class DocumentSymbol(BaseModel):
"""
Represents information about programming constructs like variables, classes, interfaces etc.
"""
name: str
detail: Optional[str] = None
kind: SymbolKind
tags: Optional[List[SymbolTag]] = None
deprecated: Optional[bool] = None
range: Range
selectionRange: Range
children: Optional[List['DocumentSymbol']] = None

class SymbolInformation(BaseModel):
"""
Represents information about programming constructs like variables, classes, interfaces, etc.
"""
name: str
kind: SymbolKind
deprecated: Optional[bool] = None
location: Location
containerName: Optional[str] = None
113 changes: 0 additions & 113 deletions pylspclient/lsp_structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,119 +216,6 @@ def __init__(self, textDocument, position):
self.position = position


class LANGUAGE_IDENTIFIER(object):
BAT="bat"
BIBTEX="bibtex"
CLOJURE="clojure"
COFFESCRIPT="coffeescript"
C="c"
CPP="cpp"
CSHARP="csharp"
CSS="css"
DIFF="diff"
DOCKERFILE="dockerfile"
FSHARP="fsharp"
GIT_COMMIT="git-commit"
GIT_REBASE="git-rebase"
GO="go"
GROOVY="groovy"
HANDLEBARS="handlebars"
HTML="html"
INI="ini"
JAVA="java"
JAVASCRIPT="javascript"
JSON="json"
LATEX="latex"
LESS="less"
LUA="lua"
MAKEFILE="makefile"
MARKDOWN="markdown"
OBJECTIVE_C="objective-c"
OBJECTIVE_CPP="objective-cpp"
Perl="perl"
PHP="php"
POWERSHELL="powershell"
PUG="jade"
PYTHON="python"
R="r"
RAZOR="razor"
RUBY="ruby"
RUST="rust"
SASS="sass"
SCSS="scss"
ShaderLab="shaderlab"
SHELL_SCRIPT="shellscript"
SQL="sql"
SWIFT="swift"
TYPE_SCRIPT="typescript"
TEX="tex"
VB="vb"
XML="xml"
XSL="xsl"
YAML="yaml"


class SymbolKind(enum.Enum):
File = 1
Module = 2
Namespace = 3
Package = 4
Class = 5
Method = 6
Property = 7
Field = 8
Constructor = 9
Enum = 10
Interface = 11
Function = 12
Variable = 13
Constant = 14
String = 15
Number = 16
Boolean = 17
Array = 18
Object = 19
Key = 20
Null = 21
EnumMember = 22
Struct = 23
Event = 24
Operator = 25
TypeParameter = 26


class SymbolInformation(object):
"""
Represents information about programming constructs like variables, classes, interfaces etc.
"""
def __init__(self, name, kind, location, containerName=None, deprecated=False):
"""
Constructs a new SymbolInformation instance.

:param str name: The name of this symbol.
:param int kind: The kind of this symbol.
:param bool Location: The location of this symbol. The location's range is used by a tool
to reveal the location in the editor. If the symbol is selected in the
tool the range's start information is used to position the cursor. So
the range usually spans more then the actual symbol's name and does
normally include things like visibility modifiers.

The range doesn't have to denote a node range in the sense of a abstract
syntax tree. It can therefore not be used to re-construct a hierarchy of
the symbols.
:param str containerName: The name of the symbol containing this symbol. This information is for
user interface purposes (e.g. to render a qualifier in the user interface
if necessary). It can't be used to re-infer a hierarchy for the document
symbols.
:param bool deprecated: Indicates if this symbol is deprecated.
"""
self.name = name
self.kind = SymbolKind(kind)
self.deprecated = deprecated
self.location = to_type(location, Location)
self.containerName = containerName


class ParameterInformation(object):
"""
Represents a parameter of a callable-signature. A parameter can
Expand Down
8 changes: 4 additions & 4 deletions tests/test_pylsp_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import threading

import pylspclient
from pylspclient.lsp_pydantic_strcuts import TextDocumentItem
from pylspclient.lsp_pydantic_strcuts import TextDocumentIdentifier, TextDocumentItem, LanguageIdentifier


def to_uri(path: str) -> str:
Expand Down Expand Up @@ -94,13 +94,13 @@ def test_type_definition(lsp_client: pylspclient.LspClient):
relative_file_path = os.path.join(DEFAULT_ROOT, file_path)
uri = to_uri(relative_file_path)
text = open(relative_file_path, "r").read()
languageId = pylspclient.lsp_structs.LANGUAGE_IDENTIFIER.PYTHON
languageId = LanguageIdentifier.PYTHON
version = 1
# First need to open the file, and then iterate over the docuemnt's symbols
symbols = lsp_client.documentSymbol(pylspclient.lsp_structs.TextDocumentIdentifier(uri))
symbols = lsp_client.documentSymbol(TextDocumentIdentifier(uri=uri))
assert set(symbol.name for symbol in symbols) == set([])
lsp_client.didOpen(TextDocumentItem(uri=uri, languageId=languageId, version=version, text=text))
symbols = lsp_client.documentSymbol(pylspclient.lsp_structs.TextDocumentIdentifier(uri))
symbols = lsp_client.documentSymbol(TextDocumentIdentifier(uri=uri))
expected_symbols = [
'__init__',
'declaration',
Expand Down