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}
 | 
			
		||||
@endif
 | 
			
		||||
 | 
			
		||||
%{JS: Cpp.includeStatement('%{Base}', Util.preferredSuffix('text/x-c++hdr'), ['QObject', 'QWidget', 'QMainWindow', 'QQuickItem', 'QSharedData'], '%{TargetPath}')}\
 | 
			
		||||
%{JS: QtSupport.qtIncludes([ ( '%{IncludeQObject}' )          ? 'QtCore/%{IncludeQObject}'                 : '',
 | 
			
		||||
                             ( '%{IncludeQWidget}' )          ? 'QtGui/%{IncludeQWidget}'                  : '',
 | 
			
		||||
                             ( '%{IncludeQMainWindow}' )      ? 'QtGui/%{IncludeQMainWindow}'              : '',
 | 
			
		||||
 
 | 
			
		||||
@@ -29,10 +29,15 @@
 | 
			
		||||
 | 
			
		||||
#include <coreplugin/icore.h>
 | 
			
		||||
 | 
			
		||||
#include <projectexplorer/project.h>
 | 
			
		||||
#include <projectexplorer/projectnodes.h>
 | 
			
		||||
#include <projectexplorer/session.h>
 | 
			
		||||
 | 
			
		||||
#include <utils/codegeneration.h>
 | 
			
		||||
#include <utils/fileutils.h>
 | 
			
		||||
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
@@ -113,5 +118,69 @@ QString CppToolsJsExtension::closeNamespaces(const QString &klass) const
 | 
			
		||||
    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 CppTools
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,14 @@ public:
 | 
			
		||||
    Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const;
 | 
			
		||||
    Q_INVOKABLE QString openNamespaces(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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user