function convert_file($path, $outDir, $log)
{
    global $out_dir;
    $lines = array_map('rtrim', file($path));
    try {
        $descriptor = phpMorphy_Generator_PhpFileParser::parseFile($path);
    } catch (Exception $e) {
        throw new phpMorphy_Exception("Can`t parse '{$path}': " . $e->getMessage());
    }
    if (count($descriptor->classes) < 1) {
        return;
    }
    $first_class = $descriptor->classes[0];
    $first_significant_line = null === $first_class->phpDoc ? $first_class->startLine : $first_class->phpDoc->startLine;
    $header = array_slice($lines, 0, $first_significant_line - 1);
    $header = implode(PHP_EOL, $header);
    $out_files = array();
    $classes_count = count($descriptor->classes);
    foreach ($descriptor->classes as $class_descriptor) {
        $class_name = $class_descriptor->name;
        $out_path = $outDir . DIRECTORY_SEPARATOR . phpMorphy_Loader::classNameToFilePath($class_name);
        if ($out_path !== $path || $classes_count > 1) {
            $log("New class {$class_name}");
            $out_files[$out_path] = 1;
            $lines_count = $class_descriptor->endLine - $class_descriptor->startLine + 1;
            $content = implode(PHP_EOL, array_merge(array($header, @$class_descriptor->phpDoc->text), array_slice($lines, $class_descriptor->startLine - 1, $lines_count)));
            @mkdir(dirname($out_path), 0744, true);
            file_put_contents($out_path, $content);
        }
    }
    if (count($out_files) && !isset($out_files[$path])) {
        $log("Delete unused file {$path}");
        @unlink($path);
    }
}
 /**
  * @param string $outputDirectory
  * @return void
  */
 static function generate($outputDirectory)
 {
     $storage_ary = array('File', 'Mem', 'Shm');
     $tpl = new phpMorphy_Generator_Template(__DIR__ . '/GramInfo/tpl');
     $helper_class = "phpMorphy_Generator_TemplateHelper_Fsa";
     foreach ($storage_ary as $storage_name) {
         $storage_class = "phpMorphy_Generator_StorageHelper_" . ucfirst($storage_name);
         $helper = new phpMorphy_Generator_GramInfo_Helper($tpl, new $storage_class());
         $result = $tpl->get('graminfo', array('helper' => $helper));
         $file_path = $outputDirectory . DIRECTORY_SEPARATOR . phpMorphy_Loader::classNameToFilePath($helper->getClassName());
         @mkdir(dirname($file_path), 0744, true);
         file_put_contents($file_path, $result);
     }
 }
function generate_decorator($class, $decorator, $outDir, $log)
{
    $new_file_path = $outDir . DIRECTORY_SEPARATOR . phpMorphy_Loader::classNameToFilePath($decorator);
    $header = phpMorphy_Generator_Decorator_PhpDocHelper::parseHeaderPhpDoc(@file_get_contents($new_file_path));
    if (!$header->auto_regenerate && is_readable($new_file_path)) {
        $log("- Skip generating {$decorator} decorator (auto_regenerate disabled, or not exist)");
        return;
    }
    // try generate decorators on class
    $code = '<' . '?php' . PHP_EOL;
    $code .= phpMorphy_Generator_Decorator_Generator::generate($class, $decorator);
    @mkdir(dirname($new_file_path), 0744, true);
    file_put_contents($new_file_path, $code);
    $log("+ {$decorator} generated");
}
#!/usr/bin/env php
<?php 
if ($argc < 2) {
    die("Usage {$argv[0]} FILE [OUTPUT_DIR]");
}
set_include_path(__DIR__ . '/../../src/' . PATH_SEPARATOR . get_include_path());
require 'phpMorphy.php';
require 'PHPUnit/Util/File.php';
define('DEFAULT_TESTS_DIR', PHPMORPHY_DIR . '/../tests');
$phpunit_bin = '/usr/bin/env phpunit';
$phpunit_args = '--bootstrap ' . escapeshellarg(DEFAULT_TESTS_DIR . '/bootstrap.php');
$remove_class_prefix = 'phpMorphy_';
$input_file = (string) $argv[1];
$output_dir = $argc > 2 ? (string) $argv[2] : DEFAULT_TESTS_DIR . '/unit';
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
$output_dir = realpath($output_dir);
$output_dir = rtrim($output_dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$classes = PHPUnit_Util_File::getClassesInFile($input_file);
foreach ($classes as $class_name => $class_descriptor) {
    echo "==> Generate test for {$class_name} class\n";
    $stripped_class_name = substr($class_name, strlen($remove_class_prefix));
    $test_class_path = phpMorphy_Loader::classNameToFilePath($stripped_class_name);
    $test_file_path = $output_dir . preg_replace('/\\.php$/u', '', $test_class_path) . 'Test.php';
    $test_class_name = 'test_' . $stripped_class_name;
    $args = array('--skeleton-test', $class_name, $input_file, $test_class_name, $test_file_path);
    $cmd = $phpunit_bin . ' ' . ('' !== $phpunit_args ? $phpunit_args . ' ' : '') . implode(' ', array_map('escapeshellarg', $args));
    @mkdir(dirname($test_file_path));
    passthru($cmd);
}