Skip to content

Commit

Permalink
Use docblock builder
Browse files Browse the repository at this point in the history
  • Loading branch information
barryvdh committed Feb 18, 2024
1 parent 127c9dc commit c223665
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 133 deletions.
18 changes: 5 additions & 13 deletions src/Alias.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@

namespace Barryvdh\LaravelIdeHelper;

use Barryvdh\LaravelIdeHelper\DocBlock\DocBlockBuilder;
use Closure;
use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Support\Facades\Facade;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Serializer;
use phpDocumentor\Reflection\DocBlock\Tags\Method as MethodTag;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\Types\Context;
use ReflectionClass;
use Throwable;
Expand Down Expand Up @@ -87,11 +87,8 @@ public function __construct($config, $alias, $facade, $magicMethods = [], $inter
//Create a DocBlock
$this->phpdocContext = new Context($this->namespace, $this->classAliases);
$reflector = new ReflectionClass($alias);
if ($reflector->getDocComment()) {
$this->phpdoc = (DocBlockFactory::createInstance())->create($reflector, $this->phpdocContext);
} else {
$this->phpdoc = new DocBlock('', null, [], $this->phpdocContext);
}

$this->phpdoc = DocBlockBuilder::createFromReflector($reflector, $this->phpdocContext);
}

if ($facade === '\Illuminate\Database\Eloquent\Model') {
Expand Down Expand Up @@ -440,18 +437,13 @@ public function getDocComment($prefix = "\t\t")
// we can perform reflection on the class and
// add in the original class DocBlock
if (count($this->phpdoc->getTags()) === 0) {

$reflector = new ReflectionClass($this->root);
if ($reflector->getDocComment()) {
$this->phpdoc = (DocBlockFactory::createInstance())->create($reflector, $this->phpdocContext);
} else {
$this->phpdoc = new DocBlock('', null, [], $this->phpdocContext);
}
$this->phpdoc = DocBlockBuilder::createFromReflector($reflector, $this->phpdocContext);
}
}

$this->removeDuplicateMethodsFromPhpDoc();
return $serializer->getDocComment($this->phpdoc);
return $serializer->getDocComment($this->phpdoc->getDocBlock());
}

/**
Expand Down
86 changes: 29 additions & 57 deletions src/Console/ModelsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Barryvdh\LaravelIdeHelper\Console;

use Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface;
use Barryvdh\LaravelIdeHelper\TypeResolver\LocalFsqenResolver;
use Barryvdh\LaravelIdeHelper\DocBlock\DocBlockBuilder;
use Composer\ClassMapGenerator\ClassMapGenerator;
use Illuminate\Console\Command;
use Illuminate\Contracts\Database\Eloquent\Castable;
Expand All @@ -39,15 +39,10 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Serializer;
use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\TagFactory;
use phpDocumentor\Reflection\DocBlock\Tags\BaseTag;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\ContextFactory;
use ReflectionClass;
use ReflectionNamedType;
Expand Down Expand Up @@ -893,29 +888,25 @@ protected function createPhpDocs($class)
$reflection->getParentClass()->getInterfaceNames()
);
$phpDocContext = (new ContextFactory())->createFromReflector($reflection);
$tagFactory = $this->getTagFactory();

$existingTags = [];
$tags = [];
$summary = $class;
$description = null;

if ($reflection->getDocComment()) {
$phpdoc = (DocBlockFactory::createInstance())->create($reflection, $phpDocContext);
$existingTags = $phpdoc->getTags();
if (!$this->reset || $this->keep_text) {
$summary = $phpdoc->getSummary();
$description = $phpdoc->getDescription();
}
$phpdoc = DocBlockBuilder::createFromReflector($reflection, $phpDocContext);

if (!$this->reset) {
$tags = $existingTags;
if ($this->reset) {
$phpdoc->clearTags();
if (!$this->keep_text) {
$phpdoc->setSummary('');
$phpdoc->setDescription(null);
}
}

// Set default summary to classname
if (!$phpdoc->getSummary()) {
$phpdoc->setSummary($class);
}

$existingTags = $phpdoc->getTags();
$properties = [];
$methods = [];
foreach ($tags as $tag) {
foreach ($phpdoc->getTags() as $tag) {
$name = $tag->getName();
if ($name == 'property' || $name == 'property-read' || $name == 'property-write') {
$properties[] = $tag->getVariableName();
Expand Down Expand Up @@ -944,7 +935,7 @@ protected function createPhpDocs($class)

$tagLine = trim("@{$attr} {$property['type']} {$name} {$property['comment']}");

$tags[] = $tagFactory->create($tagLine, $phpDocContext);
$phpdoc->appendTagline($tagLine);
}

ksort($this->methods);
Expand All @@ -958,27 +949,27 @@ protected function createPhpDocs($class)
if ($method['comment'] !== '') {
$tagLine .= " {$method['comment']}";
}
$tags[] = $tagFactory->create($tagLine, $phpDocContext);

$phpdoc->appendTagline($tagLine);
}

if ($this->write) {
$eloquentClassNameInModel = $this->getClassNameInDestinationFile($reflection, 'Eloquent');

$tags[] = $tagFactory->create('@mixin ' . $eloquentClassNameInModel, $phpDocContext);
$phpdoc->appendTagline('@mixin ' . $eloquentClassNameInModel);
}

if ($this->phpstorm_noinspections) {
/**
* Facades, Eloquent API
* @see https://www.jetbrains.com/help/phpstorm/php-fully-qualified-name-usage.html
*/
$tags[] = $tagFactory->create('@noinspection PhpFullyQualifiedNameUsageInspection', $phpDocContext);

$phpdoc->appendTagline('@noinspection PhpFullyQualifiedNameUsageInspection');
/**
* Relations, other models in the same namespace
* @see https://www.jetbrains.com/help/phpstorm/php-unnecessary-fully-qualified-name.html
*/
$tags[] = $tagFactory->create('@noinspection PhpUnnecessaryFullyQualifiedNameInspection', $phpDocContext);
$phpdoc->appendTagline('@noinspection PhpUnnecessaryFullyQualifiedNameInspection');
}

$serializer = new Serializer();
Expand All @@ -989,31 +980,24 @@ protected function createPhpDocs($class)
return !($tag instanceof BaseTag) || !Str::startsWith($tag->getDescription(), 'IdeHelper');
});

$phpdocMixin = DocBlockBuilder::create($phpdoc->getSummary(), $phpdoc->getDescription(), $mixinTags, $phpDocContext);
$mixinClassName = "IdeHelper{$classname}";
$mixinTags[] = $tagFactory->create("@mixin {$mixinClassName}", $phpDocContext);
$phpdocMixin->appendTagline("@mixin {$mixinClassName}");

$tags = array_filter($tags, function (Tag $tag) {
return !($tag instanceof BaseTag) || !Str::startsWith($tag->getDescription(), 'IdeHelper');
});
foreach ($phpdoc->getTags() as $tag) {
if ($tag instanceof BaseTag && Str::startsWith($tag->getDescription(), 'IdeHelper')) {
$phpdoc->removeTag($tag);
}
}

$phpdocMixin = new DocBlock($summary ?: $class, $description, $mixinTags, $phpDocContext);
$mixinDocComment = $serializer->getDocComment($phpdocMixin);
$mixinDocComment = $serializer->getDocComment($phpdocMixin->getDocBlock());
// remove blank lines if there's no text
if (!$phpdocMixin->getSummary()) {
$mixinDocComment = preg_replace("/\s\*\s*\n/", '', $mixinDocComment);
}
}

$tags = collect($tags)->unique(function (Tag $tag) {
if (method_exists($tag, 'getVariableName')) {
return $tag->getName() . ' ' . $tag->getVariableName();
}
return (string) $tag;

})->toArray();

$phpdoc = new DocBlock($summary ?: '', $description, $tags, $phpDocContext);
$docComment = $serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc->getDocBlock());

if ($this->write) {
$modelDocComment = $this->write_mixin ? $mixinDocComment : $docComment;
Expand Down Expand Up @@ -1050,18 +1034,6 @@ protected function createPhpDocs($class)
return $output . "{}\n}\n\n";
}

private function getTagFactory(): TagFactory
{
$fqsenResolver = new LocalFsqenResolver();
$tagFactory = new StandardTagFactory($fqsenResolver);
$descriptionFactory = new DescriptionFactory($tagFactory);

$tagFactory->addService($descriptionFactory);
$tagFactory->addService(new TypeResolver($fqsenResolver));

return $tagFactory;
}

/**
* Get the parameters and format them correctly
*
Expand Down
141 changes: 141 additions & 0 deletions src/DocBlock/DocBlockBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace Barryvdh\LaravelIdeHelper\DocBlock;

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\TagFactory;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;

class DocBlockBuilder
{
/** @var $tagFactory TagFactory */
private $tagFactory = null;

private function __construct(
protected string $summary = '',
protected ?DocBlock\Description $description = null,
protected array $tags = [],
protected ?Context $context = null
) {
}

public static function createFromReflector(\Reflector $reflector, ?Context $context = null): static
{
if ($doc = $reflector->getDocComment()) {
$docblock = DocBlockFactory::createInstance()->create($doc, $context);

return new static(
$docblock->getSummary(),
$docblock->getDescription(),
$docblock->getTags(),
$docblock->getContext()
);
}

return static::create('', null, [], $context);
}

public static function create(
string $summary = '',
?DocBlock\Description $description = null,
array $tags = null,
?Context $context = null
): static {
return new static($summary, $description, $tags, $context);
}

public function getDocBlock(): DocBlock
{
$tags = collect($this->tags)->unique(function (Tag $tag) {
if (method_exists($tag, 'getVariableName')) {
return $tag->getName() . ' ' . $tag->getVariableName();
}
return (string) $tag;
})->toArray();

return new DocBlock($this->summary, $this->description, $tags, $this->context);
}

public function getSummary(): ?string
{
return $this->summary;
}

public function setSummary(string $summary)
{
$this->summary = $summary;
}

public function getDescription(): ?DocBlock\Description
{
return $this->description;
}

public function setDescription(?DocBlock\Description $description)
{
$this->description = $description;
}

public function getTags()
{
return $this->tags;
}

public function appendTagline(string $tagline)
{
$tag = $this->getTagFactory()->create($tagline, $this->context);

$this->appendTag($tag);
}

public function hasTag(string $name): bool
{
foreach ($this->tags as $tag) {
if ($tag->getName() === $name) {
return true;
}
}

return false;
}

public function appendTag(Tag $tag)
{
$this->tags[] = $tag;
}

public function removeTag(Tag $tagToRemove)
{
foreach ($this->tags as $i => $tag) {
if ($tag === $tagToRemove) {
unset($this->tags[$i]);
break;
}
}
}

public function clearTags()
{
$this->tags = [];
}

private function getTagFactory(): TagFactory
{
if ($this->tagFactory === null) {
$fqsenResolver = new LocalFsqenResolver();
$tagFactory = new StandardTagFactory($fqsenResolver);
$descriptionFactory = new DescriptionFactory($tagFactory);

$tagFactory->addService($descriptionFactory);
$tagFactory->addService(new TypeResolver($fqsenResolver));

$this->tagFactory = $tagFactory;
}
return $this->tagFactory;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Barryvdh\LaravelIdeHelper\TypeResolver;
namespace Barryvdh\LaravelIdeHelper\DocBlock;

use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\FqsenResolver;
Expand Down
Loading

0 comments on commit c223665

Please sign in to comment.