Skip to content

Commit

Permalink
gogogo
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Jun 12, 2024
1 parent 6945f56 commit 9679727
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 110 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

**Note** Styler's only public API is its usage as a formatter plugin. While you're welcome to play with its internals,
they can and will change without that change being reflected in Styler's semantic version.

## main

### Fixes
Expand Down
69 changes: 42 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ you what's wrong, it just rewrites the code for you to fit its style rules.

You can learn more about the history, purpose and implementation of Styler from our talk: [Styler: Elixir Style-Guide Enforcer @ GigCity Elixir 2023](https://www.youtube.com/watch?v=6pF8Hl5EuD4)

-----------------------

Styler's documentation is under work as part of releasing 1.0.

You can find the much more complete and usable [0.11.9 documentation and readme here.](https://hexdocs.pm/styler/readme.html)
[See our Rewrites documentation on hexdocs for details on what all Styler does](https://hexdocs.pm/styler/)

## Installation

Expand All @@ -23,51 +19,70 @@ def deps do
end
```

Please excuse the mess below as I find spare time to update our documentation =) Anything with TODOs are, well, notes to myself on documentation that needs rewriting. Happy to accept PRs if one seems doable to others.

_@TODO put this somewhere more reasonable_

**Note** Styler's only public API is its usage as a formatter plugin. While you're welcome to play with its internals,
they can and will change without that change being reflected in Styler's semantic version.

Then add `Styler` as a plugin to your `.formatter.exs` file

```elixir
[
plugins: [Styler]
# optionally: include styler configuration
# , styler: [alias_lifting_excludes: []]
]
```

And that's it! Now when you run `mix format` you'll also get the benefits of Styler's Stylish Stylings.

**Speed**: Expect the first run to take some time as `Styler` rewrites violations of styles and bottlenecks on disk I/O. Subsequent formats formats won't take noticeably more time.

### Configuration

@TODO document: config for lifting, and why we won't add options other configs
Styler can be configured in your `.formatter.exs` file

Styler is @adobe's internal Style Guide Enforcer - allowing exceptions to the styles goes against that ethos. Happily, it's open source and thus yours to do with as you will =)
```elixir
[
plugins: [Styler],
styler: [
alias_lifting_exclude: [...]
]
]
```

## Features (or as we call them, "Styles")
Styler's only current configuration option is `:alias_lifting_exclude`, which accepts a list of atoms to _not_ lift. See the [Module Directive documentation](docs/module_directives.md#alias-lifting) for more.

@TODO link examples
#### No Credo-Style Enable/Disable

https://hexdocs.pm/styler/1.0.0-rc.0/styles.html
Styler [will not add configuration](https://github.com/adobe/elixir-styler/pull/127#issuecomment-1912242143) for ad-hoc enabling/disabling of rewrites. Sorry! Its implementation simply does not support that approach. There are however many forks out there that have attempted this; please explore the [Github forks tab](https://github.com/adobe/elixir-styler/forks) to see if there's a project that suits your needs or that you can draw inspiration from.

## Styler & Credo
Ultimately Styler is @adobe's internal tool that we're happy to share with the world. We're delighted if you like it as is, and just as excited if it's a starting point for you to make something even better for yourself.

@TODO link credo doc
## !Styler can change the behaviour of your program!

## Your first Styling
The best example of the way in which Styler changes the meaning of your code is the following rewrite:
```elixir
# Before: this case statement...
case foo do
true -> :ok
false -> :error
end

**Speed**: Expect the first run to take some time as `Styler` rewrites violations of styles.
# After: ... is rewritten by Styler to be an if statement!.
if foo do
:ok
else
:error
end
```

Once styled the first time, future styling formats shouldn't take noticeably more time.
These programs are not semantically equivalent. The former would raise if `foo` returned any value other than `true` or `false`, while the latter blissfully completes.

## Styler can break your code
However, Styler is about _style_, and the `if` statement is (in our opinion) of much better style. If the exception behaviour was intentional on the code author's part, they should have written the program like this:

```elixir
case foo do
true -> :ok
false -> :error
other -> raise "expected `true` or `false`, got: #{inspect other}"
end
```

@TODO link troubleshooting
mention our rewrite of case true false to if and how we're OK with this being _Styler_, not _SemanticallyEquivalentRewriter_.
Also good style! But Styler assumes that most of the time people just meant the `if` equivalent of the code, and so makes that change. If issues like this bother you, Styler probably isn't the tool you're looking for.

## Thanks & Inspiration

Expand Down
68 changes: 67 additions & 1 deletion docs/module_directives.md
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
## Module Directives (`use`, `import`, `alias`, `require`, ...)
## Adds Moduledoc

Adds `@moduledoc false` to modules without a moduledoc unless the module's name ends with one of the following:

* `Test`
* `Mixfile`
* `MixProject`
* `Controller`
* `Endpoint`
* `Repo`
* `Router`
* `Socket`
* `View`
* `HTML`
* `JSON`

## Directive Expansion

Expands `Module.{SubmoduleA, SubmoduleB}` to their explicit forms for ease of searching.

```elixir
# Given
import Foo.{Bar, Baz, Bop}
alias Foo.{Bar, Baz.A, Bop}

# Styled
import Foo.Bar
import Foo.Baz
import Foo.Bop

alias Foo.Bar
alias Foo.Baz.A
alias Foo.Bop
```

## Directive Organization

Modules directives are sorted into the following order:

* `@shortdoc`
* `@moduledoc` (adds `@moduledoc false`)
* `@behaviour`
* `use`
* `import` (sorted alphabetically)
* `alias` (sorted alphabetically)
* `require` (sorted alphabetically)
* everything else (order unchanged)

```elixir
defmodule OrganizeMe do

end
```

If any line previously relied on an alias, the alias is fully expanded when it is moved above the alias:

```elixir
# Given
alias Foo.Bar
import Bar
# Styled
import Foo.Bar

alias Foo.Bar
```

## Alias Lifting
34 changes: 0 additions & 34 deletions docs/troubleshooting.md

This file was deleted.

46 changes: 0 additions & 46 deletions lib/style/module_directives.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ defmodule Styler.Style.ModuleDirectives do
* `Credo.Check.Readability.UnnecessaryAliasExpansion`
* `Credo.Check.Design.AliasUsage`
## Breakages
**This can break your code.**
### Strict Layout
Modules directives are sorted into the following order:
Expand All @@ -43,48 +39,6 @@ defmodule Styler.Style.ModuleDirectives do
* `alias`
* `require`
* everything else (unchanged)
If any of the sorted directives had a dependency on code that is now below it, your code will fail to compile after being styled.
For instance, the following will be broken because the module attribute definition will
be moved below the `use` clause, meaning `@pi` is undefined when invoked.
```elixir
# before
defmodule Approximation do
@pi 3.14
use Math, pi: @pi
end
# after
defmodule Approximation do
@moduledoc false
use Math, pi: @pi
@pi 3.14
end
```
For now, it's up to you to come up with a fix for this issue. Sorry!
### Strict Layout: interwoven conflicting aliases
Ideally no one writes code like this as it's hard for our human brains to notice the context switching!
Still, it's a possible source of breakages in Styler.
alias Foo.Bar
Bar.Baz.bop()
alias Baz.Bar
Bar.Baz.bop()
# becomes
alias Baz.Bar
alias Baz.Bar.Baz
alias Foo.Bar
Baz.bop() # was Foo.Bar.Baz, is now Baz.Bar.Baz
Baz.bop()
"""
@behaviour Styler.Style

Expand Down
3 changes: 1 addition & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ defmodule Styler.MixProject do
"docs/mix_configs.md": [title: "Mix Config Files (config/config.exs, ...)"],
"docs/module_directives.md": [title: "Module Directives (use, alias, ...)"],
"docs/credo.md": [title: "Styler & Credo"],
"README.md": [title: "Styler"],
"docs/troubleshooting.md": [title: "Troubleshooting"],
"README.md": [title: "Styler"]
]
]
end
Expand Down

0 comments on commit 9679727

Please sign in to comment.