Navigation Menu

Skip to content

Commit

Permalink
Fix reflection to correctly retrieve doc comments for generators
Browse files Browse the repository at this point in the history
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
paroski authored and Joel Pobar committed Sep 28, 2012
1 parent 2a321c6 commit 92cf3eb
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 26 deletions.
40 changes: 22 additions & 18 deletions src/compiler/parser/hphp.tab.cpp
@@ -1,19 +1,23 @@
/*
+----------------------------------------------------------------------+ /* A Bison parser, made by GNU Bison 2.4.1. */
| HipHop for PHP |
+----------------------------------------------------------------------+ /* Skeleton implementation for Bison's Yacc-like parsers in C
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
| This source file is subject to version 3.01 of the PHP license, | Free Software Foundation, Inc.
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: | This program is free software: you can redistribute it and/or modify
| http://www.php.net/license/3_01.txt | it under the terms of the GNU General Public License as published by
| If you did not receive a copy of the PHP license and are unable to | the Free Software Foundation, either version 3 of the License, or
| obtain it through the world-wide-web, please send a note to | (at your option) any later version.
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+ This program is distributed in the hope that it will be useful,
*/ but WITHOUT ANY WARRANTY; without even the implied warranty of
// @generated by HipHop Compiler 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 /* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work part or all of the Bison parser skeleton and distribute that work
Expand Down Expand Up @@ -352,9 +356,9 @@ void create_generator(Parser *_p, Token &out, Token &params,
Token &origGenFunc, bool isHhvm, Token *attr) { Token &origGenFunc, bool isHhvm, Token *attr) {
_p->pushFuncLocation(); _p->pushFuncLocation();
if (clsname) { if (clsname) {
_p->onMethodStart(name, *modifiers); _p->onMethodStart(name, *modifiers, false);
} else { } else {
_p->onFunctionStart(name); _p->onFunctionStart(name, false);
} }


Token scont; Token scont;
Expand Down
23 changes: 19 additions & 4 deletions src/compiler/parser/parser.cpp
Expand Up @@ -228,6 +228,10 @@ void Parser::pushComment() {
m_comments.push_back(m_scanner.detachDocComment()); 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 Parser::popComment() {
std::string ret = m_comments.back(); std::string ret = m_comments.back();
m_comments.pop_back(); m_comments.pop_back();
Expand Down Expand Up @@ -713,9 +717,11 @@ void Parser::onClassConst(Token &out, Token &cls, Token &name, bool text) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// function/method declaration // function/method declaration


void Parser::onFunctionStart(Token &name) { void Parser::onFunctionStart(Token &name, bool doPushComment /* = true */) {
m_file->pushAttribute(); m_file->pushAttribute();
pushComment(); if (doPushComment) {
pushComment();
}
newScope(); newScope();
m_generators.push_back(0); m_generators.push_back(0);
m_foreaches.push_back(0); m_foreaches.push_back(0);
Expand All @@ -725,8 +731,9 @@ void Parser::onFunctionStart(Token &name) {
m_staticVars.push_back(StringToExpressionPtrVecMap()); m_staticVars.push_back(StringToExpressionPtrVecMap());
} }


void Parser::onMethodStart(Token &name, Token &mods) { void Parser::onMethodStart(Token &name, Token &mods,
onFunctionStart(name); bool doPushComment /* = true */) {
onFunctionStart(name, doPushComment);
} }


void Parser::fixStaticVars() { void Parser::fixStaticVars() {
Expand Down Expand Up @@ -812,6 +819,10 @@ void Parser::onFunction(Token &out, Token &ret, Token &ref, Token &name,
prepending.push_back(func); prepending.push_back(func);


if (name->text().empty()) m_closureGenerator = true; 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; Token origGenFunc;
create_generator(this, out, params, name, closureName, NULL, NULL, create_generator(this, out, params, name, closureName, NULL, NULL,
hasCallToGetArgs, origGenFunc, hasCallToGetArgs, origGenFunc,
Expand Down Expand Up @@ -1099,6 +1110,10 @@ void Parser::onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
{ {
completeScope(mth->onInitialParse(m_ar, m_file)); 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; Token origGenFunc;
create_generator(this, out, params, name, closureName, m_clsName.c_str(), create_generator(this, out, params, name, closureName, m_clsName.c_str(),
&modifiers, hasCallToGetArgs, origGenFunc, &modifiers, hasCallToGetArgs, origGenFunc,
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/parser/parser.h
Expand Up @@ -163,7 +163,7 @@ class Parser : public ParserBase {
void onUserAttribute(Token &out, Token *attrList, Token &name, Token &value); void onUserAttribute(Token &out, Token *attrList, Token &name, Token &value);
void onClassConst(Token &out, Token &cls, Token &name, bool text); void onClassConst(Token &out, Token &cls, Token &name, bool text);
void fixStaticVars(); void fixStaticVars();
void onFunctionStart(Token &name); void onFunctionStart(Token &name, bool doPushComment = true);
void onFunction(Token &out, Token &ret, Token &ref, Token &name, void onFunction(Token &out, Token &ret, Token &ref, Token &name,
Token &params, Token &stmt, Token *attr); Token &params, Token &stmt, Token *attr);
void onParam(Token &out, Token *params, Token &type, Token &var, void onParam(Token &out, Token *params, Token &type, Token &var,
Expand All @@ -182,7 +182,7 @@ class Parser : public ParserBase {
void onTraitAliasRuleStart(Token &out, Token &className, Token &methodName); void onTraitAliasRuleStart(Token &out, Token &className, Token &methodName);
void onTraitAliasRuleModify(Token &out, Token &rule, Token &accessModifiers, void onTraitAliasRuleModify(Token &out, Token &rule, Token &accessModifiers,
Token &newMethodName); 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, void onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
Token &name, Token &params, Token &stmt, Token *attr, Token &name, Token &params, Token &stmt, Token *attr,
bool reloc = true); bool reloc = true);
Expand Down Expand Up @@ -257,6 +257,7 @@ class Parser : public ParserBase {
bool m_closureGenerator; bool m_closureGenerator;


void pushComment(); void pushComment();
void pushComment(const std::string& s);
std::string popComment(); std::string popComment();


void newScope(); void newScope();
Expand Down
30 changes: 30 additions & 0 deletions src/test/test_code_run.cpp
Expand Up @@ -11838,6 +11838,36 @@ bool TestCodeRun::TestReflection() {
"}" "}"
"test();", "test();",
"string(3) \"bar\"\n"); "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" MVCR("<?php"
Expand Down
4 changes: 2 additions & 2 deletions src/util/parser/hphp.y
Expand Up @@ -277,9 +277,9 @@ void create_generator(Parser *_p, Token &out, Token &params,
Token &origGenFunc, bool isHhvm, Token *attr) { Token &origGenFunc, bool isHhvm, Token *attr) {
_p->pushFuncLocation(); _p->pushFuncLocation();
if (clsname) { if (clsname) {
_p->onMethodStart(name, *modifiers); _p->onMethodStart(name, *modifiers, false);
} else { } else {
_p->onFunctionStart(name); _p->onFunctionStart(name, false);
} }


Token scont; Token scont;
Expand Down

0 comments on commit 92cf3eb

Please sign in to comment.