work save

This commit is contained in:
royqh1979 2021-08-22 21:23:58 +08:00
parent 52eed2f34d
commit 9da351dfda
5 changed files with 541 additions and 118 deletions

View File

@ -115,7 +115,7 @@ PStatement CppParser::findAndScanBlockAt(const QString &filename, int line)
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
if (mParsing) if (mParsing)
return PStatement(); return PStatement();
PFileIncludes fileIncludes = findFileIncludes(filename); PFileIncludes fileIncludes = mIncludesList->value(filename);
if (!fileIncludes) if (!fileIncludes)
return PStatement(); return PStatement();
@ -163,7 +163,7 @@ QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QStri
PStatement CppParser::findFunctionAt(const QString &fileName, int line) PStatement CppParser::findFunctionAt(const QString &fileName, int line)
{ {
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
PFileIncludes fileIncludes = findFileIncludes(fileName); PFileIncludes fileIncludes = mIncludesList->value(fileName);
if (!fileIncludes) if (!fileIncludes)
return PStatement(); return PStatement();
for (PStatement statement : fileIncludes->statements) { for (PStatement statement : fileIncludes->statements) {
@ -198,6 +198,7 @@ int CppParser::findLastOperator(const QString &phrase) const
PStatementList CppParser::findNamespace(const QString &name) PStatementList CppParser::findNamespace(const QString &name)
{ {
QMutexLocker locker(&mMutex);
return mNamespaces.value(name,PStatementList()); return mNamespaces.value(name,PStatementList());
} }
@ -214,6 +215,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
if (mParsing && !force) if (mParsing && !force)
return PStatement(); return PStatement();
//find the start scope statement
QString namespaceName, remainder; QString namespaceName, remainder;
QString nextScopeWord,operatorToken,memberName; QString nextScopeWord,operatorToken,memberName;
PStatement statement; PStatement statement;
@ -252,7 +254,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
currentClassType = currentClass; currentClassType = currentClass;
remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName); remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName);
if (currentClass && (currentClass->kind == StatementKind::skNamespace)) { if (currentClass && (currentClass->kind == StatementKind::skNamespace)) {
PStatementList namespaceList = mNamespaces.value(currentClass->command); PStatementList namespaceList = mNamespaces.value(currentClass->fullName);
if (!namespaceList || namespaceList->isEmpty()) if (!namespaceList || namespaceList->isEmpty())
return PStatement(); return PStatement();
for (PStatement currentNamespace:*namespaceList){ for (PStatement currentNamespace:*namespaceList){
@ -268,71 +270,91 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
} }
currentClassType = currentClass; currentClassType = currentClass;
if (MemberName <> '') and (statement._Kind in [skTypedef]) then begin if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
TypeStatement := FindTypeDefinitionOf(FileName,statement^._Type, CurrentClassType); PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
if Assigned(TypeStatement) then if (typeStatement)
Statement := TypeStatement; statement = typeStatement;
end; }
if (statement._Kind in [skAlias]) and not SameStr(Phrase,statement^._Type) then begin //using alias like 'using std::vector;'
Statement := FindStatementOf(FileName, statement^._Type,CurrentClass, CurrentClassType, force); if ((statement->kind == StatementKind::skAlias) &&
if not assigned(statement) then (phrase!=statement->type)) {
Exit; statement = findStatementOf(fileName, statement->type,
end; currentClass, currentClassType, force);
if (!statement)
return PStatement();
}
if (statement._Kind = skConstructor) then begin // we need the class, not the construtor if (statement->kind == StatementKind::skConstructor) {
statement:=statement^._ParentScope; // we need the class, not the construtor
if not assigned(statement) then statement = statement->parentScope.lock();
Exit; if (!statement)
end; return PStatement();
}
LastScopeStatement:=nil; PStatement lastScopeStatement;
while MemberName <> '' do begin QString typeName;
if statement._Kind in [skVariable,skParameter,skFunction] then begin PStatement typeStatement;
if (statement^._Kind = skFunction) while (!memberName.isEmpty()) {
and assigned(statement^._ParentScope) if (statement->kind == StatementKind::skVariable
and (STLContainers.ValueOf(statement^._ParentScope^._FullName)>0) || statement->kind == StatementKind::skParameter
and (STLElementMethods.ValueOf(statement^._Command)>0) || statement->kind == StatementKind::skFunction) {
and assigned(LastScopeStatement) then begin
typeName:=self.FindFirstTemplateParamOf(FileName,LastScopeStatement^._Type,LastScopeStatement^._ParentScope);
TypeStatement:=FindTypeDefinitionOf(FileName, typeName,LastScopeStatement^._ParentScope);
end else
TypeStatement := FindTypeDefinitionOf(FileName,statement^._Type, CurrentClassType);
if assigned(TypeStatement) and ( bool isSTLContainerFunctions = false;
STLPointers.Valueof(TypeStatement^._FullName)>=0)
and SameStr(OperatorToken,'->') then begin
typeName:=self.FindFirstTemplateParamOf(FileName,Statement^._Type,statement^._ParentScope);
TypeStatement:=FindTypeDefinitionOf(FileName, typeName,statement^._ParentScope);
end else if assigned(TypeStatement) and (STLContainers.ValueOf(TypeStatement^._FullName)>0)
and EndsStr(']',NextScopeWord) then begin
typeName:=self.FindFirstTemplateParamOf(FileName,Statement^._Type,statement^._ParentScope);
TypeStatement:=FindTypeDefinitionOf(FileName, typeName,statement^._ParentScope);
end;
lastScopeStatement:= statement;
if Assigned(TypeStatement) then
Statement := TypeStatement;
end else
lastScopeStatement:= statement;
remainder := SplitPhrase(remainder,NextScopeWord,OperatorToken,MemberName);
MemberStatement := FindMemberOfStatement(NextScopeWord,statement);
if not Assigned(MemberStatement) then begin;
Exit;
end;
CurrentClassType:=statement; if (statement->kind == StatementKind::skFunction){
Statement:=MemberStatement; PStatement parentScope = statement->parentScope.lock();
if (MemberName <> '') and (statement._Kind in [skTypedef]) then begin if (parentScope
TypeStatement := FindTypeDefinitionOf(FileName,statement^._Type, CurrentClassType); && STLContainers.contains(parentScope->fullName)
if Assigned(TypeStatement) then && STLElementMethods.contains(statement->command)
Statement := TypeStatement; && lastScopeStatement) {
end; isSTLContainerFunctions = true;
end; PStatement lastScopeParent = lastScopeStatement->parentScope.lock();
Result := Statement; typeName=findFirstTemplateParamOf(fileName,lastScopeStatement->type,
lastScopeParent );
typeStatement=findTypeDefinitionOf(fileName, typeName,
lastScopeParent );
}
}
if (!isSTLContainerFunctions)
typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
finally //it's stl smart pointer
fCriticalSection.Release; if ((typeStatement)
end; && STLPointers.contains(typeStatement->fullName)
&& (operatorToken == "->")) {
PStatement parentScope = statement->parentScope.lock();
typeName=findFirstTemplateParamOf(fileName,statement->type, parentScope);
typeStatement=findTypeDefinitionOf(fileName, typeName,parentScope);
} else if ((typeStatement)
&& STLContainers.contains(typeStatement->fullName)
&& nextScopeWord.endsWith(']')) {
//it's a std container
PStatement parentScope = statement->parentScope.lock();
typeName = findFirstTemplateParamOf(fileName,statement->type,
parentScope);
typeStatement = findTypeDefinitionOf(fileName, typeName,
parentScope);
}
lastScopeStatement = statement;
if (typeStatement)
statement = typeStatement;
} else
lastScopeStatement = statement;
remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName);
PStatement memberStatement = findMemberOfStatement(nextScopeWord,statement);
if (!memberStatement)
return PStatement();
currentClassType=statement;
statement = memberStatement;
if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
if (typeStatement)
statement = typeStatement;
}
}
return statement;
} }
PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentClass, bool force) PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentClass, bool force)
@ -341,6 +363,185 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
return findStatementOf(fileName,phrase,currentClass,statementParentType,force); return findStatementOf(fileName,phrase,currentClass,statementParentType,force);
} }
PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, PStatement startScope, bool force)
{
QMutexLocker locker(&mMutex);
if (mParsing && !force)
return PStatement();
PStatement scopeStatement = startScope;
// repeat until reach global
PStatement result;
while (scopeStatement) {
//search members of current scope
result = findStatementInScope(phrase, scopeStatement);
if (result)
return result;
// not found
// search members of all usings (in current scope )
for (QString namespaceName:scopeStatement->usingList) {
result = findStatementInNamespace(phrase,namespaceName);
if (result)
return result;
}
scopeStatement = scopeStatement->parentScope.lock();
}
// Search all global members
result = findMemberOfStatement(phrase,PStatement());
if (result)
return result;
//Find in all global usings
const QSet<QString>& fileUsings = getFileUsings(fileName);
// add members of all fusings
for (QString namespaceName:fileUsings) {
result = findStatementInNamespace(phrase,namespaceName);
if (result)
return result;
}
return PStatement();
}
PStatement CppParser::findTypeDefinitionOf(const QString &fileName, const QString &aType, PStatement currentClass)
{
QMutexLocker locker(&mMutex);
if (mParsing)
return PStatement();
// Remove pointer stuff from type
QString s = aType; // 'Type' is a keyword
int position = s.length()-1;
while ((position >= 0) && (s[position] == '*'
|| s[position] == ' '
|| s[position] == '&'))
position--;
if (position != s.length()-1)
s.truncate(position+1);
// Strip template stuff
position = s.indexOf('<');
if (position >= 0) {
int endPos = getBracketEnd(s,position);
s.remove(position,endPos-position+1);
}
// Use last word only (strip 'const', 'static', etc)
position = s.lastIndexOf(' ');
if (position >= 0)
s = s.mid(position+1);
PStatement scopeStatement = currentClass;
PStatement statement = findStatementOf(fileName,s,currentClass);
return getTypeDef(statement,fileName,aType);
}
bool CppParser::freeze()
{
QMutexLocker locker(&mMutex);
if (mParsing)
return false;
mLockCount++;
return true;
}
bool CppParser::freeze(const QString &serialId)
{
QMutexLocker locker(&mMutex);
if (mParsing)
return false;
if (mSerialId!=serialId)
return false;
mLockCount++;
return true;
}
QStringList CppParser::getClassesList()
{
QMutexLocker locker(&mMutex);
if (mParsing)
return QStringList();
QStringList list;
// fills List with a list of all the known classes
QQueue<PStatement> queue;
queue.enqueue(PStatement());
while (!queue.isEmpty()) {
PStatement statement = queue.dequeue();
StatementMap statementMap = mStatementList.childrenStatements(statement);
for (PStatement child:statementMap) {
if (child->kind == StatementKind::skClass)
list.append(child->command);
if (!child->children.isEmpty())
queue.enqueue(child);
}
}
return list;
}
QSet<QString> CppParser::getFileDirectIncludes(const QString &filename)
{
QMutexLocker locker(&mMutex);
QSet<QString> list;
if (mParsing)
return list;
if (filename.isEmpty())
return list;
PFileIncludes fileIncludes = mIncludesList->value(filename,PFileIncludes());
if (fileIncludes) {
QMap<QString, bool>::const_iterator iter = fileIncludes->includeFiles.cbegin();
while (iter != fileIncludes->includeFiles.cend()) {
if (iter.value())
list.insert(iter.key());
}
}
return list;
}
QSet<QString> CppParser::getFileIncludes(const QString &filename)
{
QMutexLocker locker(&mMutex);
QSet<QString> list;
if (mParsing)
return list;
if (filename.isEmpty())
return list;
list.insert(filename);
PFileIncludes fileIncludes = mIncludesList->value(filename,PFileIncludes());
if (fileIncludes) {
for (QString file: fileIncludes->includeFiles.keys()) {
list.insert(file);
}
}
return list;
}
QSet<QString> CppParser::getFileUsings(const QString &filename)
{
QMutexLocker locker(&mMutex);
if (filename.isEmpty())
return QSet<QString>();
if (mParsing)
return QSet<QString>();
PFileIncludes fileIncludes= mIncludesList->value(filename,PFileIncludes());
if (fileIncludes) {
return fileIncludes->usings;
}
return QSet<QString>();
}
QString CppParser::getHeaderFileName(const QString &relativeTo, const QString &line)
{
QMutexLocker locker(&mMutex);
return ::getHeaderFilename(relativeTo, line, mPreprocessor.includePaths(),
mPreprocessor.projectIncludePaths());
}
StatementKind CppParser::getKindOfStatement(PStatement statement) StatementKind CppParser::getKindOfStatement(PStatement statement)
{ {
if (!statement) if (!statement)
@ -357,6 +558,151 @@ StatementKind CppParser::getKindOfStatement(PStatement statement)
return statement->kind; return statement->kind;
} }
void CppParser::invalidateFile(const QString &fileName)
{
{
QMutexLocker locker(&mMutex);
if (mParsing || mLockCount>0)
return;
updateSerialId();
mParsing = true;
}
QSet<QString> files = calculateFilesToBeReparsed(fileName);
internalInvalidateFiles(files);
mParsing = false;
}
bool CppParser::isProjectHeaderFile(const QString &fileName)
{
QMutexLocker locker(&mMutex);
return ::isSystemHeaderFile(fileName,mPreprocessor.projectIncludePaths());
}
bool CppParser::isSystemHeaderFile(const QString &fileName)
{
QMutexLocker locker(&mMutex);
return ::isSystemHeaderFile(fileName,mPreprocessor.includePaths());
}
void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNotParsed, bool updateView)
{
if (!mEnabled)
return;
{
QMutexLocker locker(&mMutex);
if (mParsing || mLockCount>0)
return;
updateSerialId();
mParsing = true;
if (updateView)
emit onBusy();
emit onStartParsing();
}
{
auto action = finally([&,this]{
mParsing = false;
if (updateView)
emit onEndParsing(mFilesScannedCount,1);
else
emit onEndParsing(mFilesScannedCount,0);
});
QString fName = fileName;
if (onlyIfNotParsed && mPreprocessor.scannedFiles().contains(fName))
return;
QSet<QString> files = calculateFilesToBeReparsed(fileName);
internalInvalidateFiles(files);
if (inProject)
mProjectFiles.insert(fileName);
else {
mProjectFiles.remove(fileName);
}
// Parse from disk or stream
mFilesToScanCount = files.count();
mFilesScannedCount = 0;
// parse header files in the first parse
for (QString file:files) {
if (isHfile(file)) {
mFilesScannedCount++;
emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount);
if (!mPreprocessor.scannedFiles().contains(file)) {
internalParse(file);
}
}
}
//we only parse CFile in the second parse
for (QString file:files) {
if (isCfile(file)) {
mFilesScannedCount++;
emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount);
if (!mPreprocessor.scannedFiles().contains(file)) {
internalParse(file);
}
}
}
}
}
void CppParser::parseFileList(bool updateView)
{
if (!mEnabled)
return;
if not fEnabled then
Exit;
fCriticalSection.Acquire;
try
if fParsing or (fLockCount>0) then
Exit;
UpdateSerialId;
fParsing:=True;
OnBusy;
OnStartParsing;
finally
fCriticalSection.Release;
end;
try
// Support stopping of parsing when files closes unexpectedly
fFilesScannedCount := 0;
fFilesToScanCount := fFilesToScan.Count;
// parse header files in the first parse
for i:=0 to fFilesToScan.Count-1 do begin
if IsCFile(fFilesToScan[i]) then
continue;
Inc(fFilesScannedCount); // progress is mentioned before scanning begins
OnProgress(fCurrentFile,fFilesToScanCount,fFilesScannedCount);
if FastIndexOf(fScannedFiles,fFilesToScan[i]) = -1 then begin
InternalParse(fFilesToScan[i]);
end;
end;
//we only parse CFile in the second parse
for i:=0 to fFilesToScan.Count-1 do begin
if not IsCFile(fFilesToScan[i]) then
continue;
Inc(fFilesScannedCount); // progress is mentioned before scanning begins
OnProgress(fCurrentFile,fFilesToScanCount,fFilesScannedCount);
if FastIndexOf(fScannedFiles,fFilesToScan[i]) = -1 then begin
InternalParse(fFilesToScan[i]);
end;
end;
fFilesToScan.Clear;
finally
fParsing:=False;
if UpdateView then
OnEndParsing(fFilesScannedCount,1)
else
OnEndParsing(fFilesScannedCount,0);
end;
}
bool CppParser::parsing()
{
return mParsing;
}
QString CppParser::getFirstTemplateParam(PStatement statement, const QString& filename, const QString& phrase, PStatement currentScope) QString CppParser::getFirstTemplateParam(PStatement statement, const QString& filename, const QString& phrase, PStatement currentScope)
{ {
if (!statement) if (!statement)
@ -400,7 +746,7 @@ void CppParser::addFileToScan(QString value, bool inProject)
mProjectFiles.insert(value); mProjectFiles.insert(value);
// Only parse given file // Only parse given file
if (!mScannedFiles->contains(value)) { if (!mPreprocessor.scannedFiles().contains(value)) {
mFilesToScan.insert(value); mFilesToScan.insert(value);
} }
@ -467,12 +813,12 @@ PStatement CppParser::addStatement(PStatement parent, const QString &fileName, c
if (oldStatement && isDefinition && !oldStatement->hasDefinition) { if (oldStatement && isDefinition && !oldStatement->hasDefinition) {
oldStatement->hasDefinition = true; oldStatement->hasDefinition = true;
if (oldStatement->fileName!=fileName) { if (oldStatement->fileName!=fileName) {
PFileIncludes fileIncludes1=findFileIncludes(fileName); PFileIncludes fileIncludes1=mIncludesList->value(fileName);
if (fileIncludes1) { if (fileIncludes1) {
fileIncludes1->statements.insert(oldStatement->fullName, fileIncludes1->statements.insert(oldStatement->fullName,
oldStatement); oldStatement);
fileIncludes1->dependingFiles.insert(oldStatement->fileName); fileIncludes1->dependingFiles.insert(oldStatement->fileName);
PFileIncludes fileIncludes2=findFileIncludes(oldStatement->fileName); PFileIncludes fileIncludes2=mIncludesList->value(oldStatement->fileName);
if (fileIncludes2) { if (fileIncludes2) {
fileIncludes2->dependedFiles.insert(fileName); fileIncludes2->dependedFiles.insert(fileName);
} }
@ -530,7 +876,7 @@ PStatement CppParser::addStatement(PStatement parent, const QString &fileName, c
} }
if (result->kind!= StatementKind::skBlock) { if (result->kind!= StatementKind::skBlock) {
PFileIncludes fileIncludes = findFileIncludes(fileName); PFileIncludes fileIncludes = mIncludesList->value(fileName);
if (fileIncludes) { if (fileIncludes) {
fileIncludes->statements.insert(result->fullName,result); fileIncludes->statements.insert(result->fullName,result);
fileIncludes->declaredStatements.insert(result->fullName,result); fileIncludes->declaredStatements.insert(result->fullName,result);
@ -611,7 +957,7 @@ void CppParser::addSoloScopeLevel(PStatement statement, int line)
mCurrentScope.append(statement); mCurrentScope.append(statement);
PFileIncludes fileIncludes = findFileIncludes(mCurrentFile); PFileIncludes fileIncludes = mIncludesList->value(mCurrentFile);
if (fileIncludes) { if (fileIncludes) {
fileIncludes->scopes.addScope(line,statement); fileIncludes->scopes.addScope(line,statement);
@ -635,7 +981,7 @@ void CppParser::removeScopeLevel(int line)
if (mCurrentScope.isEmpty()) if (mCurrentScope.isEmpty())
return; // TODO: should be an exception return; // TODO: should be an exception
PStatement currentScope = mCurrentScope.back();; PStatement currentScope = mCurrentScope.back();;
PFileIncludes fileIncludes = findFileIncludes(mCurrentFile); PFileIncludes fileIncludes = mIncludesList->value(mCurrentFile);
if (currentScope && (currentScope->kind == StatementKind::skBlock)) { if (currentScope && (currentScope->kind == StatementKind::skBlock)) {
if (currentScope->children.isEmpty()) { if (currentScope->children.isEmpty()) {
// remove no children block // remove no children block
@ -1123,6 +1469,23 @@ QString CppParser::getStatementKey(const QString &sName, const QString &sType, c
return sName + "--" + sType + "--" + sNoNameArgs; return sName + "--" + sType + "--" + sNoNameArgs;
} }
PStatement CppParser::getTypeDef(PStatement statement, const QString& fileName, const QString& aType)
{
if (!statement) {
return PStatement();
}
if (statement->kind == StatementKind::skClass) {
return statement;
} else if (statement->kind == StatementKind::skTypedef) {
if (statement->type == aType) // prevent infinite loop
return statement;
PStatement result = findTypeDefinitionOf(fileName,statement->type, statement->parentScope.lock());
if (!result) // found end of typedef trail, return result
return statement;
} else
return PStatement();
}
void CppParser::handleCatchBlock() void CppParser::handleCatchBlock()
{ {
int startLine= mTokenizer[mIndex]->line; int startLine= mTokenizer[mIndex]->line;
@ -2211,7 +2574,7 @@ void CppParser::handleUsing()
scopeStatement->usingList.insert(fullName); scopeStatement->usingList.insert(fullName);
} }
} else { } else {
PFileIncludes fileInfo = findFileIncludes(mCurrentFile); PFileIncludes fileInfo = mIncludesList->value(mCurrentFile);
if (!fileInfo) if (!fileInfo)
return; return;
if (mNamespaces.contains(usingName)) { if (mNamespaces.contains(usingName)) {
@ -2444,8 +2807,8 @@ void CppParser::internalParse(const QString &fileName)
void CppParser::inheritClassStatement(PStatement derived, bool isStruct, PStatement base, StatementClassScope access) void CppParser::inheritClassStatement(PStatement derived, bool isStruct, PStatement base, StatementClassScope access)
{ {
PFileIncludes fileIncludes1=findFileIncludes(derived->fileName); PFileIncludes fileIncludes1=mIncludesList->value(derived->fileName);
PFileIncludes fileIncludes2=findFileIncludes(base->fileName); PFileIncludes fileIncludes2=mIncludesList->value(base->fileName);
if (fileIncludes1 && fileIncludes2) { if (fileIncludes1 && fileIncludes2) {
//derived class depeneds on base class //derived class depeneds on base class
fileIncludes1->dependingFiles.insert(base->fileName); fileIncludes1->dependingFiles.insert(base->fileName);
@ -2542,6 +2905,49 @@ PStatement CppParser::findStatementInScope(const QString &name, const QString &n
return PStatement(); return PStatement();
} }
PStatement CppParser::findStatementInScope(const QString &name, PStatement scope)
{
if (!scope)
return findMemberOfStatement(name,scope);
if (scope->kind == StatementKind::skNamespace) {
return findStatementInNamespace(name, scope->fullName);
} else {
return findMemberOfStatement(name,scope);
}
}
PStatement CppParser::findStatementInNamespace(const QString &name, const QString &namespaceName)
{
PStatementList namespaceStatementsList=findNamespace(namespaceName);
if (!namespaceStatementsList)
return PStatement();
for (PStatement namespaceStatement:*namespaceStatementsList) {
PStatement result = findMemberOfStatement(name,namespaceStatement);
if (result)
return result;
}
return PStatement();
}
int CppParser::getBracketEnd(const QString &s, int startAt)
{
int i = startAt;
int level = 0; // assume we start on top of [
while (i < s.length()) {
switch(s[i].unicode()) {
case '<':
level++;
break;
case '>':
level--;
if (level == 0)
return i;
}
i++;
}
return startAt;
}
PStatement CppParser::doFindStatementInScope(const QString &name, const QString &noNameArgs, StatementKind kind, PStatement scope) PStatement CppParser::doFindStatementInScope(const QString &name, const QString &noNameArgs, StatementKind kind, PStatement scope)
{ {
const StatementMap& statementMap =mStatementList.childrenStatements(scope); const StatementMap& statementMap =mStatementList.childrenStatements(scope);
@ -2609,25 +3015,23 @@ void CppParser::internalInvalidateFile(const QString &fileName)
} }
} }
void CppParser::internalInvalidateFiles(const QStringList &files) void CppParser::internalInvalidateFiles(const QSet<QString> &files)
{ {
for (QString file:files) for (QString file:files)
internalInvalidateFile(file); internalInvalidateFile(file);
} }
void CppParser::calculateFilesToBeReparsed(const QString &fileName, QStringList &files) QSet<QString> CppParser::calculateFilesToBeReparsed(const QString &fileName)
{ {
if (fileName.isEmpty()) if (fileName.isEmpty())
return; return QSet<QString>();
files.clear();
QQueue<QString> queue; QQueue<QString> queue;
QSet<QString> processed; QSet<QString> processed;
queue.enqueue(fileName); queue.enqueue(fileName);
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
QString name = queue.dequeue(); QString name = queue.dequeue();
files.append(name);
processed.insert(name); processed.insert(name);
PFileIncludes p=findFileIncludes(name); PFileIncludes p=mIncludesList->value(name);
if (!p) if (!p)
continue; continue;
for (QString s:p->dependedFiles) { for (QString s:p->dependedFiles) {
@ -2636,6 +3040,7 @@ void CppParser::calculateFilesToBeReparsed(const QString &fileName, QStringList
} }
} }
} }
return processed;
} }
int CppParser::calcKeyLenForStruct(const QString &word) int CppParser::calcKeyLenForStruct(const QString &word)
@ -3006,6 +3411,11 @@ void CppParser::updateSerialId()
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount); mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
} }
void CppParser::setOnGetFileStream(const GetFileStreamCallBack &newOnGetFileStream)
{
mOnGetFileStream = newOnGetFileStream;
}
const QSet<QString> &CppParser::filesToScan() const const QSet<QString> &CppParser::filesToScan() const
{ {
return mFilesToScan; return mFilesToScan;

View File

@ -48,20 +48,34 @@ public:
const QString& phrase, const QString& phrase,
PStatement currentClass, PStatement currentClass,
bool force = false); bool force = false);
//{Find statement starting from startScope}
PStatement findStatementStartingFrom(const QString& fileName,
const QString& phrase,
PStatement startScope,
bool force = false);
PStatement findTypeDefinitionOf(const QString& fileName,
const QString& aType,
PStatement currentClass);
bool freeze(); // Freeze/Lock (stop reparse while searching)
bool freeze(const QString& serialId); // Freeze/Lock (stop reparse while searching)
QStringList getClassesList();
QSet<QString> getFileDirectIncludes(const QString& filename);
QSet<QString> getFileIncludes(const QString& filename);
QSet<QString> getFileUsings(const QString& filename);
QString getHeaderFileName(const QString& relativeTo, const QString& line);// both
StatementKind getKindOfStatement(PStatement statement); StatementKind getKindOfStatement(PStatement statement);
void invalidateFile(const QString& fileName);
bool isProjectHeaderFile(const QString& fileName);
bool isSystemHeaderFile(const QString& fileName);
void parseFile(const QString& fileName, bool inProject,
bool onlyIfNotParsed = false, bool updateView = true);
void parseFileList(bool updateView = true);
bool parsing();
void parseHardDefines(); void parseHardDefines();
void invalidateFile(const QString& fileName);
QStringList getFileDirectIncludes(const QString& filename) const;
const QList<QString>& getFileIncludes(const QString& filename) const;
const QSet<QString>& getFileUsings(const QString& filename) &;
bool isSystemHeaderFile(const QString& fileName);
bool isProjectHeaderFile(const QString& fileName);
void getSourcePair(const QString& fName, QString& CFile, QString& HFile); void getSourcePair(const QString& fName, QString& CFile, QString& HFile);
void getClassesList(QStringList& list);
int suggestMemberInsertionLine(PStatement parentStatement, int suggestMemberInsertionLine(PStatement parentStatement,
StatementClassScope Scope, StatementClassScope Scope,
bool addScopeStr); bool addScopeStr);
@ -70,11 +84,8 @@ public:
// function GetProjectHeaderFileName(const FileName: AnsiString): AnsiString; // <file.h> // function GetProjectHeaderFileName(const FileName: AnsiString): AnsiString; // <file.h>
// function GetLocalHeaderFileName(const RelativeTo, FileName: AnsiString): AnsiString; // "file.h" // function GetLocalHeaderFileName(const RelativeTo, FileName: AnsiString): AnsiString; // "file.h"
// } // }
QString getHeaderFileName(const QString& relativeTo, const QString& line) const;// both
bool isIncludeLine(const QString &line); bool isIncludeLine(const QString &line);
void parseFileList(bool updateView = true); void parseFileList(bool updateView = true);
void parseFile(const QString& fileName, bool inProject,
bool onlyIfNotParsed = false, bool updateView = true);
QString statementKindStr(StatementKind value); QString statementKindStr(StatementKind value);
QString statementClassScopeStr(StatementClassScope value); QString statementClassScopeStr(StatementClassScope value);
void reset(); void reset();
@ -83,22 +94,14 @@ public:
StatementKind findKindOfStatementOf(const QString& fileName, // StatementKind findKindOfStatementOf(const QString& fileName,
const QString& phrase, // const QString& phrase,
int line); // int line);
QString getHintFromStatement(const QString& fileName, QString getHintFromStatement(const QString& fileName,
const QString& phrase, const QString& phrase,
int line); int line);
//{Find statement starting from startScope}
PStatement findStatementStartingFrom(const QString& fileName,
const QString& phrase,
PStatement startScope,
bool force = false);
PStatement findTypeDefinitionOf(const QString& fileName,
const QString& phrase,
PStatement currentClass);
bool freeze(); // Freeze/Lock (stop reparse while searching)
bool freeze(const QString& serialId); // Freeze/Lock (stop reparse while searching)
void unFreeze(); // UnFree/UnLock (reparse while searching) void unFreeze(); // UnFree/UnLock (reparse while searching)
bool getParsing(); bool getParsing();
@ -109,6 +112,8 @@ public:
const QSet<QString> &filesToScan() const; const QSet<QString> &filesToScan() const;
void setFilesToScan(const QSet<QString> &newFilesToScan); void setFilesToScan(const QSet<QString> &newFilesToScan);
void setOnGetFileStream(const GetFileStreamCallBack &newOnGetFileStream);
signals: signals:
void onProgress(const QString& fileName, int total, int current); void onProgress(const QString& fileName, int total, int current);
void onBusy(); void onBusy();
@ -182,6 +187,13 @@ private:
const QString& noNameArgs, const QString& noNameArgs,
StatementKind kind, StatementKind kind,
PStatement scope); PStatement scope);
PStatement findStatementInScope(
const QString& name,
PStatement scope);
PStatement findStatementInNamespace(
const QString& name,
const QString& namespaceName);
int getBracketEnd(const QString& s, int startAt);
StatementClassScope getClassScope(int index); StatementClassScope getClassScope(int index);
int getCurrentBlockBeginSkip(); int getCurrentBlockBeginSkip();
int getCurrentBlockEndSkip(); int getCurrentBlockEndSkip();
@ -190,6 +202,7 @@ private:
QString getFirstTemplateParam(PStatement statement, const QString& filename, QString getFirstTemplateParam(PStatement statement, const QString& filename,
const QString& phrase, PStatement currentScope); const QString& phrase, PStatement currentScope);
int getFirstTemplateParamEnd(const QString& s, int startAt); int getFirstTemplateParamEnd(const QString& s, int startAt);
void getFullNamespace( void getFullNamespace(
const QString& phrase, const QString& phrase,
QString& sNamespace, QString& sNamespace,
@ -204,6 +217,7 @@ private:
QString getStatementKey(const QString& sName, QString getStatementKey(const QString& sName,
const QString& sType, const QString& sType,
const QString& sNoNameArgs); const QString& sNoNameArgs);
PStatement getTypeDef(PStatement statement, const QString& fileName, const QString& aType);
void handleCatchBlock(); void handleCatchBlock();
void handleEnum(); void handleEnum();
void handleForBlock(); void handleForBlock();
@ -234,9 +248,8 @@ private:
StatementKind kind, StatementKind kind,
PStatement scope); PStatement scope);
void internalInvalidateFile(const QString& fileName); void internalInvalidateFile(const QString& fileName);
void internalInvalidateFiles(const QStringList& files); void internalInvalidateFiles(const QSet<QString>& files);
void calculateFilesToBeReparsed(const QString& fileName, QSet<QString> calculateFilesToBeReparsed(const QString& fileName);
QStringList& files);
int calcKeyLenForStruct(const QString& word); int calcKeyLenForStruct(const QString& word);
// { // {
// function GetClass(const Phrase: AnsiString): AnsiString; // function GetClass(const Phrase: AnsiString): AnsiString;
@ -315,7 +328,7 @@ private:
StatementModel mStatementList; StatementModel mStatementList;
std::shared_ptr<QHash<QString,PFileIncludes>> mIncludesList; //List of scaned files and it's infos std::shared_ptr<QHash<QString,PFileIncludes>> mIncludesList; //List of scaned files and it's infos
//It's used in preprocessor, so we can't use fIncludeList instead //It's used in preprocessor, so we can't use fIncludeList instead
std::shared_ptr<QSet<QString>> mScannedFiles; // List of scaned file names
CppTokenizer mTokenizer; CppTokenizer mTokenizer;
CppPreprocessor mPreprocessor; CppPreprocessor mPreprocessor;
//{ List of current project's file } //{ List of current project's file }

View File

@ -330,7 +330,7 @@ void CppPreprocessor::handleInclude(const QString &line)
PParsedFile file = mIncludes.back(); PParsedFile file = mIncludes.back();
// Get full header file name // Get full header file name
QString fileName = getHeaderFileName(file->fileName, line,mIncludePaths, QString fileName = getHeaderFilename(file->fileName, line,mIncludePaths,
mProjectIncludePaths); mProjectIncludePaths);
if (fileName.isEmpty()) if (fileName.isEmpty())

View File

@ -256,7 +256,7 @@ void initParser()
JavadocTags.append("@version"); JavadocTags.append("@version");
} }
QString getHeaderFileName(const QString &relativeTo, const QString &line, QString getHeaderFilename(const QString &relativeTo, const QString &line,
const QSet<QString>& includePaths, const QSet<QString>& projectIncludePaths) { const QSet<QString>& includePaths, const QSet<QString>& projectIncludePaths) {
QString result = ""; QString result = "";
@ -267,9 +267,9 @@ QString getHeaderFileName(const QString &relativeTo, const QString &line,
if (closeTokenPos >=0) { if (closeTokenPos >=0) {
QString fileName = line.mid(openTokenPos + 1, closeTokenPos - openTokenPos - 1); QString fileName = line.mid(openTokenPos + 1, closeTokenPos - openTokenPos - 1);
//project settings is preferred //project settings is preferred
result = getSystemHeaderFileName(fileName, projectIncludePaths); result = getSystemHeaderFilename(fileName, projectIncludePaths);
if (result.isEmpty()) { if (result.isEmpty()) {
result = getSystemHeaderFileName(fileName, includePaths); result = getSystemHeaderFilename(fileName, includePaths);
} }
} }
} else { } else {
@ -279,13 +279,13 @@ QString getHeaderFileName(const QString &relativeTo, const QString &line,
int closeTokenPos = line.indexOf('"', openTokenPos+1); int closeTokenPos = line.indexOf('"', openTokenPos+1);
if (closeTokenPos >= 0) { if (closeTokenPos >= 0) {
QString fileName = line.mid(openTokenPos + 1, closeTokenPos - openTokenPos - 1); QString fileName = line.mid(openTokenPos + 1, closeTokenPos - openTokenPos - 1);
result = getLocalHeaderFileName(relativeTo, fileName); result = getLocalHeaderFilename(relativeTo, fileName);
//project settings is preferred //project settings is preferred
if (result.isEmpty()) { if (result.isEmpty()) {
result = getSystemHeaderFileName(fileName, projectIncludePaths); result = getSystemHeaderFilename(fileName, projectIncludePaths);
} }
if (result.isEmpty()) { if (result.isEmpty()) {
result = getSystemHeaderFileName(fileName, includePaths); result = getSystemHeaderFilename(fileName, includePaths);
} }
} }
} }
@ -293,7 +293,7 @@ QString getHeaderFileName(const QString &relativeTo, const QString &line,
return result; return result;
} }
QString getLocalHeaderFileName(const QString &relativeTo, const QString &fileName) QString getLocalHeaderFilename(const QString &relativeTo, const QString &fileName)
{ {
QFileInfo relativeFile(relativeTo); QFileInfo relativeFile(relativeTo);
QDir dir = relativeFile.dir(); QDir dir = relativeFile.dir();
@ -304,7 +304,7 @@ QString getLocalHeaderFileName(const QString &relativeTo, const QString &fileNam
return ""; return "";
} }
QString getSystemHeaderFileName(const QString &fileName, const QSet<QString>& includePaths) QString getSystemHeaderFilename(const QString &fileName, const QSet<QString>& includePaths)
{ {
// Search compiler include directories // Search compiler include directories

View File

@ -180,12 +180,12 @@ extern QSet<QString> STLElementMethods;
void initParser(); void initParser();
QString getHeaderFileName(const QString& relativeTo, const QString& line, QString getHeaderFilename(const QString& relativeTo, const QString& line,
const QSet<QString>& includePaths, const QSet<QString>& projectIncludePaths); const QSet<QString>& includePaths, const QSet<QString>& projectIncludePaths);
QString getLocalHeaderFileName(const QString& relativeTo, const QString& fileName); QString getLocalHeaderFilename(const QString& relativeTo, const QString& fileName);
QString getSystemHeaderFileName(const QString& fileName, const QSet<QString>& includePaths); QString getSystemHeaderFilename(const QString& fileName, const QSet<QString>& includePaths);
bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePaths); bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePaths);
bool isHfile(const QString filename); bool isHfile(const QString filename);
bool isCfile(const QString filename); bool isCfile(const QString filename);