-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrust-project.knit
105 lines (101 loc) · 3.09 KB
/
rust-project.knit
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
function crateJSON(conf, extra)
if extra ~= nil then
for k, v in pairs(extra) do conf[k] = v end
end
return f[[{
"display_name": "$(conf.display_name)",
"root_module": "$(conf.root_module)",
"edition": "2021",
"target": "wasm32-unknown-unknown",
"is_workspace_member": $(conf.is_workspace_member or false),
"is_proc_macro": $(conf.is_proc_macro or false),
"env": {},
"cfg": [],
"deps": []
}]]
end
function normalize(result)
local formatted = result:gsub("(\n+)", "%1 "):gsub(",\n+%s+$", "")
return formatted
end
function workspaceMembers() -- workaround because rust-analyzer can't mix rust-project.json and cargo-based project
local crateConf = {
is_workspace_member = true,
is_proc_macro = true,
}
function cargoFrom(dirs, conf, recursive)
local result = ""
function process(files, depth)
local list = {}; for i = 1, #dirs do
for j, path in ipairs(glob(dirs[i]..f"/$files")) do -- I HATE THIS 😢
if not path:match(dirs[i].."/"..(conf.symlink or "\0")) then
list[i+j-1] = path
end
end
end
for _, file in ipairs(list) do
local name = base(file):gsub("%.rs", "")
local crate = conf.name
if crate == nil then
local root = dir(dir(file)) -- root/[src/*]
crate = base(root)
for _ = 2, conf.depth or 2 do
root = dir(root)
crate = base(root).."::"..crate
end
end
local module = crate
if conf.prefix ~= nil then
module = conf.prefix.."::"..module
end
local src = file; for _ = 2, depth do
src = dir(src)
module = module.."::"..base(src)
end
if not ((name == "lib" and depth == 1) or (name == "mod" and depth > 1)) then
module = f"$module::$name"
end
result = result .. crateJSON({
display_name = module,
root_module = file,
}, crateConf)..",\n "
end
end
process("src/*.rs", 1)
process("src/*/*.rs", 2)
return result
end
return normalize(
cargoFrom({"libs/rust"}, {name="libnusa", symlink="src/types/"}) ..
cargoFrom(glob("examples/rust/*/*"), {prefix="example", depth=2})
)
end
function wasmCrates(files)
local result = ""
for _, file in ipairs(files) do
local parent = base(dir(file))
local name = base(file):gsub("%.rs", "")
local module = f"wasm::$parent"
if name ~= "mod" then
module = module.."::"..name
end
result = result .. crateJSON{
display_name = module,
root_module = file,
}..",\n "
end
return normalize(result)
end
-- TODO: set `rust-analyzer.linkedProjects:["./rust-project.json", "./libs/rust/Cargo.toml", "./examples/rust/*/*/Cargo.toml"]` when rust-analyzer support local config
-- https://rust-analyzer.github.io/manual.html#configuration
return function(files)
local json = f[[{
"sysroot_src": "$(env.RUST_SRC_PATH)",
"crates": [
$(workspaceMembers()),
$(wasmCrates(files))
]
}]]
local formatted = json:gsub("(\n+) ", "%1")
return formatted
end