forked from qt-creator/qt-creator
C++: Add basic 'insert #include' quick fix.
Change-Id: I3a2fef56d6d1871ea4bbb139f9bdd2bc44dd0123 Reviewed-by: Leandro Melo <leandro.melo@nokia.com>
This commit is contained in:
@@ -58,10 +58,10 @@ QT_END_NAMESPACE
|
|||||||
namespace CPlusPlus {
|
namespace CPlusPlus {
|
||||||
class OverviewModel;
|
class OverviewModel;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
|
class CppModelManagerInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
class CppModelManagerInterface;
|
|
||||||
class CppCodeStyleSettings;
|
class CppCodeStyleSettings;
|
||||||
class CppRefactoringFile;
|
class CppRefactoringFile;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,11 @@
|
|||||||
#include "cppeditor_global.h"
|
#include "cppeditor_global.h"
|
||||||
#include <texteditor/quickfix.h>
|
#include <texteditor/quickfix.h>
|
||||||
|
|
||||||
|
namespace CPlusPlus {
|
||||||
|
class CppModelManagerInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
class CppModelManagerInterface;
|
|
||||||
class CppRefactoringFile;
|
class CppRefactoringFile;
|
||||||
class CppRefactoringChanges;
|
class CppRefactoringChanges;
|
||||||
typedef QSharedPointer<CppRefactoringFile> CppRefactoringFilePtr;
|
typedef QSharedPointer<CppRefactoringFile> CppRefactoringFilePtr;
|
||||||
|
|||||||
@@ -56,12 +56,16 @@
|
|||||||
#include <cplusplus/DependencyTable.h>
|
#include <cplusplus/DependencyTable.h>
|
||||||
#include <cplusplus/Overview.h>
|
#include <cplusplus/Overview.h>
|
||||||
#include <cplusplus/TypeOfExpression.h>
|
#include <cplusplus/TypeOfExpression.h>
|
||||||
|
#include <cplusplus/ModelManagerInterface.h>
|
||||||
#include <cplusplus/CppRewriter.h>
|
#include <cplusplus/CppRewriter.h>
|
||||||
#include <cpptools/cpptoolsconstants.h>
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
#include <cpptools/cpprefactoringchanges.h>
|
#include <cpptools/cpprefactoringchanges.h>
|
||||||
#include <cpptools/insertionpointlocator.h>
|
#include <cpptools/insertionpointlocator.h>
|
||||||
#include <cpptools/cpptoolsreuse.h>
|
#include <cpptools/cpptoolsreuse.h>
|
||||||
|
#include <cpptools/cppclassesfilter.h>
|
||||||
|
#include <cpptools/searchsymbols.h>
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
#include <QtGui/QApplication>
|
#include <QtGui/QApplication>
|
||||||
@@ -1701,6 +1705,157 @@ private:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an include for an undefined identifier.
|
||||||
|
*/
|
||||||
|
class IncludeAdder : public CppQuickFixFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual QList<CppQuickFixOperation::Ptr> match(const QSharedPointer<const CppQuickFixAssistInterface> &interface)
|
||||||
|
{
|
||||||
|
CppClassesFilter *classesFilter = ExtensionSystem::PluginManager::instance()->getObject<CppClassesFilter>();
|
||||||
|
if (!classesFilter)
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
const QList<AST *> &path = interface->path();
|
||||||
|
|
||||||
|
if (path.isEmpty())
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
// find the largest enclosing Name
|
||||||
|
const NameAST *enclosingName = 0;
|
||||||
|
const SimpleNameAST *innermostName = 0;
|
||||||
|
for (int i = path.size() - 1; i >= 0; --i) {
|
||||||
|
if (NameAST *nameAst = path.at(i)->asName()) {
|
||||||
|
enclosingName = nameAst;
|
||||||
|
if (!innermostName) {
|
||||||
|
innermostName = nameAst->asSimpleName();
|
||||||
|
if (!innermostName)
|
||||||
|
return noResult();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!enclosingName || !enclosingName->name)
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
// find the enclosing scope
|
||||||
|
unsigned line, column;
|
||||||
|
const Document::Ptr &doc = interface->semanticInfo().doc;
|
||||||
|
doc->translationUnit()->getTokenStartPosition(enclosingName->firstToken(), &line, &column);
|
||||||
|
Scope *scope = doc->scopeAt(line, column);
|
||||||
|
if (!scope)
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
// check if the name resolves to something
|
||||||
|
QList<LookupItem> existingResults = interface->context().lookup(enclosingName->name, scope);
|
||||||
|
if (!existingResults.isEmpty())
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
const QString &className = Overview()(innermostName->name);
|
||||||
|
if (className.isEmpty())
|
||||||
|
return noResult();
|
||||||
|
|
||||||
|
QList<CppQuickFixOperation::Ptr> results;
|
||||||
|
|
||||||
|
// find the include paths
|
||||||
|
QStringList includePaths;
|
||||||
|
CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
|
||||||
|
QList<CppModelManagerInterface::ProjectInfo> projectInfos = modelManager->projectInfos();
|
||||||
|
bool inProject = false;
|
||||||
|
foreach (const CppModelManagerInterface::ProjectInfo &info, projectInfos) {
|
||||||
|
if (info.sourceFiles.contains(doc->fileName())) {
|
||||||
|
inProject = true;
|
||||||
|
includePaths += info.includePaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inProject) {
|
||||||
|
// better use all include paths than none
|
||||||
|
foreach (const CppModelManagerInterface::ProjectInfo &info, projectInfos)
|
||||||
|
includePaths += info.includePaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a include file through the locator
|
||||||
|
QFutureInterface<Locator::FilterEntry> dummyInterface;
|
||||||
|
QList<Locator::FilterEntry> matches = classesFilter->matchesFor(dummyInterface, className);
|
||||||
|
bool classExists = false;
|
||||||
|
foreach (const Locator::FilterEntry &entry, matches) {
|
||||||
|
const ModelItemInfo info = entry.internalData.value<ModelItemInfo>();
|
||||||
|
if (info.symbolName != className)
|
||||||
|
continue;
|
||||||
|
classExists = true;
|
||||||
|
const QString &fileName = info.fileName;
|
||||||
|
const QFileInfo fileInfo(fileName);
|
||||||
|
|
||||||
|
// find the shortest way to include fileName given the includePaths
|
||||||
|
QString shortestInclude;
|
||||||
|
|
||||||
|
if (fileInfo.path() == QFileInfo(doc->fileName()).path()) {
|
||||||
|
shortestInclude = QString("\"%1\"").arg(fileInfo.fileName());
|
||||||
|
} else {
|
||||||
|
foreach (const QString &includePath, includePaths) {
|
||||||
|
if (!fileName.startsWith(includePath))
|
||||||
|
continue;
|
||||||
|
QString relativePath = fileName.mid(includePath.size());
|
||||||
|
if (!relativePath.isEmpty() && relativePath.at(0) == QLatin1Char('/'))
|
||||||
|
relativePath = relativePath.mid(1);
|
||||||
|
if (shortestInclude.isEmpty() || relativePath.size() + 2 < shortestInclude.size())
|
||||||
|
shortestInclude = QString("<%1>").arg(relativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shortestInclude.isEmpty())
|
||||||
|
results += CppQuickFixOperation::Ptr(new Operation(interface, 0, shortestInclude));
|
||||||
|
}
|
||||||
|
|
||||||
|
// for QSomething, propose a <QSomething> include -- if such a class was in the locator
|
||||||
|
if (classExists
|
||||||
|
&& className.size() > 2
|
||||||
|
&& className.at(0) == QLatin1Char('Q')
|
||||||
|
&& className.at(1).isUpper()) {
|
||||||
|
results += CppQuickFixOperation::Ptr(new Operation(interface, 1, QString("<%1>").arg(className)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Operation: public CppQuickFixOperation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Operation(const QSharedPointer<const CppQuickFixAssistInterface> &interface, int priority, const QString &include)
|
||||||
|
: CppQuickFixOperation(interface, priority)
|
||||||
|
, m_include(include)
|
||||||
|
{
|
||||||
|
setDescription(QApplication::translate("CppTools::QuickFix",
|
||||||
|
"Add #include %1").arg(m_include));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void performChanges(const CppRefactoringFilePtr &file,
|
||||||
|
const CppRefactoringChanges &)
|
||||||
|
{
|
||||||
|
// find location of last include in file
|
||||||
|
QList<Document::Include> includes = file->cppDocument()->includes();
|
||||||
|
unsigned lastIncludeLine = 0;
|
||||||
|
foreach (const Document::Include &include, includes) {
|
||||||
|
if (include.line() > lastIncludeLine)
|
||||||
|
lastIncludeLine = include.line();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add include
|
||||||
|
const int insertPos = file->position(lastIncludeLine + 1, 1) - 1;
|
||||||
|
ChangeSet changes;
|
||||||
|
changes.insert(insertPos, QString("\n#include %1").arg(m_include));
|
||||||
|
file->setChangeSet(changes);
|
||||||
|
file->apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_include;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
||||||
@@ -1725,4 +1880,5 @@ void registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
|
|||||||
plugIn->addAutoReleasedObject(new DeclFromDef);
|
plugIn->addAutoReleasedObject(new DeclFromDef);
|
||||||
plugIn->addAutoReleasedObject(new DefFromDecl);
|
plugIn->addAutoReleasedObject(new DefFromDecl);
|
||||||
plugIn->addAutoReleasedObject(new ApplyDeclDefLinkChanges);
|
plugIn->addAutoReleasedObject(new ApplyDeclDefLinkChanges);
|
||||||
|
plugIn->addAutoReleasedObject(new IncludeAdder);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "cppclassesfilter.h"
|
#include "cppclassesfilter.h"
|
||||||
|
|
||||||
|
using namespace CppTools;
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools::Internal;
|
||||||
|
|
||||||
CppClassesFilter::CppClassesFilter(CppModelManager *manager)
|
CppClassesFilter::CppClassesFilter(CppModelManager *manager)
|
||||||
|
|||||||
@@ -33,17 +33,17 @@
|
|||||||
#ifndef CPPCLASSESFILTER_H
|
#ifndef CPPCLASSESFILTER_H
|
||||||
#define CPPCLASSESFILTER_H
|
#define CPPCLASSESFILTER_H
|
||||||
|
|
||||||
#include <cpplocatorfilter.h>
|
#include "cpptools_global.h"
|
||||||
|
#include "cpplocatorfilter.h"
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class CppClassesFilter : public CppLocatorFilter
|
class CPPTOOLS_EXPORT CppClassesFilter : public Internal::CppLocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CppClassesFilter(CppModelManager *manager);
|
CppClassesFilter(Internal::CppModelManager *manager);
|
||||||
~CppClassesFilter();
|
~CppClassesFilter();
|
||||||
|
|
||||||
QString displayName() const { return tr("Classes"); }
|
QString displayName() const { return tr("Classes"); }
|
||||||
@@ -51,7 +51,6 @@ public:
|
|||||||
Priority priority() const { return Medium; }
|
Priority priority() const { return Medium; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|
||||||
#endif // CPPCLASSESFILTER_H
|
#endif // CPPCLASSESFILTER_H
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterfac
|
|||||||
|
|
||||||
void CppCurrentDocumentFilter::accept(Locator::FilterEntry selection) const
|
void CppCurrentDocumentFilter::accept(Locator::FilterEntry selection) const
|
||||||
{
|
{
|
||||||
ModelItemInfo info = qvariant_cast<CppTools::Internal::ModelItemInfo>(selection.internalData);
|
ModelItemInfo info = qvariant_cast<CppTools::ModelItemInfo>(selection.internalData);
|
||||||
TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column,
|
TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column,
|
||||||
Core::Id(), Core::EditorManager::ModeSwitch);
|
Core::Id(), Core::EditorManager::ModeSwitch);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(QFutureInterface<Locato
|
|||||||
|
|
||||||
void CppLocatorFilter::accept(Locator::FilterEntry selection) const
|
void CppLocatorFilter::accept(Locator::FilterEntry selection) const
|
||||||
{
|
{
|
||||||
ModelItemInfo info = qvariant_cast<CppTools::Internal::ModelItemInfo>(selection.internalData);
|
ModelItemInfo info = qvariant_cast<CppTools::ModelItemInfo>(selection.internalData);
|
||||||
TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column,
|
TextEditor::BaseTextEditorWidget::openEditorAt(info.fileName, info.line, info.column,
|
||||||
Core::Id(), Core::EditorManager::ModeSwitch);
|
Core::Id(), Core::EditorManager::ModeSwitch);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
using namespace CppTools::Internal;
|
using namespace CppTools;
|
||||||
|
|
||||||
SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
|
SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
|
||||||
SearchSymbols::Classes
|
SearchSymbols::Classes
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#ifndef SEARCHSYMBOLS_H
|
#ifndef SEARCHSYMBOLS_H
|
||||||
#define SEARCHSYMBOLS_H
|
#define SEARCHSYMBOLS_H
|
||||||
|
|
||||||
|
#include "cpptools_global.h"
|
||||||
|
|
||||||
#include <cplusplus/CppDocument.h>
|
#include <cplusplus/CppDocument.h>
|
||||||
#include <cplusplus/Icons.h>
|
#include <cplusplus/Icons.h>
|
||||||
#include <cplusplus/Overview.h>
|
#include <cplusplus/Overview.h>
|
||||||
@@ -48,9 +50,8 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
struct ModelItemInfo
|
struct CPPTOOLS_EXPORT ModelItemInfo
|
||||||
{
|
{
|
||||||
enum ItemType { Enum, Class, Method, Declaration };
|
enum ItemType { Enum, Class, Method, Declaration };
|
||||||
|
|
||||||
@@ -180,10 +181,9 @@ private:
|
|||||||
bool separateScope;
|
bool separateScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(CppTools::Internal::SearchSymbols::SymbolTypes)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(CppTools::SearchSymbols::SymbolTypes)
|
||||||
Q_DECLARE_METATYPE(CppTools::Internal::ModelItemInfo)
|
Q_DECLARE_METATYPE(CppTools::ModelItemInfo)
|
||||||
|
|
||||||
#endif // SEARCHSYMBOLS_H
|
#endif // SEARCHSYMBOLS_H
|
||||||
|
|||||||
Reference in New Issue
Block a user