diff options
Diffstat (limited to 'src/plugins/cppeditor')
-rw-r--r-- | src/plugins/cppeditor/cppeditor.cpp | 47 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.h | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.pro | 6 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.qbs | 6 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorconstants.h | 3 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorplugin.cpp | 49 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorplugin.h | 7 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpppreprocessoradditionwidget.cpp | 171 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpppreprocessoradditionwidget.ui | 96 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpppreprocessordialog.cpp | 129 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpppreprocessordialog.h (renamed from src/plugins/cppeditor/cpppreprocessoradditionwidget.h) | 57 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpppreprocessordialog.ui | 109 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppquickfix_test.cpp | 180 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppquickfixes.cpp | 13 |
14 files changed, 510 insertions, 367 deletions
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 7b36de8cf0..0604edde96 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -34,7 +34,7 @@ #include "cppeditorplugin.h" #include "cppfollowsymbolundercursor.h" #include "cpphighlighter.h" -#include "cpppreprocessoradditionwidget.h" +#include "cpppreprocessordialog.h" #include "cppquickfixassistant.h" #include <coreplugin/actionmanager/actioncontainer.h> @@ -701,19 +701,15 @@ void CPPEditorWidget::selectAll() void CPPEditorWidget::setMimeType(const QString &mt) { - const QString &fileName = editor()->document()->filePath(); - // Check if this editor belongs to a project - QList<ProjectPart::Ptr> projectParts = m_modelManager->projectPart(fileName); - if (projectParts.isEmpty()) - projectParts = m_modelManager->projectPartFromDependencies(fileName); - if (!projectParts.isEmpty()) { - if (ProjectExplorer::Project *project = projectParts.first()->project) { - QByteArray additionalDefines = project->additionalCppDefines() - .value(projectParts.first()->projectFile).toByteArray(); - m_modelManager->cppEditorSupport(editor())->snapshotUpdater()->setEditorDefines( - additionalDefines); - } - } + const QString &filePath = editor()->document()->filePath(); + const QString &projectFile = ProjectExplorer::SessionManager::value( + QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX) + filePath).toString(); + const QByteArray &additionalDirectives = ProjectExplorer::SessionManager::value( + projectFile + QLatin1Char(',') + filePath).toByteArray(); + + QSharedPointer<SnapshotUpdater> updater + = m_modelManager->cppEditorSupport(editor())->snapshotUpdater(); + updater->setEditorDefines(additionalDirectives); BaseTextEditorWidget::setMimeType(mt); setObjCEnabled(mt == QLatin1String(CppTools::Constants::OBJECTIVE_C_SOURCE_MIMETYPE) @@ -1968,28 +1964,21 @@ void CPPEditorWidget::onCommentsSettingsChanged(const CppTools::CommentsSettings void CPPEditorWidget::showPreProcessorWidget() { const QString &fileName = editor()->document()->filePath(); - // Check if this editor belongs to a project + // Check if this editor belongs to a project QList<ProjectPart::Ptr> projectParts = m_modelManager->projectPart(fileName); if (projectParts.isEmpty()) projectParts = m_modelManager->projectPartFromDependencies(fileName); if (projectParts.isEmpty()) projectParts << m_modelManager->fallbackProjectPart(); - PreProcessorAdditionPopUp::instance()->show(this, projectParts); - - connect(PreProcessorAdditionPopUp::instance(), - SIGNAL(finished(QByteArray)), - SLOT(preProcessorWidgetFinished(QByteArray))); -} - -void CPPEditorWidget::preProcessorWidgetFinished(const QByteArray &additionalDefines) -{ - PreProcessorAdditionPopUp::instance()->disconnect(this); - QSharedPointer<SnapshotUpdater> updater - = m_modelManager->cppEditorSupport(editor())->snapshotUpdater(); - updater->setEditorDefines(additionalDefines); - updater->update(m_modelManager->workingCopy()); + CppPreProcessorDialog preProcessorDialog(this, projectParts); + if (preProcessorDialog.exec() == QDialog::Accepted) { + QSharedPointer<SnapshotUpdater> updater + = m_modelManager->cppEditorSupport(editor())->snapshotUpdater(); + updater->setEditorDefines(preProcessorDialog.additionalPreProcessorDirectives().toLatin1()); + updater->update(m_modelManager->workingCopy()); + } } #include <cppeditor.moc> diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 1a5fe51d37..ae1f57e31b 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -144,6 +144,7 @@ public Q_SLOTS: void renameSymbolUnderCursor(); void renameUsages(); void findUsages(); + void showPreProcessorWidget(); void renameUsagesNow(const QString &replacement = QString()); void semanticRehighlight(bool force = false); void highlighterStarted(QFuture<TextEditor::HighlightingResult> *highlighter, @@ -187,9 +188,6 @@ private Q_SLOTS: void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings); - void showPreProcessorWidget(); - void preProcessorWidgetFinished(const QByteArray &additionalDefines); - private: void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info); bool sortedOutline() const; diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index e0d9f7b0c4..64ffa94641 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -25,7 +25,7 @@ HEADERS += cppeditorplugin.h \ cppincludehierarchyitem.h \ cppincludehierarchytreeview.h \ cppvirtualfunctionassistprovider.h \ - cpppreprocessoradditionwidget.h + cpppreprocessordialog.h SOURCES += cppeditorplugin.cpp \ cppautocompleter.cpp \ @@ -49,7 +49,7 @@ SOURCES += cppeditorplugin.cpp \ cppincludehierarchyitem.cpp \ cppincludehierarchytreeview.cpp \ cppvirtualfunctionassistprovider.cpp \ - cpppreprocessoradditionwidget.cpp + cpppreprocessordialog.cpp RESOURCES += cppeditor.qrc @@ -67,4 +67,4 @@ equals(TEST, 1) { } FORMS += \ - cpppreprocessoradditionwidget.ui + cpppreprocessordialog.ui diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 7ca766b74c..d8c465ad55 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -50,9 +50,9 @@ QtcPlugin { "cppincludehierarchytreeview.h", "cppoutline.cpp", "cppoutline.h", - "cpppreprocessoradditionwidget.cpp", - "cpppreprocessoradditionwidget.h", - "cpppreprocessoradditionwidget.ui", + "cpppreprocessordialog.cpp", + "cpppreprocessordialog.h", + "cpppreprocessordialog.ui", "cppquickfixassistant.cpp", "cppquickfixassistant.h", "cppquickfix.cpp", diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h index ae87b13ead..378789f911 100644 --- a/src/plugins/cppeditor/cppeditorconstants.h +++ b/src/plugins/cppeditor/cppeditorconstants.h @@ -41,6 +41,7 @@ const char SWITCH_DECLARATION_DEFINITION[] = "CppEditor.SwitchDeclarationDefinit const char OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT[] = "CppEditor.OpenDeclarationDefinitionInNextSplit"; const char RENAME_SYMBOL_UNDER_CURSOR[] = "CppEditor.RenameSymbolUnderCursor"; const char FIND_USAGES[] = "CppEditor.FindUsages"; +const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog"; const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup"; const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel"; @@ -62,6 +63,8 @@ const char WIZARD_TR_CATEGORY[] = QT_TRANSLATE_NOOP("CppEditor", "C++"); const char CPP_SNIPPETS_GROUP_ID[] = "C++"; +const char CPP_PREPROCESSOR_PROJECT_PREFIX[] = "CppPreprocessorProject-"; + } // namespace Constants } // namespace CppEditor diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index 4ffa0d93d6..b9c66de4a1 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -210,6 +210,13 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err contextMenu->addAction(cmd); cppToolsMenu->addAction(cmd); + QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives"), this); + cmd = ActionManager::registerAction(openPreprocessorDialog, + Constants::OPEN_PREPROCESSOR_DIALOG, context); + cmd->setDefaultKeySequence(QKeySequence()); + connect(openPreprocessorDialog, SIGNAL(triggered()), this, SLOT(showPreProcessorDialog())); + cppToolsMenu->addAction(cmd); + QAction *switchDeclarationDefinition = new QAction(tr("Switch Between Function Declaration/Definition"), this); cmd = ActionManager::registerAction(switchDeclarationDefinition, Constants::SWITCH_DECLARATION_DEFINITION, context, true); @@ -326,32 +333,39 @@ ExtensionSystem::IPlugin::ShutdownFlag CppEditorPlugin::aboutToShutdown() return SynchronousShutdown; } +static CPPEditorWidget *currentCppEditorWidget() +{ + return qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); +} + void CppEditorPlugin::switchDeclarationDefinition() { - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); - if (editor) - editor->switchDeclarationDefinition(/*inNextSplit*/ false); + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->switchDeclarationDefinition(/*inNextSplit*/ false); } void CppEditorPlugin::openDeclarationDefinitionInNextSplit() { - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); - if (editor) - editor->switchDeclarationDefinition(/*inNextSplit*/ true); + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->switchDeclarationDefinition(/*inNextSplit*/ true); } void CppEditorPlugin::renameSymbolUnderCursor() { - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); - if (editor) - editor->renameSymbolUnderCursor(); + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->renameSymbolUnderCursor(); } void CppEditorPlugin::findUsages() { - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); - if (editor) - editor->findUsages(); + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->findUsages(); +} + +void CppEditorPlugin::showPreProcessorDialog() +{ + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->showPreProcessorWidget(); } void CppEditorPlugin::onTaskStarted(Core::Id type) @@ -381,14 +395,13 @@ void CppEditorPlugin::currentEditorChanged(IEditor *editor) if (!editor) return; - if (CPPEditorWidget *textEditor = qobject_cast<CPPEditorWidget *>(editor->widget())) - textEditor->semanticRehighlight(/*force = */ true); + if (CPPEditorWidget *editorWidget = currentCppEditorWidget()) + editorWidget->semanticRehighlight(/*force = */ true); } void CppEditorPlugin::openTypeHierarchy() { - CPPEditorWidget *editor = qobject_cast<CPPEditorWidget*>(EditorManager::currentEditor()->widget()); - if (editor) { + if (currentCppEditorWidget()) { NavigationWidget *navigation = NavigationWidget::instance(); navigation->activateSubWidget(Constants::TYPE_HIERARCHY_ID); emit typeHierarchyRequested(); @@ -397,9 +410,7 @@ void CppEditorPlugin::openTypeHierarchy() void CppEditorPlugin::openIncludeHierarchy() { - CPPEditorWidget *editor - = qobject_cast<CPPEditorWidget*>(Core::EditorManager::currentEditor()->widget()); - if (editor) { + if (currentCppEditorWidget()) { Core::NavigationWidget *navigation = Core::NavigationWidget::instance(); navigation->activateSubWidget(Core::Id(Constants::INCLUDE_HIERARCHY_ID)); emit includeHierarchyRequested(); diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index c1eb519de1..33e32593f4 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -81,6 +81,7 @@ public slots: void openTypeHierarchy(); void openIncludeHierarchy(); void findUsages(); + void showPreProcessorDialog(); void renameSymbolUnderCursor(); void switchDeclarationDefinition(); @@ -153,6 +154,12 @@ private slots: void test_doxygen_comments_cpp_styleA_indented_continuation(); void test_doxygen_comments_cpp_styleA_corner_case(); + void test_quickfix_CompleteSwitchCaseStatement_basic1(); + void test_quickfix_CompleteSwitchCaseStatement_basic2(); + void test_quickfix_CompleteSwitchCaseStatement_oneValueMissing(); + void test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_1(); + void test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_2(); + void test_quickfix_GenerateGetterSetter_basicGetterWithPrefix(); void test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespace(); void test_quickfix_GenerateGetterSetter_basicGetterWithPrefixAndNamespaceToCpp(); diff --git a/src/plugins/cppeditor/cpppreprocessoradditionwidget.cpp b/src/plugins/cppeditor/cpppreprocessoradditionwidget.cpp deleted file mode 100644 index 7762af59cc..0000000000 --- a/src/plugins/cppeditor/cpppreprocessoradditionwidget.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 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 "cpppreprocessoradditionwidget.h" -#include "ui_cpppreprocessoradditionwidget.h" - -#include "cppsnippetprovider.h" - -#include <utils/tooltip/tipcontents.h> -#include <utils/tooltip/tooltip.h> -#include <projectexplorer/project.h> - -#include <QDebug> - -using namespace CppEditor::Internal; - -PreProcessorAdditionWidget::PreProcessorAdditionWidget(QWidget *parent) - : QWidget(parent) - , ui(new Ui::CppPreProcessorAdditionWidget) -{ - ui->setupUi(this); - CppEditor::Internal::CppSnippetProvider prov; - prov.decorateEditor(ui->additionalEdit); - setAttribute(Qt::WA_QuitOnClose, false); - setFocusPolicy(Qt::StrongFocus); - ui->additionalEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); -} - -PreProcessorAdditionWidget::~PreProcessorAdditionWidget() -{ - emit finished(); - delete ui; -} - -PreProcessorAdditionPopUp *PreProcessorAdditionPopUp::instance() -{ - static PreProcessorAdditionPopUp inst; - return &inst; -} - -void PreProcessorAdditionPopUp::show(QWidget *parent, - const QList<CppTools::ProjectPart::Ptr> &projectParts) -{ - m_widget = new PreProcessorAdditionWidget(); - m_originalPartAdditions.clear(); - foreach (CppTools::ProjectPart::Ptr projectPart, projectParts) { - ProjectPartAddition addition; - addition.projectPart = projectPart; - m_widget->ui->projectComboBox->addItem(projectPart->displayName); - addition.additionalDefines = projectPart->project - ->additionalCppDefines().value(projectPart->projectFile).toByteArray(); - m_originalPartAdditions << addition; - } - m_partAdditions = m_originalPartAdditions; - - m_widget->ui->additionalEdit->setPlainText(QLatin1String( - m_partAdditions[m_widget->ui->projectComboBox->currentIndex()].additionalDefines)); - - QPoint pos = parent->mapToGlobal(parent->rect().topRight()); - pos.setX(pos.x() - m_widget->width()); - showInternal(pos, Utils::WidgetContent(m_widget, true), parent, QRect()); - - connect(m_widget->ui->additionalEdit, SIGNAL(textChanged()), SLOT(textChanged())); - connect(m_widget->ui->projectComboBox, SIGNAL(currentIndexChanged(int)), - SLOT(projectChanged(int))); - connect(m_widget, SIGNAL(finished()), SLOT(finish())); - connect(m_widget->ui->buttonBox, SIGNAL(accepted()), SLOT(apply())); - connect(m_widget->ui->buttonBox, SIGNAL(rejected()), SLOT(cancel())); -} - -bool PreProcessorAdditionPopUp::eventFilter(QObject *o, QEvent *event) -{ - // Filter out some events that would hide the widget, when they would be handled by the ToolTip - switch (event->type()) { - case QEvent::Leave: - // This event would hide the ToolTip because the view isn't a child of the WidgetContent - if (m_widget->ui->projectComboBox->view() == qApp->focusWidget()) - return false; - break; - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::ShortcutOverride: - // Catch the escape key to close the widget - if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) { - hideTipImmediately(); - return true; - } - break; - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::Wheel: - // This event would hide the ToolTip because the viewport isn't a child of the WidgetContent - if (o == m_widget->ui->projectComboBox->view()->viewport()) - return false; - break; - default: - break; - } - return Utils::ToolTip::eventFilter(o, event); -} - -void PreProcessorAdditionPopUp::textChanged() -{ - m_partAdditions[m_widget->ui->projectComboBox->currentIndex()].additionalDefines - = m_widget->ui->additionalEdit->toPlainText().toLatin1(); -} - - -void PreProcessorAdditionPopUp::finish() -{ - m_widget->disconnect(this); - foreach (ProjectPartAddition partAddition, m_originalPartAdditions) { - QVariantMap settings = partAddition.projectPart->project->additionalCppDefines(); - if (!settings[partAddition.projectPart->projectFile].toString().isEmpty() - && !partAddition.additionalDefines.isEmpty()) { - settings[partAddition.projectPart->projectFile] = partAddition.additionalDefines; - partAddition.projectPart->project->setAdditionalCppDefines(settings); - } - } - emit finished(m_originalPartAdditions.value(m_widget->ui->projectComboBox->currentIndex()) - .additionalDefines); -} - -void PreProcessorAdditionPopUp::projectChanged(int index) -{ - m_widget->ui->additionalEdit->setPlainText( - QLatin1String(m_partAdditions[index].additionalDefines)); -} - -void PreProcessorAdditionPopUp::apply() -{ - m_originalPartAdditions = m_partAdditions; - hideTipImmediately(); -} - -void PreProcessorAdditionPopUp::cancel() -{ - m_partAdditions = m_originalPartAdditions; - hideTipImmediately(); -} - -PreProcessorAdditionPopUp::PreProcessorAdditionPopUp() - : m_widget(0) -{} diff --git a/src/plugins/cppeditor/cpppreprocessoradditionwidget.ui b/src/plugins/cppeditor/cpppreprocessoradditionwidget.ui deleted file mode 100644 index 101ba17d3f..0000000000 --- a/src/plugins/cppeditor/cpppreprocessoradditionwidget.ui +++ /dev/null @@ -1,96 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>CppEditor::Internal::CppPreProcessorAdditionWidget</class> - <widget class="QWidget" name="CppEditor::Internal::CppPreProcessorAdditionWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>415</width> - <height>395</height> - </rect> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="windowTitle"> - <string>PP</string> - </property> - <property name="autoFillBackground"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="projectLabel"> - <property name="text"> - <string>Project:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="projectComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="Line" name="separator"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="additionalLabel"> - <property name="text"> - <string>Additional</string> - </property> - </widget> - </item> - <item> - <widget class="TextEditor::SnippetEditorWidget" name="additionalEdit"/> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>TextEditor::SnippetEditorWidget</class> - <extends>QPlainTextEdit</extends> - <header>texteditor/snippets/snippeteditor.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/src/plugins/cppeditor/cpppreprocessordialog.cpp b/src/plugins/cppeditor/cpppreprocessordialog.cpp new file mode 100644 index 0000000000..e964962555 --- /dev/null +++ b/src/plugins/cppeditor/cpppreprocessordialog.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "cpppreprocessordialog.h" +#include "ui_cpppreprocessordialog.h" + +#include "cppeditor.h" +#include "cppeditorconstants.h" +#include "cppsnippetprovider.h" + +#include <projectexplorer/session.h> + +using namespace CppEditor::Internal; + +static bool projectPartLessThan(const CppTools::ProjectPart::Ptr &projectPart1, + const CppTools::ProjectPart::Ptr &projectPart2) +{ + return projectPart1->displayName < projectPart2->displayName; +} + +CppPreProcessorDialog::CppPreProcessorDialog(CPPEditorWidget *editorWidget, + const QList<CppTools::ProjectPart::Ptr> &projectParts) + : QDialog(editorWidget) + , m_ui(new Ui::CppPreProcessorDialog()) + , m_filePath(editorWidget->editor()->document()->filePath()) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + m_ui->setupUi(this); + m_ui->editorLabel->setText(m_ui->editorLabel->text().arg(QFileInfo(m_filePath).fileName())); + m_ui->editWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + CppSnippetProvider().decorateEditor(m_ui->editWidget); + + const QString ¤tProjectFile = ProjectExplorer::SessionManager::value( + QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX) + m_filePath).toString(); + int currentIndex = 0; + + QList<CppTools::ProjectPart::Ptr> sortedProjectParts(projectParts); + qStableSort(sortedProjectParts.begin(), sortedProjectParts.end(), projectPartLessThan); + + foreach (CppTools::ProjectPart::Ptr projectPart, sortedProjectParts) { + m_ui->projectComboBox->addItem(projectPart->displayName); + ProjectPartAddition addition; + addition.projectPart = projectPart; + addition.additionalDirectives = ProjectExplorer::SessionManager::value( + projectPart->projectFile + QLatin1Char(',') + m_filePath).toString(); + if (projectPart->projectFile == currentProjectFile) + currentIndex = m_ui->projectComboBox->count() - 1; + m_partAdditions << addition; + } + if (m_ui->projectComboBox->count() <= 1) + m_ui->projectComboBox->setEnabled(false); + m_ui->projectComboBox->setCurrentIndex(currentIndex); + m_ui->editWidget->setPlainText(m_partAdditions.value(currentIndex).additionalDirectives); + + connect(m_ui->projectComboBox, SIGNAL(currentIndexChanged(int)), SLOT(projectChanged(int))); + connect(m_ui->editWidget, SIGNAL(textChanged()), SLOT(textChanged())); +} + +CppPreProcessorDialog::~CppPreProcessorDialog() +{ + delete m_ui; +} + +int CppPreProcessorDialog::exec() +{ + if (QDialog::exec() == Rejected) + return Rejected; + + ProjectExplorer::SessionManager::setValue( + QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX) + m_filePath, + m_partAdditions[m_ui->projectComboBox->currentIndex()].projectPart->projectFile); + + foreach (ProjectPartAddition partAddition, m_partAdditions) { + const QString &previousDirectives = ProjectExplorer::SessionManager::value( + partAddition.projectPart->projectFile + + QLatin1Char(',') + + m_filePath).toString(); + if (previousDirectives != partAddition.additionalDirectives) { + ProjectExplorer::SessionManager::setValue( + partAddition.projectPart->projectFile + QLatin1Char(',') + m_filePath, + partAddition.additionalDirectives); + } + } + return Accepted; +} + +QString CppPreProcessorDialog::additionalPreProcessorDirectives() const +{ + return m_ui->editWidget->toPlainText(); +} + +void CppPreProcessorDialog::projectChanged(int index) +{ + m_ui->editWidget->setPlainText(m_partAdditions[index].additionalDirectives); +} + +void CppPreProcessorDialog::textChanged() +{ + m_partAdditions[m_ui->projectComboBox->currentIndex()].additionalDirectives + = m_ui->editWidget->toPlainText(); +} diff --git a/src/plugins/cppeditor/cpppreprocessoradditionwidget.h b/src/plugins/cppeditor/cpppreprocessordialog.h index 828805ca1d..c56e397fe1 100644 --- a/src/plugins/cppeditor/cpppreprocessoradditionwidget.h +++ b/src/plugins/cppeditor/cpppreprocessordialog.h @@ -27,70 +27,47 @@ ** ****************************************************************************/ -#ifndef CPPPREPROCESSORADDITIONWIDGET_H -#define CPPPREPROCESSORADDITIONWIDGET_H +#ifndef CPPPREPROCESSORDIALOG_H +#define CPPPREPROCESSORDIALOG_H #include <cpptools/cppmodelmanagerinterface.h> -#include <utils/tooltip/tooltip.h> -#include <QWidget> -#include <QVariantMap> -#include <QPointer> +#include <QDialog> namespace CppEditor { namespace Internal { -namespace Ui { class CppPreProcessorAdditionWidget; } +namespace Ui { class CppPreProcessorDialog; } -class PreProcessorAdditionWidget : public QWidget -{ - Q_OBJECT - -public: - explicit PreProcessorAdditionWidget(QWidget *parent = 0); - ~PreProcessorAdditionWidget(); - Ui::CppPreProcessorAdditionWidget *ui; +class CPPEditorWidget; -signals: - void finished(); -}; - -class PreProcessorAdditionPopUp : public Utils::ToolTip +class CppPreProcessorDialog : public QDialog { Q_OBJECT public: - ~PreProcessorAdditionPopUp(){} - static PreProcessorAdditionPopUp *instance(); - - void show(QWidget *parent, const QList<CppTools::ProjectPart::Ptr> &projectPartAdditions); - bool eventFilter(QObject *o, QEvent *event); + explicit CppPreProcessorDialog(CPPEditorWidget *editorWidget, + const QList<CppTools::ProjectPart::Ptr> &projectParts); + ~CppPreProcessorDialog(); -signals: - void finished(const QByteArray &additionalDefines); + int exec(); + QString additionalPreProcessorDirectives() const; private slots: - void textChanged(); - void finish(); void projectChanged(int index); - void apply(); - void cancel(); - -protected: - explicit PreProcessorAdditionPopUp(); + void textChanged(); private: struct ProjectPartAddition { CppTools::ProjectPart::Ptr projectPart; - QByteArray additionalDefines; + QString additionalDirectives; }; - PreProcessorAdditionWidget* m_widget; - QList<ProjectPartAddition> m_originalPartAdditions; + Ui::CppPreProcessorDialog *m_ui; QList<ProjectPartAddition> m_partAdditions; - + QString m_filePath; }; -} // namespace CPPEditor } // namespace Internal +} // namespace CPPEditor -#endif // CPPPREPROCESSORADDITIONWIDGET_H +#endif // CPPPREPROCESSORDIALOG_H diff --git a/src/plugins/cppeditor/cpppreprocessordialog.ui b/src/plugins/cppeditor/cpppreprocessordialog.ui new file mode 100644 index 0000000000..28c7b5f47b --- /dev/null +++ b/src/plugins/cppeditor/cpppreprocessordialog.ui @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CppEditor::Internal::CppPreProcessorDialog</class> + <widget class="QDialog" name="CppEditor::Internal::CppPreProcessorDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Additional C++ Preprocess Directives</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="projectLabel"> + <property name="text"> + <string>Project:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="projectComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="separator"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="editorLabel"> + <property name="text"> + <string>Additional C++ Preprocessor Directives for %1:</string> + </property> + </widget> + </item> + <item> + <widget class="TextEditor::SnippetEditorWidget" name="editWidget"/> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>TextEditor::SnippetEditorWidget</class> + <extends>QPlainTextEdit</extends> + <header location="global">texteditor/snippets/snippeteditor.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>CppEditor::Internal::CppPreProcessorDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>CppEditor::Internal::CppPreProcessorDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 31c4b6513f..55fad435e7 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -349,6 +349,186 @@ private: } // anonymous namespace +/// Checks: All enum values are added as case statements for a blank switch. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_basic1() +{ + const QByteArray original = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " @switch (t) {\n" + " }\n" + "}\n"; + ; + const QByteArray expected = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " switch (t) {\n" + " case V1:\n" + " break;\n" + " case V2:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + +/// Checks: All enum values are added as case statements for a blank switch with a default case. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_basic2() +{ + const QByteArray original = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " @switch (t) {\n" + " default:\n" + " break;\n" + " }\n" + "}\n"; + ; + const QByteArray expected = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " switch (t) {\n" + " case V1:\n" + " break;\n" + " case V2:\n" + " break;\n" + " default:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + +/// Checks: The missing enum value is added. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_oneValueMissing() +{ + const QByteArray original = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " @switch (t) {\n" + " case V2:\n" + " break;\n" + " default:\n" + " break;\n" + " }\n" + "}\n"; + ; + const QByteArray expected = + "enum EnumType { V1, V2 };\n" + "\n" + "void f()\n" + "{\n" + " EnumType t;\n" + " switch (t) {\n" + " case V1:\n" + " break;\n" + " case V2:\n" + " break;\n" + " default:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + +/// Checks: Find the correct enum type despite there being a declaration with the same name. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_1() +{ + const QByteArray original = + "enum test { TEST_1, TEST_2 };\n" + "\n" + "void f() {\n" + " enum test test;\n" + " @switch (test) {\n" + " }\n" + "}\n" + ; + const QByteArray expected = + "enum test { TEST_1, TEST_2 };\n" + "\n" + "void f() {\n" + " enum test test;\n" + " switch (test) {\n" + " case TEST_1:\n" + " break;\n" + " case TEST_2:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + +/// Checks: Find the correct enum type despite there being a declaration with the same name. +void CppEditorPlugin::test_quickfix_CompleteSwitchCaseStatement_QTCREATORBUG10366_2() +{ + const QByteArray original = + "enum test1 { Wrong11, Wrong12 };\n" + "enum test { Right1, Right2 };\n" + "enum test2 { Wrong21, Wrong22 };\n" + "\n" + "int main() {\n" + " enum test test;\n" + " @switch (test) {\n" + " }\n" + "}\n" + ; + const QByteArray expected = + "enum test1 { Wrong11, Wrong12 };\n" + "enum test { Right1, Right2 };\n" + "enum test2 { Wrong21, Wrong22 };\n" + "\n" + "int main() {\n" + " enum test test;\n" + " switch (test) {\n" + " case Right1:\n" + " break;\n" + " case Right2:\n" + " break;\n" + " }\n" + "}\n" + "\n" + ; + + CompleteSwitchCaseStatement factory; + TestCase data(original, expected); + data.run(&factory); +} + /// Checks: /// 1. If the name does not start with ("m_" or "_") and does not /// end with "_", we are forced to prefix the getter with "get". diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index dcdd879686..6956cb9c78 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -2295,9 +2295,16 @@ Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt) if (Enum *e = type->asEnumType()) return e; if (const NamedType *namedType = type->asNamedType()) { - const QList<LookupItem> candidates = - ctxt.lookup(namedType->name(), result.scope()); - return findEnum(candidates, ctxt); + if (ClassOrNamespace *con = ctxt.lookupType(namedType->name(), result.scope())) { + const QList<Enum *> enums = con->unscopedEnums(); + const Name *referenceName = namedType->name(); + foreach (Enum *e, enums) { + if (const Name *candidateName = e->name()) { + if (candidateName->isEqualTo(referenceName)) + return e; + } + } + } } } |