Skip to content

Commit

Permalink
Feat/jump to associated signal of template (#32)
Browse files Browse the repository at this point in the history
* jump to signal in other template

* jump to component in template

* fmt

* clippy
  • Loading branch information
vuvoth authored Feb 19, 2024
1 parent 0765ffd commit 7d3d3c2
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 59 deletions.
2 changes: 1 addition & 1 deletion crates/lsp/src/global_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl GlobalState {
if let Some(token) =
lookup_token_at_postion(&file, &ast, params.text_document_position_params.position)
{
ranges = lookup_definition(&file, &ast, token);
ranges = lookup_definition(&file, &ast, &token);
};

let locations = ranges
Expand Down
185 changes: 142 additions & 43 deletions crates/lsp/src/handler/goto_definition.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@


use lsp_types::{Position, Range};
use parser::{
ast::{AstCircomProgram, AstNode},
syntax_node::SyntaxToken,
ast::{
AstCircomProgram, AstComponentCall, AstNode, AstTemplateDef,
AstTemplateName,
},
syntax_node::{SyntaxNode, SyntaxToken},
token_kind::TokenKind,
};
use rowan::{SyntaxText};

use super::lsp_utils::FileUtils;

/**
* api: lookup template have name,
*/

pub fn lookup_node_wrap_token(ast_type: TokenKind, token: &SyntaxToken) -> Option<SyntaxNode> {
let mut p = token.parent();
while let Some(t) = p {
if t.kind() == ast_type {
return Some(t);
}
p = t.parent();
}
None
}

pub fn lookup_token_at_postion(
file: &FileUtils,
ast: &AstCircomProgram,
Expand All @@ -24,75 +45,148 @@ pub fn lookup_token_at_postion(
})
}

pub fn lookup_component(template: &AstTemplateDef, text: SyntaxText) -> Option<AstTemplateName> {
if let Some(statements) = template.statements() {
for component in statements.components() {
if let Some(iden) = component.component_identifier() {
if iden.name().unwrap().syntax().text() == text {
return component.template();
}
}
}
}
None
}

pub fn lookup_definition(
file: &FileUtils,
ast: &AstCircomProgram,
token: SyntaxToken,
token: &SyntaxToken,
) -> Vec<Range> {
eprintln!("{token:?}");
let template_list = ast.template_list();

let mut result = Vec::new();

for template in template_list {
let template_name = template.template_name().unwrap();
if template_name.name().unwrap().syntax().text() == token.text() {
let range = file.range(template.syntax());
result.push(range);
let mut res = Vec::new();
let mut signal_outside = false;
if let Some(component_call) = lookup_node_wrap_token(TokenKind::ComponentCall, token) {
// find template called.
if let Some(ast_component_call) = AstComponentCall::cast(component_call) {
if let Some(signal) = ast_component_call.signal() {
if signal.syntax().text() == token.text() {
signal_outside = true;
// lookup template of componenet
if let Some(current_template) =
lookup_node_wrap_token(TokenKind::TemplateDef, token)
{
if let Some(ast_template_name) = lookup_component(
&AstTemplateDef::cast(current_template).unwrap(),
ast_component_call.component_name().unwrap().syntax().text(),
) {
if let Some(other_template) =
ast.get_template_by_name(&ast_template_name)
{
if let Some(inp) =
other_template.find_input_signal(&signal.syntax().text())
{
res.push(file.range(inp.syntax()));
}
if let Some(out) =
other_template.find_output_signal(&signal.syntax().text())
{
res.push(file.range(out.syntax()));
}
}
}
}
}
}
}
}

if !template
.syntax()
.text_range()
.contains_range(token.text_range())
{
continue;
}
if !signal_outside {
for template in template_list {
let template_name = template.template_name().unwrap();
if template_name.name().unwrap().syntax().text() == token.text() {
let range = file.range(template.syntax());
res.push(range);
}

if !template
.syntax()
.text_range()
.contains_range(token.text_range())
{
continue;
}

res.extend(lookup_signal_in_template(file, &template, token).into_iter());

if let Some(component_decl) = template.find_component(token.text()) {
res.push(file.range(component_decl.syntax()));
}

if let Some(fn_body) = template.func_body() {
if let Some(statements) = fn_body.statement_list() {
for signal in statements.input_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == token.text() {
result.push(file.range(signal.syntax()));
if let Some(fn_body) = template.func_body() {
if let Some(statements) = fn_body.statement_list() {
for var in statements.variables() {
if let Some(name) = var.variable_name() {
if name.syntax().text() == token.text() {
res.push(file.range(var.syntax()));
}
}
}
}
}
}
}
res
}

for signal in statements.output_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == token.text() {
result.push(file.range(signal.syntax()));
}
fn lookup_signal_in_template(
file: &FileUtils,
ast_template: &AstTemplateDef,
signal_token: &SyntaxToken,
) -> Vec<Range> {
let mut result = Vec::new();
if let Some(block) = ast_template.func_body() {
if let Some(statements) = block.statement_list() {
for signal in statements.input_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == signal_token.text() {
result.push(file.range(signal.syntax()));
}
}
}

for signal in statements.internal_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == token.text() {
result.push(file.range(signal.syntax()));
}
for signal in statements.output_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == signal_token.text() {
result.push(file.range(signal.syntax()));
}
}
}

for var in statements.variables() {
if let Some(name) = var.variable_name() {
if name.syntax().text() == token.text() {
result.push(file.range(var.syntax()));
}
for signal in statements.internal_signals() {
if let Some(name) = signal.signal_name() {
if name.syntax().text() == signal_token.text() {
result.push(file.range(signal.syntax()));
}
}
}
}
}
result
}

#[cfg(test)]
mod tests {
use parser::{ast::AstCircomProgram, parser::Parser, syntax_node::SyntaxNode};
use parser::{
ast::AstCircomProgram, parser::Parser, syntax_node::SyntaxNode, token_kind::TokenKind,
};
use rowan::ast::AstNode;

use crate::handler::lsp_utils::FileUtils;
use crate::handler::{
goto_definition::{lookup_node_wrap_token, lookup_token_at_postion},
lsp_utils::FileUtils,
};

#[test]
fn goto_decl_test() {
Expand Down Expand Up @@ -136,7 +230,7 @@ template Y() {
"#
.to_string();

let _file = FileUtils::create(&source);
let file = FileUtils::create(&source);

let green_node = Parser::parse_circom(&source);
let syntax_node = SyntaxNode::new_root(green_node.clone());
Expand All @@ -155,7 +249,12 @@ template Y() {

let tmp = signal_name.syntax().text_range().start();

println!("{:?}", program_ast.syntax().token_at_offset(tmp));
if let Some(token) = lookup_token_at_postion(&file, &program_ast, file.position(tmp)) {
println!(
"{:#?}",
lookup_node_wrap_token(TokenKind::TemplateDef, &token)
);
}
}
}
}
Loading

0 comments on commit 7d3d3c2

Please sign in to comment.