Commit 9038b381 authored by Eckhart Arnold's avatar Eckhart Arnold
Browse files

type errors fixed

parent c377e766
......@@ -50,3 +50,4 @@ OLDSTUFF
docs/*
**/node_modules
*.py.cfg
examples/LaTeX/testdata/*.xml
No preview for this file type
......@@ -130,7 +130,7 @@ class Compiler:
self._dirty_flag = False
self._debug = get_config_value('debug_compiler') # type: bool
self._debug_already_compiled = set() # type: Set[Node]
self.finalizers = [] # type: List[Callable, Tuple]
self.finalizers = [] # type: List[Tuple[Callable, Tuple]]
def prepare(self) -> None:
"""
......@@ -172,7 +172,7 @@ class Compiler:
"""This is a generic compiler function which will be called on
all those node types for which no compiler method `on_XXX` has
been defined."""
children = node.children
children = node.children # type: Tuple[Node, ...]
if children:
node.result = tuple(self.compile(nd) for nd in children)
return node
......
......@@ -15,13 +15,12 @@
# implied. See the License for the specific language governing
# permissions and limitations under the License.
"""
Module ``dsl`` contains various functions to support the
compilation of domain specific languages based on an EBNF-grammar.
"""
import inspect
import os
import platform
import stat
......@@ -144,7 +143,8 @@ def grammar_instance(grammar_representation) -> Tuple[Grammar, str]:
# read grammar
grammar_src = load_if_file(grammar_representation)
if is_python_code(grammar_src):
parser_py, messages = grammar_src, [] # type: str, List[Error]
parser_py = grammar_src # type: str
messages = [] # type: List[Error]
else:
log_dir = suspend_logging()
result, messages, _ = compile_source(
......@@ -154,7 +154,11 @@ def grammar_instance(grammar_representation) -> Tuple[Grammar, str]:
resume_logging(log_dir)
if has_errors(messages):
raise DefinitionError(only_errors(messages), grammar_src)
parser_root = compile_python_object(DHPARSER_IMPORTS + parser_py, r'\w+Grammar$')()
grammar_class = compile_python_object(DHPARSER_IMPORTS + parser_py, r'\w+Grammar$')
if inspect.isclass(grammar_class) and issubclass(grammar_class, Grammar):
parser_root = grammar_class()
else:
raise ValueError('Could not compile or Grammar class!')
else:
# assume that dsl_grammar is a ParserHQ-object or Grammar class
grammar_src = ''
......@@ -241,7 +245,7 @@ def compileEBNF(ebnf_src: str, branding="DSL") -> str:
return '\n'.join(src)
def grammar_provider(ebnf_src: str, branding="DSL") -> Grammar:
def grammar_provider(ebnf_src: str, branding="DSL") -> ParserFactoryFunc:
"""
Compiles an EBNF-grammar and returns a grammar-parser provider
function for that grammar.
......@@ -266,8 +270,10 @@ def grammar_provider(ebnf_src: str, branding="DSL") -> Grammar:
print(grammar_src)
grammar_factory = compile_python_object(DHPARSER_IMPORTS + grammar_src,
r'get_(?:\w+_)?grammar$')
grammar_factory.python_src__ = grammar_src
return grammar_factory
if isinstance(grammar_factory, Callable):
grammar_factory.python_src__ = grammar_src
return grammar_factory
raise ValueError('Could not compile grammar provider!')
def load_compiler_suite(compiler_suite: str) -> \
......@@ -290,7 +296,7 @@ def load_compiler_suite(compiler_suite: str) -> \
_, imports, preprocessor_py, parser_py, ast_py, compiler_py, _ = \
RX_SECTION_MARKER.split(source)
except ValueError:
raise AssertionError('File "' + compiler_suite + '" seems to be corrupted. '
raise ValueError('File "' + compiler_suite + '" seems to be corrupted. '
'Please delete or repair file manually.')
# TODO: Compile in one step and pick parts from namespace later ?
preprocessor = compile_python_object(imports + preprocessor_py,
......@@ -311,8 +317,10 @@ def load_compiler_suite(compiler_suite: str) -> \
parser = get_ebnf_grammar
ast = get_ebnf_transformer
compiler = compile_python_object(imports + compiler_py, r'get_(?:\w+_)?compiler$')
return preprocessor, parser, ast, compiler
if isinstance(preprocessor, Callable) and isinstance(parser, Callable) \
and isinstance(ast, Callable) and isinstance(compiler, Callable):
return preprocessor, parser, ast, compiler
raise ValueError('Could not generate compiler suite from source code!')
def is_outdated(compiler_suite: str, grammar_source: str) -> bool:
......@@ -405,21 +413,26 @@ def compile_on_disk(source_file: str, compiler_suite="", extension=".xml") -> It
sfactory, pfactory, tfactory, cfactory = load_compiler_suite(compiler_suite)
compiler1 = cfactory()
else:
sfactory = get_ebnf_preprocessor
pfactory = get_ebnf_grammar
tfactory = get_ebnf_transformer
cfactory = get_ebnf_compiler
compiler1 = cfactory()
sfactory = get_ebnf_preprocessor # type: PreprocessorFactoryFunc
pfactory = get_ebnf_grammar # type: ParserFactoryFunc
tfactory = get_ebnf_transformer # type: TransformerFactoryFunc
cfactory = get_ebnf_compiler # type: CompilerFactoryFunc
compiler1 = cfactory() # type: Compiler
is_ebnf_compiler = False # type: bool
if isinstance(compiler1, EBNFCompiler):
is_ebnf_compiler = True
compiler1.set_grammar_name(compiler_name, source_file)
result, messages, _ = compile_source(source, sfactory(), pfactory(), tfactory(), compiler1)
if has_errors(messages):
return messages
elif cfactory == get_ebnf_compiler:
elif is_ebnf_compiler:
# trans == get_ebnf_transformer or trans == EBNFTransformer:
# either an EBNF- or no compiler suite given
ebnf_compiler = cast(EBNFCompiler, compiler1)
ebnf_compiler = cast(EBNFCompiler, compiler1) # type: EBNFCompiler
global SECTION_MARKER, RX_SECTION_MARKER, PREPROCESSOR_SECTION, PARSER_SECTION, \
AST_SECTION, COMPILER_SECTION, END_SECTIONS_MARKER, RX_WHITESPACE, \
DHPARSER_MAIN
......
......@@ -882,6 +882,7 @@ class EBNFCompiler(Compiler):
nd = self.rules[rule.s][0].children[1]
refined = self._gen_search_rule(nd)
except IndexError:
nd = self.tree
refined = ""
if refined:
refined_rules.append(refined)
......
......@@ -215,14 +215,6 @@ FlagFunc = Callable[[ApplyFunc, Set[ApplyFunc]], bool]
ParseFunc = Callable[[StringView], Tuple[Optional[Node], StringView]]
def copy_parser_attrs(src: 'Parser', duplicate: 'Parser'):
"""Duplicates all parser attributes from source to dest."""
duplicate.pname = src.pname
duplicate.anonymous = src.anonymous
duplicate.drop_content = src.drop_content
duplicate.tag_name = src.tag_name
class Parser:
"""
(Abstract) Base class for Parser combinator parsers. Any parser
......@@ -525,7 +517,7 @@ class Parser:
else:
# if proxy is a method it must be a method of self
assert proxy.__self__ == self
self.__parse = proxy
self.__parse = cast(ParseFunc, proxy)
@property
def grammar(self) -> 'Grammar':
......@@ -557,7 +549,8 @@ class Parser:
"""
return tuple()
def _apply(self, func: ApplyFunc, flip: FlagFunc) -> bool:
def _apply(self, func: Callable[['Parser'], None],
flip: Callable[[Callable, Set[Callable]], bool]) -> bool:
"""
Applies function `func(parser)` recursively to this parser and all
descendant parsers, if any exist.
......@@ -578,12 +571,12 @@ class Parser:
parser._apply(func, flip)
return True
def apply(self, func: ApplyFunc):
def apply(self, func: Callable[['Parser'], None]):
"""
Applies function `func(parser)` recursively to this parser and all
descendant parsers, if any exist. Traversal is pre-order.
"""
def positive_flip(f: ApplyFunc, flagged: Set[Callable]) -> bool:
def positive_flip(f: Callable[['Parser'], None], flagged: Set[Callable]) -> bool:
"""Returns True, if function `f` has already been applied to this
parser and sets the flag accordingly. Interprets `f in flagged == True`
as meaning that `f` has already been applied."""
......@@ -593,7 +586,7 @@ class Parser:
flagged.add(f)
return False
def negative_flip(f: ApplyFunc, flagged: Set[Callable]) -> bool:
def negative_flip(f: Callable[['Parser'], None], flagged: Set[Callable]) -> bool:
"""Returns True, if function `f` has already been applied to this
parser and sets the flag accordingly. Interprets `f in flagged == False`
as meaning that `f` has already been applied."""
......@@ -609,6 +602,14 @@ class Parser:
self._apply(func, positive_flip)
def copy_parser_attrs(src: Parser, duplicate: Parser):
"""Duplicates all parser attributes from source to dest."""
duplicate.pname = src.pname
duplicate.anonymous = src.anonymous
duplicate.drop_content = src.drop_content
duplicate.tag_name = src.tag_name
def Drop(parser: Parser) -> Parser:
"""Returns the parser with the `parser.drop_content`-property set to `True`."""
assert parser.anonymous, "Parser must be anonymous to be allowed to drop ist content."
......@@ -1896,6 +1897,7 @@ def mandatory_violation(grammar: Grammar,
grammar.tree__.add_error(err_node, error)
else:
if grammar.history_tracking__:
pname = ':root'
for pname, _ in reversed(grammar.call_stack__):
if not pname.startswith(':'):
break
......@@ -2647,7 +2649,7 @@ class Forward(Parser):
def __init__(self):
super(Forward, self).__init__()
self.parser = None
self.parser = None # type: Optional[Parser]
self.cycle_reached = False
def __deepcopy__(self, memo):
......@@ -2657,7 +2659,9 @@ class Forward(Parser):
duplicate.tag_name = self.tag_name
memo[id(self)] = duplicate
parser = copy.deepcopy(self.parser, memo)
duplicate.set(parser)
duplicate.parser = parser
if parser is not None:
duplicate.drop_content = parser.drop_content
return duplicate
def __call__(self, text: StringView) -> Tuple[Optional[Node], StringView]:
......@@ -2710,5 +2714,7 @@ class Forward(Parser):
self.parser = parser
self.drop_content = parser.drop_content
def sub_parsers(self) -> Tuple['Parser', ...]:
return (self.parser,)
def sub_parsers(self) -> Tuple[Parser, ...]:
if self.parser is not None:
return (self.parser,)
return tuple()
......@@ -213,6 +213,7 @@ async def asyncio_connect(
delay = retry_timeout / 1.5**12 if retry_timeout > 0.0 else retry_timeout - 0.001
connected = False
reader, writer = None, None
save_error = ConnectionError
while delay < retry_timeout:
try:
reader, writer = await asyncio.open_connection(host, port)
......
......@@ -32,7 +32,7 @@ speedup. The modules comes with a ``stringview.pxd`` that contains some type
declarations to more fully exploit the benefits of the Cython-compiler.
"""
from typing import Optional, Union, Iterable, Tuple
from typing import Optional, Union, Iterable, Tuple, List
try:
import cython
......@@ -319,7 +319,7 @@ class StringView: # collections.abc.Sized
return regex.finditer(self._text, pos=self._begin, endpos=self._end)
@cython.locals(begin=cython.int, end=cython.int)
def strip(self, chars=' \n\t'):
def strip(self, chars: str = ' \n\t') -> 'StringView':
"""Returns a copy of the StringView `self` with leading and trailing
whitespace removed.
"""
......@@ -328,19 +328,19 @@ class StringView: # collections.abc.Sized
return self if begin == 0 and end == self._len else self[begin:end]
@cython.locals(begin=cython.int)
def lstrip(self, chars=' \n\t'):
def lstrip(self, chars=' \n\t') -> 'StringView':
"""Returns a copy of `self` with leading whitespace removed."""
begin = first_char(self._text, self._begin, self._end, chars) - self._begin
return self if begin == 0 else self[begin:]
@cython.locals(end=cython.int)
def rstrip(self, chars=' \n\t'):
def rstrip(self, chars=' \n\t') -> 'StringView':
"""Returns a copy of `self` with trailing whitespace removed."""
end = last_char(self._text, self._begin, self._end, chars) - self._begin
return self if end == self._len else self[:end]
@cython.locals(length=cython.int, i=cython.int, k=cython.int)
def split(self, sep=None):
def split(self, sep=None) -> List[Union['StringView', str]]:
"""Returns a list of the words in `self`, using `sep` as the
delimiter string. If `sep` is not specified or is None, any
whitespace string is a separator and empty strings are
......@@ -349,7 +349,7 @@ class StringView: # collections.abc.Sized
if self._fullstring:
return self._fullstring.split(sep)
else:
pieces = []
pieces = [] # type: List[Union['StringView', str]]
length = len(sep)
k = 0
i = self.find(sep, k)
......@@ -360,7 +360,7 @@ class StringView: # collections.abc.Sized
pieces.append(self._text[self._begin + k: self._end])
return pieces
def replace(self, old, new):
def replace(self, old, new) -> str:
"""Returns a string where `old` is replaced by `new`."""
return str(self).replace(old, new)
......
......@@ -149,18 +149,13 @@ def create_match_function(criterion: CriteriaType) -> Callable:
return lambda nd: nd == criterion
elif isinstance(criterion, str):
return lambda nd: nd.tag_name == criterion
elif isinstance(criterion, Callable):
return cast(Callable, criterion)
elif isinstance(criterion, Container):
return lambda nd: nd.tag_name in criterion
if isinstance(criterion, Callable):
return criterion
raise AssertionError("Criterion %s of type %s does not represent a legal criteria type")
ChildrenType = Tuple['Node', ...]
NO_CHILDREN = cast(ChildrenType, ()) # type: ChildrenType
StrictResultType = Union[ChildrenType, StringView, str]
ResultType = Union[ChildrenType, 'Node', StringView, str, None]
RX_AMP = re.compile(r'&(?!\w+;)')
......@@ -263,7 +258,9 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
__slots__ = '_result', 'children', '_pos', 'tag_name', '_xml_attr'
def __init__(self, tag_name: str, result: ResultType, leafhint: bool = False) -> None:
def __init__(self, tag_name: str,
result: Union[Tuple['Node', ...], 'Node', StringView, str],
leafhint: bool = False) -> None:
"""
Initializes the ``Node``-object with the ``Parser``-Instance
that generated the node and the parser's result.
......@@ -272,8 +269,8 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
# Assignment to self.result initializes the attr _result and children
# The following if-clause is merely an optimization, i.e. a fast-path for leaf-Nodes
if leafhint:
self._result = result # type: StrictResultType # cast(StrictResultType, result)
self.children = NO_CHILDREN # type: ChildrenType
self._result = result # type: Union[Tuple['Node', ...], StringView, str]
self.children = tuple() # type: Tuple[Node, ...]
else:
self._set_result(result)
self.tag_name = tag_name # type: str
......@@ -361,7 +358,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
# node content ###
def _set_result(self, result: ResultType):
def _set_result(self, result: Union[Tuple['Node', ...], 'Node', StringView, str]):
"""
Sets the result of a node without assigning the position.
An assignment to the `result`-property is to be preferred,
......@@ -370,20 +367,21 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
:param result: the new result of the note
"""
if isinstance(result, Node):
self.children = (result,)
self.children = (result,) # type: Tuple[Node, ...]
self._result = self.children
else:
if isinstance(result, tuple):
self.children = result
self._result = result or ''
else:
self.children = NO_CHILDREN
self._result = result # cast(StrictResultType, result)
assert result is not None
self.children = tuple()
self._result = result
def _init_child_pos(self):
"""Initialize position values of children with potentially
unassigned positions, i.e. child.pos < 0."""
children = self.children
children = self.children # type: Tuple['Node', ...]
if children:
offset = self._pos
prev = children[0]
......@@ -397,7 +395,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
offset = child._pos
@property
def result(self) -> StrictResultType:
def result(self) -> Union[Tuple['Node', ...], StringView, str]:
"""
Returns the result from the parser that created the node.
Error messages are not included in the result. Use `self.content()`
......@@ -406,7 +404,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
return self._result
@result.setter
def result(self, result: ResultType):
def result(self, result: Union[Tuple['Node', ...], 'Node', StringView, str]):
self._set_result(result)
# fix position values for children that are added after the parsing process
if self._pos >= 0:
......@@ -588,7 +586,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
if isinstance(key, int):
return self.children[key]
else:
mf = create_match_function(cast(CriteriaType, key))
mf = create_match_function(key)
for child in self.children:
if mf(child):
return child
......@@ -881,6 +879,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
if begin.pos > end.pos:
begin, end = end, begin
common_ancestor = self # type: Node
ctxA = self.reconstruct_context(begin)
ctxB = self.reconstruct_context(end)
for a, b in zip(ctxA, ctxB):
......@@ -1135,7 +1134,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
assert isinstance(json_obj, Sequence)
assert 2 <= len(json_obj) <= 4, str(json_obj)
if isinstance(json_obj[1], str):
result = json_obj[1] # type: StrictResultType
result = json_obj[1] # type: Union[Tuple[Node, ...], StringView, str]
else:
result = tuple(Node.from_json_obj(item) for item in json_obj[1])
node = Node(json_obj[0], result)
......@@ -1208,6 +1207,11 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
% (how, "'ast', 'cst', 'default'", ", ".join(list(SERIALIZATIONS))))
ChildrenType = Tuple[Node, ...]
StrictResultType = Union[ChildrenType, StringView, str]
ResultType = Union[ChildrenType, Node, StringView, str]
class FrozenNode(Node):
"""
FrozenNode is an immutable kind of Node, i.e. it must not be changed
......@@ -1231,7 +1235,7 @@ class FrozenNode(Node):
super(FrozenNode, self).__init__(tag_name, result, True)
@property
def result(self) -> StrictResultType:
def result(self) -> Union[Tuple[Node, ...], StringView, str]:
return self._result
@result.setter
......@@ -1247,7 +1251,7 @@ class FrozenNode(Node):
raise NotImplementedError("Frozen nodes cannot store attributes")
def with_pos(self, pos: int) -> 'Node':
pass
raise NotImplementedError("Position values cannot be assigned to frozen nodes!")
def to_json_obj(self) -> List:
raise NotImplementedError("Frozen nodes cannot and should not be serialized!")
......@@ -1346,7 +1350,7 @@ class RootNode(Node):
duplicate.children = copy.deepcopy(self.children)
duplicate._result = duplicate.children
else:
duplicate.children = NO_CHILDREN
duplicate.children = tuple()
duplicate._result = self._result
duplicate._pos = self._pos
if self.has_attr():
......@@ -1492,12 +1496,8 @@ def parse_sxpr(sxpr: Union[str, StringView]) -> Node:
>>> tree['C'].pos
1
"""
sxpr = StringView(sxpr).strip() if isinstance(sxpr, str) else sxpr.strip()
# mock_parsers = dict() # type: Dict[StringView, MockParser]
@cython.locals(level=cython.int, k=cython.int)
def next_block(s: StringView):
def next_block(s: StringView) -> Iterator[StringView]:
"""Generator that yields all characters until the next closing bracket
that does not match an opening bracket matched earlier within the same
package.
......@@ -1553,7 +1553,7 @@ def parse_sxpr(sxpr: Union[str, StringView]) -> Node:
raise ValueError('Unbalanced parantheses in S-Expression: ' + str(sxpr))
# read very special attribute pos
if sxpr[2:5] == "pos" and 0 < k < i:
pos = int(sxpr[5:k].strip(' \'"').split(' ')[0])
pos = int(str(sxpr[5:k].strip(' \'"').split(' ')[0]))
# ignore very special attribute err
elif sxpr[2:5] == "err" and 0 <= sxpr.find('`', 5) < k:
m = sxpr.find('(', 5)
......@@ -1566,10 +1566,10 @@ def parse_sxpr(sxpr: Union[str, StringView]) -> Node:
if not RX_ATTR_NAME.match(attr):
raise ValueError('Illegal attribute name: ' + attr)
value = sxpr[i:k].strip()[1:-1]
attributes[attr] = value
attributes[attr] = str(value)
sxpr = sxpr[k + 1:].strip()
if sxpr[0] == '(':
result = tuple(inner_parser(block) for block in next_block(sxpr)) # type: ResultType
result = tuple(inner_parser(block) for block in next_block(sxpr)) # type: Union[Tuple[Node, ...], str]
else:
lines = []
while sxpr and sxpr[0:1] != ')':
......@@ -1587,14 +1587,15 @@ def parse_sxpr(sxpr: Union[str, StringView]) -> Node:
end = sxpr.index(match.end())
lines.append(str(sxpr[:end]))
sxpr = sxpr[end:]
result = "\n".join(lines)
node = Node(name or ':' + class_name, result)
result = "\n".join(lines) # # type: Union[Tuple[Node, ...], str]
node = Node(str(name or ':' + class_name), result)
node._pos = pos
if attributes:
node.attr.update(attributes)
return node
return inner_parser(StringView(sxpr) if isinstance(sxpr, str) else sxpr)
xpr = StringView(sxpr).strip() if isinstance(sxpr, str) else sxpr.strip() # type: StringView
return inner_parser(xpr)
RX_WHITESPACE_TAIL = re.compile(r'\s*$')
......@@ -1685,9 +1686,9 @@ def parse_xml(xml: Union[str, StringView], ignore_pos: bool = False) -> Node:
s, closing_tagname = parse_closing_tag(s)
assert tagname == closing_tagname, tagname + ' != ' + closing_tagname
if len(res) == 1 and res[0].tag_name == TOKEN_PTYPE:
result = res[0].result
result = res[0].result # type: Union[Tuple[Node, ...], StringView, str]
else:
result = tuple(res)
result = tuple(res) # type:Union[Tuple[Node, ...], StringView, str]
node = Node(name or ':' + class_name, result)
if not ignore_pos and '_pos' in attrs:
......
......@@ -211,11 +211,10 @@ def run_server(host, port, log_path=None):
non_blocking = frozenset(('initialize', 'initialized', 'shutdown', 'exit'))
DSL_server = Server(rpc_functions=lsp_table,
cpu_bound=set(lsp_table.keys() - non_blocking),
blocking=frozenset())
blocking=set())
if log_path is not None:
DSL_server.echo_log = True
print(DSL_server.start_logging(log_path))
try:
DSL_server.run_server(host, port) # returns only after server has stopped
except OSError as e:
......@@ -224,6 +223,7 @@ def run_server(host, port, log_path=None):
sys.exit(1)
finally:
cfg_filename = get_config_filename()
print('Server on %s:%i stopped' % (host, port))
try:
os.remove(cfg_filename)
print('Removing temporary config file: "{}".'.format(cfg_filename))
......
......@@ -364,7 +364,7 @@ def md5(*txt):
return md5_hash.hexdigest()
def compile_python_object(python_src, catch_obj_regex=""):
def compile_python_object(python_src: str, catch_obj_regex="") -> Any:
"""
Compiles the python source code and returns the (first) object
the name of which is matched by ``catch_obj_regex``. If catch_obj
......
......@@ -28,7 +28,7 @@ from typing import Tuple, Optional, List, Iterable, Union
from DHParser.error import Error
from DHParser.stringview import StringView
from DHParser.syntaxtree import Node, REGEXP_PTYPE, TOKEN_PTYPE, WHITESPACE_PTYPE, EMPTY_NODE
from DHParser.syntaxtree import Node, REGEXP_PTYPE, TOKEN_PTYPE, WHITESPACE_PTYPE
from DHParser.log import HistoryRecord
from DHParser.parse import Grammar, Parser, ParserError, ParseFunc
......
......@@ -880,7 +880,7 @@ def merge_adjacent(context, condition: Callable, tag_name: str = ''):
head.result = reduce(operator.add, (nd.result for nd in adjacent), initial)
if tag_name in tag_names:
head.tag_name = tag_name
new_result.append(head)
new_result.append(head)
else:
new_result.append(children[i])
i += 1
......
......@@ -145,12 +145,10 @@ class EBNFLanguageServerProtocol:
self.shared.rootUri = ''
self.shared.clientCapabilities = ''
self.shared.serverCapabilities = json.dumps({
"capabilities": {
"textDocumentSync": 1,
"completionProvider": {
"resolveProvider": True
"textDocumentSync": 1,
"completionProvider": {
"resolveProvider": True
}
}
})
def lsp_initialize(self, **kwargs):
......@@ -161,7 +159,7 @@ class EBNFLanguageServerProtocol: