Skip to content

Commit

Permalink
Implement renaming in patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
GearsDatapacks committed Mar 6, 2025
1 parent 0e6c08f commit ac06122
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 6 deletions.
1 change: 1 addition & 0 deletions compiler-core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,7 @@ pub enum Pattern<Type> {
/// The constructor for a custom type. Starts with an uppercase letter.
Constructor {
location: SrcSpan,
name_location: SrcSpan,
name: EcoString,
arguments: Vec<CallArg<Self>>,
module: Option<(EcoString, SrcSpan)>,
Expand Down
5 changes: 5 additions & 0 deletions compiler-core/src/ast/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ pub trait Visit<'ast> {
fn visit_typed_pattern_constructor(
&mut self,
location: &'ast SrcSpan,
name_location: &'ast SrcSpan,
name: &'ast EcoString,
arguments: &'ast Vec<CallArg<TypedPattern>>,
module: &'ast Option<(EcoString, SrcSpan)>,
Expand All @@ -479,6 +480,7 @@ pub trait Visit<'ast> {
visit_typed_pattern_constructor(
self,
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -1473,6 +1475,7 @@ where
} => v.visit_typed_pattern_list(location, elements, tail, type_),
Pattern::Constructor {
location,
name_location,
name,
arguments,
module,
Expand All @@ -1481,6 +1484,7 @@ where
type_,
} => v.visit_typed_pattern_constructor(
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -1593,6 +1597,7 @@ pub fn visit_typed_pattern_list<'a, V>(
pub fn visit_typed_pattern_constructor<'a, V>(
v: &mut V,
_location: &'a SrcSpan,
_name_location: &'a SrcSpan,
_name: &'a EcoString,
arguments: &'a Vec<CallArg<TypedPattern>>,
_module: &'a Option<(EcoString, SrcSpan)>,
Expand Down
14 changes: 13 additions & 1 deletion compiler-core/src/ast_folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,13 +1173,21 @@ pub trait PatternFolder {

Pattern::Constructor {
location,
name_location,
name,
arguments,
module,
spread,
constructor: _,
type_: (),
} => self.fold_pattern_constructor(location, name, arguments, module, spread),
} => self.fold_pattern_constructor(
location,
name_location,
name,
arguments,
module,
spread,
),

Pattern::Tuple { location, elems } => self.fold_pattern_tuple(location, elems),

Expand Down Expand Up @@ -1289,13 +1297,15 @@ pub trait PatternFolder {
fn fold_pattern_constructor(
&mut self,
location: SrcSpan,
name_location: SrcSpan,
name: EcoString,
arguments: Vec<CallArg<UntypedPattern>>,
module: Option<(EcoString, SrcSpan)>,
spread: Option<SrcSpan>,
) -> UntypedPattern {
Pattern::Constructor {
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -1390,6 +1400,7 @@ pub trait PatternFolder {

Pattern::Constructor {
location,
name_location,
name,
arguments,
module,
Expand All @@ -1406,6 +1417,7 @@ pub trait PatternFolder {
.collect();
Pattern::Constructor {
location,
name_location,
name,
arguments,
module,
Expand Down
8 changes: 8 additions & 0 deletions compiler-core/src/language_server/code_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportFirstPass<'as
fn visit_typed_pattern_constructor(
&mut self,
location: &'ast SrcSpan,
name_location: &'ast SrcSpan,
name: &'ast EcoString,
arguments: &'ast Vec<CallArg<TypedPattern>>,
module: &'ast Option<(EcoString, SrcSpan)>,
Expand Down Expand Up @@ -1433,6 +1434,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportFirstPass<'as
ast::visit::visit_typed_pattern_constructor(
self,
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -1708,6 +1710,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportSecondPass<'a
fn visit_typed_pattern_constructor(
&mut self,
location: &'ast SrcSpan,
name_location: &'ast SrcSpan,
name: &'ast EcoString,
arguments: &'ast Vec<CallArg<TypedPattern>>,
module: &'ast Option<(EcoString, SrcSpan)>,
Expand All @@ -1732,6 +1735,7 @@ impl<'ast> ast::visit::Visit<'ast> for QualifiedToUnqualifiedImportSecondPass<'a
ast::visit::visit_typed_pattern_constructor(
self,
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -1916,6 +1920,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportFirstPass<'as
fn visit_typed_pattern_constructor(
&mut self,
location: &'ast SrcSpan,
name_location: &'ast SrcSpan,
name: &'ast EcoString,
arguments: &'ast Vec<CallArg<TypedPattern>>,
module: &'ast Option<(EcoString, SrcSpan)>,
Expand All @@ -1937,6 +1942,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportFirstPass<'as
ast::visit::visit_typed_pattern_constructor(
self,
location,
name_location,
name,
arguments,
module,
Expand Down Expand Up @@ -2110,6 +2116,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportSecondPass<'a
fn visit_typed_pattern_constructor(
&mut self,
location: &'ast SrcSpan,
name_location: &'ast SrcSpan,
name: &'ast EcoString,
arguments: &'ast Vec<CallArg<TypedPattern>>,
module: &'ast Option<(EcoString, SrcSpan)>,
Expand All @@ -2130,6 +2137,7 @@ impl<'ast> ast::visit::Visit<'ast> for UnqualifiedToQualifiedImportSecondPass<'a
ast::visit::visit_typed_pattern_constructor(
self,
location,
name_location,
name,
arguments,
module,
Expand Down
23 changes: 20 additions & 3 deletions compiler-core/src/language_server/engine.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Error, Result, Warning,
analyse::name::correct_name_case,
analyse::{self, name::correct_name_case},
ast::{
self, ArgNames, CustomType, Definition, DefinitionLocation, Function, ModuleConstant,
Pattern, RecordConstructor, SrcSpan, TypedArg, TypedExpr, TypedFunction, TypedModule,
Expand Down Expand Up @@ -564,6 +564,8 @@ where
)))
};

let byte_index = lines.byte_index(params.position.line, params.position.character);

Ok(match found {
Located::Expression(TypedExpr::Var {
constructor:
Expand Down Expand Up @@ -594,6 +596,13 @@ where
_ => None,
}),
Located::Pattern(Pattern::Assign { location, .. }) => success_response(*location),
Located::Pattern(Pattern::Constructor { name_location, .. }) => {
if name_location.contains(byte_index) {
success_response(*name_location)
} else {
None
}
}
Located::Arg(arg) => match &arg.names {
ArgNames::Named { location, .. }
| ArgNames::NamedLabelled {
Expand Down Expand Up @@ -627,8 +636,6 @@ where
| Definition::ModuleConstant(ModuleConstant { name_location, .. }),
)
| Located::RecordConstructor(RecordConstructor { name_location, .. }) => {
let byte_index =
lines.byte_index(params.position.line, params.position.character);
// When we locate a module statement, we don't know where exactly the cursor
// is positioned. In this example, we want to rename the first but not the second:
// ```gleam
Expand Down Expand Up @@ -827,6 +834,16 @@ where
&this.compiler.modules,
Named::CustomTypeVariant,
),
Located::Pattern(Pattern::Constructor {
constructor: analyse::Inferred::Known(constructor),
..
}) => rename_module_value(
&params,
&constructor.module,
&constructor.name,
&this.compiler.modules,
Named::CustomTypeVariant,
),
_ => None,
})
})
Expand Down
42 changes: 42 additions & 0 deletions compiler-core/src/language_server/tests/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -980,3 +980,45 @@ pub type Type {
find_position_of("X").to_selection()
);
}

#[test]
fn rename_type_variant_pattern_with_arguments() {
assert_rename!(
"
pub type Wibble {
Wibble(Int)
Wobble(Float)
}
fn wibble() {
case Wibble(10) {
Wibble(20) -> todo
Wibble(_) -> panic
}
}
",
"Variant",
find_position_of("Wibble(10)").to_selection()
);
}

#[test]
fn rename_type_variant_from_pattern() {
assert_rename!(
"
pub type Type {
X
Y
}
pub fn main(t) {
case t {
X -> 0
Y -> 0
}
}
",
"Renamed",
find_position_of("X ->").to_selection()
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: compiler-core/src/language_server/tests/rename.rs
expression: "\npub type Type {\n X\n Y\n}\n\npub fn main(t) {\n case t {\n X -> 0\n Y -> 0\n }\n}\n"
---
----- BEFORE RENAME
-- app.gleam

pub type Type {
X
Y
}

pub fn main(t) {
case t {
X -> 0
Y -> 0
}
}


----- AFTER RENAME
-- app.gleam

pub type Type {
Renamed
Y
}

pub fn main(t) {
case t {
Renamed -> 0
Y -> 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
source: compiler-core/src/language_server/tests/rename.rs
expression: "\npub type Type {\n X\n Y\n}\n"
---
----- BEFORE RENAME
-- other.gleam

import app

pub fn main(t) {
case t {
app.X -> 0
app.Y -> 0
}
}


-- app.gleam

pub type Type {
X
Y
}


----- AFTER RENAME
-- other.gleam

import app

pub fn main(t) {
case t {
app.Renamed -> 0
app.Y -> 0
}
}


-- app.gleam

pub type Type {
Renamed
Y
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
source: compiler-core/src/language_server/tests/rename.rs
expression: "\npub type Type {\n X\n Y\n}\n"
---
----- BEFORE RENAME
-- other.gleam

import app.{X, Y}

pub fn main(t) {
case t {
X -> 0
Y -> 0
}
}


-- app.gleam

pub type Type {
X
Y
}


----- AFTER RENAME
-- other.gleam

import app.{Renamed, Y}

pub fn main(t) {
case t {
Renamed -> 0
Y -> 0
}
}


-- app.gleam

pub type Type {
Renamed
Y
}
Loading

0 comments on commit ac06122

Please sign in to comment.