feat(lsp): find_node for TypedArgVia
This commit is contained in:
parent
d22ee6e086
commit
7c5b9aa35e
|
@ -237,6 +237,34 @@ pub struct Function<T, Expr, Arg> {
|
||||||
pub can_error: bool,
|
pub can_error: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypedFunction {
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
self.arguments
|
||||||
|
.iter()
|
||||||
|
.find_map(|arg| arg.find_node(byte_index))
|
||||||
|
.or_else(|| self.body.find_node(byte_index))
|
||||||
|
.or_else(|| {
|
||||||
|
self.return_annotation
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|a| a.find_node(byte_index))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypedTest {
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
self.arguments
|
||||||
|
.iter()
|
||||||
|
.find_map(|arg| arg.find_node(byte_index))
|
||||||
|
.or_else(|| self.body.find_node(byte_index))
|
||||||
|
.or_else(|| {
|
||||||
|
self.return_annotation
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|a| a.find_node(byte_index))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type TypedTypeAlias = TypeAlias<Rc<Type>>;
|
pub type TypedTypeAlias = TypeAlias<Rc<Type>>;
|
||||||
pub type UntypedTypeAlias = TypeAlias<()>;
|
pub type UntypedTypeAlias = TypeAlias<()>;
|
||||||
|
|
||||||
|
@ -496,6 +524,18 @@ pub struct Validator<T, Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypedValidator {
|
impl TypedValidator {
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
self.params
|
||||||
|
.iter()
|
||||||
|
.find_map(|arg| arg.find_node(byte_index))
|
||||||
|
.or_else(|| self.fun.find_node(byte_index))
|
||||||
|
.or_else(|| {
|
||||||
|
self.other_fun
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|f| f.find_node(byte_index))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_function_definition<'a, F>(
|
pub fn into_function_definition<'a, F>(
|
||||||
&'a self,
|
&'a self,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
|
@ -592,43 +632,18 @@ impl TypedDefinition {
|
||||||
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
// Note that the fn span covers the function head, not
|
// Note that the fn span covers the function head, not
|
||||||
// the entire statement.
|
// the entire statement.
|
||||||
match self {
|
let located = match self {
|
||||||
Definition::Validator(Validator {
|
Definition::Validator(validator) => validator.find_node(byte_index),
|
||||||
fun: Function { body, .. },
|
Definition::Fn(func) => func.find_node(byte_index),
|
||||||
other_fun:
|
Definition::Test(func) => func.find_node(byte_index),
|
||||||
Some(Function {
|
_ => None,
|
||||||
body: other_body, ..
|
};
|
||||||
}),
|
|
||||||
..
|
if located.is_none() && self.location().contains(byte_index) {
|
||||||
}) => {
|
return Some(Located::Definition(self));
|
||||||
if let Some(located) = body.find_node(byte_index) {
|
|
||||||
return Some(located);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(located) = other_body.find_node(byte_index) {
|
located
|
||||||
return Some(located);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Definition::Fn(Function { body, .. })
|
|
||||||
| Definition::Test(Function { body, .. })
|
|
||||||
| Definition::Validator(Validator {
|
|
||||||
fun: Function { body, .. },
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if let Some(located) = body.find_node(byte_index) {
|
|
||||||
return Some(located);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.location().contains(byte_index) {
|
|
||||||
Some(Located::Definition(self))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,20 +652,22 @@ pub enum Located<'a> {
|
||||||
Expression(&'a TypedExpr),
|
Expression(&'a TypedExpr),
|
||||||
Pattern(&'a TypedPattern, Rc<Type>),
|
Pattern(&'a TypedPattern, Rc<Type>),
|
||||||
Definition(&'a TypedDefinition),
|
Definition(&'a TypedDefinition),
|
||||||
|
Argument(&'a ArgName, Rc<Type>),
|
||||||
|
Annotation(&'a Annotation),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Located<'a> {
|
impl<'a> Located<'a> {
|
||||||
pub fn definition_location(&self) -> Option<DefinitionLocation<'_>> {
|
pub fn definition_location(&self) -> Option<DefinitionLocation<'_>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Expression(expression) => expression.definition_location(),
|
Self::Expression(expression) => expression.definition_location(),
|
||||||
// TODO: Revise definition location semantic for 'Pattern'
|
|
||||||
// e.g. for constructors, we might want to show the type definition
|
|
||||||
// for that constructor.
|
|
||||||
Self::Pattern(_, _) => None,
|
|
||||||
Self::Definition(definition) => Some(DefinitionLocation {
|
Self::Definition(definition) => Some(DefinitionLocation {
|
||||||
module: None,
|
module: None,
|
||||||
span: definition.location(),
|
span: definition.location(),
|
||||||
}),
|
}),
|
||||||
|
// TODO: Revise definition location semantic for 'Pattern'
|
||||||
|
// e.g. for constructors, we might want to show the type definition
|
||||||
|
// for that constructor.
|
||||||
|
Self::Pattern(_, _) | Located::Argument(_, _) | Located::Annotation(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,6 +828,18 @@ impl<A> Arg<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypedArg {
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
if self.arg_name.location().contains(byte_index) {
|
||||||
|
Some(Located::Argument(&self.arg_name, self.tipo.clone()))
|
||||||
|
} else {
|
||||||
|
self.annotation
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|annotation| annotation.find_node(byte_index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type TypedArgVia = ArgVia<Rc<Type>, TypedExpr>;
|
pub type TypedArgVia = ArgVia<Rc<Type>, TypedExpr>;
|
||||||
pub type UntypedArgVia = ArgVia<(), UntypedExpr>;
|
pub type UntypedArgVia = ArgVia<(), UntypedExpr>;
|
||||||
|
|
||||||
|
@ -835,6 +864,23 @@ impl<T, Ann> From<ArgVia<T, Ann>> for Arg<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypedArgVia {
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
if self.arg_name.location().contains(byte_index) {
|
||||||
|
Some(Located::Argument(&self.arg_name, self.tipo.clone()))
|
||||||
|
} else {
|
||||||
|
// `via` is done first here because when there is no manually written
|
||||||
|
// annotation, it seems one is injected leading to a `found` returning too early
|
||||||
|
// because the span of the filled in annotation matches the span of the via expr.
|
||||||
|
self.via.find_node(byte_index).or_else(|| {
|
||||||
|
self.annotation
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|annotation| annotation.find_node(byte_index))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum ArgName {
|
pub enum ArgName {
|
||||||
Discarded {
|
Discarded {
|
||||||
|
@ -851,6 +897,15 @@ pub enum ArgName {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgName {
|
impl ArgName {
|
||||||
|
pub fn location(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
ArgName::Discarded { location, .. } => *location,
|
||||||
|
ArgName::Named { location, .. } => *location,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the name of the variable if it is named, otherwise None.
|
||||||
|
/// Code gen uses the fact that this returns None to do certain things.
|
||||||
pub fn get_variable_name(&self) -> Option<&str> {
|
pub fn get_variable_name(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
ArgName::Discarded { .. } => None,
|
ArgName::Discarded { .. } => None,
|
||||||
|
@ -858,10 +913,15 @@ impl ArgName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_name(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ArgName::Discarded { name, .. } | ArgName::Named { name, .. } => name.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_label(&self) -> String {
|
pub fn get_label(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
ArgName::Discarded { label, .. } => label.to_string(),
|
ArgName::Discarded { label, .. } | ArgName::Named { label, .. } => label.to_string(),
|
||||||
ArgName::Named { label, .. } => label.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1022,6 +1082,28 @@ impl Annotation {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
|
||||||
|
if !self.location().contains(byte_index) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let located = match self {
|
||||||
|
Annotation::Constructor { arguments, .. } => {
|
||||||
|
arguments.iter().find_map(|arg| arg.find_node(byte_index))
|
||||||
|
}
|
||||||
|
Annotation::Fn { arguments, ret, .. } => arguments
|
||||||
|
.iter()
|
||||||
|
.find_map(|arg| arg.find_node(byte_index))
|
||||||
|
.or_else(|| ret.find_node(byte_index)),
|
||||||
|
Annotation::Tuple { elems, .. } => {
|
||||||
|
elems.iter().find_map(|arg| arg.find_node(byte_index))
|
||||||
|
}
|
||||||
|
Annotation::Var { .. } | Annotation::Hole { .. } => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
located.or(Some(Located::Annotation(self)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||||
|
|
|
@ -399,6 +399,12 @@ impl Server {
|
||||||
|
|
||||||
// TODO: autocompletion for expressions
|
// TODO: autocompletion for expressions
|
||||||
Some(Located::Expression(_expression)) => None,
|
Some(Located::Expression(_expression)) => None,
|
||||||
|
|
||||||
|
// TODO: autocompletion for arguments?
|
||||||
|
Some(Located::Argument(_arg_name, _tipo)) => None,
|
||||||
|
|
||||||
|
// TODO: autocompletion for annotation?
|
||||||
|
Some(Located::Annotation(_annotation)) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +516,9 @@ impl Server {
|
||||||
Some(expression.tipo()),
|
Some(expression.tipo()),
|
||||||
),
|
),
|
||||||
Located::Pattern(pattern, tipo) => (pattern.location(), None, Some(tipo)),
|
Located::Pattern(pattern, tipo) => (pattern.location(), None, Some(tipo)),
|
||||||
|
Located::Argument(arg_name, tipo) => (arg_name.location(), None, Some(tipo)),
|
||||||
Located::Definition(_) => return Ok(None),
|
Located::Definition(_) => return Ok(None),
|
||||||
|
Located::Annotation(_) => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let doc = definition_location
|
let doc = definition_location
|
||||||
|
@ -525,6 +533,8 @@ impl Server {
|
||||||
.and_then(|node| match node {
|
.and_then(|node| match node {
|
||||||
Located::Expression(_) => None,
|
Located::Expression(_) => None,
|
||||||
Located::Pattern(_, _) => None,
|
Located::Pattern(_, _) => None,
|
||||||
|
Located::Argument(_, _) => None,
|
||||||
|
Located::Annotation(_) => None,
|
||||||
Located::Definition(def) => def.doc(),
|
Located::Definition(def) => def.doc(),
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
Loading…
Reference in New Issue