Skip to content

Commit

Permalink
Merge b960728 into cfd68d4
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored Aug 29, 2024
2 parents cfd68d4 + b960728 commit dcdb546
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 37 deletions.
21 changes: 14 additions & 7 deletions tooling/lsp/src/requests/completion/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use noirc_frontend::token::Keyword;
use strum::IntoEnumIterator;

use super::{
completion_items::{simple_completion_item, snippet_completion_item},
completion_items::{
completion_item_with_trigger_parameter_hints_command, simple_completion_item,
snippet_completion_item,
},
kinds::FunctionCompletionKind,
name_matches, NodeFinder,
};
Expand Down Expand Up @@ -31,12 +34,16 @@ impl<'a> NodeFinder<'a> {
}
}

self.completion_items.push(snippet_completion_item(
label,
CompletionItemKind::FUNCTION,
insert_text,
description,
));
self.completion_items.push(
completion_item_with_trigger_parameter_hints_command(
snippet_completion_item(
label,
CompletionItemKind::FUNCTION,
insert_text,
description,
),
),
);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions tooling/lsp/src/requests/completion/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,19 +470,19 @@ mod completion_tests {
assert_completion_excluding_auto_import(
src,
vec![
snippet_completion_item(
completion_item_with_trigger_parameter_hints_command(snippet_completion_item(
"assert(…)",
CompletionItemKind::FUNCTION,
"assert(${1:predicate})",
Some("fn(T)".to_string()),
),
)),
function_completion_item("assert_constant(…)", "assert_constant(${1:x})", "fn(T)"),
snippet_completion_item(
completion_item_with_trigger_parameter_hints_command(snippet_completion_item(
"assert_eq(…)",
CompletionItemKind::FUNCTION,
"assert_eq(${1:lhs}, ${2:rhs})",
Some("fn(T, T)".to_string()),
),
)),
],
)
.await;
Expand Down
137 changes: 124 additions & 13 deletions tooling/lsp/src/requests/signature_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use lsp_types::{
};
use noirc_errors::{Location, Span};
use noirc_frontend::{
ast::{CallExpression, Expression, FunctionReturnType, MethodCallExpression},
ast::{
CallExpression, ConstrainKind, ConstrainStatement, Expression, ExpressionKind,
FunctionReturnType, MethodCallExpression,
},
hir_def::{function::FuncMeta, stmt::HirPattern},
macros_api::NodeInterner,
node_interner::ReferenceId,
Expand Down Expand Up @@ -104,6 +107,55 @@ impl<'a> SignatureFinder<'a> {
);
}

pub(super) fn find_in_constrain_statement(&mut self, constrain_statement: &ConstrainStatement) {
self.find_in_expression(&constrain_statement.0);

if let Some(exp) = &constrain_statement.1 {
self.find_in_expression(exp);
}

if self.signature_help.is_some() {
return;
}

let arguments_span = if let Some(expr) = &constrain_statement.1 {
Span::from(constrain_statement.0.span.start()..expr.span.end())
} else {
constrain_statement.0.span
};

if !self.includes_span(arguments_span) {
return;
}

match constrain_statement.2 {
ConstrainKind::Assert => {
let mut arguments = vec![constrain_statement.0.clone()];
if let Some(expr) = &constrain_statement.1 {
arguments.push(expr.clone());
}

let active_parameter = self.compute_active_parameter(&arguments);
let signature_information = self.assert_signature_information(active_parameter);
self.set_signature_help(signature_information);
}
ConstrainKind::AssertEq => {
if let ExpressionKind::Infix(infix) = &constrain_statement.0.kind {
let mut arguments = vec![infix.lhs.clone(), infix.rhs.clone()];
if let Some(expr) = &constrain_statement.1 {
arguments.push(expr.clone());
}

let active_parameter = self.compute_active_parameter(&arguments);
let signature_information =
self.assert_eq_signature_information(active_parameter);
self.set_signature_help(signature_information);
}
}
ConstrainKind::Constrain => (),
}
}

fn try_compute_signature_help(
&mut self,
arguments: &[Expression],
Expand All @@ -119,18 +171,7 @@ impl<'a> SignatureFinder<'a> {
return;
}

let mut active_parameter = None;
for (index, arg) in arguments.iter().enumerate() {
if self.includes_span(arg.span) || arg.span.start() as usize >= self.byte_index {
active_parameter = Some(index as u32);
break;
}
}

if active_parameter.is_none() {
active_parameter = Some(arguments.len() as u32);
}

let active_parameter = self.compute_active_parameter(arguments);
let location = Location::new(name_span, self.file);

// Check if the call references a named function
Expand Down Expand Up @@ -267,6 +308,60 @@ impl<'a> SignatureFinder<'a> {
}
}

fn assert_signature_information(&self, active_parameter: Option<u32>) -> SignatureInformation {
self.hardcoded_signature_information(
active_parameter,
"assert",
&["predicate: bool", "[failure_message: str<N>]"],
)
}

fn assert_eq_signature_information(
&self,
active_parameter: Option<u32>,
) -> SignatureInformation {
self.hardcoded_signature_information(
active_parameter,
"assert_eq",
&["lhs: T", "rhs: T", "[failure_message: str<N>]"],
)
}

fn hardcoded_signature_information(
&self,
active_parameter: Option<u32>,
name: &str,
arguments: &[&str],
) -> SignatureInformation {
let mut label = String::new();
let mut parameters = Vec::new();

label.push_str(name);
label.push('(');
for (index, typ) in arguments.iter().enumerate() {
if index > 0 {
label.push_str(", ");
}

let parameter_start = label.chars().count();
label.push_str(typ);
let parameter_end = label.chars().count();

parameters.push(ParameterInformation {
label: ParameterLabel::LabelOffsets([parameter_start as u32, parameter_end as u32]),
documentation: None,
});
}
label.push(')');

SignatureInformation {
label,
documentation: None,
parameters: Some(parameters),
active_parameter,
}
}

fn hir_pattern_to_argument(&self, pattern: &HirPattern, text: &mut String) {
match pattern {
HirPattern::Identifier(hir_ident) => {
Expand All @@ -286,6 +381,22 @@ impl<'a> SignatureFinder<'a> {
self.signature_help = Some(signature_help);
}

fn compute_active_parameter(&self, arguments: &[Expression]) -> Option<u32> {
let mut active_parameter = None;
for (index, arg) in arguments.iter().enumerate() {
if self.includes_span(arg.span) || arg.span.start() as usize >= self.byte_index {
active_parameter = Some(index as u32);
break;
}
}

if active_parameter.is_none() {
active_parameter = Some(arguments.len() as u32);
}

active_parameter
}

fn includes_span(&self, span: Span) -> bool {
span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize
}
Expand Down
47 changes: 47 additions & 0 deletions tooling/lsp/src/requests/signature_help/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,51 @@ mod signature_help_tests {

assert_eq!(signature.active_parameter, Some(0));
}

#[test]
async fn test_signature_help_for_assert() {
let src = r#"
fn bar() {
assert(>|<1, "hello");
}
"#;

let signature_help = get_signature_help(src).await;
assert_eq!(signature_help.signatures.len(), 1);

let signature = &signature_help.signatures[0];
assert_eq!(signature.label, "assert(predicate: bool, [failure_message: str<N>])");

let params = signature.parameters.as_ref().unwrap();
assert_eq!(params.len(), 2);

check_label(&signature.label, &params[0].label, "predicate: bool");
check_label(&signature.label, &params[1].label, "[failure_message: str<N>]");

assert_eq!(signature.active_parameter, Some(0));
}

#[test]
async fn test_signature_help_for_assert_eq() {
let src = r#"
fn bar() {
assert_eq(>|<true, false, "oops");
}
"#;

let signature_help = get_signature_help(src).await;
assert_eq!(signature_help.signatures.len(), 1);

let signature = &signature_help.signatures[0];
assert_eq!(signature.label, "assert_eq(lhs: T, rhs: T, [failure_message: str<N>])");

let params = signature.parameters.as_ref().unwrap();
assert_eq!(params.len(), 3);

check_label(&signature.label, &params[0].label, "lhs: T");
check_label(&signature.label, &params[1].label, "rhs: T");
check_label(&signature.label, &params[2].label, "[failure_message: str<N>]");

assert_eq!(signature.active_parameter, Some(0));
}
}
18 changes: 5 additions & 13 deletions tooling/lsp/src/requests/signature_help/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use super::SignatureFinder;

use noirc_frontend::{
ast::{
ArrayLiteral, AssignStatement, BlockExpression, CastExpression, ConstrainStatement,
ConstructorExpression, Expression, ExpressionKind, ForLoopStatement, ForRange,
IfExpression, IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal,
MemberAccessExpression, NoirFunction, NoirTrait, NoirTraitImpl, Statement, StatementKind,
TraitImplItem, TraitItem, TypeImpl,
ArrayLiteral, AssignStatement, BlockExpression, CastExpression, ConstructorExpression,
Expression, ExpressionKind, ForLoopStatement, ForRange, IfExpression, IndexExpression,
InfixExpression, LValue, Lambda, LetStatement, Literal, MemberAccessExpression,
NoirFunction, NoirTrait, NoirTraitImpl, Statement, StatementKind, TraitImplItem, TraitItem,
TypeImpl,
},
parser::{Item, ItemKind},
ParsedModule,
Expand Down Expand Up @@ -136,14 +136,6 @@ impl<'a> SignatureFinder<'a> {
self.find_in_expression(&let_statement.expression);
}

pub(super) fn find_in_constrain_statement(&mut self, constrain_statement: &ConstrainStatement) {
self.find_in_expression(&constrain_statement.0);

if let Some(exp) = &constrain_statement.1 {
self.find_in_expression(exp);
}
}

pub(super) fn find_in_assign_statement(&mut self, assign_statement: &AssignStatement) {
self.find_in_lvalue(&assign_statement.lvalue);
self.find_in_expression(&assign_statement.expression);
Expand Down

0 comments on commit dcdb546

Please sign in to comment.