วิธีการปิดการใช้งานกฎการตรวจสอบเฉพาะสำหรับบรรทัดของรหัสโดยเฉพาะ?


183

ฉันมีกฎการตรวจสอบcheckstyle ที่กำหนดค่าในโครงการของฉันซึ่งห้ามไม่ให้กำหนดวิธีการเรียนที่มีพารามิเตอร์อินพุตมากกว่า 3 ตัว กฎใช้งานได้ดีสำหรับชั้นเรียนของฉันแต่บางครั้งฉันต้องขยายชั้นเรียนของบุคคลที่สามซึ่งไม่ปฏิบัติตามกฎข้อนี้โดยเฉพาะ

มีความเป็นไปได้ไหมที่จะแนะนำ "checkstyle" ว่าวิธีการบางอย่างควรถูกเพิกเฉยหรือไม่?

BTW ฉันลงเอยด้วยเสื้อคลุมสไตล์ของตัวเอง: qulice.com (ดูการควบคุมคุณภาพของโค้ด Java อย่างเข้มงวด )

คำตอบ:


291

ตรวจสอบการใช้งานของ supressionCommentFilter ที่http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter คุณจะต้องเพิ่มโมดูลลงใน checkstyle.xml ของคุณ

<module name="SuppressionCommentFilter"/>

และมันสามารถกำหนดค่าได้ ดังนั้นคุณสามารถเพิ่มความคิดเห็นไปยังรหัสของคุณเพื่อปิดการตรวจสอบ (ในระดับต่าง ๆ ) แล้วเปิดใหม่อีกครั้งผ่านการใช้ความคิดเห็นในรหัสของคุณ เช่น

//CHECKSTYLE:OFF
public void someMethod(String arg1, String arg2, String arg3, String arg4) {
//CHECKSTYLE:ON

หรือดียิ่งขึ้นให้ใช้เวอร์ชันที่ปรับแต่งเพิ่มเติมนี้:

<module name="SuppressionCommentFilter">
    <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
    <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
    <property name="checkFormat" value="$1"/>
</module>

ซึ่งช่วยให้คุณปิดการตรวจสอบเฉพาะสำหรับบรรทัดของรหัสเฉพาะ:

//CHECKSTYLE.OFF: IllegalCatch - Much more readable than catching 7 exceptions
catch (Exception e)
//CHECKSTYLE.ON: IllegalCatch

* หมายเหตุ: คุณจะต้องเพิ่มFileContentsHolder:

<module name="FileContentsHolder"/>

ดูสิ่งนี้ด้วย

<module name="SuppressionFilter">
    <property name="file" value="docs/suppressions.xml"/>
</module>

ใต้SuppressionFilterส่วนในหน้าเดียวกันนั้นซึ่งช่วยให้คุณปิดการตรวจสอบแต่ละรายการสำหรับทรัพยากรที่จับคู่รูปแบบ

ดังนั้นถ้าคุณมีใน checkstyle.xml ของคุณ:

<module name="ParameterNumber">
   <property name="id" value="maxParameterNumber"/>
   <property name="max" value="3"/>
   <property name="tokens" value="METHOD_DEF"/>
</module>

คุณสามารถปิดได้ในไฟล์ปราบปราม xml ด้วย:

<suppress id="maxParameterNumber" files="YourCode.java"/>

อีกวิธีหนึ่งที่มีให้ใน Checkstyle 5.7 คือการระงับการละเมิดผ่าน@SuppressWarningsหมายเหตุประกอบ java ในการทำเช่นนี้คุณจะต้องเพิ่มสองโมดูลใหม่ ( SuppressWarningsFilterและSuppressWarningsHolder) ในไฟล์กำหนดค่าของคุณ:

<module name="Checker">
   ...
   <module name="SuppressWarningsFilter" />
   <module name="TreeWalker">
       ...
       <module name="SuppressWarningsHolder" />
   </module>
</module> 

จากนั้นในรหัสของคุณคุณสามารถทำสิ่งต่อไปนี้:

@SuppressWarnings("checkstyle:methodlength")
public void someLongMethod() throws Exception {

หรือสำหรับการระงับหลายรายการ:

@SuppressWarnings({"checkstyle:executablestatementcount", "checkstyle:methodlength"})
public void someLongMethod() throws Exception {

หมายเหตุ: "การcheckstyle:" คำนำหน้าเป็นตัวเลือก ( แต่แนะนำ) ตามเอกสารชื่อพารามิเตอร์จะต้องอยู่ในตัวพิมพ์เล็กทั้งหมด แต่การปฏิบัติระบุว่ากรณีใด ๆ ทำงานได้


7
อย่าลืมเพิ่ม FileContentsHolder บน TreeWalter ดูstackoverflow.com/a/5764666/480483
djjeck

2
ถ้าคุณใช้//CHECKSTYLE.OFF: แล้วลืมเปิดอีกครั้งมันจะยังคงถูกเช็กเอาต์ในไฟล์ที่มี//CHECKSTYLE.OFF: หรือไฟล์ที่ถูกประมวลผลในภายหลังทั้งหมดด้วยหรือไม่
Roland

1
@Roland มันยังคงปิดเพียงช่วงระยะเวลาของการทดสอบชั้นที่
Chris Knight

1
"ชื่อพารามิเตอร์จะต้องเป็นตัวพิมพ์เล็กทั้งหมด" @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance")ทำงานได้ดีสำหรับฉันในฐานะตัวพิมพ์เล็ก
Anders Rabo Thorbeck

2
ตั้งแต่Checkstyle 8.1 SuppressionCommentFilterควรอยู่ภายใต้TreeWalkerและFileContentHolderไม่จำเป็นต้องมี (มี) อีกต่อไป
avandeursen

70

หากคุณต้องการใช้คำอธิบายประกอบเพื่อเลือกกฎเงียบ ๆ ตอนนี้คุณสามารถใช้@SuppressWarningsคำอธิบายประกอบได้โดยเริ่มจาก Checkstyle 5.7 (และสนับสนุนโดย Checkstyle Maven Plugin 2.12+)

ก่อนอื่นให้checkstyle.xmlเพิ่มSuppressWarningsHolderโมดูลในTreeWalker:

<module name="TreeWalker">
    <!-- Make the @SuppressWarnings annotations available to Checkstyle -->
    <module name="SuppressWarningsHolder" />
</module>

ถัดไปเปิดใช้งานที่SuppressWarningsFilterนั่น (เป็นพี่น้องTreeWalker):

<!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />

<module name="TreeWalker">
...

ตอนนี้คุณสามารถใส่คำอธิบายประกอบเช่นวิธีการที่คุณต้องการแยกออกจากกฎ Checkstyle บางอย่าง:

@SuppressWarnings("checkstyle:methodlength")
@Override
public boolean equals(Object obj) {
    // very long auto-generated equals() method
}

checkstyle:คำนำหน้าในการโต้เถียงที่จะ@SuppressWarningsเป็นตัวเลือก แต่ผมชอบมันเป็นคำเตือนที่เตือนนี้มาจาก ชื่อกฎต้องเป็นตัวพิมพ์เล็ก

สุดท้ายถ้าคุณใช้ Eclipse มันจะบ่นเกี่ยวกับข้อโต้แย้งที่ไม่เป็นที่รู้จัก:

@SuppressWarnings ไม่รองรับ ("checkstyle: methodlength")

คุณสามารถปิดใช้งานคำเตือน Eclipse นี้ในการตั้งค่าหากคุณต้องการ:

Preferences:
  Java
  --> Compiler
  --> Errors/Warnings
  --> Annotations
  --> Unhandled token in '@SuppressWarnings': set to 'Ignore'

2
ฉันเสนอชื่อนี้เป็นคำตอบที่ตรวจสอบเนื่องจากฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่ควรจะทำงานได้ดีที่สุดในกรณีส่วนใหญ่
avandeursen

33

สิ่งที่ใช้งานได้ดีคือSuppressWithNearbyCommentFilterซึ่งใช้ความคิดเห็นของแต่ละบุคคลเพื่อระงับเหตุการณ์การตรวจสอบ

ตัวอย่างเช่น

// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
public void onClick(View view) { ... }

ในการกำหนดค่าตัวกรองเพื่อให้ CHECKSTYLE IGNORE ตรวจสอบว่ามี NEXT var LINES อยู่หรือไม่หลีกเลี่ยงการทริกเกอร์การตรวจสอบใด ๆ สำหรับการตรวจสอบที่กำหนดสำหรับบรรทัดปัจจุบันและบรรทัด var ถัดไป (สำหรับจำนวน var + 1 ทั้งหมด):

<module name="SuppressWithNearbyCommentFilter">
    <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
    <property name="checkFormat" value="$1"/>
    <property name="influenceFormat" value="$2"/>
</module>

http://checkstyle.sourceforge.net/config.html


ฉันจะเปลี่ยน regex CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES?ซึ่งจะทำให้คำสั่งเพิกเฉยอ่านง่ายขึ้น (คุณจะสามารถใช้ "ตรวจสอบจุดตรวจสอบ IGNORE สำหรับบรรทัดต่อไป 1 บรรทัด" และ "ตรวจสอบจุดตรวจสอบจุดบกพร่องต่อไปอีก 1 บรรทัด")
Matt3o12

@ matt3o12 CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINEใช้ได้กับฉันด้วย (มันตรงกับทั้งคู่lineและlines)
Slava Semushin

3

ทุกคำตอบที่อ้างถึงSuppressWarningsFilterไม่มีรายละเอียดที่สำคัญ คุณสามารถใช้รหัสตัวพิมพ์เล็กทั้งหมดได้เท่านั้นหากมันถูกกำหนดไว้ใน checkstyle-config.xml ของคุณ หากไม่ใช่คุณต้องใช้ชื่อโมดูลดั้งเดิม

ตัวอย่างเช่นถ้าใน checkstyle-config.xml ฉันมี:

<module name="NoWhitespaceBefore"/>

ฉันไม่สามารถใช้:

@SuppressWarnings({"nowhitespacebefore"})

อย่างไรก็ตามฉันต้องใช้:

@SuppressWarnings({"NoWhitespaceBefore"})

เพื่อให้ไวยากรณ์แรกทำงาน, checkstyle-config.xml ควรมี:

<module name="NoWhitespaceBefore">
  <property name="id" value="nowhitespacebefore"/>
</module>

นี่คือสิ่งที่ใช้ได้ผลกับฉันอย่างน้อยใน CheckStyle เวอร์ชั่น 6.17


1

ฉันมีปัญหากับคำตอบข้างต้นอาจเป็นเพราะฉันตั้งคำเตือน checkStyle ให้เป็นข้อผิดพลาด สิ่งที่ได้ผลคือ SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

ข้อเสียของสิ่งนี้คือช่วงของสายจะถูกเก็บไว้ในไฟล์ suppresssions.xml แยกต่างหากดังนั้นผู้พัฒนาที่ไม่คุ้นเคยอาจไม่ทำการเชื่อมต่อทันที


ขอบคุณมันเป็นสิ่งเดียวที่ทำงานให้ฉันด้วย
jonathanrz

1
<module name="Checker">
    <module name="SuppressionCommentFilter"/>
    <module name="TreeWalker">
        <module name="FileContentsHolder"/>
    </module>
</module>

ในการกำหนดค่าตัวกรองเพื่อระงับเหตุการณ์การตรวจสอบระหว่างความคิดเห็นที่มีบรรทัด BEGIN GENERATED CODE และความคิดเห็นที่มีบรรทัด END GENERATED CODE:

<module name="SuppressionCommentFilter">
  <property name="offCommentFormat" value="BEGIN GENERATED CODE"/>
  <property name="onCommentFormat" value="END GENERATED CODE"/>
</module>

//BEGIN GENERATED CODE
@Override
public boolean equals(Object obj) { ... } // No violation events will be reported

@Override
public int hashCode() { ... } // No violation events will be reported
//END GENERATED CODE

ดูเพิ่มเติม


0

คุณสามารถลอง https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathFilter

สร้างการระงับ Xpath โดยใช้ CLI พร้อมกับตัวเลือก -g และระบุเอาต์พุตโดยใช้สวิตช์ -o

https://checkstyle.sourceforge.io/cmdline.html#Command_line_usage

ต่อไปนี้เป็นตัวอย่างข้อมูลย่อยที่จะช่วยให้คุณตั้งค่าการระงับการตรวจสอบการสร้างอัตโนมัติ:


<target name="checkstyleg">
    <move file="suppressions-xpath.xml"
      tofile="suppressions-xpath.xml.bak"
      preservelastmodified="true"
      force="true"
      failonerror="false"
      verbose="true"/>
    <fileset dir="${basedir}"
                    id="javasrcs">
    <include name="**/*.java" />
    </fileset>
    <pathconvert property="sources"
                            refid="javasrcs"
                            pathsep=" " />
    <loadfile property="cs.cp"
                        srcFile="../${cs.classpath.file}" />
    <java classname="${cs.main.class}"
                logError="true">
    <arg line="-c ../${cs.config} -p ${cs.properties} -o ${ant.project.name}-xpath.xml -g ${sources}" />
    <classpath>
        <pathelement path="${cs.cp}" />
        <pathelement path="${java.class.path}" />
    </classpath>
</java>
<condition property="file.is.empty" else="false">
     <length file="${ant.project.name}-xpath.xml" when="equal" length="0" />
   </condition>
   <if>
     <equals arg1="${file.is.empty}" arg2="false"/>
     <then>
     <move file="${ant.project.name}-xpath.xml"
      tofile="suppressions-xpath.xml"
      preservelastmodified="true"
      force="true"
      failonerror="true"
  verbose="true"/>
   </then>
</if>
    </target>

suppressions-xpath.xml ถูกระบุเป็นแหล่งระงับ Xpath ในการกำหนดค่ากฎ Checkstyle ในตัวอย่างด้านบนฉันกำลังโหลด Checkpath classpath จากไฟล์ cs.cp ไปยังคุณสมบัติ คุณสามารถเลือกระบุ classpath ได้โดยตรง

หรือคุณสามารถใช้ groovy ภายใน Maven (หรือ Ant) เพื่อทำสิ่งเดียวกัน:


import java.nio.file.Files
import java.nio.file.StandardCopyOption  
import java.nio.file.Paths

def backupSuppressions() {
  def supprFileName = 
      project.properties["checkstyle.suppressionsFile"]
  def suppr = Paths.get(supprFileName)
  def target = null
  if (Files.exists(suppr)) {
    def supprBak = Paths.get(supprFileName + ".bak")
    target = Files.move(suppr, supprBak,
        StandardCopyOption.REPLACE_EXISTING)
    println "Backed up " + supprFileName
  }
  return target
}

def renameSuppressions() {
  def supprFileName = 
      project.properties["checkstyle.suppressionsFile"]
  def suppr = Paths.get(project.name + "-xpath.xml")
  def target = null
  if (Files.exists(suppr)) {
    def supprNew = Paths.get(supprFileName)
    target = Files.move(suppr, supprNew)
    println "Renamed " + suppr + " to " + supprFileName
  }
  return target
}

def getClassPath(classLoader, sb) {
  classLoader.getURLs().each {url->
     sb.append("${url.getFile().toString()}:")
  }
  if (classLoader.parent) {
     getClassPath(classLoader.parent, sb)
  }
  return sb.toString()
}

backupSuppressions()

def cp = getClassPath(this.class.classLoader, 
    new StringBuilder())
def csMainClass = 
      project.properties["cs.main.class"]
def csRules = 
      project.properties["checkstyle.rules"]
def csProps = 
      project.properties["checkstyle.properties"]

String[] args = ["java", "-cp", cp,
    csMainClass,
    "-c", csRules,
"-p", csProps,
"-o", project.name + "-xpath.xml",
"-g", "src"]

ProcessBuilder pb = new ProcessBuilder(args)
pb = pb.inheritIO()
Process proc = pb.start()
proc.waitFor()

renameSuppressions()

ข้อเสียเปรียบเพียงข้อเดียวที่ใช้การระงับ Xpath นอกเหนือจากการตรวจสอบที่ไม่รองรับคือหากคุณมีรหัสดังนี้:

package cstests;

@SuppressWarnings("PMD")
public interface TestMagicNumber {
  static byte[] getAsciiRotator() {
    byte[] rotation = new byte[95 * 2];
    for (byte i = ' '; i <= '~'; i++) {
      rotation[i - ' '] = i;
      rotation[i + 95 - ' '] = i;
    }
    return rotation;
  }
}

การปราบปราม Xpath ที่สร้างในกรณีนี้ไม่ได้รับการตรวจสอบโดย Checkstyle และตัวตรวจสอบล้มเหลวโดยมีข้อยกเว้น:

<suppress-xpath
       files="TestMagicNumber.java"
       checks="MagicNumberCheck"
       query="/INTERFACE_DEF[./IDENT[@text='TestMagicNumber']]/OBJBLOCK/METHOD_DEF[./IDENT[@text='getAsciiRotator']]/SLIST/VARIABLE_DEF[./IDENT[@text='rotation']]/ASSIGN/EXPR/LITERAL_NEW/ARRAY_DECLARATOR/EXPR/STAR/NUM_INT[@text='95']"/>
<suppress-xpath
       files="TestMagicNumber.java"
       checks="MagicNumberCheck"
       query="/INTERFACE_DEF[./IDENT[@text='TestMagicNumber']]/OBJBLOCK/METHOD_DEF[./IDENT[@text='getAsciiRotator']]/SLIST/LITERAL_FOR/SLIST/EXPR/ASSIGN[./IDENT[@text='i']]/INDEX_OP[./IDENT[@text='rotation']]/EXPR/MINUS[./CHAR_LITERAL[@text='' '']]/PLUS[./IDENT[@text='i']]/NUM_INT[@text='95']"/>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.