diff --git a/src/lint/ArcanistLintMessage.php b/src/lint/ArcanistLintMessage.php index cce74e5e..25f193d7 100644 --- a/src/lint/ArcanistLintMessage.php +++ b/src/lint/ArcanistLintMessage.php @@ -19,6 +19,7 @@ final class ArcanistLintMessage { protected $appliedToDisk; protected $dependentMessages = array(); protected $obsolete; + protected $uncacheable; public static function newFromDictionary(array $dict) { $message = new ArcanistLintMessage(); @@ -179,6 +180,15 @@ final class ArcanistLintMessage { return $this->appliedToDisk; } + public function setUncacheable($bool) { + $this->uncacheable = $bool; + return $this; + } + + public function isUncacheable() { + return $this->uncacheable; + } + public function setDependentMessages(array $messages) { assert_instances_of($messages, 'ArcanistLintMessage'); $this->dependentMessages = $messages; diff --git a/src/lint/engine/ArcanistLintEngine.php b/src/lint/engine/ArcanistLintEngine.php index cbf7670a..8d4845f2 100644 --- a/src/lint/engine/ArcanistLintEngine.php +++ b/src/lint/engine/ArcanistLintEngine.php @@ -198,6 +198,8 @@ abstract class ArcanistLintEngine { } $paths = $linter->getPaths(); + $cache_granularity = $linter->getCacheGranularity(); + foreach ($paths as $key => $path) { // Make sure each path has a result generated, even if it is empty // (i.e., the file has no lint messages). @@ -205,9 +207,10 @@ abstract class ArcanistLintEngine { if (isset($stopped[$path])) { unset($paths[$key]); } - // TODO: Some linters work with the whole directory. if (isset($this->cachedResults[$path][$this->cacheVersion])) { - unset($paths[$key]); + if ($cache_granularity == ArcanistLinter::GRANULARITY_FILE) { + unset($paths[$key]); + } } } $paths = array_values($paths); @@ -231,6 +234,9 @@ abstract class ArcanistLintEngine { if (!$this->isRelevantMessage($message)) { continue; } + if ($cache_granularity != ArcanistLinter::GRANULARITY_FILE) { + $message->setUncacheable(true); + } $result = $this->getResultForPath($message->getPath()); $result->addMessage($message); } diff --git a/src/lint/linter/ArcanistLinter.php b/src/lint/linter/ArcanistLinter.php index 0c20fab9..909aa71b 100644 --- a/src/lint/linter/ArcanistLinter.php +++ b/src/lint/linter/ArcanistLinter.php @@ -8,6 +8,11 @@ */ abstract class ArcanistLinter { + const GRANULARITY_FILE = 1; + const GRANULARITY_DIRECTORY = 2; + const GRANULARITY_REPOSITORY = 3; + const GRANULARITY_GLOBAL = 4; + protected $paths = array(); protected $data = array(); protected $engine; @@ -211,4 +216,8 @@ abstract class ArcanistLinter { return array(); } + public function getCacheGranularity() { + return self::GRANULARITY_FILE; + } + } diff --git a/src/lint/linter/ArcanistPhutilLibraryLinter.php b/src/lint/linter/ArcanistPhutilLibraryLinter.php index c7a31e52..7b7ebe76 100644 --- a/src/lint/linter/ArcanistPhutilLibraryLinter.php +++ b/src/lint/linter/ArcanistPhutilLibraryLinter.php @@ -171,4 +171,9 @@ final class ArcanistPhutilLibraryLinter extends ArcanistLinter { public function lintPath($path) { return; } + + public function getCacheGranularity() { + return self::GRANULARITY_GLOBAL; + } + } diff --git a/src/workflow/ArcanistLintWorkflow.php b/src/workflow/ArcanistLintWorkflow.php index 10e8a37b..fce3eccb 100644 --- a/src/workflow/ArcanistLintWorkflow.php +++ b/src/workflow/ArcanistLintWorkflow.php @@ -192,9 +192,14 @@ EOTEXT if ($this->getArgument('cache')) { $cache = $this->readScratchJSONFile('lint-cache.json'); $cache = idx($cache, $this->getCacheKey(), array()); + $cache = array_intersect_key($cache, array_flip($paths)); $cached = array(); foreach ($cache as $path => $messages) { - $messages = idx($messages, md5_file($engine->getFilePathOnDisk($path))); + $abs_path = $engine->getFilePathOnDisk($path); + if (!Filesystem::pathExists($abs_path)) { + continue; + } + $messages = idx($messages, md5_file($abs_path)); if ($messages !== null) { $cached[$path] = $messages; } @@ -400,10 +405,17 @@ EOTEXT unset($cached[$path]); continue; } - $hash = md5_file($engine->getFilePathOnDisk($path)); + $abs_path = $engine->getFilePathOnDisk($path); + if (!Filesystem::pathExists($abs_path)) { + continue; + } + $hash = md5_file($abs_path); $version = $result->getCacheVersion(); $cached[$path] = array($hash => array($version => array())); foreach ($result->getMessages() as $message) { + if ($message->isUncacheable()) { + continue; + } if (!$message->isPatchApplied()) { $cached[$path][$hash][$version][] = $message->toDictionary(); }