work save
This commit is contained in:
parent
0c6be9b93c
commit
d18347c44e
|
@ -273,7 +273,7 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
|||
}
|
||||
break;
|
||||
} else {
|
||||
//if IsValidIdentifier(fTokenizer[fIndex]^.Text) then
|
||||
//if IsValidIdentifier(mTokenizer[mIndex]->text) then
|
||||
// Still walking through type
|
||||
QString s = expandMacroType(mTokenizer[mIndex]->text); //todo: do we really need expand macro? it should be done in preprocessor
|
||||
if (s == "static")
|
||||
|
@ -742,7 +742,7 @@ void CppParser::handleEnum()
|
|||
cmd,
|
||||
args,
|
||||
"",
|
||||
//fTokenizer[fIndex]^.Line,
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
startLine,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
|
@ -759,7 +759,7 @@ void CppParser::handleEnum()
|
|||
cmd,
|
||||
args,
|
||||
"",
|
||||
//fTokenizer[fIndex]^.Line,
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
startLine,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
|
@ -859,9 +859,347 @@ void CppParser::handleKeyword()
|
|||
mIndex++;
|
||||
mIndex++; // step over
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CppParser::HandleMethod(const QString &sType, const QString &sName, const QString &sArgs, bool isStatic, bool isFriend)
|
||||
{
|
||||
bool isValid = true;
|
||||
bool isDeclaration = false; // assume it's not a prototype
|
||||
int i = mIndex;
|
||||
int startLine = mTokenizer[mIndex]->line;
|
||||
|
||||
// Skip over argument list
|
||||
while ((mIndex < mTokenizer.tokenCount()) and ! (
|
||||
isblockChar(mTokenizer[mIndex]->text.front())
|
||||
|| mTokenizer[mIndex]->text.startsWith(':')))
|
||||
mIndex++;
|
||||
|
||||
if (mIndex >= mTokenizer.tokenCount()) // not finished define, just skip it;
|
||||
return;
|
||||
|
||||
PStatement functionClass = getCurrentScope();
|
||||
// Check if this is a prototype
|
||||
if (mTokenizer[mIndex]->text.startsWith(';')
|
||||
|| mTokenizer[mIndex]->text.startsWith('}')) {// prototype
|
||||
isDeclaration = true;
|
||||
} else {
|
||||
// Find the function body start after the inherited constructor
|
||||
if ((mIndex < mTokenizer.tokenCount()) && mTokenizer[mIndex]->text.startsWith(':')) {
|
||||
while ((mIndex < mTokenizer.tokenCount()) && !isblockChar(mTokenizer[mIndex]->text.front()))
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
// Still a prototype
|
||||
if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.startsWith(';')
|
||||
|| mTokenizer[mIndex]->text.startsWith('}'))) {// prototype
|
||||
isDeclaration = true;
|
||||
}
|
||||
}
|
||||
|
||||
QString scopelessName;
|
||||
PStatement functionStatement;
|
||||
if (isFriend && isDeclaration && functionClass) {
|
||||
int delimPos = sName.indexOf("::");
|
||||
if (delimPos >= 0) {
|
||||
scopelessName = sName.mid(delimPos+2);
|
||||
} else
|
||||
scopelessName = sName;
|
||||
//TODO : we should check namespace
|
||||
functionClass->friends.insert(scopelessName);
|
||||
} else if (isValid) {
|
||||
// Use the class the function belongs to as the parent ID if the function is declared outside of the class body
|
||||
int delimPos = sName.indexOf("::");
|
||||
QString scopelessName;
|
||||
QString parentClassName;
|
||||
PStatement functionClass;
|
||||
if (delimPos >= 0) {
|
||||
// Provide Bar instead of Foo::Bar
|
||||
scopelessName = sName.mid(delimPos);
|
||||
|
||||
// Check what class this function belongs to
|
||||
parentClassName = sName.mid(0, delimPos);
|
||||
functionClass = getIncompleteClass(parentClassName,getCurrentScope());
|
||||
} else
|
||||
scopelessName = sName;
|
||||
|
||||
StatementKind functionKind;
|
||||
// Determine function type
|
||||
if (scopelessName == sType) {
|
||||
functionKind = StatementKind::skConstructor;
|
||||
} else if (scopelessName == '~' + sType) {
|
||||
functionKind = StatementKind::skDestructor;
|
||||
} else {
|
||||
functionKind = StatementKind::skFunction;
|
||||
}
|
||||
|
||||
// For function definitions, the parent class is given. Only use that as a parent
|
||||
if (!isDeclaration) {
|
||||
functionStatement=addStatement(
|
||||
functionClass,
|
||||
mCurrentFile,
|
||||
"", // do not override hint
|
||||
sType,
|
||||
scopelessName,
|
||||
sArgs,
|
||||
"",
|
||||
//mTokenizer[mIndex - 1]^.Line,
|
||||
startLine,
|
||||
functionKind,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
isStatic);
|
||||
scanMethodArgs(functionStatement, functionStatement->args);
|
||||
// add variable this to the class function
|
||||
if (functionClass && functionClass->kind == StatementKind::skClass &&
|
||||
!isStatic) {
|
||||
//add this to non-static class member function
|
||||
addStatement(
|
||||
functionStatement,
|
||||
mCurrentFile,
|
||||
"", // do not override hint
|
||||
functionClass->command,
|
||||
"this",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skVariable,
|
||||
StatementScope::ssLocal,
|
||||
StatementClassScope::scsNone,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
} else {
|
||||
functionStatement = addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"", // do not override hint
|
||||
sType,
|
||||
scopelessName,
|
||||
sArgs,
|
||||
"",
|
||||
//mTokenizer[mIndex - 1]^.Line,
|
||||
startLine,
|
||||
functionKind,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
false,
|
||||
isStatic);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ((mIndex < mTokenizer.tokenCount()) && mTokenizer[mIndex]->text.startsWith('{')) {
|
||||
addSoloScopeLevel(functionStatement,startLine);
|
||||
mIndex++; //skip '{'
|
||||
} else if ((mIndex < mTokenizer.tokenCount()) && mTokenizer[mIndex]->text.startsWith(';')) {
|
||||
addSoloScopeLevel(functionStatement,startLine);
|
||||
if (mTokenizer[mIndex]->line != startLine)
|
||||
removeScopeLevel(mTokenizer[mIndex]->line+1);
|
||||
else
|
||||
removeScopeLevel(startLine+1);
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
if (i == mIndex) { // if not moved ahead, something is wrong but don't get stuck ;)
|
||||
if ( (mIndex < mTokenizer.tokenCount()) &&
|
||||
! isBraceChar(mTokenizer[mIndex]->text.front())) {
|
||||
mIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CppParser::handleNamespace()
|
||||
{
|
||||
bool isInline=false;
|
||||
if (mTokenizer[mIndex]->text == "inline") {
|
||||
isInline = true;
|
||||
mIndex++; //skip 'inline'
|
||||
}
|
||||
|
||||
int startLine = mTokenizer[mIndex]->line;
|
||||
mIndex++; //skip 'namespace'
|
||||
|
||||
if (!isLetterChar(mTokenizer[mIndex]->text.front()))
|
||||
//wrong namespace define, stop handling
|
||||
return;
|
||||
QString command = mTokenizer[mIndex]->text;
|
||||
mIndex++;
|
||||
if (mIndex>=mTokenizer.tokenCount())
|
||||
return;
|
||||
QString aliasName;
|
||||
if ((mIndex+2<mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == '=')) {
|
||||
aliasName=mTokenizer[mIndex+1]->text;
|
||||
//namespace alias
|
||||
addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"", // do not override hint
|
||||
aliasName, // name of the alias namespace
|
||||
command, // command
|
||||
"", // args
|
||||
"", // values
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
startLine,
|
||||
StatementKind::skNamespaceAlias,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
mIndex+=2; //skip ;
|
||||
return;
|
||||
} else if (isInline) {
|
||||
//inline namespace , just skip it
|
||||
// Skip to '{'
|
||||
while ((mIndex<mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() != '{'))
|
||||
mIndex++;
|
||||
int i =skipBraces(mIndex); //skip '}'
|
||||
if (i==mIndex)
|
||||
mInlineNamespaceEndSkips.append(mTokenizer.tokenCount());
|
||||
else
|
||||
mInlineNamespaceEndSkips.append(i);
|
||||
if (mIndex<mTokenizer.tokenCount())
|
||||
mIndex++; //skip '{'
|
||||
} else {
|
||||
PStatement namespaceStatement = addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"", // do not override hint
|
||||
"", // type
|
||||
command, // command
|
||||
"", // args
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skNamespace,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
addSoloScopeLevel(namespaceStatement,startLine);
|
||||
|
||||
// Skip to '{'
|
||||
while ((mIndex<mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith('{'))
|
||||
mIndex++;
|
||||
if (mIndex<mTokenizer.tokenCount())
|
||||
mIndex++; //skip '{'
|
||||
}
|
||||
}
|
||||
|
||||
void CppParser::handleOtherTypedefs()
|
||||
{
|
||||
int startLine = mTokenizer[mIndex]->line;
|
||||
// Skip typedef word
|
||||
mIndex++;
|
||||
|
||||
if (mIndex>=mTokenizer.tokenCount())
|
||||
return;
|
||||
|
||||
if (mTokenizer[mIndex]->text.front() == '('
|
||||
|| mTokenizer[mIndex]->text.front() == ','
|
||||
|| mTokenizer[mIndex]->text.front() == ';') { // error typedef
|
||||
//skip to ;
|
||||
while ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';'))
|
||||
mIndex++;
|
||||
//skip ;
|
||||
if ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';'))
|
||||
mIndex++;
|
||||
return;
|
||||
}
|
||||
QString oldType;
|
||||
// Walk up to first new word (before first comma or ;)
|
||||
while(true) {
|
||||
oldType += mTokenizer[mIndex]->text + ' ';
|
||||
mIndex++;
|
||||
if ((mIndex + 1 < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex + 1]->text.front() == ','
|
||||
|| mTokenizer[mIndex + 1]->text.front() == ';'))
|
||||
break;
|
||||
if ((mIndex + 2 < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex + 2]->text.front() == ','
|
||||
|| mTokenizer[mIndex + 2]->text.front() == ';'))
|
||||
break;
|
||||
}
|
||||
oldType = oldType.trimmed();
|
||||
|
||||
|
||||
// Add synonyms for old
|
||||
if ((mIndex+1 < mTokenizer.tokenCount()) && !oldType.isEmpty()) {
|
||||
while(true) {
|
||||
// Support multiword typedefs
|
||||
if (mIndex+2 < mTokenizer.tokenCount()) and (mTokenizer[mIndex + 2]->text[1] in [',', ';']) then begin // function define
|
||||
if (mIndex + 2 < mTokenizer.tokenCount()) and (mIndex + 1 < mTokenizer.tokenCount()) and (mTokenizer[mIndex + 1]->text[1] = '(') then begin
|
||||
//valid function define
|
||||
NewType:=TrimRight(mTokenizer[mIndex]->text);
|
||||
NewType:=Copy(NewType,2,Length(NewType)-2); //remove '(' and ')';
|
||||
NewType:=TrimRight(NewType);
|
||||
p:=LastDelimiter(' ',NewType);
|
||||
if p <> 0 then
|
||||
NewType := Copy(NewType,p+1,Length(NewType)-p);
|
||||
AddStatement(
|
||||
GetCurrentScope,
|
||||
fCurrentFile,
|
||||
'typedef ' + OldType + ' ' + mTokenizer[mIndex]->text + ' ' + mTokenizer[mIndex + 1]->text, // do not override hint
|
||||
OldType,
|
||||
NewType,
|
||||
mTokenizer[mIndex + 1]->text,
|
||||
'',
|
||||
startLine,
|
||||
skTypedef,
|
||||
GetScope,
|
||||
fClassScope,
|
||||
True,
|
||||
nil,
|
||||
False);
|
||||
end;
|
||||
NewType:='';
|
||||
//skip to ',' or ';'
|
||||
Inc(mIndex,2);
|
||||
{
|
||||
while (mIndex< mTokenizer.tokenCount()) and not (mTokenizer[mIndex]->text[1] in [',', ';']) do
|
||||
Inc(mIndex);
|
||||
}
|
||||
end else if not (mTokenizer[mIndex+1]->text[1] in [',', ';', '(']) then begin
|
||||
NewType := NewType + mTokenizer[mIndex]->text + ' ';
|
||||
Inc(mIndex);
|
||||
end else begin
|
||||
NewType := NewType + mTokenizer[mIndex]->text + ' ';
|
||||
NewType := TrimRight(NewType);
|
||||
AddStatement(
|
||||
GetCurrentScope,
|
||||
fCurrentFile,
|
||||
'typedef ' + OldType + ' ' + NewType, // override hint
|
||||
OldType,
|
||||
NewType,
|
||||
'',
|
||||
'',
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
startLine,
|
||||
skTypedef,
|
||||
GetScope,
|
||||
fClassScope,
|
||||
True,
|
||||
nil,
|
||||
False);
|
||||
NewType := '';
|
||||
Inc(mIndex);
|
||||
end;
|
||||
if (mIndex>= mTokenizer.tokenCount()) or (mTokenizer[mIndex]->text[1] = ';') then
|
||||
break
|
||||
else if mTokenizer[mIndex]->text[1] = ',' then
|
||||
Inc(mIndex);
|
||||
if (mIndex+1 >= mTokenizer.tokenCount())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Step over semicolon (saves one HandleStatement loop)
|
||||
Inc(mIndex);
|
||||
}
|
||||
|
||||
QString CppParser::expandMacroType(const QString &name)
|
||||
{
|
||||
//its done in the preprocessor
|
||||
|
@ -1102,6 +1440,11 @@ bool CppParser::isInvalidVarPrefixChar(const QChar &ch)
|
|||
}
|
||||
}
|
||||
|
||||
bool CppParser::isBraceChar(const QChar &ch)
|
||||
{
|
||||
return ch == '{' || ch =='}';
|
||||
}
|
||||
|
||||
bool CppParser::isLineChar(const QChar &ch)
|
||||
{
|
||||
return ch=='\n' || ch=='\r';
|
||||
|
|
|
@ -184,8 +184,8 @@ private:
|
|||
const QString& sNoNameArgs);
|
||||
void handleCatchBlock();
|
||||
void handleEnum();
|
||||
void handleKeyword();
|
||||
void handleForBlock();
|
||||
void handleKeyword();
|
||||
void HandleMethod(
|
||||
const QString& sType,
|
||||
const QString& sName,
|
||||
|
@ -249,6 +249,9 @@ private:
|
|||
/* '#', ',', ';', ':', '{', '}', '!', '/', '+', '-', '<', '>' */
|
||||
bool isInvalidVarPrefixChar(const QChar& ch);
|
||||
|
||||
/*'{', '}' */
|
||||
bool isBraceChar(const QChar& ch);
|
||||
|
||||
bool isLineChar(const QChar& ch);
|
||||
|
||||
bool isNotFuncArgs(const QString& args);
|
||||
|
|
Loading…
Reference in New Issue