Skip to content

Commit b45fa60

Browse files
committed
feat: handle hover info & go to definition for named arguments in calls
1 parent 4d37432 commit b45fa60

File tree

8 files changed

+408
-101
lines changed

8 files changed

+408
-101
lines changed

starlark/src/docs/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ impl DocParam {
654654
Some(indented)
655655
}
656656

657-
fn render_as_code(&self) -> String {
657+
pub fn render_as_code(&self) -> String {
658658
match self {
659659
DocParam::Arg {
660660
name,

starlark_lsp/src/bind.rs

+59-15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use std::collections::HashMap;
2020
use starlark::codemap::Pos;
2121
use starlark::codemap::Span;
2222
use starlark::syntax::AstModule;
23+
use starlark_syntax::syntax::ast::Argument;
24+
use starlark_syntax::syntax::ast::ArgumentP;
2325
use starlark_syntax::syntax::ast::AssignIdentP;
2426
use starlark_syntax::syntax::ast::AssignP;
2527
use starlark_syntax::syntax::ast::AstAssignIdent;
@@ -33,6 +35,7 @@ use starlark_syntax::syntax::ast::AstTypeExpr;
3335
use starlark_syntax::syntax::ast::Clause;
3436
use starlark_syntax::syntax::ast::DefP;
3537
use starlark_syntax::syntax::ast::Expr;
38+
use starlark_syntax::syntax::ast::ExprP;
3639
use starlark_syntax::syntax::ast::ForClause;
3740
use starlark_syntax::syntax::ast::ForP;
3841
use starlark_syntax::syntax::ast::IdentP;
@@ -43,21 +46,35 @@ use starlark_syntax::syntax::module::AstModuleFields;
4346
#[derive(Debug, Clone, Eq, PartialEq)]
4447
pub(crate) enum Assigner {
4548
/// Obtained from `load`. `name` is the symbol in that file, not necessarily the local name
46-
Load {
47-
path: AstString,
48-
name: AstString,
49-
},
50-
Argument, // From a function argument
51-
Assign, // From an assignment
49+
Load { path: AstString, name: AstString },
50+
/// From a function call argument
51+
Argument,
52+
/// From an assignment
53+
Assign,
5254
}
5355

5456
#[derive(Debug)]
5557
pub(crate) enum Bind {
56-
Set(Assigner, AstAssignIdent), // Variable assigned to directly
57-
Get(AstIdent), // Variable that is referenced
58-
GetDotted(GetDotted), // Variable is referenced, but is part of a dotted access
59-
Flow, // Flow control occurs here (if, for etc) - can arrive or leave at this point
60-
Scope(Scope), // Entering a new scope (lambda/def/comprehension)
58+
/// Variable assigned to directly
59+
Set(Assigner, AstAssignIdent),
60+
/// Variable that is referenced
61+
Get(AstIdent),
62+
/// Variable is referenced, but is part of a dotted access
63+
GetDotted(GetDotted),
64+
/// An indirect reference, i.e. a named argument in a function call
65+
IndirectReference(IndirectReference),
66+
/// Flow control occurs here (if, for etc) - can arrive or leave at this point
67+
Flow,
68+
/// Entering a new scope (lambda/def/comprehension)
69+
Scope(Scope),
70+
}
71+
72+
#[derive(Debug)]
73+
pub(crate) struct IndirectReference {
74+
pub(crate) argument_name: AstString,
75+
// TODO: This could also be a dotted access, another function call, etc. These kinds of
76+
// references are not captured at the moment.
77+
pub(crate) function: AstIdent,
6178
}
6279

6380
/// A 'get' bind that was part of a dotted member access pattern.
@@ -123,7 +140,7 @@ impl Scope {
123140
Bind::Scope(scope) => scope.free.iter().for_each(|(k, v)| {
124141
free.entry(k.clone()).or_insert(*v);
125142
}),
126-
Bind::Flow => {}
143+
Bind::IndirectReference(_) | Bind::Flow => {}
127144
}
128145
}
129146
for x in bound.keys() {
@@ -183,10 +200,19 @@ fn dot_access<'a>(lhs: &'a AstExpr, attribute: &'a AstString, res: &mut Vec<Bind
183200
attributes.push(attribute);
184201
f(lhs, attributes, res);
185202
}
186-
Expr::Call(name, parameters) => {
187-
f(name, attributes, res);
188-
// make sure that if someone does a(b).c, 'b' is bound and considered used.
203+
Expr::Call(func_name, parameters) => {
204+
f(func_name, attributes, res);
189205
for parameter in parameters {
206+
if let ExprP::Identifier(func_name) = &func_name.node {
207+
if let ArgumentP::Named(arg_name, _) = &parameter.node {
208+
res.push(Bind::IndirectReference(IndirectReference {
209+
argument_name: arg_name.clone(),
210+
function: func_name.clone(),
211+
}))
212+
}
213+
}
214+
215+
// make sure that if someone does a(b).c, 'b' is bound and considered used.
190216
expr(parameter.expr(), res);
191217
}
192218
}
@@ -221,6 +247,24 @@ fn expr(x: &AstExpr, res: &mut Vec<Bind>) {
221247
expr(&x.0, res);
222248
expr(&x.1, res)
223249
}),
250+
Expr::Call(func, args) => {
251+
expr(func, res);
252+
for x in args {
253+
if let ExprP::Identifier(function_ident) = &func.node {
254+
match &**x {
255+
Argument::Named(name, value) => {
256+
res.push(Bind::IndirectReference(IndirectReference {
257+
argument_name: name.clone(),
258+
function: function_ident.clone(),
259+
}));
260+
expr(value, res);
261+
}
262+
_ => expr(x.expr(), res),
263+
}
264+
}
265+
expr(x.expr(), res)
266+
}
267+
}
224268

225269
// Uninteresting - just recurse
226270
_ => x.visit_expr(|x| expr(x, res)),

starlark_lsp/src/completion.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,11 @@ impl<T: LspContext> Backend<T> {
282282
.and_then(|ast| ast.find_exported_symbol(name))
283283
.and_then(|symbol| match symbol.kind {
284284
SymbolKind::Constant | SymbolKind::Variable => None,
285-
SymbolKind::Method { argument_names } => Some(
286-
argument_names
285+
SymbolKind::Method { arguments } => Some(
286+
arguments
287287
.into_iter()
288-
.map(|name| CompletionItem {
289-
label: name,
288+
.map(|arg| CompletionItem {
289+
label: arg.name,
290290
kind: Some(CompletionItemKind::PROPERTY),
291291
..Default::default()
292292
})
@@ -325,6 +325,8 @@ impl<T: LspContext> Backend<T> {
325325
}
326326
// None of these can be functions, so can't have any parameters.
327327
IdentifierDefinition::LoadPath { .. }
328+
| IdentifierDefinition::LocationWithParameterReference { .. }
329+
| IdentifierDefinition::LoadedLocationWithParameterReference { .. }
328330
| IdentifierDefinition::StringLiteral { .. }
329331
| IdentifierDefinition::NotFound => None,
330332
})

0 commit comments

Comments
 (0)