Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: enum member declarations can now be renamed correctly. #2043

Merged
merged 1 commit into from
Oct 5, 2024

Conversation

srijan-paul
Copy link
Contributor

@srijan-paul srijan-paul commented Oct 1, 2024

Fixes #2042.

Currently, renaming enum field members will return two duplicate edit actions in the LSP response.
On VSCode, this causes the editor to raise an error.
On Emacs, Neovim, and Helix, the edits made are incorrect.

ThesymbolReferences function tries to find all references to a declaration and the declaration itself (when include_decls flag is set). However, when searching for the references to an enum member like in here:

const Number = enum {
  zero, // <-- rename triggered from here
  one
};

const myZero = Number.zero; // <-- rename should happen here too
_ = myZero;

The first identifier zero is treated first as a declaration and then also as a reference.
This edge case can be handled by ensuring the name token for a symbol's declaration is never the same as its reference's name token.

Ideally, the lookup function should never be called for a container field init identifier, but the way AST traversal works right now, there is no straightforward way to figure out if the node we're currently on declares an enum member.

Before:

Screen.Recording.2024-10-01.at.9.00.23.PM.mov

After:

Screen.Recording.2024-10-01.at.8.56.41.PM.mov

@srijan-paul srijan-paul changed the title fix: enum member declarations are no longer repeated in rename response fix: enum member declarations can now be renamed correctly. Oct 3, 2024
Copy link
Member

@Techatrix Techatrix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check can be simplified by comparing the two name tokens for equality:

child.handle == handle and child.nameToken() == name_token

We can also move this to the Builder.add function to generalize the solution and avoid unnecessarily running this check on decls that we going to be ignored anyway.

This is going to give us the following patch (includes a test case):

diff --git a/src/features/references.zig b/src/features/references.zig
index f475086..6ed8095 100644
--- a/src/features/references.zig
+++ b/src/features/references.zig
@@ -68,6 +68,8 @@ const Builder = struct {
     locations: std.ArrayListUnmanaged(types.Location) = .{},
     /// this is the declaration we are searching for
     decl_handle: Analyser.DeclWithHandle,
+    /// Whether the `decl_handle` has been added
+    did_add_decl_handle: bool = false,
     analyser: *Analyser,
     encoding: offsets.Encoding,
 
@@ -81,6 +83,12 @@ const Builder = struct {
     }
 
     fn add(self: *Builder, handle: *DocumentStore.Handle, token_index: Ast.TokenIndex) error{OutOfMemory}!void {
+        if (self.decl_handle.handle == handle and
+            self.decl_handle.nameToken() == token_index)
+        {
+            if (self.did_add_decl_handle) return;
+            self.did_add_decl_handle = true;
+        }
         try self.locations.append(self.allocator, .{
             .uri = handle.uri,
             .range = offsets.tokenToRange(handle.tree, token_index, self.encoding),
diff --git a/tests/lsp_features/references.zig b/tests/lsp_features/references.zig
index 250ccd9..c11c588 100644
--- a/tests/lsp_features/references.zig
+++ b/tests/lsp_features/references.zig
@@ -97,6 +97,16 @@ test "for/while capture" {
     );
 }
 
+test "enum field access" {
+    try testReferences(
+        \\const E = enum {
+        \\  <0>,
+        \\  bar
+        \\};
+        \\const e = E.<0>;
+    );
+}
+
 test "struct field access" {
     try testReferences(
         \\const S = struct {<0>: u32 = 3};

@srijan-paul
Copy link
Contributor Author

Ah yes, the tokens are indices anyway.
Updated the PR.

@srijan-paul srijan-paul requested a review from Techatrix October 5, 2024 12:05
@Techatrix Techatrix merged commit 063d7ff into zigtools:master Oct 5, 2024
6 checks passed
llogick pushed a commit to llogick/zls that referenced this pull request Oct 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot rename enum fields using VSCode extension.
2 participants