1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 16:22:42 +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:
epriestley 2012-01-12 13:51:35 -08:00
parent 6dfa45a8b3
commit 93db641a3e

View file

@ -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());
} }
} }
}
} }
} }