<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
    "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
    "https://checkstyle.org/dtds/configuration_1_3.dtd">

<!--
    Checkstyle configuration that checks the coremail coding conventions from
    - the Coremail Java Style at http://wiki.mailtech.cn/pages/viewpage.action?pageId=455
    - the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
    - the Javadoc guidelines at https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html

    Checkstyle is very configurable. Be sure to read the documentation at
    https://checkstyle.org (or in your downloaded distribution).

    Most Checks are configurable, be sure to consult the documentation.

    To completely disable a check, comment it out or delete it from the file.
    To suppress certain violations, please review suppression filters.
-->

<module name="Checker">
    <property name="charset" value="utf8" />

    <module name="FileLength">
        <property name="max" value="2300" />
        <property name="fileExtensions" value="java, kt" />
    </module>
    <module name="LineLength">
        <property name="max" value="150" />
        <property name="fileExtensions" value="java, kt" />
    </module>

    <module name="TreeWalker">

        <!-- Checks for Javadoc comments.                     -->
        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
        <!--
        <module name="JavadocMethod"/>
        <module name="JavadocType"/>
        <module name="JavadocVariable"/>
        <module name="JavadocStyle"/>
        -->

        <!-- Checks for Naming Conventions.                  -->
        <!-- See http://checkstyle.sf.net/config_naming.html -->
        <module name="ConstantName" />
        <module name="LocalFinalVariableName" />
        <module name="LocalVariableName" />
        <module name="MemberName" />
        <module name="MethodName">
            <!-- getter / setter methods allow underline '_' characters -->
            <property name="format" value="^[a-z][a-zA-Z0-9]*$|^(get|set|test)[A-Z]" />
        </module>
        <module name="PackageName" />
        <module name="ParameterName" />
        <module name="StaticVariableName" />
        <module name="TypeName">
            <!-- Test class allow underline '_' characters -->
            <property name="format" value="^[A-Z][a-zA-Z0-9]*$|^(Test)[A-Z]" />
        </module>

        <!-- Checks for imports                              -->
        <!-- See http://checkstyle.sf.net/config_import.html -->
        <module name="AvoidStarImport">
            <property name="excludes" value="java.io,java.util,java.net,org.junit.Assert,org.junit.Assume" />
        </module>

        <!-- IllegalImport: defaults to sun.* packages -->
        <module name="IllegalImport" />
        <module name="RedundantImport" />
        <module name="UnusedImports" />

        <!-- Checks for Size Violations.                    -->
        <!-- See http://checkstyle.sf.net/config_sizes.html -->
        <module name="MethodLength">
            <property name="max" value="350" />
        </module>
        <module name="ParameterNumber" />

        <!-- Checks for whitespace                               -->
        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
        <module name="EmptyForInitializerPad" />
        <module name="MethodParamPad">
            <property name="allowLineBreaks" value="true" />
        </module>
        <module name="NoWhitespaceAfter">
            <property name="tokens" value="AT, INC, DEC, UNARY_MINUS, UNARY_PLUS, BNOT, LNOT, DOT, ARRAY_DECLARATOR, INDEX_OP" />
        </module>
        <module name="NoWhitespaceBefore">
            <property name="allowLineBreaks" value="true" />
            <property name="tokens" value="DOT, POST_DEC, POST_INC" />
        </module>
        <module name="OperatorWrap" />
        <module name="ParenPad" />
        <module name="TypecastParenPad" />
        <module name="WhitespaceAfter" />
        <module name="WhitespaceAround">
            <property name="allowEmptyConstructors" value="true" />
            <property name="allowEmptyMethods" value="true" />
            <!-- Remove 'RCURLY' for reporting annotations: @Annotation({"val1", "val2"}) with error:
                 ~~~~~~  '}' is not proceeded with whitespace. ~~~~~~
            -->
            <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN,
                                           COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE,
                                           LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
                                           LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
                                           LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE,
                                           LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN,
                                           QUESTION, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN, TYPE_EXTENSION_AND" />
        </module>

        <!-- Modifier Checks                                    -->
        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
        <module name="ModifierOrder" />
        <module name="RedundantModifier" />

        <!-- Checks for blocks. You know, those {}'s         -->
        <!-- See http://checkstyle.sf.net/config_blocks.html -->
        <module name="AvoidNestedBlocks" />
        <module name="EmptyBlock">
            <property name="option" value="text" />
        </module>
        <module name="LeftCurly" />
        <module name="NeedBraces" />
        <module name="RightCurly" />

        <!-- Checks for common coding problems               -->
        <!-- See http://checkstyle.sf.net/config_coding.html -->
        <!-- <module name="AvoidInlineConditionals"/> -->
        <module name="CovariantEquals" />
        <!-- <module name="DoubleCheckedLocking"/> -->    <!-- MY FAVOURITE -->
        <module name="EmptyStatement" />
        <module name="EqualsHashCode" />
        <!-- <module name="HiddenField"/> -->
        <module name="IllegalInstantiation" />
        <module name="InnerAssignment" />
        <!--
        <module name="MagicNumber">
            <property name="ignoreNumbers" value="-2, -1, 0, 1, 2"/>
        </module>
        -->

        <!--
        <module name="MissingSwitchDefault"/>
        -->
        <!--
        <module name="RedundantThrows">
            <property name="allowUnchecked" value="true"/>
            <property name="allowSubclasses" value="true"/>
        </module>
        -->
        <!--
        <module name="SimplifyBooleanExpression"/>
        <module name="SimplifyBooleanReturn"/>
        -->

        <!-- Checks for class design                         -->
        <!-- See http://checkstyle.sf.net/config_design.html -->
        <!-- <module name="FinalClass"/> -->
        <module name="HideUtilityClassConstructor" />
        <module name="InterfaceIsType" />
        <module name="VisibilityModifier">
            <property name="protectedAllowed" value="true" />
            <property name="packageAllowed" value="true" />
        </module>


        <!-- Miscellaneous other checks.                   -->
        <!-- See http://checkstyle.sf.net/config_misc.html -->
        <module name="ArrayTypeStyle" />
        <!-- <module name="FinalParameters"/> -->
        <!-- <module name="TodoComment"/> -->
        <module name="UpperEll" />
        <module name="Indentation">
            <property name="basicOffset" value="4" />
            <property name="braceAdjustment" value="0" />
            <property name="caseIndent" value="0" />
            <property name="lineWrappingIndentation" value="4" />
            <property name="arrayInitIndent" value="8" />
            <property name="forceStrictCondition" value="false" />
        </module>

        <module name="SuppressWarningsHolder" />

        <module name="IllegalType">
        </module>

        <module name="Regexp">
            <property name="format" value="System\.out\.println" />
            <property name="illegalPattern" value="true" />
            <property name="ignoreComments" value="true" />
            <property name="message" value="Line has System.out.println call." />
        </module>

        <module name="SuppressionCommentFilter">
            <property name="offCommentFormat" value="CS:AllowPrintln" />
            <property name="onCommentFormat" value="CS:RejectPrintln" />
            <property name="checkFormat" value="Regexp" />
            <!-- 估计应该是 checkstyle 的 bug: SuppressionCommentFilter.messageFormat 如果有 ^ 字符则无法匹配到 -->
            <property name="messageFormat" value="has System\.out\.println" />
        </module>
    </module>

    <module name="SuppressWarningsFilter" />

    <module name="SuppressWithPlainTextCommentFilter ">
        <property name="offCommentFormat" value="CSOFF: *([\w|]+)" />
        <property name="onCommentFormat" value="CSON: *([\w|]+)" />
        <property name="checkFormat" value="$1" />
    </module>

    <property name="fileExtensions" value="
            xml, xhtml, pom, iml, json, jsp, jspx, jspf, tag, tagx, php, asp, aspx,
            java, kt, js, mjs, es6, css, scss, less, yaml, yml, md, markdown, txt, res, cf, ini, htm, html,
            properties, editorconfig, ignore, gitignore, npmignore, eslintignore" />

    <!-- Checks whether files end with a new line.                        -->
    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
    <module name="NewlineAtEndOfFile">
        <property name="fileExtensions" value="
            java, kt, js, mjs, es6, css, scss, less, yaml, yml, md, markdown, txt, res, cf, ini, htm, html,
            properties, editorconfig, ignore, gitignore, npmignore, eslintignore" />
    </module>
    <module name="FileTabCharacter" />
    <module name="RegexpMultiline">
        <property name="format" value="[ \t][\n\r]" />
        <property name="message" value="Trailing whitespace" />
    </module>

</module>
