Skip to content

Commit

Permalink
added services completion and type detection
Browse files Browse the repository at this point in the history
  • Loading branch information
mkusher committed Aug 11, 2015
1 parent 806482b commit 8496835
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 11 deletions.
24 changes: 24 additions & 0 deletions src/Completer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Mkusher\PadawanSymfony;

use Complete\Completer\CompleterInterface;
use Entity\Completion\Entry;
use Entity\Project;
use Entity\Completion\Context;

class Completer implements CompleterInterface
{
public function getEntries(Project $project, Context $context)
{
$services = $project->getPlugin('padawan-symfony');
return array_map(function ($serviceName) {
return new Entry(
sprintf('"%s"', $serviceName),
"",
"",
$serviceName
);
}, array_keys($services));
}
}
28 changes: 28 additions & 0 deletions src/IndexGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Mkusher\PadawanSymfony;

class IndexGenerator
{
public function handleAfterGenerationEvent($event)
{
$project = $event->getProject();
$output = [];
$container = [];
try {
exec(sprintf("%s/app/console container:debug", $project->getRootFolder()), $output);
$output = array_slice($output, 2);
array_pop($output);
foreach ($output as $containerStr) {
$service = explode(" ", $containerStr);
preg_match('/^\s*(\S*)\s*(\S*)$/i', $containerStr, $matches);
if ($matches && count($matches) === 3) {
$container[$matches[1]] = $matches[2];
}
}
$project->addPlugin('padawan-symfony', $container);
} catch (\Exception $e) {
return;
}
}
}
87 changes: 76 additions & 11 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,106 @@
use Symfony\Component\EventDispatcher\EventDispatcher;
use Complete\Resolver\NodeTypeResolver;
use Complete\CompleteEngine;
use Generator\IndexGenerator as Generator;
use Parser\UseParser;
use Entity\FQCN;
use Entity\Node\ClassData;

class Plugin
{
public function __construct(
EventDispatcher $dispatcher,
TypeResolver $resolver,
Completer $completer
Completer $completer,
IndexGenerator $generator
) {
$this->dispatcher = $dispatcher;
$this->resolver = $resolver;
$this->completer = $completer;
$this->generator = $generator;
$this->containerNames = [
'Symfony\\Component\\DependencyInjection\\Container',
'Symfony\\Component\\DependencyInjection\\ContainerInterface'
];
}

public function init()
{
//$this->dispatcher->addListener(
//NodeTypeResolver::BLOCK_START,
//[$this->resolver, 'handleParentTypeEvent']
//);
//$this->dispatcher->addListener(
//NodeTypeResolver::BLOCK_END,
//[$this->resolver, 'handleTypeResolveEvent']
//);
$this->dispatcher->addListener(
NodeTypeResolver::BLOCK_START,
[$this->resolver, 'handleParentTypeEvent']
);
$this->dispatcher->addListener(
'project.load',
[$this, 'handleProjectLoadEvent']
);
$this->dispatcher->addListener(
NodeTypeResolver::BLOCK_END,
[$this, 'handleTypeResolveEvent']
);
$this->dispatcher->addListener(
CompleteEngine::CUSTOM_COMPLETER,
[$this, 'handleCompleteEvent']
);
$this->dispatcher->addListener(
Generator::BEFORE_GENERATION,
[$this->generator, 'handleAfterGenerationEvent']
);
}

public function handleProjectLoadEvent($e)
{
$this->project = $e->project;
}

public function handleTypeResolveEvent($e)
{
$index = $this->project->getIndex();
if ($this->checkForContainerClass($this->resolver->getParentType(), $index)) {
$this->resolver->handleTypeResolveEvent($e, $this->project);
}
}
public function handleCompleteEvent($e)
{
$context = $e->context;
if ($context->isMethodCall()) {
list($type, $isThis, $types, $workingNode) = $context->getData();
$fqcn = array_pop($types);
printf("Symfony fqcn: %s\n", $fqcn->toString());
if ($this->checkForContainerClass(array_pop($types), $e->project->getIndex())) {
$e->completer = $this->completer;
}
}
}
protected function checkForContainerClass($fqcn, $index)
{
if (!$fqcn instanceof FQCN) {
return false;
}
if (in_array($fqcn->toString(), $this->containerNames)
&& $workingNode->name === 'get'
) {
return true;
}
$class = $index->findClassByFQCN($fqcn);
if (!$class instanceof ClassData) {
return false;
}
$parent = $class->getParent();
if ($parent instanceof FQCN) {
$parentFQCN = $parent;
}
if ($parent instanceof ClassData
&& $parent->fqcn instanceof FQCN
) {
$parentFQCN = $parent->fqcn;
}
if (empty($parentFQCN) || !$parentFQCN instanceof FQCN) {
return false;
}
$controller = 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller';
if ($parentFQCN->toString() === $controller) {
return true;
}
return false;
}

/** @var Completer */
Expand All @@ -52,4 +113,8 @@ public function handleCompleteEvent($e)
private $resolver;
/** @var EventDispatcher */
private $dispatcher;
/** @var IndexGenerator */
private $generator;
private $containerNames;
private $project;
}
41 changes: 41 additions & 0 deletions src/TypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,48 @@

namespace Mkusher\PadawanSymfony;

use Parser\UseParser;
use Complete\Resolver\TypeResolveEvent;
use Entity\FQCN;
use PhpParser\Node\Arg;
use PhpParser\Node\Scalar\String_;
use Entity\Project;

class TypeResolver
{
public function __construct(
UseParser $useParser
) {
$this->useParser = $useParser;
}

public function handleParentTypeEvent(TypeResolveEvent $e)
{
$this->parentType = $e->getType();
}

public function handleTypeResolveEvent(TypeResolveEvent $e, Project $project)
{
/** @var \Entity\Chain\MethodCall */
$chain = $e->getChain();
if ($chain->getType() === 'method' && count($chain->getArgs()) > 0) {
$firstArg = array_pop($chain->getArgs())->value;
if ($firstArg instanceof String_) {
$serviceName = $firstArg->value;
$container = $project->getPlugin("padawan-symfony");
if (array_key_exists($serviceName, $container)) {
$fqcn = $this->useParser->parseFQCN($container[$serviceName]);
$e->setType($fqcn);
}
}
}
}
public function getParentType()
{
return $this->parentType;
}

/** @var UseParser */
private $useParser;
private $parentType;
}

0 comments on commit 8496835

Please sign in to comment.