diff --git a/languages/clang/codecompletion/completionhelper.h b/languages/clang/codecompletion/completionhelper.h --- a/languages/clang/codecompletion/completionhelper.h +++ b/languages/clang/codecompletion/completionhelper.h @@ -28,13 +28,24 @@ #include +struct FuncParameterInfo +{ + QString type; + QString id; + /// Returns true if types are equal, id is ignored + bool operator==(const FuncParameterInfo& rhs) const { return type == rhs.type; } +}; +Q_DECLARE_TYPEINFO(FuncParameterInfo, Q_MOVABLE_TYPE); +using FuncParameterList = QVector; + struct FuncOverrideInfo { QString returnType; QString name; - QStringList params; - bool isVirtual; + FuncParameterList params; + bool isPureVirtual; bool isConst; + /// Returns true if equal, isPureVirtual & parameter ids are ignored bool operator==(const FuncOverrideInfo& rhs) const; }; diff --git a/languages/clang/codecompletion/completionhelper.cpp b/languages/clang/codecompletion/completionhelper.cpp --- a/languages/clang/codecompletion/completionhelper.cpp +++ b/languages/clang/codecompletion/completionhelper.cpp @@ -74,7 +74,7 @@ FuncOverrideInfo processCXXMethod(CXCursor cursor, OverrideInfo* info) { - QStringList params; + FuncParameterList params; int numArgs = clang_Cursor_getNumArguments(cursor); for (int i = 0; i < numArgs; i++) { @@ -84,7 +84,10 @@ if (info->templateTypeMap.contains(type)) { type = info->templateTypeMap.value(type); } - params << type + QLatin1Char(' ') + id; + FuncParameterInfo param; + param.type = type; + param.id = id; + params << param; } FuncOverrideInfo fp; @@ -96,7 +99,7 @@ fp.returnType = retType; fp.name = ClangString(clang_getCursorSpelling(cursor)).toString(); fp.params = params; - fp.isVirtual = clang_CXXMethod_isPureVirtual(cursor); + fp.isPureVirtual = clang_CXXMethod_isPureVirtual(cursor); fp.isConst = clang_CXXMethod_isConst(cursor); return fp; @@ -142,7 +145,15 @@ return CXChildVisit_Continue; case CXCursor_CXXMethod: if (clang_CXXMethod_isVirtual(cursor)) { - info->functions->append(processCXXMethod(cursor, info)); + auto methodInfo = processCXXMethod(cursor, info); + const int methodIndex = info->functions->indexOf(methodInfo); + if (methodIndex == -1) { + info->functions->append(methodInfo); + } else { + // update to subclass override + auto& listedMethodInfo = (*info->functions)[methodIndex]; + listedMethodInfo.isPureVirtual = methodInfo.isPureVirtual; + } } return CXChildVisit_Continue; default: @@ -164,10 +175,9 @@ OverrideInfo overrideInfo {info, {}, {}}; auto methodInfo = processCXXMethod(cursor, &overrideInfo); - if (info->contains(methodInfo)) { - // This method is already implemented, remove it from the list of methods that can be overridden. - info->remove(info->indexOf(methodInfo), 1); - } + // If this method is already implemented, remove it from the list of methods that can be overridden. + // If not implemented, this is a noop + info->removeOne(methodInfo); } return CXChildVisit_Continue; diff --git a/languages/clang/codecompletion/context.cpp b/languages/clang/codecompletion/context.cpp --- a/languages/clang/codecompletion/context.cpp +++ b/languages/clang/codecompletion/context.cpp @@ -1173,16 +1173,19 @@ QList overrides; QList overridesAbstract; - for (int i = 0; i < overrideList.count(); i++) { - FuncOverrideInfo info = overrideList.at(i); - QString nameAndParams = info.name + QLatin1Char('(') + info.params.join(QStringLiteral(", ")) + QLatin1Char(')'); + for (const auto& info : overrideList) { + QStringList params; + for (const auto& param : info.params) { + params << param.type + QLatin1Char(' ') + param.id; + } + QString nameAndParams = info.name + QLatin1Char('(') + params.join(QStringLiteral(", ")) + QLatin1Char(')'); if(info.isConst) nameAndParams = nameAndParams + QLatin1String(" const"); - if(info.isVirtual) + if(info.isPureVirtual) nameAndParams = nameAndParams + QLatin1String(" = 0"); auto item = CompletionTreeItemPointer(new OverrideItem(nameAndParams, info.returnType)); - if (info.isVirtual) + if (info.isPureVirtual) overridesAbstract << item; else overrides << item;