Skip to content

Instantly share code, notes, and snippets.

@thekid
Created September 20, 2020 23:05
Show Gist options
  • Select an option

  • Save thekid/0b2b355ab8780cdf774c25be35997978 to your computer and use it in GitHub Desktop.

Select an option

Save thekid/0b2b355ab8780cdf774c25be35997978 to your computer and use it in GitHub Desktop.
Convert XP annotations to PHP 8 attributes
<?php namespace unittest;
use io\collections\iterate\{FilteredIOCollectionIterator, ExtensionEqualsFilter} from 'xp-framework/io-collections';
use io\collections\{FileCollection, FileElement} from 'xp-framework/io-collections';
use io\streams\LinesIn;
use util\cmd\Console;
function import(string $line): iterable {
$p= strrpos($line, '\\');
$namespace= substr($line, 4, $p - 4);
if ('{' === $line[$p + 1]) {
yield $namespace => preg_split('/, ?/', substr($line, $p + 2, -2));
} else {
yield $namespace => [substr($line, $p + 1, -1)];
}
}
function rewrite(FileElement $origin, FileElement $target): FileElement {
$out= '';
$annotation= null;
$pos= null;
$imports= [];
foreach (new LinesIn($origin->in()) as $line) {
// Remember position of first import
if (0 === strncmp($line, 'use ', 4)) {
$pos ??= strlen($out);
foreach (import($line) as $ns => $classes) {
foreach ($classes as $name) {
$imports[$ns][$name]= 0;
}
}
continue;
}
// Fold XP annotations into a single line
if (preg_match('/^\s+#(\[@.+)/', $line)) {
$annotation= $line;
} else if (null === $annotation) {
$out.= $line."\n";
} else if (preg_match('/^\s+#\s+(.+)/', $line, $matches)) {
$annotation.= $matches[1].' ';
} else if (preg_match('/^\s+#(.+)/', $line, $matches)) {
$annotation= rtrim($annotation, ' ').$matches[1];
} else {
$replace= function($match) use(&$imports) {
$type= ucfirst($match[2]);
$imports['unittest'][$type]= 1;
return $match[1].$type;
};
$out.= preg_replace_callback('/(\[|, )@([^,\(\]]+)/', $replace, $annotation)."\n".$line."\n";
$annotation= null;
}
}
// Recreate use statements
$use= [];
foreach ($imports as $namespace => $classes) {
if (1 === sizeof($classes)) {
$use[]= 'use '.$namespace.'\\'.key($classes).';';
} else {
ksort($classes);
$use[]= 'use '.$namespace.'\\{'.implode(', ', array_keys($classes)).'};';
}
}
sort($use);
// Insert imports at remembered position
if ($use) {
$target->out()->write(substr($out, 0, $pos).implode("\n", $use)."\n".substr($out, $pos, -1));
} else {
$target->out()->write($out);
}
return $target;
}
$src= new FilteredIOCollectionIterator(
new FileCollection($argv[1] ?? 'src'),
new ExtensionEqualsFilter(\xp::CLASS_FILE_EXT),
true
);
foreach ($src as $file) {
Console::write('> ', $file->getURI(), ': ');
$target= rewrite($file, $file->getOrigin()->newElement('.rewrite'));
rename($target->getURI(), $file->getURI());
Console::writeLine('OK');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment