美文网首页
IDEA统一CodeStyle

IDEA统一CodeStyle

作者: 猴子的烟枪 | 来源:发表于2020-07-06 18:48 被阅读0次

    IDEA 配置统一的方法注释和类注释

    最近觉得建立统一的代码风格检查很有必要,主要有以下原因

    • 没有良好的注释和返回说明,有些不能见名知意;往往代码经过多人修改,就会无法溯源,扯皮的事儿就会多

    • 风格差异太大,只要每个人的IDE不同,提交后自动格式化后就会有版本冲突

    类注释

    image-20200615183353699.png

    在File->Settings->Editor->File and Code Templates下分别修改Class,Interface,Enum等注释模板

    /**
     * FileName: ${NAME}
     * Author:   ${USER}
     * Date:     ${DATE} ${TIME}
     * Description: ${DESCRIPTION}
     */
    #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")
     package ${PACKAGE_NAME};
    #end
    ​
    /**
     * 〈${DESCRIPTION}〉
     * @author ${USER}
     * @create ${DATE}
     * @since 1.0.0
     */
    public class ${NAME} {
    ​
    }
    

    方法注释模板

    • 新建方法注释模板


      image.png
    • 设置注释模板
     * @Author $user$
     * @Description
     * @date $date$ $time$ $params$ $return$
     **/
    
    • 编辑注释模板的环境变量(groovy脚本)
    image.png
    • @param自动获取脚本
    groovyScript("if(\"${_1}\".length() == 2){
     return '';
     }else{
     def result=''; 
     def params=\"${_1}\".replaceAll('[\\\\[|\\\\]|\\\\s]', '').split(',').toList();
     for(i = 0; i < params.size(); i++) {
     if(params[i]=='null'){
     return;
     }else{
     result+='\\n' + ' * @param ' + params[i] 
     }
     }; 
     return result;
     }", methodParameters());
    
    • @return注释模板脚本
      • 不带泛型参数(本次使用这个)
    groovyScript("def result=''; def params=\"${_1}\"; 
             if(params.indexOf('<')!=-1){
             result=params.substring(0, params.indexOf('<')); 
             return '\\n * @return ' +'{@link '+result+'}';
             }
             else{
             if(params=='null'||params=='void'){
             return;
             }
             else{
             return '\\n * @return ' +'{@link ' + params+'}';
             }
             }", methodReturnType());
    
    • 返回参数带泛型(不建议使用)
             if(returnType=='null'||returnType=='void'){
             return;
             }else{
             result += '\\n * @return ' + \"{@link \"+returnType+\"}\"; return result;
             }", methodReturnType());
    

    IDEA配置GoogleCodeStyle

    导入官方配置文件

    image-20200616144738276.png

    IDEA修改

    intellij-java-google-style.xml导入后,根据个人习惯修改部分设置,以下是示例

    备注:你也可以直接修改intellij-java-google-style.xml文件后导入IDEA就可以了

    • 修改每行字符限制
    image-20200616145130828.png
    • 缩进调整
    image-20200616145248178.png
    • 对齐
    image-20200616145504306.png

    IDEA 配置GoogleCodeStyleCheck

    intellij-java-google-style.xml可以控制你的代码格式,但是对于方法是否有doc文档注释,类名是否合法,导入无效的包等,需要能够对这些不符合规定风格的代码进行检查,CheckStyle插件就是专门做这个的。

    安装CheckStyle-IEEA插件

    image-20200615180636252.png

    配置CheckStyle.xml

    • CheckStyle.xml文件修改

    CheckStyle官方参考

    以下是基于官方配置修改后内容

    <?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 Google coding conventions from Google Java Style
     that can be found at https://google.github.io/styleguide/javaguide.html
     Checkstyle is very configurable. Be sure to read the documentation at
     http://checkstyle.org (or in your downloaded distribution).
     To completely disable a check, just comment it out or delete it from the file.
     To suppress certain violations please review suppression filters.
     Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
     -->
    ​
    <module name = "Checker">
     <property name="charset" value="UTF-8"/>
    ​
     <property name="severity" value="warning"/>
    ​
     <property name="fileExtensions" value="java, properties, xml"/>
     <!-- Excludes all 'module-info.java' files              -->
     <!-- See https://checkstyle.org/config_filefilters.html -->
     <module name="BeforeExecutionExclusionFileFilter">
     <property name="fileNamePattern" value="module\-info\.java$"/>
     </module>
     <!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
     <module name="SuppressionFilter">
     <property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
     default="checkstyle-suppressions.xml" />
     <property name="optional" value="true"/>
     </module>
    ​
     <!-- Checks for whitespace                               -->
     <!-- See http://checkstyle.org/config_whitespace.html -->
     <module name="FileTabCharacter">
     <property name="eachLine" value="true"/>
     </module>
    ​
     <!--每行不超过120字-->
     <module name="LineLength">
     <property name="fileExtensions" value="java"/>
     <property name="max" value="120"/>
     <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
     </module>
    ​
     <module name="TreeWalker">
     <module name="OuterTypeFilename"/>
     <module name="IllegalTokenText">
     <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
     <property name="format"
     value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
     <property name="message"
     value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
     </module>
     <module name="AvoidEscapedUnicodeCharacters">
     <property name="allowEscapesForControlCharacters" value="true"/>
     <property name="allowByTailComment" value="true"/>
     <property name="allowNonPrintableEscapes" value="true"/>
     </module>
     <module name="AvoidStarImport"/>
     <module name="RedundantImport"/>
     <module name="UnusedImports"/>
     <module name="OneTopLevelClass"/>
     <module name="NoLineWrap">
     <property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT"/>
     </module>
     <module name="EmptyBlock">
     <property name="option" value="TEXT"/>
     <property name="tokens"
     value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
     </module>
     <module name="NeedBraces">
     <property name="tokens"
     value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
     </module>
     <!--<module name="LeftCurly">
     <property name="tokens"
     value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
     INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
     LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
     LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
     OBJBLOCK, STATIC_INIT"/>
     </module>-->
     <module name="RightCurly">
     <property name="id" value="RightCurlySame"/>
     <property name="tokens"
     value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
     LITERAL_DO"/>
     </module>
     <!--<module name="RightCurly">
     <property name="id" value="RightCurlyAlone"/>
     <property name="option" value="alone"/>
     <property name="tokens"
     value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
     INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF"/>
     </module>-->
     <module name="SuppressionXpathSingleFilter">
     <!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
     <property name="id" value="RightCurlyAlone"/>
     <property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
     or preceding-sibling::*[last()][self::LCURLY]]"/>
     </module>
     <module name="WhitespaceAfter">
     <property name="tokens"
     value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
     LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
     </module>
     <module name="WhitespaceAround">
     <property name="allowEmptyConstructors" value="true"/>
     <property name="allowEmptyLambdas" value="true"/>
     <property name="allowEmptyMethods" value="true"/>
     <property name="allowEmptyTypes" value="true"/>
     <property name="allowEmptyLoops" value="true"/>
     <property name="tokens"
     value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
     BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
     LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
     LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
     LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
     NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
     SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
     <message key="ws.notFollowed"
     value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
     <message key="ws.notPreceded"
     value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
     </module>
     <module name="OneStatementPerLine"/>
     <module name="MultipleVariableDeclarations"/>
     <module name="ArrayTypeStyle"/>
     <module name="MissingSwitchDefault"/>
     <module name="FallThrough"/>
     <module name="UpperEll"/>
     <module name="ModifierOrder"/>
     <!-- <module name="EmptyLineSeparator">
     <property name="tokens"
     value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
     STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
     <property name="allowNoEmptyLineBetweenFields" value="true"/>
     </module>-->
     <module name="SeparatorWrap">
     <property name="id" value="SeparatorWrapDot"/>
     <property name="tokens" value="DOT"/>
     <property name="option" value="nl"/>
     </module>
     <module name="SeparatorWrap">
     <property name="id" value="SeparatorWrapComma"/>
     <property name="tokens" value="COMMA"/>
     <property name="option" value="EOL"/>
     </module>
     <module name="SeparatorWrap">
     <!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
     <property name="id" value="SeparatorWrapEllipsis"/>
     <property name="tokens" value="ELLIPSIS"/>
     <property name="option" value="EOL"/>
     </module>
     <module name="SeparatorWrap">
     <!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
     <property name="id" value="SeparatorWrapArrayDeclarator"/>
     <property name="tokens" value="ARRAY_DECLARATOR"/>
     <property name="option" value="EOL"/>
     </module>
     <module name="SeparatorWrap">
     <property name="id" value="SeparatorWrapMethodRef"/>
     <property name="tokens" value="METHOD_REF"/>
     <property name="option" value="nl"/>
     </module>
     <module name="PackageName">
     <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
     <message key="name.invalidPattern"
     value="Package name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <!--类名-->
     <module name="TypeName">
     <property name="format" value="(^[A-Z][a-zA-Z0-9]*$)"/>
     </module>
     <module name="MemberName">
     <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
     <message key="name.invalidPattern"
     value="Member name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="ParameterName">
     <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
     <message key="name.invalidPattern"
     value="Parameter name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="LambdaParameterName">
     <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
     <message key="name.invalidPattern"
     value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="CatchParameterName">
     <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
     <message key="name.invalidPattern"
     value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="LocalVariableName">
     <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
     <message key="name.invalidPattern"
     value="Local variable name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="ClassTypeParameterName">
     <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
     <message key="name.invalidPattern"
     value="Class type name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="MethodTypeParameterName">
     <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
     <message key="name.invalidPattern"
     value="Method type name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="InterfaceTypeParameterName">
     <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
     <message key="name.invalidPattern"
     value="Interface type name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <module name="NoFinalizer"/>
     <module name="GenericWhitespace">
     <message key="ws.followed"
     value="GenericWhitespace ''{0}'' is followed by whitespace."/>
     <message key="ws.preceded"
     value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
     <message key="ws.illegalFollow"
     value="GenericWhitespace ''{0}'' should followed by whitespace."/>
     <message key="ws.notPreceded"
     value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
     </module>
     <!--代码缩进-->
     <module name="Indentation">
     <property name="basicOffset" value="4"/>
     <property name="braceAdjustment" value="0"/>
     <property name="caseIndent" value="2"/>
     <property name="throwsIndent" value="2"/>
     <property name="lineWrappingIndentation" value="8"/>
     <property name="arrayInitIndent" value="2"/>
     </module>
     <module name="AbbreviationAsWordInName">
     <property name="ignoreFinal" value="false"/>
     <property name="allowedAbbreviationLength" value="1"/>
     </module>
     <module name="OverloadMethodsDeclarationOrder"/>
     <module name="VariableDeclarationUsageDistance"/>
     <module name="CustomImportOrder">
     <property name="sortImportsInGroupAlphabetically" value="true"/>
     <property name="separateLineBetweenGroups" value="true"/>
     <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
     <property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
     </module>
     <module name="MethodParamPad">
     <property name="tokens"
     value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
     SUPER_CTOR_CALL, ENUM_CONSTANT_DEF"/>
     </module>
     <module name="NoWhitespaceBefore">
     <property name="tokens"
     value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
     LABELED_STAT, METHOD_REF"/>
     <property name="allowLineBreaks" value="true"/>
     </module>
     <module name="ParenPad">
     <property name="tokens"
     value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
     EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
     LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
     METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
     </module>
     <module name="OperatorWrap">
     <property name="option" value="NL"/>
     <property name="tokens"
     value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
     LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
     </module>
     <!-- <module name="AnnotationLocation">
     <property name="id" value="AnnotationLocationMostCases"/>
     <property name="tokens"
     value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
     </module>-->
     <module name="AnnotationLocation">
     <property name="id" value="AnnotationLocationVariables"/>
     <property name="tokens" value="VARIABLE_DEF"/>
     <property name="allowSamelineMultipleAnnotations" value="true"/>
     </module>
     <module name="NonEmptyAtclauseDescription"/>
     <module name="InvalidJavadocPosition"/>
     <module name="JavadocTagContinuationIndentation"/>
     <!--<module name="SummaryJavadoc">
     <property name="forbiddenSummaryFragments"
     value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
     </module>-->
     <module name="JavadocParagraph"/>
     <!-- <module name="AtclauseOrder">
     <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
     <property name="target"
     value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
     </module>-->
     <module name="JavadocType">
     <property name="allowUnknownTags" value="true"/>
     <message key="javadoc.missing" value="类注释:缺少Javadoc注释"/>
     </module>
     <module name="JavadocMethod">
     <property name="scope" value="public"/>
     <property name="allowMissingParamTags" value="false"/>
     <property name="allowMissingReturnTag" value="false"/>
     <property name="allowedAnnotations" value="Override, Test"/>
     <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
     </module>
     <module name="MissingJavadocMethod">
     <property name="scope" value="public"/>
     <property name="minLineCount" value="2"/>
     <property name="allowedAnnotations" value="Override, Test"/>
     <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
     </module>
     <module name="MethodName">
     <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
     <message key="name.invalidPattern"
     value="Method name ''{0}'' must match pattern ''{1}''."/>
     </module>
     <!--忽略行内的标签-->
     <!-- <module name="SingleLineJavadoc">
     <property name="ignoreInlineTags" value="true"/>
     </module>-->
     <module name="EmptyCatchBlock">
     <property name="exceptionVariableName" value="expected"/>
     </module>
     <module name="CommentsIndentation">
     <property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN"/>
     </module>
     <!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
     <module name="SuppressionXpathFilter">
     <property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
     default="checkstyle-xpath-suppressions.xml" />
     <property name="optional" value="true"/>
     </module>
     </module>
    </module>
    
    • 加入CheckStyle.xml

      image-20200615181710608.png
    image-20200615182417378.png image-20200615182529011.png

    扫描一下试试,看看当前代码有哪些问题

    image-20200615182739875.png

    后续:其实我们只做到了本地代码的检查,没有强制的约束。其实应该配合sonarqube+jenkins自动检查,sonarqube是可以导入checkstyle.xml来进行代码检查的,所以只需要我们把本次的checkstyle.xml导入即可。只有通过自动检查的才可以提交编译(这个是个好的思路,希望大家可以一起探讨)。

    相关文章

      网友评论

          本文标题:IDEA统一CodeStyle

          本文链接:https://www.haomeiwen.com/subject/hlwsjctx.html