Skip to content

improvement: within tests and docs #267

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ken-kost
Copy link
Contributor

I made a test before the guide to use an example I suppose. But before that we can improve the test also.

Contributor checklist

  • Bug fixes include regression tests
  • Features include unit/acceptance tests

Copy link
Contributor

@zachdaniel zachdaniel left a comment

Choose a reason for hiding this comment

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

Looks good 👍

@ken-kost ken-kost force-pushed the improvement-within-test-and-guide branch from 25bbe87 to 91c572c Compare April 12, 2025 12:01
@ken-kost ken-kost requested a review from zachdaniel April 12, 2025 12:13
@ken-kost ken-kost marked this pull request as ready for review April 12, 2025 12:13
@ken-kost
Copy link
Contributor Author

First time doing a docs guide. 🐛 Tried to keep it simple and concise. But I'm guessing this could be expanded to cover more real world examples. 🤔

|> Igniter.Project.Module.find_and_update_module!(SomeModule, fn zipper ->
zipper
|> within!(fn zipper ->
pred = &match?(%Zipper{node: {:alias, _, _}}, &1)
Copy link
Contributor

Choose a reason for hiding this comment

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

We never really want to match on the zipper node if we can avoid it. For this example I'd pick something exactly matching for simplicity, like Igniter.Code.Common.nodes_equal?(zipper, Some.Module)

Copy link
Contributor

@zachdaniel zachdaniel Apr 12, 2025

Choose a reason for hiding this comment

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

Ah, ignore that, use Igniter.Code.Function.function_call?(zipper, :alias, 1)

Copy link
Contributor

Choose a reason for hiding this comment

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

Even better:

Igniter.Code.Function.function_call?(zipper, :alias, 1, &Igniter.Code.Function.argument_equals?(&1, 0, The.Module.To.Replace)

Copy link
Contributor

Choose a reason for hiding this comment

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

Your example using remove will actually remove all aliases from the module, so that's why you want to be as specific as possible :).

The way I would typically recommend doing it is instead of using remove and add, you would move to the location of the node you want to modify and then replace that node.

case move_to_my_alias(zipper) do
  {:ok, zipper} -> 
    {:ok, Igniter.Code.Common.replace_code(zipper, "import Some.Example, only: [:function]")}
  :error ->
    {:ok, zipper}
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I knew my way wasn't the right way 😂 But this way I'll learn the right way. 💯

@@ -0,0 +1,100 @@
# Writing Installers
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets call this guide "writing installers & generators".

The logic is essentially the same, the only thing is that if your task is called <your_library>.install then it will be invoked when mix igniter.install is called.

## Fetching Dependency

```elixir
if Igniter.Project.Deps.has_dep?(igniter, :my_dep) do
Copy link
Contributor

Choose a reason for hiding this comment

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

So you don't have to do this typically. I'd say let's remove this example. If your installer should install additional packages or add additional dependencies, that should be configured in the installer. i.e installs: [{:other_dep, ...}], adds_deps: [{:other_dep2, ...}].

You don't need to add the specific dep that you are installing, as igniter handles that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤔
When I comment out fetch_dep which does above and do in info:

        adds_deps: [{:routex, "~> 1.1"}],
        installs: [{:routex, "~> 1.1"}],

No changes detected on assert_has_patch("mix.exs", ...)

Refering to this

Am I missing something? :thinkies:

Copy link
Contributor

Choose a reason for hiding this comment

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

In tests we use compose_task which does not call the full installer. but when using igniter.install it will.

end)
```

In the function block use [`within/2`](https://hexdocs.pm/igniter/Igniter.Code.Common.html#within/2) to do multiple modifications. Find the part you want to change and modify it.
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this tip, but let's maybe put it in its own section called like "making multiple modifications to a zipper"? Something good to describe also is the general concept of:

Igniter provides a high level API for working with a data structure called a "zipper". This data structure is defined by sourceror (link to sourceror), and at a certain level of generator complexity, you will inevitably end up working with zippers. We recommend reading through sourcerer's documentation. While we provide many tools for working with source code (Igniter.Code.*, or working with project level concepts (Igniter.Project.*), you may find yourself needing to use functions from Sourceror.Zipper. This is normal. We provide high level wrappers around many sourceror operations that are "smart" and handle various edge cases and source code formats for you, but not every function from Sourceror.Zipper needs a corresponding function from Igniter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So much to learn 🧠 I should put this back to draft. ✔️

Copy link
Contributor

Choose a reason for hiding this comment

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

You're doing great 😄 This is an important guide to get right and I'm grateful you're putting in the effort here 🙇

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually I just realized we have a "Writing generators" guide: https://github.com/ash-project/igniter/blob/main/documentation/writing-generators.md

Maybe lets merge these with the name "Writing installers and generators" 😄

@ken-kost ken-kost marked this pull request as draft April 12, 2025 15:32
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.

2 participants