Permalink
Browse files

Fix reflection to correctly retrieve doc comments for generators

Calling the getDocComment() method on instances of ReflectionFunction or
ReflectionMethod was always returning 'false' if the function/method was
a generator.

This diff adds the missing plumbing in the parser to make this work
correctly and adds some test coverage.
  • Loading branch information...
1 parent 2a321c6 commit 92cf3ebe972ea0e3febceb6737589ef2a72b3cb1 andrewparoski committed with joelpob Sep 26, 2012
@@ -1,19 +1,23 @@
-/*
- +----------------------------------------------------------------------+
- | HipHop for PHP |
- +----------------------------------------------------------------------+
- | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
-*/
-// @generated by HipHop Compiler
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -352,9 +356,9 @@ void create_generator(Parser *_p, Token &out, Token &params,
Token &origGenFunc, bool isHhvm, Token *attr) {
_p->pushFuncLocation();
if (clsname) {
- _p->onMethodStart(name, *modifiers);
+ _p->onMethodStart(name, *modifiers, false);
} else {
- _p->onFunctionStart(name);
+ _p->onFunctionStart(name, false);
}
Token scont;
@@ -228,6 +228,10 @@ void Parser::pushComment() {
m_comments.push_back(m_scanner.detachDocComment());
}
+void Parser::pushComment(const std::string& s) {
+ m_comments.push_back(s);
+}
+
std::string Parser::popComment() {
std::string ret = m_comments.back();
m_comments.pop_back();
@@ -713,9 +717,11 @@ void Parser::onClassConst(Token &out, Token &cls, Token &name, bool text) {
///////////////////////////////////////////////////////////////////////////////
// function/method declaration
-void Parser::onFunctionStart(Token &name) {
+void Parser::onFunctionStart(Token &name, bool doPushComment /* = true */) {
m_file->pushAttribute();
- pushComment();
+ if (doPushComment) {
+ pushComment();
+ }
newScope();
m_generators.push_back(0);
m_foreaches.push_back(0);
@@ -725,8 +731,9 @@ void Parser::onFunctionStart(Token &name) {
m_staticVars.push_back(StringToExpressionPtrVecMap());
}
-void Parser::onMethodStart(Token &name, Token &mods) {
- onFunctionStart(name);
+void Parser::onMethodStart(Token &name, Token &mods,
+ bool doPushComment /* = true */) {
+ onFunctionStart(name, doPushComment);
}
void Parser::fixStaticVars() {
@@ -812,6 +819,10 @@ void Parser::onFunction(Token &out, Token &ret, Token &ref, Token &name,
prepending.push_back(func);
if (name->text().empty()) m_closureGenerator = true;
+ // create_generator() expects us to push the docComment back
+ // onto the comment stack so that it can make sure that the
+ // the MethodStatement it's building will get the docComment
+ pushComment(comment);
Token origGenFunc;
create_generator(this, out, params, name, closureName, NULL, NULL,
hasCallToGetArgs, origGenFunc,
@@ -1099,6 +1110,10 @@ void Parser::onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
{
completeScope(mth->onInitialParse(m_ar, m_file));
}
+ // create_generator() expects us to push the docComment back
+ // onto the comment stack so that it can make sure that the
+ // the MethodStatement it's building will get the docComment
+ pushComment(comment);
Token origGenFunc;
create_generator(this, out, params, name, closureName, m_clsName.c_str(),
&modifiers, hasCallToGetArgs, origGenFunc,
@@ -163,7 +163,7 @@ class Parser : public ParserBase {
void onUserAttribute(Token &out, Token *attrList, Token &name, Token &value);
void onClassConst(Token &out, Token &cls, Token &name, bool text);
void fixStaticVars();
- void onFunctionStart(Token &name);
+ void onFunctionStart(Token &name, bool doPushComment = true);
void onFunction(Token &out, Token &ret, Token &ref, Token &name,
Token &params, Token &stmt, Token *attr);
void onParam(Token &out, Token *params, Token &type, Token &var,
@@ -182,7 +182,7 @@ class Parser : public ParserBase {
void onTraitAliasRuleStart(Token &out, Token &className, Token &methodName);
void onTraitAliasRuleModify(Token &out, Token &rule, Token &accessModifiers,
Token &newMethodName);
- void onMethodStart(Token &name, Token &mods);
+ void onMethodStart(Token &name, Token &mods, bool doPushComment = true);
void onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
Token &name, Token &params, Token &stmt, Token *attr,
bool reloc = true);
@@ -257,6 +257,7 @@ class Parser : public ParserBase {
bool m_closureGenerator;
void pushComment();
+ void pushComment(const std::string& s);
std::string popComment();
void newScope();
View
@@ -11838,6 +11838,36 @@ bool TestCodeRun::TestReflection() {
"}"
"test();",
"string(3) \"bar\"\n");
+
+ MVCRO("<?php\n"
+ "\n"
+ "/**\n"
+ " * Doc comment on a function generator\n"
+ " */\n"
+ "function foo() {\n"
+ " yield null;\n"
+ "}\n"
+ "$rf = new ReflectionFunction('foo');\n"
+ "var_dump($rf->getDocComment());\n"
+ "\n"
+ "class C {\n"
+ " /**\n"
+ " * Doc comment on a method generator\n"
+ " */\n"
+ " public function bar() {\n"
+ " yield null;\n"
+ " }\n"
+ "}\n"
+ "$rm = new ReflectionMethod('C','bar');\n"
+ "var_dump($rm->getDocComment());\n"
+ ,
+ "string(46) \"/**\n"
+ " * Doc comment on a function generator\n"
+ " */\"\n"
+ "string(48) \"/**\n"
+ " * Doc comment on a method generator\n"
+ " */\"\n"
+ );
}
MVCR("<?php"
View
@@ -277,9 +277,9 @@ void create_generator(Parser *_p, Token &out, Token &params,
Token &origGenFunc, bool isHhvm, Token *attr) {
_p->pushFuncLocation();
if (clsname) {
- _p->onMethodStart(name, *modifiers);
+ _p->onMethodStart(name, *modifiers, false);
} else {
- _p->onFunctionStart(name);
+ _p->onFunctionStart(name, false);
}
Token scont;

0 comments on commit 92cf3eb

Please sign in to comment.