Skip to content

Commit

Permalink
feat: add enum Definition as find_def result type
Browse files Browse the repository at this point in the history
  • Loading branch information
He1pa committed Jul 17, 2023
1 parent abb3871 commit 31af04c
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 244 deletions.
3 changes: 0 additions & 3 deletions kclvm/sema/src/resolver/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ impl<'ctx> Resolver<'ctx> {
self.ctx.pkgpath = pkgpath.to_string();
self.ctx.filename = filename.to_string();
let scope = self.scope_map.get(pkgpath).unwrap().clone();
if let ScopeKind::Package(files) = &mut scope.borrow_mut().kind {
files.push(filename.to_string())
}
self.scope = scope;
}
}
3 changes: 3 additions & 0 deletions kclvm/sema/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ impl<'ctx> Resolver<'ctx> {
Some(modules) => {
for module in modules {
self.ctx.filename = module.filename.to_string();
if let scope::ScopeKind::Package(files) = &mut self.scope.borrow_mut().kind {
files.push(module.filename.to_string())
}
for stmt in &module.body {
self.stmt(&stmt);
}
Expand Down
47 changes: 27 additions & 20 deletions kclvm/tools/src/LSP/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use lsp_types::CompletionItem;

use crate::goto_def::{get_identifier_last_name, resolve_var};
use crate::util::inner_most_expr_in_stmt;
use crate::util::{fix_missing_identifier, get_current_scope};
use crate::util::{fix_missing_identifier, get_pkg_scope};

/// Computes completions at the given position.
pub(crate) fn completion(
Expand Down Expand Up @@ -128,7 +128,10 @@ fn get_completion_items(expr: &Expr, prog_scope: &ProgramScope) -> IndexSet<Stri
)
}
// user module
if let Some(scope) = prog_scope.scope_map.get(&pkgpath_without_prefix!(id.pkgpath)) {
if let Some(scope) = prog_scope
.scope_map
.get(&pkgpath_without_prefix!(id.pkgpath))
{
let scope = scope.borrow();
for (name, obj) in &scope.elems {
if obj.borrow().ty.is_module() {
Expand All @@ -140,31 +143,35 @@ fn get_completion_items(expr: &Expr, prog_scope: &ProgramScope) -> IndexSet<Stri
return items;
}

let obj = resolve_var(
let def = resolve_var(
&fix_missing_identifier(&id.names),
&id.pkgpath,
&get_current_scope(&id.pkgpath, &prog_scope.scope_map),
&get_pkg_scope(&id.pkgpath, &prog_scope.scope_map),
&prog_scope.scope_map,
);

if let Some(obj) = obj {
match &obj.ty.kind {
// builtin (str) functions
kclvm_sema::ty::TypeKind::Str => {
let binding = STRING_MEMBER_FUNCTIONS;
for k in binding.keys() {
items.insert(format!("{}{}", k, "()"));
}
}
// schema attrs
kclvm_sema::ty::TypeKind::Schema(schema) => {
for k in schema.attrs.keys() {
if k != "__settings__" {
items.insert(k.clone());
if let Some(def) = def {
match def {
crate::goto_def::Definition::Object(obj) => {
match &obj.ty.kind {
// builtin (str) functions
kclvm_sema::ty::TypeKind::Str => {
let binding = STRING_MEMBER_FUNCTIONS;
for k in binding.keys() {
items.insert(format!("{}{}", k, "()"));
}
}
// schema attrs
kclvm_sema::ty::TypeKind::Schema(schema) => {
for k in schema.attrs.keys() {
if k != "__settings__" {
items.insert(k.clone());
}
}
}
_ => {}
}
}
_ => {}
crate::goto_def::Definition::Scope(_) => {}
}
}
}
Expand Down
168 changes: 97 additions & 71 deletions kclvm/tools/src/LSP/src/goto_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use std::rc::Rc;

use crate::to_lsp::lsp_pos;
use crate::util::{
get_current_scope, get_pos_from_real_path, get_real_path_from_external,
inner_most_expr_in_stmt, pre_process_identifier,
get_pkg_scope, get_pos_from_real_path, get_real_path_from_external, inner_most_expr_in_stmt,
pre_process_identifier,
};

// Navigates to the definition of an identifier.
Expand All @@ -38,11 +38,7 @@ pub(crate) fn goto_definition(
Some(node) => match node.node {
Stmt::Import(stmt) => goto_def_for_import(&stmt, kcl_pos, prog_scope, program),
_ => match find_def(node.clone(), kcl_pos, prog_scope) {
Some(obj) => {
let mut positions = IndexSet::new();
positions.insert((obj.start.clone(), obj.end.clone()));
positions_to_goto_def_resp(&positions)
}
Some(def) => positions_to_goto_def_resp(&def.get_positions()),
None => None,
},
},
Expand All @@ -69,11 +65,43 @@ pub(crate) fn goto_definition(
// }
// }

pub enum Definition {
Object(ScopeObject),
Scope(Scope),
}

impl Definition {
pub(crate) fn get_positions(&self) -> IndexSet<(KCLPos, KCLPos)> {
let mut positions = IndexSet::new();
match self {
Definition::Object(obj) => {
positions.insert((obj.start.clone(), obj.end.clone()));
}
Definition::Scope(scope) => match &scope.kind {
kclvm_sema::resolver::scope::ScopeKind::Package(modules) => {
for module in modules {
let dummy_pos = KCLPos {
filename: module.clone(),
line: 1,
column: None,
};
positions.insert((dummy_pos.clone(), dummy_pos));
}
}
_ => {
positions.insert((scope.start.clone(), scope.end.clone()));
}
},
}
positions
}
}

pub(crate) fn find_def(
node: Node<Stmt>,
kcl_pos: &KCLPos,
prog_scope: &ProgramScope,
) -> Option<ScopeObject> {
) -> Option<Definition> {
let (inner_expr, parent) = inner_most_expr_in_stmt(&node.node, kcl_pos, None);
if let Some(expr) = inner_expr {
if let Expr::Identifier(id) = expr.node {
Expand All @@ -91,23 +119,27 @@ pub(crate) fn find_def(
match parent {
Some(schema_expr_node) => {
if let Expr::Schema(schema_expr) = schema_expr_node.node {
let schema_obj = find_def(node, &schema_expr.name.get_pos(), prog_scope);
if let Some(schema) = schema_obj {
let schema_type = schema.ty.into_schema_type();
return find_attr_in_schema(
&schema_type,
&id.names,
&id.pkgpath,
&prog_scope.scope_map,
);
let schema_def =
find_def(node, &schema_expr.name.get_end_pos(), prog_scope);
if let Some(schema) = schema_def {
match schema {
Definition::Object(obj) => {
let schema_type = obj.ty.into_schema_type();
return find_attr_in_schema(
&schema_type,
&id.names,
&prog_scope.scope_map,
);
}
Definition::Scope(_) => todo!(),
}
}
}
}
None => {
return resolve_var(
&id.names,
&id.pkgpath,
&get_current_scope(&id.pkgpath, &prog_scope.scope_map),
&get_pkg_scope(&"".to_string(), &prog_scope.scope_map),
&prog_scope.scope_map,
);
}
Expand All @@ -119,86 +151,80 @@ pub(crate) fn find_def(

/// Similar to vars.rs/resolver_var, find a ScopeObj corresponding to the definition of identifier
pub(crate) fn resolve_var(
names: &[String],
pkgpath: &str,
node_names: &[Node<String>],
current_scope: &Scope,
scope_map: &IndexMap<String, Rc<RefCell<Scope>>>,
) -> Option<ScopeObject> {
) -> Option<Definition> {
let names = node_names
.iter()
.map(|node| node.node.clone())
.collect::<Vec<String>>();
match names.len() {
0 => None,
1 => {
let name = names[0].clone();
match current_scope.lookup(&name) {
Some(obj) => Some(obj.borrow().clone()),
Some(obj) => match obj.borrow().kind {
kclvm_sema::resolver::scope::ScopeObjectKind::Module => {
match scope_map.get(&name) {
Some(scope) => Some(Definition::Scope(scope.borrow().clone())),
None => None,
}
}
_ => Some(Definition::Object(obj.borrow().clone())),
},
None => None,
}
}
_ => {
if pkgpath.is_empty() {
let name = names[0].clone();
match current_scope.lookup(&name) {
Some(obj) => {
match &obj.borrow().ty.kind {
kclvm_sema::ty::TypeKind::Schema(schema_type) => {
find_attr_in_schema(
schema_type,
&names[1..],
pkgpath,
scope_map,
)
}
kclvm_sema::ty::TypeKind::Module(_) => {
let pkg = name;
match scope_map.get(&pkgpath_without_prefix!(pkg)) {
Some(scope) => {
return resolve_var(
&names[1..],
pkgpath,
&scope.borrow(),
scope_map,
)
}
None => None,
let name = names[0].clone();
match current_scope.lookup(&name) {
Some(obj) => {
match &obj.borrow().ty.kind {
kclvm_sema::ty::TypeKind::Schema(schema_type) => {
find_attr_in_schema(schema_type, &node_names[1..], scope_map)
}
kclvm_sema::ty::TypeKind::Module(module_ty) => {
match scope_map.get(&pkgpath_without_prefix!(module_ty.pkgpath)) {
Some(scope) => {
return resolve_var(
&node_names[1..],
&scope.borrow(),
scope_map,
);
}
None => None,
}
_ => None,
}
}
None => {
let pkg = name;
match scope_map.get(&pkgpath_without_prefix!(pkg)) {
Some(scope) => {
resolve_var(&names[1..], pkgpath, &scope.borrow(), scope_map)
}
None => None,
kclvm_sema::ty::TypeKind::Dict(_, _) => {
// Todo: find key def in dict
None
}
_ => None,
}
}
} else {
match scope_map.get(&pkgpath_without_prefix!(pkgpath)) {
Some(scope) => resolve_var(&names[1..], pkgpath, &scope.borrow(), scope_map),
None => None,
}
None => None,
}
}
}
}

pub fn find_attr_in_schema(
schema_type: &SchemaType,
names: &[String],
pkgpath: &str,
names: &[Node<String>],
scope_map: &IndexMap<String, Rc<RefCell<Scope>>>,
) -> Option<ScopeObject> {
let schema_pkg_scope = get_current_scope(&schema_type.pkgpath, scope_map);
let names = if schema_type.pkgpath.is_empty() {&names[1..] } else {names};
) -> Option<Definition> {
let schema_pkg_scope = get_pkg_scope(&schema_type.pkgpath, scope_map);
let names = if schema_type.pkgpath.is_empty() {
&names[1..]
} else {
names
};
for child in &schema_pkg_scope.children {
let child_scope = child.borrow();
if let kclvm_sema::resolver::scope::ScopeKind::Schema(schema_name) =
&child_scope.kind
{
if let kclvm_sema::resolver::scope::ScopeKind::Schema(schema_name) = &child_scope.kind {
if schema_name == &schema_type.name {
return resolve_var(&names, pkgpath, &child_scope, scope_map);
return resolve_var(&names, &child_scope, scope_map);
}
}
}
Expand Down
22 changes: 12 additions & 10 deletions kclvm/tools/src/LSP/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ pub(crate) fn hover(
match program.pos_to_stmt(kcl_pos) {
Some(node) => {
let mut docs: IndexSet<String> = IndexSet::new();
if let Some(obj) = find_def(node, kcl_pos, prog_scope) {
match obj.kind {
ScopeObjectKind::Definition => {
docs.insert(obj.ty.ty_str());
let doc = obj.ty.into_schema_type().doc.clone();
if !doc.is_empty() {
docs.insert(doc);
if let Some(def) = find_def(node, kcl_pos, prog_scope) {
if let crate::goto_def::Definition::Object(obj) = def {
match obj.kind {
ScopeObjectKind::Definition => {
docs.insert(obj.ty.ty_str());
let doc = obj.ty.into_schema_type().doc.clone();
if !doc.is_empty() {
docs.insert(doc);
}
}
_ => {
docs.insert(obj.ty.ty_str());
}
}
_ => {
docs.insert(obj.ty.ty_str());
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_def.k
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ schema Person:

p2 = Person {
n: Name{
name: "a"
name: pkg.m.name
}
}

s = p2.n.name
s = p2.n.name

a: int = 1

Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ schema Person:
"""
name: str
age: int

m : {str: str} = {
name: "a"
}
Loading

0 comments on commit 31af04c

Please sign in to comment.