work save
This commit is contained in:
parent
4afe1f4315
commit
f8ab38b634
|
@ -904,18 +904,19 @@ void CppParser::parseHardDefines()
|
||||||
});
|
});
|
||||||
for (const PDefine& define:mPreprocessor.hardDefines()) {
|
for (const PDefine& define:mPreprocessor.hardDefines()) {
|
||||||
addStatement(
|
addStatement(
|
||||||
PStatement(), // defines don't belong to any scope
|
PStatement(), // defines don't belong to any scope
|
||||||
"",
|
"",
|
||||||
"", // define has no type
|
"", // define has no type
|
||||||
define->name,
|
define->name,
|
||||||
define->value,
|
define->args,
|
||||||
define->args,
|
"",
|
||||||
-1,
|
define->value,
|
||||||
StatementKind::skPreprocessor,
|
-1,
|
||||||
StatementScope::ssGlobal,
|
StatementKind::skPreprocessor,
|
||||||
StatementClassScope::scsNone,
|
StatementScope::ssGlobal,
|
||||||
true,
|
StatementClassScope::scsNone,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1133,18 +1134,19 @@ PStatement CppParser::addInheritedStatement(const PStatement& derived, const PSt
|
||||||
{
|
{
|
||||||
|
|
||||||
PStatement statement = addStatement(
|
PStatement statement = addStatement(
|
||||||
derived,
|
derived,
|
||||||
inherit->fileName,
|
inherit->fileName,
|
||||||
inherit->type, // "Type" is already in use
|
inherit->type, // "Type" is already in use
|
||||||
inherit->command,
|
inherit->command,
|
||||||
inherit->args,
|
inherit->args,
|
||||||
inherit->value,
|
inherit->noNameArgs,
|
||||||
inherit->line,
|
inherit->value,
|
||||||
inherit->kind,
|
inherit->line,
|
||||||
inherit->scope,
|
inherit->kind,
|
||||||
access,
|
inherit->scope,
|
||||||
true,
|
access,
|
||||||
inherit->isStatic);
|
true,
|
||||||
|
inherit->isStatic);
|
||||||
statement->isInherited = true;
|
statement->isInherited = true;
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
@ -1152,6 +1154,7 @@ PStatement CppParser::addInheritedStatement(const PStatement& derived, const PSt
|
||||||
PStatement CppParser::addChildStatement(const PStatement& parent, const QString &fileName,
|
PStatement CppParser::addChildStatement(const PStatement& parent, const QString &fileName,
|
||||||
const QString &aType,
|
const QString &aType,
|
||||||
const QString &command, const QString &args,
|
const QString &command, const QString &args,
|
||||||
|
const QString& noNameArgs,
|
||||||
const QString &value, int line, StatementKind kind,
|
const QString &value, int line, StatementKind kind,
|
||||||
const StatementScope& scope, const StatementClassScope& classScope,
|
const StatementScope& scope, const StatementClassScope& classScope,
|
||||||
bool isDefinition, bool isStatic)
|
bool isDefinition, bool isStatic)
|
||||||
|
@ -1162,6 +1165,7 @@ PStatement CppParser::addChildStatement(const PStatement& parent, const QString
|
||||||
aType,
|
aType,
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
|
noNameArgs,
|
||||||
value,
|
value,
|
||||||
line,
|
line,
|
||||||
kind,
|
kind,
|
||||||
|
@ -1176,6 +1180,7 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
||||||
const QString &aType,
|
const QString &aType,
|
||||||
const QString &command,
|
const QString &command,
|
||||||
const QString &args,
|
const QString &args,
|
||||||
|
const QString &noNameArgs,
|
||||||
const QString &value,
|
const QString &value,
|
||||||
int line, StatementKind kind,
|
int line, StatementKind kind,
|
||||||
const StatementScope& scope,
|
const StatementScope& scope,
|
||||||
|
@ -1192,13 +1197,11 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
||||||
// qDebug()<<command<<fileName<<line<<kind<<parent->fullName;
|
// qDebug()<<command<<fileName<<line<<kind<<parent->fullName;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
QString noNameArgs = "";
|
|
||||||
if (kind == StatementKind::skConstructor
|
if (kind == StatementKind::skConstructor
|
||||||
|| kind == StatementKind::skFunction
|
|| kind == StatementKind::skFunction
|
||||||
|| kind == StatementKind::skDestructor
|
|| kind == StatementKind::skDestructor
|
||||||
|| kind == StatementKind::skVariable
|
|| kind == StatementKind::skVariable
|
||||||
) {
|
) {
|
||||||
noNameArgs = removeArgNames(args);
|
|
||||||
//find
|
//find
|
||||||
if (isDefinition) {
|
if (isDefinition) {
|
||||||
PStatement oldStatement = findStatementInScope(newCommand,noNameArgs,kind,parent);
|
PStatement oldStatement = findStatementInScope(newCommand,noNameArgs,kind,parent);
|
||||||
|
@ -1270,18 +1273,96 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PStatement CppParser::addStatement(const PStatement &parent, const QString &fileName, const QString &aType, const QString &command, int argStart, int argEnd, const QString &value, int line, StatementKind kind, const StatementScope &scope, const StatementClassScope &classScope, bool isDefinition, bool isStatic)
|
||||||
|
{
|
||||||
|
QString args("(");
|
||||||
|
QString noNameArgs("(");
|
||||||
|
|
||||||
|
int start=argStart+1;
|
||||||
|
bool typeGetted = false;
|
||||||
|
int braceLevel=0;
|
||||||
|
QString word;
|
||||||
|
for (int i=start;i<argEnd;i++) {
|
||||||
|
QChar ch=mTokenizer[i]->text[0];
|
||||||
|
if (this->isLetterChar(ch)) {
|
||||||
|
QString spaces=(i>argStart)?" ":"";
|
||||||
|
args+=spaces;
|
||||||
|
word += mTokenizer[i]->text[0];
|
||||||
|
if (!typeGetted) {
|
||||||
|
noNameArgs+=spaces+word;
|
||||||
|
if (mCppTypeKeywords.contains(word) || !isCppKeyword(word))
|
||||||
|
typeGetted = true;
|
||||||
|
} else {
|
||||||
|
if (isCppKeyword(word)) {
|
||||||
|
noNameArgs+=spaces+word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
word="";
|
||||||
|
} else if (this->isDigitChar(ch)) {
|
||||||
|
args+=" ";
|
||||||
|
} else {
|
||||||
|
switch(ch.unicode()) {
|
||||||
|
case ',':
|
||||||
|
if (braceLevel==0)
|
||||||
|
typeGetted=false;
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
case '<':
|
||||||
|
case '(':
|
||||||
|
braceLevel++;
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
case '>':
|
||||||
|
case ')':
|
||||||
|
braceLevel--;
|
||||||
|
break;
|
||||||
|
//todo: * and & processing
|
||||||
|
case '*':
|
||||||
|
case '&':
|
||||||
|
if (braceLevel==0)
|
||||||
|
word+=ch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
noNameArgs+= mTokenizer[i]->text;
|
||||||
|
}
|
||||||
|
args+=mTokenizer[i]->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push_back(")");
|
||||||
|
noNameArgs.push_back(")");
|
||||||
|
return addStatement(
|
||||||
|
parent,
|
||||||
|
fileName,
|
||||||
|
aType,
|
||||||
|
command,
|
||||||
|
args,
|
||||||
|
noNameArgs,
|
||||||
|
value,
|
||||||
|
line,
|
||||||
|
kind,
|
||||||
|
scope,
|
||||||
|
classScope,
|
||||||
|
isDefinition,
|
||||||
|
isStatic);
|
||||||
|
}
|
||||||
|
|
||||||
void CppParser::setInheritance(int index, const PStatement& classStatement, bool isStruct)
|
void CppParser::setInheritance(int index, const PStatement& classStatement, bool isStruct)
|
||||||
{
|
{
|
||||||
// Clear it. Assume it is assigned
|
// Clear it. Assume it is assigned
|
||||||
StatementClassScope lastInheritScopeType = StatementClassScope::scsNone;
|
StatementClassScope lastInheritScopeType = StatementClassScope::scsNone;
|
||||||
// Assemble a list of statements in text form we inherit from
|
// Assemble a list of statements in text form we inherit from
|
||||||
while (true) {
|
while (true) {
|
||||||
StatementClassScope inheritScopeType = getClassScope(index);
|
StatementClassScope inheritScopeType = getClassScope(mTokenizer[index]->text);
|
||||||
if (inheritScopeType == StatementClassScope::scsNone) {
|
QString currentText = mTokenizer[index]->text;
|
||||||
if (mTokenizer[index]->text.front()!=','
|
if (currentText=='(') {
|
||||||
&& mTokenizer[index]->text.front()!=':'
|
//skip to matching ')'
|
||||||
&& mTokenizer[index]->text.front()!='(') {
|
index=mTokenizer[index]->matchIndex;
|
||||||
QString basename = mTokenizer[index]->text;
|
} else if (inheritScopeType == StatementClassScope::scsNone) {
|
||||||
|
if (currentText.front()!=','
|
||||||
|
&& currentText.front()!=':') {
|
||||||
|
QString basename = currentText;
|
||||||
//remove template staff
|
//remove template staff
|
||||||
if (basename.endsWith('>')) {
|
if (basename.endsWith('>')) {
|
||||||
int pBegin = basename.indexOf('<');
|
int pBegin = basename.indexOf('<');
|
||||||
|
@ -1525,7 +1606,8 @@ bool CppParser::checkForKeyword()
|
||||||
return st!=SkipType::skNone;
|
return st!=SkipType::skNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, bool &isStatic, bool &isFriend)
|
bool CppParser::checkForMethod(QString &sType, QString &sName, int &argStartIndex,
|
||||||
|
int &argEndIndex, , bool &isStatic, bool &isFriend)
|
||||||
{
|
{
|
||||||
PStatement scope = getCurrentScope();
|
PStatement scope = getCurrentScope();
|
||||||
|
|
||||||
|
@ -1546,7 +1628,6 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
||||||
|
|
||||||
sType = ""; // should contain type "int"
|
sType = ""; // should contain type "int"
|
||||||
sName = ""; // should contain function name "foo::function"
|
sName = ""; // should contain function name "foo::function"
|
||||||
sArgs = ""; // should contain argument list "(int a)"
|
|
||||||
|
|
||||||
bool bTypeOK = false;
|
bool bTypeOK = false;
|
||||||
bool bNameOK = false;
|
bool bNameOK = false;
|
||||||
|
@ -1558,20 +1639,34 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
||||||
// Gather data for the string parts
|
// Gather data for the string parts
|
||||||
while ((mIndex < mTokenizer.tokenCount()) && !isSeperator(mTokenizer[mIndex]->text[0])) {
|
while ((mIndex < mTokenizer.tokenCount()) && !isSeperator(mTokenizer[mIndex]->text[0])) {
|
||||||
if ((mIndex + 1 < mTokenizer.tokenCount())
|
if ((mIndex + 1 < mTokenizer.tokenCount())
|
||||||
&& (mTokenizer[mIndex + 1]->text[0] == '(')) { // and start of a function
|
&& (mTokenizer[mIndex + 1]->text == '(')) { // and start of a function
|
||||||
|
int indexAfter = mTokenizer[mIndex + 1]->matchIndex+1;
|
||||||
//it's not a function define
|
//it's not a function define
|
||||||
if ((mIndex+2 < mTokenizer.tokenCount()) && (mTokenizer[mIndex + 2]->text[0] == ','))
|
if ((indexAfter < mTokenizer.tokenCount()) && (mTokenizer[indexAfter]->text[0] == ','))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((mIndex+2 < mTokenizer.tokenCount()) && (mTokenizer[mIndex + 2]->text[0] == ';')) {
|
if ((indexAfter < mTokenizer.tokenCount()) && (mTokenizer[indexAfter]->text[0] == ';')) {
|
||||||
if (isNotFuncArgs(mTokenizer[mIndex + 1]->text))
|
//function can only be defined in global/namespaces/classes
|
||||||
|
if (!mCurrentScope.isEmpty()) {
|
||||||
|
PStatement currentScope=mCurrentScope.last();
|
||||||
|
//in namespace, it might be function or object initilization
|
||||||
|
if (currentScope->kind == StatementKind::skNamespace
|
||||||
|
&& isNotFuncArgs(mIndex + 1,mTokenizer[mIndex + 1]->matchIndex)) {
|
||||||
|
break;
|
||||||
|
//not in class, it can't be a valid function definition
|
||||||
|
} else if (currentScope->kind != StatementKind::skClass)
|
||||||
|
break;
|
||||||
|
//variable can't be initialized in class definition, it must be a function
|
||||||
|
} else if (isNotFuncArgs(mIndex + 1,mTokenizer[mIndex + 1]->matchIndex))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sName = mTokenizer[mIndex]->text;
|
sName = mTokenizer[mIndex]->text;
|
||||||
sArgs = mTokenizer[mIndex + 1]->text;
|
argStartIndex = mIndex+1;
|
||||||
|
argEndIndex = mTokenizer[mIndex + 1]->matchIndex;
|
||||||
bTypeOK = !sType.isEmpty();
|
bTypeOK = !sType.isEmpty();
|
||||||
bNameOK = !sName.isEmpty();
|
bNameOK = !sName.isEmpty();
|
||||||
bArgsOK = !sArgs.isEmpty();
|
bArgsOK = true;
|
||||||
|
mIndex = argEndIndex;
|
||||||
|
|
||||||
// Allow constructor/destructor too
|
// Allow constructor/destructor too
|
||||||
if (!bTypeOK) {
|
if (!bTypeOK) {
|
||||||
|
@ -1619,7 +1714,6 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
||||||
if (bTypeOK && bNameOK && bArgsOK) {
|
if (bTypeOK && bNameOK && bArgsOK) {
|
||||||
sType = sType.trimmed(); // should contain type "int"
|
sType = sType.trimmed(); // should contain type "int"
|
||||||
sName = sName.trimmed(); // should contain function name "foo::function"
|
sName = sName.trimmed(); // should contain function name "foo::function"
|
||||||
sArgs = sArgs.trimmed(); // should contain argument list "(int a)"
|
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
|
@ -1972,18 +2066,19 @@ void CppParser::handleCatchBlock()
|
||||||
}
|
}
|
||||||
// add a block
|
// add a block
|
||||||
PStatement block = addStatement(
|
PStatement block = addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
startLine,
|
"",
|
||||||
StatementKind::skBlock,
|
startLine,
|
||||||
getScope(),
|
StatementKind::skBlock,
|
||||||
mClassScope,
|
getScope(),
|
||||||
true,
|
mClassScope,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
addSoloScopeLevel(block,startLine,false);
|
addSoloScopeLevel(block,startLine,false);
|
||||||
if (!mTokenizer[mIndex]->text.contains("..."))
|
if (!mTokenizer[mIndex]->text.contains("..."))
|
||||||
scanMethodArgs(block,mTokenizer[mIndex]->text);
|
scanMethodArgs(block,mTokenizer[mIndex]->text);
|
||||||
|
@ -2044,6 +2139,7 @@ void CppParser::handleEnum()
|
||||||
enumName,
|
enumName,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skEnumClassType,
|
StatementKind::skEnumClassType,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2058,6 +2154,7 @@ void CppParser::handleEnum()
|
||||||
enumName,
|
enumName,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skEnumType,
|
StatementKind::skEnumType,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2099,6 +2196,7 @@ void CppParser::handleEnum()
|
||||||
cmd,
|
cmd,
|
||||||
args,
|
args,
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
mTokenizer[mIndex]->line,
|
||||||
StatementKind::skEnum,
|
StatementKind::skEnum,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2115,6 +2213,7 @@ void CppParser::handleEnum()
|
||||||
cmd,
|
cmd,
|
||||||
args,
|
args,
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
mTokenizer[mIndex]->line,
|
||||||
StatementKind::skEnum,
|
StatementKind::skEnum,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2123,18 +2222,19 @@ void CppParser::handleEnum()
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
addStatement(
|
addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
lastType,
|
lastType,
|
||||||
cmd,
|
cmd,
|
||||||
args,
|
"",
|
||||||
"",
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
"",
|
||||||
StatementKind::skEnum,
|
mTokenizer[mIndex]->line,
|
||||||
getScope(),
|
StatementKind::skEnum,
|
||||||
mClassScope,
|
getScope(),
|
||||||
true,
|
mClassScope,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mIndex ++ ;
|
mIndex ++ ;
|
||||||
|
@ -2180,6 +2280,7 @@ void CppParser::handleForBlock()
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skBlock,
|
StatementKind::skBlock,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2232,7 +2333,7 @@ void CppParser::handleKeyword()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppParser::handleMethod(const QString &sType, const QString &sName, const QString &sArgs, bool isStatic, bool isFriend)
|
void CppParser::handleMethod(const QString &sType, const QString &sName, int argStart, int argEnd, bool isStatic, bool isFriend)
|
||||||
{
|
{
|
||||||
bool isValid = true;
|
bool isValid = true;
|
||||||
bool isDeclaration = false; // assume it's not a prototype
|
bool isDeclaration = false; // assume it's not a prototype
|
||||||
|
@ -2309,7 +2410,8 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
sType,
|
sType,
|
||||||
scopelessName,
|
scopelessName,
|
||||||
sArgs,
|
argStart,
|
||||||
|
argEnd,
|
||||||
"",
|
"",
|
||||||
//mTokenizer[mIndex - 1]^.Line,
|
//mTokenizer[mIndex - 1]^.Line,
|
||||||
startLine,
|
startLine,
|
||||||
|
@ -2330,6 +2432,7 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
||||||
"this",
|
"this",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skVariable,
|
StatementKind::skVariable,
|
||||||
StatementScope::ssLocal,
|
StatementScope::ssLocal,
|
||||||
|
@ -2344,6 +2447,7 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
||||||
"static const char ",
|
"static const char ",
|
||||||
"__func__",
|
"__func__",
|
||||||
"[]",
|
"[]",
|
||||||
|
"",
|
||||||
"\""+scopelessName+"\"",
|
"\""+scopelessName+"\"",
|
||||||
startLine+1,
|
startLine+1,
|
||||||
StatementKind::skVariable,
|
StatementKind::skVariable,
|
||||||
|
@ -2357,7 +2461,8 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
sType,
|
sType,
|
||||||
scopelessName,
|
scopelessName,
|
||||||
sArgs,
|
argStart,
|
||||||
|
argEnd,
|
||||||
"",
|
"",
|
||||||
//mTokenizer[mIndex - 1]^.Line,
|
//mTokenizer[mIndex - 1]^.Line,
|
||||||
startLine,
|
startLine,
|
||||||
|
@ -2428,6 +2533,7 @@ void CppParser::handleNamespace()
|
||||||
aliasName, // name of the alias namespace
|
aliasName, // name of the alias namespace
|
||||||
command, // command
|
command, // command
|
||||||
"", // args
|
"", // args
|
||||||
|
"", // noname args
|
||||||
"", // values
|
"", // values
|
||||||
//mTokenizer[mIndex]^.Line,
|
//mTokenizer[mIndex]^.Line,
|
||||||
startLine,
|
startLine,
|
||||||
|
@ -2452,18 +2558,19 @@ void CppParser::handleNamespace()
|
||||||
mIndex++; //skip '{'
|
mIndex++; //skip '{'
|
||||||
} else {
|
} else {
|
||||||
PStatement namespaceStatement = addStatement(
|
PStatement namespaceStatement = addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
"", // type
|
"", // type
|
||||||
command, // command
|
command, // command
|
||||||
"", // args
|
"", // args
|
||||||
"", // values
|
"", // noname args
|
||||||
startLine,
|
"", // values
|
||||||
StatementKind::skNamespace,
|
startLine,
|
||||||
getScope(),
|
StatementKind::skNamespace,
|
||||||
mClassScope,
|
getScope(),
|
||||||
true,
|
mClassScope,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
addSoloScopeLevel(namespaceStatement,startLine);
|
addSoloScopeLevel(namespaceStatement,startLine);
|
||||||
|
|
||||||
// Skip to '{'
|
// Skip to '{'
|
||||||
|
@ -2505,6 +2612,7 @@ void CppParser::handleOtherTypedefs()
|
||||||
newType,
|
newType,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skTypedef,
|
StatementKind::skTypedef,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2549,12 +2657,14 @@ void CppParser::handleOtherTypedefs()
|
||||||
int p = newType.lastIndexOf(' ');
|
int p = newType.lastIndexOf(' ');
|
||||||
if (p>=0)
|
if (p>=0)
|
||||||
newType.truncate(p+1);
|
newType.truncate(p+1);
|
||||||
|
QString args=mTokenizer[mIndex + 1]->text;
|
||||||
addStatement(
|
addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
oldType,
|
oldType,
|
||||||
newType,
|
newType,
|
||||||
mTokenizer[mIndex + 1]->text,
|
args,
|
||||||
|
removeArgNames(args),
|
||||||
"",
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skTypedef,
|
StatementKind::skTypedef,
|
||||||
|
@ -2577,6 +2687,7 @@ void CppParser::handleOtherTypedefs()
|
||||||
newType,
|
newType,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skTypedef,
|
StatementKind::skTypedef,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2639,43 +2750,46 @@ void CppParser::handlePreprocessor()
|
||||||
mPreprocessor.getDefineParts(s,name,args,value);
|
mPreprocessor.getDefineParts(s,name,args,value);
|
||||||
|
|
||||||
addStatement(
|
addStatement(
|
||||||
nullptr, // defines don't belong to any scope
|
nullptr, // defines don't belong to any scope
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
"", // define has no type
|
"", // define has no type
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
value,
|
"",// noname args
|
||||||
mTokenizer[mIndex]->line,
|
value,
|
||||||
StatementKind::skPreprocessor,
|
mTokenizer[mIndex]->line,
|
||||||
StatementScope::ssGlobal,
|
StatementKind::skPreprocessor,
|
||||||
StatementClassScope::scsNone,
|
StatementScope::ssGlobal,
|
||||||
true,
|
StatementClassScope::scsNone,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
} // TODO: undef ( define has limited scope)
|
} // TODO: undef ( define has limited scope)
|
||||||
handlePreprocessorEnd:
|
handlePreprocessorEnd:
|
||||||
mIndex++;
|
mIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementClassScope CppParser::getClassScope(int index) {
|
StatementClassScope CppParser::getClassScope(const QString& text) {
|
||||||
if (mTokenizer[index]->text=="public")
|
if (!text.isEmpty() && text[0]=='p') {
|
||||||
return StatementClassScope::scsPublic;
|
if (text=="public")
|
||||||
else if (mTokenizer[index]->text=="private")
|
return StatementClassScope::scsPublic;
|
||||||
return StatementClassScope::scsPrivate;
|
else if (text=="private")
|
||||||
else if (mTokenizer[index]->text=="protected")
|
return StatementClassScope::scsPrivate;
|
||||||
return StatementClassScope::scsProtected;
|
else if (text=="protected")
|
||||||
else
|
return StatementClassScope::scsProtected;
|
||||||
return StatementClassScope::scsNone;
|
}
|
||||||
|
return StatementClassScope::scsNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppParser::handleScope()
|
void CppParser::handleScope()
|
||||||
{
|
{
|
||||||
mClassScope = getClassScope(mIndex);
|
mClassScope = getClassScope(mTokenizer[mIndex]->text);
|
||||||
mIndex+=2; // the scope is followed by a ':'
|
mIndex+=2; // the scope is followed by a ':'
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::handleStatement()
|
bool CppParser::handleStatement()
|
||||||
{
|
{
|
||||||
QString S1,S2,S3;
|
QString funcType,funcName;
|
||||||
|
int argStart,argEnd;
|
||||||
bool isStatic, isFriend;
|
bool isStatic, isFriend;
|
||||||
int idx=getCurrentBlockEndSkip();
|
int idx=getCurrentBlockEndSkip();
|
||||||
int idx2=getCurrentBlockBeginSkip();
|
int idx2=getCurrentBlockBeginSkip();
|
||||||
|
@ -2701,19 +2815,20 @@ bool CppParser::handleStatement()
|
||||||
mIndex++;
|
mIndex++;
|
||||||
} else if (mTokenizer[mIndex]->text.startsWith('{')) {
|
} else if (mTokenizer[mIndex]->text.startsWith('{')) {
|
||||||
PStatement block = addStatement(
|
PStatement block = addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
//mTokenizer[mIndex]^.Line,
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
//mTokenizer[mIndex]^.Line,
|
||||||
StatementKind::skBlock,
|
mTokenizer[mIndex]->line,
|
||||||
getScope(),
|
StatementKind::skBlock,
|
||||||
mClassScope,
|
getScope(),
|
||||||
true,
|
mClassScope,
|
||||||
false);
|
true,
|
||||||
|
false);
|
||||||
addSoloScopeLevel(block,mTokenizer[mIndex]->line);
|
addSoloScopeLevel(block,mTokenizer[mIndex]->line);
|
||||||
mIndex++;
|
mIndex++;
|
||||||
} else if (mTokenizer[mIndex]->text[0] == '}') {
|
} else if (mTokenizer[mIndex]->text[0] == '}') {
|
||||||
|
@ -2749,8 +2864,8 @@ bool CppParser::handleStatement()
|
||||||
handleUsing();
|
handleUsing();
|
||||||
} else if (checkForStructs()) {
|
} else if (checkForStructs()) {
|
||||||
handleStructs(false);
|
handleStructs(false);
|
||||||
} else if (checkForMethod(S1, S2, S3, isStatic, isFriend)) {
|
} else if (checkForMethod(funcType, funcName, argStart,argEnd, isStatic, isFriend)) {
|
||||||
handleMethod(S1, S2, S3, isStatic, isFriend); // don't recalculate parts
|
handleMethod(funcType, funcName, argStart, argEnd, isStatic, isFriend); // don't recalculate parts
|
||||||
} else if (checkForVar()) {
|
} else if (checkForVar()) {
|
||||||
handleVar();
|
handleVar();
|
||||||
} else
|
} else
|
||||||
|
@ -2805,8 +2920,9 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
oldType,
|
oldType,
|
||||||
newType,
|
newType,
|
||||||
"",
|
"", // args
|
||||||
"",
|
"", // noname args
|
||||||
|
"", // values
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skTypedef,
|
StatementKind::skTypedef,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2852,6 +2968,7 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
prefix, // type
|
prefix, // type
|
||||||
command, // command
|
command, // command
|
||||||
"", // args
|
"", // args
|
||||||
|
"", // no name args,
|
||||||
"", // values
|
"", // values
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skClass,
|
StatementKind::skClass,
|
||||||
|
@ -2875,6 +2992,7 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
prefix, // type
|
prefix, // type
|
||||||
command, // command
|
command, // command
|
||||||
"", // args
|
"", // args
|
||||||
|
"", // no name args
|
||||||
"", // values
|
"", // values
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skClass,
|
StatementKind::skClass,
|
||||||
|
@ -2958,6 +3076,7 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
"__"+command,
|
"__"+command,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skClass,
|
StatementKind::skClass,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -2968,18 +3087,19 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
if (isTypedef) {
|
if (isTypedef) {
|
||||||
//typedef
|
//typedef
|
||||||
addStatement(
|
addStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
firstSynonym->command,
|
firstSynonym->command,
|
||||||
command,
|
command,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
"",
|
||||||
StatementKind::skTypedef,
|
mTokenizer[mIndex]->line,
|
||||||
getScope(),
|
StatementKind::skTypedef,
|
||||||
mClassScope,
|
getScope(),
|
||||||
true,
|
mClassScope,
|
||||||
false); // typedef
|
true,
|
||||||
|
false); // typedef
|
||||||
} else {
|
} else {
|
||||||
//variable define
|
//variable define
|
||||||
addStatement(
|
addStatement(
|
||||||
|
@ -2989,6 +3109,7 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
mTokenizer[i]->line,
|
mTokenizer[i]->line,
|
||||||
StatementKind::skVariable,
|
StatementKind::skVariable,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -3019,6 +3140,7 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skBlock,
|
StatementKind::skBlock,
|
||||||
getScope(),
|
getScope(),
|
||||||
|
@ -3064,6 +3186,8 @@ void CppParser::handleUsing()
|
||||||
aliasName, // name of the alias (type)
|
aliasName, // name of the alias (type)
|
||||||
fullName, // command
|
fullName, // command
|
||||||
"", // args
|
"", // args
|
||||||
|
"",
|
||||||
|
"",
|
||||||
"", // values
|
"", // values
|
||||||
startLine,
|
startLine,
|
||||||
StatementKind::skTypedef,
|
StatementKind::skTypedef,
|
||||||
|
@ -3248,19 +3372,20 @@ void CppParser::handleVar()
|
||||||
// Add a statement for every struct we are in
|
// Add a statement for every struct we are in
|
||||||
if (!lastType.isEmpty()) {
|
if (!lastType.isEmpty()) {
|
||||||
addChildStatement(
|
addChildStatement(
|
||||||
getCurrentScope(),
|
getCurrentScope(),
|
||||||
mCurrentFile,
|
mCurrentFile,
|
||||||
lastType,
|
lastType,
|
||||||
cmd,
|
cmd,
|
||||||
args,
|
args,
|
||||||
"",
|
"",
|
||||||
mTokenizer[mIndex]->line,
|
"",
|
||||||
StatementKind::skVariable,
|
mTokenizer[mIndex]->line,
|
||||||
getScope(),
|
StatementKind::skVariable,
|
||||||
mClassScope,
|
getScope(),
|
||||||
//True,
|
mClassScope,
|
||||||
!isExtern,
|
//True,
|
||||||
isStatic); // TODO: not supported to pass list
|
!isExtern,
|
||||||
|
isStatic); // TODO: not supported to pass list
|
||||||
varAdded = true;
|
varAdded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3337,6 +3462,7 @@ void CppParser::internalParse(const QString &fileName)
|
||||||
if (!handleStatement())
|
if (!handleStatement())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
// mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
// mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||||
//
|
//
|
||||||
|
@ -4361,14 +4487,16 @@ int CppParser::calcKeyLenForStruct(const QString &word)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppParser::scanMethodArgs(const PStatement& functionStatement, const QString &argStr)
|
void CppParser::scanMethodArgs(const PStatement& functionStatement, int argStart, int argEnd)
|
||||||
{
|
{
|
||||||
// Split up argument string by ,
|
// Split up argument string by ,
|
||||||
int i = 1; // assume it starts with ( and ends with )
|
int i = argStart+1; // assume it starts with ( and ends with )
|
||||||
int paramStart = i;
|
int paramStart = i;
|
||||||
|
// Keep going and stop on top of the variable name
|
||||||
QString args;
|
QString lastType = "";
|
||||||
while (i < argStr.length()) {
|
bool isFunctionPointer = false;
|
||||||
|
bool varAdded = false;
|
||||||
|
while (i < argEnd) {
|
||||||
if ((argStr[i] == ',') ||
|
if ((argStr[i] == ',') ||
|
||||||
((i == argStr.length()-1) && (argStr[i] == ')'))) {
|
((i == argStr.length()-1) && (argStr[i] == ')'))) {
|
||||||
// We've found "int* a" for example
|
// We've found "int* a" for example
|
||||||
|
@ -4380,14 +4508,8 @@ void CppParser::scanMethodArgs(const PStatement& functionStatement, const QStrin
|
||||||
s.truncate(assignPos);
|
s.truncate(assignPos);
|
||||||
s = s.trimmed();
|
s = s.trimmed();
|
||||||
}
|
}
|
||||||
// we don't support function pointer parameters now, till we can tokenize function parameters
|
//todo: we don't support function pointer parameters now, till we can tokenize function parameters
|
||||||
// {
|
|
||||||
// // Can be a function pointer. If so, scan after last )
|
|
||||||
// BracePos := LastPos(')', S);
|
|
||||||
// if (BracePos > 0) then // it's a function pointer... begin
|
|
||||||
// SpacePos := LastPos(' ', Copy(S, BracePos, MaxInt)) // start search at brace
|
|
||||||
// end else begin
|
|
||||||
// }
|
|
||||||
//skip []
|
//skip []
|
||||||
int varEndPos = s.length()-1;
|
int varEndPos = s.length()-1;
|
||||||
int bracketLevel = 0;
|
int bracketLevel = 0;
|
||||||
|
@ -4442,6 +4564,162 @@ void CppParser::scanMethodArgs(const PStatement& functionStatement, const QStrin
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if ((mIndex + 2 < mTokenizer.tokenCount())
|
||||||
|
&& (mTokenizer[mIndex + 1]->text.front() == '(')
|
||||||
|
&& (mTokenizer[mIndex + 2]->text.front() == '(')) {
|
||||||
|
isFunctionPointer = mTokenizer[mIndex + 1]->text.indexOf('*') >= 0;
|
||||||
|
if (!isFunctionPointer)
|
||||||
|
break; // inline constructor
|
||||||
|
} else if ((mIndex + 1 < mTokenizer.tokenCount())
|
||||||
|
&& (mTokenizer[mIndex + 1]->text.front()=='('
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()==','
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()==';'
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()==':'
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()=='}'
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()=='#'
|
||||||
|
|| mTokenizer[mIndex + 1]->text.front()=='{')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we've made a mistake, this is a typedef , not a variable definition.
|
||||||
|
if (mTokenizer[mIndex]->text == "typedef")
|
||||||
|
return;
|
||||||
|
|
||||||
|
// struct/class/union is part of the type signature
|
||||||
|
// but we dont store it in the type cache, so must trim it to find the type info
|
||||||
|
if (mTokenizer[mIndex]->text!="struct"
|
||||||
|
&& mTokenizer[mIndex]->text!="class"
|
||||||
|
&& mTokenizer[mIndex]->text!="union") {
|
||||||
|
if (mTokenizer[mIndex]->text == ':') {
|
||||||
|
lastType += ':';
|
||||||
|
} else {
|
||||||
|
QString s=expandMacroType(mTokenizer[mIndex]->text);
|
||||||
|
if (s == "extern") {
|
||||||
|
isExtern = true;
|
||||||
|
} else {
|
||||||
|
if (!s.isEmpty())
|
||||||
|
lastType += ' '+s;
|
||||||
|
if (s == "static")
|
||||||
|
isStatic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mIndex++;
|
||||||
|
if(mIndex >= mTokenizer.tokenCount())
|
||||||
|
break;
|
||||||
|
if (isFunctionPointer)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastType = lastType.trimmed();
|
||||||
|
|
||||||
|
// Don't bother entering the scanning loop when we have failed
|
||||||
|
if (mIndex >= mTokenizer.tokenCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the variable name
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// Skip bit identifiers,
|
||||||
|
// e.g.:
|
||||||
|
// handle
|
||||||
|
// unsigned short bAppReturnCode:8,reserved:6,fBusy:1,fAck:1
|
||||||
|
// as
|
||||||
|
// unsigned short bAppReturnCode,reserved,fBusy,fAck
|
||||||
|
if ( (mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == ':')) {
|
||||||
|
while ( (mIndex < mTokenizer.tokenCount())
|
||||||
|
&& !(
|
||||||
|
mTokenizer[mIndex]->text.front() == ','
|
||||||
|
|| isblockChar(';')
|
||||||
|
))
|
||||||
|
mIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip inline constructors,
|
||||||
|
// e.g.:
|
||||||
|
// handle
|
||||||
|
// int a(3)
|
||||||
|
// as
|
||||||
|
// int a
|
||||||
|
if (!isFunctionPointer &&
|
||||||
|
mIndex < mTokenizer.tokenCount() &&
|
||||||
|
mTokenizer[mIndex]->text.front() == '(') {
|
||||||
|
while ((mIndex < mTokenizer.tokenCount())
|
||||||
|
&& !(
|
||||||
|
mTokenizer[mIndex]->text.front() == ','
|
||||||
|
|| isblockChar(mTokenizer[mIndex]->text.front())
|
||||||
|
))
|
||||||
|
mIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we stop on top of the variable name?
|
||||||
|
if (mIndex < mTokenizer.tokenCount()) {
|
||||||
|
if (mTokenizer[mIndex]->text.front()!=','
|
||||||
|
&& mTokenizer[mIndex]->text.front()!=';') {
|
||||||
|
QString cmd;
|
||||||
|
QString args;
|
||||||
|
if (isFunctionPointer && (mIndex + 1 < mTokenizer.tokenCount())) {
|
||||||
|
QString s = mTokenizer[mIndex]->text;
|
||||||
|
cmd = s.mid(2,s.length()-3).trimmed(); // (*foo) -> foo
|
||||||
|
args = mTokenizer[mIndex + 1]->text; // (int a,int b)
|
||||||
|
lastType += "(*)" + args; // void(int a,int b)
|
||||||
|
mIndex++;
|
||||||
|
} else if (mTokenizer[mIndex]->text.back() == ']') { //array; break args
|
||||||
|
int pos = mTokenizer[mIndex]->text.indexOf('[');
|
||||||
|
cmd = mTokenizer[mIndex]->text.mid(0,pos);
|
||||||
|
args = mTokenizer[mIndex]->text.mid(pos);
|
||||||
|
} else {
|
||||||
|
cmd = mTokenizer[mIndex]->text;
|
||||||
|
args = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a statement for every struct we are in
|
||||||
|
if (!lastType.isEmpty()) {
|
||||||
|
addChildStatement(
|
||||||
|
getCurrentScope(),
|
||||||
|
mCurrentFile,
|
||||||
|
lastType,
|
||||||
|
cmd,
|
||||||
|
args,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
mTokenizer[mIndex]->line,
|
||||||
|
StatementKind::skVariable,
|
||||||
|
getScope(),
|
||||||
|
mClassScope,
|
||||||
|
//True,
|
||||||
|
!isExtern,
|
||||||
|
isStatic); // TODO: not supported to pass list
|
||||||
|
varAdded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step over the variable name
|
||||||
|
if (isblockChar(mTokenizer[mIndex]->text.front())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mIndex++;
|
||||||
|
}
|
||||||
|
if (mIndex >= mTokenizer.tokenCount())
|
||||||
|
break;
|
||||||
|
if (isblockChar(mTokenizer[mIndex]->text.front()))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (varAdded && (mIndex < mTokenizer.tokenCount())
|
||||||
|
&& (mTokenizer[mIndex]->text == '{')) {
|
||||||
|
// skip { } like A x {new A};
|
||||||
|
int i=skipBraces(mIndex);
|
||||||
|
if (i!=mIndex)
|
||||||
|
mIndex = i+1;
|
||||||
|
}
|
||||||
|
// Skip ; and ,
|
||||||
|
if ( (mIndex < mTokenizer.tokenCount()) &&
|
||||||
|
(mTokenizer[mIndex]->text.front() == ';'
|
||||||
|
|| mTokenizer[mIndex]->text.front() == ','))
|
||||||
|
mIndex++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CppParser::splitPhrase(const QString &phrase, QString &sClazz,
|
QString CppParser::splitPhrase(const QString &phrase, QString &sClazz,
|
||||||
|
@ -4622,50 +4900,43 @@ QString CppParser::removeArgNames(const QString &args)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isNotFuncArgs(const QString &args)
|
bool CppParser::isNotFuncArgs(int startIndex, int endIndex)
|
||||||
{
|
{
|
||||||
int i=1; //skip '('
|
//no args, it must be a function
|
||||||
int endPos = args.length()-1;//skip ')'
|
if (endIndex-startIndex==1)
|
||||||
bool lastCharIsId=false;
|
return false;
|
||||||
|
int i=startIndex+1; //skip '('
|
||||||
|
int endPos = endIndex;
|
||||||
QString word = "";
|
QString word = "";
|
||||||
while (i<endPos) {
|
while (i<endPos) {
|
||||||
if (args[i] == '"' || args[i]=='\'') {
|
QChar ch=mTokenizer[i]->text[0];
|
||||||
// args contains a string/char, can't be a func define
|
switch(ch.unicode()) {
|
||||||
|
// args contains a string/char, can't be a func define
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
return true;
|
return true;
|
||||||
} else if ( isLetterChar(args[i])) {
|
case '(':
|
||||||
word += args[i];
|
case '[':
|
||||||
lastCharIsId = true;
|
case '{':
|
||||||
i++;
|
i=mTokenizer[i]->matchIndex+1;
|
||||||
} else if ((args[i] == ':') && (args[i+1] == ':')) {
|
continue;
|
||||||
lastCharIsId = false;
|
}
|
||||||
word += "::";
|
if (isDigitChar(ch))
|
||||||
i+=2;
|
return true;
|
||||||
} else if (isDigitChar(args[i])) {
|
if (isLetterChar(ch)) {
|
||||||
if (!lastCharIsId)
|
QString currentText=mTokenizer[i]->text;
|
||||||
|
if (currentText=="true" || currentText=="false" || currentText=="nullptr"
|
||||||
|
|| currentText=="const")
|
||||||
return true;
|
return true;
|
||||||
word+=args[i];
|
PStatement statement =findStatementOf(mCurrentFile,word,getCurrentScope(),true);
|
||||||
i++;
|
if (statement &&
|
||||||
} else if (isSpaceChar(args[i]) || isLineChar(args[i])) {
|
!isTypeStatement(statement->kind))
|
||||||
if (!word.isEmpty())
|
return true;
|
||||||
break;
|
}
|
||||||
i++;
|
i++;
|
||||||
} else if (word.isEmpty()) {
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
//function with no args
|
//function with no args
|
||||||
if (i>endPos && word.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCppKeyword(word)) {
|
|
||||||
return word == "true" || word == "false" || word == "nullptr";
|
|
||||||
}
|
|
||||||
PStatement statement =findStatementOf(mCurrentFile,word,getCurrentScope(),true);
|
|
||||||
if (statement &&
|
|
||||||
!isTypeStatement(statement->kind))
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ private:
|
||||||
const QString& aType, // "Type" is already in use
|
const QString& aType, // "Type" is already in use
|
||||||
const QString& command,
|
const QString& command,
|
||||||
const QString& args,
|
const QString& args,
|
||||||
|
const QString& noNameArgs,
|
||||||
const QString& value,
|
const QString& value,
|
||||||
int line,
|
int line,
|
||||||
StatementKind kind,
|
StatementKind kind,
|
||||||
|
@ -173,6 +174,21 @@ private:
|
||||||
const QString &aType, // "Type" is already in use
|
const QString &aType, // "Type" is already in use
|
||||||
const QString &command,
|
const QString &command,
|
||||||
const QString &args,
|
const QString &args,
|
||||||
|
const QString &noNameArgs,
|
||||||
|
const QString& value,
|
||||||
|
int line,
|
||||||
|
StatementKind kind,
|
||||||
|
const StatementScope& scope,
|
||||||
|
const StatementClassScope& classScope,
|
||||||
|
bool isDefinition,
|
||||||
|
bool isStatic);
|
||||||
|
PStatement addStatement(
|
||||||
|
const PStatement& parent,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &aType, // "Type" is already in use
|
||||||
|
const QString &command,
|
||||||
|
int argStart,
|
||||||
|
int argEnd,
|
||||||
const QString& value,
|
const QString& value,
|
||||||
int line,
|
int line,
|
||||||
StatementKind kind,
|
StatementKind kind,
|
||||||
|
@ -195,8 +211,8 @@ private:
|
||||||
bool checkForEnum();
|
bool checkForEnum();
|
||||||
bool checkForForBlock();
|
bool checkForForBlock();
|
||||||
bool checkForKeyword();
|
bool checkForKeyword();
|
||||||
bool checkForMethod(QString &sType, QString &sName, QString &sArgs,
|
bool checkForMethod(QString &sType, QString &sName, int &argStartIndex,
|
||||||
bool &isStatic, bool &isFriend); // caching of results
|
int &argEndIndex, bool &isStatic, bool &isFriend); // caching of results
|
||||||
bool checkForNamespace();
|
bool checkForNamespace();
|
||||||
bool checkForPreprocessor();
|
bool checkForPreprocessor();
|
||||||
bool checkForScope();
|
bool checkForScope();
|
||||||
|
@ -343,7 +359,7 @@ private:
|
||||||
int& pointerLevel);
|
int& pointerLevel);
|
||||||
|
|
||||||
int getBracketEnd(const QString& s, int startAt);
|
int getBracketEnd(const QString& s, int startAt);
|
||||||
StatementClassScope getClassScope(int index);
|
StatementClassScope getClassScope(const QString& text);
|
||||||
int getCurrentBlockBeginSkip();
|
int getCurrentBlockBeginSkip();
|
||||||
int getCurrentBlockEndSkip();
|
int getCurrentBlockEndSkip();
|
||||||
int getCurrentInlineNamespaceEndSkip();
|
int getCurrentInlineNamespaceEndSkip();
|
||||||
|
@ -376,7 +392,8 @@ private:
|
||||||
void handleMethod(
|
void handleMethod(
|
||||||
const QString& sType,
|
const QString& sType,
|
||||||
const QString& sName,
|
const QString& sName,
|
||||||
const QString& sArgs,
|
int argStart,
|
||||||
|
int argEnd,
|
||||||
bool isStatic,
|
bool isStatic,
|
||||||
bool isFriend);
|
bool isFriend);
|
||||||
void handleNamespace();
|
void handleNamespace();
|
||||||
|
@ -410,7 +427,8 @@ private:
|
||||||
// }
|
// }
|
||||||
void scanMethodArgs(
|
void scanMethodArgs(
|
||||||
const PStatement& functionStatement,
|
const PStatement& functionStatement,
|
||||||
const QString& argStr);
|
int argStart,
|
||||||
|
int argEnd);
|
||||||
QString splitPhrase(const QString& phrase, QString& sClazz,
|
QString splitPhrase(const QString& phrase, QString& sClazz,
|
||||||
QString& sOperator, QString &sMember);
|
QString& sOperator, QString &sMember);
|
||||||
|
|
||||||
|
@ -493,7 +511,7 @@ private:
|
||||||
return ch=='\n' || ch=='\r';
|
return ch=='\n' || ch=='\r';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNotFuncArgs(const QString& args);
|
bool isNotFuncArgs(int startIndex, int endIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Test if a statement is a class/struct/union/namespace/function
|
* @brief Test if a statement is a class/struct/union/namespace/function
|
||||||
|
|
|
@ -30,6 +30,9 @@ void CppTokenizer::clear()
|
||||||
mBuffer.clear();
|
mBuffer.clear();
|
||||||
mBufferStr.clear();
|
mBufferStr.clear();
|
||||||
mLastToken.clear();
|
mLastToken.clear();
|
||||||
|
mUnmatchedBraces.clear();
|
||||||
|
mUnmatchedBrackets.clear();
|
||||||
|
mUnmatchedParenthesis.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppTokenizer::tokenize(const QStringList &buffer)
|
void CppTokenizer::tokenize(const QStringList &buffer)
|
||||||
|
@ -48,16 +51,26 @@ void CppTokenizer::tokenize(const QStringList &buffer)
|
||||||
mCurrent = mStart;
|
mCurrent = mStart;
|
||||||
mLineCount = mStart;
|
mLineCount = mStart;
|
||||||
QString s = "";
|
QString s = "";
|
||||||
bool bSkipBlocks = false;
|
|
||||||
mCurrentLine = 1;
|
mCurrentLine = 1;
|
||||||
|
|
||||||
|
TokenType tokenType;
|
||||||
while (true) {
|
while (true) {
|
||||||
mLastToken = s;
|
mLastToken = s;
|
||||||
s = getNextToken(true, true, bSkipBlocks);
|
s = getNextToken(&tokenType, true, false);
|
||||||
simplify(s);
|
simplify(s);
|
||||||
if (s.isEmpty())
|
if (s.isEmpty())
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
addToken(s,mCurrentLine);
|
addToken(s,mCurrentLine,tokenType);
|
||||||
|
}
|
||||||
|
while (!mUnmatchedBraces.isEmpty()) {
|
||||||
|
mTokenList[mUnmatchedBraces.back()]->matchIndex=mTokenList.count()-1;
|
||||||
|
}
|
||||||
|
while (!mUnmatchedBrackets.isEmpty()) {
|
||||||
|
mTokenList[mUnmatchedBrackets.back()]->matchIndex=mTokenList.count()-1;
|
||||||
|
}
|
||||||
|
while (!mUnmatchedParenthesis.isEmpty()) {
|
||||||
|
mTokenList[mUnmatchedParenthesis.back()]->matchIndex=mTokenList.count()-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +81,7 @@ void CppTokenizer::dumpTokens(const QString &fileName)
|
||||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
QTextStream stream(&file);
|
QTextStream stream(&file);
|
||||||
foreach (const PToken& token,mTokenList) {
|
foreach (const PToken& token,mTokenList) {
|
||||||
stream<<QString("%1,%2").arg(token->line).arg(token->text)
|
stream<<QString("%1,%2,%3").arg(token->line).arg(token->text).arg(token->matchIndex)
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
<<Qt::endl;
|
<<Qt::endl;
|
||||||
#else
|
#else
|
||||||
|
@ -93,11 +106,55 @@ int CppTokenizer::tokenCount()
|
||||||
return mTokenList.count();
|
return mTokenList.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppTokenizer::addToken(const QString &sText, int iLine)
|
void CppTokenizer::addToken(const QString &sText, int iLine, TokenType tokenType)
|
||||||
{
|
{
|
||||||
PToken token = std::make_shared<Token>();
|
PToken token = std::make_shared<Token>();
|
||||||
token->text = sText;
|
token->text = sText;
|
||||||
token->line = iLine;
|
token->line = iLine;
|
||||||
|
switch(tokenType) {
|
||||||
|
case TokenType::LeftBrace:
|
||||||
|
token->matchIndex=-1;
|
||||||
|
mUnmatchedBraces.push_back(mTokenList.count());
|
||||||
|
break;
|
||||||
|
case TokenType::RightBrace:
|
||||||
|
if (mUnmatchedBraces.isEmpty()) {
|
||||||
|
token->matchIndex=-1;
|
||||||
|
} else {
|
||||||
|
token->matchIndex = mUnmatchedBraces.last();
|
||||||
|
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||||
|
mUnmatchedBraces.pop_back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TokenType::LeftBracket:
|
||||||
|
token->matchIndex=-1;
|
||||||
|
mUnmatchedBrackets.push_back(mTokenList.count());
|
||||||
|
break;
|
||||||
|
case TokenType::RightBracket:
|
||||||
|
if (mUnmatchedBrackets.isEmpty()) {
|
||||||
|
token->matchIndex=-1;
|
||||||
|
} else {
|
||||||
|
token->matchIndex = mUnmatchedBrackets.last();
|
||||||
|
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||||
|
mUnmatchedBrackets.pop_back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TokenType::LeftParenthesis:
|
||||||
|
token->matchIndex=-1;
|
||||||
|
mUnmatchedParenthesis.push_back(mTokenList.count());
|
||||||
|
break;
|
||||||
|
case TokenType::RightParenthesis:
|
||||||
|
if (mUnmatchedParenthesis.isEmpty()) {
|
||||||
|
token->matchIndex=-1;
|
||||||
|
} else {
|
||||||
|
token->matchIndex = mUnmatchedParenthesis.last();
|
||||||
|
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||||
|
mUnmatchedParenthesis.pop_back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mTokenList.append(token);
|
mTokenList.append(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,12 +196,13 @@ QString CppTokenizer::getForInit()
|
||||||
// Step into the init statement
|
// Step into the init statement
|
||||||
mCurrent++;
|
mCurrent++;
|
||||||
|
|
||||||
|
TokenType tokenType;
|
||||||
// Process until ; or end of file
|
// Process until ; or end of file
|
||||||
while (true) {
|
while (true) {
|
||||||
QString s = getNextToken(true, true, false);
|
QString s = getNextToken(&tokenType, true, false);
|
||||||
simplify(s);
|
simplify(s);
|
||||||
if (!s.isEmpty())
|
if (!s.isEmpty())
|
||||||
addToken(s,mCurrentLine);
|
addToken(s,mCurrentLine,tokenType);
|
||||||
if ( (s == "") || (s == ";") || (s==":"))
|
if ( (s == "") || (s == ";") || (s==":"))
|
||||||
break;
|
break;
|
||||||
// : is used in for-each loop
|
// : is used in for-each loop
|
||||||
|
@ -156,10 +214,11 @@ QString CppTokenizer::getForInit()
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray, bool bSkipBlock)
|
QString CppTokenizer::getNextToken(TokenType *pTokenType, bool bSkipArray, bool bSkipBlock)
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
*pTokenType=TokenType::Normal;
|
||||||
while (true) {
|
while (true) {
|
||||||
skipToNextToken();
|
skipToNextToken();
|
||||||
if (*mCurrent == 0)
|
if (*mCurrent == 0)
|
||||||
|
@ -179,10 +238,10 @@ QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray,
|
||||||
countLines();
|
countLines();
|
||||||
result = getForInit();
|
result = getForInit();
|
||||||
done = (result != "");
|
done = (result != "");
|
||||||
} else if (isArguments()) {
|
// } else if (isArguments()) {
|
||||||
countLines();
|
// countLines();
|
||||||
result = getArguments();
|
// result = getArguments();
|
||||||
done = (result != "");
|
// done = (result != "");
|
||||||
} else if (isWord()) {
|
} else if (isWord()) {
|
||||||
countLines();
|
countLines();
|
||||||
result = getWord(false, bSkipArray, bSkipBlock);
|
result = getWord(false, bSkipArray, bSkipBlock);
|
||||||
|
@ -214,7 +273,33 @@ QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
|
*pTokenType=TokenType::LeftBrace;
|
||||||
|
countLines();
|
||||||
|
result = *mCurrent;
|
||||||
|
advance();
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
case '}':
|
case '}':
|
||||||
|
*pTokenType=TokenType::RightBrace;
|
||||||
|
countLines();
|
||||||
|
result = *mCurrent;
|
||||||
|
advance();
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
*pTokenType=TokenType::LeftParenthesis;
|
||||||
|
countLines();
|
||||||
|
result = *mCurrent;
|
||||||
|
advance();
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
*pTokenType=TokenType::RightParenthesis;
|
||||||
|
countLines();
|
||||||
|
result = *mCurrent;
|
||||||
|
advance();
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
case ',': //just return the brace or the ';'
|
case ',': //just return the brace or the ';'
|
||||||
countLines();
|
countLines();
|
||||||
|
@ -625,7 +710,7 @@ void CppTokenizer::advance()
|
||||||
case '=': {
|
case '=': {
|
||||||
if (mTokenList.size()>2
|
if (mTokenList.size()>2
|
||||||
&& mTokenList[mTokenList.size()-2]->text == "using") {
|
&& mTokenList[mTokenList.size()-2]->text == "using") {
|
||||||
addToken("=",mCurrentLine);
|
addToken("=", mCurrentLine, TokenType::Normal);
|
||||||
mCurrent++;
|
mCurrent++;
|
||||||
} else
|
} else
|
||||||
skipAssignment();
|
skipAssignment();
|
||||||
|
|
|
@ -22,10 +22,22 @@
|
||||||
|
|
||||||
class CppTokenizer
|
class CppTokenizer
|
||||||
{
|
{
|
||||||
|
enum class TokenType {
|
||||||
|
Normal,
|
||||||
|
LeftBrace,
|
||||||
|
RightBrace,
|
||||||
|
LeftParenthesis,
|
||||||
|
RightParenthesis,
|
||||||
|
LeftBracket,
|
||||||
|
RightBracket,
|
||||||
|
Assignment,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Token {
|
struct Token {
|
||||||
QString text;
|
QString text;
|
||||||
int line;
|
int line;
|
||||||
|
int matchIndex;
|
||||||
};
|
};
|
||||||
using PToken = std::shared_ptr<Token>;
|
using PToken = std::shared_ptr<Token>;
|
||||||
using TokenList = QVector<PToken>;
|
using TokenList = QVector<PToken>;
|
||||||
|
@ -39,7 +51,7 @@ public:
|
||||||
int tokenCount();
|
int tokenCount();
|
||||||
bool isIdentChar(const QChar& ch);
|
bool isIdentChar(const QChar& ch);
|
||||||
private:
|
private:
|
||||||
void addToken(const QString& sText, int iLine);
|
void addToken(const QString& sText, int iLine, TokenType tokenType);
|
||||||
void advance();
|
void advance();
|
||||||
void countLines();
|
void countLines();
|
||||||
PToken getToken(int index);
|
PToken getToken(int index);
|
||||||
|
@ -47,7 +59,7 @@ private:
|
||||||
QString getArguments();
|
QString getArguments();
|
||||||
QString getForInit();
|
QString getForInit();
|
||||||
QString getNextToken(
|
QString getNextToken(
|
||||||
bool bSkipParenthesis = false,
|
TokenType *pTokenType,
|
||||||
bool bSkipArray = false,
|
bool bSkipArray = false,
|
||||||
bool bSkipBlock = false);
|
bool bSkipBlock = false);
|
||||||
QString getNumber();
|
QString getNumber();
|
||||||
|
@ -92,6 +104,9 @@ private:
|
||||||
int mCurrentLine;
|
int mCurrentLine;
|
||||||
QString mLastToken;
|
QString mLastToken;
|
||||||
TokenList mTokenList;
|
TokenList mTokenList;
|
||||||
|
QList<int> mUnmatchedBraces; // stack of indices for unmatched '{'
|
||||||
|
QList<int> mUnmatchedBrackets; // stack of indices for unmatched '['
|
||||||
|
QList<int> mUnmatchedParenthesis;// stack of indices for unmatched '('
|
||||||
};
|
};
|
||||||
|
|
||||||
using PCppTokenizer = std::shared_ptr<CppTokenizer>;
|
using PCppTokenizer = std::shared_ptr<CppTokenizer>;
|
||||||
|
|
Loading…
Reference in New Issue