mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-29 02:02:40 +01:00
Allow "arc liberate" / PhutilModuleLinter to ignore declared external symbols
Summary: See T762. Currently, some externals functions (recaptcha, xhprof) raise errors and prevent clean runs of "arc liberate" without --force-update or a forced cache. Allow such symbols to be declared: /** * @phutil-external-symbol function some_function */ This prevents them from being treated as dependencies. Test Plan: Ran "arc liberate src/ --all" on Phabricator, fixed all the warnings by adding @phutil-external-symbol declarations. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, jungejason Maniphest Tasks: T762 Differential Revision: https://secure.phabricator.com/D1381
This commit is contained in:
parent
6dfa45a8b3
commit
93db641a3e
1 changed files with 57 additions and 22 deletions
|
@ -2,7 +2,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -56,6 +56,7 @@ if ($argc != 2) {
|
||||||
phutil_require_module('phutil', 'filesystem');
|
phutil_require_module('phutil', 'filesystem');
|
||||||
$dir = Filesystem::resolvePath($argv[1]);
|
$dir = Filesystem::resolvePath($argv[1]);
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'parser/docblock');
|
||||||
phutil_require_module('phutil', 'parser/xhpast/bin');
|
phutil_require_module('phutil', 'parser/xhpast/bin');
|
||||||
phutil_require_module('phutil', 'parser/xhpast/api/tree');
|
phutil_require_module('phutil', 'parser/xhpast/api/tree');
|
||||||
|
|
||||||
|
@ -78,6 +79,8 @@ foreach (Filesystem::listDirectory($dir, $hidden_files = false) as $file) {
|
||||||
$requirements = new PhutilModuleRequirements();
|
$requirements = new PhutilModuleRequirements();
|
||||||
$requirements->addBuiltins($builtin);
|
$requirements->addBuiltins($builtin);
|
||||||
|
|
||||||
|
$doc_parser = new PhutilDocblockParser();
|
||||||
|
|
||||||
$has_init = false;
|
$has_init = false;
|
||||||
$has_files = false;
|
$has_files = false;
|
||||||
foreach (Futures($futures) as $file => $future) {
|
foreach (Futures($futures) as $file => $future) {
|
||||||
|
@ -130,6 +133,28 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
|
|
||||||
$requirements->addSourceDeclaration(basename($file));
|
$requirements->addSourceDeclaration(basename($file));
|
||||||
|
|
||||||
|
// Find symbols declared as "@phutil-external-symbol function example",
|
||||||
|
// and ignore these in building dependency lists.
|
||||||
|
|
||||||
|
$externals = array();
|
||||||
|
foreach ($root->getTokens() as $token) {
|
||||||
|
if ($token->getTypeName() == 'T_DOC_COMMENT') {
|
||||||
|
list($block, $special) = $doc_parser->parse($token->getValue());
|
||||||
|
|
||||||
|
$ext_list = idx($special, 'phutil-external-symbol');
|
||||||
|
$ext_list = explode("\n", $ext_list);
|
||||||
|
$ext_list = array_filter($ext_list);
|
||||||
|
|
||||||
|
foreach ($ext_list as $ext_ref) {
|
||||||
|
$matches = null;
|
||||||
|
if (preg_match('/^\s*(\S+)\s+(\S+)/', $ext_ref, $matches)) {
|
||||||
|
$externals[$matches[1]][$matches[2]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function uses:
|
// Function uses:
|
||||||
// - Explicit call
|
// - Explicit call
|
||||||
// TODO?: String literal in ReflectionFunction().
|
// TODO?: String literal in ReflectionFunction().
|
||||||
|
@ -180,7 +205,7 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
"from being checked statically. This module may have undetectable ".
|
"from being checked statically. This module may have undetectable ".
|
||||||
"errors.");
|
"errors.");
|
||||||
}
|
}
|
||||||
} else {
|
} else if (empty($externals['function'][$name->getConcreteString()])) {
|
||||||
$requirements->addFunctionDependency(
|
$requirements->addFunctionDependency(
|
||||||
$name,
|
$name,
|
||||||
$name->getConcreteString());
|
$name->getConcreteString());
|
||||||
|
@ -219,20 +244,24 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
$class_name->getConcreteString());
|
$class_name->getConcreteString());
|
||||||
$extends = $class->getChildByIndex(2);
|
$extends = $class->getChildByIndex(2);
|
||||||
foreach ($extends->selectDescendantsOfType('n_CLASS_NAME') as $parent) {
|
foreach ($extends->selectDescendantsOfType('n_CLASS_NAME') as $parent) {
|
||||||
|
if (empty($externals['class'][$parent->getConcreteString()])) {
|
||||||
$requirements->addClassDependency(
|
$requirements->addClassDependency(
|
||||||
$class_name->getConcreteString(),
|
$class_name->getConcreteString(),
|
||||||
$parent,
|
$parent,
|
||||||
$parent->getConcreteString());
|
$parent->getConcreteString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$implements = $class->getChildByIndex(3);
|
$implements = $class->getChildByIndex(3);
|
||||||
$interfaces = $implements->selectDescendantsOfType('n_CLASS_NAME');
|
$interfaces = $implements->selectDescendantsOfType('n_CLASS_NAME');
|
||||||
foreach ($interfaces as $interface) {
|
foreach ($interfaces as $interface) {
|
||||||
|
if (empty($externals['interface'][$interface->getConcreteString()])) {
|
||||||
$requirements->addInterfaceDependency(
|
$requirements->addInterfaceDependency(
|
||||||
$class_name->getConcreteString(),
|
$class_name->getConcreteString(),
|
||||||
$interface,
|
$interface,
|
||||||
$interface->getConcreteString());
|
$interface->getConcreteString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count($classes) > 1) {
|
if (count($classes) > 1) {
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
|
@ -262,11 +291,13 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
"errors.");
|
"errors.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (empty($externals['class'][$name->getConcreteString()])) {
|
||||||
$requirements->addClassDependency(
|
$requirements->addClassDependency(
|
||||||
null,
|
null,
|
||||||
$name,
|
$name,
|
||||||
$name->getConcreteString());
|
$name->getConcreteString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$static_uses = $root->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
|
$static_uses = $root->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
|
||||||
foreach ($static_uses as $static_use) {
|
foreach ($static_uses as $static_use) {
|
||||||
|
@ -284,11 +315,13 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
if (isset($magic_names[$name_concrete])) {
|
if (isset($magic_names[$name_concrete])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (empty($externals['class'][$name_concrete])) {
|
||||||
$requirements->addClassDependency(
|
$requirements->addClassDependency(
|
||||||
null,
|
null,
|
||||||
$name,
|
$name,
|
||||||
$name_concrete);
|
$name_concrete);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Interface uses:
|
// Interface uses:
|
||||||
// - implements
|
// - implements
|
||||||
|
@ -302,12 +335,14 @@ foreach (Futures($futures) as $file => $future) {
|
||||||
$interface_name->getConcreteString());
|
$interface_name->getConcreteString());
|
||||||
$extends = $interface->getChildByIndex(2);
|
$extends = $interface->getChildByIndex(2);
|
||||||
foreach ($extends->selectDescendantsOfType('n_CLASS_NAME') as $parent) {
|
foreach ($extends->selectDescendantsOfType('n_CLASS_NAME') as $parent) {
|
||||||
|
if (empty($externals['interface'][$parent->getConcreteString()])) {
|
||||||
$requirements->addInterfaceDependency(
|
$requirements->addInterfaceDependency(
|
||||||
$interface_name->getConcreteString(),
|
$interface_name->getConcreteString(),
|
||||||
$parent,
|
$parent,
|
||||||
$parent->getConcreteString());
|
$parent->getConcreteString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue