@@ -139,6 +139,7 @@ def _reset(self):
139139 self ._types : OrderedDict [str , List [str ]] = collections .OrderedDict ()
140140 self ._imports : List [str ] = [
141141 "import enum" ,
142+ "import functools" ,
142143 "from typing import Any, Dict, List, Optional, Tuple, Union" ,
143144 "import attrs" ,
144145 "from . import validators" ,
@@ -292,6 +293,41 @@ def _has_type(self, type_name: str) -> bool:
292293 type_name = type_name [1 :- 1 ]
293294 return type_name in self ._types
294295
296+ def _get_additional_methods (self , class_name : str ) -> List [str ]:
297+ indent = " " * 4
298+ if class_name == "Position" :
299+ return [
300+ "def __eq__(self, o: 'Position') -> Union[bool, 'NotImplemented']:" ,
301+ f"{ indent } if not isinstance(o, Position):" ,
302+ f"{ indent } { indent } return NotImplemented" ,
303+ f"{ indent } return (self.line, self.character) == (o.line, o.character)" ,
304+ "def __gt__(self, o: 'Position') -> Union[bool, 'NotImplemented']:" ,
305+ f"{ indent } if not isinstance(o, Position):" ,
306+ f"{ indent } { indent } return NotImplemented" ,
307+ f"{ indent } return (self.line, self.character) > (o.line, o.character)" ,
308+ "def __repr__(self) -> str:" ,
309+ f"{ indent } " + "return f'{self.line}:{self.character}'" ,
310+ ]
311+ if class_name == "Range" :
312+ return [
313+ "def __eq__(self, o: 'Range') -> Union[bool, 'NotImplemented']:" ,
314+ f"{ indent } if not isinstance(o, Range):" ,
315+ f"{ indent } { indent } return NotImplemented" ,
316+ f"{ indent } return (self.start == o.start) and (self.end == o.end)" ,
317+ "def __repr__(self) -> str:" ,
318+ f"{ indent } " + "return f'{self.start!r}-{self.end!r}'" ,
319+ ]
320+ if class_name == "Location" :
321+ return [
322+ "def __eq__(self, o:'Location') -> Union[bool, 'NotImplemented']:" ,
323+ f"{ indent } if not isinstance(o, Location):" ,
324+ f"{ indent } { indent } return NotImplemented" ,
325+ f"{ indent } return (self.uri == o.uri) and (self.range == o.range)" ,
326+ "def __repr__(self) -> str:" ,
327+ f"{ indent } " + "return f'{self.uri}:{self.range!r}'" ,
328+ ]
329+ return None
330+
295331 def _add_type_code (self , type_name : str , code : List [str ]) -> None :
296332 if not self ._has_type (type_name ):
297333 self ._types [type_name ] = code
@@ -529,6 +565,7 @@ def _add_structure(
529565
530566 class_lines = [
531567 "" if class_name == "LSPObject" else "@attrs.define" ,
568+ "@functools.total_ordering" if class_name == "Position" else "" ,
532569 f"class { class_name } :" ,
533570 f'{ indent } """{ doc } """' if struct_def .documentation else "" ,
534571 f"{ indent } # Since: { _sanitize_comment (struct_def .since )} "
@@ -549,10 +586,15 @@ def _add_structure(
549586 properties += copy .deepcopy (d .properties )
550587
551588 code_lines += self ._generate_properties (class_name , properties , indent )
589+ methods = self ._get_additional_methods (class_name )
590+
552591 # If the class has no properties then add `pass`
553- if len (properties ) == 0 :
592+ if len (properties ) == 0 and not methods :
554593 code_lines += [f"{ indent } pass" ]
555594
595+ if methods :
596+ code_lines += [f"{ indent } { l } " for l in methods ]
597+
556598 # Detect if the class has properties that might be keywords.
557599 self ._add_type_code (class_name , code_lines )
558600
@@ -764,9 +806,9 @@ def _add_lsp_method_type(self, lsp_model: model.LSPModel) -> None:
764806 "@enum.unique" ,
765807 "class MessageDirection(enum.Enum):" ,
766808 ]
767- code_lines += [
768- f"{ indent } { _capitalized_item_name (m )} = '{ m } '" for m in directions
769- ]
809+ code_lines += sorted (
810+ [ f"{ indent } { _capitalized_item_name (m )} = '{ m } '" for m in directions ]
811+ )
770812 self ._add_type_code ("MessageDirection" , code_lines )
771813
772814 def _generate_code (self , lsp_model : model .LSPModel ) -> None :
0 commit comments