Handle preprocessor conditions inside classes

Also remove the dead parseClass() function.
This commit is contained in:
Nikita Popov 2019-08-10 16:28:57 +02:00
parent 9c02c58481
commit ae721c488d

View file

@ -194,17 +194,32 @@ function parseFunctionLike(string $name, Node\FunctionLike $func, ?string $cond)
return new FuncInfo($name, $args, $return, $numRequiredArgs, $cond); return new FuncInfo($name, $args, $return, $numRequiredArgs, $cond);
} }
function parseClass(Stmt\Class_ $class): ClassInfo { function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string {
$funcs = []; foreach ($stmt->getComments() as $comment) {
$className = $class->name->toString(); $text = trim($comment->getText());
foreach ($class as $stmt) { if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) {
if (!$stmt instanceof Stmt\ClassMethod) { $conds[] = $matches[1];
throw new Exception("Not implemented class statement"); } else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) {
$conds[] = "defined($matches[1])";
} else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) {
$conds[] = "!defined($matches[1])";
} else if (preg_match('/^#\s*else$/', $text)) {
if (empty($conds)) {
throw new Exception("Encountered else without corresponding #if");
}
$cond = array_pop($conds);
$conds[] = "!($cond)";
} else if (preg_match('/^#\s*endif$/', $text)) {
if (empty($conds)) {
throw new Exception("Encountered #endif without corresponding #if");
}
array_pop($conds);
} else if ($text[0] === '#') {
throw new Exception("Unrecognized preprocessor directive \"$text\"");
} }
$funcs[] = parseFunctionLike($className . '_' . $stmt->name->toString(), $stmt);
} }
return new ClassInfo($className, $funcs);
return empty($conds) ? null : implode(' && ', $conds);
} }
/** @return FuncInfo[] */ /** @return FuncInfo[] */
@ -226,32 +241,7 @@ function parseStubFile(string $fileName) {
$funcInfos = []; $funcInfos = [];
$conds = []; $conds = [];
foreach ($stmts as $stmt) { foreach ($stmts as $stmt) {
foreach ($stmt->getComments() as $comment) { $cond = handlePreprocessorConditions($conds, $stmt);
$text = trim($comment->getText());
if (preg_match('/^#\s*if\s+(.+)$/', $text, $matches)) {
$conds[] = $matches[1];
} else if (preg_match('/^#\s*ifdef\s+(.+)$/', $text, $matches)) {
$conds[] = "defined($matches[1])";
} else if (preg_match('/^#\s*ifndef\s+(.+)$/', $text, $matches)) {
$conds[] = "!defined($matches[1])";
} else if (preg_match('/^#\s*else$/', $text)) {
if (empty($conds)) {
throw new Exception("Encountered else without corresponding #if");
}
$cond = array_pop($conds);
$conds[] = "!($cond)";
} else if (preg_match('/^#\s*endif$/', $text)) {
if (empty($conds)) {
throw new Exception("Encountered #endif without corresponding #if");
}
array_pop($conds);
} else if ($text[0] === '#') {
throw new Exception("Unrecognized preprocessor directive \"$text\"");
}
}
$cond = empty($conds) ? null : implode(' && ', $conds);
if ($stmt instanceof Stmt\Nop) { if ($stmt instanceof Stmt\Nop) {
continue; continue;
} }
@ -264,6 +254,7 @@ function parseStubFile(string $fileName) {
if ($stmt instanceof Stmt\ClassLike) { if ($stmt instanceof Stmt\ClassLike) {
$className = $stmt->name->toString(); $className = $stmt->name->toString();
foreach ($stmt->stmts as $classStmt) { foreach ($stmt->stmts as $classStmt) {
$cond = handlePreprocessorConditions($conds, $classStmt);
if ($classStmt instanceof Stmt\Nop) { if ($classStmt instanceof Stmt\Nop) {
continue; continue;
} }