Skip to content

Commit 8fc37fd

Browse files
giacomocavalierilpil
authored andcommitted
avoid needless clone and pattern traversal
1 parent 5ec0c66 commit 8fc37fd

File tree

1 file changed

+52
-100
lines changed

1 file changed

+52
-100
lines changed

compiler-core/src/language_server/code_action.rs

Lines changed: 52 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,6 +4444,7 @@ pub struct PatternMatchOnValue<'a, A> {
44444444
module: &'a Module,
44454445
params: &'a CodeActionParams,
44464446
compiler: &'a LspProjectCompiler<A>,
4447+
pattern_variable_under_cursor: Option<(&'a EcoString, Arc<Type>)>,
44474448
selected_value: Option<PatternMatchedValue<'a>>,
44484449
edits: TextEdits<'a>,
44494450
}
@@ -4468,15 +4469,15 @@ pub enum PatternMatchedValue<'a> {
44684469
function_range: Range,
44694470
},
44704471
LetVariable {
4471-
variable_name: EcoString,
4472+
variable_name: &'a EcoString,
44724473
variable_type: Arc<Type>,
44734474
/// The location of the entire let assignment the variable is part of,
44744475
/// so that we can add the pattern matching _after_ it.
44754476
///
44764477
assignment_location: SrcSpan,
44774478
},
44784479
UseVariable {
4479-
variable_name: EcoString,
4480+
variable_name: &'a EcoString,
44804481
variable_type: Arc<Type>,
44814482
/// The location of the entire use expression the variable is part of,
44824483
/// so that we can add the pattern matching _after_ it.
@@ -4500,6 +4501,7 @@ where
45004501
params,
45014502
compiler,
45024503
selected_value: None,
4504+
pattern_variable_under_cursor: None,
45034505
edits: TextEdits::new(line_numbers),
45044506
}
45054507
}
@@ -4531,6 +4533,7 @@ where
45314533
self.match_on_let_variable(variable_name, variable_type, location);
45324534
"Pattern match on variable"
45334535
}
4536+
45344537
None => return vec![],
45354538
};
45364539

@@ -4615,7 +4618,7 @@ where
46154618

46164619
fn match_on_let_variable(
46174620
&mut self,
4618-
variable_name: EcoString,
4621+
variable_name: &EcoString,
46194622
variable_type: Arc<Type>,
46204623
assignment_location: SrcSpan,
46214624
) {
@@ -4781,94 +4784,6 @@ where
47814784
pattern.push(')');
47824785
Some(pattern)
47834786
}
4784-
4785-
fn pattern_variable_under_cursor(
4786-
&self,
4787-
pattern: &'a TypedPattern,
4788-
) -> Option<(&'a EcoString, Arc<Type>)> {
4789-
match pattern {
4790-
Pattern::Int { .. }
4791-
| Pattern::Float { .. }
4792-
| Pattern::String { .. }
4793-
| Pattern::BitArraySize(_)
4794-
| Pattern::Discard { .. }
4795-
| Pattern::Invalid { .. } => None,
4796-
4797-
Pattern::Variable {
4798-
location,
4799-
name,
4800-
type_,
4801-
..
4802-
} => {
4803-
if within(
4804-
self.params.range,
4805-
self.edits.src_span_to_lsp_range(*location),
4806-
) {
4807-
Some((name, type_.clone()))
4808-
} else {
4809-
None
4810-
}
4811-
}
4812-
4813-
Pattern::Assign { pattern, .. } => self.pattern_variable_under_cursor(pattern),
4814-
4815-
Pattern::Constructor { arguments, .. } => arguments
4816-
.iter()
4817-
.find_map(|argument| self.pattern_variable_under_cursor(&argument.value)),
4818-
4819-
Pattern::Tuple { elements, .. } => elements
4820-
.iter()
4821-
.find_map(|element| self.pattern_variable_under_cursor(element)),
4822-
4823-
Pattern::List { elements, tail, .. } => elements
4824-
.iter()
4825-
.find_map(|element| self.pattern_variable_under_cursor(element))
4826-
.or_else(|| {
4827-
tail.as_ref()
4828-
.and_then(|tail| self.pattern_variable_under_cursor(tail))
4829-
}),
4830-
4831-
Pattern::BitArray { segments, .. } => segments
4832-
.iter()
4833-
.flat_map(|segment| &segment.options)
4834-
.find_map(|option| {
4835-
option
4836-
.value()
4837-
.and_then(|pattern| self.pattern_variable_under_cursor(pattern))
4838-
}),
4839-
4840-
Pattern::StringPrefix {
4841-
left_side_assignment: Some((name, location)),
4842-
..
4843-
} => {
4844-
if within(
4845-
self.params.range,
4846-
self.edits.src_span_to_lsp_range(*location),
4847-
) {
4848-
Some((name, type_::string()))
4849-
} else {
4850-
None
4851-
}
4852-
}
4853-
4854-
Pattern::StringPrefix {
4855-
right_side_assignment: AssignName::Variable(name),
4856-
right_location,
4857-
..
4858-
} => {
4859-
if within(
4860-
self.params.range,
4861-
self.edits.src_span_to_lsp_range(*right_location),
4862-
) {
4863-
Some((name, type_::string()))
4864-
} else {
4865-
None
4866-
}
4867-
}
4868-
4869-
Pattern::StringPrefix { .. } => None,
4870-
}
4871-
}
48724787
}
48734788

48744789
impl<'ast, IO> ast::visit::Visit<'ast> for PatternMatchOnValue<'ast, IO>
@@ -4952,18 +4867,14 @@ where
49524867
}
49534868

49544869
fn visit_typed_assignment(&mut self, assignment: &'ast TypedAssignment) {
4955-
if let Some((name, type_)) = self.pattern_variable_under_cursor(&assignment.pattern) {
4870+
ast::visit::visit_typed_assignment(self, assignment);
4871+
if let Some((name, ref type_)) = self.pattern_variable_under_cursor {
49564872
self.selected_value = Some(PatternMatchedValue::LetVariable {
4957-
variable_name: name.clone(),
4958-
variable_type: type_,
4873+
variable_name: name,
4874+
variable_type: type_.clone(),
49594875
assignment_location: assignment.location,
49604876
});
4961-
// If we've found the variable to pattern match on, there's no
4962-
// point in keeping traversing the AST.
4963-
return;
49644877
}
4965-
4966-
ast::visit::visit_typed_assignment(self, assignment);
49674878
}
49684879

49694880
fn visit_typed_use(&mut self, use_: &'ast TypedUse) {
@@ -4989,7 +4900,7 @@ where
49894900
let variable_range = self.edits.src_span_to_lsp_range(*variable_location);
49904901
if within(self.params.range, variable_range) {
49914902
self.selected_value = Some(PatternMatchedValue::UseVariable {
4992-
variable_name: name.clone(),
4903+
variable_name: name,
49934904
variable_type: type_.clone(),
49944905
use_location: use_.location,
49954906
});
@@ -5002,6 +4913,47 @@ where
50024913

50034914
ast::visit::visit_typed_use(self, use_);
50044915
}
4916+
4917+
fn visit_typed_pattern_variable(
4918+
&mut self,
4919+
location: &'ast SrcSpan,
4920+
name: &'ast EcoString,
4921+
type_: &'ast Arc<Type>,
4922+
_origin: &'ast VariableOrigin,
4923+
) {
4924+
if within(
4925+
self.params.range,
4926+
self.edits.src_span_to_lsp_range(*location),
4927+
) {
4928+
self.pattern_variable_under_cursor = Some((name, type_.clone()));
4929+
}
4930+
}
4931+
4932+
fn visit_typed_pattern_string_prefix(
4933+
&mut self,
4934+
_location: &'ast SrcSpan,
4935+
_left_location: &'ast SrcSpan,
4936+
left_side_assignment: &'ast Option<(EcoString, SrcSpan)>,
4937+
right_location: &'ast SrcSpan,
4938+
_left_side_string: &'ast EcoString,
4939+
right_side_assignment: &'ast AssignName,
4940+
) {
4941+
if let Some((name, location)) = left_side_assignment
4942+
&& within(
4943+
self.params.range,
4944+
self.edits.src_span_to_lsp_range(*location),
4945+
)
4946+
{
4947+
self.pattern_variable_under_cursor = Some((name, type_::string()));
4948+
} else if let AssignName::Variable(name) = right_side_assignment
4949+
&& within(
4950+
self.params.range,
4951+
self.edits.src_span_to_lsp_range(*right_location),
4952+
)
4953+
{
4954+
self.pattern_variable_under_cursor = Some((name, type_::string()));
4955+
}
4956+
}
50054957
}
50064958

50074959
/// Given a type and its module, returns a list of its *importable*

0 commit comments

Comments
 (0)