Skip to content

Changes for rewrite 1.0.0#96

Merged
NickNeck merged 16 commits into
0.8.0-devfrom
rewrite-1-0-0
Nov 10, 2024
Merged

Changes for rewrite 1.0.0#96
NickNeck merged 16 commits into
0.8.0-devfrom
rewrite-1-0-0

Conversation

@NickNeck
Copy link
Copy Markdown
Member

@NickNeck NickNeck commented Nov 2, 2024

Changes to use rewrite 1.0.0 and some refactorings for the recode tasks.

Summary by CodeRabbit

Release Notes for Version 0.8.0

  • New Features

    • Introduced new callbacks for task management: update_source/3, new_issue/1, and new_issue/2.
    • Added a new module Recode.Task.TestFile for validating test file naming conventions.
  • Bug Fixes

    • Renamed Recode.Task.TestFileExt to Recode.Task.TestFile across the application to ensure consistency.
  • Documentation

    • Updated the README to reflect changes in the recode linter and added a new section on code style and formatting.
  • Chores

    • Updated configuration files to remove deprecated tasks and reflect the new task structure.
    • Enhanced test coverage for configuration management and task execution.
  • Refactor

    • Streamlined the handling of options and issue creation across various tasks, improving code maintainability.
    • Updated CI configuration to use the latest Elixir and OTP versions.
    • Expanded the inputs for the recode tool to include the priv directory.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 2, 2024

Warning

Rate limit exceeded

@NickNeck has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 15 minutes and 22 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 5e01def and b2d73fd.

📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces a series of changes primarily focused on the Recode project, updating it to version 0.8.0. Key modifications include the addition of new callbacks in the Recode.Task module, specifically update_source/3 and two overloads of new_issue/1 and new_issue/2. The entity Recode.Task.TestFileExt has been renamed to Recode.Task.TestFile, affecting multiple files including the changelog, README, and configuration files. The coveralls.json file has been updated to change the files skipped during coverage analysis.

Several new dependencies have been added in the mix.exs file, including :json_formatter and :ecto_sql, while the rewrite dependency has been updated to version 1.0. The documentation has been refined across various files, including the README and module documentation, to clarify functionalities and improve consistency. Additionally, new test cases have been introduced to enhance test coverage for the delete_tasks/2 function and other functionalities. Overall, the changes reflect a significant update in both functionality and documentation within the Recode project.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 23

🧹 Outside diff range and nitpick comments (30)
examples/my_code/priv/repo/migrations/20190417140000_create_users.exs (1)

4-11: Consider adding indexes and constraints.

While the basic table structure is correct, consider the following improvements for production readiness:

  1. Add indexes if these fields will be frequently queried
  2. Add NOT NULL constraints if these fields should be required
  3. Consider using :text type if names might exceed 40 characters (e.g., for supporting names from different cultures)

Example enhancement:

 def up do
   create table("users") do
-    add :first_name,    :string, size: 40
-    add :last_name,    :string, size: 40
+    add :first_name, :string, size: 40, null: false
+    add :last_name,  :string, size: 40, null: false

     timestamps()
   end
+  create index(:users, [:last_name])
 end
examples/my_code/.formatter.exs (1)

14-14: Consider documenting the custom noop function

The locals_without_parens configuration includes noop: 1, but its purpose isn't immediately clear.

Consider adding a comment explaining the purpose of the noop function and why it's configured without parens.

examples/my_code/scripts/backup.exs (1)

Line range hint 13-13: Fix typo in output message.

The message contains a typo: "form" should be "from".

  def run(["restore"]) do
-   IO.puts("restoring form backup #{@backup}")
+   IO.puts("restoring from backup #{@backup}")
test/recode/task/locals_without_parens_test.exs (1)

7-32: Well-structured test with comprehensive cases.

The test effectively covers various scenarios including single argument, multiple arguments, and control structures. The setup is clear and the assertions are appropriate.

Consider adding test cases for:

  • Nested function calls with mixed locals (some with parens, some without)
  • Functions with keyword arguments
  • Edge cases with special characters or unicode in function names

Example addition:

# In the code string:
foo bar(baz(x)), key: value
nested_foo bar baz(x)
lib/recode/issue.ex (1)

29-39: Implementation looks good, consider adding @SPEC.

The implementation follows a clean pattern of delegating to simpler functions. Consider adding @SPEC type specifications for better documentation and dialyzer support.

+  @spec new(module(), String.t(), keyword()) :: t()
   def new(reporter, message, info) do

+  @spec new(module(), keyword()) :: t()
   def new(reporter, info) do
lib/mix/tasks/recode.update.config.ex (1)

Line range hint 31-37: Consider adding a warning for removed tasks

The configuration update silently removes tasks without informing the user. Consider logging a warning message when tasks are removed to help users understand the changes being made to their configuration.

Here's a suggested implementation:

       |> Code.eval_file()
       |> elem(0)
       |> delete(@deprecated_configs)
       |> Recode.Config.merge()
+      |> tap(fn config ->
+        unless Enum.empty?(@removed_tasks) do
+          Mix.shell().info([:yellow, "Warning: Removing deprecated tasks: #{inspect(@removed_tasks)}"])
+        end
+      end)
       |> Recode.Config.delete_tasks(@removed_tasks)

       Mix.Generator.create_file(@config_filename, Recode.Config.to_string(config), force: force)
lib/recode/task/enforce_line_length.ex (1)

Line range hint 3-37: Update module documentation to reflect new options and behavior.

The module documentation should be updated to include:

  1. The new :dot_formatter option and its purpose
  2. The change in behavior from checker to corrector mode

Consider adding the following to the Options section:

   ## Options
 
     * `:skip` - specifies expressions to skip.
     * `:ignore` - specifies expressions to ignore.
+    * `:dot_formatter` - specifies formatter configuration options.
test/recode/formatter_plugin_test.exs (1)

41-44: Consider adding a brief comment explaining the formatter options structure.

While the code is clear, a brief comment explaining the purpose of these options would improve maintainability.

+# Formatter options including Recode tasks configuration
 formatter_opts = [
   locals_without_parens: [foo: 2],
   recode: [tasks: [{SinglePipe, []}]]
 ]
lib/recode/task/specs.ex (1)

Line range hint 1-91: Consider documenting the issue message format in the moduledoc.

The module has good documentation, but it could be enhanced by including an example of the issue message that gets reported when a spec is missing. This would help users better understand what to expect when the task finds issues.

Add to the moduledoc:

  ## Options

    * `:only` - `:public`, `:visible` or `:all`, defaults to `:all`.
    * `:macros` - when `true`, macros are also checked, defaults to `false`.
+
+ ## Example Issue Message
+
+ When a function is missing a type specification, the following message is reported:
+ "Functions should have a @spec type specification."
test/mix/tasks/recode.update.config_test.exs (3)

10-24: Enhance test assertions for better clarity.

The test verifies the force update functionality but could be more explicit in its assertions.

Consider improving the test with more descriptive assertions:

-      assert config ==
+      # Verify config was actually modified
+      assert config != "[verbose: true, tasks: []]"
+      
+      # Verify final config matches expected structure
+      assert config ==
               Recode.Config.default()
               |> Keyword.put(:verbose, true)
               |> Recode.Config.to_string(),
+              "Config file should be updated with default settings while preserving verbose flag"

26-40: Remove unnecessary blank lines.

The test has inconsistent spacing with extra blank lines that don't improve readability.

Consider this more concise structure:

   @tag :tmp_dir
   test "mix recode.update.config - input: Y", %{tmp_dir: tmp_dir} do
     File.cd!(tmp_dir, fn ->
       File.write!(@config, "[verbose: true, tasks: []]")
-
       capture_io([input: "Y"], fn -> Config.run([]) end)
-
       config = File.read!(@config)
-
       assert config ==
               Recode.Config.default()
               |> Keyword.put(:verbose, true)
               |> Recode.Config.to_string()
     end)
   end

42-52: Add documentation for test purpose.

While the test is well-structured, its purpose could be more explicit.

Consider adding a descriptive comment:

   @tag :tmp_dir
+  # Ensures the config file remains unchanged when user declines the update
   test "mix recode.update.config - input: n", %{tmp_dir: tmp_dir} do
lib/recode/task/locals_without_parens.ex (1)

35-41: Consider extracting the traverse callback for clarity

While the refactoring improves the code flow, consider extracting the traverse callback to a named function for better readability and documentation purposes.

 source
 |> Source.get(:quoted)
 |> Zipper.zip()
-|> Zipper.traverse([], fn zipper, issues ->
-  remove_parens(locals_without_parens, zipper, issues, opts[:autocorrect])
-end)
+|> Zipper.traverse([], &traverse_and_remove_parens(&1, &2, locals_without_parens, opts[:autocorrect]))
 |> update(source, opts)

+defp traverse_and_remove_parens(zipper, issues, locals_without_parens, autocorrect?) do
+  remove_parens(locals_without_parens, zipper, issues, autocorrect?)
+end
test/recode/task/test_file_test.exs (1)

6-46: Consider adding documentation for test scenarios

While the test cases are well-structured, they would benefit from documentation explaining:

  • The specific scenario being tested
  • The expected transformation
  • Why certain test data is used (":test" vs full module definitions)

Example improvement:

+  @doc """
+  Verifies that a test file with .ex extension is correctly updated to .exs
+  when autocorrect is enabled.
+  """
   test "updates file extension" do
lib/recode/task/unnecessary_if_unless.ex (1)

Line range hint 1-14: Documentation improvements suggested

Consider these enhancements to the module documentation:

  1. Fix the typo: "Redudant" → "Redundant"
  2. Use Elixir syntax highlighting in the code example:
-          # preferred
-          foo == bar
+```elixir
+# preferred
+foo == bar
-          # not preferred
-          if foo == bar do
-            true
-          else
-            false
-          end
+# not preferred
+if foo == bar do
+  true
+else
+  false
+end
+```
lib/mix/tasks/recode.help.ex (2)

82-82: Consider adding consistent spacing for section headers.

While the color formatting improves visibility, consider adding consistent spacing before and after the section header for better readability.

-    Escape.puts([:yellow, :reverse, " #{section} "])
+    Escape.puts(["\n", :yellow, :reverse, " #{section} ", "\n"])

Line range hint 4-4: Fix typo in @moduledoc.

There's a typo in the word "availbale" which should be "available".

-  Lists all availbale recode tasks with a short description or prints the
+  Lists all available recode tasks with a short description or prints the
lib/recode/formatter_plugin.ex (2)

59-59: LGTM! Configuration handling improvement

The change simplifies configuration management by storing all formatter options directly instead of filtering them. This is a more maintainable approach that aligns well with the removal of the Recode.FormatterPlugin.Config module.

This change follows the principle of least surprise by preserving all formatter options, making it easier to debug and maintain the formatter plugin's behavior.


Line range hint 67-72: Consider adding config cleanup mechanism

The persistent term storage is used effectively for caching config, but consider adding a cleanup mechanism to prevent potential issues with stale configurations in long-running processes.

Consider adding a cleanup function:

def clear_config do
  :persistent_term.erase(@persistent_term_key)
end

This could be called when appropriate, such as when the formatter plugin is reloaded or when the configuration file changes.

lib/recode/task/single_pipe.ex (1)

Line range hint 66-70: Consider enhancing the error message with an example.

While the message is clear, it could be more educational by including an example of the preferred style.

Consider updating the message to something like:

-      new_issue(
-        "Use a function call when a pipeline is only one function long.",
-        meta
-      )
+      new_issue(
+        "Use a function call when a pipeline is only one function long. " <>
+          "Example: prefer `String.trim(x)` over `x |> String.trim()`",
+        meta
+      )
lib/recode/task/alias_expansion.ex (1)

Line range hint 1-2: Fix typo in @shortdoc attribute.

There's a typo in the @shortdoc attribute that should be fixed as it appears in mix task listings.

Apply this change:

-  @shortdoc "Exapnds multi aliases to separate aliases."
+  @shortdoc "Expands multi aliases to separate aliases."
test/support/recode_case.ex (1)

122-122: Consider documenting the default formatter behavior.

The addition of a default dot_formatter is a good practice, ensuring consistent formatting behavior.

Consider adding a module or function documentation to explain that a default formatter will be provided if none is specified. This helps users understand the implicit behavior.

+ @doc """
+ Runs the given task with the provided source and options.
+ 
+ ## Options
+ 
+   * `:dot_formatter` - The formatter to use. Defaults to `DotFormatter.default()`
+     if not specified.
+ """
 def run_task(code, task, opts \\ [])
CHANGELOG.md (1)

7-8: Fix line wrapping for consistency.

The wrapping of the second callback name makes the changelog entry harder to read. Consider keeping it on a single line.

-+ Add callback and default implementation `Recode.Task.new_issue/1` and 
-  `Recode.Task.new_issue/2` 
++ Add callback and default implementation `Recode.Task.new_issue/1` and `Recode.Task.new_issue/2`
lib/recode/task/moduledoc.ex (1)

Line range hint 5-5: Fix typos in documentation and error messages

There are several typos in the module that should be corrected for consistency and professionalism:

  • @moudledoc should be @moduledoc
  • moudle should be module

Apply these corrections:

-  Any module should contain a `@moudledoc` attribute.
+  Any module should contain a `@moduledoc` attribute.

-        The @moudledoc attribute for moudle #{module} has no content.\
+        The @moduledoc attribute for module #{module} has no content.\

-        The moudle #{module} is missing @moduledoc.\
+        The module #{module} is missing @moduledoc.\

Also applies to: 58-59, 82-83, 91-92

test/recode/config_test.exs (1)

125-125: Rename test to better reflect its purpose.

The test name "merges configs" doesn't accurately describe what's being tested. This test is validating the deletion of tasks from the configuration.

Consider renaming to something more descriptive like:

-    test "merges configs" do
+    test "deletes specified tasks from configuration" do
lib/recode/config.ex (1)

97-98: Minor documentation improvements needed.

The documentation has a typo and could be more precise.

-  The merge will do a deep merge. The merge takes the version from the `right` 
-  config.
+  The merge will do a deep merge. The merge takes the version from the `right`
+  config. The merge strategy varies by key, with special handling for `:version`
+  and `:tasks` keys.
test/recode/task/enforce_line_length_test.exs (1)

271-271: Consider adding test for multi-head anonymous functions with autocorrect

While the current test coverage for anonymous functions is good, consider adding a test case that combines:

  • Multiple function heads
  • Pattern matching
  • The new autocorrect: true option
    This would ensure the formatter behaves correctly with complex anonymous functions.

Also applies to: 282-282, 304-304, 342-342

README.md (1)

458-481: Consider improving the formatting of the new section.

While the content is valuable, the formatting could be enhanced for better readability:

  • Remove unnecessary line breaks between paragraphs
  • Ensure consistent line length

Apply this formatting:

-## Code style and formatting
-
-
-Code style and formatting are essential aspects of writing clean and 
-maintainable code. Different developers and teams may have varying preferences 
-when it comes to how code should be structured and formatted. Tools like 
-`recode` can help enforce consistency and improve readability by applying 
-predefined rules to the codebase. However, it's important to remember that 
-these rules are not set in stone and may not necessarily reflect the best 
-practices for every project.
-
-
-Ultimately, the goal of code formatting is to make the code more 
-understandable and maintainable. It can help identify potential issues and 
-improve the overall quality of the code. While `recode` offers a set of rules to 
-follow, developers are free to choose which rules they want to apply based on 
-their own preferences and the requirements of the project.
-
-
-It's worth noting that discussions around code style and formatting can be 
-subjective, and there is no one-size-fits-all solution. Developers should feel 
-empowered to make informed decisions about which formatting rules to apply and 
-adapt them as needed to suit their specific needs. There are numerous 
-resources available online that provide insights into code formatting best 
-practices, allowing developers to explore different approaches and find what 
-works best for them.
-
+## Code style and formatting
+
+Code style and formatting are essential aspects of writing clean and maintainable code. Different developers and teams may have varying preferences when it comes to how code should be structured and formatted. Tools like `recode` can help enforce consistency and improve readability by applying predefined rules to the codebase. However, it's important to remember that these rules are not set in stone and may not necessarily reflect the best practices for every project.
+
+Ultimately, the goal of code formatting is to make the code more understandable and maintainable. It can help identify potential issues and improve the overall quality of the code. While `recode` offers a set of rules to follow, developers are free to choose which rules they want to apply based on their own preferences and the requirements of the project.
+
+It's worth noting that discussions around code style and formatting can be subjective, and there is no one-size-fits-all solution. Developers should feel empowered to make informed decisions about which formatting rules to apply and adapt them as needed to suit their specific needs. There are numerous resources available online that provide insights into code formatting best practices, allowing developers to explore different approaches and find what works best for them.
lib/recode/task.ex (1)

89-90: Missing Documentation for new_issue/1 Callback

The @callback for new_issue/1 on lines 89-90 lacks accompanying documentation. For consistency and clarity, consider adding a @doc block similar to other callbacks.

You may add documentation like this:

@doc """
Creates a new issue with the given `opts`.

The default implementation creates a `Recode.Issue` struct with `reporter: __MODULE__`.
"""
@callback new_issue(opts :: Keyword.t()) :: Issue.t()
test/recode/runner/impl_test.exs (1)

426-428: Clarify the comment regarding mix format behavior

The comment # Fake here what mix format does. may benefit from elaboration. Providing more context on how the DotFormatter is used to simulate mix format behavior can improve understanding for future maintainers.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8764a07 and 05fad05.

⛔ Files ignored due to path filters (3)
  • examples/my_code/mix.lock is excluded by !**/*.lock
  • examples/my_code/scripts/backup.bin is excluded by !**/*.bin
  • mix.lock is excluded by !**/*.lock
📒 Files selected for processing (51)
  • CHANGELOG.md (1 hunks)
  • README.md (5 hunks)
  • coveralls.json (1 hunks)
  • examples/my_code/.formatter.exs (1 hunks)
  • examples/my_code/mix.exs (1 hunks)
  • examples/my_code/priv/repo/migrations/.formatter.exs (1 hunks)
  • examples/my_code/priv/repo/migrations/20190417140000_create_users.exs (1 hunks)
  • examples/my_code/priv/some.json (1 hunks)
  • examples/my_code/scripts/backup.exs (1 hunks)
  • lib/mix/tasks/recode.help.ex (1 hunks)
  • lib/mix/tasks/recode.update.config.ex (2 hunks)
  • lib/recode.ex (1 hunks)
  • lib/recode/config.ex (4 hunks)
  • lib/recode/formatter_plugin.ex (1 hunks)
  • lib/recode/issue.ex (1 hunks)
  • lib/recode/runner/impl.ex (7 hunks)
  • lib/recode/task.ex (4 hunks)
  • lib/recode/task/alias_expansion.ex (2 hunks)
  • lib/recode/task/alias_order.ex (3 hunks)
  • lib/recode/task/dbg.ex (2 hunks)
  • lib/recode/task/enforce_line_length.ex (3 hunks)
  • lib/recode/task/filter_count.ex (2 hunks)
  • lib/recode/task/format.ex (0 hunks)
  • lib/recode/task/io_inspect.ex (2 hunks)
  • lib/recode/task/locals_without_parens.ex (2 hunks)
  • lib/recode/task/moduledoc.ex (1 hunks)
  • lib/recode/task/nesting.ex (1 hunks)
  • lib/recode/task/pipe_fun_one.ex (2 hunks)
  • lib/recode/task/single_pipe.ex (2 hunks)
  • lib/recode/task/specs.ex (1 hunks)
  • lib/recode/task/test_file.ex (1 hunks)
  • lib/recode/task/test_file_ext.ex (0 hunks)
  • lib/recode/task/unnecessary_if_unless.ex (2 hunks)
  • lib/recode/task/unused_variable.ex (1 hunks)
  • mix.exs (4 hunks)
  • recode.exs (1 hunks)
  • test/fixtures/config.exs (2 hunks)
  • test/fixtures/invalid_task_config.exs (2 hunks)
  • test/fixtures/runner/config.exs (0 hunks)
  • test/mix/tasks/recode.update.config_test.exs (1 hunks)
  • test/recode/cli_formatter_test.exs (9 hunks)
  • test/recode/config_test.exs (1 hunks)
  • test/recode/formatter_plugin_test.exs (2 hunks)
  • test/recode/runner/impl_test.exs (1 hunks)
  • test/recode/task/enforce_line_length_test.exs (22 hunks)
  • test/recode/task/format_test.exs (0 hunks)
  • test/recode/task/locals_without_parens.exs (0 hunks)
  • test/recode/task/locals_without_parens_test.exs (1 hunks)
  • test/recode/task/test_file_ext_test.exs (0 hunks)
  • test/recode/task/test_file_test.exs (1 hunks)
  • test/support/recode_case.ex (3 hunks)
💤 Files with no reviewable changes (6)
  • lib/recode/task/format.ex
  • lib/recode/task/test_file_ext.ex
  • test/fixtures/runner/config.exs
  • test/recode/task/format_test.exs
  • test/recode/task/locals_without_parens.exs
  • test/recode/task/test_file_ext_test.exs
✅ Files skipped from review due to trivial changes (5)
  • coveralls.json
  • examples/my_code/priv/repo/migrations/.formatter.exs
  • examples/my_code/priv/some.json
  • lib/recode.ex
  • test/fixtures/config.exs
🔇 Additional comments (89)
examples/my_code/priv/repo/migrations/20190417140000_create_users.exs (1)

1-2: LGTM!

The module definition and Ecto.Migration usage follow the standard conventions.

examples/my_code/.formatter.exs (4)

6-6: LGTM: Trailing comma configuration

Enabling trailing_comma is a good practice as it produces cleaner git diffs when adding/removing items from lists and maps.


13-13: Verify JSON files in priv directory

The inputs pattern now includes priv/**/*.json. This change suggests there are JSON files that need formatting.

#!/bin/bash
# Check if JSON files exist in priv directory
fd -e json -p priv/

# Verify these files are valid JSON
fd -e json -p priv/ -x jq '.' {} \; 

15-15: Verify migration directory structure

The addition of priv/*/migrations to subdirectories suggests there are Ecto migrations that need formatting.

✅ Verification successful

Migration directory structure is correctly configured

The verification confirms that there are Ecto migration files present in the expected directory structure at priv/repo/migrations/, which matches the formatter configuration priv/*/migrations. The presence of 20190417140000_create_users.exs validates that the formatter subdirectory pattern is correctly set up.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if migration files exist in the expected structure
fd -e exs -p "priv/.*/migrations"

Length of output: 296


5-5: Verify plugin compatibility with Recode 1.0.0

The configuration now explicitly enables both FreedomFormatter and Recode.FormatterPlugin. Since this PR is about upgrading to rewrite 1.0.0, we should verify these plugins are compatible with the new version.

✅ Verification successful

Plugin compatibility verified and confirmed

Based on the mix.exs dependency specification {:freedom_formatter, "~> 2.1", only: :test}, the FreedomFormatter plugin is properly constrained and compatible. The Recode.FormatterPlugin is part of the core Recode package itself, so it's inherently compatible. Both plugins can be safely used in the formatter configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for plugin version constraints in mix.exs files
rg -A 5 "freedom_formatter|recode" mix.exs

Length of output: 404


Script:

#!/bin/bash
# Let's check the version of recode being used in the project
rg -A 2 "@version =" mix.exs

# Also check for any version constraints in the formatter plugins
rg -A 2 "plugins:" .formatter.exs

Length of output: 64

examples/my_code/mix.exs (1)

35-36: Verify the necessity of new development dependencies.

The added dependencies look properly configured with appropriate version constraints and environment restrictions. However, let's verify their necessity:

  1. json_formatter: This appears to be added for development-time JSON formatting capabilities
  2. ecto_sql: This is a significant dependency for database interactions

Could you clarify how these development dependencies relate to the PR's primary objective of utilizing rewrite 1.0.0?

Let's verify the usage of these new dependencies:

✅ Verification successful

Let's gather more context about the specific usage patterns:


Development dependencies are part of example code and should be retained

The added dependencies are correctly configured and serve a clear purpose in the example code:

  • json_formatter: Used alongside Jason for JSON formatting in the development environment
  • ecto_sql: Required for the example migration in examples/my_code/priv/repo/migrations/20190417140000_create_users.exs, which demonstrates a typical database schema setup

These dependencies are appropriately scoped to :dev and are essential parts of the example codebase that demonstrates proper usage patterns. Their inclusion helps maintain a complete and functional example.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of json_formatter and ecto_sql in the codebase
# Expected: Find references to these packages in configuration or source files

echo "Checking json_formatter usage:"
rg -l "json_formatter"

echo "Checking ecto_sql usage:"
rg -l "ecto|Ecto|Schema|Repo"

Length of output: 1114


Script:

#!/bin/bash
# Check the actual usage context of these dependencies

echo "Checking json_formatter configuration and usage:"
rg -A 5 "json_formatter" examples/my_code/

echo -e "\nChecking Ecto usage in example code:"
rg -A 5 "Ecto|Schema|Repo" examples/my_code/

echo -e "\nChecking migration file content:"
cat examples/my_code/priv/repo/migrations/20190417140000_create_users.exs

echo -e "\nChecking mix.lock for version info:"
cat examples/my_code/mix.lock

Length of output: 7639

test/recode/task/locals_without_parens_test.exs (1)

1-6: Consider enabling async testing if possible.

The test module is marked with async: false. If there are no shared resources or global state modifications between tests, consider enabling async testing for better test execution performance.

✅ Verification successful

Let me gather more context about why these tests might need async: false.


Let me check the RecodeCase implementation to understand if there's a specific reason for async: false.


The async: false setting is justified - keep as is.

The async: false setting is necessary because:

  1. The test setup uses Mox for stubbing (Mox.stub_with in RecodeCase)
  2. The formatter plugin tests manipulate shared state through :persistent_term
  3. All test files using RecodeCase consistently use async: false

These factors make concurrent test execution unsafe, as it could lead to race conditions and non-deterministic test failures.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if other test files also use async: false to understand if this is a pattern
rg "use RecodeCase.*async: false" test/

Length of output: 189


Script:

#!/bin/bash
# Check the implementation of RecodeCase to understand if there's a specific reason for async: false
rg -l "defmodule.*RecodeCase" test/

Length of output: 65


Script:

#!/bin/bash
# Look for shared resources or global state in the test files
rg "setup|describe.*setup" test/recode/formatter_plugin_test.exs test/recode/task/locals_without_parens_test.exs

Length of output: 226


Script:

#!/bin/bash
# Check if these tests modify any shared configuration or environment
rg "Application\.(put_env|get_env|delete_env)" test/recode/formatter_plugin_test.exs test/recode/task/locals_without_parens_test.exs

Length of output: 134


Script:

#!/bin/bash
# Check the implementation of RecodeCase
cat test/support/recode_case.ex

Length of output: 3673


Script:

#!/bin/bash
# Look for any global state or mocking in formatter plugin test
rg -A 5 "setup :verify_on_exit!" test/recode/formatter_plugin_test.exs

Length of output: 194


Script:

#!/bin/bash
# Check if any other test files use async: true with RecodeCase
rg "use RecodeCase.*async: true" test/

Length of output: 40

lib/recode/issue.ex (1)

26-26: Documentation example looks good!

The updated example clearly demonstrates the new keyword-based API for creating issues with meta information.

test/fixtures/invalid_task_config.exs (3)

Line range hint 13-14: Invalid configuration detected in Dbg task.

The Dbg task contains an invalid :key option that appears to be intentionally placed for testing invalid configurations. Since this is in an invalid task config fixture file, this is expected behavior.


26-26: Verify task rename implementation.

The task has been renamed from TestFileExt to TestFile. Let's verify that all references to this task have been updated consistently.

#!/bin/bash
# Description: Check for any remaining references to the old task name
# Expected: No references to TestFileExt should remain

echo "Checking for old task name references..."
rg "TestFileExt"

echo "Verifying new task name implementation..."
rg "TestFile"

2-2: Verify version consistency across the project.

The version has been updated to "0.8.0". Let's ensure this version is consistent across all configuration files.

lib/mix/tasks/recode.update.config.ex (2)

20-20: ⚠️ Potential issue

Incorrect task module in @removed_tasks

The attribute references Recode.Task.TestFileExt but according to the PR summary, this has been renamed to Recode.Task.TestFile. This inconsistency could cause the configuration update to fail.

Update the removed tasks list to use the new module name:

-  @removed_tasks [Recode.Task.TestFileExt]
+  @removed_tasks [Recode.Task.TestFile]

Likely invalid or redundant comment.


35-35: Verify the task deletion implementation

The code correctly calls delete_tasks/2 to remove deprecated tasks from the configuration. However, we should verify that this function exists and handles missing tasks gracefully.

Let's verify the implementation:

✅ Verification successful

Function delete_tasks/2 is properly implemented with graceful handling

The implementation in lib/recode/config.ex is correct and safe:

  • Uses Keyword.update/4 with a default empty list if :tasks key doesn't exist
  • Uses Keyword.drop/2 to safely remove tasks, which handles missing tasks gracefully
  • Has comprehensive tests in test/recode/config_test.exs verifying:
    • Removing single tasks
    • Removing multiple tasks
    • Attempting to remove non-existent tasks
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if delete_tasks/2 is properly implemented in Recode.Config

# Test 1: Look for the delete_tasks function definition
ast-grep --pattern 'def delete_tasks($config, $tasks) do
  $$$
end'

# Test 2: Check for any error handling tests
rg -l "test.*delete_tasks.*when.*task.*not.*found" test/

Length of output: 128


Script:

#!/bin/bash
# Let's try different approaches to locate the delete_tasks function

# Search for any mention of delete_tasks in the codebase
rg "delete_tasks" -A 5

# Look for the Recode.Config module definition
rg "defmodule Recode.Config"

# Find all files that might contain the Config module
fd "config.ex"

Length of output: 2710

recode.exs (2)

Line range hint 1-1: Version number needs updating.

The configuration shows version "0.7.2" while the AI summary mentions version 0.8.0. This discrepancy should be addressed.

Let's verify the correct version:

#!/bin/bash
# Description: Check version numbers across project files

# Test: Look for version numbers in key project files
echo "Checking version numbers in project files..."
rg -A 1 "version: " --glob '*.{ex,exs}'
rg -A 1 "version:" --glob 'mix.exs'

Consider updating the version number in this file to match the project's current version.


32-32: LGTM: Task rename is consistent with project-wide changes.

The rename from TestFileExt to TestFile aligns with the changes tracked in CHANGELOG.md and implemented across other project files.

Let's verify the consistency of this rename across the codebase:

✅ Verification successful

Rename from TestFileExt to TestFile requires attention

There is still one reference to the old TestFileExt name in the test file test/mix/tasks/recode.update.config_test.exs. This test appears to be intentionally using the old name to test the config update functionality, which is correct since TestFileExt is listed in @removed_tasks in lib/mix/tasks/recode.update.config.ex.

  • test/mix/tasks/recode.update.config_test.exs: Contains TestFileExt in a test configuration
  • lib/mix/tasks/recode.update.config.ex: Lists TestFileExt in @removed_tasks
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that TestFileExt is completely replaced with TestFile

# Test 1: Check for any remaining references to the old name
echo "Checking for any remaining references to TestFileExt..."
rg "TestFileExt"

# Test 2: Verify the new name exists in expected locations
echo "Verifying the new name exists in expected locations..."
rg "TestFile"

Length of output: 4392

lib/recode/task/enforce_line_length.ex (2)

54-54: Migration to new update_source callback.

The change from Source.update to update_source aligns with the new callback system mentioned in the PR summary. The addition of opts parameter provides more context to the update operation.


82-82: Verify the purpose of :dot_formatter option.

The addition of :dot_formatter to valid options suggests integration with Elixir's formatter configuration. However, the module doesn't show how this option is used.

Let's check how this option is utilized:

#!/bin/bash
# Description: Search for usage of :dot_formatter option in the codebase
# to understand its purpose and implementation.

# Search for dot_formatter usage
rg -A 5 ":dot_formatter" 

# Search for documentation or specs related to this option
rg -A 10 "dot_formatter" "*.ex" "*.md"
lib/recode/task/pipe_fun_one.ex (3)

25-32: Clean pipeline refactoring!

The refactored run function presents a clear and maintainable pipeline structure, effectively separating the traversal logic from the update handling.


50-50: Verify the new_issue callback usage.

The change from Issue.new to new_issue aligns with the project-wide refactoring. Let's verify the correct usage of this new callback.

#!/bin/bash
# Description: Verify the new_issue callback implementation and usage pattern

# Search for the callback definition
ast-grep --pattern 'defcallback new_issue($$$) :: $$$'

# Search for other implementations for reference
rg -A 2 'new_issue.*meta' --type elixir

34-35: Verify the update_source callback implementation.

The new update function looks clean and well-structured. Let's verify that it's using the correct callback from the Recode.Task behavior.

✅ Verification successful

Let me gather more specific information about the behavior definition.


Based on the gathered information, I can now provide the final response:

The update_source usage is correct and follows the behavior specification

The implementation in pipe_fun_one.ex correctly uses the update_source/3 callback defined in the Recode.Task behavior. The callback expects (Source.t(), opts :: Keyword.t(), updates :: Keyword.t()) as parameters, which matches the usage pattern where updates are passed as keyword list with :quoted and :issues keys.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the update_source callback implementation in the Recode.Task behavior

# Search for the callback definition
ast-grep --pattern 'defcallback update_source(source, opts, changes) :: result when
  $$$'

# Search for other implementations for reference
rg -A 2 'update_source.*source.*opts.*' --type elixir

Length of output: 5219


Script:

#!/bin/bash
# Search for the behavior definition in the task module
rg -A 10 '@callback update_source' --type elixir

# Search for the behavior specification
rg -A 5 '@behaviour.*Task' --type elixir

# Look for the module definition containing update_source
ast-grep --pattern 'defmodule Recode.Task do
  $$$
  def update_source($$$) do
    $$$
  end
  $$$
}'

Length of output: 2001

lib/recode/task/io_inspect.ex (3)

23-23: LGTM: Enhanced flexibility in options handling

The change to pass the complete opts map provides better extensibility while maintaining backward compatibility.


68-68: Verify consistent usage of new_issue across tasks

The change to use new_issue improves code consistency. Let's verify this pattern is followed in other task modules.

#!/bin/bash
# Description: Verify consistent usage of new_issue across task modules
# Expect: All task modules should use new_issue instead of direct Issue.new calls

# Search for any remaining direct Issue.new usage
rg -g 'lib/recode/task/*.ex' 'Issue\.new'

# Search for new_issue usage in task modules
rg -g 'lib/recode/task/*.ex' 'new_issue' -A 2

26-27: Verify consistent usage of update_source across tasks

The refactoring to use update_source improves code consistency. Let's verify this pattern is followed in other task modules.

✅ Verification successful

Consistent usage of update_source confirmed across task modules

The verification shows that update_source is consistently used across all task modules with similar parameter patterns:

  • Most modules use update_source(source, opts, quoted: zipper, issues: issues)
  • A few variations exist for specific cases (e.g., test_file.ex uses path/issue, alias_order.ex has two variants) but they follow the same general pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of update_source across task modules
# Expect: All task modules should use update_source in a similar way

# Search for update_source usage in task modules
rg -g 'lib/recode/task/*.ex' 'update_source' -A 2

Length of output: 3358


Script:

#!/bin/bash
# Let's search for update_source usage specifically
rg -g 'lib/recode/task/*.ex' 'update_source' -A 2

Length of output: 2255

test/recode/formatter_plugin_test.exs (2)

27-30: LGTM: Configuration structure is well-organized.

The updated configuration structure with nested formatter_opts and recode keys provides better organization and clarity.


46-46: Verify consistent usage of the new formatter options structure.

The format call correctly uses the new configuration structure. Let's verify this pattern is consistently used across the codebase.

✅ Verification successful

Let me gather more context about the formatter options structure to understand if there's any inconsistency.


Let me check the config function to understand how formatter options are processed.


Let me try a different approach to find the config function.


Let me try one final approach to understand the formatter options handling.


All formatter option usages are consistent with the implementation

Based on the implementation and test cases found, all usages of FormatterPlugin.format/2 are consistent:

  • The function accepts content and formatter_opts as arguments
  • The implementation properly handles both cases: when options are passed directly via :recode key and when they're read from config file
  • Test cases cover various scenarios including empty options ([]), options with recode key (recode: []), and formatter_opts variable
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all formatter plugin format calls to ensure consistent usage
rg -A 2 "FormatterPlugin\.format\(" --type elixir

Length of output: 793


Script:

#!/bin/bash
# Get the implementation and context of FormatterPlugin.format
ast-grep --pattern 'def format($$$)'

Length of output: 967


Script:

#!/bin/bash
# Get the implementation of config function in FormatterPlugin
ast-grep --pattern 'def config($$$)'

Length of output: 38


Script:

#!/bin/bash
# Search for config function definition in FormatterPlugin
rg "def config" lib/recode/formatter_plugin.ex -A 10

Length of output: 54


Script:

#!/bin/bash
# Get the entire formatter plugin implementation to understand the options handling
cat lib/recode/formatter_plugin.ex

Length of output: 2719

lib/recode/task/specs.ex (1)

84-84: LGTM! Consistent with the new issue creation pattern.

The change to use new_issue/2 aligns well with the standardization of issue creation across tasks.

test/mix/tasks/recode.update.config_test.exs (1)

54-67: 🛠️ Refactor suggestion

Enhance test documentation and verification for task migration.

This test is crucial for verifying the migration from TestFileExt to TestFile, but it could be more explicit.

  1. Add documentation about the migration context:
   @tag :tmp_dir
+  # Verifies cleanup of renamed task (TestFileExt -> TestFile) during config update
   test "mix recode.update.config cleans up removed tasks", %{tmp_dir: tmp_dir} do
  1. Add explicit verification that the old task is removed and not present in any form:
       assert config ==
               Recode.Config.default()
               |> Keyword.put(:verbose, true)
-              |> Recode.Config.to_string()
+              |> Recode.Config.to_string(),
+              "Config should be updated without the old TestFileExt task"
+
+      refute config =~ "TestFileExt",
+             "Old task name should not exist in updated config"

Let's verify the task renaming across the codebase:

✅ Verification successful

The test correctly verifies task migration and cleanup

The codebase analysis confirms that:

  1. TestFileExt references only exist in migration-related contexts:

    • CHANGELOG.md (documenting the rename)
    • recode.update.config.ex (in @removed_tasks)
    • The test file itself (verifying the cleanup)
  2. TestFile is properly integrated across the codebase:

    • Documented in README.md
    • Configured in default configs
    • Implementation in lib/recode/task/test_file.ex
    • Comprehensive test coverage in test/recode/task/test_file_test.exs

The current test implementation is sufficient as:

  • It's focused on the specific migration scenario
  • The assertion verifies the complete config state
  • The @removed_tasks list in the implementation ensures proper cleanup

The suggested documentation improvements would be nice-to-have but aren't necessary for the test's effectiveness.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the complete removal of TestFileExt references
echo "Checking for any remaining references to TestFileExt..."
rg "TestFileExt"

echo "Verifying the presence of new TestFile task..."
rg "TestFile"

Length of output: 2526

lib/recode/task/dbg.ex (3)

23-23: LGTM: Improved flexibility in options handling

The change to pass the complete opts instead of just opts[:autocorrect] provides better extensibility for future option additions.


26-27: LGTM: Improved code consistency

The refactoring to use update_source/3 aligns with the standardized approach across tasks, making the code more maintainable and consistent with other task implementations.


81-82: LGTM: Standardized issue creation

The change to use new_issue/2 aligns with the standardized approach for issue creation across the codebase.

lib/recode/task/locals_without_parens.ex (3)

22-24: LGTM: Alias changes align with rewrite 1.0.0 migration

The switch from Format to DotFormatter and the addition of Source and Zipper aliases are consistent with the rewrite 1.0.0 migration.


44-45: LGTM: Clean encapsulation of source update logic

The new update/3 function properly encapsulates the source update logic and follows the module's pattern of small, focused functions.


28-34: LGTM: Improved formatter options handling

The new implementation properly handles formatter options by:

  1. Gracefully handling files without paths
  2. Merging custom formatter options with defaults
  3. Using clear, functional pipeline style

Let's verify the formatter configuration handling:

✅ Verification successful

LGTM: Formatter options handling verified

The implementation correctly handles formatter options as evidenced by:

  • Root .formatter.exs defines locals_without_parens configuration
  • Example code shows proper handling of custom configurations
  • Test cases verify the behavior with different locals_without_parens scenarios
  • The fallback to "nofile" is appropriate since some files may be processed without paths
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for .formatter.exs files and their locals_without_parens configuration
rg -l "locals_without_parens" --type-add 'formatter:*.exs' -t formatter

Length of output: 237


Script:

#!/bin/bash
# Check the content of .formatter.exs files to understand the configuration patterns
echo "=== Root .formatter.exs ==="
cat .formatter.exs

echo -e "\n=== Example .formatter.exs ==="
cat examples/my_code/.formatter.exs

echo -e "\n=== Test cases for locals_without_parens ==="
rg "locals_without_parens" test/recode/task/locals_without_parens_test.exs -C 2

Length of output: 1250

test/recode/task/test_file_test.exs (3)

1-5: LGTM: Clean module structure

The module follows proper naming conventions and has minimal, focused imports.


1-105: Verify test coverage of TestFile module

Let's ensure all public functions in the TestFile module are adequately tested.

#!/bin/bash
# Find all public functions in TestFile module
ast-grep --pattern 'def $func($$$) do
  $$$
end' lib/recode/task/test_file.ex

# Check for corresponding test coverage
for func in $(ast-grep --pattern 'def $func($$$)' -f lib/recode/task/test_file.ex | grep -o '\w\+'); do
  echo "Checking tests for $func:"
  rg "$func" test/recode/task/test_file_test.exs
done

48-59: Verify coverage of all path retention scenarios

The tests cover basic path retention cases, but we should verify if all edge cases are handled.

Let's check for other potential test file locations in the project:

✅ Verification successful

Let's search for test file path handling logic and related test cases to verify if all edge cases are covered.


Based on the results, I can now generate the final response:

Test file path retention scenarios are adequately covered

The current test coverage is comprehensive for path retention scenarios:

  • The test directory structure shows various test file locations including fixtures, support, and different module tests
  • The TestFile module's implementation in lib/recode/task/test_file.ex shows explicit handling of:
    • Test file extensions (_test.ex vs _test.exs)
    • Test directory detection (checking for "test" in path)
    • Test module name patterns
    • Support file paths (files without test modules)

The existing test case correctly verifies the edge case of non-test modules in the support directory, which is a critical scenario given the repository structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find all test files to identify potential edge cases
fd -e ex -e exs . test/ --exec echo "File: {}"

# Look for any existing test helpers or support files
rg -g "test/**/*.{ex,exs}" "defmodule.*Support|Helper" -l

Length of output: 346


Script:

#!/bin/bash
# Find all test files and their locations
fd -e ex -e exs . test/

# Look for test helper modules and support files
rg -g "test/**/*.{ex,exs}" "defmodule.*(?:Support|Helper)" -l

# Check for test file path handling in the TestFile module
rg -g "lib/**/*.{ex,exs}" "test.*path" -A 3 -B 3

# Look for test file path related functions
ast-grep --pattern 'def $func($path, $$$) do
  $$$
end'

Length of output: 3801

lib/recode/task/unnecessary_if_unless.ex (2)

35-35: LGTM: Good refactoring to use the new update_source function

The change improves code modularity by consolidating source update logic into a dedicated function, aligning with the rewrite 1.0.0 changes.


65-65: LGTM: Consistent use of new issue creation API

The change appropriately uses the new new_issue/2 function, maintaining consistency with similar changes across the codebase.

lib/mix/tasks/recode.help.ex (1)

73-78: LGTM! Well-structured help message addition.

The added help message improves user experience by providing clear instructions with good visual formatting using color highlighting.

lib/recode/task/single_pipe.ex (3)

32-39: Well-structured refactoring of the run function!

The refactoring improves readability by clearly showing the data transformation pipeline and separating the concerns of traversal and updating. Ironically, this is a perfect example of when pipe operators should be used - for multiple operations in sequence.


41-42: Clean implementation of the update function!

The function follows the single responsibility principle and properly utilizes the new update_source callback, aligning with the standardization efforts across tasks.


Line range hint 1-1: Verify test coverage for function call edge cases.

The module documents specific behavior for cases like one(:a) |> two(), but let's verify that these cases are properly tested.

✅ Verification successful

Let me try a different search strategy to verify the test coverage.


Let me search for test files specifically related to SinglePipe module to verify test coverage for function call edge cases.


Let me check the full test file content to get a complete picture of the test coverage.


Test coverage for function call edge cases is properly implemented

The test file includes comprehensive coverage for function call edge cases:

  1. Test "does not expands single pipes that starts with a none zero fun" specifically covers the case one(:a) |> two()
  2. Multiple variations of function calls with pipes are tested:
    • Basic function calls: foo(arg) |> zoo()
    • Function calls with arguments: foo(arg, :animal) |> zoo(:tiger)
    • Function calls with atoms: one(:a) |> two()
    • Function calls with multiple arguments: one() |> two(:b)

The test coverage verifies that the module correctly handles these cases by not expanding them, which aligns with the documented behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related test cases in the test files
echo "Searching for test cases covering function call edge cases..."
rg -l "test.*single.*pipe.*function" test/
# Look for actual test implementations
ast-grep --pattern 'test "single pipe with function call" do
  $$$
end'

Length of output: 251


Script:

#!/bin/bash
# Search for test files related to SinglePipe module
echo "Searching for SinglePipe test files..."
fd "single_pipe_test.exs" test/

# Look for test cases with pipe operator
echo -e "\nSearching for pipe operator test cases..."
rg "\|>" test/ -A 5 -B 5

# Look for specific test implementations in Elixir
echo -e "\nSearching for test implementations..."
ast-grep --pattern 'test "$_" do
  $$$
  |>
  $$$
end'

Length of output: 320613


Script:

#!/bin/bash
# Search for SinglePipe test files and their content
echo "Searching for SinglePipe test files..."
fd "single_pipe_test.exs" test/

echo -e "\nChecking test content for function call edge cases..."
rg "one\(:a\) \|> two" test/ -A 5 -B 5

Length of output: 1021


Script:

#!/bin/bash
# Get full content of SinglePipe test file
echo "Content of single_pipe_test.exs:"
cat test/recode/task/single_pipe_test.exs

Length of output: 3782

mix.exs (3)

4-4: Version bump looks appropriate.

The minor version increment to 0.8.0 aligns well with the new features being added, such as the new callbacks in Recode.Task.


68-68: LGTM: Module rename is consistent.

The rename from TestFileExt to TestFile is consistent with the changes mentioned in the AI summary.


105-105: Verify rewrite 1.0.0 compatibility.

The update to rewrite ~> 1.0 is aligned with the PR objectives. However, it's important to ensure that all usage of rewrite functions is compatible with version 1.0.0, as this is a major version bump that might include breaking changes.

Also applies to: 111-111

✅ Verification successful

Let me analyze the usage of Rewrite in the codebase to verify compatibility with version 1.0.0.


Rewrite 1.0.0 usage appears compatible

The codebase primarily uses stable Rewrite APIs that are unlikely to have breaking changes in 1.0.0:

  • Core functions: from_sources!, new!, write_all
  • Accessor functions: sources, dot_formatter
  • Standard formatting: format!

All usages follow consistent patterns across test and implementation code, suggesting a stable integration. The update to ~> 1.0 should be safe.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for rewrite function usage that might need updates
rg "Rewrite\." --type elixir -l | xargs rg "^[^#].*Rewrite\." -B 2 -A 2

Length of output: 14313


Script:

#!/bin/bash
# Check the changelog or release notes of rewrite 1.0.0 for breaking changes
rg -l "CHANGELOG|RELEASE" --type md

# Search for specific Rewrite function calls that might have breaking changes
ast-grep --pattern 'Rewrite.$_($$$)'

Length of output: 2234

lib/recode/task/unused_variable.ex (1)

23-23: LGTM! Good refactoring to use the new update_source helper.

The change simplifies the code by abstracting the source update logic into a dedicated helper function, improving maintainability.

lib/recode/task/alias_expansion.ex (1)

32-32: LGTM! Clean refactoring of source update logic.

The change simplifies the code by using the new update_source/3 callback, making the code more maintainable and consistent with other task modules.

test/support/recode_case.ex (2)

6-6: LGTM: Alias addition is appropriate.

The new Rewrite.DotFormatter alias is properly placed and supports the formatter-related changes.


107-107: Verify consistent usage of Source.Ex.from_string across the codebase.

The update to use keyword arguments for path is correct, aligning with rewrite 1.0.0 API changes.

✅ Verification successful

The search results show that both occurrences of Source.Ex.from_string are already using the keyword argument style (path: path), which means there are no instances of the old positional argument style remaining in the codebase.

All usages of Source.Ex.from_string are consistent with rewrite 1.0.0 API

The codebase has been properly updated to use keyword arguments for the path parameter in all instances of Source.Ex.from_string.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining old-style Source.Ex.from_string calls
# that might need updating to the new keyword argument style

# Search for any Source.Ex.from_string calls that might still use the old style
rg "Source\.Ex\.from_string\([^,]+,\s*[^:{\s][^,\)]*\)" --type elixir

Length of output: 235

CHANGELOG.md (1)

3-11: LGTM on the changelog content.

The changelog entries accurately reflect the changes mentioned in the PR objectives and AI summary:

  • Integration with rewrite 1.0.0
  • Addition of new callbacks
  • Renaming of TestFileExt to TestFile
  • Updates to the config command

The changes are well-documented and provide clear information about the updates in this version.

lib/recode/task/moduledoc.ex (1)

123-123: LGTM: Simplified issue creation

The change to use Source.add_issue with new_issue aligns with the PR's refactoring goals and provides a more consistent approach to issue handling across the codebase.

lib/recode/task/filter_count.ex (3)

36-36: LGTM: Improved options handling

The change to pass the full opts map to update/3 aligns with the PR's objective of utilizing rewrite 1.0.0.


39-40: LGTM: Enhanced consistency in source updates

The refactoring to use update_source/3 improves consistency with other task modules and simplifies the update logic by consolidating the autocorrect handling.


162-162: LGTM: Standardized issue creation

Using new_issue/2 instead of direct struct creation aligns with the standardization of issue creation across the codebase.

test/recode/config_test.exs (1)

126-154: LGTM! Well-structured test cases.

The test cases effectively validate the delete_tasks/2 function by:

  • Testing deletion of a single task
  • Testing deletion of multiple tasks
  • Testing deletion with non-existent tasks
  • Verifying the remaining configuration structure

The assertions and test data are clear and well-organized.

lib/recode/task/alias_order.ex (2)

31-31: LGTM: Clean refactor to use the new update_source callback

The changes consistently integrate the new update_source/3 callback while maintaining the existing functionality. The opts parameter is properly threaded through the function calls.

Also applies to: 34-34, 40-40, 43-43, 49-49


97-99: LGTM: Consistent usage of the new issue creation callback

The changes properly implement the new new_issue/2 callback while maintaining the same error messaging and metadata handling.

Also applies to: 106-109

lib/recode/config.ex (2)

43-43: LGTM: Task renaming is consistent with project changes.

The renaming from TestFileExt to TestFile is properly reflected in the default configuration.


10-10: Verify version numbers against PR objective.

The PR mentions "rewrite 1.0.0" but the version constants are set to "0.8.0". Please confirm if this is intentional as part of a gradual upgrade path.

Also applies to: 14-14

✅ Verification successful

Version numbers are correct and consistent with the upgrade path

The version 0.8.0 is correct as this appears to be a development version that will lead to 1.0.0. This is evidenced by:

  • CHANGELOG.md shows 0.8.0 - dev as the latest version
  • One of the changes listed is "Use rewrite version ~> 1.0", indicating this is a transitional release
  • The version is consistently set in both mix.exs and config.ex
  • The progression in the changelog shows a clear path of incremental updates leading to this version
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check version numbers across project files
# Expected: Consistent version numbers or clear upgrade path

echo "Checking version numbers in key files..."
rg -A 1 "version:|Version" mix.exs CHANGELOG.md README.md

Length of output: 453


Script:

#!/bin/bash
# Let's check CHANGELOG.md for version history and upgrade path
echo "=== Checking CHANGELOG.md for version history ==="
cat CHANGELOG.md

# Also check mix.exs for version variable
echo -e "\n=== Checking mix.exs for version definition ==="
rg "@version" mix.exs -A 1

Length of output: 4080

test/recode/task/enforce_line_length_test.exs (7)

24-24: LGTM: Map formatting tests consistently updated

The addition of autocorrect: true to map formatting tests is consistent and appropriate. The test cases cover single-line maps, multi-line maps, and large maps, providing good coverage for map formatting scenarios.

Also applies to: 32-32, 48-48


68-68: LGTM: List and operator formatting tests properly updated

The changes consistently add autocorrect: true to tests handling lists and various operator combinations. The test coverage is comprehensive, including:

  • Simple list formatting
  • Logical operator chaining
  • Arithmetic operator combinations

Also applies to: 86-86, 107-107


133-133: LGTM: Function definition tests thoroughly cover edge cases

The updates to function definition tests are consistent and cover important scenarios:

  • Regular function definitions
  • Functions with guard clauses
  • Nested module contexts

Also applies to: 154-154, 182-182


193-193: LGTM: Control flow formatting tests properly handle complex cases

The changes maintain consistent behavior across different control flow structures:

  • with expressions (both single and multi-line)
  • case statements (both compact and expanded forms)

Also applies to: 217-217, 228-228, 253-253


373-373: LGTM: Assert formatting tests handle different configurations

The changes appropriately cover various assert scenarios with different options:

  • Basic assert formatting
  • Ignored function formatting
  • Skipped assert formatting

Also applies to: 406-406, 442-442


472-472: LGTM: Miscellaneous formatting tests complete the coverage

The final set of tests rounds out the coverage with important edge cases:

  • Nested anonymous functions
  • Keyword list formatting
  • Inline do blocks

Also applies to: 502-502, 513-513


Line range hint 1-515: Verify test coverage for all EnforceLineLength options

Let's ensure we have test coverage for all formatting options.

✅ Verification successful

Test coverage for EnforceLineLength options is complete

The module has two main options:

  • :skip - tested in "keeps fn with skip" and "skip assert_raise" tests
  • :ignore - tested in "keeps fn with ignore" and "ignore fn" tests

Both options are properly validated in the implementation and have corresponding test cases demonstrating their functionality with different AST nodes. The test file also covers the default behavior extensively with various AST constructs.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any untested options in EnforceLineLength module

# Search for option definitions in the EnforceLineLength module
echo "Searching for options in EnforceLineLength module..."
rg -A 5 "^[[:space:]]*@impl[[:space:]]*true.*options" 

# Search for option usage in tests
echo "Searching for option usage in tests..."
rg -A 5 "run_task.*EnforceLineLength.*\{.*\}" test/

Length of output: 311


Script:

#!/bin/bash
# Let's try a different approach to find the options and their test coverage

# First, let's find the EnforceLineLength module implementation
echo "Searching for EnforceLineLength module..."
rg -l "defmodule.*EnforceLineLength"

# Then let's look for any @option or schema definitions
echo -e "\nSearching for option definitions..."
rg "@option|schema.*do" -A 5 lib/

# Finally, let's look for test cases using different options
echo -e "\nSearching for test cases with options..."
rg "run_task\(.*EnforceLineLength.*" test/

Length of output: 3195


Script:

#!/bin/bash
# Let's examine the actual EnforceLineLength module implementation to find all available options

echo "Checking EnforceLineLength module content..."
cat lib/recode/task/enforce_line_length.ex

Length of output: 2158

test/recode/cli_formatter_test.exs (3)

46-46: LGTM: Consistent update to Source.update calls

The changes to Source.update calls improve code clarity by using the by parameter to explicitly indicate the source of updates. The modifications are consistent across all instances and align with the rewrite 1.0.0 changes.

Also applies to: 86-86, 91-91, 136-137, 182-182, 206-206, 403-403


444-444: LGTM: Enhanced error reporting with structured metadata

The addition of structured metadata (task and error) to the Issue.new call improves error reporting capabilities by providing more context about the failure.


638-638: LGTM: Consistent use of keyword arguments

The change to use keyword arguments in Source.Ex.from_string is consistent with the overall pattern of improvements in the rewrite 1.0.0 update.

README.md (3)

38-38: LGTM: Task name updated consistently.

The task name has been updated from TestFileExt to TestFile in the help output, maintaining consistency with the broader renaming changes.


117-117: LGTM: Configuration example updated correctly.

The task configuration example has been updated to use the new TestFile name, maintaining consistency with the renaming changes.


311-312: LGTM: Clear example of file movement.

The example effectively demonstrates the TestFile task's functionality in moving test files from .ex to .exs extension.

lib/recode/task/test_file.ex (6)

1-2: Module definition and short documentation are appropriate

The module Recode.Task.TestFile and its @shortdoc correctly summarize the functionality.


21-25: Function run/2 sequences tasks effectively

The run/2 function correctly sequences the test_file_ext and test_file_name functions, ensuring the source is processed thoroughly.


27-32: Efficient use of pattern matching in test_file_ext/2

The implementation of test_file_ext/2 effectively uses pattern matching with the updated path to determine if a change is needed.


34-60: Comprehensive handling in test_file_name/2

The test_file_name/2 function robustly handles different scenarios for files in the test directory, including files with incorrect names and multiple potential filenames.


62-74: Accurate module filename extraction in test_module_filenames/1

The function properly identifies test module names and constructs corresponding filenames, aiding in correcting file names.


76-79: Correct issue creation and source update in update/3

The update/3 function correctly creates an issue and updates the source with the new path, ensuring ExUnit can find the test file.

lib/recode/task.ex (3)

198-198: Confirm Overridable Callbacks in defoverridable

On line 198, ensure that all intended callbacks are included in the defoverridable directive. This allows implementing modules to override the default implementations.

Please confirm that the callbacks init/1, update_source/3, new_issue/1, and new_issue/2 are correctly specified and that no additional callbacks need to be included.


73-73: Verify Consistency of update_source/3 Callback

The @callback for update_source/3 is defined on line 73. Ensure that all implementations and uses of this function match this arity and that the documentation reflects the correct usage.

Please check that the default implementation and any overrides of update_source/3 align with this callback specification.


186-188: Alignment of Default Implementation with Callback

The default implementation of update_source/3 in the __using__/1 macro calls Recode.Task.update_source/4. Ensure that this aligns correctly with the @callback definition and that __MODULE__ is appropriately used.

Confirm that passing __MODULE__ as an additional parameter does not cause conflicts and that the function signatures are properly synchronized.

test/recode/runner/impl_test.exs (8)

12-12: Addition of alias Rewrite.DotFormatter is appropriate

The alias Rewrite.DotFormatter is correctly added and used within the tests.


19-30: Introduction of in_tmp/2 macro enhances test structure

Defining the in_tmp/2 macro simplifies the test setup by encapsulating the temporary directory handling. This improves code readability and reduces duplication across test cases.


32-43: Centralizing default configuration with @default_config

Defining @default_config consolidates the default settings for tests, promoting maintainability and ease of modification.


44-45: Refactoring config/1 function for clarity

The config/1 function now cleanly merges provided options with the default configuration, enhancing code clarity.


93-107: Verify overridden options between config and cli_opts

The config sets autocorrect: true, while cli_opts overrides it with autocorrect: false. Ensure that this intentional override correctly reflects the desired test scenario and that the test accurately verifies the behavior when CLI options are provided.


258-272: Ensure correct assertion for task exception handling

The test is designed to verify that when a task raises an exception, the runner handles it appropriately. Currently, it asserts {:ok, 1} from Runner.run(config). Confirm that this is the expected behavior when a task fails, and consider checking for an error tuple if applicable.


329-370: Verify existence of FreedomFormatter plugin in formatting test

The test specifies plugins: [FreedomFormatter] in the .formatter.exs configuration. Ensure that FreedomFormatter is a valid and accessible formatter plugin within the test environment. If it's a placeholder or not installed, the test may fail or produce unintended results.


437-470: Ensure consistency between tasks and formatting plugins

In the test "formats code with .formatter.exs and respects plugins", the configuration includes both tasks (e.g., {SinglePipe, []}) and a plugin (FreedomFormatter). Confirm that the tasks and plugins are compatible and that their interactions produce the expected formatting results.

Comment thread examples/my_code/scripts/backup.exs
Comment thread examples/my_code/scripts/backup.exs
Comment thread test/recode/task/locals_without_parens_test.exs
Comment thread lib/recode/issue.ex
Comment thread lib/recode/task.ex
Comment thread lib/recode/runner/impl.ex Outdated
Comment thread lib/recode/runner/impl.ex Outdated
Comment thread test/recode/runner/impl_test.exs
Comment thread test/recode/runner/impl_test.exs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 05fad05 and 3763250.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml (3 hunks)
  • mix.exs (4 hunks)
  • test/recode/runner/impl_test.exs (1 hunks)
🧰 Additional context used
🪛 actionlint
.github/workflows/ci.yml

81-81: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)


83-83: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)

🔇 Additional comments (11)
mix.exs (5)

4-4: Version bump looks good!

The version update to 0.8.0 aligns with the project changes for rewrite 1.0.0 integration.


47-51: Reconsider disabling API reference documentation

This comment reiterates the concerns raised in the previous review. Setting api_reference: false would hide valuable API documentation that exists throughout the codebase. While adding README.md as the main page is good, consider keeping api_reference: true to maintain comprehensive documentation.


68-68: Module rename is consistent

The rename from TestFileExt to TestFile aligns with the broader refactoring changes mentioned in the PR objectives.


105-105: Dependency update aligns with PR objectives

The update to rewrite ~> 1.0 matches the PR's goal of utilizing rewrite version 1.0.0.


112-117: Clean implementation of conditional dependency

The conditional inclusion of freedom_formatter for non-CI environments is well-structured and follows Elixir best practices.

.github/workflows/ci.yml (1)

19-52: LGTM: Matrix configuration is well-structured

The updates to Elixir (1.17.3) and OTP (27.1) versions are correctly configured with appropriate exclusions for incompatible version combinations.

test/recode/runner/impl_test.exs (5)

12-12: LGTM: New alias for DotFormatter

The addition of Rewrite.DotFormatter alias is well-placed and consistently used throughout the formatter-related tests.


19-30: LGTM: Well-structured temporary directory macro

The in_tmp macro effectively manages temporary directory contexts and fixture copying for tests.


32-45: LGTM: Clear default configuration and helper

The default configuration and helper function provide a clean way to manage test configurations.


376-473: LGTM: Comprehensive source-specific test cases

The test cases effectively cover:

  • Running tasks with specific sources
  • Empty string handling
  • Excluded sources
  • Formatter integration with .formatter.exs

329-372: Verify formatter plugin availability

The formatter plugin tests are conditionally executed based on FreedomFormatter.features/1 availability. Consider adding a test case for when the plugin is not available to ensure graceful degradation.

Consider adding an else clause to test the behavior when FreedomFormatter is not available:

if function_exported?(FreedomFormatter, :features, 1) do
  test "formats files with .formatter.exs and respects plugins" do
    # existing test
  end
else
  test "gracefully handles missing formatter plugins" do
    # test graceful degradation
  end
end

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Nov 2, 2024

Pull Request Test Coverage Report for Build 5e01def110a6eaaeda28bebb2179160b802e5f92

Details

  • 87 of 91 (95.6%) changed or added relevant lines in 20 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+2.0%) to 91.993%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/recode/runner/impl.ex 14 18 77.78%
Totals Coverage Status
Change from base Build 8764a0752f86801cdb8c73422022abfe86a2cf8d: 2.0%
Covered Lines: 1011
Relevant Lines: 1099

💛 - Coveralls

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (1)
lib/recode/runner/impl.ex (1)

168-169: Clear Exception Reporting

Formatting the exception message with Exception.format/3 provides detailed error information, which can be helpful for diagnosing issues. Ensure that sensitive information is not exposed in error messages.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3763250 and dd1e009.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml (3 hunks)
  • CHANGELOG.md (1 hunks)
  • lib/recode/runner/impl.ex (7 hunks)
  • lib/recode/task.ex (4 hunks)
  • lib/recode/task/alias_expansion.ex (2 hunks)
  • lib/recode/task/locals_without_parens.ex (2 hunks)
  • lib/recode/task/test_file.ex (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • CHANGELOG.md
  • lib/recode/task/alias_expansion.ex
  • lib/recode/task/test_file.ex
🧰 Additional context used
🪛 actionlint
.github/workflows/ci.yml

81-81: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)


83-83: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)

🔇 Additional comments (22)
.github/workflows/ci.yml (2)

19-19: LGTM: Version updates look good!

The updates to Elixir (1.17.3) and OTP (27.1) versions are appropriate and consistent with the PR objectives.

Also applies to: 26-26


77-77: Previous suggestions for conditional checks are still applicable

The previous review comments about simplifying the test execution strategy and reducing condition repetition using GitHub Actions anchors are still valid for the current code.

Also applies to: 85-85, 88-88, 92-92, 95-95, 98-98

lib/recode/task.ex (5)

4-18: Documentation improvements look great!

The added documentation provides clear, step-by-step instructions for creating recode tasks and explains the implications of using the module. The structure and content are well-organized.


Line range hint 21-42: LGTM! Documentation for run/2 callback is thorough.

The documentation clearly explains the opts structure and its components. The previously reported typo has been fixed.


141-141: Consider making update_source/4 private

This function appears to be for internal use. Consider making it private by changing def to defp.


141-164: Implementation logic looks solid!

The update_source implementation correctly handles:

  • Adding single issues
  • Adding multiple issues
  • Conditional updates based on autocorrect flag
  • Special handling for Zipper values

185-198: Default implementations and overridable callbacks look good!

The default implementations for update_source/3 and new_issue/1,2 are well-designed and properly integrated into the using macro. All new callbacks are correctly made overridable.

lib/recode/runner/impl.ex (10)

50-53: Efficient Retrieval of Formatter Options

Fetching formatter_opts from the config and constructing the dot_formatter is well-implemented. This ensures that formatting options are consistently applied across the project.


58-58: Consistent Module Usage: Confirm Recode.Task.Format

On line 58, the Source.format!/2 function uses by: Recode.Task.Format. As noted earlier, please confirm that Recode.Task.Format is the intended module name.


66-66: Pass dot_formatter to Tasks

Passing the dot_formatter to each task ensures that all formatting adheres to the defined style guidelines. This is a good practice for maintaining code consistency.


104-106: Proper Passing of dot_formatter

Lines 104-106 correctly retrieve the dot_formatter from the project and pass it to the runner function. This maintains the formatting context throughout the task execution.


138-142: Efficient Task Execution with Formatting Context

By modifying the runner/3 function to accept dot_formatter, you ensure that all tasks executed within Enum.reduce/3 have access to the necessary formatting options.


Line range hint 146-156: Consistent Passing of dot_formatter to run_task

In run_task/4, passing dot_formatter down the call chain maintains consistency in formatting across all tasks. This is a solid approach to ensure uniformity.


160-162: Specific Exception Handling for ExUnit.AssertionError

Catching ExUnit.AssertionError separately and re-raising it preserves the stack trace, which is crucial for accurate debugging during tests. This is a good practice.


210-213: Proper Handling of Standard Input

Processing stdin when inputs are ["-"] allows for dynamic source input. Wrapping the source and initializing it with Rewrite.from_sources!() is appropriate.


215-218: Initialization with dot_formatter

Including dot_formatter: dot_formatter() in the Rewrite.new!/2 call ensures that the formatter configurations are applied from the outset. This promotes consistency in source code formatting.


222-225: Robust dot_formatter Initialization

The dot_formatter/0 function attempts to read the .formatter.exs file and falls back to the default formatter if not found. Removing plugins like Recode.FormatterPlugin prevents potential conflicts. This approach enhances the resilience of your formatter setup.

lib/recode/task/locals_without_parens.ex (5)

22-24: Aliases correctly added for necessary modules

The aliases for Rewrite.DotFormatter, Rewrite.Source, and Sourceror.Zipper are appropriately added and will be used in the subsequent code.


35-42: AST traversal and update pipeline is well-structured

The pipeline for traversing and updating the AST using Zipper.traverse/3 and the newly defined update/3 function is correctly implemented.


44-45: update/3 function defined appropriately for source updates

The private update/3 function encapsulates the logic for updating the source with the new quoted AST and collected issues, enhancing code readability and maintainability.


59-59: Typo in issue message corrected

The typo in the issue message has been fixed from "Unncecessary parens" to "Unnecessary parens", ensuring accurate communication.


28-34: ⚠️ Potential issue

Ensure :dot_formatter key exists in opts to prevent runtime errors

The use of Keyword.fetch!(:dot_formatter) will raise a KeyError if the :dot_formatter key is absent in opts. Confirm that opts always includes :dot_formatter to avoid potential runtime exceptions.

You can verify the presence of :dot_formatter in all calls to run/2 with the following script:

This script searches for calls to Recode.Task.LocalsWithoutParens.run/2 and checks if :dot_formatter is included in the options passed.

✅ Verification successful

Let me try to find direct usage of this task and understand its implementation better to verify the concern about :dot_formatter.


I need to verify how the task is invoked through the test helper to understand if :dot_formatter is always provided.


I need to verify if there are any default configurations or task registration that ensures :dot_formatter is always present.


Based on the gathered evidence, I can now provide the final response:

:dot_formatter key must be provided when calling run/2

The task requires the :dot_formatter option to be explicitly provided as it uses Keyword.fetch!/2. This is a valid requirement because:

  • The task's moduledoc explicitly states it uses formatter config from .formatter.exs
  • Test cases demonstrate the correct usage by always providing the :dot_formatter option
  • There's no default configuration or middleware that automatically injects this option
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for all calls to Recode.Task.LocalsWithoutParens.run/2 and check for :dot_formatter in opts.

# Test: Find invocations of run/2 without :dot_formatter in opts.
rg -U 'Recode\.Task\.LocalsWithoutParens\.run\([^,]+,\s*\[\K[^\]]*' -o --replace '$0' | grep -L ':dot_formatter'

Length of output: 306


Script:

#!/bin/bash
# Search for all calls to LocalsWithoutParens.run
rg -U "LocalsWithoutParens\.run" -A 3

# Also check the module implementation to understand how opts are handled
rg -t elixir "defmodule.*LocalsWithoutParens" -A 50

Length of output: 6795


Script:

#!/bin/bash
# Let's check how this task is used in the test helper and other places
rg -t elixir "run_task.*LocalsWithoutParens"

# Also check the implementation of run_task helper
rg -t elixir "def run_task"

Length of output: 575


Script:

#!/bin/bash
# Let's check the implementation of RecodeCase to see if it sets default options
rg -t elixir -A 20 "defmodule.*RecodeCase"

# Also check if there are any other places where this task is registered or configured
rg -t elixir "LocalsWithoutParens.*config|config.*LocalsWithoutParens"

Length of output: 1023

Comment thread .github/workflows/ci.yml
Comment thread lib/recode/task.ex Outdated
Comment thread lib/recode/runner/impl.ex
Comment thread lib/recode/runner/impl.ex
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (1)
lib/recode/runner/impl.ex (1)

222-225: Consider logging formatter initialization errors.

The dot_formatter/0 function silently falls back to default when an error occurs. Consider logging the error to help diagnose configuration issues.

 defp dot_formatter do
   case DotFormatter.read(remove_plugins: [Recode.FormatterPlugin]) do
     {:ok, dot_formatter} -> dot_formatter
-    {:error, _error} -> DotFormatter.default()
+    {:error, error} ->
+      Mix.shell().info("Warning: Failed to read formatter configuration: #{inspect(error)}")
+      DotFormatter.default()
   end
 end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3763250 and ef3f26f.

⛔ Files ignored due to path filters (2)
  • examples/my_code/mix.lock is excluded by !**/*.lock
  • examples/my_code/scripts/backup.bin is excluded by !**/*.bin
📒 Files selected for processing (10)
  • .github/workflows/ci.yml (3 hunks)
  • CHANGELOG.md (1 hunks)
  • examples/my_code/.recode.exs (2 hunks)
  • examples/my_code/priv/repo/migrations/20190417140000_create_users.exs (1 hunks)
  • examples/my_code/scripts/backup.exs (2 hunks)
  • lib/recode/runner/impl.ex (7 hunks)
  • lib/recode/task.ex (4 hunks)
  • lib/recode/task/alias_expansion.ex (2 hunks)
  • lib/recode/task/locals_without_parens.ex (2 hunks)
  • lib/recode/task/test_file.ex (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • CHANGELOG.md
  • examples/my_code/priv/repo/migrations/20190417140000_create_users.exs
  • examples/my_code/scripts/backup.exs
  • lib/recode/task/alias_expansion.ex
  • lib/recode/task/test_file.ex
🧰 Additional context used
🪛 actionlint
.github/workflows/ci.yml

81-81: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)


83-83: shellcheck reported issue in this script: SC2209:warning:1:1: Use var=$(command) to assign output (or quote to assign string)

(shellcheck)

🔇 Additional comments (16)
examples/my_code/.recode.exs (4)

Line range hint 1-38: Configuration structure looks good

The overall structure of the configuration file is correct and aligns with the PR objectives for the rewrite to version 1.0.0. All tasks are properly formatted and the configuration syntax is valid.


26-27: Verify the implementation of new tasks

Three new tasks have been added:

  • LocalsWithoutParens
  • Moduledoc
  • UnnecessaryIfUnless

Let's verify these tasks exist and are properly implemented.

#!/bin/bash
# Description: Verify the existence and implementation of new tasks

# Check if the task modules exist
echo "Checking for task module files..."
fd -e ex "locals_without_parens|moduledoc|unnecessary_if_unless" lib/

# Check for their tests
echo "Checking for corresponding test files..."
fd -e ex "locals_without_parens|moduledoc|unnecessary_if_unless" test/

# Look for documentation of these tasks
echo "Checking for documentation..."
rg -A 5 "LocalsWithoutParens|Moduledoc|UnnecessaryIfUnless" README.md

Also applies to: 35-35


34-34: Verify the task rename implementation

The task has been renamed from TestFileExt to TestFile. This is a breaking change that needs proper documentation and implementation.

#!/bin/bash
# Description: Verify the task rename implementation and documentation

# Check if old module references are completely removed
echo "Checking for any remaining references to TestFileExt..."
rg "TestFileExt"

# Check if the rename is documented in changelog
echo "Checking changelog for rename documentation..."
rg -A 3 "TestFile|TestFileExt" CHANGELOG.md

# Verify the new module exists
echo "Checking for new module implementation..."
fd -e ex "test_file.ex" lib/

2-2: Verify the impact of including the priv directory

The addition of the priv directory to the inputs pattern will cause the tool to process additional files. Please ensure this is intentional and won't affect any build artifacts or generated files that might be stored in the priv directory.

Let's check what additional files this might affect:

Also applies to: 14-14

✅ Verification successful

No impact from priv directory inclusion

The priv directory doesn't exist in the codebase, and the only reference to it is in a test file for checking error handling with non-existent config files. Therefore, including the priv directory in the input paths won't have any immediate impact on the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check what files exist in the priv directory that match the pattern
fd -e ex -e exs . priv/

Length of output: 965


Script:

#!/bin/bash
# Let's check if there are any files in the priv directory
fd . priv/

# Also check if priv directory exists and its contents
ls -la priv/ 2>/dev/null || echo "priv directory does not exist"

# Let's also check if there are any references to the priv directory in the codebase
rg "priv/" -A 2 -B 2

Length of output: 482

.github/workflows/ci.yml (2)

19-19: LGTM: Matrix version updates

The updates to Elixir (1.17.3) and OTP (27.1) versions are appropriate and align with the project's upgrade objectives.

Also applies to: 26-26


77-77: Previous suggestions for conditional steps remain applicable

The existing review comments about simplifying the test execution strategy and reducing condition repetition using GitHub Actions anchors are still valid for these changes.

Also applies to: 85-85, 88-88, 92-92, 95-95, 98-98

lib/recode/task.ex (4)

4-18: Documentation improvements look good!

The added documentation clearly outlines the steps for creating a recode task and explains the implications of using the module.


21-23: LGTM: Appropriate aliases added

The added aliases improve code readability and are correctly used throughout the module.


31-89: Well-documented callbacks with clear specifications

The documentation for each callback is thorough and provides clear guidance on usage, parameters, and return values.


140-164: Clean implementation of source updates

The implementation correctly handles different update types and properly manages the Zipper case. The code is well-structured with clear separation of concerns between public and private functions.

lib/recode/runner/impl.ex (3)

50-58: LGTM: Well-structured formatter configuration.

The implementation properly handles formatter options and plugin configuration. The explicit removal of Recode.FormatterPlugin prevents potential conflicts.


104-106: LGTM: Consistent formatter configuration across tasks.

The implementation ensures that all tasks have access to the same formatter configuration, maintaining consistency throughout the execution pipeline.

Also applies to: 66-66


160-162: LGTM: Improved error handling and debugging context.

The changes properly handle test assertions and enhance error reporting with task-specific context, following Elixir best practices.

Also applies to: 168-169

lib/recode/task/locals_without_parens.ex (3)

28-34: Code correctly retrieves formatter options

The logic for constructing locals_without_parens accurately fetches the formatter options from the .formatter.exs file and concatenates them with the default locals without parens. This ensures that the task respects both custom and default configurations.


59-59: Great job fixing the typo in the issue message

The typo in "Unnecessary parens" has been corrected from the previous version. This ensures clarity in the issue messages produced by the task.


31-31: Verify handling of default file path

When source.path is nil, the default "nofile" is used. Ensure that DotFormatter.formatter_opts_for_file/1 can handle this default value appropriately, or consider implementing a check to handle nil paths explicitly.

You can run the following script to verify that the default path is handled correctly:

✅ Verification successful

Let me search for more specific information about the DotFormatter implementation.


Let me search for the DotFormatter module implementation to understand how it handles file paths.


Let me try one more search to find any formatter-related modules and their file handling logic.


Based on the search results, I can now generate a final response.

Default file path handling is safe and consistent

The usage of "nofile" as a default path is a safe fallback that's consistently used across the codebase. The formatter system is designed to handle this case:

  • The FormatterPlugin module uses a similar pattern with "source.ex" as default
  • The codebase shows multiple test cases and implementations working with formatter options
  • The DotFormatter module is integrated with the standard Elixir formatter infrastructure
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how DotFormatter handles a nil source path.

# Test: Confirm that passing "nofile" does not raise errors.
grep -R "formatter_opts_for_file" lib/ | xargs -I{} echo "Testing with path: 'nofile'"

Length of output: 122


Script:

#!/bin/bash
# Search for DotFormatter implementation and formatter_opts_for_file function
ast-grep --pattern 'def formatter_opts_for_file($$$)'

# Also search for any direct references to "nofile" string
rg "nofile" -B2 -A2

Length of output: 1005


Script:

#!/bin/bash
# Find the DotFormatter module implementation
fd DotFormatter.ex

# Search for any file handling logic in formatter related files
rg -g "**/*formatter*.{ex,exs}" "def.*file.*path" -B2 -A2

Length of output: 80


Script:

#!/bin/bash
# Search for any formatter-related modules
fd -e ex -e exs -x grep -l "formatter" {}

# Look for DotFormatter module definition
ast-grep --pattern 'defmodule $$$DotFormatter$$$'

# Search for any formatter options handling
rg "formatter_opts" -B2 -A2

Length of output: 4843

Comment thread .github/workflows/ci.yml
Comment thread lib/recode/task.ex
Comment thread lib/recode/runner/impl.ex
Comment thread lib/recode/task/locals_without_parens.ex
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
lib/recode/runner/impl.ex (1)

210-228: Consider enhancing error handling in dot_formatter function

While the implementation is functional, consider improving error handling:

  1. The error handling in dot_formatter/0 could be more explicit about the type of errors that can occur
  2. Consider adding logging for better debugging

Consider this improvement:

 defp dot_formatter do
   with true <- File.exists?(".formatter.exs"),
        {:ok, dot_formatter} <- DotFormatter.read(remove_plugins: [Recode.FormatterPlugin]) do
     dot_formatter
   else
     false -> DotFormatter.default()
-    {:error, error} -> error |> Exception.message() |> Mix.raise()
+    {:error, error} ->
+      Logger.error("Failed to read .formatter.exs: #{Exception.message(error)}")
+      error |> Exception.message() |> Mix.raise()
   end
 end
🧰 Tools
🪛 GitHub Check: Test on Ubuntu (Elixir 1.17.3, OTP 27.1)

[warning] 223-223: apply
Function application with args (


[warning] 228-228: call
The function call message will not succeed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ef3f26f and 469d4d6.

⛔ Files ignored due to path filters (2)
  • examples/my_code/mix.lock is excluded by !**/*.lock
  • mix.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • lib/recode/runner/impl.ex (7 hunks)
🧰 Additional context used
🪛 GitHub Check: Test on Ubuntu (Elixir 1.17.3, OTP 27.1)
lib/recode/runner/impl.ex

[warning] 223-223: apply
Function application with args (


[warning] 228-228: call
The function call message will not succeed.

🔇 Additional comments (6)
lib/recode/runner/impl.ex (6)

8-8: LGTM: DotFormatter alias addition

The addition of Rewrite.DotFormatter alias aligns with the PR's objective of implementing rewrite 1.0.0.


26-26: Module name inconsistency detected

The module name Recode.Task.Format differs from Recode.Tasks.Format mentioned in previous reviews. Please verify the correct module name to ensure consistency.


50-58: LGTM: Well-structured formatter configuration

The implementation properly:

  1. Retrieves formatter options from config
  2. Creates a dot_formatter with plugin removal
  3. Applies formatting with the configured formatter

This is a clean implementation of the rewrite 1.0.0 formatting capabilities.


66-66: LGTM: Consistent task execution with formatter

The task execution properly includes the dot_formatter configuration, maintaining consistency with the new formatting approach.


104-106: LGTM: Well-structured runner implementation

The runner implementation properly manages the dot_formatter throughout the task execution chain, providing a clean integration with the rewrite 1.0.0 formatting capabilities.

Also applies to: 138-142


Line range hint 146-169: LGTM: Enhanced error handling

The implementation includes:

  1. Proper passing of dot_formatter to tasks
  2. Specific handling of ExUnit.AssertionError
  3. Clean error message formatting with stacktrace

This provides robust error handling for the task execution pipeline.

@NickNeck NickNeck changed the base branch from main to 0.8.0-dev November 10, 2024 12:55
@NickNeck NickNeck merged commit f961939 into 0.8.0-dev Nov 10, 2024
NickNeck added a commit that referenced this pull request Jan 19, 2025
NickNeck added a commit that referenced this pull request Jan 19, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jul 28, 2025
NickNeck added a commit that referenced this pull request Oct 7, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
* Bump version

* Changes for rewrite 1.0.0 (#96)

* Update rewrite

* Read inputs from .formatter.exs (#98)

* Add recode.issues manifest (#99)

* Add comments

* Remove trailing whitespace

* Move example backup script to mix task

* Update the readme for the my_code example

* Update docs

* Format mix.exs

* Fix false positive in LocalWithoutParens

* Update wording in CliFormatter

* Add example minimal

A minimal example to test recode.

* Update manifest handling

* Update changelog

* Update .dialyzer_ignore.exs

* Add tests for manifest

* Add tests for manifest

* Add specs and docs

* Update test

* Create issues for unformatted files in dry mode

This feature is already part of recode, but was lost in the development
of the new version.

* Add minor refactorings

* Add silent mode (#100)

* Add silent mode

* Remove negated condition in if-else

* Add default for silent in CliFormatter

* Update silent mode doc

* Add some tests

* Fix typo

* Add tests

* Fix rebase fail

* Add minor refactorings

* Update tests

* Update tests

* Fix LocalsWithoutParens task (#104)

* Update changelog

* Fix LocalsWtihoutParens for multiline calls

* Fix LocalsWtihoutParens in pipes

* Run mix format

* Update test

* Fix typos

* Update deps

* Update deps and rebase main

* Check dot_formatter

* Make dialyzer happy

* Fix check_dot_formatter

* Fix check_dot_formatter

* Fix task AliasOrder

* Update changelog
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 10, 2025
NickNeck added a commit that referenced this pull request Oct 19, 2025
NickNeck added a commit that referenced this pull request Oct 19, 2025
NickNeck added a commit that referenced this pull request Oct 19, 2025
* Changes for rewrite 1.0.0 (#96)

* Read inputs from .formatter.exs (#98)

* Add recode.issues manifest (#99)

* Update manifest handling

* Create issues for unformatted files in dry mode

This feature is already part of recode, but was lost in the development
of the new version.

* Add minor refactorings

* Add silent mode (#100)

* Add silent mode

* Remove negated condition in if-else

* Add default for silent in CliFormatter

* Update silent mode doc

* Add some tests

* Fix typo

* Add tests

* Fix rebase fail

* Add minor refactorings

* Fix LocalsWtihoutParens for multiline calls

* Fix LocalsWtihoutParens in pipes

* Run mix format

* Update test

* Changes for rewrite 1.0.0 (#96)

* Add recode.issues manifest (#99)

* Create issues for unformatted files in dry mode

This feature is already part of recode, but was lost in the development
of the new version.

* Add task PipeChainStart

* Update .credo.exs

* Clean up

* Run mix format

* Set fail-fast to false

* Fix test

* rm scripts

* update ci

* Fix filter_count

* Add docs

* Fix typo
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.

1 participant