1 package com.puppycrawl.tools.checkstyle.filters; 20 21 import java.lang.ref.WeakReference ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 import java.util.regex.Matcher ; 29 import java.util.regex.Pattern ; 30 import java.util.regex.PatternSyntaxException ; 31 32 import org.apache.commons.beanutils.ConversionException; 33 34 import com.puppycrawl.tools.checkstyle.api.AuditEvent; 35 import com.puppycrawl.tools.checkstyle.api.AutomaticBean; 36 import com.puppycrawl.tools.checkstyle.api.FileContents; 37 import com.puppycrawl.tools.checkstyle.api.Filter; 38 import com.puppycrawl.tools.checkstyle.api.TextBlock; 39 import com.puppycrawl.tools.checkstyle.api.Utils; 40 import com.puppycrawl.tools.checkstyle.checks.FileContentsHolder; 41 42 43 66 public class SuppressionCommentFilter 67 extends AutomaticBean 68 implements Filter 69 { 70 75 public class Tag 76 implements Comparable 77 { 78 79 private String mText; 80 81 82 private int mLine; 83 84 85 private int mColumn; 86 87 88 private boolean mOn; 89 90 91 private Pattern mTagCheckRegexp; 92 93 94 private Pattern mTagMessageRegexp; 95 96 105 public Tag(int aLine, int aColumn, String aText, boolean aOn) 106 throws ConversionException 107 { 108 mLine = aLine; 109 mColumn = aColumn; 110 mText = aText; 111 mOn = aOn; 112 113 mTagCheckRegexp = mCheckRegexp; 114 String format = ""; 117 try { 118 if (aOn) { 119 format = 120 expandFromComment(aText, mCheckFormat, mOnRegexp); 121 mTagCheckRegexp = Pattern.compile(format); 122 if (mMessageFormat != null) { 123 format = 124 expandFromComment(aText, mMessageFormat, mOnRegexp); 125 mTagMessageRegexp = Pattern.compile(format); 126 } 127 } 128 else { 129 format = 130 expandFromComment(aText, mCheckFormat, mOffRegexp); 131 mTagCheckRegexp = Pattern.compile(format); 132 if (mMessageFormat != null) { 133 format = 134 expandFromComment( 135 aText, 136 mMessageFormat, 137 mOffRegexp); 138 mTagMessageRegexp = Pattern.compile(format); 139 } 140 } 141 } 142 catch (final PatternSyntaxException e) { 143 throw new ConversionException( 144 "unable to parse expanded comment " + format, 145 e); 146 } 147 } 148 149 150 public String getText() 151 { 152 return mText; 153 } 154 155 156 public int getLine() 157 { 158 return mLine; 159 } 160 161 167 public int getColumn() 168 { 169 return mColumn; 170 } 171 172 177 public boolean isOn() 178 { 179 return mOn; 180 } 181 182 191 public int compareTo(Object aObject) 192 { 193 final Tag other = (Tag) aObject; 194 if (mLine == other.mLine) { 195 return mColumn - other.mColumn; 196 } 197 198 return (mLine - other.mLine); 199 } 200 201 207 public boolean isMatch(AuditEvent aEvent) 208 { 209 final Matcher tagMatcher = 210 mTagCheckRegexp.matcher(aEvent.getSourceName()); 211 if (tagMatcher.find()) { 212 return true; 213 } 214 if (mTagMessageRegexp != null) { 215 final Matcher messageMatcher = 216 mTagMessageRegexp.matcher(aEvent.getMessage()); 217 return messageMatcher.find(); 218 } 219 return false; 220 } 221 222 229 private String expandFromComment( 230 String aComment, 231 String aString, 232 Pattern aRegexp) 233 { 234 final Matcher matcher = aRegexp.matcher(aComment); 235 if (!matcher.find()) { 237 return aString; 239 } 241 String result = aString; 242 for (int i = 0; i <= matcher.groupCount(); i++) { 243 result = result.replaceAll("\\$" + i, matcher.group(i)); 245 } 246 return result; 247 } 248 249 250 public final String toString() 251 { 252 return "Tag[line=" + getLine() + "; col=" + getColumn() 253 + "; on=" + isOn() + "; text='" + getText() + "']"; 254 } 255 } 256 257 258 private static final String DEFAULT_OFF_FORMAT = "CHECKSTYLE\\:OFF"; 259 260 261 private static final String DEFAULT_ON_FORMAT = "CHECKSTYLE\\:ON"; 262 263 264 private static final String DEFAULT_CHECK_FORMAT = ".*"; 265 266 267 private boolean mCheckC = true; 268 269 270 private boolean mCheckCPP = true; 271 272 273 private Pattern mOffRegexp; 274 275 276 private Pattern mOnRegexp; 277 278 279 private String mCheckFormat; 280 281 282 private Pattern mCheckRegexp; 283 284 285 private String mMessageFormat; 286 287 289 private final List mTags = new ArrayList (); 290 291 298 private WeakReference mFileContentsReference = new WeakReference (null); 299 300 305 public SuppressionCommentFilter() 306 { 307 setOnCommentFormat(DEFAULT_ON_FORMAT); 308 setOffCommentFormat(DEFAULT_OFF_FORMAT); 309 setCheckFormat(DEFAULT_CHECK_FORMAT); 310 } 311 312 317 public void setOffCommentFormat(String aFormat) 318 throws ConversionException 319 { 320 try { 321 mOffRegexp = Utils.getPattern(aFormat); 322 } 323 catch (final PatternSyntaxException e) { 324 throw new ConversionException("unable to parse " + aFormat, e); 325 } 326 } 327 328 333 public void setOnCommentFormat(String aFormat) 334 throws ConversionException 335 { 336 try { 337 mOnRegexp = Utils.getPattern(aFormat); 338 } 339 catch (final PatternSyntaxException e) { 340 throw new ConversionException("unable to parse " + aFormat, e); 341 } 342 } 343 344 345 public FileContents getFileContents() 346 { 347 return (FileContents) mFileContentsReference.get(); 348 } 349 350 354 public void setFileContents(FileContents aFileContents) 355 { 356 mFileContentsReference = new WeakReference (aFileContents); 357 } 358 359 364 public void setCheckFormat(String aFormat) 365 throws ConversionException 366 { 367 try { 368 mCheckRegexp = Utils.getPattern(aFormat); 369 mCheckFormat = aFormat; 370 } 371 catch (final PatternSyntaxException e) { 372 throw new ConversionException("unable to parse " + aFormat, e); 373 } 374 } 375 376 381 public void setMessageFormat(String aFormat) 382 throws ConversionException 383 { 384 try { 386 Utils.getPattern(aFormat); 387 } 388 catch (final PatternSyntaxException e) { 389 throw new ConversionException("unable to parse " + aFormat, e); 390 } 391 mMessageFormat = aFormat; 392 } 393 394 395 399 public void setCheckCPP(boolean aCheckCPP) 400 { 401 mCheckCPP = aCheckCPP; 402 } 403 404 408 public void setCheckC(boolean aCheckC) 409 { 410 mCheckC = aCheckC; 411 } 412 413 414 public boolean accept(AuditEvent aEvent) 415 { 416 if (aEvent.getLocalizedMessage() == null) { 417 return true; } 419 420 final FileContents currentContents = FileContentsHolder.getContents(); 423 if (currentContents == null) { 424 return true; 427 } 428 if (getFileContents() != currentContents) { 429 setFileContents(currentContents); 430 tagSuppressions(); 431 } 432 final Tag matchTag = findNearestMatch(aEvent); 433 if ((matchTag != null) && !matchTag.isOn()) { 434 return false; 435 } 436 return true; 437 } 438 439 445 private Tag findNearestMatch(AuditEvent aEvent) 446 { 447 Tag result = null; 448 for (final Iterator iter = mTags.iterator(); iter.hasNext();) { 451 final Tag tag = (Tag) iter.next(); 452 if ((tag.getLine() > aEvent.getLine()) 453 || ((tag.getLine() == aEvent.getLine()) 454 && (tag.getColumn() > aEvent.getColumn()))) 455 { 456 break; 457 } 458 if (tag.isMatch(aEvent)) { 459 result = tag; 460 } 461 }; 462 return result; 463 } 464 465 469 private void tagSuppressions() 470 { 471 mTags.clear(); 472 final FileContents contents = getFileContents(); 473 if (mCheckCPP) { 474 tagSuppressions(contents.getCppComments().values()); 475 } 476 if (mCheckC) { 477 final Collection cComments = contents.getCComments().values(); 478 final Iterator iter = cComments.iterator(); 479 while (iter.hasNext()) { 480 final Collection element = (Collection ) iter.next(); 481 tagSuppressions(element); 482 } 483 } 484 Collections.sort(mTags); 485 } 486 487 492 private void tagSuppressions(Collection aComments) 493 { 494 for (final Iterator iter = aComments.iterator(); iter.hasNext();) { 495 final TextBlock comment = (TextBlock) iter.next(); 496 final int startLineNo = comment.getStartLineNo(); 497 final String [] text = comment.getText(); 498 tagCommentLine(text[0], startLineNo, comment.getStartColNo()); 499 for (int i = 1; i < text.length; i++) { 500 tagCommentLine(text[i], startLineNo + i, 0); 501 } 502 } 503 } 504 505 512 private void tagCommentLine(String aText, int aLine, int aColumn) 513 { 514 final Matcher offMatcher = mOffRegexp.matcher(aText); 515 if (offMatcher.find()) { 516 addTag(offMatcher.group(0), aLine, aColumn, false); 517 } 518 else { 519 final Matcher onMatcher = mOnRegexp.matcher(aText); 520 if (onMatcher.find()) { 521 addTag(onMatcher.group(0), aLine, aColumn, true); 522 } 523 } 524 } 525 526 533 private void addTag(String aText, int aLine, int aColumn, boolean aOn) 534 { 535 final Tag tag = new Tag(aLine, aColumn, aText, aOn); 536 mTags.add(tag); 537 } 538 } 539 | Popular Tags |