mirror of
https://we.phorge.it/source/arcanist.git
synced 2025-01-11 07:11:03 +01:00
Add ArcanistConduitLinter, a linter that delegates through Conduit
Summary: Julien built a really cool static analysis database of our codebase. One capability is that it can suggest typehints that are not in the code. The analysis to do this is very expensive, so it can't reasonably be run locally. But it can remain indexed on a server. The idea here is to provide a familiar interface to it through arc lint, via a generic Conduit service call. In our lint engine, this will probably be gated on --advice for performance. This will introduce a slight awkwardness in that running with --advice can add new non-advice lint if the server chooses, but this isn't likely to cause a practical problem. Test Plan: Construct a fake Conduit lint endpoint, attach this linter to it, and see bogus lint appear with --advice. Reviewers: epriestley Reviewed By: epriestley CC: aran Differential Revision: https://secure.phabricator.com/D1462
This commit is contained in:
parent
3299f1fc73
commit
2c4eb00a12
3 changed files with 129 additions and 0 deletions
|
@ -21,6 +21,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistChooseInvalidRevisionException' => 'exception',
|
||||
'ArcanistChooseNoRevisionsException' => 'exception',
|
||||
'ArcanistCommitWorkflow' => 'workflow/commit',
|
||||
'ArcanistConduitLinter' => 'lint/linter/conduit',
|
||||
'ArcanistConfiguration' => 'configuration',
|
||||
'ArcanistCoverWorkflow' => 'workflow/cover',
|
||||
'ArcanistDiffChange' => 'parser/diff/change',
|
||||
|
@ -119,6 +120,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistBundleTestCase' => 'ArcanistPhutilTestCase',
|
||||
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
|
||||
'ArcanistCommitWorkflow' => 'ArcanistBaseWorkflow',
|
||||
'ArcanistConduitLinter' => 'ArcanistLinter',
|
||||
'ArcanistCoverWorkflow' => 'ArcanistBaseWorkflow',
|
||||
'ArcanistDiffParserTestCase' => 'ArcanistPhutilTestCase',
|
||||
'ArcanistDiffUtilsTestCase' => 'ArcanistPhutilTestCase',
|
||||
|
|
110
src/lint/linter/conduit/ArcanistConduitLinter.php
Normal file
110
src/lint/linter/conduit/ArcanistConduitLinter.php
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements linting via Conduit RPC call.
|
||||
* Slow by definition, but allows sophisticated linting that relies on
|
||||
* stuff like big indexes of a codebase.
|
||||
* Recommended usage is to gate these to the advice lint level.
|
||||
*
|
||||
* The conduit endpoint should implement a method named the same as
|
||||
* the value of ArcanistConduitLinter::CONDUIT_METHOD.
|
||||
*
|
||||
* It takes an array with a key 'file_contents' which is an array mapping
|
||||
* file paths to their complete contents.
|
||||
*
|
||||
* It should return an array mapping those same paths to arrays describing the
|
||||
* lint for each path.
|
||||
*
|
||||
* The lint for a path is described as a list of structured dictionaries.
|
||||
*
|
||||
* The dictionary structure is effectively defined by
|
||||
* ArcanistLintMessage::newFromDictionary.
|
||||
*
|
||||
* Effective keys are:
|
||||
* 'path' => must match passed in path.
|
||||
* 'line'
|
||||
* 'char'
|
||||
* 'code'
|
||||
* 'severity' => Must match a constant in ArcanistLintSeverity.
|
||||
* 'name'
|
||||
* 'description'
|
||||
* 'original' & 'replacement' => optional patch information
|
||||
*
|
||||
* This class is intended for customization via instantiation, not via
|
||||
* subclassing.
|
||||
*/
|
||||
class ArcanistConduitLinter extends ArcanistLinter {
|
||||
const CONDUIT_METHOD = 'lint.getalllint';
|
||||
|
||||
private $conduitURI;
|
||||
private $linterName;
|
||||
private $lintByPath; // array(/pa/th/ => <lint>), valid after willLintPaths().
|
||||
|
||||
public function __construct($conduit_uri, $linter_name) {
|
||||
$this->conduitURI = $conduit_uri;
|
||||
$this->linterName = $linter_name;
|
||||
}
|
||||
|
||||
public function willLintPaths(array $paths) {
|
||||
// Load all file path data into $this->data.
|
||||
array_map(array($this, 'getData'), $paths);
|
||||
|
||||
$conduit = new ConduitClient($this->conduitURI);
|
||||
|
||||
$this->lintByPath = $conduit->callMethodSynchronous(
|
||||
self::CONDUIT_METHOD,
|
||||
array(
|
||||
'file_contents' => $this->data,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function lintPath($path) {
|
||||
$lint_for_path = idx($this->lintByPath, $path);
|
||||
if (!$lint_for_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($lint_for_path as $lint) {
|
||||
$this->addLintMessage(ArcanistLintMessage::newFromDictionary($lint));
|
||||
}
|
||||
}
|
||||
|
||||
public function getLinterName() {
|
||||
return $this->linterName;
|
||||
}
|
||||
|
||||
public function getLintSeverityMap() {
|
||||
// The rationale here is that this class will only be used for custom
|
||||
// linting in installations. No two server endpoints will be the same across
|
||||
// different instantiations. Therefore, the server can handle all severity
|
||||
// customization directly.
|
||||
throw new ArcanistUsageException(
|
||||
'ArcanistConduitLinter does not support client-side severity '.
|
||||
'customization.'
|
||||
);
|
||||
}
|
||||
|
||||
public function getLintNameMap() {
|
||||
// See getLintSeverityMap for rationale.
|
||||
throw new ArcanistUsageException(
|
||||
'ArcanistConduitLinter does not support a name map.'
|
||||
);
|
||||
}
|
||||
}
|
17
src/lint/linter/conduit/__init__.php
Normal file
17
src/lint/linter/conduit/__init__.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('arcanist', 'exception/usage');
|
||||
phutil_require_module('arcanist', 'lint/linter/base');
|
||||
phutil_require_module('arcanist', 'lint/message');
|
||||
|
||||
phutil_require_module('phutil', 'conduit/client');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('ArcanistConduitLinter.php');
|
Loading…
Reference in a new issue