Rfx provides a catalog of automated refactoring operations for Elixir source code.
Rfx operations are meant to be embedded into editors, tools and end-user apps. See the experimental rfxi for an example app. Rfx depends on the excellent Sourceror to manipulate AST code and comments.
To get started with this pre-release code, clone the repo, then run > mix test
. NOTE this code is under heavy development - expect rapid changes
and bugs!
See Rfx.Catalog.OpsCat
for a live catalog of Operations.
Module Operations:
Rfx.Ops.Module.RenameModule
)Function Operations:
Filesystem Operations:
Rfx.Ops.Filesys.MvDir
)Rfx.Ops.Filesys.MvFile
)Credo Operations:
Rfx.Ops.Credo.MultiAlias
)Surface Operations:
PhxGen Operations:
Project Operations:
Prototype Operations:
Rfx.Ops.Proto.CommentAdd
)Rfx.Ops.Proto.CommentDel
)Rfx.Ops.Proto.NoOp
)Each operation returns a change set (Rfx.Change.Set
) with a list of of
change requests (Rfx.Change.Request
). The change set is a data structure
that describes all the refactoring changes to be made for an operation.
A change request struct has elements for text edits and file actions (create, rename, delete).
Rfx provides an extensible catalog of converter functions:
Rfx.Change.Set.convert(changeset, :to_string) #> Returns the modified source code
Rfx.Change.Set.convert(changeset, :to_patchfile) #> Returns a unix-standard patchfile
Rfx.Change.Set.convert(changeset, :to_lsp) #> Returns a data structure for LSP
Rfx.Change.Set.convert(changeset, :to_pr) #> Returns a pull-request data structure
Rfx also provides a function that applies the change requests to the filesystem.
Rfx.Change.Set.apply!(changeset) #> Applies the changereqs to the filesystem
Each operation is coded in a standalone module that implements the Rfx.Ops
behavior. A refactoring operation may be applied to different scopes:
Each scope will generate a different set of change requests. Consider for
example the operation Rfx.Ops.Module.RenameModule
.
Rename_Module | # of Change Requests | Text Edits | File Actions |
---|---|---|---|
Scope1 code |
1 | Edit src & docs | NA |
Scope2 file |
1 | Edit src & docs | Rename Src file |
Scope3 project |
1 for each related project file | Edit src & docs | Rename Src & Test file |
Scope4 subapp |
1 for each related subapp file | Edit src & docs | Rename Src & Test file |
Scope5 tmpfile |
1 | Edit src & docs | NA |
Here's a code example:
#!/usr/bin/env elixir
Mix.install([ {:rfx, github: "andyl/rfx"} ])
"x = 1"
|> Rfx.Ops.Proto.CommentAdd.cl_code()
|> Rfx.Change.Set.convert(:to_string)
|> IO.inspect()
# [
# %Rfx.Change.Request{
# file_req: nil,
# text_req: %{diff: "0a1\n> # TestComment\n", input_text: "x = 1"},
# log: %{convert: %{to_string: "# TestComment\nx = 1"}}
# }
# ]
Rfx Operations are intended for use in developer tools:
rfx/scripts
and rfx/notebooks
)def deps do
[
{:rfx, github: "andyl/rfx"}
]
end