1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-26 00:32:41 +01:00

Add a linter rule for detecting empty files

Summary: Adds two different linter rules (one general purpose and another PHP specific) to prevent empty files from being added to a repository. For some unknown reason, people seem to like to do this.

Test Plan: Added test cases.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: avivey, cburroughs, Korvin

Differential Revision: https://secure.phabricator.com/D13881
This commit is contained in:
Joshua Spence 2015-09-01 19:20:11 +10:00
parent a5304e472d
commit 6fa2de5ff8
8 changed files with 83 additions and 0 deletions

View file

@ -90,6 +90,7 @@ phutil_register_library_map(array(
'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDuplicateSwitchCaseXHPASTLinterRule.php',
'ArcanistDynamicDefineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php',
'ArcanistElseIfUsageXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php',
'ArcanistEmptyFileXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php',
'ArcanistEmptyStatementXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyStatementXHPASTLinterRule.php',
'ArcanistEventType' => 'events/constant/ArcanistEventType.php',
'ArcanistExitExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php',
@ -375,6 +376,7 @@ phutil_register_library_map(array(
'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistDynamicDefineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistElseIfUsageXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistEmptyFileXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistEmptyStatementXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistEventType' => 'PhutilEventType',
'ArcanistExitExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',

View file

@ -13,6 +13,7 @@ final class ArcanistTextLinter extends ArcanistLinter {
const LINT_TRAILING_WHITESPACE = 6;
const LINT_BOF_WHITESPACE = 8;
const LINT_EOF_WHITESPACE = 9;
const LINT_EMPTY_FILE = 10;
private $maxLineLength = 80;
@ -85,16 +86,23 @@ final class ArcanistTextLinter extends ArcanistLinter {
self::LINT_TRAILING_WHITESPACE => pht('Trailing Whitespace'),
self::LINT_BOF_WHITESPACE => pht('Leading Whitespace at BOF'),
self::LINT_EOF_WHITESPACE => pht('Trailing Whitespace at EOF'),
self::LINT_EMPTY_FILE => pht('Empty File'),
);
}
public function lintPath($path) {
$this->lintEmptyFile($path);
if (!strlen($this->getData($path))) {
// If the file is empty, don't bother; particularly, don't require
// the user to add a newline.
return;
}
if ($this->didStopAllLinters()) {
return;
}
$this->lintNewlines($path);
$this->lintTabs($path);
@ -116,6 +124,29 @@ final class ArcanistTextLinter extends ArcanistLinter {
$this->lintEOFWhitespace($path);
}
protected function lintEmptyFile($path) {
$data = $this->getData($path);
// It is reasonable for certain file types to be completely empty,
// so they are excluded here.
switch ($filename = basename($this->getActivePath())) {
case '__init__.py':
return;
default:
if (strlen($filename) && $filename[0] == '.') {
return;
}
}
if (preg_match('/^\s*$/', $data)) {
$this->raiseLintAtPath(
self::LINT_EMPTY_FILE,
pht("Empty files usually don't serve any useful purpose."));
$this->stopAllLinters();
}
}
protected function lintNewlines($path) {
$data = $this->getData($path);
$pos = strpos($this->getData($path), "\r");

View file

@ -0,0 +1,3 @@
<?php ?>
~~~~~~~~~~
warning::

View file

@ -0,0 +1,4 @@
<?php
// This file is not empty.
~~~~~~~~~~

View file

@ -1,6 +1,7 @@
<?
~~~~~~~~~~
warning::
error:1:1
~~~~~~~~~~
<?php

View file

@ -146,6 +146,10 @@ abstract class ArcanistXHPASTLinterRule extends Phobject {
$replace);
}
final protected function raiseLintAtPath($desc) {
return $this->linter->raiseLintAtPath($this->getLintID(), $desc);
}
final protected function raiseLintAtToken(
XHPASTToken $token,
$desc,

View file

@ -0,0 +1,35 @@
<?php
final class ArcanistEmptyFileXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 82;
public function getLintName() {
return pht('Empty File');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$tokens = $root->getTokens();
foreach ($tokens as $token) {
switch ($token->getTypeName()) {
case 'T_OPEN_TAG':
case 'T_CLOSE_TAG':
case 'T_WHITESPACE':
break;
default:
return;
}
}
$this->raiseLintAtPath(
pht("Empty files usually don't serve any useful purpose."));
}
}