diff options
Diffstat (limited to 'src')
22 files changed, 1153 insertions, 720 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp new file mode 100644 index 0000000000..a4ca8a87b9 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cmakefilecompletionassist.h" +#include "cmakeprojectconstants.h" +#include "cmakeprojectmanager.h" + +#include <texteditor/codeassist/keywordscompletionassist.h> + +using namespace CMakeProjectManager::Internal; +using namespace TextEditor; + +// ------------------------------- +// CMakeFileCompletionAssistProvider +// ------------------------------- +CMakeFileCompletionAssistProvider::CMakeFileCompletionAssistProvider(CMakeSettingsPage *settingsPage) + : m_settingsPage(settingsPage) +{} + +CMakeFileCompletionAssistProvider::~CMakeFileCompletionAssistProvider() +{} + +bool CMakeFileCompletionAssistProvider::supportsEditor(const Core::Id &editorId) const +{ + return editorId == CMakeProjectManager::Constants::CMAKE_EDITOR_ID; +} + +IAssistProcessor *CMakeFileCompletionAssistProvider::createProcessor() const +{ + return new KeywordsCompletionAssistProcessor(m_settingsPage->keywords()); +} diff --git a/src/plugins/qt4projectmanager/profilekeywords.h b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h index 0aed9caebf..75b7c4bf93 100644 --- a/src/plugins/qt4projectmanager/profilekeywords.h +++ b/src/plugins/cmakeprojectmanager/cmakefilecompletionassist.h @@ -27,27 +27,30 @@ ** ****************************************************************************/ -#ifndef PROFILEKEYWORDS_H -#define PROFILEKEYWORDS_H +#ifndef CMAKEFILECOMPLETIONASSIST_H +#define CMAKEFILECOMPLETIONASSIST_H -#include <QStringList> - -namespace Qt4ProjectManager { +#include <texteditor/codeassist/completionassistprovider.h> +namespace CMakeProjectManager { namespace Internal { -class ProFileKeywords +class CMakeSettingsPage; + +class CMakeFileCompletionAssistProvider : public TextEditor::CompletionAssistProvider { public: - static QStringList variables(); - static QStringList functions(); - static bool isVariable(const QString &word); - static bool isFunction(const QString &word); + CMakeFileCompletionAssistProvider(CMakeSettingsPage *settingsPage); + ~CMakeFileCompletionAssistProvider(); + + bool supportsEditor(const Core::Id &editorId) const; + TextEditor::IAssistProcessor *createProcessor() const; + private: - ProFileKeywords(); + CMakeSettingsPage *m_settingsPage; }; -} // namespace Internal -} // namespace Qt4ProjectManager +} // Internal +} // CMakeProjectManager -#endif // PROFILEKEYWORDS_H +#endif // CMAKEFILECOMPLETIONASSIST_H diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index db3e65d1bf..768e65a49a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -250,102 +250,26 @@ CMakeSettingsPage::CMakeSettingsPage() ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY)); setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON)); - m_userCmake.process = 0; - m_pathCmake.process = 0; - m_userCmake.hasCodeBlocksMsvcGenerator = false; - m_pathCmake.hasCodeBlocksMsvcGenerator = false; - m_userCmake.hasCodeBlocksNinjaGenerator = false; - m_pathCmake.hasCodeBlocksNinjaGenerator = false; QSettings *settings = Core::ICore::settings(); settings->beginGroup(QLatin1String("CMakeSettings")); - m_userCmake.executable = settings->value(QLatin1String("cmakeExecutable")).toString(); + m_cmakeValidatorForUser.setCMakeExecutable(settings->value(QLatin1String("cmakeExecutable")).toString()); settings->endGroup(); - updateInfo(&m_userCmake); - m_pathCmake.executable = findCmakeExecutable(); - updateInfo(&m_pathCmake); -} - -void CMakeSettingsPage::startProcess(CMakeValidator *cmakeValidator) -{ - cmakeValidator->process = new QProcess(); - - if (cmakeValidator == &m_pathCmake) // ugly - connect(cmakeValidator->process, SIGNAL(finished(int)), - this, SLOT(userCmakeFinished())); - else - connect(cmakeValidator->process, SIGNAL(finished(int)), - this, SLOT(pathCmakeFinished())); - - cmakeValidator->process->start(cmakeValidator->executable, QStringList(QLatin1String("--help"))); - cmakeValidator->process->waitForStarted(); -} - -void CMakeSettingsPage::userCmakeFinished() -{ - cmakeFinished(&m_userCmake); -} - -void CMakeSettingsPage::pathCmakeFinished() -{ - cmakeFinished(&m_pathCmake); -} - -void CMakeSettingsPage::cmakeFinished(CMakeValidator *cmakeValidator) const -{ - if (cmakeValidator->process) { - cmakeValidator->process->waitForFinished(); - QString response = cmakeValidator->process->readAll(); - QRegExp versionRegexp(QLatin1String("^cmake version ([\\d\\.]*)")); - versionRegexp.indexIn(response); - - //m_supportsQtCreator = response.contains(QLatin1String("QtCreator")); - cmakeValidator->hasCodeBlocksNinjaGenerator = response.contains(QLatin1String("CodeBlocks - Ninja")); - cmakeValidator->hasCodeBlocksMsvcGenerator = response.contains(QLatin1String("CodeBlocks - NMake Makefiles")); - cmakeValidator->version = versionRegexp.cap(1); - if (!(versionRegexp.capturedTexts().size() > 3)) - cmakeValidator->version += QLatin1Char('.') + versionRegexp.cap(3); - - if (cmakeValidator->version.isEmpty()) - cmakeValidator->state = CMakeValidator::INVALID; - else - cmakeValidator->state = CMakeValidator::VALID; - - cmakeValidator->process->deleteLater(); - cmakeValidator->process = 0; - } + m_cmakeValidatorForSystem.setCMakeExecutable(findCmakeExecutable()); } bool CMakeSettingsPage::isCMakeExecutableValid() const { - if (m_userCmake.state == CMakeValidator::RUNNING) { - disconnect(m_userCmake.process, SIGNAL(finished(int)), - this, SLOT(userCmakeFinished())); - m_userCmake.process->waitForFinished(); - // Parse the output now - cmakeFinished(&m_userCmake); - } - - if (m_userCmake.state == CMakeValidator::VALID) + if (m_cmakeValidatorForUser.isValid()) return true; - if (m_pathCmake.state == CMakeValidator::RUNNING) { - disconnect(m_userCmake.process, SIGNAL(finished(int)), - this, SLOT(pathCmakeFinished())); - m_pathCmake.process->waitForFinished(); - // Parse the output now - cmakeFinished(&m_pathCmake); - } - return m_pathCmake.state == CMakeValidator::VALID; + + return m_cmakeValidatorForSystem.isValid(); } CMakeSettingsPage::~CMakeSettingsPage() { - if (m_userCmake.process) - m_userCmake.process->waitForFinished(); - delete m_userCmake.process; - if (m_pathCmake.process) - m_pathCmake.process->waitForFinished(); - delete m_pathCmake.process; + m_cmakeValidatorForUser.cancel(); + m_cmakeValidatorForSystem.cancel(); } QString CMakeSettingsPage::findCmakeExecutable() const @@ -363,28 +287,15 @@ QWidget *CMakeSettingsPage::createPage(QWidget *parent) m_pathchooser->setExpectedKind(Utils::PathChooser::ExistingCommand); formLayout->addRow(tr("Executable:"), m_pathchooser); formLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); - m_pathchooser->setPath(m_userCmake.executable); + m_pathchooser->setPath(m_cmakeValidatorForUser.cmakeExecutable()); return outerWidget; } -void CMakeSettingsPage::updateInfo(CMakeValidator *cmakeValidator) -{ - QFileInfo fi(cmakeValidator->executable); - if (fi.exists() && fi.isExecutable()) { - // Run it to find out more - cmakeValidator->state = CMakeValidator::RUNNING; - startProcess(cmakeValidator); - } else { - cmakeValidator->state = CMakeValidator::INVALID; - } - saveSettings(); -} - void CMakeSettingsPage::saveSettings() const { QSettings *settings = Core::ICore::settings(); settings->beginGroup(QLatin1String("CMakeSettings")); - settings->setValue(QLatin1String("cmakeExecutable"), m_userCmake.executable); + settings->setValue(QLatin1String("cmakeExecutable"), m_cmakeValidatorForUser.cmakeExecutable()); settings->endGroup(); } @@ -392,10 +303,10 @@ void CMakeSettingsPage::apply() { if (!m_pathchooser) // page was never shown return; - if (m_userCmake.executable == m_pathchooser->path()) + if (m_cmakeValidatorForUser.cmakeExecutable() == m_pathchooser->path()) return; - m_userCmake.executable = m_pathchooser->path(); - updateInfo(&m_userCmake); + m_cmakeValidatorForUser.setCMakeExecutable(m_pathchooser->path()); + saveSettings(); } void CMakeSettingsPage::finish() @@ -407,36 +318,46 @@ QString CMakeSettingsPage::cmakeExecutable() const { if (!isCMakeExecutableValid()) return QString(); - if (m_userCmake.state == CMakeValidator::VALID) - return m_userCmake.executable; - else - return m_pathCmake.executable; + + if (m_cmakeValidatorForUser.isValid()) + return m_cmakeValidatorForUser.cmakeExecutable(); + if (m_cmakeValidatorForSystem.isValid()) + return m_cmakeValidatorForSystem.cmakeExecutable(); + return QString(); } void CMakeSettingsPage::setCMakeExecutable(const QString &executable) { - if (m_userCmake.executable == executable) + if (m_cmakeValidatorForUser.cmakeExecutable() == executable) return; - m_userCmake.executable = executable; - updateInfo(&m_userCmake); + m_cmakeValidatorForUser.setCMakeExecutable(executable); } bool CMakeSettingsPage::hasCodeBlocksMsvcGenerator() const { - if (!isCMakeExecutableValid()) - return false; - if (m_userCmake.state == CMakeValidator::VALID) - return m_userCmake.hasCodeBlocksMsvcGenerator; - else - return m_pathCmake.hasCodeBlocksMsvcGenerator; + if (m_cmakeValidatorForUser.isValid()) + return m_cmakeValidatorForUser.hasCodeBlocksMsvcGenerator(); + if (m_cmakeValidatorForSystem.isValid()) + return m_cmakeValidatorForSystem.hasCodeBlocksMsvcGenerator(); + return false; } bool CMakeSettingsPage::hasCodeBlocksNinjaGenerator() const { - if (!isCMakeExecutableValid()) - return false; - if (m_userCmake.state == CMakeValidator::VALID) - return m_userCmake.hasCodeBlocksNinjaGenerator; - else - return m_pathCmake.hasCodeBlocksNinjaGenerator; + if (m_cmakeValidatorForUser.isValid()) + return m_cmakeValidatorForUser.hasCodeBlocksNinjaGenerator(); + if (m_cmakeValidatorForSystem.isValid()) + return m_cmakeValidatorForSystem.hasCodeBlocksNinjaGenerator(); + return false; +} + +TextEditor::Keywords CMakeSettingsPage::keywords() +{ + if (m_cmakeValidatorForUser.isValid()) + return m_cmakeValidatorForUser.keywords(); + + if (m_cmakeValidatorForSystem.isValid()) + return m_cmakeValidatorForSystem.keywords(); + + return TextEditor::Keywords(QStringList(), QStringList(), QMap<QString, QStringList>()); } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index e9665232ad..ef75fd74e9 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -35,6 +35,7 @@ #include <projectexplorer/project.h> #include <projectexplorer/projectnodes.h> #include <coreplugin/icontext.h> +#include <texteditor/codeassist/keywordscompletionassist.h> #include <utils/environment.h> #include <utils/pathchooser.h> @@ -42,9 +43,11 @@ #include <QFuture> #include <QStringList> #include <QDir> +#include <QVector> #include <QAction> -QT_FORWARD_DECLARE_CLASS(QProcess) +#include "cmakevalidator.h" + QT_FORWARD_DECLARE_CLASS(QLabel) namespace Utils { @@ -95,17 +98,6 @@ private: ProjectExplorer::Project *m_contextProject; }; -struct CMakeValidator -{ - enum STATE { VALID, INVALID, RUNNING }; - STATE state; - QProcess *process; - bool hasCodeBlocksMsvcGenerator; - bool hasCodeBlocksNinjaGenerator; - QString version; - QString executable; -}; - class CMakeSettingsPage : public Core::IOptionsPage { Q_OBJECT @@ -124,20 +116,15 @@ public: bool hasCodeBlocksMsvcGenerator() const; bool hasCodeBlocksNinjaGenerator() const; -private slots: - void userCmakeFinished(); - void pathCmakeFinished(); + TextEditor::Keywords keywords(); private: - void cmakeFinished(CMakeValidator *cmakeValidator) const; void saveSettings() const; QString findCmakeExecutable() const; - void startProcess(CMakeValidator *cmakeValidator); - void updateInfo(CMakeValidator *cmakeValidator); Utils::PathChooser *m_pathchooser; - mutable CMakeValidator m_userCmake; - mutable CMakeValidator m_pathCmake; + CMakeValidator m_cmakeValidatorForUser; + CMakeValidator m_cmakeValidatorForSystem; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro index b0b516944d..e52e9a730c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro @@ -17,7 +17,9 @@ HEADERS = cmakeproject.h \ cmakeeditor.h \ cmakehighlighter.h \ cmakeuicodemodelsupport.h \ - cmakelocatorfilter.h + cmakelocatorfilter.h \ + cmakefilecompletionassist.h \ + cmakevalidator.h SOURCES = cmakeproject.cpp \ cmakeprojectplugin.cpp \ @@ -31,7 +33,9 @@ SOURCES = cmakeproject.cpp \ cmakeeditor.cpp \ cmakehighlighter.cpp \ cmakeuicodemodelsupport.cpp \ - cmakelocatorfilter.cpp + cmakelocatorfilter.cpp \ + cmakefilecompletionassist.cpp \ + cmakevalidator.cpp RESOURCES += cmakeproject.qrc diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs index 3ce75fbbcb..61ff1f0b95 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs @@ -22,6 +22,8 @@ QtcPlugin { "cmakeeditor.h", "cmakeeditorfactory.cpp", "cmakeeditorfactory.h", + "cmakefilecompletionassist.cpp", + "cmakefilecompletionassist.h", "cmakehighlighter.cpp", "cmakehighlighter.h", "cmakelocatorfilter.cpp", @@ -42,6 +44,8 @@ QtcPlugin { "cmakerunconfiguration.h", "cmakeuicodemodelsupport.cpp", "cmakeuicodemodelsupport.h", + "cmakevalidator.cpp", + "cmakevalidator.h", "makestep.cpp", "makestep.h", ] diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index 619a594d35..23540b83bd 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -35,6 +35,7 @@ #include "makestep.h" #include "cmakeprojectconstants.h" #include "cmakelocatorfilter.h" +#include "cmakefilecompletionassist.h" #include <coreplugin/icore.h> #include <coreplugin/mimedatabase.h> @@ -68,7 +69,7 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString * addAutoReleasedObject(new CMakeEditorFactory(manager)); addAutoReleasedObject(new CMakeLocatorFilter); - + addAutoReleasedObject(new CMakeFileCompletionAssistProvider(cmp)); return true; } diff --git a/src/plugins/cmakeprojectmanager/cmakevalidator.cpp b/src/plugins/cmakeprojectmanager/cmakevalidator.cpp new file mode 100644 index 0000000000..a481ed26e5 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/cmakevalidator.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cmakevalidator.h" + +#include <QProcess> +#include <QFileInfo> +#include <QTextDocument> + +using namespace CMakeProjectManager::Internal; + +/////////////////////////// +// CMakeValidator +/////////////////////////// +CMakeValidator::CMakeValidator() + : m_state(Invalid), m_process(0), m_hasCodeBlocksMsvcGenerator(false), m_hasCodeBlocksNinjaGenerator(false) +{ + +} + +CMakeValidator::~CMakeValidator() +{ + cancel(); +} + +void CMakeValidator::cancel() +{ + if (m_process) { + disconnect(m_process, SIGNAL(finished(int))); + m_process->waitForFinished(); + delete m_process; + m_process = 0; + } +} + +void CMakeValidator::setCMakeExecutable(const QString &executable) +{ + cancel(); + m_process = new QProcess(); + connect(m_process, SIGNAL(finished(int)), + this, SLOT(finished(int))); + + m_executable = executable; + QFileInfo fi(m_executable); + if (fi.exists() && fi.isExecutable()) { + // Run it to find out more + m_state = CMakeValidator::RunningBasic; + if (!startProcess(QStringList(QLatin1String("--help")))) + m_state = CMakeValidator::Invalid; + } else { + m_state = CMakeValidator::Invalid; + } +} + +void CMakeValidator::finished(int exitCode) +{ + if (exitCode) { + m_state = CMakeValidator::Invalid; + return; + } + if (m_state == CMakeValidator::RunningBasic) { + QString response = m_process->readAll(); + QRegExp versionRegexp(QLatin1String("^cmake version ([\\d\\.]*)")); + versionRegexp.indexIn(response); + + //m_supportsQtCreator = response.contains(QLatin1String("QtCreator")); + m_hasCodeBlocksMsvcGenerator = response.contains(QLatin1String("CodeBlocks - NMake Makefiles")); + m_hasCodeBlocksNinjaGenerator = response.contains(QLatin1String("CodeBlocks - Ninja")); + m_version = versionRegexp.cap(1); + if (!(versionRegexp.capturedTexts().size() > 3)) + m_version += QLatin1Char('.') + versionRegexp.cap(3); + + if (m_version.isEmpty()) { + m_state = CMakeValidator::Invalid; + } else { + m_state = CMakeValidator::RunningFunctionList; + if (!startProcess(QStringList(QLatin1String("--help-command-list")))) + finished(0); // shoud never happen, just continue + } + } else if (m_state == CMakeValidator::RunningFunctionList) { + parseFunctionOutput(m_process->readAll()); + m_state = CMakeValidator::RunningFunctionDetails; + if (!startProcess(QStringList(QLatin1String("--help-commands")))) + finished(0); // shoud never happen, just continue + } else if (m_state == CMakeValidator::RunningFunctionDetails) { + parseFunctionDetailsOutput(m_process->readAll()); + m_state = CMakeValidator::ValidFunctionDetails; + } +} + +bool CMakeValidator::isValid() const +{ + if (m_state == CMakeValidator::Invalid) + return false; + if (m_state == CMakeValidator::RunningBasic) + m_process->waitForFinished(); + return (m_state != CMakeValidator::Invalid); +} + +bool CMakeValidator::startProcess(const QStringList &args) +{ + m_process->start(m_executable, args); + return m_process->waitForStarted(2000); +} + +QString CMakeValidator::cmakeExecutable() const +{ + return m_executable; +} + +bool CMakeValidator::hasCodeBlocksMsvcGenerator() const +{ + if (!isValid()) + return false; + return m_hasCodeBlocksMsvcGenerator; +} + +bool CMakeValidator::hasCodeBlocksNinjaGenerator() const +{ + if (!isValid()) + return false; + return m_hasCodeBlocksNinjaGenerator; +} + + +TextEditor::Keywords CMakeValidator::keywords() +{ + while (m_state != ValidFunctionDetails && m_state != CMakeValidator::Invalid) { + m_process->waitForFinished(); + } + + if (m_state == CMakeValidator::Invalid) + return TextEditor::Keywords(QStringList(), QStringList(), QMap<QString, QStringList>()); + + return TextEditor::Keywords(m_variables, m_functions, m_functionArgs); +} + +static void extractKeywords(const QByteArray &input, QStringList *destination) +{ + if (!destination) + return; + + QString keyword; + int ignoreZone = 0; + for (int i = 0; i < input.count(); ++i) { + const QChar chr = input.at(i); + if (chr == QLatin1Char('{')) + ++ignoreZone; + if (chr == QLatin1Char('}')) + --ignoreZone; + if (ignoreZone == 0) { + if ((chr.isLetterOrNumber() && chr.isUpper()) + || chr == QLatin1Char('_')) { + keyword += chr; + } else { + if (!keyword.isEmpty()) { + if (keyword.size() > 1) { + *destination << keyword; + } + keyword.clear(); + } + } + } + } + if (keyword.size() > 1) { + *destination << keyword; + } +} + +void CMakeValidator::parseFunctionOutput(const QByteArray &output) +{ + QList<QByteArray> cmakeFunctionsList = output.split('\n'); + m_functions.clear(); + if (!cmakeFunctionsList.isEmpty()) { + cmakeFunctionsList.removeFirst(); //remove version string + foreach (const QByteArray &function, cmakeFunctionsList) + m_functions << QString(function).trimmed(); + } +} + +QString CMakeValidator::formatFunctionDetails(const QString &command, const QByteArray &args) +{ + return QLatin1String("<table><tr><td><b>") + Qt::escape(command) + + QLatin1String("</b></td><td>") + + Qt::escape(args) + + QLatin1String("</td></tr>"); +} + +void CMakeValidator::parseFunctionDetailsOutput(const QByteArray &output) +{ + QStringList cmakeFunctionsList = m_functions; + QList<QByteArray> cmakeCommandsHelp = output.split('\n'); + for (int i = 0; i < cmakeCommandsHelp.count(); ++i) { + QByteArray lineTrimmed = cmakeCommandsHelp.at(i).trimmed(); + if (cmakeFunctionsList.first().toLatin1() == lineTrimmed) { + QStringList commandSyntaxes; + QString currentCommandSyntax; + QString currentCommand = cmakeFunctionsList.takeFirst(); + ++i; + for (; i < cmakeCommandsHelp.count(); ++i) { + lineTrimmed = cmakeCommandsHelp.at(i).trimmed(); + + if (cmakeFunctionsList.first().toLatin1() == lineTrimmed) { + //start of next function in output + if (!currentCommandSyntax.isEmpty()) + commandSyntaxes << currentCommandSyntax.append("</table>"); + --i; + break; + } + if (lineTrimmed.startsWith(currentCommand.toLatin1() + "(")) { + if (!currentCommandSyntax.isEmpty()) + commandSyntaxes << currentCommandSyntax.append("</table>"); + + QByteArray argLine = lineTrimmed.mid(currentCommand.length()); + extractKeywords(argLine, &m_variables); + currentCommandSyntax = formatFunctionDetails(currentCommand, argLine); + } else { + if (!currentCommandSyntax.isEmpty()) { + if (lineTrimmed.isEmpty()) { + commandSyntaxes << currentCommandSyntax.append("</table>"); + currentCommandSyntax.clear(); + } else { + extractKeywords(lineTrimmed, &m_variables); + currentCommandSyntax += "<tr><td> </td><td>" + Qt::escape(lineTrimmed) + "</td></tr>"; + } + } + } + } + m_functionArgs[currentCommand] = commandSyntaxes; + } + } + m_functions = m_functionArgs.keys(); + m_variables.sort(); + m_variables.removeDuplicates(); +} + diff --git a/src/plugins/cmakeprojectmanager/cmakevalidator.h b/src/plugins/cmakeprojectmanager/cmakevalidator.h new file mode 100644 index 0000000000..38c413b79e --- /dev/null +++ b/src/plugins/cmakeprojectmanager/cmakevalidator.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CMAKEVALIDATOR_H +#define CMAKEVALIDATOR_H + +#include <QObject> +#include <QString> +#include <QStringList> +#include <texteditor/codeassist/keywordscompletionassist.h> + +QT_FORWARD_DECLARE_CLASS(QProcess) + +namespace CMakeProjectManager { +namespace Internal { + +class CMakeValidator : public QObject +{ + Q_OBJECT +public: + CMakeValidator(); + ~CMakeValidator(); + + enum State { Invalid, RunningBasic, RunningFunctionList, RunningFunctionDetails, ValidFunctionDetails }; + void cancel(); + bool isValid() const; + + void setCMakeExecutable(const QString &executable); + QString cmakeExecutable() const; + bool hasCodeBlocksMsvcGenerator() const; + bool hasCodeBlocksNinjaGenerator() const; + TextEditor::Keywords keywords(); +private slots: + void finished(int exitCode); + +private: + void finishStep(); + void startNextStep(); + bool startProcess(const QStringList &args); + void parseFunctionOutput(const QByteArray &output); + void parseFunctionDetailsOutput(const QByteArray &output); + QString formatFunctionDetails(const QString &command, const QByteArray &args); + + State m_state; + QProcess *m_process; + bool m_hasCodeBlocksMsvcGenerator; + bool m_hasCodeBlocksNinjaGenerator; + QString m_version; + QString m_executable; + + QMap<QString, QStringList> m_functionArgs; + QStringList m_variables; + QStringList m_functions; +}; + +} // namespace Internal +} // namespace CMakeProjectManager + +#endif // CMAKEVALIDATOR_H diff --git a/src/plugins/qt4projectmanager/profilecompletionassist.cpp b/src/plugins/qt4projectmanager/profilecompletionassist.cpp index 2478b5d00a..a0ae7dc887 100644 --- a/src/plugins/qt4projectmanager/profilecompletionassist.cpp +++ b/src/plugins/qt4projectmanager/profilecompletionassist.cpp @@ -29,73 +29,236 @@ #include "profilecompletionassist.h" #include "qt4projectmanagerconstants.h" -#include "profilekeywords.h" -#include <texteditor/codeassist/iassistinterface.h> -#include <texteditor/codeassist/genericproposal.h> -#include <texteditor/completionsettings.h> -#include <texteditor/texteditorsettings.h> -#include <texteditor/basetexteditor.h> - -#include <cplusplus/Icons.h> - -#include <QTextCursor> +#include <texteditor/codeassist/keywordscompletionassist.h> using namespace Qt4ProjectManager::Internal; using namespace TextEditor; -// ------------------------- -// ProFileAssistProposalItem -// ------------------------- -ProFileAssistProposalItem::ProFileAssistProposalItem() -{} -ProFileAssistProposalItem::~ProFileAssistProposalItem() -{} - -bool ProFileAssistProposalItem::prematurelyApplies(const QChar &c) const -{ - // only '(' in case of a function - if (c == QLatin1Char('(') && ProFileKeywords::isFunction(text())) - return true; - return false; -} - -void ProFileAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *editor, - int basePosition) const -{ - const CompletionSettings &settings = TextEditorSettings::instance()->completionSettings(); - - int replaceLength = editor->position() - basePosition; - QString toInsert = text(); - int cursorOffset = 0; - if (ProFileKeywords::isFunction(toInsert) && settings.m_autoInsertBrackets) { - if (settings.m_spaceAfterFunctionName) { - if (editor->textAt(editor->position(), 2) == QLatin1String(" (")) { - cursorOffset = 2; - } else if (editor->characterAt(editor->position()) == QLatin1Char('(') - || editor->characterAt(editor->position()) == QLatin1Char(' ')) { - replaceLength += 1; - toInsert += QLatin1String(" ("); - } else { - toInsert += QLatin1String(" ()"); - cursorOffset = -1; - } - } else { - if (editor->characterAt(editor->position()) == QLatin1Char('(')) { - cursorOffset = 1; - } else { - toInsert += QLatin1String("()"); - cursorOffset = -1; - } - } - } - - editor->setCursorPosition(basePosition); - editor->replace(replaceLength, toInsert); - if (cursorOffset) - editor->setCursorPosition(editor->position() + cursorOffset); -} +static const char *const variableKeywords[] = { + "BACKUP_REGISTRATION_FILE_MAEMO", + "CCFLAG", + "CONFIG", + "DEFINES", + "DEF_FILE", + "DEPENDPATH", + "DEPLOYMENT", + "DEPLOYMENT_PLUGIN", + "DESTDIR", + "DESTDIR_TARGET", + "DISTFILES", + "DLLDESTDIR", + "DISTFILES", + "DSP_TEMPLATE", + "FORMS", + "FORMS3", + "GUID", + "HEADERS", + "ICON", + "INCLUDEPATH", + "INSTALLS", + "LEXIMPLS", + "LEXOBJECTS", + "LEXSOURCES", + "LIBS", + "LITERAL_HASH", + "MAKEFILE", + "MAKEFILE_GENERATOR", + "MOBILITY", + "MOC_DIR", + "OBJECTIVE_HEADERS", + "OBJECTIVE_SOURCES", + "OBJECTS", + "OBJECTS_DIR", + "OBJMOC", + "OTHER_FILES", + "PKGCONFIG", + "POST_TARGETDEPS", + "PRE_TARGETDEPS", + "PRECOMPILED_HEADER", + "PWD", + "OUT_PWD", + "QMAKE", + "QMAKESPEC", + "QMAKE_APP_FLAG", + "QMAKE_APP_OR_DLL", + "QMAKE_AR_CMD", + "QMAKE_BUNDLE_DATA", + "QMAKE_BUNDLE_EXTENSION", + "QMAKE_CC", + "QMAKE_CFLAGS_DEBUG", + "QMAKE_CFLAGS_MT", + "QMAKE_CFLAGS_MT_DBG", + "QMAKE_CFLAGS_MT_DLL", + "QMAKE_CFLAGS_MT_DLLDBG", + "QMAKE_CFLAGS_RELEASE", + "QMAKE_CFLAGS_SHLIB", + "QMAKE_CFLAGS_THREAD", + "QMAKE_CFLAGS_WARN_OFF", + "QMAKE_CFLAGS_WARN_ON", + "QMAKE_CLEAN", + "QMAKE_CXX", + "QMAKE_CXXFLAGS", + "QMAKE_CXXFLAGS_DEBUG", + "QMAKE_CXXFLAGS_MT", + "QMAKE_CXXFLAGS_MT_DBG", + "QMAKE_CXXFLAGS_MT_DLL", + "QMAKE_CXXFLAGS_MT_DLLDBG", + "QMAKE_CXXFLAGS_RELEASE", + "QMAKE_CXXFLAGS_SHLIB", + "QMAKE_CXXFLAGS_THREAD", + "QMAKE_CXXFLAGS_WARN_OFF", + "QMAKE_CXXFLAGS_WARN_ON", + "QMAKE_DISTCLEAN", + "QMAKE_EXTENSION_SHLIB", + "QMAKE_EXT_MOC", + "QMAKE_EXT_UI", + "QMAKE_EXT_PRL", + "QMAKE_EXT_LEX", + "QMAKE_EXT_YACC", + "QMAKE_EXT_OBJ", + "QMAKE_EXT_CPP", + "QMAKE_EXT_H", + "QMAKE_EXTRA_COMPILERS", + "QMAKE_EXTRA_TARGETS", + "QMAKE_FAILED_REQUIREMENTS", + "QMAKE_FRAMEWORK_BUNDLE_NAME", + "QMAKE_FRAMEWORK_VERSION", + "QMAKE_INCDIR", + "QMAKE_INCDIR_EGL", + "QMAKE_INCDIR_OPENGL", + "QMAKE_INCDIR_OPENGL_ES1", + "QMAKE_INCDIR_OPENGL_ES2", + "QMAKE_INCDIR_OPENVG", + "QMAKE_INCDIR_QT", + "QMAKE_INCDIR_THREAD", + "QMAKE_INCDIR_X11", + "QMAKE_INFO_PLIST", + "QMAKE_LFLAGS", + "QMAKE_LFLAGS_CONSOLE", + "QMAKE_LFLAGS_CONSOLE_DLL", + "QMAKE_LFLAGS_DEBUG", + "QMAKE_LFLAGS_PLUGIN", + "QMAKE_LFLAGS_RPATH", + "QMAKE_LFLAGS_QT_DLL", + "QMAKE_LFLAGS_RELEASE", + "QMAKE_LFLAGS_SHAPP", + "QMAKE_LFLAGS_SHLIB", + "QMAKE_LFLAGS_SONAME", + "QMAKE_LFLAGS_THREAD", + "QMAKE_LFLAGS_WINDOWS", + "QMAKE_LFLAGS_WINDOWS_DLL", + "QMAKE_LIBDIR", + "QMAKE_LIBDIR_FLAGS", + "QMAKE_LIBDIR_EGL", + "QMAKE_LIBDIR_OPENGL", + "QMAKE_LIBDIR_OPENVG", + "QMAKE_LIBDIR_QT", + "QMAKE_LIBDIR_X11", + "QMAKE_LIBS", + "QMAKE_LIBS_CONSOLE", + "QMAKE_LIBS_EGL", + "QMAKE_LIBS_OPENGL", + "QMAKE_LIBS_OPENGL_QT", + "QMAKE_LIBS_OPENGL_ES1", + "QMAKE_LIBS_OPENGL_ES2", + "QMAKE_LIBS_OPENVG", + "QMAKE_LIBS_QT", + "QMAKE_LIBS_QT_DLL", + "QMAKE_LIBS_QT_OPENGL", + "QMAKE_LIBS_QT_THREAD", + "QMAKE_LIBS_RT", + "QMAKE_LIBS_RTMT", + "QMAKE_LIBS_THREAD", + "QMAKE_LIBS_WINDOWS", + "QMAKE_LIBS_X11", + "QMAKE_LIBS_X11SM", + "QMAKE_LIB_FLAG", + "QMAKE_LINK_SHLIB_CMD", + "QMAKE_LN_SHLIB", + "QMAKE_POST_LINK", + "QMAKE_PRE_LINK", + "QMAKE_PROJECT_NAME", + "QMAKE_MAC_SDK", + "QMAKE_MACOSX_DEPLOYMENT_TARGET", + "QMAKE_MAKEFILE", + "QMAKE_MOC_SRC", + "QMAKE_QMAKE", + "QMAKE_QT_DLL", + "QMAKE_RESOURCE_FLAGS", + "QMAKE_RPATH", + "QMAKE_RPATHDIR", + "QMAKE_RUN_CC", + "QMAKE_RUN_CC_IMP", + "QMAKE_RUN_CXX", + "QMAKE_RUN_CXX_IMP", + "QMAKE_TARGET", + "QMAKE_UIC", + "QT", + "QTPLUGIN", + "QT_VERSION", + "QT_MAJOR_VERSION", + "QT_MINOR_VERSION", + "QT_PATCH_VERSION", + "RCC_DIR", + "RC_FILE", + "REQUIRES", + "RESOURCES", + "RES_FILE", + "RSS_RULES", + "SIGNATURE_FILE", + "SOURCES", + "SRCMOC", + "STATECHARTS", + "SUBDIRS", + "TARGET", + "TEMPLATE", + "TRANSLATIONS", + "UICIMPLS", + "UICOBJECTS", + "UI_DIR", + "UI_HEADERS_DIR", + "UI_SOURCES_DIR", + "VER_MAJ", + "VER_MIN", + "VER_PAT", + "VERSION", + "VPATH", + "YACCIMPLS", + "YACCOBJECTS", + "YACCSOURCES", + "_PRO_FILE_", + "_PRO_FILE_PWD_", + 0 +}; + +static const char *const functionKeywords[] = { + "basename", + "contains", + "count", + "dirname", + "error", + "eval", + "exists", + "find", + "for", + "include", + "infile", + "isEmpty", + "join", + "member", + "message", + "packagesExist", + "prompt", + "quote", + "replace", + "sprintf", + "system", + "unique", + "warning", + 0 +}; // ------------------------------- // ProFileCompletionAssistProvider @@ -103,127 +266,41 @@ void ProFileAssistProposalItem::applyContextualContent(TextEditor::BaseTextEdito ProFileCompletionAssistProvider::ProFileCompletionAssistProvider() {} -ProFileCompletionAssistProvider::~ProFileCompletionAssistProvider() -{} - -bool ProFileCompletionAssistProvider::supportsEditor(const Core::Id &editorId) const -{ - return editorId == Qt4ProjectManager::Constants::PROFILE_EDITOR_ID; -} - -bool ProFileCompletionAssistProvider::isAsynchronous() const -{ - return false; -} - -int ProFileCompletionAssistProvider::activationCharSequenceLength() const +void ProFileCompletionAssistProvider::init() { - return 0; + for (uint i = 0; i < sizeof variableKeywords / sizeof variableKeywords[0] - 1; i++) + m_variables.append(QLatin1String(variableKeywords[i])); + for (uint i = 0; i < sizeof functionKeywords / sizeof functionKeywords[0] - 1; i++) + m_functions.append(QLatin1String(functionKeywords[i])); } -bool ProFileCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const +ProFileCompletionAssistProvider::~ProFileCompletionAssistProvider() { - Q_UNUSED(sequence); - return false; } -bool ProFileCompletionAssistProvider::isContinuationChar(const QChar &c) const +bool ProFileCompletionAssistProvider::supportsEditor(const Core::Id &editorId) const { - return c.isLetterOrNumber() || c == QLatin1Char('_'); + return editorId == Qt4ProjectManager::Constants::PROFILE_EDITOR_ID; } IAssistProcessor *ProFileCompletionAssistProvider::createProcessor() const { - return new ProFileCompletionAssistProcessor; -} - -// -------------------------------- -// ProFileCompletionAssistProcessor -// -------------------------------- -ProFileCompletionAssistProcessor::ProFileCompletionAssistProcessor() - : m_startPosition(-1) - , m_variableIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::VarPublicIconType)) - , m_functionIcon(CPlusPlus::Icons().iconForType(CPlusPlus::Icons::FuncPublicIconType)) -{} - -ProFileCompletionAssistProcessor::~ProFileCompletionAssistProcessor() -{} - -IAssistProposal *ProFileCompletionAssistProcessor::perform(const IAssistInterface *interface) -{ - m_interface.reset(interface); - - if (isInComment()) - return 0; - - if (interface->reason() == IdleEditor && !acceptsIdleEditor()) - return 0; - - if (m_startPosition == -1) - m_startPosition = findStartOfName(); - - QList<TextEditor::BasicProposalItem *> items; - QStringList keywords = ProFileKeywords::variables() + ProFileKeywords::functions(); - for (int i = 0; i < keywords.count(); i++) { - BasicProposalItem *item = new ProFileAssistProposalItem; - item->setText(keywords[i]); - item->setIcon(ProFileKeywords::isFunction(item->text()) ? m_functionIcon : m_variableIcon); - items.append(item); - } - - return new GenericProposal(m_startPosition, new ProFileAssistProposalModel(items)); + if (m_variables.isEmpty()) + const_cast<ProFileCompletionAssistProvider *>(this)->init(); + TextEditor::Keywords keywords = TextEditor::Keywords(m_variables, m_functions, QMap<QString, QStringList>()); + return new KeywordsCompletionAssistProcessor(keywords); } -bool ProFileCompletionAssistProcessor::acceptsIdleEditor() +QStringList ProFileCompletionAssistProvider::variables() const { - const int pos = m_interface->position(); - QChar characterUnderCursor = m_interface->characterAt(pos); - if (!characterUnderCursor.isLetterOrNumber()) { - m_startPosition = findStartOfName(); - if (pos - m_startPosition >= 3 && !isInComment()) - return true; - } - return false; + if (m_variables.isEmpty()) + const_cast<ProFileCompletionAssistProvider *>(this)->init(); + return m_variables; } -int ProFileCompletionAssistProcessor::findStartOfName(int pos) const -{ - if (pos == -1) - pos = m_interface->position(); - QChar chr; - - // Skip to the start of a name - do { - chr = m_interface->characterAt(--pos); - } while (chr.isLetterOrNumber() || chr == QLatin1Char('_')); - - return pos + 1; -} - -bool ProFileCompletionAssistProcessor::isInComment() const -{ - QTextCursor tc(m_interface->textDocument()); - tc.setPosition(m_interface->position()); - tc.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - const QString &lineBeginning = tc.selectedText(); - if (lineBeginning.contains(QLatin1Char('#'))) - return true; - return false; -} - -// -------------------------- -// ProFileAssistProposalModel -// -------------------------- -ProFileAssistProposalModel::ProFileAssistProposalModel( - const QList<BasicProposalItem *> &items) - : BasicProposalItemListModel(items) -{} - -ProFileAssistProposalModel::~ProFileAssistProposalModel() -{} - -bool ProFileAssistProposalModel::isSortable(const QString &prefix) const +QStringList ProFileCompletionAssistProvider::functions() const { - Q_UNUSED(prefix) - return false; + if (m_functions.isEmpty()) + const_cast<ProFileCompletionAssistProvider *>(this)->init(); + return m_functions; } diff --git a/src/plugins/qt4projectmanager/profilecompletionassist.h b/src/plugins/qt4projectmanager/profilecompletionassist.h index 7b0906333f..e0012fe668 100644 --- a/src/plugins/qt4projectmanager/profilecompletionassist.h +++ b/src/plugins/qt4projectmanager/profilecompletionassist.h @@ -30,71 +30,28 @@ #ifndef PROFILECOMPLETIONASSIST_H #define PROFILECOMPLETIONASSIST_H -#include <texteditor/codeassist/basicproposalitem.h> -#include <texteditor/codeassist/basicproposalitemlistmodel.h> #include <texteditor/codeassist/completionassistprovider.h> -#include <texteditor/codeassist/iassistprocessor.h> -#include <QIcon> +#include <QStringList> namespace Qt4ProjectManager { namespace Internal { -class ProFileAssistProposalItem : public TextEditor::BasicProposalItem -{ -public: - ProFileAssistProposalItem(); - virtual ~ProFileAssistProposalItem(); - - virtual bool prematurelyApplies(const QChar &c) const; - virtual void applyContextualContent(TextEditor::BaseTextEditor *editor, - int basePosition) const; -}; - - class ProFileCompletionAssistProvider : public TextEditor::CompletionAssistProvider { + Q_OBJECT public: ProFileCompletionAssistProvider(); + void init(); virtual ~ProFileCompletionAssistProvider(); virtual bool supportsEditor(const Core::Id &editorId) const; virtual TextEditor::IAssistProcessor *createProcessor() const; - - virtual bool isAsynchronous() const; - virtual int activationCharSequenceLength() const; - virtual bool isActivationCharSequence(const QString &sequence) const; - virtual bool isContinuationChar(const QChar &c) const; -}; - - -class ProFileCompletionAssistProcessor : public TextEditor::IAssistProcessor -{ -public: - ProFileCompletionAssistProcessor(); - virtual ~ProFileCompletionAssistProcessor(); - - virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface); - + QStringList variables() const; + QStringList functions() const; private: - bool acceptsIdleEditor(); - int findStartOfName(int pos = -1) const; - bool isInComment() const; - - int m_startPosition; - QScopedPointer<const TextEditor::IAssistInterface> m_interface; - const QIcon m_variableIcon; - const QIcon m_functionIcon; -}; - - -class ProFileAssistProposalModel : public TextEditor::BasicProposalItemListModel -{ -public: - ProFileAssistProposalModel(const QList<TextEditor::BasicProposalItem *> &items); - virtual ~ProFileAssistProposalModel(); - - virtual bool isSortable(const QString &prefix) const; + QStringList m_variables; + QStringList m_functions; }; } // Internal diff --git a/src/plugins/qt4projectmanager/profilehighlighter.cpp b/src/plugins/qt4projectmanager/profilehighlighter.cpp index 487dffefb6..ddd480c378 100644 --- a/src/plugins/qt4projectmanager/profilehighlighter.cpp +++ b/src/plugins/qt4projectmanager/profilehighlighter.cpp @@ -28,7 +28,9 @@ ****************************************************************************/ #include "profilehighlighter.h" -#include "profilekeywords.h" +#include "profilecompletionassist.h" + +#include <extensionsystem/pluginmanager.h> #include <QRegExp> #include <QColor> @@ -41,6 +43,9 @@ using namespace Qt4ProjectManager::Internal; ProFileHighlighter::ProFileHighlighter(QTextDocument *document) : TextEditor::SyntaxHighlighter(document) { + ProFileCompletionAssistProvider *pcap + = ExtensionSystem::PluginManager::instance()->getObject<ProFileCompletionAssistProvider>(); + m_keywords = TextEditor::Keywords(pcap->variables(), pcap->functions(), QMap<QString, QStringList>()); } void ProFileHighlighter::highlightBlock(const QString &text) @@ -61,12 +66,12 @@ void ProFileHighlighter::highlightBlock(const QString &text) if (c.isLetter() || c == QLatin1Char('_') || c == QLatin1Char('.') || c.isDigit()) { buf += c; setFormat(i - buf.length()+1, buf.length(), emptyFormat); - if (!buf.isEmpty() && ProFileKeywords::isFunction(buf)) + if (!buf.isEmpty() && m_keywords.isFunction(buf)) setFormat(i - buf.length()+1, buf.length(), m_formats[ProfileFunctionFormat]); - else if (!buf.isEmpty() && ProFileKeywords::isVariable(buf)) + else if (!buf.isEmpty() && m_keywords.isVariable(buf)) setFormat(i - buf.length()+1, buf.length(), m_formats[ProfileVariableFormat]); } else if (c == QLatin1Char('(')) { - if (!buf.isEmpty() && ProFileKeywords::isFunction(buf)) + if (!buf.isEmpty() && m_keywords.isFunction(buf)) setFormat(i - buf.length(), buf.length(), m_formats[ProfileFunctionFormat]); buf.clear(); } else if (c == QLatin1Char('#')) { @@ -74,7 +79,7 @@ void ProFileHighlighter::highlightBlock(const QString &text) setFormat(i, 1, m_formats[ProfileCommentFormat]); buf.clear(); } else { - if (!buf.isEmpty() && ProFileKeywords::isVariable(buf)) + if (!buf.isEmpty() && m_keywords.isVariable(buf)) setFormat(i - buf.length(), buf.length(), m_formats[ProfileVariableFormat]); buf.clear(); } diff --git a/src/plugins/qt4projectmanager/profilehighlighter.h b/src/plugins/qt4projectmanager/profilehighlighter.h index 70147f6f6b..f135d498bf 100644 --- a/src/plugins/qt4projectmanager/profilehighlighter.h +++ b/src/plugins/qt4projectmanager/profilehighlighter.h @@ -31,6 +31,7 @@ #define PROFILEHIGHLIGHTER_H #include <texteditor/syntaxhighlighter.h> +#include <texteditor/codeassist/keywordscompletionassist.h> #include <QtAlgorithms> #include <QSyntaxHighlighter> #include <QTextCharFormat> @@ -61,6 +62,8 @@ public: private: QTextCharFormat m_formats[NumProfileFormats]; + TextEditor::Keywords m_keywords; + }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/profilehoverhandler.cpp b/src/plugins/qt4projectmanager/profilehoverhandler.cpp index 3249d88c14..7e4ca30f3e 100644 --- a/src/plugins/qt4projectmanager/profilehoverhandler.cpp +++ b/src/plugins/qt4projectmanager/profilehoverhandler.cpp @@ -29,7 +29,7 @@ #include "profilehoverhandler.h" #include "profileeditor.h" -#include "profilekeywords.h" +#include "profilecompletionassist.h" #include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/editormanager.h> @@ -53,6 +53,9 @@ ProFileHoverHandler::ProFileHoverHandler(QObject *parent) : BaseHoverHandler(parent), m_manualKind(UnknownManual) { + ProFileCompletionAssistProvider *pcap + = ExtensionSystem::PluginManager::instance()->getObject<ProFileCompletionAssistProvider>(); + m_keywords = TextEditor::Keywords(pcap->variables(), pcap->functions(), QMap<QString, QStringList>()); } ProFileHoverHandler::~ProFileHoverHandler() @@ -111,9 +114,9 @@ void ProFileHoverHandler::identifyQMakeKeyword(const QString &text, int pos) if (checkBuffer) { if (!buf.isEmpty()) { if ((i >= pos) && (i - buf.size() <= pos)) { - if (ProFileKeywords::isFunction(buf)) + if (m_keywords.isFunction(buf)) identifyDocFragment(FunctionManual, buf); - else if (ProFileKeywords::isVariable(buf)) + else if (m_keywords.isVariable(buf)) identifyDocFragment(VariableManual, buf); break; } diff --git a/src/plugins/qt4projectmanager/profilehoverhandler.h b/src/plugins/qt4projectmanager/profilehoverhandler.h index 7a881e694b..086c7db43f 100644 --- a/src/plugins/qt4projectmanager/profilehoverhandler.h +++ b/src/plugins/qt4projectmanager/profilehoverhandler.h @@ -31,6 +31,7 @@ #define PROFILEHOVERHANDLER_H #include <texteditor/basehoverhandler.h> +#include <texteditor/codeassist/keywordscompletionassist.h> #include <QObject> @@ -76,6 +77,7 @@ private: QString m_docFragment; ManualKind m_manualKind; + TextEditor::Keywords m_keywords; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/profilekeywords.cpp b/src/plugins/qt4projectmanager/profilekeywords.cpp deleted file mode 100644 index fce55584a3..0000000000 --- a/src/plugins/qt4projectmanager/profilekeywords.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "profilekeywords.h" - -using namespace Qt4ProjectManager::Internal; - -static const char *const variableKeywords[] = { - "BACKUP_REGISTRATION_FILE_MAEMO", - "CCFLAG", - "CONFIG", - "DEFINES", - "DEF_FILE", - "DEPENDPATH", - "DEPLOYMENT", - "DEPLOYMENT_PLUGIN", - "DESTDIR", - "DESTDIR_TARGET", - "DISTFILES", - "DLLDESTDIR", - "DISTFILES", - "DSP_TEMPLATE", - "FORMS", - "FORMS3", - "GUID", - "HEADERS", - "ICON", - "INCLUDEPATH", - "INSTALLS", - "LEXIMPLS", - "LEXOBJECTS", - "LEXSOURCES", - "LIBS", - "LITERAL_HASH", - "MAKEFILE", - "MAKEFILE_GENERATOR", - "MOBILITY", - "MOC_DIR", - "OBJECTIVE_HEADERS", - "OBJECTIVE_SOURCES", - "OBJECTS", - "OBJECTS_DIR", - "OBJMOC", - "OTHER_FILES", - "PKGCONFIG", - "POST_TARGETDEPS", - "PRE_TARGETDEPS", - "PRECOMPILED_HEADER", - "PWD", - "OUT_PWD", - "QMAKE", - "QMAKESPEC", - "QMAKE_APP_FLAG", - "QMAKE_APP_OR_DLL", - "QMAKE_AR_CMD", - "QMAKE_BUNDLE_DATA", - "QMAKE_BUNDLE_EXTENSION", - "QMAKE_CC", - "QMAKE_CFLAGS_DEBUG", - "QMAKE_CFLAGS_MT", - "QMAKE_CFLAGS_MT_DBG", - "QMAKE_CFLAGS_MT_DLL", - "QMAKE_CFLAGS_MT_DLLDBG", - "QMAKE_CFLAGS_RELEASE", - "QMAKE_CFLAGS_SHLIB", - "QMAKE_CFLAGS_THREAD", - "QMAKE_CFLAGS_WARN_OFF", - "QMAKE_CFLAGS_WARN_ON", - "QMAKE_CLEAN", - "QMAKE_CXX", - "QMAKE_CXXFLAGS", - "QMAKE_CXXFLAGS_DEBUG", - "QMAKE_CXXFLAGS_MT", - "QMAKE_CXXFLAGS_MT_DBG", - "QMAKE_CXXFLAGS_MT_DLL", - "QMAKE_CXXFLAGS_MT_DLLDBG", - "QMAKE_CXXFLAGS_RELEASE", - "QMAKE_CXXFLAGS_SHLIB", - "QMAKE_CXXFLAGS_THREAD", - "QMAKE_CXXFLAGS_WARN_OFF", - "QMAKE_CXXFLAGS_WARN_ON", - "QMAKE_DISTCLEAN", - "QMAKE_EXTENSION_SHLIB", - "QMAKE_EXT_MOC", - "QMAKE_EXT_UI", - "QMAKE_EXT_PRL", - "QMAKE_EXT_LEX", - "QMAKE_EXT_YACC", - "QMAKE_EXT_OBJ", - "QMAKE_EXT_CPP", - "QMAKE_EXT_H", - "QMAKE_EXTRA_COMPILERS", - "QMAKE_EXTRA_TARGETS", - "QMAKE_FAILED_REQUIREMENTS", - "QMAKE_FILETAGS", - "QMAKE_FRAMEWORK_BUNDLE_NAME", - "QMAKE_FRAMEWORK_VERSION", - "QMAKE_INCDIR", - "QMAKE_INCDIR_EGL", - "QMAKE_INCDIR_OPENGL", - "QMAKE_INCDIR_OPENGL_ES1", - "QMAKE_INCDIR_OPENGL_ES2", - "QMAKE_INCDIR_OPENVG", - "QMAKE_INCDIR_QT", - "QMAKE_INCDIR_THREAD", - "QMAKE_INCDIR_X11", - "QMAKE_INFO_PLIST", - "QMAKE_LFLAGS", - "QMAKE_LFLAGS_CONSOLE", - "QMAKE_LFLAGS_CONSOLE_DLL", - "QMAKE_LFLAGS_DEBUG", - "QMAKE_LFLAGS_PLUGIN", - "QMAKE_LFLAGS_RPATH", - "QMAKE_LFLAGS_QT_DLL", - "QMAKE_LFLAGS_RELEASE", - "QMAKE_LFLAGS_SHAPP", - "QMAKE_LFLAGS_SHLIB", - "QMAKE_LFLAGS_SONAME", - "QMAKE_LFLAGS_THREAD", - "QMAKE_LFLAGS_WINDOWS", - "QMAKE_LFLAGS_WINDOWS_DLL", - "QMAKE_LIBDIR", - "QMAKE_LIBDIR_FLAGS", - "QMAKE_LIBDIR_EGL", - "QMAKE_LIBDIR_OPENGL", - "QMAKE_LIBDIR_OPENVG", - "QMAKE_LIBDIR_QT", - "QMAKE_LIBDIR_X11", - "QMAKE_LIBS", - "QMAKE_LIBS_CONSOLE", - "QMAKE_LIBS_EGL", - "QMAKE_LIBS_OPENGL", - "QMAKE_LIBS_OPENGL_QT", - "QMAKE_LIBS_OPENGL_ES1", - "QMAKE_LIBS_OPENGL_ES2", - "QMAKE_LIBS_OPENVG", - "QMAKE_LIBS_QT", - "QMAKE_LIBS_QT_DLL", - "QMAKE_LIBS_QT_OPENGL", - "QMAKE_LIBS_QT_THREAD", - "QMAKE_LIBS_RT", - "QMAKE_LIBS_RTMT", - "QMAKE_LIBS_THREAD", - "QMAKE_LIBS_WINDOWS", - "QMAKE_LIBS_X11", - "QMAKE_LIBS_X11SM", - "QMAKE_LIB_FLAG", - "QMAKE_LINK_SHLIB_CMD", - "QMAKE_LN_SHLIB", - "QMAKE_POST_LINK", - "QMAKE_PRE_LINK", - "QMAKE_PROJECT_NAME", - "QMAKE_MAC_SDK", - "QMAKE_MACOSX_DEPLOYMENT_TARGET", - "QMAKE_MAKEFILE", - "QMAKE_MOC_SRC", - "QMAKE_QMAKE", - "QMAKE_QT_DLL", - "QMAKE_RESOURCE_FLAGS", - "QMAKE_RPATH", - "QMAKE_RPATHDIR", - "QMAKE_RUN_CC", - "QMAKE_RUN_CC_IMP", - "QMAKE_RUN_CXX", - "QMAKE_RUN_CXX_IMP", - "QMAKE_TARGET", - "QMAKE_UIC", - "QT", - "QTPLUGIN", - "QT_VERSION", - "QT_MAJOR_VERSION", - "QT_MINOR_VERSION", - "QT_PATCH_VERSION", - "RCC_DIR", - "RC_FILE", - "REQUIRES", - "RESOURCES", - "RES_FILE", - "RSS_RULES", - "SIGNATURE_FILE", - "SOURCES", - "SRCMOC", - "STATECHARTS", - "SUBDIRS", - "TEMPLATE", - "TRANSLATIONS", - "UICIMPLS", - "UICOBJECTS", - "UI_DIR", - "UI_HEADERS_DIR", - "UI_SOURCES_DIR", - "VER_MAJ", - "VER_MIN", - "VER_PAT", - "VERSION", - "VPATH", - "YACCIMPLS", - "YACCOBJECTS", - "YACCSOURCES", - "_PRO_FILE_", - "_PRO_FILE_PWD_", - 0 -}; - -static const char *const functionKeywords[] = { - "basename", - "contains", - "count", - "dirname", - "error", - "eval", - "exists", - "find", - "for", - "include", - "infile", - "isEmpty", - "join", - "member", - "message", - "packagesExist", - "prompt", - "quote", - "replace", - "sprintf", - "system", - "unique", - "warning", - 0 -}; - -class ProFileKeywordsImplementation -{ -public: - static ProFileKeywordsImplementation *instance(); - QStringList variables(); - QStringList functions(); - bool isVariable(const QString &word); - bool isFunction(const QString &word); -private: - ProFileKeywordsImplementation(); - static ProFileKeywordsImplementation *m_instance; - QStringList m_variables; - QStringList m_functions; -}; - -ProFileKeywordsImplementation *ProFileKeywordsImplementation::m_instance = 0; - -ProFileKeywordsImplementation *ProFileKeywordsImplementation::instance() -{ - if (!m_instance) - m_instance = new ProFileKeywordsImplementation(); - return m_instance; -} - -QStringList ProFileKeywordsImplementation::variables() -{ - return m_variables; -} - -QStringList ProFileKeywordsImplementation::functions() -{ - return m_functions; -} - -bool ProFileKeywordsImplementation::isVariable(const QString &word) -{ - return m_variables.contains(word); -} - -bool ProFileKeywordsImplementation::isFunction(const QString &word) -{ - return m_functions.contains(word); -} - -ProFileKeywordsImplementation::ProFileKeywordsImplementation() -{ - for (uint i = 0; i < sizeof variableKeywords / sizeof variableKeywords[0] - 1; i++) - m_variables.append(QLatin1String(variableKeywords[i])); - for (uint i = 0; i < sizeof functionKeywords / sizeof functionKeywords[0] - 1; i++) - m_functions.append(QLatin1String(functionKeywords[i])); -} - -ProFileKeywords::ProFileKeywords() -{ -} - -QStringList ProFileKeywords::variables() -{ - return ProFileKeywordsImplementation::instance()->variables(); -} - -QStringList ProFileKeywords::functions() -{ - return ProFileKeywordsImplementation::instance()->functions(); -} - -bool ProFileKeywords::isVariable(const QString &word) -{ - return ProFileKeywordsImplementation::instance()->isVariable(word); -} - -bool ProFileKeywords::isFunction(const QString &word) -{ - return ProFileKeywordsImplementation::instance()->isFunction(word); -} diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index ae1b4ff64d..9b228041cb 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -63,7 +63,6 @@ HEADERS += \ librarydetailscontroller.h \ findqt4profiles.h \ qt4projectmanager_global.h \ - profilekeywords.h \ qt4targetsetupwidget.h \ buildconfigurationinfo.h \ winceqtversionfactory.h \ @@ -127,7 +126,6 @@ SOURCES += \ addlibrarywizard.cpp \ librarydetailscontroller.cpp \ findqt4profiles.cpp \ - profilekeywords.cpp \ qt4targetsetupwidget.cpp \ winceqtversionfactory.cpp \ winceqtversion.cpp \ diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.qbs b/src/plugins/qt4projectmanager/qt4projectmanager.qbs index a706b5070a..57502c1d0e 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.qbs +++ b/src/plugins/qt4projectmanager/qt4projectmanager.qbs @@ -52,8 +52,8 @@ QtcPlugin { "profilehighlighter.h", "profilehoverhandler.cpp", "profilehoverhandler.h", - "profilekeywords.cpp", - "profilekeywords.h", + "qmakeparser.cpp", + "qmakeparser.h", "qmakekitconfigwidget.cpp", "qmakekitconfigwidget.h", "qmakekitinformation.cpp", diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp new file mode 100644 index 0000000000..3fda0de0f2 --- /dev/null +++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "keywordscompletionassist.h" + +#include <texteditor/codeassist/iassistinterface.h> +#include <texteditor/codeassist/genericproposal.h> +#include <texteditor/codeassist/ifunctionhintproposalmodel.h> +#include <texteditor/codeassist/functionhintproposal.h> +#include <texteditor/codeassist/basicproposalitemlistmodel.h> +#include "completionsettings.h" +#include "texteditorsettings.h" +#include "basetexteditor.h" + +#include <QtGui/QTextCursor> + +using namespace TextEditor; + +// -------------------------- +// Keywords +// -------------------------- +Keywords::Keywords() +{ + +} + +// Note: variables and functions must be sorted +Keywords::Keywords(const QStringList &variabels, const QStringList &functions, const QMap<QString, QStringList> &functionArgs) + : m_variables(variabels), m_functions(functions), m_functionArgs(functionArgs) +{ + +} + +bool Keywords::isVariable(const QString &word) const +{ + return qBinaryFind(m_variables, word) != m_variables.constEnd(); +} + +bool Keywords::isFunction(const QString &word) const +{ + return qBinaryFind(m_functions, word) != m_functions.constEnd(); +} + +QStringList Keywords::variables() const +{ + return m_variables; +} + +QStringList Keywords::functions() const +{ + return m_functions; +} + +QStringList Keywords::argsForFunction(const QString &function) const +{ + return m_functionArgs.value(function); +} + + +// -------------------------- +// KeywordsAssistProposalItem +// -------------------------- +KeywordsAssistProposalItem::KeywordsAssistProposalItem(Keywords keywords) + : m_keywords(keywords) +{ +} + +KeywordsAssistProposalItem::~KeywordsAssistProposalItem() +{} + +bool KeywordsAssistProposalItem::prematurelyApplies(const QChar &c) const +{ + // only '(' in case of a function + if (c == QLatin1Char('(') && m_keywords.isFunction(text())) + return true; + return false; +} + +void KeywordsAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *editor, + int basePosition) const +{ + const CompletionSettings &settings = TextEditorSettings::instance()->completionSettings(); + + int replaceLength = editor->position() - basePosition; + QString toInsert = text(); + int cursorOffset = 0; + if (m_keywords.isFunction(toInsert) && settings.m_autoInsertBrackets) { + if (settings.m_spaceAfterFunctionName) { + if (editor->textAt(editor->position(), 2) == QLatin1String(" (")) { + cursorOffset = 2; + } else if (editor->characterAt(editor->position()) == QLatin1Char('(') + || editor->characterAt(editor->position()) == QLatin1Char(' ')) { + replaceLength += 1; + toInsert += QLatin1String(" ("); + } else { + toInsert += QLatin1String(" ()"); + cursorOffset = -1; + } + } else { + if (editor->characterAt(editor->position()) == QLatin1Char('(')) { + cursorOffset = 1; + } else { + toInsert += QLatin1String("()"); + cursorOffset = -1; + } + } + } + + editor->setCursorPosition(basePosition); + editor->replace(replaceLength, toInsert); + if (cursorOffset) + editor->setCursorPosition(editor->position() + cursorOffset); +} + +// ------------------------- +// KeywordsFunctionHintModel +// ------------------------- +KeywordsFunctionHintModel::KeywordsFunctionHintModel(const QStringList &functionSymbols) + : m_functionSymbols(functionSymbols) +{} + +KeywordsFunctionHintModel::~KeywordsFunctionHintModel() +{} + +void KeywordsFunctionHintModel::reset() +{} + +int KeywordsFunctionHintModel::size() const +{ + return m_functionSymbols.size(); +} + +QString KeywordsFunctionHintModel::text(int index) const +{ + return m_functionSymbols.at(index); +} + +int KeywordsFunctionHintModel::activeArgument(const QString &prefix) const +{ + Q_UNUSED(prefix); + return 1; +} + +// --------------------------------- +// KeywordsCompletionAssistProcessor +// --------------------------------- +KeywordsCompletionAssistProcessor::KeywordsCompletionAssistProcessor(Keywords keywords) + : m_startPosition(-1) + , m_variableIcon(QLatin1String(":/codemodel/images/keyword.png")) + , m_functionIcon(QLatin1String(":/codemodel/images/func.png")) + , m_keywords(keywords) +{} + +KeywordsCompletionAssistProcessor::~KeywordsCompletionAssistProcessor() +{} + +IAssistProposal *KeywordsCompletionAssistProcessor::perform(const IAssistInterface *interface) +{ + m_interface.reset(interface); + + if (isInComment()) + return 0; + + if (interface->reason() == IdleEditor && !acceptsIdleEditor()) + return 0; + + if (m_startPosition == -1) + m_startPosition = findStartOfName(); + + int nextCharPos = m_startPosition + m_word.length(); + if (m_keywords.isFunction(m_word) + && m_interface->characterAt(nextCharPos) == QLatin1Char('(')) { + QStringList functionSymbols = m_keywords.argsForFunction(m_word); + IFunctionHintProposalModel *model = + new KeywordsFunctionHintModel(functionSymbols); + IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model); + return proposal; + } else { + QList<TextEditor::BasicProposalItem *> items; + addWordsToProposalList(&items, m_keywords.variables(), m_variableIcon); + addWordsToProposalList(&items, m_keywords.functions(), m_functionIcon); + return new GenericProposal(m_startPosition, new BasicProposalItemListModel(items)); + } +} + +QChar KeywordsCompletionAssistProcessor::startOfCommentChar() const +{ + return QLatin1Char('#'); +} + +bool KeywordsCompletionAssistProcessor::acceptsIdleEditor() +{ + const int pos = m_interface->position(); + QChar characterUnderCursor = m_interface->characterAt(pos); + if (!characterUnderCursor.isLetterOrNumber()) { + m_startPosition = findStartOfName(); + if (pos - m_startPosition >= 3 && !isInComment()) + return true; + } + return false; +} + +int KeywordsCompletionAssistProcessor::findStartOfName(int pos) +{ + if (pos == -1) + pos = m_interface->position(); + + QChar chr = m_interface->characterAt(pos-1); + if (chr == QLatin1Char('(')) { + --pos; + } + // Skip to the start of a name + do { + chr = m_interface->characterAt(--pos); + } while (chr.isLetterOrNumber() || chr == QLatin1Char('_')); + + int start = ++pos; + m_word.clear(); + do { + m_word += m_interface->characterAt(pos); + chr = m_interface->characterAt(++pos); + } while ((chr.isLetterOrNumber() || chr == QLatin1Char('_')) + && chr != QLatin1Char('(')); + + return start; +} + +bool KeywordsCompletionAssistProcessor::isInComment() const +{ + QTextCursor tc(m_interface->textDocument()); + tc.setPosition(m_interface->position()); + tc.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); + const QString &lineBeginning = tc.selectedText(); + if (lineBeginning.contains(startOfCommentChar())) + return true; + return false; +} + +void KeywordsCompletionAssistProcessor::addWordsToProposalList(QList<BasicProposalItem *> *items, const QStringList &words, const QIcon &icon) +{ + if (!items) + return; + + for (int i = 0; i < words.count(); ++i) { + BasicProposalItem *item = new KeywordsAssistProposalItem(m_keywords); + item->setText(words.at(i)); + item->setIcon(icon); + items->append(item); + } +} + + diff --git a/src/plugins/texteditor/codeassist/keywordscompletionassist.h b/src/plugins/texteditor/codeassist/keywordscompletionassist.h new file mode 100644 index 0000000000..7c8f8eac66 --- /dev/null +++ b/src/plugins/texteditor/codeassist/keywordscompletionassist.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef KEYWORDSCOMPLETIONASSIST_H +#define KEYWORDSCOMPLETIONASSIST_H + +#include "iassistprocessor.h" +#include "basicproposalitem.h" +#include "ifunctionhintproposalmodel.h" + +#include <QtGui/QIcon> +#include <QtCore/QStringList> + +namespace TextEditor { + +class TEXTEDITOR_EXPORT Keywords +{ +public: + Keywords(); + Keywords(const QStringList &variabels, const QStringList &functions, const QMap<QString, QStringList> &functionArgs); + bool isVariable(const QString &word) const; + bool isFunction(const QString &word) const; + + QStringList variables() const; + QStringList functions() const; + QStringList argsForFunction(const QString &function) const; + +private: + QStringList m_variables; + QStringList m_functions; + QMap<QString, QStringList> m_functionArgs; +}; + +class TEXTEDITOR_EXPORT KeywordsAssistProposalItem : public TextEditor::BasicProposalItem +{ +public: + KeywordsAssistProposalItem(Keywords keywords); + virtual ~KeywordsAssistProposalItem(); + + virtual bool prematurelyApplies(const QChar &c) const; + virtual void applyContextualContent(TextEditor::BaseTextEditor *editor, + int basePosition) const; +private: + Keywords m_keywords; +}; + +class TEXTEDITOR_EXPORT KeywordsFunctionHintModel : public TextEditor::IFunctionHintProposalModel +{ +public: + KeywordsFunctionHintModel(const QStringList &functionSymbols); + virtual ~KeywordsFunctionHintModel(); + + virtual void reset(); + virtual int size() const; + virtual QString text(int index) const; + virtual int activeArgument(const QString &prefix) const; + +private: + QStringList m_functionSymbols; +}; + +class TEXTEDITOR_EXPORT KeywordsCompletionAssistProcessor : public TextEditor::IAssistProcessor +{ +public: + KeywordsCompletionAssistProcessor(Keywords keywords); + virtual ~KeywordsCompletionAssistProcessor(); + + virtual TextEditor::IAssistProposal *perform(const TextEditor::IAssistInterface *interface); + virtual QChar startOfCommentChar() const; + +private: + bool acceptsIdleEditor(); + int findStartOfName(int pos = -1); + bool isInComment() const; + void addWordsToProposalList(QList<BasicProposalItem *> *items, const QStringList &words, const QIcon &icon); + + int m_startPosition; + QString m_word; + QScopedPointer<const TextEditor::IAssistInterface> m_interface; + const QIcon m_variableIcon; + const QIcon m_functionIcon; + Keywords m_keywords; +}; + +} // TextEditor + +#endif // KEYWORDSCOMPLETIONASSISTPROCESSOR_H diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro index d123c07569..5840f6b61d 100644 --- a/src/plugins/texteditor/texteditor.pro +++ b/src/plugins/texteditor/texteditor.pro @@ -116,7 +116,8 @@ SOURCES += texteditorplugin.cpp \ codestyleeditor.cpp \ circularclipboard.cpp \ circularclipboardassist.cpp \ - itextmark.cpp + itextmark.cpp \ + codeassist/keywordscompletionassist.cpp HEADERS += texteditorplugin.h \ textfilewizard.h \ @@ -235,7 +236,8 @@ HEADERS += texteditorplugin.h \ basefilefind_p.h \ circularclipboard.h \ circularclipboardassist.h \ - itextmark.h + itextmark.h \ + codeassist/keywordscompletionassist.h FORMS += \ displaysettingspage.ui \ diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 3eaa4bb194..ef14c2500d 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -188,6 +188,9 @@ QtcPlugin { "ifunctionhintproposalmodel.h", "igenericproposalmodel.cpp", "igenericproposalmodel.h", + "ikeywords.h", + "keywordscompletionassist.cpp", + "keywordscompletionassist.h", "quickfixassistprocessor.cpp", "quickfixassistprocessor.h", "quickfixassistprovider.cpp", |