Skip to content

Commit 76b513f

Browse files
committed
Address feedback
1 parent 631ebf1 commit 76b513f

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

blog/_posts/2017-02-23-scalafix-v0.3.md renamed to blog/_posts/2017-02-25-scalafix-v0.3.md

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,42 @@ title: "Refactor with scalafix v0.3"
66
---
77

88
I am happy to announce the release of [scalafix v0.3][scalafix].
9-
This release leverages the new scala.meta semantic API to provide a re-designed `Rewrite` and `Patch` API for refactorings.
9+
This release uses the new scala.meta semantic API to provide a re-designed `Rewrite` and `Patch` API for refactorings.
1010
Let me explain what that means word by word.
1111

12-
## scala.meta semantic API
12+
> Note. This is the second post on scalafix and scala.meta. You might be
13+
> interested in reading the first post
14+
> [here](http://scala-lang.org/blog/2016/10/24/scalafix.html).
15+
16+
## Scala.meta semantic API
1317

1418
Scala.meta recently announced the [first release of its semantic API][meta-1.6].
1519
This release is the product of close collaboration for the past several months between
16-
[@xeno-by](https://twitter.com/xeno_by) at Twitter and myself at the Scala Center.
17-
The semantic API provides operations to query information from the compiler.
20+
[@xeno_by][] at Twitter and [myself][@olafurpg] at the Scala Center.
21+
The objective of the semantic API is to provide operations to query information from the compiler.
1822

19-
The first version of the scala.meta semantic API makes it possible to query for the "symbol" of a name that appears in a Scala source file.
20-
A symbol is a unique identifier of a definition such as a class, val, def or trait.
21-
For example, the symbol of `println` from the standard library is `_root_.scala.Predef.println(Ljava/lang/Object;)V`.
23+
The first version of the scala.meta semantic API makes it possible to query for the resolved "symbol" of a name that appears in a Scala source file.
24+
A name is a reference to some definition, for example `println` or `scala.Predef.println`.
25+
A symbol is a unique identifier of a single definition.
26+
For example, `println` from the standard library has the symbol `_root_.scala.Predef.println(Ljava/lang/Object;)V.`.
27+
The compiler is responsible for resolving names to symbols.
2228

23-
Symbols are created by "scalahost", a compiler plugin.
24-
Scalahost emits symbols of a source file in the form of a "semantic database".
29+
Scalahost is a compiler plugin in the scala.meta project that extracts symbols from the compiler and maps them to scala.meta syntax trees.
30+
Scalahost emits the extracted symbols into a "semantic database".
2531
The semantic database can be persisted to files on disk and loaded for later analysis.
2632
Semantic databases from different compilation units, potentially produced by different
2733
versions of the Scala compiler, can be merged.
2834
This opens possibilities for large-scale code analysis.
2935

3036
The introduction of the scala.meta semantic API is a game changer for scalafix.
31-
The ability to query for symbols open possibilities for many scalafix rewrites.
37+
The ability to resolve names to symbols opens possibilities for many scalafix rewrites.
3238

3339
## Rewrite: meta.Tree => Seq[Patch]
3440

3541
A scalafix `Patch` is a small operation that can produce a diff on a Scala source file.
3642
A patch can either be a "token patch" or a "tree patch".
3743

38-
Token patches are low-level but give full control of how small details are handled in a source files, for example formatting and comments
44+
Token patches are low-level but give full control over how every detail in a source file is handled, for example formatting and comments.
3945
Example token patches are `Remove(token)` and `AddLeft(token, toAdd: String)`, which removes or prepends a string to `token`, respectively.
4046

4147
Tree patches are high-level and allow rewrite author to declaratively explain what operation to perform.
@@ -46,8 +52,8 @@ Tree and token patches build a small algebra of operations that can be composed
4652
A challenge with composing patches is to figure out what to do on conflicts.
4753
For example, what happens when one patch renames a token while the other patch removes the same token?
4854
The current strategy in scalafix is to try and resolve as many conflicts as possible on the tree patch level.
49-
Once we we only have token patches, it is harder to resolve conflicts.
50-
Unsolvable conflicts on the token level abort the refactoring.
55+
It can be harder to resolve conflicts on the token level since the original intent of the patch is lost.
56+
Unsolvable conflicts abort the refactoring.
5157
In the future, we hope to support more advanced conflict resolution strategies.
5258

5359
In a nutshell, a scalafix `Rewrite` is a `scala.meta.Tree => Seq[Patch]` function.
@@ -56,9 +62,9 @@ To demonstrate how rewrites are implemented with scalafix v0.3, let's step throu
5662

5763
## Example: Xor to Either
5864

59-
The functional programming library [cats][cats] migrated recently from its `Xor` data type to `Either` from the standard library.
65+
The functional programming library [cats][] migrated recently from its `Xor` data type to `Either` from the standard library.
6066
It requires a few mechanical steps to migrate code to use `Either` instead of `Xor`.
61-
For example, below is a diff that's taken from [circe][xor-circe]'s migration to `Either`.
67+
For example, below is a diff that's taken from [circe][]'s migration to `Either`.
6268

6369
```diff
6470
-final def either: Xor[HCursor, HCursor] = if (succeeded) Xor.right(any) else Xor.left(any)
@@ -108,30 +114,37 @@ The recommended way to use scalafix as tool is the [`sbt-scalafix`][sbt-scalafix
108114
It's possible define custom tree patches in the [`.scalafix.conf` configuration file][config-patches].
109115

110116
The long-term mission of scalafix is to help automate the migration of deprecated Scala 2.x features to Dotty.
111-
However, as I have hopefully demonstrated in this post, scalafix can be used for more than just migrating between Scala versions.
117+
However, as I have demonstrated in this post, scalafix can be used for more than just migrating between Scala versions.
112118
Scalafix can also be used for ad-hoc library and application migrations.
113119

114120
I am excited to see what applications the community can build with scala.meta and scalafix.
115121
Some promising ideas that have floated around include
116122

117-
- parse and run rewrites from `@deprecated` warning messages. This would enable library authors
118-
to provide exectuable migration guides.
119-
- use scalafix to cross-build against multiple similar APIs. For example, a
120-
library author could write against scalaz and rewrite to cats.
123+
- parse and run rewrites from `@deprecated` warning messages. This would enable
124+
library authors to provide executable migration guides.
125+
- shim/cross-build libraries with similar APIs. For example,
126+
a library could be developed with the scalaz API, and use scalafix to
127+
code-generate a version of the library that uses cats instead.
121128
- build a code search web-interface with "jump to definition" functionality
122129
powered by the scala.meta's semantic database.
123-
- replace usage of the infamous `any2StringAdd` in favor of string interpolators or explicit `.toString`.
124-
- replace usages of `scala.Seq`, which can be mutable, in favor of `scala.collection.immutable.Seq`.
130+
- replace usage of `scala.Seq`, which can be mutable, in favor of `scala.collection.immutable.Seq`.
125131

126132
If this sounds exciting to you, join us!
127133
I am happy to answer any question in the [scalafix gitter][gitter] channel.
128134

135+
PS. I want to thank [@ShaneDelmore][] who has provided invaluable feedback from
136+
the early days of scalafix development and come up with several brilliant ideas
137+
for scalafix use-cases.
138+
139+
140+
[@ShaneDelmore]: https://twitter.com/ShaneDelmore
141+
[@olafurpg]: https://twitter.com/olafurpg
142+
[@xeno_by]: https://twitter.com/xeno_by
129143
[xor2either-test]: https://github.com/scalacenter/scalafix/blob/f61136fad79afcdbb03528ce78c7928afc6eafd6/scalafix-nsc/src/test/resources/syntactic/Xor2Either.source
130144
[xor2either]: https://github.com/scalacenter/scalafix/blob/f61136fad79afcdbb03528ce78c7928afc6eafd6/core/src/main/scala/scalafix/rewrite/Xor2Either.scala
131-
[xor-circe]: https://github.com/circe/circe/pull/343/files
145+
[circe]: https://github.com/circe/circe/pull/343/files
132146
[cats]: http://github.com/typelevel/cats
133147
[ghpages]: http://github.com/scalacenter/scalafix
134-
[prevpost]: http://scala-lang.org/blog/2016/10/24/scalafix.html
135148
[scalafix]: https://scalacenter.github.io/scalafix/#0.3.0
136149
[sbt-scalafix]: https://scalacenter.github.io/scalafix/#sbt-scalafix
137150
[sbt-scalahost]: https://scalacenter.github.io/scalafix/#sbt-scalahost

0 commit comments

Comments
 (0)