Skip to content

Commit

Permalink
Allow renaming of variables inside bit array segments
Browse files Browse the repository at this point in the history
  • Loading branch information
GearsDatapacks committed Jan 20, 2025
1 parent 628c31a commit 76d4621
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 1 deletion.
40 changes: 39 additions & 1 deletion compiler-core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,6 @@ impl TypedPattern {
| Pattern::VarUsage { .. }
| Pattern::Assign { .. }
| Pattern::Discard { .. }
| Pattern::BitArray { .. }
| Pattern::StringPrefix { .. }
| Pattern::Invalid { .. } => Some(Located::Pattern(self)),

Expand All @@ -1973,6 +1972,11 @@ impl TypedPattern {
.or_else(|| tail.as_ref().and_then(|p| p.find_node(byte_index))),

Pattern::Tuple { elems, .. } => elems.iter().find_map(|p| p.find_node(byte_index)),

Pattern::BitArray { segments, .. } => segments
.iter()
.find_map(|segment| segment.find_node(byte_index))
.or(Some(Located::Pattern(self))),
}
.or(Some(Located::Pattern(self)))
}
Expand Down Expand Up @@ -2049,6 +2053,16 @@ impl TypedExprBitArraySegment {
}
}

impl TypedPatternBitArraySegment {
pub fn find_node(&self, byte_index: u32) -> Option<Located<'_>> {
self.value.find_node(byte_index).or_else(|| {
self.options
.iter()
.find_map(|option| option.find_node(byte_index))
})
}
}

pub type TypedConstantBitArraySegmentOption = BitArrayOption<TypedConstant>;

#[derive(Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -2178,6 +2192,30 @@ impl<A> BitArrayOption<A> {
}
}

impl BitArrayOption<TypedPattern> {
pub fn find_node(&self, byte_index: u32) -> Option<Located<'_>> {
match self {
BitArrayOption::Bytes { .. }
| BitArrayOption::Int { .. }
| BitArrayOption::Float { .. }
| BitArrayOption::Bits { .. }
| BitArrayOption::Utf8 { .. }
| BitArrayOption::Utf16 { .. }
| BitArrayOption::Utf32 { .. }
| BitArrayOption::Utf8Codepoint { .. }
| BitArrayOption::Utf16Codepoint { .. }
| BitArrayOption::Utf32Codepoint { .. }
| BitArrayOption::Signed { .. }
| BitArrayOption::Unsigned { .. }
| BitArrayOption::Big { .. }
| BitArrayOption::Little { .. }
| BitArrayOption::Native { .. }
| BitArrayOption::Unit { .. } => None,
BitArrayOption::Size { value, .. } => value.find_node(byte_index),
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum TodoKind {
Keyword,
Expand Down
43 changes: 43 additions & 0 deletions compiler-core/src/ast/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ pub trait Visit<'ast> {
visit_typed_pattern_bit_array(self, location, segments);
}

fn visit_typed_pattern_bit_array_option(&mut self, option: &'ast BitArrayOption<TypedPattern>) {
visit_typed_pattern_bit_array_option(self, option);
}

fn visit_typed_pattern_string_prefix(
&mut self,
location: &'ast SrcSpan,
Expand Down Expand Up @@ -1582,6 +1586,45 @@ pub fn visit_typed_pattern_bit_array<'a, V>(
{
for segment in segments {
v.visit_typed_pattern(&segment.value);
for option in segment.options.iter() {
v.visit_typed_pattern_bit_array_option(option);
}
}
}

pub fn visit_typed_pattern_bit_array_option<'a, V>(
v: &mut V,
option: &'a BitArrayOption<TypedPattern>,
) where
V: Visit<'a> + ?Sized,
{
match option {
BitArrayOption::Bytes { location: _ } => { /* TODO */ }
BitArrayOption::Int { location: _ } => { /* TODO */ }
BitArrayOption::Float { location: _ } => { /* TODO */ }
BitArrayOption::Bits { location: _ } => { /* TODO */ }
BitArrayOption::Utf8 { location: _ } => { /* TODO */ }
BitArrayOption::Utf16 { location: _ } => { /* TODO */ }
BitArrayOption::Utf32 { location: _ } => { /* TODO */ }
BitArrayOption::Utf8Codepoint { location: _ } => { /* TODO */ }
BitArrayOption::Utf16Codepoint { location: _ } => { /* TODO */ }
BitArrayOption::Utf32Codepoint { location: _ } => { /* TODO */ }
BitArrayOption::Signed { location: _ } => { /* TODO */ }
BitArrayOption::Unsigned { location: _ } => { /* TODO */ }
BitArrayOption::Big { location: _ } => { /* TODO */ }
BitArrayOption::Little { location: _ } => { /* TODO */ }
BitArrayOption::Native { location: _ } => { /* TODO */ }
BitArrayOption::Size {
location: _,
value,
short_form: _,
} => {
v.visit_typed_pattern(value);
}
BitArrayOption::Unit {
location: _,
value: _,
} => { /* TODO */ }
}
}

Expand Down
36 changes: 36 additions & 0 deletions compiler-core/src/language_server/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,17 @@ where
| VariableOrigin::LabelShorthand(_) => success_response,
VariableOrigin::Generated => None,
},
Located::Pattern(Pattern::VarUsage { constructor, .. }) => constructor
.as_ref()
.and_then(|constructor| match &constructor.variant {
ValueConstructorVariant::LocalVariable { origin, .. } => match origin {
VariableOrigin::Variable(_)
| VariableOrigin::AssignmentPattern
| VariableOrigin::LabelShorthand(_) => success_response,
VariableOrigin::Generated => None,
},
_ => None,
}),
Located::Pattern(Pattern::Assign { .. }) => success_response,
Located::Arg(arg) => match &arg.names {
ArgNames::Named { .. } | ArgNames::NamedLabelled { .. } => success_response,
Expand Down Expand Up @@ -578,6 +589,31 @@ where
),
VariableOrigin::Generated => None,
},
Located::Pattern(Pattern::VarUsage { constructor, .. }) => constructor
.as_ref()
.and_then(|constructor| match &constructor.variant {
ValueConstructorVariant::LocalVariable { location, origin } => match origin
{
VariableOrigin::Variable(_) | VariableOrigin::AssignmentPattern => {
rename_local_variable(
module,
&lines,
&params,
*location,
VariableRenameKind::Variable,
)
}
VariableOrigin::LabelShorthand(_) => rename_local_variable(
module,
&lines,
&params,
*location,
VariableRenameKind::LabelShorthand,
),
VariableOrigin::Generated => None,
},
_ => None,
}),
Located::Pattern(Pattern::Assign { location, .. }) => rename_local_variable(
module,
&lines,
Expand Down
22 changes: 22 additions & 0 deletions compiler-core/src/language_server/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,26 @@ impl<'ast> Visit<'ast> for RenameLocalVariable {
self.references.push(*location)
}
}

fn visit_typed_pattern_var_usage(
&mut self,
location: &'ast SrcSpan,
_name: &'ast EcoString,
constructor: &'ast Option<ValueConstructor>,
_type_: &'ast std::sync::Arc<crate::type_::Type>,
) {
let variant = match constructor {
Some(constructor) => &constructor.variant,
None => return,
};
match variant {
ValueConstructorVariant::LocalVariable {
location: definition_location,
..
} if *definition_location == self.definition_location => {
self.references.push(*location)
}
_ => {}
}
}
}
36 changes: 36 additions & 0 deletions compiler-core/src/language_server/tests/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,42 @@ pub fn main() {
);
}

#[test]
fn rename_local_variable_in_bit_array_pattern() {
assert_rename!(
"
pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let prefix_size = bit_size(prefix)
case bits {
<<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True
_ -> False
}
}
",
"size_of_prefix",
find_position_of("prefix_size =").to_selection()
);
}

#[test]
fn rename_local_variable_from_bit_array_pattern() {
assert_rename!(
"
pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let prefix_size = bit_size(prefix)
case bits {
<<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True
_ -> False
}
}
",
"size_of_prefix",
find_position_of("prefix_size)").to_selection()
);
}

#[test]
fn no_rename_keyword() {
assert_no_rename!(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
source: compiler-core/src/language_server/tests/rename.rs
expression: "\npub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {\n let prefix_size = bit_size(prefix)\n\n case bits {\n <<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True\n _ -> False\n }\n}\n"
---
----- BEFORE RENAME

pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let prefix_size = bit_size(prefix)

case bits {
<<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True
_ -> False
}
}


----- AFTER RENAME

pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let size_of_prefix = bit_size(prefix)

case bits {
<<pref:bits-size(size_of_prefix), _:bits>> if pref == prefix -> True
_ -> False
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
source: compiler-core/src/language_server/tests/rename.rs
expression: "\npub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {\n let prefix_size = bit_size(prefix)\n\n case bits {\n <<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True\n _ -> False\n }\n}\n"
---
----- BEFORE RENAME

pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let prefix_size = bit_size(prefix)

case bits {
<<pref:bits-size(prefix_size), _:bits>> if pref == prefix -> True
_ -> False
}
}


----- AFTER RENAME

pub fn starts_with(bits: BitArray, prefix: BitArray) -> Bool {
let size_of_prefix = bit_size(prefix)

case bits {
<<pref:bits-size(size_of_prefix), _:bits>> if pref == prefix -> True
_ -> False
}
}

0 comments on commit 76d4621

Please sign in to comment.