diff --git a/src/lint/linter/ArcanistTextLinter.php b/src/lint/linter/ArcanistTextLinter.php index 9042207e..3b6ee659 100644 --- a/src/lint/linter/ArcanistTextLinter.php +++ b/src/lint/linter/ArcanistTextLinter.php @@ -1,270 +1,288 @@ 'optional int', + ); + + return $options + parent::getLinterConfigurationOptions(); + } + public function setMaxLineLength($new_length) { $this->maxLineLength = $new_length; return $this; } + public function setLinterConfigurationValue($key, $value) { + switch ($key) { + case 'text.max-line-length': + $this->setMaxLineLength($value); + return; + } + + return parent::setLinterConfigurationValue($key, $value); + } + public function getLinterName() { return 'TXT'; } public function getLinterConfigurationName() { return 'text'; } public function getLintSeverityMap() { return array( self::LINT_LINE_WRAP => ArcanistLintSeverity::SEVERITY_WARNING, self::LINT_TRAILING_WHITESPACE => ArcanistLintSeverity::SEVERITY_AUTOFIX, self::LINT_BOF_WHITESPACE => ArcanistLintSeverity::SEVERITY_AUTOFIX, self::LINT_EOF_WHITESPACE => ArcanistLintSeverity::SEVERITY_AUTOFIX, ); } public function getLintNameMap() { return array( self::LINT_DOS_NEWLINE => pht('DOS Newlines'), self::LINT_TAB_LITERAL => pht('Tab Literal'), self::LINT_LINE_WRAP => pht('Line Too Long'), self::LINT_EOF_NEWLINE => pht('File Does Not End in Newline'), self::LINT_BAD_CHARSET => pht('Bad Charset'), self::LINT_TRAILING_WHITESPACE => pht('Trailing Whitespace'), self::LINT_NO_COMMIT => pht('Explicit %s', '@no'.'commit'), self::LINT_BOF_WHITESPACE => pht('Leading Whitespace at BOF'), self::LINT_EOF_WHITESPACE => pht('Trailing Whitespace at EOF'), ); } public function lintPath($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; } $this->lintNewlines($path); $this->lintTabs($path); if ($this->didStopAllLinters()) { return; } $this->lintCharset($path); if ($this->didStopAllLinters()) { return; } $this->lintLineLength($path); $this->lintEOFNewline($path); $this->lintTrailingWhitespace($path); $this->lintBOFWhitespace($path); $this->lintEOFWhitespace($path); if ($this->getEngine()->getCommitHookMode()) { $this->lintNoCommit($path); } } protected function lintNewlines($path) { $pos = strpos($this->getData($path), "\r"); if ($pos !== false) { $this->raiseLintAtOffset( $pos, self::LINT_DOS_NEWLINE, 'You must use ONLY Unix linebreaks ("\n") in source code.', "\r"); if ($this->isMessageEnabled(self::LINT_DOS_NEWLINE)) { $this->stopAllLinters(); } } } protected function lintTabs($path) { $pos = strpos($this->getData($path), "\t"); if ($pos !== false) { $this->raiseLintAtOffset( $pos, self::LINT_TAB_LITERAL, 'Configure your editor to use spaces for indentation.', "\t"); } } protected function lintLineLength($path) { $lines = explode("\n", $this->getData($path)); $width = $this->maxLineLength; foreach ($lines as $line_idx => $line) { if (strlen($line) > $width) { $this->raiseLintAtLine( $line_idx + 1, 1, self::LINT_LINE_WRAP, 'This line is '.number_format(strlen($line)).' characters long, '. 'but the convention is '.$width.' characters.', $line); } } } protected function lintEOFNewline($path) { $data = $this->getData($path); if (!strlen($data) || $data[strlen($data) - 1] != "\n") { $this->raiseLintAtOffset( strlen($data), self::LINT_EOF_NEWLINE, "Files must end in a newline.", '', "\n"); } } protected function lintCharset($path) { $data = $this->getData($path); $matches = null; $bad = '[^\x09\x0A\x20-\x7E]'; $preg = preg_match_all( "/{$bad}(.*{$bad})?/", $data, $matches, PREG_OFFSET_CAPTURE); if (!$preg) { return; } foreach ($matches[0] as $match) { list($string, $offset) = $match; $this->raiseLintAtOffset( $offset, self::LINT_BAD_CHARSET, 'Source code should contain only ASCII bytes with ordinal decimal '. 'values between 32 and 126 inclusive, plus linefeed. Do not use UTF-8 '. 'or other multibyte charsets.', $string); } if ($this->isMessageEnabled(self::LINT_BAD_CHARSET)) { $this->stopAllLinters(); } } protected function lintTrailingWhitespace($path) { $data = $this->getData($path); $matches = null; $preg = preg_match_all( '/ +$/m', $data, $matches, PREG_OFFSET_CAPTURE); if (!$preg) { return; } foreach ($matches[0] as $match) { list($string, $offset) = $match; $this->raiseLintAtOffset( $offset, self::LINT_TRAILING_WHITESPACE, 'This line contains trailing whitespace. Consider setting up your '. 'editor to automatically remove trailing whitespace, you will save '. 'time.', $string, ''); } } protected function lintBOFWhitespace($path) { $data = $this->getData($path); $matches = null; $preg = preg_match( '/^\s*\n/', $data, $matches, PREG_OFFSET_CAPTURE); if (!$preg) { return; } list($string, $offset) = $matches[0]; $this->raiseLintAtOffset( $offset, self::LINT_BOF_WHITESPACE, 'This file contains leading whitespace at the beginning of the file. ' . 'This is unnecessary and should be avoided when possible.', $string, ''); } protected function lintEOFWhitespace($path) { $data = $this->getData($path); $matches = null; $preg = preg_match( '/(?<=\n)\s+$/', $data, $matches, PREG_OFFSET_CAPTURE); if (!$preg) { return; } list($string, $offset) = $matches[0]; $this->raiseLintAtOffset( $offset, self::LINT_EOF_WHITESPACE, 'This file contains trailing whitespace at the end of the file. This ' . 'is unnecessary and should be avoided when possible.', $string, ''); } private function lintNoCommit($path) { $data = $this->getData($path); $deadly = '@no'.'commit'; $offset = strpos($data, $deadly); if ($offset !== false) { $this->raiseLintAtOffset( $offset, self::LINT_NO_COMMIT, 'This file is explicitly marked as "'.$deadly.'", which blocks '. 'commits.', $deadly); } } }