mirror of
https://github.com/barryvdh/laravel-ide-helper.git
synced 2026-08-18 01:57:13 +00:00
Use php-templates from vs-code
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,5 @@
|
||||
The templates here are based on the official VS Code extension by Laravel https://github.com/laravel/vs-code-extension
|
||||
|
||||
Modifications:
|
||||
- return instead of echo
|
||||
- do not serialize to JSON
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
$local = collect(glob(config_path("/*.php")))
|
||||
->merge(glob(config_path("**/*.php")))
|
||||
->map(fn ($path) => [
|
||||
(string) \Illuminate\Support\Str::of($path)
|
||||
->replace([config_path("/"), ".php"], "")
|
||||
->replace("/", "."),
|
||||
$path
|
||||
]);
|
||||
|
||||
$vendor = collect(glob(base_path("vendor/**/**/config/*.php")))->map(fn (
|
||||
$path
|
||||
) => [
|
||||
(string) \Illuminate\Support\Str::of($path)
|
||||
->afterLast("/config/")
|
||||
->replace(".php", "")
|
||||
->replace("/", "."),
|
||||
$path
|
||||
]);
|
||||
|
||||
$configPaths = $local
|
||||
->merge($vendor)
|
||||
->groupBy(0)
|
||||
->map(fn ($items)=>$items->pluck(1));
|
||||
|
||||
$cachedContents = [];
|
||||
$cachedParsed = [];
|
||||
|
||||
function vsCodeGetConfigValue($value, $key, $configPaths) {
|
||||
$parts = explode(".", $key);
|
||||
$toFind = $key;
|
||||
$found = null;
|
||||
|
||||
while (count($parts) > 0) {
|
||||
array_pop($parts);
|
||||
$toFind = implode(".", $parts);
|
||||
|
||||
if ($configPaths->has($toFind)) {
|
||||
$found = $toFind;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file = null;
|
||||
$line = null;
|
||||
|
||||
if ($found === $key) {
|
||||
$file = $configPaths->get($found)[0];
|
||||
} else {
|
||||
foreach ($configPaths->get($found) as $path) {
|
||||
$cachedContents[$path] ??= file_get_contents($path);
|
||||
$cachedParsed[$path] ??= token_get_all($cachedContents[$path]);
|
||||
|
||||
$keysToFind = \Illuminate\Support\Str::of($key)
|
||||
->replaceFirst($found, "")
|
||||
->ltrim(".")
|
||||
->explode(".");
|
||||
|
||||
if (is_numeric($keysToFind->last())) {
|
||||
$index = $keysToFind->pop();
|
||||
|
||||
if ($index !== "0") {
|
||||
return null;
|
||||
}
|
||||
|
||||
$key = collect(explode(".", $key));
|
||||
$key->pop();
|
||||
$key = $key->implode(".");
|
||||
$value = "array(...)";
|
||||
}
|
||||
|
||||
$nextKey = $keysToFind->shift();
|
||||
$expectedDepth = 1;
|
||||
|
||||
$depth = 0;
|
||||
|
||||
foreach ($cachedParsed[$path] as $token) {
|
||||
if ($token === "[") {
|
||||
$depth++;
|
||||
}
|
||||
|
||||
if ($token === "]") {
|
||||
$depth--;
|
||||
}
|
||||
|
||||
if (!is_array($token)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$str = trim($token[1], '"\'');
|
||||
|
||||
if (
|
||||
$str === $nextKey &&
|
||||
$depth === $expectedDepth &&
|
||||
$token[0] === T_CONSTANT_ENCAPSED_STRING
|
||||
) {
|
||||
$nextKey = $keysToFind->shift();
|
||||
$expectedDepth++;
|
||||
|
||||
if ($nextKey === null) {
|
||||
$file = $path;
|
||||
$line = $token[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($file) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
"name" => $key,
|
||||
"value" => $value,
|
||||
"file" => $file === null ? null : str_replace(base_path('/'), '', $file),
|
||||
"line" => $line
|
||||
];
|
||||
}
|
||||
|
||||
return collect(\Illuminate\Support\Arr::dot(config()->all()))
|
||||
->map(fn ($value, $key) => vsCodeGetConfigValue($value, $key, $configPaths))
|
||||
->filter()
|
||||
->values();
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
function vsCodeGetRouterReflection(\Illuminate\Routing\Route $route)
|
||||
{
|
||||
if ($route->getActionName() === 'Closure') {
|
||||
return new \ReflectionFunction($route->getAction()['uses']);
|
||||
}
|
||||
|
||||
if (!str_contains($route->getActionName(), '@')) {
|
||||
return new \ReflectionClass($route->getActionName());
|
||||
}
|
||||
|
||||
try {
|
||||
return new \ReflectionMethod($route->getControllerClass(), $route->getActionMethod());
|
||||
} catch (\Throwable $e) {
|
||||
$namespace = app(\Illuminate\Routing\UrlGenerator::class)->getRootControllerNamespace()
|
||||
?? (app()->getNamespace() . 'Http\Controllers');
|
||||
|
||||
return new \ReflectionMethod(
|
||||
$namespace . '\\' . ltrim($route->getControllerClass(), '\\'),
|
||||
$route->getActionMethod(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return collect(app('router')->getRoutes()->getRoutes())
|
||||
->map(function (\Illuminate\Routing\Route $route) {
|
||||
try {
|
||||
$reflection = vsCodeGetRouterReflection($route);
|
||||
} catch (\Throwable $e) {
|
||||
$reflection = null;
|
||||
}
|
||||
|
||||
return [
|
||||
'method' => collect($route->methods())->filter(function ($method) {
|
||||
return $method !== 'HEAD';
|
||||
})->implode('|'),
|
||||
'uri' => $route->uri(),
|
||||
'name' => $route->getName(),
|
||||
'action' => $route->getActionName(),
|
||||
'parameters' => $route->parameterNames(),
|
||||
'filename' => $reflection ? $reflection->getFileName() : null,
|
||||
'line' => $reflection ? $reflection->getStartLine() : null,
|
||||
];
|
||||
})
|
||||
;
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
function vsCodeFindBladeFiles($path)
|
||||
{
|
||||
$paths = [];
|
||||
|
||||
if (!is_dir($path)) {
|
||||
return $paths;
|
||||
}
|
||||
|
||||
foreach (
|
||||
\Symfony\Component\Finder\Finder::create()
|
||||
->files()
|
||||
->name("*.blade.php")
|
||||
->in($path)
|
||||
as $file
|
||||
) {
|
||||
$paths[] = [
|
||||
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $file->getRealPath()),
|
||||
"isVendor" => str_contains($file->getRealPath(), base_path("vendor")),
|
||||
"key" => \Illuminate\Support\Str::of($file->getRealPath())
|
||||
->replace(realpath($path), "")
|
||||
->replace(".blade.php", "")
|
||||
->ltrim(DIRECTORY_SEPARATOR)
|
||||
->replace(DIRECTORY_SEPARATOR, ".")
|
||||
];
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
$paths = collect(
|
||||
app("view")
|
||||
->getFinder()
|
||||
->getPaths()
|
||||
)->flatMap(function ($path) {
|
||||
return vsCodeFindBladeFiles($path);
|
||||
});
|
||||
|
||||
$hints = collect(
|
||||
app("view")
|
||||
->getFinder()
|
||||
->getHints()
|
||||
)->flatMap(function ($paths, $key) {
|
||||
return collect($paths)->flatMap(function ($path) use ($key) {
|
||||
return collect(vsCodeFindBladeFiles($path))->map(function ($value) use (
|
||||
$key
|
||||
) {
|
||||
return array_merge($value, ["key" => "{$key}::{$value["key"]}"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[$local, $vendor] = $paths
|
||||
->merge($hints)
|
||||
->values()
|
||||
->partition(function ($v) {
|
||||
return !$v["isVendor"];
|
||||
});
|
||||
|
||||
return $local
|
||||
->sortBy("key", SORT_NATURAL)
|
||||
->merge($vendor->sortBy("key", SORT_NATURAL));
|
||||
@@ -21,6 +21,14 @@ namespace PHPSTORM_META {
|
||||
]));
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($configMethods as $method) : ?>
|
||||
override(<?= $method ?>, map([
|
||||
<?php foreach ($configValues as $name => $value) : ?>
|
||||
'<?= $name ?>' => '<?= $value ?>',
|
||||
<?php endforeach; ?>
|
||||
]));
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (count($factories)) : ?>
|
||||
override(\factory(0), map([
|
||||
'' => '@FactoryBuilder',
|
||||
@@ -65,14 +73,20 @@ namespace PHPSTORM_META {
|
||||
override(\tap(0), type(0));
|
||||
override(\optional(0), type(0));
|
||||
|
||||
<?php if (isset($expectedArgumentSets)): ?>
|
||||
<?php foreach ($expectedArgumentSets as $name => $argumentsList) : ?>
|
||||
registerArgumentsSet('<?= $name ?>', <?php foreach ($argumentsList as $i => $arg) : ?><?php if($i % 5 == 0) {
|
||||
echo "\n";
|
||||
} ?><?= var_export($arg, true); ?>,<?php endforeach; ?>);
|
||||
<?php endforeach; ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (isset($expectedArguments)) : ?>
|
||||
<?php foreach ($expectedArguments as $function => $arguments) : ?>
|
||||
<?php foreach ($arguments as $index => $argumentList) : ?>
|
||||
expectedArguments(\<?= $function ?>(), <?= $index ?>,<?php foreach ($argumentList as $i => $arg) : ?><?php if($i % 10 == 0) {
|
||||
echo "\n";
|
||||
} ?><?= var_export($arg, true); ?>,<?php endforeach; ?>
|
||||
);
|
||||
<?php foreach ($arguments as $index => $argumentSet) : ?>
|
||||
expectedArguments(<?= $function ?>, <?= $index ?>, argumentsSet('<?= $argumentSet ?>'));
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Config\Repository;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Collection;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@@ -64,6 +65,16 @@ class MetaCommand extends Command
|
||||
'\Psr\Container\ContainerInterface::get(0)',
|
||||
];
|
||||
|
||||
protected $configMethods = [
|
||||
'\config()',
|
||||
'\Illuminate\Config\Repository::get()',
|
||||
'\Illuminate\Config\Repository::set()',
|
||||
'\Illuminate\Support\Facades\Config::get()',
|
||||
'\Illuminate\Support\Facades\Config::set()',
|
||||
];
|
||||
|
||||
protected $templateCache = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Filesystem $files
|
||||
@@ -120,10 +131,17 @@ class MetaCommand extends Command
|
||||
|
||||
$this->unregisterClassAutoloadExceptions($ourAutoloader);
|
||||
|
||||
$configValues = $this->loadTemplate('configs')->pluck('value', 'name')->map(function ($value, $key) {
|
||||
return gettype($value);
|
||||
});
|
||||
|
||||
$content = $this->view->make('meta', [
|
||||
'bindings' => $bindings,
|
||||
'methods' => $this->methods,
|
||||
'factories' => $factories,
|
||||
'configMethods' => $this->configMethods,
|
||||
'configValues' => $configValues,
|
||||
'expectedArgumentSets' => $this->getExpectedArgumentSets(),
|
||||
'expectedArguments' => $this->getExpectedArguments(),
|
||||
])->render();
|
||||
|
||||
@@ -168,18 +186,49 @@ class MetaCommand extends Command
|
||||
return $autoloader;
|
||||
}
|
||||
|
||||
protected function getExpectedArgumentSets()
|
||||
{
|
||||
return [
|
||||
'configs' => $this->loadTemplate('configs')->pluck('name')->filter(),
|
||||
'routes' => $this->loadTemplate('routes')->pluck('name')->filter(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getExpectedArguments()
|
||||
{
|
||||
return [
|
||||
'config' => [
|
||||
0 => $this->getConfigHints(),
|
||||
'\config()' => [
|
||||
0 => 'configs',
|
||||
],
|
||||
'\Illuminate\Config\Repository::get()' => [
|
||||
0 => 'configs',
|
||||
],
|
||||
'\Illuminate\Config\Repository::set()' => [
|
||||
0 => 'configs',
|
||||
],
|
||||
'\Illuminate\Support\Facades\Config::get()' => [
|
||||
0 => 'configs',
|
||||
],
|
||||
'\Illuminate\Support\Facades\Config::set()' => [
|
||||
0 => 'configs',
|
||||
],
|
||||
'\route()' => [
|
||||
0 => 'routes',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function getConfigHints()
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
protected function loadTemplate($name)
|
||||
{
|
||||
return collect($this->config->all())->dot()->keys()->toArray();
|
||||
if (!isset($this->templates[$name])) {
|
||||
$file = __DIR__ . '/../../php-templates/' . basename($name) .'.php';
|
||||
$this->templates[$name] = $this->files->requireOnce($file);
|
||||
}
|
||||
|
||||
return $this->templates[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user