1487 lines
78 KiB
C++
1487 lines
78 KiB
C++
/*******************************************
|
|
* Zira Editor
|
|
* A lightweight PHP Editor
|
|
* (C)2019 https://github.com/ziracms/editor
|
|
*******************************************/
|
|
|
|
#include "parsephp.h"
|
|
#include <QVector>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include "helper.h"
|
|
|
|
const int EXPECT_NAMESPACE = 0;
|
|
const int EXPECT_CLASS = 1;
|
|
const int EXPECT_CLASS_EXTENDED = 2;
|
|
const int EXPECT_CLASS_IMPLEMENTED = 3;
|
|
const int EXPECT_CLASS_EXTENDED_IMPLEMENTED = 4;
|
|
const int EXPECT_INTERFACE = 5;
|
|
const int EXPECT_INTERFACE_EXTENDED = 6;
|
|
const int EXPECT_TRAIT = 7;
|
|
const int EXPECT_USE = 8;
|
|
const int EXPECT_USE_FUNCTION = 9;
|
|
const int EXPECT_USE_CONSTANT = 10;
|
|
const int EXPECT_FUNCTION = 11;
|
|
const int EXPECT_FUNCTION_RETURN_TYPE = 12;
|
|
const int EXPECT_VARIABLE = 13;
|
|
const int EXPECT_CONST = 14;
|
|
const int EXPECT_CONST_VALUE = 15;
|
|
|
|
const QString IMPORT_TYPE_CLASS = "class";
|
|
const QString IMPORT_TYPE_FUNCTION = "function";
|
|
const QString IMPORT_TYPE_CONSTANT = "constant";
|
|
|
|
std::unordered_map<std::string, std::string> ParsePHP::dataTypes = {};
|
|
|
|
ParsePHP::ParsePHP()
|
|
{
|
|
phpExpression = QRegularExpression("[<][?](?:php)?[\\s](.+?)([?][>]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
phpStartExpression = QRegularExpression("[<][?](php)?[\\s]", QRegularExpression::DotMatchesEverythingOption);
|
|
phpEndExpression = QRegularExpression("[?][>]", QRegularExpression::DotMatchesEverythingOption);
|
|
stringHeredocExpression = QRegularExpression("[<][<][<]([_a-zA-Z][_a-zA-Z0-9]*)[\n](.+?)[\n](\\1)[;]([\n]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
stringHeredocDQExpression = QRegularExpression("[<][<][<][\"]([_a-zA-Z][_a-zA-Z0-9]*)[\"][\n](.+?)[\n](\\1)[;]([\n]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
stringNowdocExpression = QRegularExpression("[<][<][<][']([_a-zA-Z][_a-zA-Z0-9]*)['][\n](.+?)[\n](\\1)[;]([\n]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
commentSLExpression = QRegularExpression("[/][/]([^\n]+?)([?][>]|[\n]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
commentSLAExpression = QRegularExpression("[#]([^\n]+?)([?][>]|[\n]|$)", QRegularExpression::DotMatchesEverythingOption);
|
|
parseExpression = QRegularExpression("([a-zA-Z0-9_\\$\\\\]+|[\\(\\)\\{\\}\\[\\],=;:!@#%^&*\\-+/\\|<>\\?])", QRegularExpression::DotMatchesEverythingOption);
|
|
nameExpression = QRegularExpression("^[\\$\\\\]?[a-zA-Z_][a-zA-Z0-9_\\\\]*$");
|
|
|
|
if (dataTypes.size() == 0) {
|
|
QFile tf(":/highlight/php_types");
|
|
tf.open(QIODevice::ReadOnly);
|
|
QTextStream tin(&tf);
|
|
QString k;
|
|
while (!tin.atEnd()) {
|
|
k = tin.readLine();
|
|
if (k == "") continue;
|
|
dataTypes[k.toStdString()] = k.toStdString();
|
|
}
|
|
tf.close();
|
|
}
|
|
}
|
|
|
|
QString ParsePHP::cleanUp(QString text)
|
|
{
|
|
comments.clear();
|
|
prepare(text);
|
|
// strip strings & comments
|
|
bool phpOpened = false;
|
|
int offset = 0;
|
|
QRegularExpressionMatch phpEndMatch;
|
|
QRegularExpressionMatch stringDQMatch;
|
|
QRegularExpressionMatch stringSQMatch;
|
|
QRegularExpressionMatch stringHeredocMatch;
|
|
QRegularExpressionMatch stringHeredocDQMatch;
|
|
QRegularExpressionMatch stringNowdocMatch;
|
|
QRegularExpressionMatch commentMLMatch;
|
|
QRegularExpressionMatch commentSLMatch;
|
|
QRegularExpressionMatch commentSLAMatch;
|
|
QRegularExpressionMatch backtickMatch;
|
|
QList<int> matchesPos;
|
|
int phpEndPos = -2,
|
|
stringDQPos = -2,
|
|
stringSQPos = -2,
|
|
stringHeredocPos = -2,
|
|
stringHeredocDQPos = -2,
|
|
stringNowdocPos = -2,
|
|
commentMLPos = -2,
|
|
commentSLPos = -2,
|
|
commentSLAPos = -2,
|
|
backtickPos = -2;
|
|
do {
|
|
if (!phpOpened) {
|
|
QRegularExpressionMatch match = phpStartExpression.match(text, offset);
|
|
if (match.capturedStart() < 0) break;
|
|
offset = match.capturedStart() + match.capturedLength();
|
|
phpOpened = true;
|
|
}
|
|
matchesPos.clear();
|
|
if (phpEndPos != -1 && phpEndPos < offset) {
|
|
phpEndMatch = phpEndExpression.match(text, offset);
|
|
phpEndPos = phpEndMatch.capturedStart();
|
|
}
|
|
if (phpEndPos >= 0) matchesPos.append(phpEndPos);
|
|
if (stringDQPos != -1 && stringDQPos < offset) {
|
|
stringDQMatch = stringDQExpression.match(text, offset);
|
|
stringDQPos = stringDQMatch.capturedStart(1)-1;
|
|
}
|
|
if (stringDQPos >= 0) matchesPos.append(stringDQPos);
|
|
if (stringSQPos != -1 && stringSQPos < offset) {
|
|
stringSQMatch = stringSQExpression.match(text, offset);
|
|
stringSQPos = stringSQMatch.capturedStart(1)-1;
|
|
}
|
|
if (stringSQPos >= 0) matchesPos.append(stringSQPos);
|
|
if (stringHeredocPos != -1 && stringHeredocPos < offset) {
|
|
stringHeredocMatch = stringHeredocExpression.match(text, offset);
|
|
stringHeredocPos = stringHeredocMatch.capturedStart();
|
|
}
|
|
if (stringHeredocPos >= 0) matchesPos.append(stringHeredocPos);
|
|
if (stringHeredocDQPos != -1 && stringHeredocDQPos < offset) {
|
|
stringHeredocDQMatch = stringHeredocDQExpression.match(text, offset);
|
|
stringHeredocDQPos = stringHeredocDQMatch.capturedStart();
|
|
}
|
|
if (stringHeredocDQPos >= 0) matchesPos.append(stringHeredocDQPos);
|
|
if (stringNowdocPos != -1 && stringNowdocPos < offset) {
|
|
stringNowdocMatch = stringNowdocExpression.match(text, offset);
|
|
stringNowdocPos = stringNowdocMatch.capturedStart();
|
|
}
|
|
if (stringNowdocPos >= 0) matchesPos.append(stringNowdocPos);
|
|
if (commentMLPos != -1 && commentMLPos < offset) {
|
|
commentMLMatch = commentMLExpression.match(text, offset);
|
|
commentMLPos = commentMLMatch.capturedStart();
|
|
}
|
|
if (commentMLPos >= 0) matchesPos.append(commentMLPos);
|
|
if (commentSLPos != -1 && commentSLPos < offset) {
|
|
commentSLMatch = commentSLExpression.match(text, offset);
|
|
commentSLPos = commentSLMatch.capturedStart();
|
|
}
|
|
if (commentSLPos >= 0) matchesPos.append(commentSLPos);
|
|
if (commentSLAPos != -1 && commentSLAPos < offset) {
|
|
commentSLAMatch = commentSLAExpression.match(text, offset);
|
|
commentSLAPos = commentSLAMatch.capturedStart();
|
|
}
|
|
if (commentSLAPos >= 0) matchesPos.append(commentSLAPos);
|
|
if (backtickPos != -1 && backtickPos < offset) {
|
|
backtickMatch = backtickExpression.match(text, offset);
|
|
backtickPos = backtickMatch.capturedStart(1)-1;
|
|
}
|
|
if (backtickPos >= 0) matchesPos.append(backtickPos);
|
|
if (matchesPos.size() == 0) break;
|
|
std::sort(matchesPos.begin(), matchesPos.end());
|
|
int pos = matchesPos.at(0);
|
|
if (phpEndPos == pos) {
|
|
offset = phpEndMatch.capturedStart() + phpEndMatch.capturedLength();
|
|
phpOpened = false;
|
|
continue;
|
|
}
|
|
if (stringDQPos == pos) {
|
|
offset = stringDQMatch.capturedStart() + stringDQMatch.capturedLength();
|
|
strip(stringDQMatch, text, 1);
|
|
continue;
|
|
}
|
|
if (stringSQPos == pos) {
|
|
offset = stringSQMatch.capturedStart() + stringSQMatch.capturedLength();
|
|
strip(stringSQMatch, text, 1);
|
|
continue;
|
|
}
|
|
if (stringHeredocPos == pos) {
|
|
offset = stringHeredocMatch.capturedStart() + stringHeredocMatch.capturedLength();
|
|
strip(stringHeredocMatch, text, 2);
|
|
continue;
|
|
}
|
|
if (stringHeredocDQPos == pos) {
|
|
offset = stringHeredocDQMatch.capturedStart() + stringHeredocDQMatch.capturedLength();
|
|
strip(stringHeredocDQMatch, text, 2);
|
|
continue;
|
|
}
|
|
if (stringNowdocPos == pos) {
|
|
offset = stringNowdocMatch.capturedStart() + stringNowdocMatch.capturedLength();
|
|
strip(stringNowdocMatch, text, 2);
|
|
continue;
|
|
}
|
|
if (commentMLPos == pos) {
|
|
offset = commentMLMatch.capturedStart() + commentMLMatch.capturedLength();
|
|
QString stripped = strip(commentMLMatch, text, 0); // group 0
|
|
comments[getLine(text, offset)] = stripped.toStdString();
|
|
continue;
|
|
}
|
|
if (commentSLPos == pos) {
|
|
offset = commentSLMatch.capturedStart(1) + commentSLMatch.capturedLength(1);
|
|
QString stripped = strip(commentSLMatch, text, 0); // group 0
|
|
comments[getLine(text, offset)] = stripped.toStdString();
|
|
continue;
|
|
}
|
|
if (commentSLAPos == pos) {
|
|
offset = commentSLAMatch.capturedStart(1) + commentSLAMatch.capturedLength(1);
|
|
QString stripped = strip(commentSLAMatch, text, 0); // group 0
|
|
comments[getLine(text, offset)] = stripped.toStdString();
|
|
continue;
|
|
}
|
|
if (backtickPos == pos) {
|
|
offset = backtickMatch.capturedStart() + backtickMatch.capturedLength();
|
|
strip(backtickMatch, text, 1);
|
|
continue;
|
|
}
|
|
} while (matchesPos.size() > 0);
|
|
return text;
|
|
}
|
|
|
|
bool ParsePHP::isValidName(QString name)
|
|
{
|
|
QRegularExpressionMatch m = nameExpression.match(name);
|
|
return (m.capturedStart()==0);
|
|
}
|
|
|
|
QString ParsePHP::toAbs(QString ns, QString path, QString type)
|
|
{
|
|
if (type.size() == 0) type = IMPORT_TYPE_CLASS;
|
|
QString name = path;
|
|
int p = path.indexOf("\\");
|
|
if (p > 0) {
|
|
if (path.indexOf("namespace\\")==0) {
|
|
if (ns.size() > 0 && ns[0] != "\\") ns = "\\" + ns;
|
|
path = ns + path.mid(p);
|
|
p = 0;
|
|
} else {
|
|
name = path.mid(0, p);
|
|
}
|
|
}
|
|
if (p != 0) {
|
|
std::unordered_map<std::string, std::string> aliases;
|
|
std::unordered_map<std::string, std::string>::iterator aliasesIterator;
|
|
if (type == IMPORT_TYPE_FUNCTION) {
|
|
aliases = functionAliases;
|
|
aliasesIterator = functionAliasesIterator;
|
|
} else if (type == IMPORT_TYPE_CONSTANT) {
|
|
aliases = constantAliases;
|
|
aliasesIterator = constantAliasesIterator;
|
|
} else {
|
|
aliases = classAliases;
|
|
aliasesIterator = classAliasesIterator;
|
|
}
|
|
aliasesIterator = aliases.find(name.toStdString());
|
|
if (aliasesIterator != aliases.end()) {
|
|
QString use_path = QString::fromStdString(aliasesIterator->second);
|
|
if (use_path.size() > 0 && use_path[0] != "\\") use_path = "\\" + use_path;
|
|
if (p > 0) {
|
|
return use_path + path.mid(p);
|
|
} else {
|
|
return use_path;
|
|
}
|
|
} else {
|
|
if (ns.size() > 0 && ns[0] != "\\") ns = "\\" + ns;
|
|
return ns + "\\" + path;
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
|
|
void ParsePHP::addImport(QString nsName, QString name, QString path, QString type, int line) {
|
|
if (!isValidName(name) || !isValidName(path)) return;
|
|
ParseResultImport imp;
|
|
imp.name = name;
|
|
imp.path = path;
|
|
imp.type = type;
|
|
imp.line = line;
|
|
result.imports.append(imp);
|
|
importIndexes[name.toStdString()] = result.imports.size() - 1;
|
|
if (nsName.size() > 0) {
|
|
namespaceIndexesIterator = namespaceIndexes.find(nsName.toStdString());
|
|
if (namespaceIndexesIterator != namespaceIndexes.end()) {
|
|
int i = namespaceIndexesIterator->second;
|
|
if (result.namespaces.size() > i) {
|
|
ParsePHP::ParseResultNamespace ns = result.namespaces.at(i);
|
|
ns.importsIndexes.append(result.imports.size() - 1);
|
|
result.namespaces.replace(i, ns);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::addNamespace(QString name, int line) {
|
|
if (!isValidName(name)) return;
|
|
ParseResultNamespace ns;
|
|
ns.name = name;
|
|
ns.line = line;
|
|
result.namespaces.append(ns);
|
|
namespaceIndexes[name.toStdString()] = result.namespaces.size() - 1;
|
|
}
|
|
|
|
void ParsePHP::addClass(QString name, bool isAbstract, QString extend, QStringList implements, int line) {
|
|
if (!isValidName(name)) return;
|
|
ParseResultClass cls;
|
|
cls.name = name;
|
|
cls.isAbstract = isAbstract;
|
|
cls.isInterface = false;
|
|
cls.isTrait = false;
|
|
cls.parent = extend;
|
|
cls.interfaces = implements;
|
|
cls.line = line;
|
|
result.classes.append(cls);
|
|
classIndexes[name.toStdString()] = result.classes.size() - 1;
|
|
}
|
|
|
|
void ParsePHP::addInterface(QString name, QString extend, int line) {
|
|
if (!isValidName(name)) return;
|
|
ParseResultClass cls;
|
|
cls.name = name;
|
|
cls.isAbstract = false;
|
|
cls.isInterface = true;
|
|
cls.isTrait = false;
|
|
cls.parent = extend;
|
|
cls.interfaces.clear();
|
|
cls.line = line;
|
|
result.classes.append(cls);
|
|
classIndexes[name.toStdString()] = result.classes.size() - 1;
|
|
}
|
|
|
|
void ParsePHP::addTrait(QString name, int line) {
|
|
if (!isValidName(name)) return;
|
|
ParseResultClass cls;
|
|
cls.name = name;
|
|
cls.isAbstract = false;
|
|
cls.isInterface = false;
|
|
cls.isTrait = true;
|
|
cls.parent = "";
|
|
cls.interfaces.clear();
|
|
cls.line = line;
|
|
result.classes.append(cls);
|
|
classIndexes[name.toStdString()] = result.classes.size() - 1;
|
|
}
|
|
|
|
void ParsePHP::addFunction(QString clsName, QString name, QString args, bool isStatic, bool isAbstract, QString visibility, int minArgs, int maxArgs, QString returnType, QString comment, int line) {
|
|
if (!isValidName(name)) return;
|
|
ParseResultFunction func;
|
|
func.name = name;
|
|
func.clsName = clsName;
|
|
func.args = args;
|
|
func.isStatic = isStatic;
|
|
func.isAbstract = isAbstract;
|
|
func.visibility = visibility;
|
|
func.minArgs = minArgs;
|
|
func.maxArgs = maxArgs;
|
|
func.returnType = returnType;
|
|
func.comment = comment;
|
|
func.line = line;
|
|
result.functions.append(func);
|
|
functionIndexes[clsName.toStdString() + "::" + name.toStdString()] = result.functions.size() - 1;
|
|
if (clsName.size() > 0) {
|
|
classIndexesIterator = classIndexes.find(clsName.toStdString());
|
|
if (classIndexesIterator != classIndexes.end()) {
|
|
int i = classIndexesIterator->second;
|
|
if (result.classes.size() > i) {
|
|
ParsePHP::ParseResultClass cls = result.classes.at(i);
|
|
cls.functionIndexes.append(result.functions.size() - 1);
|
|
result.classes.replace(i, cls);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::updateFunctionReturnType(QString clsName, QString funcName, QString returnType)
|
|
{
|
|
functionIndexesIterator = functionIndexes.find(clsName.toStdString() + "::" + funcName.toStdString());
|
|
if (functionIndexesIterator != functionIndexes.end()) {
|
|
int i = functionIndexesIterator->second;
|
|
if (result.functions.size() > i) {
|
|
ParseResultFunction func = result.functions.at(i);
|
|
func.returnType = returnType;
|
|
result.functions.replace(i, func);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::addVariable(QString clsName, QString funcName, QString name, bool isStatic, QString visibility, QString type, int line)
|
|
{
|
|
if (!isValidName(name)) return;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + funcName.toStdString() + "::" + name.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) return;
|
|
ParseResultVariable variable;
|
|
variable.name = name;
|
|
variable.clsName = clsName;
|
|
variable.funcName = funcName;
|
|
variable.isStatic = isStatic;
|
|
variable.visibility =visibility;
|
|
variable.type = type;
|
|
variable.line = line;
|
|
result.variables.append(variable);
|
|
variableIndexes[clsName.toStdString() + "::" + funcName.toStdString() + "::" + name.toStdString()] = result.variables.size() - 1;
|
|
if (clsName.size() > 0 && funcName.size() == 0) {
|
|
classIndexesIterator = classIndexes.find(clsName.toStdString());
|
|
if (classIndexesIterator != classIndexes.end()) {
|
|
int i = classIndexesIterator->second;
|
|
if (result.classes.size() > i) {
|
|
ParsePHP::ParseResultClass cls = result.classes.at(i);
|
|
cls.variableIndexes.append(result.variables.size() - 1);
|
|
result.classes.replace(i, cls);
|
|
}
|
|
}
|
|
} else if (funcName.size() > 0) {
|
|
functionIndexesIterator = functionIndexes.find(clsName.toStdString() + "::" + funcName.toStdString());
|
|
if (functionIndexesIterator != functionIndexes.end()) {
|
|
int i = functionIndexesIterator->second;
|
|
if (result.functions.size() > i) {
|
|
ParsePHP::ParseResultFunction func = result.functions.at(i);
|
|
func.variableIndexes.append(result.variables.size() - 1);
|
|
result.functions.replace(i, func);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::updateVariableType(QString clsName, QString funcName, QString varName, QString type)
|
|
{
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + funcName.toStdString() + "::" + varName.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
variable.type = type;
|
|
result.variables.replace(i, variable);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::addConstant(QString clsName, QString name, QString value, int line)
|
|
{
|
|
if (!isValidName(name)) return;
|
|
ParseResultConstant constant;
|
|
constant.name = name;
|
|
constant.clsName = clsName;
|
|
constant.value = value;
|
|
constant.line = line;
|
|
result.constants.append(constant);
|
|
constantIndexes[clsName.toStdString() + "::" + name.toStdString()] = result.constants.size() - 1;
|
|
if (clsName.size() > 0) {
|
|
classIndexesIterator = classIndexes.find(clsName.toStdString());
|
|
if (classIndexesIterator != classIndexes.end()) {
|
|
int i = classIndexesIterator->second;
|
|
if (result.classes.size() > i) {
|
|
ParsePHP::ParseResultClass cls = result.classes.at(i);
|
|
cls.constantIndexes.append(result.constants.size() - 1);
|
|
result.classes.replace(i, cls);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParsePHP::addComment(QString text, int line) {
|
|
QString name = "";
|
|
if (text.size() > 0) {
|
|
if (text.indexOf("//")==0) text = text.mid(2);
|
|
else if (text.indexOf("#")==0) text = text.mid(1);
|
|
else text.replace(QRegularExpression("^[/][*](.*)[*][/]$", QRegularExpression::DotMatchesEverythingOption), "\\1");
|
|
QString text_clean = "";
|
|
QStringList textList = text.split("\n");
|
|
for (int i=0; i<textList.size(); i++) {
|
|
QString text_line = textList.at(i).trimmed().replace(QRegularExpression("^[*]+[\\s]*"), "").replace(QRegularExpression("[\\s]*[*]+$"), "");
|
|
if (text_line.size() == 0) continue;
|
|
if (text_clean.size() > 0) text_clean += "\n";
|
|
if (name.size() == 0) name = text_line;
|
|
text_clean += text_line;
|
|
}
|
|
text = text_clean;
|
|
}
|
|
if (text.size() == 0 || name.size() == 0) return;
|
|
ParseResultComment comment;
|
|
comment.name = name;
|
|
comment.text = text;
|
|
comment.line = line;
|
|
result.comments.append(comment);
|
|
}
|
|
|
|
void ParsePHP::addError(QString text, int line, int symbol) {
|
|
ParseResultError error;
|
|
error.text = text;
|
|
error.line = line;
|
|
error.symbol = symbol;
|
|
result.errors.append(error);
|
|
}
|
|
|
|
void ParsePHP::parseCode(QString & code, QString & origText, int textOffset)
|
|
{
|
|
// parse data
|
|
QString current_namespace = "";
|
|
QString current_class = "";
|
|
bool current_class_is_abstract = false;
|
|
QString current_class_parent = "";
|
|
QStringList current_class_interfaces;
|
|
QString current_interface = "";
|
|
QString current_interface_parent = "";
|
|
QString current_trait = "";
|
|
QString current_function = "";
|
|
QString current_function_args = "";
|
|
bool current_function_is_static = false;
|
|
bool current_function_is_abstract = false;
|
|
QString current_function_visibility = "";
|
|
int current_function_min_args = 0;
|
|
int current_function_max_args = 0;
|
|
QString current_function_return_type = "";
|
|
QString current_variable = "";
|
|
bool current_variable_is_static = false;
|
|
QString current_variable_visibility = "";
|
|
QString current_variable_type = "";
|
|
QString current_constant = "";
|
|
QString current_constant_value = "";
|
|
|
|
QStringList parent_namespaces;
|
|
QVector<int> parent_namespace_scopes;
|
|
QString expected_function_name = "";
|
|
QStringList expected_function_args;
|
|
QStringList expected_function_arg_types;
|
|
QString expected_class_name = "";
|
|
int scope = 0;
|
|
int namespaceScope = -1, classScope = -1, interfaceScope = -1, traitScope = -1, functionScope = -1, anonymFunctionScope = -1, anonymClassScope = -1;
|
|
int pars = 0;
|
|
int curlyBrackets = 0, roundBrackets = 0, squareBrackets = 0;
|
|
QVector<int> curlyBracketsList, roundBracketsList, squareBracketsList;
|
|
int functionArgPars = -1;
|
|
int functionArgsStart = -1;
|
|
int constantValueStart = -1;
|
|
bool functionParsFound = false, classParsFound = false;
|
|
int expect = -1;
|
|
QString expectName = "";
|
|
QString prevK = "", prevPrevK = "", prevPrevPrevK = "", prevPrevPrevPrevK = "", prevPrevPrevPrevPrevK = "", prevPrevPrevPrevPrevPrevK = "", prevPrevPrevPrevPrevPrevPrevK = "", prevPrevPrevPrevPrevPrevPrevPrevK = "";
|
|
int useStart = -1, namespaceStart = -1, classStart = -1, interfaceStart = -1, traitStart = -1, functionStart = -1, variableStart = -1, constantStart = -1;
|
|
QString class_static_variable = "", class_variable = "";
|
|
QStringList functionChainList, classChainList, traitChainList;
|
|
|
|
QRegularExpressionMatchIterator mi = parseExpression.globalMatch(code);
|
|
while(mi.hasNext()){
|
|
QRegularExpressionMatch m = mi.next();
|
|
if (m.capturedStart(1) < 0) continue;
|
|
QString k = m.captured(1).trimmed();
|
|
if (k.size() == 0) continue;
|
|
|
|
// uses
|
|
if (expect < 0 && (((namespaceScope < 0 && scope == 0) || scope == namespaceScope+1) && (prevK == ";" || prevK == "{" || prevK == "}" || prevK.size() == 0)) && k.toLower() == "use" && current_class.size() == 0 && current_interface.size() == 0 && current_trait.size() == 0 && current_function.size() == 0 && anonymFunctionScope < 0) {
|
|
expect = EXPECT_USE;
|
|
expectName = "";
|
|
useStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_USE && expectName.size() == 0 && k.toLower() == "function") {
|
|
expect = EXPECT_USE_FUNCTION;
|
|
} else if (expect == EXPECT_USE && expectName.size() == 0 && k.toLower() == "const") {
|
|
expect = EXPECT_USE_CONSTANT;
|
|
} else if ((expect == EXPECT_USE || expect == EXPECT_USE_FUNCTION || expect == EXPECT_USE_CONSTANT) && expectName.size() == 0) {
|
|
expectName = k;
|
|
} else if ((expect == EXPECT_USE || expect == EXPECT_USE_FUNCTION || expect == EXPECT_USE_CONSTANT) && expectName.size() > 0 && k.toLower() == "as") {
|
|
expectName += " as ";
|
|
} else if ((expect == EXPECT_USE || expect == EXPECT_USE_FUNCTION || expect == EXPECT_USE_CONSTANT) && expectName.size() > 0 && k != ";") {
|
|
expectName += k;
|
|
} else if ((expect == EXPECT_USE || expect == EXPECT_USE_FUNCTION || expect == EXPECT_USE_CONSTANT) && expectName.size() > 0 && k == ";") {
|
|
QString useType = IMPORT_TYPE_CLASS;
|
|
if (expect == EXPECT_USE_FUNCTION) useType = IMPORT_TYPE_FUNCTION;
|
|
else if (expect == EXPECT_USE_CONSTANT) useType = IMPORT_TYPE_CONSTANT;
|
|
if (expectName.indexOf("{") > 0 && expectName.indexOf("}") == expectName.size() - 1 && expectName.size() - expectName.indexOf("{") > 2) {
|
|
QString expectNameUnscoped = "";
|
|
QString usePre = expectName.mid(0, expectName.indexOf("{"));
|
|
if (usePre.size() > 1 && usePre.mid(usePre.size()-1) == "\\") {
|
|
QString useScope = expectName.mid(expectName.indexOf("{")+1, expectName.size() - expectName.indexOf("{") - 2);
|
|
QStringList useScopeList = useScope.split(",");
|
|
for (int i=0; i<useScopeList.size(); i++) {
|
|
QString useScopePart = useScopeList.at(i);
|
|
if (expectNameUnscoped.size() > 0) expectNameUnscoped += ",";
|
|
expectNameUnscoped += usePre+useScopePart;
|
|
}
|
|
}
|
|
expectName = expectNameUnscoped;
|
|
}
|
|
QStringList useList = expectName.split(",");
|
|
for (int i=0; i<useList.size(); i++) {
|
|
QString usePath = "", useName = "";
|
|
QString usePart = useList.at(i);
|
|
if (usePart.indexOf("{") >= 0 || usePart.indexOf("}") >= 0) continue;
|
|
QStringList usePartList = usePart.split(" as ");
|
|
if (usePartList.size() == 2) {
|
|
usePath = usePartList.at(0);
|
|
useName = usePartList.at(1);
|
|
} else if (usePartList.size() == 1) {
|
|
usePath = usePartList.at(0);
|
|
useName = usePath;
|
|
int p = useName.lastIndexOf("\\");
|
|
if (p >= 0) useName = useName.mid(p+1);
|
|
}
|
|
if (usePath.size() > 0 && useName.size() > 0 && isValidName(usePath) && isValidName(useName)) {
|
|
if (usePath[0] != "\\") usePath = "\\" + usePath;
|
|
if (useType == IMPORT_TYPE_CLASS) {
|
|
classAliases[useName.toStdString()] = usePath.toStdString();
|
|
} else if (useType == IMPORT_TYPE_FUNCTION) {
|
|
functionAliases[useName.toStdString()] = usePath.toStdString();
|
|
} else if (useType == IMPORT_TYPE_CONSTANT) {
|
|
constantAliases[useName.toStdString()] = usePath.toStdString();
|
|
}
|
|
int line = 0;
|
|
//if (useStart >= 0) line = getLine(origText, textOffset + useStart);
|
|
if (useStart >= 0) line = getLine(origText, textOffset + m.capturedStart(1)); // line at end
|
|
addImport(current_namespace, useName, usePath, useType, line);
|
|
}
|
|
}
|
|
expect = -1;
|
|
expectName = "";
|
|
}
|
|
|
|
// namespaces
|
|
if (expect < 0 && k.toLower() == "namespace") {
|
|
expect = EXPECT_NAMESPACE;
|
|
expectName = "";
|
|
namespaceStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_NAMESPACE && expectName.size() == 0) {
|
|
expectName = k;
|
|
} else if (expect == EXPECT_NAMESPACE && expectName.size() > 0 && (k == ";" || k == "{")) {
|
|
QString parent = "";
|
|
if (namespaceScope >= 0 && current_namespace.size() > 0) {
|
|
parent_namespaces.append(current_namespace);
|
|
parent_namespace_scopes.append(namespaceScope);
|
|
// namespace cannot be nested
|
|
//if (expectName[0] != "\\") parent = current_namespace + "\\";
|
|
}
|
|
current_namespace = parent + expectName;
|
|
if (current_namespace[0] == "\\") current_namespace = current_namespace.mid(1);
|
|
int line = 0;
|
|
//if (namespaceStart >= 0) line = getLine(origText, textOffset + namespaceStart);
|
|
if (namespaceStart >= 0) line = getLine(origText, textOffset + m.capturedStart(1)); // line at end
|
|
addNamespace(current_namespace, line);
|
|
expect = -1;
|
|
expectName = "";
|
|
if (k == "{") namespaceScope = scope;
|
|
if (k == ";") {
|
|
parent_namespaces.clear();
|
|
parent_namespace_scopes.clear();
|
|
}
|
|
// reset imports
|
|
classAliases.clear();
|
|
functionAliases.clear();
|
|
constantAliases.clear();
|
|
}
|
|
|
|
// classes
|
|
if ((((prevPrevPrevK.size() == 0 || prevPrevPrevK == ";" || prevPrevPrevK == "{" || prevPrevPrevK == "}" || prevPrevPrevK == ">" || prevPrevPrevK == ":") && prevPrevK.size() > 0 && prevK == "=") || prevK.toLower() == "return") && k == "new" && anonymClassScope < 0) {
|
|
expected_class_name = prevPrevK;
|
|
}
|
|
if (expect < 0 && k.toLower() == "class" && (prevK == ";" || prevK == "{" || prevK == "}" || prevK == "=" || prevK.size() == 0 || prevK.toLower() == "new" || prevK.toLower() == "abstract" || prevK.toLower() == "final") && anonymClassScope < 0) {
|
|
expect = EXPECT_CLASS;
|
|
expectName = "";
|
|
current_class_is_abstract = (prevK.toLower() == "abstract");
|
|
current_class_parent = "";
|
|
current_class_interfaces.clear();
|
|
classStart = m.capturedStart(1);
|
|
classParsFound = false;
|
|
} else if (expect == EXPECT_CLASS && expectName.size() == 0 && k != "{" && !classParsFound) {
|
|
if (k != "(" && k != ")" && k != "{" && k != "extends" && k != "implements" && k.indexOf("$") < 0 && (current_class.size() == 0 && current_interface.size() == 0 && current_trait.size() == 0)) {
|
|
expectName = k;
|
|
} else {
|
|
classParsFound = true;
|
|
}
|
|
} else if (expect == EXPECT_CLASS && expectName.size() > 0 && k.toLower() == "extends") {
|
|
expect = EXPECT_CLASS_EXTENDED;
|
|
} else if (expect == EXPECT_CLASS_EXTENDED && expectName.size() > 0 && current_class_parent.size() == 0 && k != "{") {
|
|
current_class_parent = toAbs(current_namespace, k);
|
|
} else if ((expect == EXPECT_CLASS || expect == EXPECT_CLASS_EXTENDED) && expectName.size() > 0 && k.toLower() == "implements") {
|
|
if (expect == EXPECT_CLASS) expect = EXPECT_CLASS_IMPLEMENTED;
|
|
if (expect == EXPECT_CLASS_EXTENDED) expect = EXPECT_CLASS_EXTENDED_IMPLEMENTED;
|
|
} else if ((expect == EXPECT_CLASS_IMPLEMENTED || expect == EXPECT_CLASS_EXTENDED_IMPLEMENTED) && expectName.size() > 0 && k != "{" && k != ",") {
|
|
current_class_interfaces.append(toAbs(current_namespace, k));
|
|
} else if ((expect == EXPECT_CLASS || expect == EXPECT_CLASS_EXTENDED || expect == EXPECT_CLASS_IMPLEMENTED || expect == EXPECT_CLASS_EXTENDED_IMPLEMENTED) && (expectName.size() > 0 || expected_class_name.size() > 0) && k == "{") {
|
|
if (expectName.size() > 0 && (current_class.size() == 0 && current_interface.size() == 0 && current_trait.size() == 0)) {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
current_class = ns + expectName;
|
|
int line = 0;
|
|
if (classStart >= 0) line = getLine(origText, textOffset + classStart);
|
|
addClass(current_class, current_class_is_abstract, current_class_parent, current_class_interfaces, line);
|
|
classScope = scope;
|
|
} else {
|
|
anonymClassScope = scope;
|
|
if (current_class.size() > 0) {
|
|
classChainList.append(current_class);
|
|
current_class = "";
|
|
} else if (current_trait.size() > 0) {
|
|
traitChainList.append(current_trait);
|
|
current_trait = "";
|
|
}
|
|
}
|
|
expect = -1;
|
|
expectName = "";
|
|
current_interface = "";
|
|
current_trait = "";
|
|
expected_class_name = "";
|
|
classParsFound = false;
|
|
}
|
|
|
|
// interfaces
|
|
if (expect < 0 && k.toLower() == "interface" && (current_class.size() == 0 && current_interface.size() == 0 && current_trait.size() == 0)) {
|
|
expect = EXPECT_INTERFACE;
|
|
expectName = "";
|
|
current_interface_parent = "";
|
|
interfaceStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_INTERFACE && expectName.size() == 0) {
|
|
expectName = k;
|
|
} else if (expect == EXPECT_INTERFACE && expectName.size() > 0 && k.toLower() == "extends") {
|
|
expect = EXPECT_INTERFACE_EXTENDED;
|
|
} else if (expect == EXPECT_INTERFACE_EXTENDED && expectName.size() > 0 && current_interface_parent.size() == 0 && k != "{") {
|
|
current_interface_parent = toAbs(current_namespace, k);
|
|
} else if ((expect == EXPECT_INTERFACE || expect == EXPECT_INTERFACE_EXTENDED) && expectName.size() > 0 && k == "{") {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
current_interface = ns + expectName;
|
|
int line = 0;
|
|
if (interfaceStart >= 0) line = getLine(origText, textOffset + interfaceStart);
|
|
addInterface(current_interface, current_interface_parent, line);
|
|
expect = -1;
|
|
expectName = "";
|
|
interfaceScope = scope;
|
|
current_class = "";
|
|
current_trait = "";
|
|
}
|
|
|
|
// traits
|
|
if (expect < 0 && k.toLower() == "trait" && (current_class.size() == 0 && current_interface.size() == 0 && current_trait.size() == 0) && anonymClassScope < 0) {
|
|
expect = EXPECT_TRAIT;
|
|
expectName = "";
|
|
traitStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_TRAIT && expectName.size() == 0) {
|
|
expectName = k;
|
|
} else if (expect == EXPECT_TRAIT && expectName.size() > 0 && k == "{") {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
current_trait = ns + expectName;
|
|
int line = 0;
|
|
if (traitStart >= 0) line = getLine(origText, textOffset + traitStart);
|
|
addTrait(current_trait, line);
|
|
expect = -1;
|
|
expectName = "";
|
|
traitScope = scope;
|
|
current_class = "";
|
|
current_interface = "";
|
|
}
|
|
|
|
// functions
|
|
if ((prevPrevK.size() == 0 || prevPrevK == ";" || prevPrevK == "{" || prevPrevK == "}" || prevPrevK == ">" || prevPrevK == ":") && prevK.size() > 0 && k == "=" && functionArgsStart < 0 && anonymFunctionScope < 0) {
|
|
expected_function_name = prevK;
|
|
}
|
|
if (expect < 0 && k.toLower() == "function" && (prevK == ";" || prevK == "{" || prevK == "}" || prevK == "=" || prevK.size() == 0 || prevK.toLower() == "public" || prevK.toLower() == "protected" || prevK.toLower() == "private" || prevK.toLower() == "static" || prevK.toLower() == "abstract") && functionArgsStart < 0 && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
expect = EXPECT_FUNCTION;
|
|
current_function_args = "";
|
|
expected_function_args.clear();
|
|
expected_function_arg_types.clear();
|
|
current_function_is_static = (prevK.toLower() == "static" || (prevK.size() > 1 && prevPrevK.toLower() == "static") || (prevK.size() > 1 && prevPrevK.size() > 1 && prevPrevPrevK.toLower() == "static"));
|
|
current_function_is_abstract = (prevK.toLower() == "abstract" || (prevK.size() > 1 && prevPrevK.toLower() == "abstract") || (prevK.size() > 1 && prevPrevK.size() > 1 && prevPrevPrevK.toLower() == "abstract"));
|
|
current_function_visibility = "";
|
|
if (prevK.toLower() == "public" || prevK.toLower() == "protected" || prevK.toLower() == "private") current_function_visibility = prevK.toLower();
|
|
if (prevK.size() > 1 && (prevPrevK.toLower() == "public" || prevPrevK.toLower() == "protected" || prevPrevK.toLower() == "private")) current_function_visibility = prevPrevK.toLower();
|
|
if (prevK.size() > 1 && prevPrevK.size() > 1 && (prevPrevPrevK.toLower() == "public" || prevPrevPrevK.toLower() == "protected" || prevPrevPrevK.toLower() == "private")) current_function_visibility = prevPrevPrevK.toLower();
|
|
current_function_min_args = 0;
|
|
current_function_max_args = 0;
|
|
current_function_return_type = "";
|
|
expectName = "";
|
|
functionArgPars = -1;
|
|
functionArgsStart = -1;
|
|
functionParsFound = false;
|
|
functionStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_FUNCTION && expectName.size() == 0 && k != "&" && k != "(" && k != ")" && k != "{" && k != "use" && functionArgsStart < 0 && current_function_args.size() == 0 && !functionParsFound) {
|
|
expectName = k;
|
|
} else if (expect == EXPECT_FUNCTION && functionArgPars < 0 && k == "(" && !functionParsFound) {
|
|
functionArgPars = pars;
|
|
functionArgsStart = m.capturedStart(1);
|
|
functionParsFound = true;
|
|
} else if (expect == EXPECT_FUNCTION && expectName.size() > 0 && functionArgPars < 0 && k == ":") {
|
|
expect = EXPECT_FUNCTION_RETURN_TYPE;
|
|
} else if (expect == EXPECT_FUNCTION_RETURN_TYPE && expectName.size() > 0 && (current_function_return_type.size() == 0 || current_function_return_type == "?") && k != "{" && k != ";") {
|
|
if (current_function_return_type == "?") current_function_return_type += k;
|
|
else current_function_return_type = k;
|
|
} else if ((expect == EXPECT_FUNCTION || expect == EXPECT_FUNCTION_RETURN_TYPE) && (expectName.size() > 0 || expected_function_name.size() > 0) && (k == "{" || (current_interface.size() > 0 && k == ";") || (current_function_is_abstract && k == ";")) && functionArgsStart < 0) {
|
|
if (expectName.size() > 0) {
|
|
current_function = expectName;
|
|
QString current_function_return_type_clean = current_function_return_type;
|
|
if (current_function_return_type_clean.size() > 0 && current_function_return_type_clean.mid(0, 1) == "?") {
|
|
current_function_return_type_clean = current_function_return_type_clean.mid(1);
|
|
}
|
|
if (current_function_return_type_clean.size() > 0) {
|
|
dataTypesIterator = dataTypes.find(current_function_return_type_clean.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
current_function_return_type_clean = toAbs(current_namespace, current_function_return_type_clean);
|
|
if (current_function_return_type.mid(0, 1) == "?") current_function_return_type = "?"+current_function_return_type_clean;
|
|
else current_function_return_type = current_function_return_type_clean;
|
|
}
|
|
}
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if (current_function_visibility.size() == 0 && clsName.size() > 0) current_function_visibility = "public";
|
|
int line = 0;
|
|
if (functionStart >= 0) line = getLine(origText, textOffset + functionStart);
|
|
QString current_comment = "";
|
|
int comment_line = getFirstNotEmptyLineTo(origText, textOffset + functionStart);
|
|
if (comment_line > 0) {
|
|
commentsIterator = comments.find(comment_line);
|
|
if (commentsIterator != comments.end()) {
|
|
current_comment = QString::fromStdString(commentsIterator->second);
|
|
}
|
|
}
|
|
if (current_comment.size() > 0) {
|
|
if (current_comment.indexOf("//")==0) current_comment = current_comment.mid(2);
|
|
else if (current_comment.indexOf("#")==0) current_comment = current_comment.mid(1);
|
|
else current_comment.replace(QRegularExpression("^[/][*](.*)[*][/]$", QRegularExpression::DotMatchesEverythingOption), "\\1");
|
|
QString current_comment_clean = "";
|
|
QStringList commentList = current_comment.split("\n");
|
|
for (int i=0; i<commentList.size(); i++) {
|
|
//QString current_comment_line = commentList.at(i).trimmed().replace(QRegularExpression("^[*]+[\\s]*"), "").replace(QRegularExpression("^[@]"), "- ");
|
|
QString current_comment_line = commentList.at(i).trimmed().replace(QRegularExpression("^[*]+[\\s]*"), "");
|
|
if (current_comment_line.size() == 0) continue;
|
|
if (current_comment_clean.size() > 0) current_comment_clean += "\n";
|
|
current_comment_clean += current_comment_line;
|
|
}
|
|
current_comment = current_comment_clean;
|
|
}
|
|
if (clsName.size() == 0) {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
current_function = ns + current_function;
|
|
}
|
|
addFunction(clsName, current_function, current_function_args, current_function_is_static, current_function_is_abstract, current_function_visibility, current_function_min_args, current_function_max_args, current_function_return_type, current_comment, line);
|
|
if (expected_function_args.size() > 0 && expected_function_args.size() == expected_function_arg_types.size()) {
|
|
for (int i=0; i<expected_function_args.size(); i++) {
|
|
QString argName = expected_function_args.at(i);
|
|
QString argType = expected_function_arg_types.at(i);
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
addVariable(clsName, current_function, argName, false, "", argType, line);
|
|
}
|
|
}
|
|
functionScope = scope;
|
|
if ((current_interface.size() > 0 && k == ";") || (current_function_is_abstract && k == ";")) {
|
|
current_function = "";
|
|
current_function_args = "";
|
|
current_function_is_static = false;
|
|
current_function_is_abstract = false;
|
|
current_function_visibility = "";
|
|
current_function_min_args = 0;
|
|
current_function_max_args = 0;
|
|
current_function_return_type = "";
|
|
expected_function_args.clear();
|
|
expected_function_arg_types.clear();
|
|
functionScope = -1;
|
|
functionArgPars = -1;
|
|
functionArgsStart = -1;
|
|
functionStart = -1;
|
|
functionParsFound = false;
|
|
expected_function_name = "";
|
|
}
|
|
} else {
|
|
anonymFunctionScope = scope;
|
|
if (current_function.size() > 0) {
|
|
functionChainList.append(current_function);
|
|
current_function = "";
|
|
}
|
|
}
|
|
expect = -1;
|
|
expectName = "";
|
|
functionArgPars = -1;
|
|
functionArgsStart = -1;
|
|
functionParsFound = false;
|
|
expected_function_name = "";
|
|
}
|
|
|
|
bool wantFunctionReturnType = current_function_return_type.size() == 0 && current_function.size() > 0;
|
|
|
|
// class method return "$this" type
|
|
if (wantFunctionReturnType && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevK.toLower() == "return" && prevK == "$this" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
current_function_return_type = current_class;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
} else if (wantFunctionReturnType && prevPrevK.toLower() == "return" && prevK.indexOf("$") == 0 && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "$var" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + current_function.toStdString() + "::" + prevK.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
if (variable.type.size() > 0) {
|
|
current_function_return_type = variable.type;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
} else if (wantFunctionReturnType && prevPrevPrevPrevK.toLower() == "return" && prevPrevPrevK.size() > 0 && prevPrevK == "(" && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "function()" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if (prevPrevPrevK[0] != "\\") {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
prevPrevPrevK = ns + prevPrevPrevK;
|
|
}
|
|
functionIndexesIterator = functionIndexes.find("::" + prevPrevPrevK.toStdString());
|
|
if (functionIndexesIterator != functionIndexes.end()) {
|
|
int i = functionIndexesIterator->second;
|
|
if (result.functions.size() > i) {
|
|
ParseResultFunction func = result.functions.at(i);
|
|
if (func.returnType.size() > 0) {
|
|
current_function_return_type = func.returnType;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
} else if (wantFunctionReturnType && prevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevK == "new" && prevPrevPrevK.size() > 0 && prevPrevK == "(" && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "new Class()" type
|
|
QString type = prevPrevPrevK;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((type.toLower() == "self" || type.toLower() == "static") && clsName.size() > 0) {
|
|
type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
type = toAbs(current_namespace, type);
|
|
}
|
|
updateFunctionReturnType(clsName, current_function, type);
|
|
} else if (wantFunctionReturnType && prevPrevPrevK.toLower() == "return" && prevPrevK == "new" && prevK.size() > 0 && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "new Class" type
|
|
QString type = prevK;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((type.toLower() == "self" || type.toLower() == "static") && clsName.size() > 0) {
|
|
type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
type = toAbs(current_namespace, type);
|
|
}
|
|
updateFunctionReturnType(clsName, current_function, type);
|
|
} else if (wantFunctionReturnType && prevPrevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevPrevK == "new" && prevPrevPrevPrevK.size() > 0 && prevPrevPrevK == "(" && prevPrevK.size() > 0 && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "new Class($var)" type
|
|
QString type = prevPrevPrevPrevK;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((type.toLower() == "self" || type.toLower() == "static") && clsName.size() > 0) {
|
|
type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
type = toAbs(current_namespace, type);
|
|
}
|
|
updateFunctionReturnType(clsName, current_function, type);
|
|
} else if (wantFunctionReturnType && prevPrevPrevPrevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevPrevPrevPrevK == "new" && prevPrevPrevPrevPrevPrevK.size() > 0 && prevPrevPrevPrevPrevK == "(" && prevPrevPrevPrevK.size() > 0 && prevPrevPrevK == "," && prevPrevK.size() > 0 && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "new Class($var1, $var2)" type
|
|
QString type = prevPrevPrevPrevPrevPrevK;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((type.toLower() == "self" || type.toLower() == "static") && clsName.size() > 0) {
|
|
type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
type = toAbs(current_namespace, type);
|
|
}
|
|
updateFunctionReturnType(clsName, current_function, type);
|
|
} else if (wantFunctionReturnType && prevPrevPrevPrevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevPrevPrevPrevK == "new" && prevPrevPrevPrevPrevPrevK.size() > 0 && prevPrevPrevPrevPrevK == "(" && prevPrevPrevPrevK.size() > 0 && prevPrevPrevK == "(" && prevPrevK == ")" && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "new Class(func())" type
|
|
QString type = prevPrevPrevPrevPrevPrevK;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((type.toLower() == "self" || type.toLower() == "static") && clsName.size() > 0) {
|
|
type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
type = toAbs(current_namespace, type);
|
|
}
|
|
updateFunctionReturnType(clsName, current_function, type);
|
|
} else if (wantFunctionReturnType && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevPrevPrevPrevK.toLower() == "return" && (prevPrevPrevPrevK.toLower() == "self" || prevPrevPrevPrevK.toLower() == "static") && prevPrevPrevK == ":" && prevPrevK == ":" && prevK.indexOf("$") == 0 && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "self::$var" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + "::" + prevK.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
if (variable.isStatic && variable.type.size() > 0) {
|
|
current_function_return_type = variable.type;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
} else if (wantFunctionReturnType && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevK == "$this" && prevPrevPrevK == "-" && prevPrevK == ">" && prevK.indexOf("$") < 0 && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "$this->var" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + "::" + "$" + prevK.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
if (variable.type.size() > 0) {
|
|
current_function_return_type = variable.type;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
} else if (wantFunctionReturnType && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevPrevPrevPrevPrevPrevK.toLower() == "return" && (prevPrevPrevPrevPrevPrevK.toLower() == "self" || prevPrevPrevPrevPrevPrevK.toLower() == "static") && prevPrevPrevPrevPrevK == ":" && prevPrevPrevPrevK == ":" && prevPrevPrevK.size() > 0 && prevPrevK == "(" && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "self::function()" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
functionIndexesIterator = functionIndexes.find(clsName.toStdString() + "::" + prevPrevPrevK.toStdString());
|
|
if (functionIndexesIterator != functionIndexes.end()) {
|
|
int i = functionIndexesIterator->second;
|
|
if (result.functions.size() > i) {
|
|
ParseResultFunction func = result.functions.at(i);
|
|
if (func.isStatic && func.returnType.size() > 0) {
|
|
current_function_return_type = func.returnType;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
} else if (wantFunctionReturnType && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevPrevPrevPrevPrevPrevK.toLower() == "return" && prevPrevPrevPrevPrevPrevK == "$this" && prevPrevPrevPrevPrevK == "-" && prevPrevPrevPrevK == ">" && prevPrevPrevK.size() > 0 && prevPrevK == "(" && prevK == ")" && k == ";" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// function return "$this->function()" type
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
functionIndexesIterator = functionIndexes.find(clsName.toStdString() + "::" + prevPrevPrevK.toStdString());
|
|
if (functionIndexesIterator != functionIndexes.end()) {
|
|
int i = functionIndexesIterator->second;
|
|
if (result.functions.size() > i) {
|
|
ParseResultFunction func = result.functions.at(i);
|
|
if (func.returnType.size() > 0) {
|
|
current_function_return_type = func.returnType;
|
|
updateFunctionReturnType(clsName, current_function, current_function_return_type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// variables
|
|
if (expect < 0 && functionArgPars < 0 && k.indexOf("$") == 0 && prevK != ":" && prevK != ">" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
expect = EXPECT_VARIABLE;
|
|
expectName = k;
|
|
current_variable = "";
|
|
current_variable_type = "";
|
|
class_static_variable = "";
|
|
class_variable = "";
|
|
if ((current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && current_function.size() == 0) {
|
|
current_variable_is_static = (prevK.toLower() == "static" || (prevK.size() > 1 && prevPrevK.toLower() == "static"));
|
|
current_variable_visibility = "public";
|
|
if (prevK.toLower() == "public" || prevK.toLower() == "protected" || prevK.toLower() == "private") current_variable_visibility = prevK.toLower();
|
|
if (prevK.size() > 1 && (prevPrevK.toLower() == "public" || prevPrevK.toLower() == "protected" || prevPrevK.toLower() == "private")) current_variable_visibility = prevPrevK.toLower();
|
|
} else {
|
|
current_variable_is_static = false;
|
|
current_variable_visibility = "";
|
|
}
|
|
variableStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_VARIABLE && expectName.size() > 0 && current_variable.size() == 0 && (k == "=" || (k == ";" && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && current_function.size() == 0))) {
|
|
current_variable = expectName;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
int line = 0;
|
|
if (variableStart >= 0) line = getLine(origText, textOffset + variableStart);
|
|
addVariable(clsName, current_function, current_variable, current_variable_is_static, current_variable_visibility, current_variable_type, line);
|
|
expect = -1;
|
|
expectName = "";
|
|
class_static_variable = "";
|
|
class_variable = "";
|
|
}
|
|
|
|
// class static variable
|
|
if (class_static_variable.size() == 0 && functionArgPars < 0 && k.indexOf("$") == 0 && prevK == ":" && prevPrevK == ":" && (prevPrevPrevK.toLower() == "self" || prevPrevPrevK.toLower() == "static") && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + "::" + k.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
if (variable.isStatic && variable.type.size() == 0) {
|
|
class_static_variable = k;
|
|
current_variable = "";
|
|
current_variable_type = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// class property
|
|
if (class_variable.size() == 0 && functionArgPars < 0 && k.indexOf("$") < 0 && prevK == ">" && prevPrevK == "-" && prevPrevPrevK == "$this" && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
variableIndexesIterator = variableIndexes.find(clsName.toStdString() + "::" + "::" + "$" + k.toStdString());
|
|
if (variableIndexesIterator != variableIndexes.end()) {
|
|
int i = variableIndexesIterator->second;
|
|
if (result.variables.size() > i) {
|
|
ParseResultVariable variable = result.variables.at(i);
|
|
if (variable.type.size() == 0) {
|
|
class_variable = k;
|
|
current_variable = "";
|
|
current_variable_type = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// variable type
|
|
if (current_variable.size() > 0 && prevPrevK == "=" && prevK.toLower() == "new" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
current_variable_type = k;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((current_variable_type.toLower() == "self" || current_variable_type.toLower() == "static") && clsName.size() > 0) {
|
|
current_variable_type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(current_variable_type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
current_variable_type = toAbs(current_namespace, current_variable_type);
|
|
}
|
|
updateVariableType(clsName, current_function, current_variable, current_variable_type);
|
|
} else if (class_static_variable.size() > 0 && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevK == "=" && prevK.toLower() == "new" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// class static variable type
|
|
QString class_static_variable_type = k;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((class_static_variable_type.toLower() == "self" || class_static_variable_type.toLower() == "static") && clsName.size() > 0) {
|
|
class_static_variable_type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(class_static_variable_type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
class_static_variable_type = toAbs(current_namespace, class_static_variable_type);
|
|
}
|
|
updateVariableType(clsName, "", class_static_variable, class_static_variable_type);
|
|
} else if (class_variable.size() > 0 && (current_class.size() > 0 || current_interface.size() > 0 || current_trait.size() > 0) && prevPrevK == "=" && prevK.toLower() == "new" && anonymFunctionScope < 0 && anonymClassScope < 0) {
|
|
// class property type
|
|
QString class_variable_type = k;
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
if ((class_variable_type.toLower() == "self" || class_variable_type.toLower() == "static") && clsName.size() > 0) {
|
|
class_variable_type = clsName;
|
|
}
|
|
dataTypesIterator = dataTypes.find(class_variable_type.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
class_variable_type = toAbs(current_namespace, class_variable_type);
|
|
}
|
|
updateVariableType(clsName, "", "$" + class_variable, class_variable_type);
|
|
}
|
|
|
|
// constants
|
|
if (expect < 0 && k.toLower() == "const" && functionArgsStart < 0 && (prevK == ";" || prevK == "{" || prevK == "}" || prevK.size() == 0) && anonymFunctionScope < 0 && (((namespaceScope < 0 && scope == 0) || scope == namespaceScope+1) || (current_class.size() > 0 && scope == classScope + 1) || (current_interface.size() > 0 && scope == interfaceScope + 1) || (current_trait.size() > 0 && scope == traitScope + 1))) {
|
|
expect = EXPECT_CONST;
|
|
expectName = "";
|
|
current_constant = "";
|
|
current_constant_value = "";
|
|
constantValueStart = -1;
|
|
constantStart = m.capturedStart(1);
|
|
} else if (expect == EXPECT_CONST && expectName.size() == 0 && k.size() > 0) {
|
|
expectName = k;
|
|
} else if (expect == EXPECT_CONST && expectName.size() > 0 && k == "=") {
|
|
expect = EXPECT_CONST_VALUE;
|
|
constantValueStart = m.capturedStart(1) + 1;
|
|
} else if (expect == EXPECT_CONST_VALUE && expectName.size() > 0 && k == ";") {
|
|
current_constant = expectName;
|
|
current_constant_value = origText.mid(textOffset+constantValueStart, m.capturedStart(1)-constantValueStart).trimmed();
|
|
QString clsName = "";
|
|
if (current_class.size() > 0) clsName = current_class;
|
|
else if (current_interface.size() > 0) clsName = current_interface;
|
|
else if (current_trait.size() > 0) clsName = current_trait;
|
|
int line = 0;
|
|
if (constantStart >= 0) line = getLine(origText, textOffset + constantStart);
|
|
if (clsName.size() == 0) {
|
|
QString ns = "\\";
|
|
if (current_namespace.size() > 0) ns += current_namespace + "\\";
|
|
current_constant = ns + current_constant;
|
|
}
|
|
addConstant(clsName, current_constant, current_constant_value, line);
|
|
expect = -1;
|
|
expectName = "";
|
|
constantValueStart = -1;
|
|
}
|
|
|
|
if ((expect == EXPECT_VARIABLE ||
|
|
expect == EXPECT_USE ||
|
|
expect == EXPECT_USE_FUNCTION ||
|
|
expect == EXPECT_USE_CONSTANT ||
|
|
expect == EXPECT_NAMESPACE ||
|
|
expect == EXPECT_CLASS_EXTENDED ||
|
|
expect == EXPECT_CLASS_IMPLEMENTED ||
|
|
expect == EXPECT_CLASS_EXTENDED_IMPLEMENTED ||
|
|
expect == EXPECT_INTERFACE ||
|
|
expect == EXPECT_INTERFACE_EXTENDED ||
|
|
expect == EXPECT_TRAIT ||
|
|
class_static_variable.size() > 0 || class_variable.size() > 0
|
|
) && (k == "-" || k == "+" || k == "*" || k == "/" || k == "%" || k == "&" || k == "|" || k == ":" || k == ">" || k == "<" || k == "?" || k == "[" || k == "]" || k == "(" || k == ")") && functionArgsStart < 0
|
|
) {
|
|
expect = -1;
|
|
expectName = "";
|
|
class_static_variable = "";
|
|
class_variable = "";
|
|
}
|
|
|
|
if ((k == ";" || ((k == "{" || k == "}") && expect != EXPECT_USE)) && functionArgsStart < 0) {
|
|
expect = -1;
|
|
expectName = "";
|
|
class_static_variable = "";
|
|
class_variable = "";
|
|
expected_function_name = "";
|
|
expected_class_name = "";
|
|
}
|
|
// braces
|
|
if (k == "{") {
|
|
scope++;
|
|
curlyBrackets++;
|
|
curlyBracketsList.append(m.capturedStart(1)+1);
|
|
}
|
|
if (k == "}") {
|
|
scope--;
|
|
if (scope < 0) scope = 0;
|
|
curlyBrackets--;
|
|
curlyBracketsList.append(-1 * (m.capturedStart(1)+1));
|
|
// namespace close
|
|
if (current_namespace.size() > 0 && namespaceScope >= 0 && namespaceScope == scope) {
|
|
current_namespace = "";
|
|
namespaceScope = -1;
|
|
if (parent_namespaces.size() > 0 && parent_namespaces.size() == parent_namespace_scopes.size()) {
|
|
current_namespace = parent_namespaces.last();
|
|
namespaceScope = parent_namespace_scopes.last();
|
|
parent_namespaces.removeLast();
|
|
parent_namespace_scopes.removeLast();
|
|
}
|
|
namespaceStart = -1;
|
|
}
|
|
// class close
|
|
if (current_class.size() > 0 && classScope >= 0 && classScope == scope) {
|
|
current_class = "";
|
|
current_class_is_abstract = false;
|
|
current_class_parent = "";
|
|
current_class_interfaces.clear();
|
|
classScope = -1;
|
|
classStart = -1;
|
|
expected_class_name = "";
|
|
classParsFound = false;
|
|
}
|
|
// anonymous class close
|
|
if (anonymClassScope >= 0 && anonymClassScope == scope) {
|
|
anonymClassScope = -1;
|
|
if (!classChainList.isEmpty()) {
|
|
current_class = classChainList.last();
|
|
classChainList.removeLast();
|
|
} else if (!traitChainList.isEmpty()) {
|
|
current_trait = traitChainList.last();
|
|
traitChainList.removeLast();
|
|
}
|
|
}
|
|
// interface close
|
|
if (current_interface.size() > 0 && interfaceScope >= 0 && interfaceScope == scope) {
|
|
current_interface = "";
|
|
current_interface_parent = "";
|
|
interfaceScope = -1;
|
|
interfaceStart = -1;
|
|
}
|
|
// trait close
|
|
if (current_trait.size() > 0 && traitScope >= 0 && traitScope == scope) {
|
|
current_trait = "";
|
|
traitScope = -1;
|
|
traitStart = -1;
|
|
}
|
|
// function close
|
|
if (current_function.size() > 0 && functionScope >= 0 && functionScope == scope) {
|
|
current_function = "";
|
|
current_function_args = "";
|
|
current_function_is_static = false;
|
|
current_function_is_abstract = false;
|
|
current_function_visibility = "";
|
|
current_function_min_args = 0;
|
|
current_function_max_args = 0;
|
|
current_function_return_type = "";
|
|
expected_function_args.clear();
|
|
expected_function_arg_types.clear();
|
|
functionScope = -1;
|
|
functionArgPars = -1;
|
|
functionArgsStart = -1;
|
|
functionStart = -1;
|
|
functionParsFound = false;
|
|
expected_function_name = "";
|
|
}
|
|
// anonymous function close
|
|
if (anonymFunctionScope >= 0 && anonymFunctionScope == scope) {
|
|
anonymFunctionScope = -1;
|
|
if (!functionChainList.isEmpty()) {
|
|
current_function = functionChainList.last();
|
|
functionChainList.removeLast();
|
|
}
|
|
}
|
|
}
|
|
// parens
|
|
if (k == "(") {
|
|
pars++;
|
|
roundBrackets++;
|
|
roundBracketsList.append(m.capturedStart(1)+1);
|
|
}
|
|
if (k == ")") {
|
|
pars--;
|
|
if (pars < 0) pars = 0;
|
|
roundBrackets--;
|
|
roundBracketsList.append(-1 * (m.capturedStart(1)+1));
|
|
// function args
|
|
if (functionArgPars >= 0 && functionArgPars == pars && functionArgsStart >= 0) {
|
|
current_function_args = origText.mid(textOffset+functionArgsStart+1, m.capturedStart(1)-functionArgsStart-1).trimmed();
|
|
current_function_args = Helper::stripScopedText(current_function_args);
|
|
if (current_function_args.size() > 0) {
|
|
QString current_function_args_cleaned = "";
|
|
QStringList argsList, argsDefaultsList, argsTypeList;
|
|
QString argType, argName, argDefault;
|
|
argsList = current_function_args.split(",");
|
|
for (int i=0; i<argsList.size(); i++) {
|
|
argType = ""; argName = ""; argDefault = "";
|
|
argsDefaultsList = argsList.at(i).trimmed().split("=");
|
|
if (argsDefaultsList.size() == 2) {
|
|
argDefault = argsDefaultsList.at(1).trimmed();
|
|
} else if (argsDefaultsList.size() > 2) {
|
|
continue;
|
|
}
|
|
argsTypeList = argsDefaultsList.at(0).trimmed().replace(QRegularExpression("[&][\\s]+"), "&").split(QRegularExpression("[\\s]"));
|
|
if (argsTypeList.size() == 2) {
|
|
argType = argsTypeList.at(0).trimmed();
|
|
argName = argsTypeList.at(1).trimmed();
|
|
} else if (argsTypeList.size() == 1) {
|
|
argName = argsTypeList.at(0).trimmed();
|
|
} else {
|
|
continue;
|
|
}
|
|
if (argName.size() == 0 || (argName.indexOf("$") != 0 && argName.indexOf("&$") != 0)) {
|
|
continue;
|
|
}
|
|
QString argNameClean = argName;
|
|
if (argNameClean.mid(0, 1) == "&") argNameClean = argNameClean.mid(1);
|
|
if (argType.size() > 0) {
|
|
dataTypesIterator = dataTypes.find(argType.toLower().toStdString());
|
|
if (dataTypesIterator == dataTypes.end()) {
|
|
argType = toAbs(current_namespace, argType);
|
|
}
|
|
} else {
|
|
argType = "mixed";
|
|
}
|
|
current_function_max_args++;
|
|
if (argDefault.size() == 0) {
|
|
current_function_min_args++;
|
|
}
|
|
expected_function_args.append(argNameClean);
|
|
expected_function_arg_types.append(argType);
|
|
if (argType.size() > 0) {
|
|
argType += " ";
|
|
}
|
|
if (current_function_args_cleaned.size() > 0) {
|
|
current_function_args_cleaned += ", ";
|
|
}
|
|
if (argDefault.size() > 0) argDefault = " = "+argDefault;
|
|
current_function_args_cleaned += argType + argName + argDefault;
|
|
}
|
|
current_function_args = current_function_args_cleaned;
|
|
}
|
|
functionArgPars = -1;
|
|
functionArgsStart = -1;
|
|
}
|
|
}
|
|
// brackets
|
|
if (k == "[") {
|
|
squareBrackets++;
|
|
squareBracketsList.append(m.capturedStart(1)+1);
|
|
}
|
|
if (k == "]") {
|
|
squareBrackets--;
|
|
squareBracketsList.append(-1 * (m.capturedStart(1)+1));
|
|
}
|
|
prevPrevPrevPrevPrevPrevPrevPrevK = prevPrevPrevPrevPrevPrevPrevK;
|
|
prevPrevPrevPrevPrevPrevPrevK = prevPrevPrevPrevPrevPrevK;
|
|
prevPrevPrevPrevPrevPrevK = prevPrevPrevPrevPrevK;
|
|
prevPrevPrevPrevPrevK = prevPrevPrevPrevK;
|
|
prevPrevPrevPrevK = prevPrevPrevK;
|
|
prevPrevPrevK = prevPrevK;
|
|
prevPrevK = prevK;
|
|
prevK = k;
|
|
}
|
|
if (curlyBrackets > 0) {
|
|
int offset = findOpenScope(curlyBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Unclosed brace"), line, textOffset + offset);
|
|
} else if (curlyBrackets < 0) {
|
|
int offset = findCloseScope(curlyBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Excess brace"), line, textOffset + offset);
|
|
}
|
|
if (roundBrackets > 0) {
|
|
int offset = findOpenScope(roundBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Unclosed parenthesis"), line, textOffset + offset);
|
|
} else if (roundBrackets < 0) {
|
|
int offset = findCloseScope(roundBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Excess parenthesis"), line, textOffset + offset);
|
|
}
|
|
if (squareBrackets > 0) {
|
|
int offset = findOpenScope(squareBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Unclosed bracket"), line, textOffset + offset);
|
|
} else if (squareBrackets < 0) {
|
|
int offset = findCloseScope(squareBracketsList);
|
|
if (offset != 0) offset = abs(offset) - 1;
|
|
int line = getLine(origText, textOffset + offset);
|
|
addError(QObject::tr("Excess bracket"), line, textOffset + offset);
|
|
}
|
|
}
|
|
|
|
void ParsePHP::reset()
|
|
{
|
|
classAliases.clear();
|
|
functionAliases.clear();
|
|
constantAliases.clear();
|
|
functionIndexes.clear();
|
|
variableIndexes.clear();
|
|
constantIndexes.clear();
|
|
namespaceIndexes.clear();
|
|
importIndexes.clear();
|
|
classIndexes.clear();
|
|
comments.clear();
|
|
}
|
|
|
|
ParsePHP::ParseResult ParsePHP::parse(QString text)
|
|
{
|
|
result = ParseResult();
|
|
reset();
|
|
QString cleanText = cleanUp(text);
|
|
QRegularExpressionMatchIterator mi = phpExpression.globalMatch(cleanText);
|
|
while(mi.hasNext()){
|
|
QRegularExpressionMatch m = mi.next();
|
|
if (m.capturedStart(1) < 0) continue;
|
|
if (m.captured(1).trimmed().size() == 0) continue;
|
|
QString code = m.captured(1);
|
|
parseCode(code, text, m.capturedStart(1));
|
|
}
|
|
// comments
|
|
std::map<int, std::string> orderedComments(comments.begin(), comments.end());
|
|
for (auto & commentsIterator : orderedComments) {
|
|
addComment(QString::fromStdString(commentsIterator.second), commentsIterator.first);
|
|
}
|
|
return result;
|
|
}
|