summaryrefslogtreecommitdiffstats
path: root/generator/model.py
diff options
context:
space:
mode:
Diffstat (limited to 'generator/model.py')
-rw-r--r--generator/model.py897
1 files changed, 897 insertions, 0 deletions
diff --git a/generator/model.py b/generator/model.py
new file mode 100644
index 0000000..abac69d
--- /dev/null
+++ b/generator/model.py
@@ -0,0 +1,897 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+from __future__ import annotations
+
+import uuid
+from typing import Any, Dict, Iterable, List, Optional, Type, TypeVar, Union
+
+import attrs
+
+LSP_TYPE_SPEC = Union[
+ "BaseType",
+ "ReferenceType",
+ "OrType",
+ "AndType",
+ "ArrayType",
+ "LiteralType",
+ "StringLiteralType",
+ "MapType",
+ "TupleType",
+]
+
+
+def partial_apply(callable):
+ def apply(x):
+ if isinstance(x, dict):
+ return callable(**x)
+ else:
+ return x
+
+ return apply
+
+
+def list_converter(callable):
+ def apply(x):
+ if isinstance(x, dict):
+ return callable(**x)
+ else:
+ return x
+
+ def converter(x: List[Any]) -> List[Any]:
+ return list(map(apply, x))
+
+ return converter
+
+
+def enum_validator(instance: Enum, attribute: Any, value: Any) -> None:
+ test_type = str if instance.type.name == "string" else int
+ for e in value:
+ if not isinstance(e.value, test_type):
+ raise ValueError(
+ f"Value of {instance.name}.{e.name} is not of type {test_type}: {e.value}."
+ )
+
+
+def convert_to_lsp_type(**type_info) -> Optional[LSP_TYPE_SPEC]:
+ if type_info is None:
+ return None
+ lut: Dict[str, LSP_TYPE_SPEC] = {
+ "base": BaseType,
+ "reference": ReferenceType,
+ "array": ArrayType,
+ "or": OrType,
+ "and": AndType,
+ "literal": LiteralType,
+ "map": MapType,
+ "stringLiteral": StringLiteralType,
+ "tuple": TupleType,
+ }
+ callable = lut.get(type_info["kind"])
+ if callable:
+ return callable(**type_info)
+
+ raise ValueError(f"Unknown LSP type: {type_info}")
+
+
+def type_validator(instance: Any, attribute: str, value: Any) -> bool:
+ return isinstance(
+ value,
+ (
+ BaseType,
+ ReferenceType,
+ ArrayType,
+ OrType,
+ LiteralType,
+ AndType,
+ MapType,
+ StringLiteralType,
+ TupleType,
+ ),
+ )
+
+
+@attrs.define
+class EnumItem:
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ value: Union[str, int] = attrs.field(
+ validator=attrs.validators.instance_of((str, int))
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: Any) -> bool:
+ if isinstance(other, EnumItem):
+ return self.name == other.name and self.value == other.value
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class EnumValueType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["base"]))
+ name: str = attrs.field(
+ validator=attrs.validators.in_(["string", "integer", "uinteger"])
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, EnumValueType):
+ return self.name == other.name and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class Enum:
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ type: EnumValueType = attrs.field(converter=partial_apply(EnumValueType))
+ values: Iterable[EnumItem] = attrs.field(
+ validator=enum_validator,
+ converter=list_converter(EnumItem),
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ supportsCustomValues: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Enum):
+ return (
+ self.name == other.name
+ and self.type == other.type
+ and self.values == other.values
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = [self.type]
+ for value in self.values:
+ types.append(value)
+ types.extend(value.get_inner_types())
+ return types
+
+
+@attrs.define
+class BaseType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["base"]))
+ name: str = attrs.field(
+ validator=attrs.validators.in_(
+ [
+ "URI",
+ "DocumentUri",
+ "integer",
+ "uinteger",
+ "decimal",
+ "RegExp",
+ "string",
+ "boolean",
+ "null",
+ ]
+ )
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, BaseType):
+ return self.name == other.name and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class ReferenceType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["reference"]))
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, ReferenceType):
+ return self.name == other.name and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class StringLiteralType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["stringLiteral"]))
+ value: str = attrs.field(validator=attrs.validators.instance_of(str))
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, StringLiteralType):
+ return self.value == other.value and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class OrType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["or"]))
+ items: Iterable[LSP_TYPE_SPEC] = attrs.field(
+ converter=list_converter(convert_to_lsp_type)
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, OrType):
+ return self.items == other.items and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ for item in self.items:
+ types.append(item)
+ types.extend(item.get_inner_types())
+ return types
+
+
+@attrs.define
+class AndType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["and"]))
+ items: Iterable[LSP_TYPE_SPEC] = attrs.field(
+ converter=list_converter(convert_to_lsp_type),
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, AndType):
+ return self.items == other.items and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ for item in self.items:
+ types.append(item)
+ types.extend(item.get_inner_types())
+ return types
+
+
+@attrs.define
+class ArrayType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["array"]))
+ element: LSP_TYPE_SPEC = attrs.field(
+ validator=type_validator, converter=partial_apply(convert_to_lsp_type)
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, ArrayType):
+ return self.element == other.element and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return [self.element] + self.element.get_inner_types()
+
+
+@attrs.define
+class TupleType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["tuple"]))
+ items: Iterable[LSP_TYPE_SPEC] = attrs.field(
+ converter=list_converter(convert_to_lsp_type)
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, TupleType):
+ return self.items == other.items and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ for item in self.items:
+ types.append(item)
+ types.extend(item.get_inner_types())
+ return types
+
+
+@attrs.define
+class BaseMapKeyType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["base"]))
+ name: str = attrs.field(
+ validator=attrs.validators.in_(
+ [
+ "URI",
+ "DocumentUri",
+ "integer",
+ "string",
+ ]
+ )
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, BaseMapKeyType):
+ return self.name == other.name and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class ReferenceMapKeyType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["reference"]))
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, ReferenceMapKeyType):
+ return self.name == other.name and self.kind == other.kind
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+def convert_map_key(
+ key_info: Dict[str, Any]
+) -> Union[BaseMapKeyType, ReferenceMapKeyType]:
+ if key_info["kind"] == "base":
+ return BaseMapKeyType(**key_info)
+ return ReferenceMapKeyType(**key_info)
+
+
+@attrs.define
+class MapType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["map"]))
+ key: Union[BaseMapKeyType, ReferenceMapKeyType] = attrs.field(
+ converter=convert_map_key
+ )
+ value: LSP_TYPE_SPEC = attrs.field(
+ validator=type_validator, converter=partial_apply(convert_to_lsp_type)
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, MapType):
+ return (
+ self.key == other.key
+ and self.value == other.value
+ and self.kind == other.kind
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return (
+ [self.value, self.key]
+ + self.value.get_inner_types()
+ + self.key.get_inner_types()
+ )
+
+
+@attrs.define
+class MetaData:
+ version: str = attrs.field(validator=attrs.validators.instance_of(str))
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, MetaData):
+ return self.version == other.version
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return []
+
+
+@attrs.define
+class Property:
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ type: LSP_TYPE_SPEC = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ )
+ optional: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Property):
+ return (
+ self.name == other.name
+ and self.type == other.type
+ and self.optional == other.optional
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return [self.type] + self.type.get_inner_types()
+
+
+@attrs.define
+class LiteralValue:
+ properties: Iterable[Property] = attrs.field(
+ converter=list_converter(Property),
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, LiteralValue):
+ return self.properties == other.properties
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ for prop in self.properties:
+ types.append(prop)
+ types.extend(prop.get_inner_types())
+ return types
+
+
+@attrs.define
+class LiteralType:
+ kind: str = attrs.field(validator=attrs.validators.in_(["literal"]))
+ value: LiteralValue = attrs.field(
+ validator=attrs.validators.instance_of(LiteralValue),
+ converter=partial_apply(LiteralValue),
+ )
+ name: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, LiteralType):
+ return (
+ self.value == other.value
+ and self.kind == other.kind
+ and self.name == other.name
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return [self.value] + self.value.get_inner_types()
+
+
+@attrs.define
+class TypeAlias:
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ type: LSP_TYPE_SPEC = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, TypeAlias):
+ return (
+ self.name == other.name
+ and self.type == other.type
+ and self.kind == other.kind
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ return [self.type] + self.type.get_inner_types()
+
+
+@attrs.define
+class Structure:
+ name: str = attrs.field(validator=attrs.validators.instance_of(str))
+ properties: Iterable[Property] = attrs.field(
+ converter=list_converter(Property),
+ )
+ extends: Optional[Iterable[LSP_TYPE_SPEC]] = attrs.field(
+ converter=list_converter(convert_to_lsp_type), default=[]
+ )
+ mixins: Optional[Iterable[LSP_TYPE_SPEC]] = attrs.field(
+ converter=list_converter(convert_to_lsp_type), default=[]
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Structure):
+ return (
+ self.name == other.name
+ and self.properties == other.properties
+ and self.extends == other.extends
+ and self.mixins == other.mixins
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ for prop in self.properties:
+ types.append(prop.type)
+ types.extend(prop.type.get_inner_types())
+ for ext in self.extends:
+ types.append(ext)
+ types.extend(ext.get_inner_types())
+ for mixin in self.mixins:
+ types.append(mixin)
+ types.extend(mixin.get_inner_types())
+ return types
+
+
+@attrs.define
+class Notification:
+ method: str = attrs.field(validator=attrs.validators.instance_of(str))
+ messageDirection: str = attrs.field(
+ validator=attrs.validators.in_(["clientToServer", "serverToClient", "both"])
+ )
+ params: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ registrationOptions: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ registrationMethod: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Notification):
+ return (
+ self.method == other.method
+ and self.messageDirection == other.messageDirection
+ and self.params == other.params
+ and self.registrationOptions == other.registrationOptions
+ and self.registrationMethod == other.registrationMethod
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ if self.params:
+ types.append(self.params)
+ types.extend(self.params.get_inner_types())
+ if self.registrationOptions:
+ types.append(self.registrationOptions)
+ types.extend(self.registrationOptions.get_inner_types())
+ return types
+
+
+@attrs.define
+class Request:
+ method: str = attrs.field(validator=attrs.validators.instance_of(str))
+ messageDirection: str = attrs.field(
+ validator=attrs.validators.in_(["clientToServer", "serverToClient", "both"])
+ )
+ params: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ result: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ partialResult: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ errorData: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ registrationOptions: Optional[LSP_TYPE_SPEC] = attrs.field(
+ validator=type_validator,
+ converter=partial_apply(convert_to_lsp_type),
+ default=None,
+ )
+ proposed: Optional[bool] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(bool)),
+ default=None,
+ )
+ documentation: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ since: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ registrationMethod: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ deprecated: Optional[str] = attrs.field(
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+ id_: Optional[str] = attrs.field(
+ converter=lambda x: str(uuid.uuid4()),
+ validator=attrs.validators.optional(attrs.validators.instance_of(str)),
+ default=None,
+ )
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Request):
+ return (
+ self.method == other.method
+ and self.messageDirection == other.messageDirection
+ and self.params == other.params
+ and self.result == other.result
+ and self.partialResult == other.partialResult
+ and self.errorData == other.errorData
+ and self.registrationOptions == other.registrationOptions
+ and self.registrationMethod == other.registrationMethod
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = []
+ if self.params:
+ types.append(self.params)
+ types.extend(self.params.get_inner_types())
+ if self.result:
+ types.append(self.result)
+ types.extend(self.result.get_inner_types())
+ if self.partialResult:
+ types.append(self.partialResult)
+ types.extend(self.partialResult.get_inner_types())
+ if self.errorData:
+ types.append(self.errorData)
+ types.extend(self.errorData.get_inner_types())
+ if self.registrationOptions:
+ types.append(self.registrationOptions)
+ types.extend(self.registrationOptions.get_inner_types())
+ return types
+
+
+@attrs.define
+class LSPModel:
+ requests: Iterable[Request] = attrs.field(converter=list_converter(Request))
+ notifications: Iterable[Notification] = attrs.field(
+ converter=list_converter(Notification)
+ )
+ structures: Iterable[Structure] = attrs.field(converter=list_converter(Structure))
+ enumerations: Iterable[Enum] = attrs.field(converter=list_converter(Enum))
+ typeAliases: Iterable[TypeAlias] = attrs.field(converter=list_converter(TypeAlias))
+ metaData: MetaData = attrs.field(converter=lambda x: MetaData(**x))
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, LSPModel):
+ return (
+ self.requests == other.requests
+ and self.notifications == other.notifications
+ and self.structures == other.structures
+ and self.enumerations == other.enumerations
+ and self.typeAliases == other.typeAliases
+ and self.metaData == other.metaData
+ )
+ return False
+
+ def get_inner_types(self) -> List[Type]:
+ types = self.metaData.get_inner_types()
+ for r in self.requests:
+ types.extend(r.get_inner_types())
+ for n in self.notifications:
+ types.extend(n.get_inner_types())
+ for s in self.structures:
+ types.extend(s.get_inner_types())
+ for e in self.enumerations:
+ types.extend(e.get_inner_types())
+ for t in self.typeAliases:
+ types.extend(t.get_inner_types())
+ return types
+
+
+def create_lsp_model(models: List[Dict[str, Any]]) -> LSPModel:
+ if len(models) >= 1:
+ spec = LSPModel(**models[0])
+
+ if len(models) >= 2:
+ for model in models[1:]:
+ addition = LSPModel(**model)
+ spec.requests.extend(addition.requests)
+ spec.notifications.extend(addition.notifications)
+ spec.structures.extend(addition.structures)
+ spec.enumerations.extend(addition.enumerations)
+ spec.typeAliases.extend(addition.typeAliases)
+
+ return spec