Scalafmt formats code so that it looks consistent between people on your team.
For example, it can automatically rewrite this code, which has a weird indentation:
1
2
3
4
5
// Example 1: parameters with indentation after the parenthesis
case class Demo(a: String,
b: Int,
c: Char
)
to a code that is well formatted:
1
2
3
4
5
6
// Example 2: Parameters with 2 spaces indentation
case class Demo(
a: String,
b: Int,
c: Char
)
The original version of the class had several problems:
- The field
b
did not have the same indentation level as the rest of the fields. - Even worse, the argument list started immediately after the class name.
In our example, we started reading the arguments after 16 characters:case class Demo(
.
This means that fieldc
has 16 spaces before it, and ifb
had the same indentation level then it would also have 16 spaces before it.
Now imagine that you rename the class fromDemo
toDemonstration
.
Since we added several characters to the class name, now we also need to indentb
,c
and)
with 9 extra spaces.
It means that for a simple refactor, now the reader of thegit diff
has to read several lines.
Furthermore, the indentation should not depend on the class name.
See more formatting options in the website.
Formatters allow you not think about this kind of problems, and just focus on the code itself.
Add Scalafmt sbt plugin
Scalafmt has an sbt plugin.
After we add it to the project we can use the sbt task scalafmt
to format our code.
Add the plugin to you code by adding the latest version of Scalafmt from the website to project/plugins.sbt
. e.g:
1
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.2.1")
Run reload
in the sbt shell for the changes to take effect.
Configure Scalafmt
We can now use the sbt task scalafmt
in the sbt-shell to format our code.
However, let’s set some custom configuration before that.
Under the root of your project, create a new file called .scalafmt.conf
with the following configuration:
1
2
3
4
version = 2.3.2
maxColumn = 120
trailingCommas = preserve
rewrite.rules = [SortImports]
Config | Description |
---|---|
maxColumn = 120 | scalafmt will split the line if it is longer than 120 characters |
trailingCommas = preserve | keeps the last , in an argument list |
rewrite.rules = [SortImports] | The imports are sorted by the groups: symbols, lower-case, upper-case |
version = 2.3.2 | The latest stable scalafmt version |
Use Scalafmt
Option 1
Use the sbt task scalafmt
in the sbt-shell to format our code.
Option 2
Configure IntelliJ to use scalafmt.
Set the formatter as scalafmt
under Preferences
> Editor
> Code Style
> Scala
.
Now use Option + CMD + L
to format the current file.
You can also set Reformat on file save
in the setting dialog above.
Note
Below is the code style that I use in IntelliJ for projects that do not have scalafmt.
You should change com.example
to your organization’s namespace, save this file as custom-code-style.xml
and set in IntelliJ settings with:
File -> Other Settings -> Preferences for New Projects -> Editor -> Code Style -> Scala
Then click on the wheel icon, choose Import Scheme
and IntelliJ IDEA code style XML
and select this file.
This will set this code style for new projects. You can do so for current projects similarly in the project settings.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<code_scheme name="Dvir" version="173">
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="USE_TAB_CHARACTER" value="true" />
</value>
</option>
<MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings>
<ScalaCodeStyleSettings>
<option name="alwaysUsedImports">
<array>
<option value="pureconfig.generic.auto._" />
</array>
</option>
<option name="importLayout">
<array>
<option value="java" />
<option value="javax" />
<option value="scala" />
<option value="_______ blank line _______" />
<option value="all other imports" />
<option value="com.example" />
<option value="_______ blank line _______" />
</array>
</option>
<option name="PLACE_SELF_TYPE_ON_NEW_LINE" value="false" />
<option name="USE_SCALADOC2_FORMATTING" value="true" />
<option name="CALL_PARAMETERS_NEW_LINE_AFTER_LPAREN" value="2" />
</ScalaCodeStyleSettings>
<codeStyleSettings language="HTML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Scala">
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
</codeStyleSettings>
<codeStyleSettings language="ruby">
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
<option name="SPACE_WITHIN_BRACES" value="true" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="USE_RELATIVE_INDENTS" value="false" />
</indentOptions>
</codeStyleSettings>