Scala 的代码风格怎么统一?这份 scalastyle 配置你可以无脑复制

Posted Shockang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala 的代码风格怎么统一?这份 scalastyle 配置你可以无脑复制相关的知识,希望对你有一定的参考价值。

前言

本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系

正文

本文参考 Apache Spark 的 scalastyle 配置。

首先需要在 pom.xml 里面新增 scalastyle 的 plugin。

pom.xml

先定义 2 个和文件字符编码相关的全局变量。

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

配置 scalastyle-maven-plugin

				<plugin>
                    <groupId>org.scalastyle</groupId>
                    <artifactId>scalastyle-maven-plugin</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <verbose>false</verbose>
                        <failOnViolation>true</failOnViolation>
                        <includeTestSourceDirectory>false</includeTestSourceDirectory>
                        <failOnWarning>false</failOnWarning>
                        <sourceDirectory>$basedir/src/main/scala</sourceDirectory>
                        <testSourceDirectory>$basedir/src/test/scala</testSourceDirectory>
                        <configLocation>scalastyle-config.xml</configLocation>
                        <outputFile>$basedir/target/scalastyle-output.xml</outputFile>
                        <inputEncoding>$project.build.sourceEncoding</inputEncoding>
                        <outputEncoding>$project.reporting.outputEncoding</outputEncoding>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>check</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

在项目根目录下定义 scalastyle 的配置文件:scalastyle-config.xml

scalastyle-config.xml

可以无脑复制的部分

<!--
这里参考的 Apache Spark 的 scala 代码风格配置文件。

如果希望关闭代码段的检查,可以在源代码中添加注释
在代码段之前和之后,使用以下语法:

  // scalastyle:off
  ...  // 用来破坏风格的东西
  // scalastyle:on

也可以通过指定规则 ID 来单独取消一条规则,就像这样:
  http://www.scalastyle.org/rules-0.7.0.html

  // scalastyle:off no.finalize
  override def finalize(): Unit = ...
  // scalastyle:on no.finalize

这个文件分成了 3 个部分:

 (1) 我们应当遵守的规则
 (2) 我们想要遵守的规则,但是实际情况不允许。
 (3) 我们不想遵守的规则
-->

<scalastyle>
    <name>Scalastyle standard configuration</name>

    <!-- ================================================================================ -->
    <!--                               我们应当遵守的规则                                   -->
    <!-- ================================================================================ -->

    <!-- 检查文件中是否有标签 -->
    <check level="error" class="org.scalastyle.file.FileTabChecker" enabled="true"></check>

    <!-- 检查加号后面是否有空格 -->
    <check level="error" class="org.scalastyle.scalariform.SpacesAfterPlusChecker" enabled="true"></check>

    <!-- 检查加号前面是否有空格 -->
    <check level="error" class="org.scalastyle.scalariform.SpacesBeforePlusChecker" enabled="true"></check>

    <!-- 检查行尾没有空格 -->
    <check level="error" class="org.scalastyle.file.WhitespaceEndOfLineChecker" enabled="true"></check>

    <!-- 检查一行中的字符数 -->
    <check level="error" class="org.scalastyle.file.FileLineLengthChecker" enabled="true">
        <parameters>
            <parameter name="maxLineLength"><![CDATA[100]]></parameter>
            <parameter name="tabSize"><![CDATA[2]]></parameter>
            <parameter name="ignoreImports">true</parameter>
        </parameters>
    </check>

    <!-- 检查类名是否与正则表达式匹配 -->
    <check level="error" class="org.scalastyle.scalariform.ClassNamesChecker" enabled="true">
        <parameters>
            <parameter name="regex"><![CDATA[[A-Z][A-Za-z]*]]></parameter>
        </parameters>
    </check>

    <!-- 检查对象名称是否与正则表达式匹配 -->
    <check level="error" class="org.scalastyle.scalariform.ObjectNamesChecker" enabled="true">
        <parameters>
            <parameter name="regex"><![CDATA[(config|[A-Z][A-Za-z]*)]]></parameter>
        </parameters>
    </check>

    <!-- 检查包对象名是否与正则表达式匹配 -->
    <check level="error" class="org.scalastyle.scalariform.PackageObjectNamesChecker" enabled="true">
        <parameters>
            <parameter name="regex"><![CDATA[^[a-z][A-Za-z]*$]]></parameter>
        </parameters>
    </check>

    <!-- 检查方法的参数个数是否超过设置数量 -->
    <check customId="argcount" level="error" class="org.scalastyle.scalariform.ParameterNumberChecker" enabled="true">
        <parameters>
            <parameter name="maxParameters"><![CDATA[10]]></parameter>
        </parameters>
    </check>

    <!-- 检查类和对象是否定义了finalize()方法 -->
    <check level="error" class="org.scalastyle.scalariform.NoFinalizeChecker" enabled="true"></check>

    <!-- 检查类和对象在没有覆盖的情况下定义了相等(java.lang.object) -->
    <check level="error" class="org.scalastyle.scalariform.CovariantEqualsChecker" enabled="true"></check>

    <!-- 检查结构类型是否未被使用 -->
    <check level="error" class="org.scalastyle.scalariform.StructuralTypeChecker" enabled="true"></check>

    <!-- 检查如果使用长字符串,则使用大写字母 -->
    <check level="error" class="org.scalastyle.scalariform.UppercaseLChecker" enabled="true"></check>

    <!-- 检查if是否使用大括号 -->
    <check level="error" class="org.scalastyle.scalariform.IfBraceChecker" enabled="true">
        <parameters>
            <parameter name="singleLineAllowed"><![CDATA[true]]></parameter>
            <parameter name="doubleLineAllowed"><![CDATA[true]]></parameter>
        </parameters>
    </check>

    <!-- 检查方法是否具有显式返回类型 -->
    <check level="error" class="org.scalastyle.scalariform.PublicMethodsHaveTypeChecker" enabled="true"></check>

    <!-- 检查文件是否以换行符结尾 -->
    <check level="error" class="org.scalastyle.file.NewLineAtEofChecker" enabled="true"></check>

    <!-- 检查是否使用非ASCII字符(Unicode字符) -->
    <check customId="nonascii" level="error" class="org.scalastyle.scalariform.NonASCIICharacterChecker"
           enabled="true"></check>

    <!-- 检查在注释后是否有一个空格 -->
    <check level="error" class="org.scalastyle.scalariform.SpaceAfterCommentStartChecker" enabled="true"></check>

    <!-- 检查某些既定标记前是否有空间 -->
    <check level="error" class="org.scalastyle.scalariform.EnsureSingleSpaceBeforeTokenChecker" enabled="true">
        <parameters>
            <parameter name="tokens">ARROW, EQUALS, ELSE, TRY, CATCH, FINALLY, LARROW, RARROW</parameter>
        </parameters>
    </check>

    <!-- 检查某些既定标记后是否有空间 -->
    <check level="error" class="org.scalastyle.scalariform.EnsureSingleSpaceAfterTokenChecker" enabled="true">
        <parameters>
            <parameter name="tokens">ARROW, EQUALS, COMMA, COLON, IF, ELSE, DO, WHILE, FOR, MATCH, TRY, CATCH, FINALLY,
                LARROW, RARROW
            </parameter>
        </parameters>
    </check>

    <!-- 检查代码是否有 ??? 操作符 -->
    <check level="error" class="org.scalastyle.scalariform.NotImplementedErrorUsage" enabled="true"></check>

    <!-- 由于 SPARK-7977, 所有的 println 都应该由 '// scalastyle:off/on println' 包裹-->
    <check customId="println" level="error" class="org.scalastyle.scalariform.TokenChecker" enabled="true">
        <parameters>
            <parameter name="regex">^println$</parameter>
        </parameters>
        <customMessage><![CDATA[确定要 println 吗? 如果是的话,需要用下面的代码段包裹:
        // scalastyle:off println
        println(...)
        // scalastyle:on println]]></customMessage>
    </check>

    <!-- mutable.SynchronizedBuffer -->
    <check customId="mutablesynchronizedbuffer" level="error" class="org.scalastyle.file.RegexChecker" enabled="true">
        <parameters>
            <parameter name="regex">mutable\\.SynchronizedBuffer</parameter>
        </parameters>
        <customMessage><![CDATA[
      确定要使用 mutable.SynchronizedBuffer 吗? 大多数场景下,你应该使用
      java.util.concurrent.ConcurrentLinkedQueue 来替代。
      如果你必须使用 mutable.SynchronizedBuffer,使用下面的代码段来包裹:
      // scalastyle:off mutablesynchronizedbuffer
      mutable.SynchronizedBuffer[...]
      // scalastyle:on mutablesynchronizedbuffer
    ]]></customMessage>
    </check>

    <!-- Class.forName -->
    <check customId="classforname" level="error" class="org.scalastyle.file.RegexChecker" enabled="true">
        <parameters>
            <parameter name="regex">Class\\.forName</parameter>
        </parameters>
        <customMessage><![CDATA[
      确定要使用 Class.forName 吗? 大多数场景下,你应该使用 Utils.classForName 来替代.
      如果你必须使用 Class.forName,使用下面的代码段来包裹:
      // scalastyle:off classforname
      Class.forName(...)
      // scalastyle:on classforname
    ]]></customMessage>
    </check>

    <!-- 检查正则表达式是否匹配 -->
    <check customId="caselocale" level="error" class="org.scalastyle.file.RegexChecker" enabled="true">
        <parameters>
            <parameter name="regex">(\\.toUpperCase|\\.toLowerCase)(?!(\\(|\\(Locale.ROOT\\)))</parameter>
        </parameters>
        <customMessage><![CDATA[
      确定要使用 toUpperCase or toLowerCase without the root locale ? 大多数场景下,你应该使用
       toUpperCase(Locale.ROOT) or toLowerCase(Locale.ROOT) 来替代。
      如果你必须使用 toUpperCase or toLowerCase without the root locale,使用下面的代码段来包裹:
      // scalastyle:off caselocale
      .toUpperCase
      .toLowerCase
      // scalastyle:on caselocale
    ]]></customMessage>
    </check>

    <!-- throw new Error -->
    <check customId="throwerror" level="error" class="org.scalastyle.file.RegexChecker" enabled="true">
        <parameters>
            <parameter name="regex">throw new \\w+Error\\(</parameter>
        </parameters>
        <customMessage><![CDATA[
      确定要这样抛出异常吗?大多数场景下,你应该使用精确的异常来替代。
      如果你必须这样抛出异常,使用下面的代码段来包裹:
      // scalastyle:off throwerror
      throw new XXXError(...)
      // scalastyle:on throwerror
    ]]></customMessage>
    </check>

    <!-- 由于 SPARK-9613, JavaConversions 应该替换成 JavaConverters -->
    <check customId="javaconversions" level="error" class="org.scalastyle.scalariform.TokenChecker" enabled="true">
        <parameters>
            <parameter name="regex">JavaConversions</parameter>
        </parameters>
        <customMessage>不要去隐式导入 scala.collection.JavaConversions._ 了, 导入
            scala.collection.JavaConverters._ 并且使用 .asScala / .asJava 方法
        </customMessage>
    </check>

    <!-- extractOpt -->
    <check customId="extractopt" level="error" class="org.scalastyle.scalariform.TokenChecker" enabled="true">
        <parameters>
            <parameter name="regex">extractOpt</parameter>
        Scala 风格:一个文件中有多个类?

在Scala中表示readline循环的最佳方法?

scala入门笔记

使用Scala的强大api快速加工数据

Scala数据类型的继承结构

linux 怎么运行scala