Skip to content

Commit 6220cb1

Browse files
committed
parsed all of yegapan's lsp
1 parent a9c3855 commit 6220cb1

21 files changed

Lines changed: 946 additions & 209 deletions

File tree

autoload/vim9/job.vim

Lines changed: 409 additions & 0 deletions
Large diffs are not rendered by default.

autoload/vim9script.vim

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
function! vim9script#fn(name, args) abort
2-
let ret = function(a:name, a:args)()
2+
try
3+
let ret = function(a:name, a:args)()
4+
catch
5+
echo "Failed..."
6+
echo a:name
7+
echo a:args
8+
9+
throw v:errmsg
10+
endtry
11+
312
return [ret, a:args]
413
endfunction

crates/vim9-gen/src/call_expr.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,17 @@ pub fn mutates(
7171
Some(ident) => match ident {
7272
Identifier::Raw(raw) => match raw.name.as_str() {
7373
// We have overriden insert
74-
"add" | "insert" => None,
74+
"add" | "insert" | "extend" => None,
7575

7676
"remove" => Some(VimFuncMutability {
7777
returned: None,
7878
modified_args: HashSet::from_iter(vec![0].into_iter()),
7979
}),
8080

81-
"extend" | "reverse" | "sort" | "filter" => {
82-
Some(VimFuncMutability {
83-
returned: Some(0),
84-
modified_args: HashSet::from_iter(vec![0].into_iter()),
85-
})
86-
}
81+
"reverse" | "sort" | "filter" => Some(VimFuncMutability {
82+
returned: Some(0),
83+
modified_args: HashSet::from_iter(vec![0].into_iter()),
84+
}),
8785
_ => None,
8886
},
8987
Identifier::Scope(_) => todo!(),
@@ -121,7 +119,7 @@ pub enum FunctionData {
121119
},
122120
VimFunc(VimFunc),
123121
VimFuncRef {
124-
name: String,
122+
name: Expression,
125123
arglist: Option<Expression>,
126124
dict: Option<Expression>,
127125
},
@@ -140,7 +138,7 @@ impl FunctionData {
140138
match self {
141139
FunctionData::ApiFunc { name, .. } => name,
142140
FunctionData::VimFunc(vimfunc) => vimfunc.name.as_str(),
143-
FunctionData::VimFuncRef { name, .. } => name,
141+
FunctionData::VimFuncRef { .. } => todo!("VimFuncRef.name()"),
144142
FunctionData::GeneratedFunc { name, .. } => name,
145143
FunctionData::ExprFunc { .. } => todo!("ExprFunc.name()"),
146144
}
@@ -185,10 +183,12 @@ impl From<&CallExpression> for FunctionData {
185183
Expression::Identifier(id) => {
186184
ident_to_func_data(expr.clone(), id.clone())
187185
}
188-
Expression::DictAccess(_) => FunctionData::ExprFunc {
189-
caller: *expr.expr.clone(),
190-
args: expr.args.clone(),
191-
},
186+
Expression::DictAccess(_) | Expression::Index(_) => {
187+
FunctionData::ExprFunc {
188+
caller: *expr.expr.clone(),
189+
args: expr.args.clone(),
190+
}
191+
}
192192
_ => todo!("{:#?}", expr),
193193
}
194194
}
@@ -205,7 +205,7 @@ fn ident_to_func_data(call: CallExpression, ident: Identifier) -> FunctionData {
205205
}
206206
} else if raw.name == "function" {
207207
FunctionData::VimFuncRef {
208-
name: raw.name,
208+
name: call.args[0].clone(),
209209
arglist: call.args.get(1).cloned(),
210210
dict: call.args.get(2).cloned(),
211211
}
@@ -274,11 +274,19 @@ pub fn generate(call: &CallExpression, state: &mut State) -> String {
274274
for _, val in ipairs({{...}}) do
275275
table.insert(copied, val)
276276
end
277-
return vim.fn['{}'](unpack(copied))
277+
278+
local funcref = {}
279+
if type(funcref) == "function" then
280+
return funcref(unpack(copied))
281+
elseif type(funcref) == "string" then
282+
return vim.fn[funcref](unpack(copied))
283+
else
284+
error(string.format("unable to call funcref: %s", funcref))
285+
end
278286
end
279287
"#,
280288
arglist.gen(state),
281-
name
289+
name.gen(state)
282290
)
283291
}
284292
None => {

crates/vim9-gen/src/lib.rs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ impl Generate for ExCommand {
163163
ExCommand::Break(b) => b.gen(state),
164164
ExCommand::Continue(c) => c.gen(state),
165165
ExCommand::Defer(defer) => defer.gen(state),
166+
ExCommand::Execute(exec) => exec.gen(state),
166167
_ => todo!("Have not yet handled: {:?}", self),
167168
}
168169
}
@@ -358,7 +359,8 @@ impl Generate for ExportCommand {
358359

359360
impl Generate for SharedCommand {
360361
fn gen(&self, _: &mut State) -> String {
361-
format!("vim.cmd [[ {} ]]", self.contents.trim())
362+
// Temp
363+
format!("pcall(vim.cmd, [[ {} ]])", self.contents.trim())
362364
}
363365
}
364366

@@ -379,6 +381,15 @@ impl Generate for UserCommand {
379381
state.command_depth += 1;
380382

381383
let complete = to_str_or_nil(&self.command_complete);
384+
let nargs = match &self.command_nargs {
385+
Some(nargs) => match nargs.as_str() {
386+
"0" => "0".to_string(),
387+
"1" => "1".to_string(),
388+
_ => format!("'{}'", nargs),
389+
},
390+
None => "nil".to_string(),
391+
};
392+
382393
let result = format!(
383394
r#"
384395
vim.api.nvim_create_user_command(
@@ -387,15 +398,14 @@ impl Generate for UserCommand {
387398
{}
388399
end,
389400
{{
390-
nargs = '{}',
391401
bang = {},
402+
nargs = {nargs},
392403
complete = {complete},
393404
}}
394405
)"#,
395406
self.name,
396407
make_user_command_arg(state),
397408
self.command.gen(state),
398-
self.command_nargs.clone().unwrap_or("0".to_string()),
399409
self.command_bang,
400410
);
401411

@@ -658,7 +668,7 @@ impl Generate for AssignStatement {
658668
let left = match &self.left {
659669
Expression::Index(idx) => {
660670
format!(
661-
"{}[{} + 1]",
671+
"{}[NVIM9.index_expr({})]",
662672
idx.container.gen(state),
663673
match idx.index.as_ref() {
664674
IndexType::Item(item) => item.gen(state),
@@ -795,6 +805,10 @@ impl Generate for VarCommand {
795805
inner: InnerType::Bool,
796806
..
797807
}) => format!("NVIM9.convert.decl_bool({})", self.expr.gen(state)),
808+
Some(Type {
809+
inner: InnerType::Dict { .. },
810+
..
811+
}) => format!("NVIM9.convert.decl_dict({})", self.expr.gen(state)),
798812
_ => self.expr.gen(state),
799813
};
800814

@@ -839,7 +853,13 @@ impl Generate for ScopedIdentifier {
839853

840854
impl Generate for RawIdentifier {
841855
fn gen(&self, _: &mut State) -> String {
842-
self.name.clone()
856+
// There are a variety of keywords we have to make sure
857+
// that we don't use when creating identifiers
858+
match self.name.as_str() {
859+
"end" => "__end__",
860+
_ => &self.name,
861+
}
862+
.to_string()
843863
}
844864
}
845865

@@ -1059,7 +1079,9 @@ impl Generate for Literal {
10591079
impl Generate for VimKey {
10601080
fn gen(&self, state: &mut State) -> String {
10611081
match self {
1062-
VimKey::Literal(literal) => literal.token.text.to_string(),
1082+
// TODO: For literals, we could simplify this to do
1083+
// direct key access if it doesn't contain any illegal characters
1084+
VimKey::Literal(literal) => format!("['{}']", literal.token.text),
10631085
VimKey::Expression(expr) => format!("[{}]", expr.gen(state)),
10641086
}
10651087
}
@@ -1123,10 +1145,10 @@ impl Generate for VimString {
11231145
format!("\"{}\"", s)
11241146
}
11251147
VimString::Interpolated(interp) => {
1126-
format!("string.format('{}')", interp)
1148+
format!("string.format([=[{}]=])", interp)
11271149
}
11281150
VimString::InterpolatedLit(interp) => {
1129-
format!("string.format('{}')", interp)
1151+
format!("string.format([=[{}']=])", interp)
11301152
}
11311153
VimString::EnvironmentVariable(env) => {
11321154
format!("vim.env['{}']", env)
@@ -1274,13 +1296,16 @@ pub fn eval(program: parser::Program, is_test: bool) -> String {
12741296
output
12751297
}
12761298

1277-
pub fn generate(contents: &str, is_test: bool) -> String {
1299+
pub fn generate(
1300+
contents: &str,
1301+
is_test: bool,
1302+
) -> Result<String, (String, String)> {
12781303
let lexer = Lexer::new(contents);
12791304
let parser = new_parser(&lexer);
12801305
let program = parser.parse_program();
12811306

12821307
let result = eval(program, is_test);
1283-
println!("{}", result);
1308+
// println!("{}", result);
12841309

12851310
let config = stylua_lib::Config::new()
12861311
.with_indent_type(stylua_lib::IndentType::Spaces)
@@ -1293,8 +1318,8 @@ pub fn generate(contents: &str, is_test: bool) -> String {
12931318
None,
12941319
stylua_lib::OutputVerification::None,
12951320
) {
1296-
Ok(res) => res,
1297-
Err(err) => format!("{}\n\n{}", result, err),
1321+
Ok(res) => Ok(res),
1322+
Err(err) => Err((result, err.to_string())),
12981323
}
12991324
}
13001325

@@ -1315,7 +1340,7 @@ mod test {
13151340
let mut settings = insta::Settings::clone_current();
13161341
settings.set_snapshot_path("../testdata/output/");
13171342
settings.bind(|| {
1318-
insta::assert_snapshot!(generate(contents, false));
1343+
insta::assert_snapshot!(generate(contents, false).unwrap());
13191344
});
13201345
}
13211346
};
@@ -1326,7 +1351,7 @@ mod test {
13261351
#[test]
13271352
fn $name() {
13281353
let vim_contents = include_str!($path);
1329-
let lua_contents = generate(vim_contents, true);
1354+
let lua_contents = generate(vim_contents, true).unwrap();
13301355

13311356
let filepath = concat!(
13321357
env!("CARGO_MANIFEST_DIR"),
@@ -1377,7 +1402,7 @@ mod test {
13771402
export var x = MyCoolFunc() + 1
13781403
"#;
13791404

1380-
let generated = generate(contents, false);
1405+
let generated = generate(contents, false).unwrap();
13811406
let eval = exec_lua(&generated).unwrap();
13821407
assert_eq!(eval["x"], 6.into());
13831408
}
@@ -1390,7 +1415,7 @@ mod test {
13901415
export var x = len("hello")
13911416
"#;
13921417

1393-
let generated = generate(contents, false);
1418+
let generated = generate(contents, false).unwrap();
13941419
let eval = exec_lua(&generated).unwrap();
13951420
assert_eq!(eval["x"], 5.into());
13961421
}
@@ -1412,7 +1437,7 @@ mod test {
14121437
export var x = len(nvim_get_autocmds({group: "matchparen"}))
14131438
"#;
14141439

1415-
let generated = generate(contents, false);
1440+
let generated = generate(contents, false).unwrap();
14161441
let eval = exec_lua(&generated).unwrap();
14171442
assert_eq!(eval["x"], 4.into());
14181443
}

crates/vim9-gen/testdata/busted/methods.vim

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ def Test_inplace_inplace_single()
4141

4242
assert_equal([2, 4], foo)
4343
enddef
44+
45+
def Test_method_precedence()
46+
var server = {filetype: true}
47+
assert_equal(false, !server->has_key('filetype'))
48+
enddef

crates/vim9-gen/testdata/output/busted_methods.lua

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ describe("filename", function()
66
local Test_inplace = nil
77
local Test_inplace_inplace_multi = nil
88
local Test_inplace_inplace_single = nil
9+
local Test_method_precedence = nil
910
-- vim9script
1011

1112
it("Test_string_methods", function()
@@ -95,5 +96,17 @@ describe("filename", function()
9596
-- Assert that errors is still empty
9697
assert.are.same({}, vim.v.errors)
9798
end)
99+
100+
it("Test_method_precedence", function()
101+
-- Set errors to empty
102+
vim.v.errors = {}
103+
104+
-- Actual test
105+
local server = { ["filetype"] = true }
106+
NVIM9.fn["assert_equal"](false, NVIM9.prefix["Bang"](NVIM9.fn["has_key"](server, "filetype")))
107+
108+
-- Assert that errors is still empty
109+
assert.are.same({}, vim.v.errors)
110+
end)
98111
end)
99112
return __VIM9_MODULE

crates/vim9-gen/testdata/output/vim9_gen__test__autocmd.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/vim9-gen/src/lib.rs
3-
assertion_line: 1007
4-
expression: "generate(contents, false)"
3+
assertion_line: 1369
4+
expression: "generate(contents, false).unwrap()"
55
---
66
local NVIM9 = require("vim9script")
77
local __VIM9_MODULE = {}
@@ -23,6 +23,6 @@ vim.api.nvim_create_autocmd({ "WinLeave" }, {
2323
end,
2424
})
2525

26-
local x = NVIM9.fn["len"](vim.api["nvim_get_autocmds"]({ group = "matchparen" }))
26+
local x = NVIM9.fn["len"](vim.api["nvim_get_autocmds"]({ ["group"] = "matchparen" }))
2727
return __VIM9_MODULE
2828

crates/vim9-gen/testdata/output/vim9_gen__test__cfilter.snap

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/vim9-gen/src/lib.rs
3-
assertion_line: 1364
4-
expression: "generate(contents, false)"
3+
assertion_line: 1388
4+
expression: "generate(contents, false).unwrap()"
55
---
66
local NVIM9 = require("vim9script")
77
local __VIM9_MODULE = {}
@@ -110,22 +110,22 @@ Qf_filter = function(qf, searchpat, bang)
110110

111111
items = NVIM9.fn_mut("filter", { Xgetlist(), Cond }, { replace = 0 })
112112
title = NVIM9.ops["StringConcat"](NVIM9.ops["StringConcat"](NVIM9.ops["StringConcat"](cmd, " /"), pat), "/")
113-
Xsetlist({}, " ", { title = title, items = items })
113+
Xsetlist({}, " ", { ["title"] = title, ["items"] = items })
114114
end
115115

116116
vim.api.nvim_create_user_command("Cfilter", function(__vim9_arg_1)
117117
Qf_filter(true, __vim9_arg_1.args, (__vim9_arg_1.bang and "!" or ""))
118118
end, {
119-
nargs = "+",
120119
bang = true,
120+
nargs = "+",
121121
complete = nil,
122122
})
123123

124124
vim.api.nvim_create_user_command("Lfilter", function(__vim9_arg_1)
125125
Qf_filter(false, __vim9_arg_1.args, (__vim9_arg_1.bang and "!" or ""))
126126
end, {
127-
nargs = "+",
128127
bang = true,
128+
nargs = "+",
129129
complete = nil,
130130
})
131131

crates/vim9-parser/src/cmds/cmd_user.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ impl UserCommand {
5050
}
5151
"complete" => {
5252
parser.expect_token(TokenKind::Equal)?;
53-
command_complete = Some(parser.pop().text.to_string());
53+
let mut complete = parser.pop().text.to_string();
54+
if parser.front_kind() == TokenKind::Comma {
55+
complete += &parser.pop().text.to_string();
56+
complete += &parser.pop().text.to_string();
57+
}
58+
59+
command_complete = Some(complete);
5460
}
5561
"range" => {
5662
parser.expect_token(TokenKind::Equal)?;

0 commit comments

Comments
 (0)