1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-12-01 19:22:41 +01:00

Allow specifying multiple locations of the same lint error

Summary:
Some errors (duplicate declaration, invalid number of arguments) have more related places.
We need to notify user if he changes any related place.
This could be currently achieved by triggering errors instead of warnings or by including both files in the range (impossible if the locations are in different files) or by issuing multiple errors.
All options are too aggressive.

Test Plan: Issued error on unmodified line with other location on modified line.

Reviewers: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D4392
This commit is contained in:
vrana 2013-01-10 15:03:33 -08:00
parent 80cd881fb1
commit a82493a84d
4 changed files with 56 additions and 27 deletions

View file

@ -18,6 +18,7 @@ final class ArcanistLintMessage {
protected $replacementText; protected $replacementText;
protected $appliedToDisk; protected $appliedToDisk;
protected $dependentMessages = array(); protected $dependentMessages = array();
protected $otherLocations = array();
protected $obsolete; protected $obsolete;
protected $uncacheable; protected $uncacheable;
@ -37,6 +38,7 @@ final class ArcanistLintMessage {
if (isset($dict['replacement'])) { if (isset($dict['replacement'])) {
$message->setReplacementText($dict['replacement']); $message->setReplacementText($dict['replacement']);
} }
$message->setOtherLocations(idx($dict, 'locations', array()));
return $message; return $message;
} }
@ -51,6 +53,7 @@ final class ArcanistLintMessage {
'description' => $this->getDescription(), 'description' => $this->getDescription(),
'original' => $this->getOriginalText(), 'original' => $this->getOriginalText(),
'replacement' => $this->getReplacementText(), 'replacement' => $this->getReplacementText(),
'locations' => $this->getOtherLocations(),
); );
} }
@ -135,6 +138,18 @@ final class ArcanistLintMessage {
return $this->replacementText; return $this->replacementText;
} }
/**
* @param dict Keys 'path', 'line', 'char', 'original'.
*/
public function setOtherLocations(array $locations) {
$this->otherLocations = $locations;
return $this;
}
public function getOtherLocations() {
return $this->otherLocations;
}
public function isError() { public function isError() {
return $this->getSeverity() == ArcanistLintSeverity::SEVERITY_ERROR; return $this->getSeverity() == ArcanistLintSeverity::SEVERITY_ERROR;
} }

View file

@ -305,28 +305,43 @@ abstract class ArcanistLintEngine {
abstract protected function buildLinters(); abstract protected function buildLinters();
private function isRelevantMessage($message) { private function isRelevantMessage(ArcanistLintMessage $message) {
// When a user runs "arc lint", we default to raising only warnings on // When a user runs "arc lint", we default to raising only warnings on
// lines they have changed (errors are still raised anywhere in the // lines they have changed (errors are still raised anywhere in the
// file). The list of $changed lines may be null, to indicate that the // file). The list of $changed lines may be null, to indicate that the
// path is a directory or a binary file so we should not exclude // path is a directory or a binary file so we should not exclude
// warnings. // warnings.
$changed = $this->getPathChangedLines($message->getPath()); if (!$this->changedLines || $message->isError()) {
if ($changed === null || $message->isError() || !$message->getLine()) {
return true; return true;
} }
$last_line = $message->getLine(); $locations = $message->getOtherLocations();
if ($message->getOriginalText()) { $locations[] = $message->toDictionary();
$last_line += substr_count($message->getOriginalText(), "\n");
}
for ($l = $message->getLine(); $l <= $last_line; $l++) { foreach ($locations as $location) {
if (!empty($changed[$l])) { $path = idx($location, 'path', $message->getPath());
if (!array_key_exists($path, $this->changedLines)) {
continue;
}
$changed = $this->getPathChangedLines($path);
if ($changed === null || !$location['line']) {
return true; return true;
} }
$last_line = $location['line'];
if (isset($location['original'])) {
$last_line += substr_count($location['original'], "\n");
}
for ($l = $location['line']; $l <= $last_line; $l++) {
if (!empty($changed[$l])) {
return true;
}
}
} }
return false; return false;

View file

@ -29,6 +29,7 @@
* 'name' * 'name'
* 'description' * 'description'
* 'original' & 'replacement' => optional patch information * 'original' & 'replacement' => optional patch information
* 'locations' => other locations of the same error (in the same format)
* *
* This class is intended for customization via instantiation, not via * This class is intended for customization via instantiation, not via
* subclassing. * subclassing.

View file

@ -135,6 +135,17 @@ abstract class ArcanistLinter {
return $this->messages; return $this->messages;
} }
protected function newLintAtLine($line, $char, $code, $desc) {
return id(new ArcanistLintMessage())
->setPath($this->getActivePath())
->setLine($line)
->setChar($char)
->setCode($this->getLintMessageFullCode($code))
->setSeverity($this->getLintMessageSeverity($code))
->setName($this->getLintMessageName($code))
->setDescription($desc);
}
protected function raiseLintAtLine( protected function raiseLintAtLine(
$line, $line,
$char, $char,
@ -143,24 +154,11 @@ abstract class ArcanistLinter {
$original = null, $original = null,
$replacement = null) { $replacement = null) {
$dict = array( $message = $this->newLintAtLine($line, $char, $code, $desc)
'path' => $this->getActivePath(), ->setOriginalText($original)
'line' => $line, ->setReplacementText($replacement);
'char' => $char,
'code' => $this->getLintMessageFullCode($code),
'severity' => $this->getLintMessageSeverity($code),
'name' => $this->getLintMessageName($code),
'description' => $desc,
);
if ($original !== null) { return $this->addLintMessage($message);
$dict['original'] = $original;
}
if ($replacement !== null) {
$dict['replacement'] = $replacement;
}
return $this->addLintMessage(ArcanistLintMessage::newFromDictionary($dict));
} }
protected function raiseLintAtPath( protected function raiseLintAtPath(