Skip to content

Commit

Permalink
Fix not finding vendor paths, closes psalm#9
Browse files Browse the repository at this point in the history
Previously paths to dependencies were resolved against the current
working directory and the plugin crashed early if the current working
directory is different with a RuntimeException making Psalm failing
to load the PsalmWordPress\Plugin.

This has been tested against a scenario where psalm is available as
tools/psalm in the project and the composer.json lies within the tools/
folder.

This would also be the case if the vendor directory is not named
"vendor" or when installing psalm with the composer-bin plugin (which is
sometimes suggested in the psalm project [1]).

Fix here is to check for the other packages folders relative to its own
package folder in case the original path relative to the current working
directory is not a directory.

It is done in a way that effectively prevents checking for the name "vendor"
for the [vendor-dir] in case it is installed as a package.

[1]: vimeo/psalm#2905 (comment)
[vendor-dir]: https://getcomposer.org/doc/06-config.md#vendor-dir
  • Loading branch information
ktomk committed May 8, 2021
1 parent c15b5d5 commit c6e9367
Showing 1 changed file with 53 additions and 7 deletions.
60 changes: 53 additions & 7 deletions Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,57 @@ public function __invoke( RegistrationInterface $registration, ?SimpleXMLElement
static::loadStubbedHooks();
}

/**
* resolve a vendor-relative directory-path to the absolute package directory
*
* the plugin must run both from the source file in the repository (current working directory)
* as well as when required as a composer package when the current working directory may not
* have a vendor/ folder and the package directory is detected relative to this file.
*
* @param string $path of a folder, relative, inside vendor/ (composer), must start with 'vendor/' marker
* @return string
*/
private static function getVendorDir(string $path) : string {
$vendor = 'vendor/';
$self = 'humanmade/psalm-plugin-wordpress';

if (0 !== strpos($path, $vendor)) {
throw new \BadMethodCallException(
sprintf('$path must start with "%s", "%s" given', $vendor, $path)
);
}

$cwd = getcwd();

// prefer path relative to current working directory (original default)
$cwdPath = $cwd . '/' . $path;
if (is_dir($cwdPath)) {
return $cwdPath;
}

// check running as composer package inside a vendor folder
$pkgSelfDir = __DIR__;
$vendorDir = dirname($pkgSelfDir, 2);
if ($pkgSelfDir === $vendorDir . '/' . $self) {
// likely plugin is running as composer package, let's try for the path
$pkgPath = substr($path, strlen($vendor));
$vendorPath = $vendorDir . '/' . $pkgPath;
if (is_dir($vendorPath)) {
return $vendorPath;
}
}

// original default behaviour
return $cwdPath;
}

/**
* @return string[]
*/
private function getStubFiles(): array {

return [
getcwd() . '/vendor/php-stubs/wordpress-stubs/wordpress-stubs.php',
self::getVendorDir('vendor/php-stubs/wordpress-stubs') . '/wordpress-stubs.php',
__DIR__ . '/stubs/overrides.php',
];
}
Expand All @@ -59,9 +103,11 @@ protected static function loadStubbedHooks() : void {
return;
}

$wpHooksDataDir = self::getVendorDir('vendor/johnbillion/wp-hooks/hooks');

$hooks = array_merge(
static::getHooksFromFile( 'vendor/johnbillion/wp-hooks/hooks/actions.json' ),
static::getHooksFromFile( 'vendor/johnbillion/wp-hooks/hooks/filters.json' )
static::getHooksFromFile( $wpHooksDataDir . '/actions.json' ),
static::getHooksFromFile( $wpHooksDataDir . '/filters.json' )
);

static::$hooks = $hooks;
Expand Down Expand Up @@ -177,10 +223,10 @@ public static function getFunctionIds() : array {
}

/**
* @param list<PhpParser\Node\Arg> $call_args
*
* @return ?array<int, \Psalm\Storage\FunctionLikeParameter>
*/
* @param list<PhpParser\Node\Arg> $call_args
*
* @return ?array<int, \Psalm\Storage\FunctionLikeParameter>
*/
public static function getFunctionParams(
StatementsSource $statements_source,
string $function_id,
Expand Down

0 comments on commit c6e9367

Please sign in to comment.