mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-22 21:40:54 +01:00
Verify classes used in typehints
Summary: Also support `SomeInterface::CONSTANT`. Test Plan: interface I { const A = 1; } I::A; function f(stdClass $a, array $b, Iterator $c) { } Linted Phabricator. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D6135
This commit is contained in:
parent
e93726cb3b
commit
5336f4bcf0
3 changed files with 35 additions and 16 deletions
|
@ -21,7 +21,7 @@ final class PhutilLibraryMapBuilder {
|
|||
const LIBRARY_MAP_VERSION = 2;
|
||||
|
||||
const SYMBOL_CACHE_VERSION_KEY = '__symbol_cache_version__';
|
||||
const SYMBOL_CACHE_VERSION = 8;
|
||||
const SYMBOL_CACHE_VERSION = 9;
|
||||
|
||||
|
||||
/* -( Mapping libphutil Libraries )---------------------------------------- */
|
||||
|
|
|
@ -211,10 +211,10 @@ foreach ($classes as $class) {
|
|||
// - Static method call
|
||||
// - Static property access
|
||||
// - Use of class constant
|
||||
// - typehints
|
||||
//
|
||||
// TODO: Possibly support these:
|
||||
//
|
||||
// - typehints
|
||||
// - instanceof
|
||||
// - catch
|
||||
// - String literal in ReflectionClass().
|
||||
|
@ -273,11 +273,24 @@ foreach ($static_uses as $static_use) {
|
|||
continue;
|
||||
}
|
||||
$need[] = array(
|
||||
'type' => 'class',
|
||||
'type' => 'class/interface',
|
||||
'symbol' => $name,
|
||||
);
|
||||
}
|
||||
|
||||
// This is "function (X $x)".
|
||||
$parameters = $root->selectDescendantsOfType('n_DECLARATION_PARAMETER');
|
||||
foreach ($parameters as $parameter) {
|
||||
$hint = $parameter->getChildByIndex(0);
|
||||
if ($hint->getTypeName() != 'n_CLASS_NAME') {
|
||||
continue;
|
||||
}
|
||||
$need[] = array(
|
||||
'type' => 'class/interface',
|
||||
'symbol' => $hint,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// -( Interfaces )------------------------------------------------------------
|
||||
|
||||
|
@ -355,14 +368,20 @@ foreach ($need as $key => $spec) {
|
|||
}
|
||||
|
||||
$type = $spec['type'];
|
||||
if (!$show_all) {
|
||||
if (!empty($externals[$type][$name])) {
|
||||
// Ignore symbols declared as externals.
|
||||
continue;
|
||||
foreach (explode('/', $type) as $libtype) {
|
||||
if (!$show_all) {
|
||||
if (!empty($externals[$libtype][$name])) {
|
||||
// Ignore symbols declared as externals.
|
||||
continue 2;
|
||||
}
|
||||
if (!empty($builtins[$libtype][$name])) {
|
||||
// Ignore symbols declared as builtins.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
if (!empty($builtins[$type][$name])) {
|
||||
// Ignore symbols declared as builtins.
|
||||
continue;
|
||||
if (!empty($declared_symbols[$libtype][$name])) {
|
||||
// We declare this symbol, so don't treat it as a requirement.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
if (!empty($required_symbols[$type][$name])) {
|
||||
|
@ -370,10 +389,6 @@ foreach ($need as $key => $spec) {
|
|||
// isn't terribly informative.
|
||||
continue;
|
||||
}
|
||||
if (!empty($declared_symbols[$type][$name])) {
|
||||
// We declare this symbol, so don't treat it as a requirement.
|
||||
continue;
|
||||
}
|
||||
$required_symbols[$type][$name] = $spec['symbol']->getOffset();
|
||||
}
|
||||
|
||||
|
|
|
@ -134,14 +134,18 @@ final class ArcanistPhutilLibraryLinter extends ArcanistLinter {
|
|||
}
|
||||
}
|
||||
|
||||
$types = array('class', 'function', 'interface', 'class/interface');
|
||||
foreach ($symbols as $library => $map) {
|
||||
// Check for unknown symbols: uses of classes, functions or interfaces
|
||||
// which are not defined anywhere. We reference the list of all symbols
|
||||
// we built up earlier.
|
||||
foreach ($map as $file => $spec) {
|
||||
$need = idx($spec, 'need', array());
|
||||
foreach (array('class', 'function', 'interface') as $type) {
|
||||
$libtype = ($type == 'interface') ? 'class' : $type;
|
||||
foreach ($types as $type) {
|
||||
$libtype = $type;
|
||||
if ($type == 'interface' || $type == 'class/interface') {
|
||||
$libtype = 'class';
|
||||
}
|
||||
foreach (idx($need, $type, array()) as $symbol => $offset) {
|
||||
if (!empty($all_symbols[$libtype][$symbol])) {
|
||||
// Symbol is defined somewhere.
|
||||
|
|
Loading…
Reference in a new issue