Browse files

Merge remote-tracking branch 'vicb/classmap'

  • Loading branch information...
2 parents 1726fd4 + 86bb1be commit 8a0c8560b7449869722733f50e567ce252ab6369 @Seldaek Seldaek committed Nov 12, 2012
View
97 src/Composer/Autoload/ClassMapGenerator.php
@@ -40,42 +40,49 @@ public static function dump($dirs, $file)
/**
* Iterate over all files in the given directory searching for classes
*
- * @param Iterator|string $dir The directory to search in or an iterator
+ * @param Iterator|string $path The path to search in or an iterator
* @param string $whitelist Regex that matches against the file path
*
* @return array A class map array
+ *
+ * @throws \RuntimeException When the path is neither an existing file nor directory
*/
- public static function createMap($dir, $whitelist = null)
+ public static function createMap($path, $whitelist = null)
{
- if (is_string($dir)) {
- if (is_file($dir)) {
- $dir = array(new \SplFileInfo($dir));
+ if (is_string($path)) {
+ if (is_file($path)) {
+ $path = array(new \SplFileInfo($path));
+ } else if (is_dir($path)) {
+ $path = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
} else {
- $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
+ throw new \RuntimeException(
+ 'Could not scan for classes inside "'.$path.
+ '" which does not appear to be a file nor a folder'
+ );
}
}
$map = array();
- foreach ($dir as $file) {
+ foreach ($path as $file) {
if (!$file->isFile()) {
continue;
}
- $path = $file->getRealPath();
+ $filePath = $file->getRealPath();
- if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
+ if (pathinfo($filePath, PATHINFO_EXTENSION) !== 'php') {
continue;
}
- if ($whitelist && !preg_match($whitelist, strtr($path, '\\', '/'))) {
+ if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) {
continue;
}
- $classes = self::findClasses($path);
+ $classes = self::findClasses($filePath);
foreach ($classes as $class) {
- $map[$class] = $path;
+ $map[$class] = $filePath;
}
}
@@ -96,38 +103,44 @@ private static function findClasses($path)
try {
$contents = php_strip_whitespace($path);
- if (!preg_match('{\b(?:class|interface'.$traits.')\b}i', $contents)) {
- return array();
- }
-
- // strip heredocs/nowdocs
- $contents = preg_replace('{<<<\'?(\w+)\'?(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\1(?=\r\n|\n|\r|;)}s', 'null', $contents);
- // strip strings
- $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}', 'null', $contents);
-
- preg_match_all('{
- (?:
- \b(?<![\$:>])(?<type>class|interface'.$traits.') \s+ (?<name>\S+)
- | \b(?<![\$:>])(?<ns>namespace) (?<nsname>\s+[^\s;{}\\\\]+(?:\s*\\\\\s*[^\s;{}\\\\]+)*)? \s*[\{;]
- )
- }ix', $contents, $matches);
- $classes = array();
-
- $namespace = '';
-
- for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
- $name = $matches['name'][$i];
-
- if (!empty($matches['ns'][$i])) {
- $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
- } else {
- $classes[] = ltrim($namespace . $matches['name'][$i], '\\');
- }
- }
-
- return $classes;
} catch (\Exception $e) {
throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e);
}
+
+ // strip heredocs/nowdocs
+ $contents = preg_replace('{<<<\'?(\w+)\'?(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\1(?=\r\n|\n|\r|;)}s', 'null', $contents);
+ // strip strings
+ $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}', 'null', $contents);
+ // keep only php code
+ $phpContents = preg_match_all('{<\?(?:php)?(.*)\?>}s', $contents, $m) ? join($m[1], ' ') : '';
+ $contents = preg_replace('{<\?(php)?.*\?>}s', '', $contents);
+ if (preg_match('{<\?(?:php)?(.*)}s', $contents, $m)) {
+ $phpContents .= ' ' . $m[1];
+ }
+
+ if (!preg_match('{\b(?:class|interface'.$traits.')\b}i', $phpContents)) {
+ return array();
+ }
+
+ preg_match_all('{
+ (?:
+ \b(?<![\$:>])(?<type>class|interface'.$traits.') \s+ (?<name>\S+)
+ | \b(?<![\$:>])(?<ns>namespace) (?<nsname>\s+[^\s;{}\\\\]+(?:\s*\\\\\s*[^\s;{}\\\\]+)*)? \s*[\{;]
+ )
+ }ix', $phpContents, $matches);
+ $classes = array();
+
+ $namespace = '';
+
+ for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+ if (!empty($matches['ns'][$i])) {
+ $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+ } else {
+ $classes[] = ltrim($namespace . $matches['name'][$i], '\\');
+ }
+ }
+
+ return $classes;
+
}
}
View
23 tests/Composer/Test/Autoload/ClassMapGeneratorTest.php
@@ -53,6 +53,7 @@ public function getTestCreateMapTests()
'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php',
'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php',
)),
+ array(__DIR__.'/Fixtures/template', array()),
);
if (version_compare(PHP_VERSION, '5.4', '>=')) {
@@ -84,6 +85,28 @@ public function testCreateMapFinderSupport()
), ClassMapGenerator::createMap($finder));
}
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Could not scan for classes inside
+ */
+ public function testFindClassesThrowsWhenFileDoesNotExist()
+ {
+ $r = new \ReflectionClass('Composer\\Autoload\\ClassMapGenerator');
+ $find = $r->getMethod('findClasses');
+ $find->setAccessible(true);
+
+ $find->invoke(null, __DIR__.'/no-file');
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Could not scan for classes inside
+ */
+ public function testCreateMapThrowsWhenDirectoryDoesNotExist()
+ {
+ ClassMapGenerator::createMap(__DIR__.'/no-file.no-foler');
+ }
+
protected function assertEqualsNormalized($expected, $actual, $message = null)
{
foreach ($expected as $ns => $path) {
View
6 tests/Composer/Test/Autoload/Fixtures/template/template_1.php
@@ -0,0 +1,6 @@
+/*
+ * class templateClass_1
+ * interface templateInterface_1
+ * trait temlpateTrait_1
+ */
+<?php echo $code
View
8 tests/Composer/Test/Autoload/Fixtures/template/template_2.php
@@ -0,0 +1,8 @@
+/*
+ * class templateClass_2
+ * interface templateInterface_2
+ * trait temlpateTrait_2
+ */
+<?php
+ echo $code
+?>

0 comments on commit 8a0c856

Please sign in to comment.