forked from qt-creator/qt-creator
"New Class" wizard: Try to find a base class header
If the project has a header file whose name suggests that it might declare the base class, then add an include statement for it. While we cannot guarantee that the include statement is resolvable as- is, it's at least a basis for the user to adapt accordingly, while without any include statement the class will definitely not compile. Fixes: QTCREATORBUG-3855 Change-Id: I55ec43d58a9a13b9b59a5bbe6415a457b974b654 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#define %{GUARD}
|
#define %{GUARD}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
%{JS: Cpp.includeStatement('%{Base}', Util.preferredSuffix('text/x-c++hdr'), ['QObject', 'QWidget', 'QMainWindow', 'QQuickItem', 'QSharedData'], '%{TargetPath}')}\
|
||||||
%{JS: QtSupport.qtIncludes([ ( '%{IncludeQObject}' ) ? 'QtCore/%{IncludeQObject}' : '',
|
%{JS: QtSupport.qtIncludes([ ( '%{IncludeQObject}' ) ? 'QtCore/%{IncludeQObject}' : '',
|
||||||
( '%{IncludeQWidget}' ) ? 'QtGui/%{IncludeQWidget}' : '',
|
( '%{IncludeQWidget}' ) ? 'QtGui/%{IncludeQWidget}' : '',
|
||||||
( '%{IncludeQMainWindow}' ) ? 'QtGui/%{IncludeQMainWindow}' : '',
|
( '%{IncludeQMainWindow}' ) ? 'QtGui/%{IncludeQMainWindow}' : '',
|
||||||
|
@@ -29,10 +29,15 @@
|
|||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
#include <utils/codegeneration.h>
|
#include <utils/codegeneration.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QStringList>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
@@ -113,5 +118,69 @@ QString CppToolsJsExtension::closeNamespaces(const QString &klass) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CppToolsJsExtension::includeStatement(
|
||||||
|
const QString &fullyQualifiedClassName,
|
||||||
|
const QString &suffix,
|
||||||
|
const QString &specialClasses,
|
||||||
|
const QString &pathOfIncludingFile
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (fullyQualifiedClassName.isEmpty())
|
||||||
|
return {};
|
||||||
|
const QString className = parts(fullyQualifiedClassName).last();
|
||||||
|
if (className.isEmpty() || specialClasses.contains(className))
|
||||||
|
return {};
|
||||||
|
if (className.startsWith('Q') && className.length() > 2 && className.at(1).isUpper())
|
||||||
|
return "#include <" + className + ">\n";
|
||||||
|
const auto withUnderScores = [&className] {
|
||||||
|
QString baseName = className;
|
||||||
|
baseName[0] = baseName[0].toLower();
|
||||||
|
for (int i = 1; i < baseName.length(); ++i) {
|
||||||
|
if (baseName[i].isUpper()) {
|
||||||
|
baseName.insert(i, '_');
|
||||||
|
baseName[i + 1] = baseName[i + 1].toLower();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return baseName;
|
||||||
|
};
|
||||||
|
QStringList candidates{className + '.' + suffix};
|
||||||
|
bool hasUpperCase = false;
|
||||||
|
bool hasLowerCase = false;
|
||||||
|
for (int i = 0; i < className.length() && (!hasUpperCase || !hasLowerCase); ++i) {
|
||||||
|
if (className.at(i).isUpper())
|
||||||
|
hasUpperCase = true;
|
||||||
|
if (className.at(i).isLower())
|
||||||
|
hasLowerCase = true;
|
||||||
|
}
|
||||||
|
if (hasUpperCase)
|
||||||
|
candidates << className.toLower() + '.' + suffix;
|
||||||
|
if (hasUpperCase && hasLowerCase)
|
||||||
|
candidates << withUnderScores() + '.' + suffix;
|
||||||
|
candidates.removeDuplicates();
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
const auto nodeMatchesFileName = [&candidates](Node *n) {
|
||||||
|
if (const FileNode * const fileNode = n->asFileNode()) {
|
||||||
|
if (fileNode->fileType() == FileType::Header
|
||||||
|
&& candidates.contains(fileNode->filePath().fileName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
for (const Project * const p : SessionManager::projects()) {
|
||||||
|
const Node *theNode = p->rootProjectNode()->findNode(nodeMatchesFileName);
|
||||||
|
if (theNode) {
|
||||||
|
const bool sameDir = pathOfIncludingFile == theNode->filePath().toFileInfo().path();
|
||||||
|
return QString("#include ")
|
||||||
|
.append(sameDir ? '"' : '<')
|
||||||
|
.append(theNode->filePath().fileName())
|
||||||
|
.append(sameDir ? '"' : '>')
|
||||||
|
.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -55,6 +55,14 @@ public:
|
|||||||
Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const;
|
Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const;
|
||||||
Q_INVOKABLE QString openNamespaces(const QString &klass) const;
|
Q_INVOKABLE QString openNamespaces(const QString &klass) const;
|
||||||
Q_INVOKABLE QString closeNamespaces(const QString &klass) const;
|
Q_INVOKABLE QString closeNamespaces(const QString &klass) const;
|
||||||
|
|
||||||
|
// Find header file for class.
|
||||||
|
Q_INVOKABLE QString includeStatement(
|
||||||
|
const QString &fullyQualifiedClassName,
|
||||||
|
const QString &suffix,
|
||||||
|
const QString &specialClasses,
|
||||||
|
const QString &pathOfIncludingFile
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user