- fix: Dummy struct/enum symbols shouldn't be shown in the completion suggestion.

- enhancement: Support optional enum name.
  - enhancement: Support optional enum type.
  - enhancement: Support simple const expression evaluation for enum values.
  - fix: Accessibilty for inherited members are not correct calculated in multiple inheritance.
  - fix: Can't handle full class name when handle inheritance.
This commit is contained in:
Roy Qu 2023-08-07 14:23:57 +08:00
parent dd724e64c2
commit 6a06b5b3d6
7 changed files with 359 additions and 127 deletions

View File

@ -10,6 +10,12 @@ Red Panda C++ Version 2.24
- enhancement: Press left/right arrow will move caret to the begin/end of the selection. - enhancement: Press left/right arrow will move caret to the begin/end of the selection.
- enhancement: Press up/down arrow will move caret up/down from the begin/end of the selection. - enhancement: Press up/down arrow will move caret up/down from the begin/end of the selection.
- enhancement: Show progress dialog if the time for searching compilers is too long. - enhancement: Show progress dialog if the time for searching compilers is too long.
- fix: Dummy struct/enum symbols shouldn't be shown in the completion suggestion.
- enhancement: Support optional enum name.
- enhancement: Support optional enum type.
- enhancement: Support simple const expression evaluation for enum values.
- fix: Accessibilty for inherited members are not correct calculated in multiple inheritance.
- fix: Can't handle full class name when handle inheritance.
Red Panda C++ Version 2.23 Red Panda C++ Version 2.23
@ -1054,7 +1060,7 @@ Red Panda C++ Version 0.14.0
- enhancement: show custom icon set folder in options -> enviroment -> folders - enhancement: show custom icon set folder in options -> enviroment -> folders
- enhancement: new class ( to project) wizard - enhancement: new class ( to project) wizard
- enhancement: greatly speed up code completion - enhancement: greatly speed up code completion
- fix: code folding calcuation not correct when some codes are folded and editing after them - fix: code folding calculation not correct when some codes are folded and editing after them
- enhancement: code completion ui redesigned - enhancement: code completion ui redesigned
- fix: mainwindow action's short cut doesn't work, if the action is not in menu or toolbar - fix: mainwindow action's short cut doesn't work, if the action is not in menu or toolbar
- fix: when run all cases for a problem, processing of output is slow - fix: when run all cases for a problem, processing of output is slow

View File

@ -4018,28 +4018,6 @@ QString Editor::getParserHint(const QStringList& expression,const QString &/*s*/
if (statement->kind == StatementKind::skFunction if (statement->kind == StatementKind::skFunction
|| statement->kind == StatementKind::skConstructor || statement->kind == StatementKind::skConstructor
|| statement->kind == StatementKind::skDestructor) { || statement->kind == StatementKind::skDestructor) {
//PStatement parentScope = statement->parentScope.lock();
// if (parentScope && parentScope->kind == StatementKind::skNamespace) {
// PStatementList namespaceStatementsList =
// mParser->findNamespace(parentScope->command);
// if (namespaceStatementsList) {
// int counts=0;
// foreach (const PStatement& namespaceStatement, *namespaceStatementsList) {
// QString hint = getHintForFunction(statement,namespaceStatement,
// mFilename,line);
// if (!hint.isEmpty()) {
// counts++;
// if (!result.isEmpty())
// result += "\n";
// if (counts>4) {
// result += "...";
// break;
// }
// result += hint;
// }
// }
// }
// } else
result = getHintForFunction(statement,mFilename,line); result = getHintForFunction(statement,mFilename,line);
} else if (statement->line>0) { } else if (statement->line>0) {
QFileInfo fileInfo(statement->fileName); QFileInfo fileInfo(statement->fileName);

View File

@ -266,7 +266,9 @@ PStatement CppParser::doFindStatement(const QString &fullname) const
return PStatement(); return PStatement();
PStatement parentStatement; PStatement parentStatement;
PStatement statement; PStatement statement;
foreach (const QString& phrase, phrases) {
for (int i=(phrases[0].isEmpty()?1:0);i<phrases.count();i++) {
const QString& phrase=phrases[i];
if (parentStatement && parentStatement->kind == StatementKind::skNamespace) { if (parentStatement && parentStatement->kind == StatementKind::skNamespace) {
PStatementList lst = doFindNamespace(parentStatement->fullName); PStatementList lst = doFindNamespace(parentStatement->fullName);
foreach (const PStatement& namespaceStatement, *lst) { foreach (const PStatement& namespaceStatement, *lst) {
@ -1143,7 +1145,13 @@ QString CppParser::prettyPrintStatement(const PStatement& statement, const QStri
result = "enum "+statement->command; result = "enum "+statement->command;
break; break;
case StatementKind::skEnum: case StatementKind::skEnum:
result = statement->type + "::" + statement->command; if (!statement->type.isEmpty())
result = statement->type + "::";
else
result = "";
result += statement->command;
if (!statement->value.isEmpty())
result += "(" + statement->value + ")";
break; break;
case StatementKind::skTypedef: case StatementKind::skTypedef:
result = "typedef "+statement->type+" "+statement->command; result = "typedef "+statement->type+" "+statement->command;
@ -1518,25 +1526,53 @@ void CppParser::setInheritance(int index, const PStatement& classStatement, bool
//skip to matching ')' //skip to matching ')'
index=mTokenizer[index]->matchIndex; index=mTokenizer[index]->matchIndex;
} else if (inheritScopeType == StatementAccessibility::None) { } else if (inheritScopeType == StatementAccessibility::None) {
if (currentText !=',' if (currentText=="::"
&& currentText!=':') { || isIdentChar(currentText[0])) {
QString basename = currentText; QString basename = currentText;
bool isGlobal = false;
index++;
if (basename=="::") {
if (index>=tokenCount || !isIdentChar(mTokenizer[index]->text[0])) {
return;
}
isGlobal=true;
basename=mTokenizer[index]->text;
index++;
}
//remove template staff //remove template staff
if (basename.endsWith('>')) { if (basename.endsWith('>')) {
int pBegin = basename.indexOf('<'); int pBegin = basename.indexOf('<');
if (pBegin>=0) if (pBegin>=0)
basename.truncate(pBegin); basename.truncate(pBegin);
} }
while (index+1<tokenCount
&& mTokenizer[index]->text=="::"
&& isIdentChar(mTokenizer[index+1]->text[0])){
basename += "::" + mTokenizer[index+1]->text;
index+=2;
//remove template staff
if (basename.endsWith('>')) {
int pBegin = basename.indexOf('<');
if (pBegin>=0)
basename.truncate(pBegin);
}
}
// Find the corresponding PStatement // Find the corresponding PStatement
PStatement statement = doFindStatementOf(mCurrentFile,basename, PStatement statement = doFindStatementOf(mCurrentFile,basename,
classStatement->parentScope.lock()); isGlobal?PStatement():classStatement->parentScope.lock());
if (statement && statement->kind == StatementKind::skClass) { if (statement && statement->kind == StatementKind::skClass) {
inheritClassStatement(classStatement,isStruct,statement,lastInheritScopeType); inheritClassStatement(classStatement,isStruct,statement,lastInheritScopeType);
} }
} }
} else {
lastInheritScopeType = inheritScopeType;
} }
index++; index++;
lastInheritScopeType = inheritScopeType;
if (index >= tokenCount) if (index >= tokenCount)
break; break;
if (mTokenizer[index]->text.front() == '{' if (mTokenizer[index]->text.front() == '{'
@ -1717,6 +1753,174 @@ QStringList CppParser::sortFilesByIncludeRelations(const QSet<QString> &files)
return result; return result;
} }
int CppParser::evaluateConstExpr(int endIndex, bool &ok)
{
int result = 0;
if (mIndex>=endIndex) {
ok=false;
return 0;
}
result = evaluateAdditionConstExpr(endIndex,ok);
if (mIndex!=endIndex)
ok = false;
return result;
}
int CppParser::evaluateAdditionConstExpr(int endIndex, bool &ok)
{
int result = 0;
if (mIndex>=endIndex) {
ok=false;
return 0;
}
result = evaluateMultiplyConstExpr(endIndex,ok);
if (!ok)
return result;
while (mIndex<endIndex) {
if (mTokenizer[mIndex]->text=='+') {
mIndex++;
int temp = evaluateMultiplyConstExpr(endIndex,ok);
if (!ok)
return result;
result+=temp;
} else if (mTokenizer[mIndex]->text=='-') {
mIndex++;
int temp = evaluateMultiplyConstExpr(endIndex,ok);
if (!ok)
return result;
result-=temp;
} else
break;
}
return result;
}
int CppParser::evaluateMultiplyConstExpr(int endIndex, bool &ok)
{
int result = 0;
if (mIndex>=endIndex) {
ok=false;
return 0;
}
result = evaluateConstExprTerm(endIndex,ok);
if (!ok)
return result;
while (mIndex<endIndex) {
if (mTokenizer[mIndex]->text=='*') {
mIndex++;
int temp = evaluateConstExprTerm(endIndex,ok);
if (!ok)
return result;
result*=temp;
} else if (mTokenizer[mIndex]->text=='/') {
mIndex++;
int temp = evaluateConstExprTerm(endIndex,ok);
if (!ok)
return result;
result/=temp;
} else if (mTokenizer[mIndex]->text=='%') {
mIndex++;
int temp = evaluateConstExprTerm(endIndex,ok);
if (!ok)
return result;
result%=temp;
} else
break;
}
return result;
}
int CppParser::evaluateConstExprTerm(int endIndex, bool &ok)
{
int result = 0;
if (mIndex>=endIndex) {
ok=false;
return 0;
}
if (mTokenizer[mIndex]->text=="(") {
mIndex++;
result = evaluateConstExpr(endIndex, ok);
if (mIndex>=endIndex || mTokenizer[mIndex]->text!=')')
ok=false;
mIndex++;
} else if (isIdentChar(mTokenizer[mIndex]->text[0])
|| mTokenizer[mIndex]->text=="::") {
QString s = mTokenizer[mIndex]->text;
QSet<QString> searched;
mIndex++;
if (s=="::") {
if (mIndex>=endIndex || !isIdentChar(mTokenizer[mIndex]->text[0])) {
ok=false;
return result;
}
s+=mTokenizer[mIndex]->text;
mIndex++;
}
while (mIndex+1<endIndex
&& mTokenizer[mIndex]->text=="::"
&& isIdentChar(mTokenizer[mIndex+1]->text[0])){
s += "::" + mTokenizer[mIndex+1]->text;
mIndex+=2;
}
while (true){
//prevent infinite loop
if (searched.contains(s)) {
ok=false;
return result;
}
searched.insert(s);
PStatement statement = doFindStatement(s);
if (!statement) {
ok=false;
return result;
}
if (statement->kind == StatementKind::skEnum) {
result = statement->value.toInt(&ok);
break;
} else if (statement->kind == StatementKind::skPreprocessor) {
if (!statement->args.isEmpty()) {
ok=false;
return result;
}
QString macroText = statement->value;
if (macroText.isEmpty()) {
ok=false;
return result;
}
if (isDigitChar(macroText[0])) {
result = evaluateLiteralNumber(endIndex,ok);
} else {
s = macroText;
}
}
}
} else {
result = evaluateLiteralNumber(endIndex,ok);
mIndex++;
}
return result;
}
int CppParser::evaluateLiteralNumber(int endIndex, bool &ok)
{
int result = 0;
if (mIndex>=endIndex) {
ok=false;
return 0;
}
if (mTokenizer[mIndex]->text.startsWith("0x")
|| mTokenizer[mIndex]->text.startsWith("0X"))
result = mTokenizer[mIndex]->text.mid(2).toInt(&ok,16);
else if (mTokenizer[mIndex]->text.startsWith("0b")
|| mTokenizer[mIndex]->text.startsWith("0B"))
result = mTokenizer[mIndex]->text.mid(2).toInt(&ok,2);
else if (mTokenizer[mIndex]->text.startsWith("0"))
result = mTokenizer[mIndex]->text.toInt(&ok,8);
else
result = mTokenizer[mIndex]->text.toInt(&ok);
return result;
}
bool CppParser::checkForKeyword(KeywordType& keywordType) bool CppParser::checkForKeyword(KeywordType& keywordType)
{ {
keywordType = mCppKeywords.value(mTokenizer[mIndex]->text,KeywordType::NotKeyword); keywordType = mCppKeywords.value(mTokenizer[mIndex]->text,KeywordType::NotKeyword);
@ -2349,9 +2553,9 @@ void CppParser::handleEnum(bool isTypedef)
//enum class //enum class
isEnumClass = true; isEnumClass = true;
mIndex++; //skip class mIndex++; //skip class
} }
bool isAdhocVar=false; bool isAdhocVar=false;
bool isNonameEnum=false;
int endIndex=-1; int endIndex=-1;
if ((mIndex< tokenCount) && mTokenizer[mIndex]->text.startsWith('{')) { // enum {...} NAME if ((mIndex< tokenCount) && mTokenizer[mIndex]->text.startsWith('{')) { // enum {...} NAME
// Skip to the closing brace // Skip to the closing brace
@ -2360,9 +2564,12 @@ void CppParser::handleEnum(bool isTypedef)
if (i + 1 < tokenCount) { if (i + 1 < tokenCount) {
enumName = mTokenizer[i + 1]->text.trimmed(); enumName = mTokenizer[i + 1]->text.trimmed();
if (!isIdentifierOrPointer(enumName)) { if (!isIdentifierOrPointer(enumName)) {
//not a valid enum, skip to j if (isTypedef || isEnumClass) {
mIndex=indexOfNextSemicolon(i+1)+1; //not a valid enum, skip to j
return; mIndex=indexOfNextSemicolon(i+1)+1;
return;
} else
isNonameEnum = true;
} }
if (!isTypedef) { if (!isTypedef) {
//it's an ad-hoc enum var define; //it's an ad-hoc enum var define;
@ -2371,13 +2578,20 @@ void CppParser::handleEnum(bool isTypedef)
mIndex=indexOfNextSemicolon(i+1)+1; mIndex=indexOfNextSemicolon(i+1)+1;
return; return;
} }
enumName = "__enum__"+enumName+"__"; enumName = "__@enum@__"+enumName+"__";
isAdhocVar=true; isAdhocVar=true;
} }
} }
endIndex=i+1; endIndex=i+1;
} else if (mIndex+1< tokenCount && mTokenizer[mIndex+1]->text.startsWith('{')){ // enum NAME {...}; } else if (mIndex+1< tokenCount && mTokenizer[mIndex+1]->text.startsWith('{')){ // enum NAME {...};
enumName = mTokenizer[mIndex]->text; enumName = mTokenizer[mIndex]->text;
mIndex++;
} else if (mIndex+1< tokenCount && mTokenizer[mIndex+1]->text.startsWith(':')){ // enum NAME:int {...};
enumName = mTokenizer[mIndex]->text;
//skip :
mIndex = indexOfNextLeftBrace(mIndex);
if (mIndex>tokenCount)
return;
} else { } else {
// enum NAME blahblah // enum NAME blahblah
// it's an old c-style enum variable definition // it's an old c-style enum variable definition
@ -2386,34 +2600,37 @@ void CppParser::handleEnum(bool isTypedef)
// Add statement for enum name too // Add statement for enum name too
PStatement enumStatement; PStatement enumStatement;
if (isEnumClass) { if (!isNonameEnum) {
enumStatement=addStatement( if (isEnumClass) {
getCurrentScope(), enumStatement=addStatement(
mCurrentFile, getCurrentScope(),
"enum class", mCurrentFile,
enumName, "enum class",
"", enumName,
"", "",
"", "",
startLine, "",
StatementKind::skEnumClassType, startLine,
getScope(), StatementKind::skEnumClassType,
mCurrentMemberAccessibility, getScope(),
StatementProperty::spHasDefinition); mCurrentMemberAccessibility,
} else { StatementProperty::spHasDefinition);
enumStatement=addStatement( } else {
getCurrentScope(), enumStatement=addStatement(
mCurrentFile, getCurrentScope(),
"enum", mCurrentFile,
enumName, "enum",
"", enumName,
"", "",
"", "",
startLine, "",
StatementKind::skEnumType, startLine,
getScope(), StatementKind::skEnumType,
mCurrentMemberAccessibility, getScope(),
StatementProperty::spHasDefinition); mCurrentMemberAccessibility,
isAdhocVar?(StatementProperty::spHasDefinition|StatementProperty::spDummyStatement)
:StatementProperty::spHasDefinition );
}
} }
if (isAdhocVar) { if (isAdhocVar) {
//Ad-hoc var definition //Ad-hoc var definition
@ -2454,69 +2671,81 @@ void CppParser::handleEnum(bool isTypedef)
mIndex++; mIndex++;
// Call every member "enum NAME ITEMNAME" // Call every member "enum NAME ITEMNAME"
QString lastType("enum"); QString lastType;
if (!enumName.isEmpty()) if (enumStatement && !isAdhocVar)
lastType += ' ' + enumName; lastType = "enum " + enumName;
QString cmd; QString cmd;
QString args; QString args;
if (mTokenizer[mIndex]->text!='}') { int value=0;
while ((mIndex < tokenCount) && bool canCalcValue=true;
mTokenizer[mIndex]->text!='}') { while ((mIndex < tokenCount) &&
if (mTokenizer[mIndex]->text=="=") { mTokenizer[mIndex]->text!='}') {
mIndex=indexOfNextPeriodOrSemicolon(mIndex); if (tokenIsIdentifier(mTokenizer[mIndex]->text)) {
continue; cmd = mTokenizer[mIndex]->text;
} else if (tokenIsIdentifier(mTokenizer[mIndex]->text)) { args = "";
cmd = mTokenizer[mIndex]->text; if (mIndex+1<tokenCount &&
args = ""; mTokenizer[mIndex+1]->text=="=") {
if (isEnumClass) { mIndex+=2;
if (enumStatement) { if (mIndex<tokenCount) {
addStatement( bool ok;
enumStatement, int endIndex = indexOfNextPeriodOrSemicolon(mIndex);
mCurrentFile, value = evaluateConstExpr(endIndex,ok);
lastType, if (!ok) {
cmd, canCalcValue=false;
args,
"",
"",
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
} }
} else { mIndex = endIndex - 1;
if (enumStatement) {
addStatement(
enumStatement,
mCurrentFile,
lastType,
cmd,
args,
"",
"",
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
}
addStatement(
getCurrentScope(),
mCurrentFile,
lastType,
cmd,
"",
"",
"",
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
} }
} }
mIndex ++ ; if (isEnumClass) {
if (enumStatement) {
addStatement(
enumStatement,
mCurrentFile,
lastType,
cmd,
args,
"",
canCalcValue?QString("%1").arg(value):"",
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
}
} else {
QString strValue=canCalcValue?QString("%1").arg(value):"";
if (enumStatement) {
addStatement(
enumStatement,
mCurrentFile,
lastType,
cmd,
args,
"",
strValue,
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
}
addStatement(
getCurrentScope(),
mCurrentFile,
lastType,
cmd,
"",
"",
strValue,
mTokenizer[mIndex]->line,
StatementKind::skEnum,
getScope(),
mCurrentMemberAccessibility,
StatementProperty::spHasDefinition);
}
value++;
} }
mIndex ++ ;
} }
if (mIndex<endIndex) if (mIndex<endIndex)
mIndex=endIndex; mIndex=endIndex;
@ -3474,6 +3703,7 @@ void CppParser::handleStructs(bool isTypedef)
PStatement scopeStatement=getCurrentScope(); PStatement scopeStatement=getCurrentScope();
QString scopelessName; QString scopelessName;
QString parentName; QString parentName;
if (splitLastMember(command,scopelessName,parentName)) { if (splitLastMember(command,scopelessName,parentName)) {
scopeStatement = getIncompleteClass(parentName,getCurrentScope()); scopeStatement = getIncompleteClass(parentName,getCurrentScope());
} else { } else {
@ -3580,7 +3810,7 @@ void CppParser::handleStructs(bool isTypedef)
getCurrentScope(), getCurrentScope(),
mCurrentFile, mCurrentFile,
prefix, prefix,
"__"+command, "_@dummy@_"+command,
"", "",
"", "",
"", "",
@ -3589,7 +3819,7 @@ void CppParser::handleStructs(bool isTypedef)
StatementKind::skClass, StatementKind::skClass,
getScope(), getScope(),
mCurrentMemberAccessibility, mCurrentMemberAccessibility,
StatementProperty::spHasDefinition); StatementProperty::spHasDefinition | StatementProperty::spDummyStatement);
} }
if (isTypedef) { if (isTypedef) {
//typedef //typedef

View File

@ -216,6 +216,12 @@ private:
QStringList sortFilesByIncludeRelations(const QSet<QString> &files); QStringList sortFilesByIncludeRelations(const QSet<QString> &files);
int evaluateConstExpr(int endIndex, bool &ok);
int evaluateAdditionConstExpr(int endIndex, bool &ok);
int evaluateMultiplyConstExpr(int endIndex, bool &ok);
int evaluateConstExprTerm(int endIndex, bool &ok);
int evaluateLiteralNumber(int endIndex, bool &ok);
bool checkForKeyword(KeywordType &keywordType); bool checkForKeyword(KeywordType &keywordType);
bool checkForNamespace(KeywordType keywordType); bool checkForNamespace(KeywordType keywordType);
bool checkForPreprocessor(); bool checkForPreprocessor();

View File

@ -153,7 +153,8 @@ enum StatementProperty {
spOverride = 0x0040, spOverride = 0x0040,
spConstexpr = 0x0080, spConstexpr = 0x0080,
spFunctionPointer = 0x0100, spFunctionPointer = 0x0100,
spOperatorOverloading = 0x0200 spOperatorOverloading = 0x0200,
spDummyStatement = 0x0400
}; };
Q_DECLARE_FLAGS(StatementProperties, StatementProperty) Q_DECLARE_FLAGS(StatementProperties, StatementProperty)

View File

@ -148,12 +148,18 @@ QVariant ClassBrowserModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
if (node->statement) { if (node->statement) {
if (!(node->statement->type.isEmpty()) && if (!(node->statement->type.isEmpty())) {
((node->statement->kind == StatementKind::skFunction) if ((node->statement->kind == StatementKind::skFunction)
|| (node->statement->kind == StatementKind::skVariable) || (node->statement->kind == StatementKind::skVariable)
|| (node->statement->kind == StatementKind::skTypedef) || (node->statement->kind == StatementKind::skTypedef)
)) { ) {
return node->statement->command + node->statement->args + " : " + node->statement->type; return node->statement->command + node->statement->args + " : " + node->statement->type;
} else if (node->statement->kind == StatementKind::skEnum) {
if (!node->statement->value.isEmpty())
return node->statement->command + node->statement->args + QString("(%1)").arg(node->statement->value);
else
return node->statement->command;
}
} }
return node->statement->command + node->statement->args; return node->statement->command + node->statement->args;
} }
@ -351,9 +357,12 @@ void ClassBrowserModel::filterChildren(ClassBrowserNode *node, const StatementMa
if (mProcessedStatements.contains(statement.get())) if (mProcessedStatements.contains(statement.get()))
continue; continue;
// if (statement->properties.testFlag(StatementProperty::spDummyStatement))
// continue;
if (statement->kind == StatementKind::skBlock) if (statement->kind == StatementKind::skBlock)
continue; continue;
if (statement->isInherited() && !pSettings->ui().classBrowserShowInherited()) if (statement->isInherited() && !pSettings->ui().classBrowserShowInherited())
continue; continue;

View File

@ -286,7 +286,9 @@ void CodeCompletionPopup::addStatement(const PStatement& statement, const QStrin
if (statement->kind == StatementKind::skConstructor if (statement->kind == StatementKind::skConstructor
|| statement->kind == StatementKind::skDestructor || statement->kind == StatementKind::skDestructor
|| statement->kind == StatementKind::skBlock || statement->kind == StatementKind::skBlock
|| statement->properties.testFlag(StatementProperty::spOperatorOverloading)) || statement->properties.testFlag(StatementProperty::spOperatorOverloading)
|| statement->properties.testFlag(StatementProperty::spDummyStatement)
)
return; return;
if ((line!=-1) if ((line!=-1)
&& (line < statement->line) && (line < statement->line)