Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/lint/linter/PhabricatorJavelinLinter.php
| Show All 13 Lines | final class PhabricatorJavelinLinter extends ArcanistLinter { | ||||
| const LINT_MISSING_BINARY = 5; | const LINT_MISSING_BINARY = 5; | ||||
| public function willLintPaths(array $paths) { | public function willLintPaths(array $paths) { | ||||
| $root = dirname(phutil_get_library_root('phabricator')); | $root = dirname(phutil_get_library_root('phabricator')); | ||||
| require_once $root.'/scripts/__init_script__.php'; | require_once $root.'/scripts/__init_script__.php'; | ||||
| if ($this->haveSymbolsBinary === null) { | if ($this->haveSymbolsBinary === null) { | ||||
| $binary = $this->getSymbolsBinaryPath(); | list($err) = exec_manual('which javelinsymbols'); | ||||
| $this->haveSymbolsBinary = Filesystem::pathExists($binary); | $this->haveSymbolsBinary = !$err; | ||||
| if (!$this->haveSymbolsBinary) { | if (!$this->haveSymbolsBinary) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| $futures = array(); | $futures = array(); | ||||
| foreach ($paths as $path) { | foreach ($paths as $path) { | ||||
| if ($this->shouldIgnorePath($path)) { | |||||
| continue; | |||||
| } | |||||
| $future = $this->newSymbolsFuture($path); | $future = $this->newSymbolsFuture($path); | ||||
| $futures[$path] = $future; | $futures[$path] = $future; | ||||
| } | } | ||||
| foreach (Futures($futures)->limit(8) as $path => $future) { | foreach (Futures($futures)->limit(8) as $path => $future) { | ||||
| $this->symbols[$path] = $future->resolvex(); | $this->symbols[$path] = $future->resolvex(); | ||||
| } | } | ||||
| } | } | ||||
| Show All 9 Lines | final class PhabricatorJavelinLinter extends ArcanistLinter { | ||||
| } | } | ||||
| public function getLintNameMap() { | public function getLintNameMap() { | ||||
| return array( | return array( | ||||
| self::LINT_PRIVATE_ACCESS => 'Private Method/Member Access', | self::LINT_PRIVATE_ACCESS => 'Private Method/Member Access', | ||||
| self::LINT_MISSING_DEPENDENCY => 'Missing Javelin Dependency', | self::LINT_MISSING_DEPENDENCY => 'Missing Javelin Dependency', | ||||
| self::LINT_UNNECESSARY_DEPENDENCY => 'Unnecessary Javelin Dependency', | self::LINT_UNNECESSARY_DEPENDENCY => 'Unnecessary Javelin Dependency', | ||||
| self::LINT_UNKNOWN_DEPENDENCY => 'Unknown Javelin Dependency', | self::LINT_UNKNOWN_DEPENDENCY => 'Unknown Javelin Dependency', | ||||
| self::LINT_MISSING_BINARY => '`javelinsymbols` Binary Not Built', | self::LINT_MISSING_BINARY => '`javelinsymbols` Not In Path', | ||||
| ); | ); | ||||
| } | } | ||||
| private function shouldIgnorePath($path) { | |||||
| return preg_match('@/__tests__/|externals/javelin/src/docs/@', $path); | |||||
| } | |||||
| public function lintPath($path) { | public function lintPath($path) { | ||||
| if ($this->shouldIgnorePath($path)) { | |||||
| return; | |||||
| } | |||||
| if (!$this->haveSymbolsBinary) { | if (!$this->haveSymbolsBinary) { | ||||
| if (!$this->haveWarnedAboutBinary) { | if (!$this->haveWarnedAboutBinary) { | ||||
| $this->haveWarnedAboutBinary = true; | $this->haveWarnedAboutBinary = true; | ||||
| // TODO: Write build documentation for the Javelin binaries and point | // TODO: Write build documentation for the Javelin binaries and point | ||||
| // the user at it. | // the user at it. | ||||
| $this->raiseLintAtLine( | $this->raiseLintAtLine( | ||||
| 1, | 1, | ||||
| 0, | 0, | ||||
| self::LINT_MISSING_BINARY, | self::LINT_MISSING_BINARY, | ||||
| "The 'javelinsymbols' binary in the Javelin project has not been ". | "The 'javelinsymbols' binary in the Javelin project is not ". | ||||
| "built, so the Javelin linter can't run. This isn't a big concern, ". | "available in \$PATH, so the Javelin linter can't run. This ". | ||||
| "but means some Javelin problems can't be automatically detected."); | "isn't a big concern, but means some Javelin problems can't be ". | ||||
| "automatically detected."); | |||||
| } | } | ||||
| return; | return; | ||||
| } | } | ||||
| list($uses, $installs) = $this->getUsedAndInstalledSymbolsForPath($path); | list($uses, $installs) = $this->getUsedAndInstalledSymbolsForPath($path); | ||||
| foreach ($uses as $symbol => $line) { | foreach ($uses as $symbol => $line) { | ||||
| $parts = explode('.', $symbol); | $parts = explode('.', $symbol); | ||||
| foreach ($parts as $part) { | foreach ($parts as $part) { | ||||
| ▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | final class PhabricatorJavelinLinter extends ArcanistLinter { | ||||
| private function loadSymbols($path) { | private function loadSymbols($path) { | ||||
| if (empty($this->symbols[$path])) { | if (empty($this->symbols[$path])) { | ||||
| $this->symbols[$path] = $this->newSymbolsFuture($path)->resolvex(); | $this->symbols[$path] = $this->newSymbolsFuture($path)->resolvex(); | ||||
| } | } | ||||
| return $this->symbols[$path]; | return $this->symbols[$path]; | ||||
| } | } | ||||
| private function newSymbolsFuture($path) { | private function newSymbolsFuture($path) { | ||||
| $javelinsymbols = $this->getSymbolsBinaryPath(); | $javelinsymbols = 'javelinsymbols'; | ||||
| $future = new ExecFuture($javelinsymbols.' # '.escapeshellarg($path)); | $future = new ExecFuture($javelinsymbols.' # '.escapeshellarg($path)); | ||||
| $future->write($this->getData($path)); | $future->write($this->getData($path)); | ||||
| return $future; | return $future; | ||||
| } | } | ||||
| private function getSymbolsBinaryPath() { | |||||
| $root = dirname(phutil_get_library_root('phabricator')); | |||||
| $support = $root.'/externals/javelin/support'; | |||||
| return $support.'/javelinsymbols/javelinsymbols'; | |||||
| } | |||||
| private function getUsedAndInstalledSymbolsForPath($path) { | private function getUsedAndInstalledSymbolsForPath($path) { | ||||
| list($symbols) = $this->loadSymbols($path); | list($symbols) = $this->loadSymbols($path); | ||||
| $symbols = trim($symbols); | $symbols = trim($symbols); | ||||
| $uses = array(); | $uses = array(); | ||||
| $installs = array(); | $installs = array(); | ||||
| if (empty($symbols)) { | if (empty($symbols)) { | ||||
| // This file has no symbols. | // This file has no symbols. | ||||
| ▲ Show 20 Lines • Show All 43 Lines • Show Last 20 Lines | |||||