Mark classes with the same name as a type alias as redeclaring @override-unit-failures
If you have an alias named "Foo", and a class named "Foo" in the same program, we should not be treating instanceof (and probably other things) as if the class name is unique.
Esse commit está contido em:
@@ -423,6 +423,16 @@ void AnalysisResult::markRedeclaringClasses() {
|
||||
}
|
||||
}
|
||||
|
||||
auto markRedeclaring = [&] (const std::string& name) {
|
||||
auto it = m_classDecs.find(name);
|
||||
if (it != m_classDecs.end()) {
|
||||
auto& classes = it->second;
|
||||
for (unsigned int i = 0; i < classes.size(); ++i) {
|
||||
classes[i]->setRedeclaring(ar, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* In WholeProgram mode, during parse time we collected all
|
||||
* class_alias calls so we can mark the targets of such calls
|
||||
@@ -446,19 +456,19 @@ void AnalysisResult::markRedeclaringClasses() {
|
||||
* as redeclaring for now.
|
||||
*/
|
||||
for (auto& kv : m_classAliases) {
|
||||
auto markRedeclaring = [&] (const std::string& name) {
|
||||
auto it = m_classDecs.find(name);
|
||||
if (it != m_classDecs.end()) {
|
||||
auto& classes = it->second;
|
||||
for (unsigned int i = 0; i < classes.size(); ++i) {
|
||||
classes[i]->setRedeclaring(ar, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
markRedeclaring(Util::toLower(kv.first));
|
||||
markRedeclaring(Util::toLower(kv.second));
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to class_alias, when a type alias is declared with the
|
||||
* same name as a class in the program, we need to make sure the
|
||||
* class is marked redeclaring. It is possible in some requests
|
||||
* that things like 'instanceof Foo' will not mean the same thing.
|
||||
*/
|
||||
for (auto& name : m_typeAliasNames) {
|
||||
markRedeclaring(Util::toLower(name));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -643,6 +653,8 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
|
||||
|
||||
m_classAliases.insert(fs->getClassAliases().begin(),
|
||||
fs->getClassAliases().end());
|
||||
m_typeAliasNames.insert(fs->getTypeAliasNames().begin(),
|
||||
fs->getTypeAliasNames().end());
|
||||
}
|
||||
|
||||
static bool by_filename(const FileScopePtr &f1, const FileScopePtr &f2) {
|
||||
|
||||
@@ -324,6 +324,9 @@ private:
|
||||
// Only in WholeProgram mode. See markRedeclaringClasses.
|
||||
std::multimap<std::string,std::string> m_classAliases;
|
||||
|
||||
// Names of type aliases.
|
||||
std::set<std::string> m_typeAliasNames;
|
||||
|
||||
bool m_classForcedVariants[2];
|
||||
|
||||
StatementPtrVec m_stmts;
|
||||
|
||||
@@ -145,6 +145,14 @@ public:
|
||||
return m_classAliasMap;
|
||||
}
|
||||
|
||||
void addTypeAliasName(const std::string& name) {
|
||||
m_typeAliasNames.insert(name);
|
||||
}
|
||||
|
||||
std::set<std::string> const& getTypeAliasNames() const {
|
||||
return m_typeAliasNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only by World
|
||||
*/
|
||||
@@ -217,6 +225,11 @@ private:
|
||||
// This is only needed in WholeProgram mode.
|
||||
std::multimap<std::string,std::string> m_classAliasMap;
|
||||
|
||||
// Set of names that are on the left hand side of type alias
|
||||
// declarations. We need this to make sure we don't mark classes
|
||||
// with the same name Unique.
|
||||
std::set<std::string> m_typeAliasNames;
|
||||
|
||||
FunctionScopePtr createPseudoMain(AnalysisResultConstPtr ar);
|
||||
void setFileLevel(StatementListPtr stmt);
|
||||
};
|
||||
|
||||
@@ -1634,7 +1634,9 @@ void Parser::onGoto(Token &out, Token &label, bool limited) {
|
||||
}
|
||||
|
||||
void Parser::onTypedef(Token& out, const Token& name, const Token& type) {
|
||||
out->stmt = NEW_STMT(TypedefStatement, name.text(), type.text());
|
||||
auto td_stmt = NEW_STMT(TypedefStatement, name.text(), type.text());
|
||||
td_stmt->onParse(m_ar, m_file);
|
||||
out->stmt = td_stmt;
|
||||
}
|
||||
|
||||
void Parser::onTypeAnnotation(Token& out, const Token& name,
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
#include "hphp/compiler/statement/typedef_statement.h"
|
||||
|
||||
#include "hphp/compiler/analysis/file_scope.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -57,6 +59,10 @@ void TypedefStatement::inferTypes(AnalysisResultPtr) {}
|
||||
void TypedefStatement::outputPHP(CodeGenerator& cg, AnalysisResultPtr ar) {
|
||||
}
|
||||
|
||||
void TypedefStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) {
|
||||
scope->addTypeAliasName(name);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace HPHP {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TypedefStatement : Statement {
|
||||
struct TypedefStatement : Statement, IParseHandler {
|
||||
explicit TypedefStatement(STATEMENT_CONSTRUCTOR_PARAMETERS,
|
||||
const std::string& name,
|
||||
const std::string& value);
|
||||
@@ -33,6 +33,10 @@ struct TypedefStatement : Statement {
|
||||
|
||||
DECLARE_STATEMENT_VIRTUAL_FUNCTIONS;
|
||||
|
||||
public: // IParseHandler
|
||||
void onParse(AnalysisResultConstPtr, FileScopePtr);
|
||||
|
||||
public:
|
||||
const std::string name;
|
||||
const std::string value;
|
||||
};
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário