forked from secondlife/lsl-definitions
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathslua_lsp_docs.py
More file actions
139 lines (121 loc) · 5.3 KB
/
Copy pathslua_lsp_docs.py
File metadata and controls
139 lines (121 loc) · 5.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Generator for SLua documentation files for Luau LSP, like this one:
https://github.com/MaximumADHD/Roblox-Client-Tracker/blob/roblox/api-docs/en-us.json
"""
from __future__ import annotations
import dataclasses
import json
from lsl_definitions.generators.base import register
from lsl_definitions.lsl import LSLDefinitions
from lsl_definitions.slua import (
SLuaDefinitions,
SLuaFunction,
SLuaModule,
SLuaProperty,
)
from lsl_definitions.utils import (
remove_nones,
)
GLOBALS_PREFIX = "@sl-slua/global/"
def htmlize(text: str) -> str:
text = text.replace("\\n", "\n").strip()
text = text.replace("\n", "<br>")
text = text.replace(" ", " ")
text = text.replace("\t", " ")
return text
def doc_url(module: str | None, func: str | None) -> str | None:
# TODO: Change these when they have a more stable home
if module in {"ll", "llcompat"} and func is not None:
return f"https://wiki.secondlife.com/wiki/Ll{func}"
if module in {
"bit32",
"buffer",
"coroutine",
"debug",
"math",
"os",
"string",
"table",
"utf8",
"vector",
}:
if func is None:
return f"https://luau.org/library/#{module}-library"
return f"https://create.roblox.com/docs/reference/engine/libraries/{module}#{func}"
if func == "vector":
return "https://luau.org/library/#vector-library"
if module == "lljson":
return "https://create.secondlife.com/script/learn-slua/json/"
if module in {"quaternion", "rotation"}:
return "https://suzanna-linn.github.io/slua/moving-rotations"
return None
@dataclasses.dataclass
class DocBuilder:
docs: dict = dataclasses.field(default_factory=dict)
def add_function(self, func: SLuaFunction, module: str | None = None, method=False):
module_prefix = f"{module}." if module else ""
entry = remove_nones(
documentation=htmlize(func.comment or f"{func.name} function"),
learn_more_link=doc_url(module, func.name),
)
self.docs[f"{GLOBALS_PREFIX}{module_prefix}{func.name}"] = entry
def add_constant(self, const: SLuaProperty, module: str | None = None):
module_prefix = f"{module}." if module else ""
value = f"Value: {const.value}" if const.value is not None else ""
comment = htmlize(const.comment)
documentation = value + "<br>" + comment if comment and value else value + comment
entry = remove_nones(
documentation=documentation,
learn_more_link=doc_url(module, const.name),
)
self.docs[f"{GLOBALS_PREFIX}{module_prefix}{const.name}"] = entry
def add_module(self, module: SLuaModule) -> None:
if module.callable:
self.add_function(module.callable)
else:
self.docs[f"{GLOBALS_PREFIX}{module.name}"] = remove_nones(
documentation=htmlize(module.comment),
learn_more_link=doc_url(module.name, None),
)
# for const in sorted(self.constants, key=lambda x: x.name)
for const in module.constants.values():
if not const.private:
self.add_constant(const, module=module.name)
# for func in sorted(self.functions, key=lambda x: x.name)
for func in module.functions.values():
if not func.private and not func.local_only:
self.add_function(func, module=module.name)
@register("slua_lsp_docs")
def gen_slua_lsp_docs(definitions: LSLDefinitions, slua_definitions: SLuaDefinitions) -> str:
"""Generate SLua standard library for Luau LSP docs.json"""
builder = DocBuilder()
# Duplicate quaternion module as rotation. The callable aspect of quaternion
# prevents us from being able to de-duplicate this with structs.
slua_definitions.modules["rotation"] = SLuaModule(
name="rotation",
comment=slua_definitions.modules["quaternion"].comment,
callable=slua_definitions.modules["quaternion"].callable,
constants=slua_definitions.modules["quaternion"].constants,
functions=slua_definitions.modules["quaternion"].functions,
)
# class docs are unused if generated
# for const in slua_definitions.globalVariables:
# if not const.private and const.name != "rotation":
# selene["globals"][const.name] = selene_property(const)
for func in slua_definitions.functions.values():
if not func.private and not func.local_only and not func.slua_removed:
builder.add_function(func)
for module in sorted(slua_definitions.modules.values(), key=lambda x: x.name):
if module.name not in {"ll", "llcompat"}:
builder.add_module(module)
builder.add_module(slua_definitions.modules["ll"])
builder.add_module(slua_definitions.modules["llcompat"])
# builtin docs are unused if generated
# for const in slua_definitions.builtin_constants:
# builder.add_constant(const)
for const in sorted(slua_definitions.global_constants.values(), key=lambda x: x.name):
if not const.private:
builder.add_constant(const)
# class docs are unused if generated
# for class_ in classes.values():
# selene["structs"][class_.name] = selene_class(class_)
return json.dumps(builder.docs, indent=4)