mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Add hover
This commit is contained in:
parent
9d365a8a57
commit
0db1cd9c28
6 changed files with 193 additions and 19 deletions
|
@ -1,7 +1,7 @@
|
|||
//! Traversals over the can ast.
|
||||
|
||||
use roc_module::{ident::Lowercase, symbol::Symbol};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
use roc_types::{subs::Variable, types::MemberImpl};
|
||||
|
||||
use crate::{
|
||||
|
@ -657,6 +657,35 @@ impl Visitor for TypeAtVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
struct TypeAtPositionVisitor {
|
||||
position: Position,
|
||||
region_typ: Option<(Region, Variable)>,
|
||||
}
|
||||
|
||||
impl Visitor for TypeAtPositionVisitor {
|
||||
fn should_visit(&mut self, region: Region) -> bool {
|
||||
region.contains_pos(self.position)
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &Expr, region: Region, var: Variable) {
|
||||
if region.contains_pos(self.position) {
|
||||
self.region_typ = Some((region, var));
|
||||
|
||||
walk_expr(self, expr, var);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_pattern(&mut self, pat: &Pattern, region: Region, opt_var: Option<Variable>) {
|
||||
if region.contains_pos(self.position) {
|
||||
if let Some(var) = opt_var {
|
||||
self.region_typ = Some((region, var));
|
||||
}
|
||||
|
||||
walk_pattern(self, pat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to find the type of an expression at `region`, if it exists.
|
||||
pub fn find_type_at(region: Region, decls: &Declarations) -> Option<Variable> {
|
||||
let mut visitor = TypeAtVisitor { region, typ: None };
|
||||
|
@ -675,6 +704,20 @@ pub enum FoundSymbol {
|
|||
}
|
||||
|
||||
/// Given an ability Foo implements foo : ..., returns (T, foo1) if the symbol at the given region is a
|
||||
/// Like [find_type_at], but descends into the narrowest node containing [position].
|
||||
pub fn find_closest_type_at(
|
||||
position: Position,
|
||||
decls: &Declarations,
|
||||
) -> Option<(Region, Variable)> {
|
||||
let mut visitor = TypeAtPositionVisitor {
|
||||
position,
|
||||
region_typ: None,
|
||||
};
|
||||
visitor.visit_decls(decls);
|
||||
visitor.region_typ
|
||||
}
|
||||
|
||||
/// Given an ability Foo has foo : ..., returns (T, foo1) if the symbol at the given region is a
|
||||
/// symbol foo1 that specializes foo for T. Otherwise if the symbol is foo but the specialization
|
||||
/// is unknown, (Foo, foo) is returned. Otherwise [None] is returned.
|
||||
pub fn find_symbol_at(
|
||||
|
|
|
@ -22,6 +22,10 @@ impl Region {
|
|||
self.start <= other.start && self.end >= other.end
|
||||
}
|
||||
|
||||
pub fn contains_pos(&self, pos: Position) -> bool {
|
||||
self.start <= pos && self.end >= pos
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.start == self.end
|
||||
}
|
||||
|
@ -356,6 +360,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LineInfo {
|
||||
line_offsets: Vec<u32>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue