Skip to content

Commit

Permalink
Refactor parsing subsystem and clean up code and responsibilities qui…
Browse files Browse the repository at this point in the history
…te a bit
  • Loading branch information
theseer committed Aug 5, 2014
1 parent 3c746a7 commit 1d5c545
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 210 deletions.
19 changes: 7 additions & 12 deletions src/Application.php
Expand Up @@ -50,11 +50,11 @@ public function __construct(Logger $logger, Config $config, Factory $factory) {
}

public function run() {
$finder = $this->runCollector();
if ($finder->getCount() == 0) {
$result = $this->runCollector();
if (!$result->hasUnits()) {
throw new ApplicationException("No classes were found - process aborted.", ApplicationException::NoUnitsFound);
}
$builder = $this->factory->getRenderer($finder);
$builder = $this->factory->getRenderer($result);
$code = $builder->render(file_get_contents($this->config->getTemplate()));
if ($this->config->isLintMode()) {
return $this->runLint($code);
Expand All @@ -63,26 +63,21 @@ public function run() {
}

/**
* @return Finder
* @return CollectorResult
*/
private function runCollector() {
$finder = $this->factory->getFinder();
$basedir = $this->config->getBaseDirectory();
$trusting = $this->config->isTrustingMode();
if ($this->config->isFollowSymlinks()) {
$this->logger->log('Following symbolic links is enabled.' . "\n\n");
}
$collector = $this->factory->getCollector();
foreach ($this->config->getDirectories() as $directory) {
$this->logger->log('Scanning directory ' . $directory . "\n");
if ($basedir == NULL) {
$basedir = $directory;
}
$scanner = $this->factory->getScanner()->getIterator($directory);
$finder->parseMulti($scanner, !$trusting);
$collector->addDirectory($scanner);
// this unset is needed to "fix" a segfault on shutdown in some PHP Versions
unset($scanner);
}
return $finder;
return $collector->getResult();
}

private function runSaver($code) {
Expand Down
84 changes: 84 additions & 0 deletions src/Collector.php
@@ -0,0 +1,84 @@
<?php
namespace TheSeer\Autoload {

use TheSeer\DirectoryScanner\PHPFilterIterator;

class Collector {

/**
* @var Parser
*/
private $parser;

/**
* @var CollectorResult
*/
private $collectorResult;

/**
* @var bool
*/
private $toleranceMode;

/**
* @var bool
*/
private $mimeCheck;

/**
* @param Parser $parser
* @param bool $toleranceMode
* @param bool $mimeCheck
*/
public function __construct(Parser $parser, $toleranceMode = false, $mimeCheck = false) {
$this->parser = $parser;
$this->toleranceMode = $toleranceMode;
$this->mimeCheck = $mimeCheck;
$this->collectorResult = new CollectorResult();
}

public function getResult() {
return $this->collectorResult;
}

public function addDirectory(\Iterator $sources) {
$worker = $this->mimeCheck ? new PHPFilterIterator($sources) : $sources;
foreach($worker as $file) {
try {
$parseResult = $this->parser->parse(new SourceFile($file->getRealpath()));
if ($parseResult->hasRedeclarations() && !$this->toleranceMode) {
throw new CollectorException(
sprintf(
'The file "%s" conains duplicate (potentially conditional) definitions of the following unit(s): %s',
$file->getRealPath(),
join(', ', $parseResult->getRedeclarations())
),
CollectorException::InFileRedeclarationFound
);
}
$this->collectorResult->addParseResult($file, $parseResult);
} catch(ParserException $e) {
throw new CollectorException(
sprintf(
'Could not process file "%s" due to parse errors',
$file->getRealPath()
),
CollectorException::ParseErrror,
$e
);
} catch(CollectorResultException $e) {
throw new CollectorException(
$e->getMessage(),
CollectorException::RedeclarationFound
);
}
}
}
}

class CollectorException extends \Exception {
const ParseErrror = 1;
const RedeclarationFound = 2;
const InFileRedeclarationFound = 3;
}
}
55 changes: 55 additions & 0 deletions src/CollectorResult.php
@@ -0,0 +1,55 @@
<?php
namespace TheSeer\Autoload {

class CollectorResult {

private $units = array();
private $dependencies = array();

public function addParseResult(\SplFileInfo $file, ParseResult $result) {
if (!$result->hasUnits()) {
return;
}
$filename = $file->getRealPath();
foreach($result->getUnits() as $unit) {
if (isset($this->units[$unit])) {
throw new CollectorResultException(
sprintf(
'Redeclaration of unit "%s" in file "%s" (first occurance was in file "%s")',
$unit,
$filename,
$this->units[$unit]
),
CollectorResultException::DuplicateUnitName
);
}
$this->units[$unit] = $filename;
$this->dependencies[$unit] = $result->getDependenciesForUnit($unit);
}

}

public function hasUnits() {
return count($this->units) > 0;
}

/**
* @return array
*/
public function getDependencies() {
return $this->dependencies;
}

/**
* @return array
*/
public function getUnits() {
return $this->units;
}
}

class CollectorResultException extends \Exception {
const DuplicateUnitName = 1;
}

}
28 changes: 17 additions & 11 deletions src/Factory.php
Expand Up @@ -70,17 +70,23 @@ public function getLogger() {
}

/**
* @return ClassFinder
* @return Parser
*/
public function getFinder() {
return new ClassFinder(
$this->config->isStaticMode(),
$this->config->isTolerantMode(),
!$this->config->isLowercaseMode()
public function getParser() {
return new Parser(
$this->config->isLowercaseMode()
);
}


public function getCollector() {
return new Collector(
$this->getParser(),
$this->config->isTolerantMode(),
$this->config->isTrustingMode()
);
}

/**
* Get instance of DirectoryScanner with filter options applied
*
Expand All @@ -94,7 +100,7 @@ public function getScanner($filter = TRUE) {
$scanner->setExcludes($this->config->getExclude());
}
if ($this->config->isFollowSymlinks()) {
$scanner->setFollowSymlinks(TRUE);
$scanner->setFlag(\FilesystemIterator::FOLLOW_SYMLINKS);
}
return $scanner;
}
Expand All @@ -119,19 +125,19 @@ public function getPharBuilder() {
* @throws \RuntimeException
* @return \TheSeer\Autoload\AutoloadRenderer|\TheSeer\Autoload\StaticRenderer
*/
public function getRenderer(ClassFinder $finder) {
public function getRenderer(CollectorResult $result) {
$isStatic = $this->config->isStaticMode();
$isPhar = $this->config->isPharMode();
$isCompat = $this->config->isCompatMode();
$isOnce = $this->config->isOnceMode();

if ($isStatic === TRUE) {
$renderer = new StaticRenderer($finder->getMerged());
$renderer->setDependencies($finder->getDependencies());
$renderer = new StaticRenderer($result->getUnits());
$renderer->setDependencies($result->getDependencies());
$renderer->setPharMode($isPhar);
$renderer->setRequireOnce($isOnce);
} else {
$renderer = new AutoloadRenderer($finder->getMerged());
$renderer = new AutoloadRenderer($result->getUnits());
}

$renderer->setCompat($isCompat);
Expand Down
61 changes: 61 additions & 0 deletions src/ParseResult.php
@@ -0,0 +1,61 @@
<?php
namespace TheSeer\Autoload {

class ParseResult {

/**
* @var string[]
*/
private $units = array();

/**
* @var array
*/
private $dependencies = array();

/**
* @var string[]
*/
private $redeclarations = array();

public function __construct(Array $units, Array $dependencies, Array $redeclarations) {
$this->units = $units;
$this->dependencies = $dependencies;
$this->redeclarations = $redeclarations;
}

public function hasUnits() {
return count($this->units) > 0;
}

public function hasRedeclarations() {
return count($this->redeclarations) > 0;
}

/**
* @return array
*/
public function getDependenciesForUnit($unit) {
if (!isset($this->dependencies[$unit])) {
return array();
}
return $this->dependencies[$unit];
}

/**
* @return \string[]
*/
public function getRedeclarations() {
return $this->redeclarations;
}

/**
* @return \string[]
*/
public function getUnits() {
return $this->units;
}

}

}

0 comments on commit 1d5c545

Please sign in to comment.