forked from qt-creator/qt-creator
		
	C++: Automatic Doxygen comment blocks generation
This improves our completion support for documentation comments. It's now possible to have a Doxygen block generated when hitting enter after a /** or /*! comment start. A couple other related options are also available. Task-number: QTCREATORBUG-2752 Task-number: QTCREATORBUG-3165 Change-Id: I1c81c0b4b370eb1d409ef72a9c7f22c357f202f4 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@nokia.com> Reviewed-by: Christian Kamm <christian.d.kamm@nokia.com>
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/plugins/cpptools/commentssettings.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/plugins/cpptools/commentssettings.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
#include "commentssettings.h"
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QSettings>
 | 
			
		||||
 | 
			
		||||
using namespace CppTools;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
const char kDocumentationCommentsGroup[] = "DocumentationComments";
 | 
			
		||||
const char kEnableDoxygenBlocks[] = "EnableDoxygenBlocks";
 | 
			
		||||
const char kGenerateBrief[] = "GenerateBrief";
 | 
			
		||||
const char kAddLeadingAsterisks[] = "AddLeadingAsterisks";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CommentsSettings::CommentsSettings()
 | 
			
		||||
    : m_enableDoxygen(true)
 | 
			
		||||
    , m_generateBrief(true)
 | 
			
		||||
    , m_leadingAsterisks(true)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void CommentsSettings::toSettings(const QString &category, QSettings *s) const
 | 
			
		||||
{
 | 
			
		||||
    s->beginGroup(category + QLatin1String(kDocumentationCommentsGroup));
 | 
			
		||||
    s->setValue(QLatin1String(kEnableDoxygenBlocks), m_enableDoxygen);
 | 
			
		||||
    s->setValue(QLatin1String(kGenerateBrief), m_generateBrief);
 | 
			
		||||
    s->setValue(QLatin1String(kAddLeadingAsterisks), m_leadingAsterisks);
 | 
			
		||||
    s->endGroup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CommentsSettings::fromSettings(const QString &category, QSettings *s)
 | 
			
		||||
{
 | 
			
		||||
    s->beginGroup(category + QLatin1String(kDocumentationCommentsGroup));
 | 
			
		||||
    m_enableDoxygen = s->value(QLatin1String(kEnableDoxygenBlocks), true).toBool();
 | 
			
		||||
    m_generateBrief = m_enableDoxygen
 | 
			
		||||
            && s->value(QLatin1String(kGenerateBrief), true).toBool();
 | 
			
		||||
    m_leadingAsterisks = s->value(QLatin1String(kAddLeadingAsterisks), true).toBool();
 | 
			
		||||
    s->endGroup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommentsSettings::equals(const CommentsSettings &other) const
 | 
			
		||||
{
 | 
			
		||||
    return m_enableDoxygen == other.m_enableDoxygen
 | 
			
		||||
            && m_generateBrief == other.m_generateBrief
 | 
			
		||||
            && m_leadingAsterisks == other.m_leadingAsterisks;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								src/plugins/cpptools/commentssettings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/plugins/cpptools/commentssettings.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#ifndef COMMENTSSETTINGS_H
 | 
			
		||||
#define COMMENTSSETTINGS_H
 | 
			
		||||
 | 
			
		||||
#include "cpptools_global.h"
 | 
			
		||||
 | 
			
		||||
QT_BEGIN_NAMESPACE
 | 
			
		||||
class QSettings;
 | 
			
		||||
QT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
 | 
			
		||||
class CPPTOOLS_EXPORT CommentsSettings
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    CommentsSettings();
 | 
			
		||||
 | 
			
		||||
    void toSettings(const QString &category, QSettings *s) const;
 | 
			
		||||
    void fromSettings(const QString &category, QSettings *s);
 | 
			
		||||
 | 
			
		||||
    bool equals(const CommentsSettings &other) const;
 | 
			
		||||
 | 
			
		||||
    bool m_enableDoxygen;
 | 
			
		||||
    bool m_generateBrief;
 | 
			
		||||
    bool m_leadingAsterisks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool operator==(const CommentsSettings &a, const CommentsSettings &b)
 | 
			
		||||
{ return a.equals(b); }
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const CommentsSettings &a, const CommentsSettings &b)
 | 
			
		||||
{ return !(a == b); }
 | 
			
		||||
 | 
			
		||||
} // namespace CppTools
 | 
			
		||||
 | 
			
		||||
#endif // COMMENTSSETTINGS_H
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include "completionsettingspage.h"
 | 
			
		||||
#include "ui_completionsettingspage.h"
 | 
			
		||||
#include "cpptoolsconstants.h"
 | 
			
		||||
 | 
			
		||||
#include <coreplugin/icore.h>
 | 
			
		||||
#include <extensionsystem/pluginmanager.h>
 | 
			
		||||
@@ -40,11 +41,16 @@
 | 
			
		||||
#include <QtCore/QTextStream>
 | 
			
		||||
#include <QtCore/QCoreApplication>
 | 
			
		||||
 | 
			
		||||
using namespace CppTools;
 | 
			
		||||
using namespace CppTools::Internal;
 | 
			
		||||
using namespace CppTools::Constants;
 | 
			
		||||
 | 
			
		||||
CompletionSettingsPage::CompletionSettingsPage()
 | 
			
		||||
    : m_page(0)
 | 
			
		||||
CompletionSettingsPage::CompletionSettingsPage(QObject *parent)
 | 
			
		||||
    : TextEditor::TextEditorOptionsPage(parent)
 | 
			
		||||
    , m_page(0)
 | 
			
		||||
{
 | 
			
		||||
    if (QSettings *s = Core::ICore::instance()->settings())
 | 
			
		||||
        m_commentsSettings.fromSettings(QLatin1String(CPPTOOLS_SETTINGSGROUP), s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CompletionSettingsPage::~CompletionSettingsPage()
 | 
			
		||||
@@ -103,6 +109,9 @@ QWidget *CompletionSettingsPage::createPage(QWidget *parent)
 | 
			
		||||
    m_page->surroundSelectedText->setChecked(settings.m_surroundingAutoBrackets);
 | 
			
		||||
    m_page->partiallyComplete->setChecked(settings.m_partiallyComplete);
 | 
			
		||||
    m_page->spaceAfterFunctionName->setChecked(settings.m_spaceAfterFunctionName);
 | 
			
		||||
    m_page->enableDoxygenCheckBox->setChecked(m_commentsSettings.m_enableDoxygen);
 | 
			
		||||
    m_page->generateBriefCheckBox->setChecked(m_commentsSettings.m_generateBrief);
 | 
			
		||||
    m_page->leadingAsterisksCheckBox->setChecked(m_commentsSettings.m_leadingAsterisks);
 | 
			
		||||
 | 
			
		||||
    if (m_searchKeywords.isEmpty()) {
 | 
			
		||||
        QTextStream(&m_searchKeywords) << m_page->caseSensitivityLabel->text()
 | 
			
		||||
@@ -110,10 +119,15 @@ QWidget *CompletionSettingsPage::createPage(QWidget *parent)
 | 
			
		||||
                << ' ' << m_page->surroundSelectedText->text()
 | 
			
		||||
                << ' ' << m_page->completionTriggerLabel->text()
 | 
			
		||||
                << ' ' << m_page->partiallyComplete->text()
 | 
			
		||||
                << ' ' << m_page->spaceAfterFunctionName->text();
 | 
			
		||||
                << ' ' << m_page->spaceAfterFunctionName->text()
 | 
			
		||||
                << ' ' << m_page->enableDoxygenCheckBox->text()
 | 
			
		||||
                << ' ' << m_page->generateBriefCheckBox->text()
 | 
			
		||||
                << ' ' << m_page->leadingAsterisksCheckBox->text();
 | 
			
		||||
        m_searchKeywords.remove(QLatin1Char('&'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_page->generateBriefCheckBox->setEnabled(m_page->enableDoxygenCheckBox->isChecked());
 | 
			
		||||
 | 
			
		||||
    return w;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -130,6 +144,17 @@ void CompletionSettingsPage::apply()
 | 
			
		||||
    settings.m_spaceAfterFunctionName = m_page->spaceAfterFunctionName->isChecked();
 | 
			
		||||
 | 
			
		||||
    TextEditor::TextEditorSettings::instance()->setCompletionSettings(settings);
 | 
			
		||||
 | 
			
		||||
    if (!requireCommentsSettingsUpdate())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    m_commentsSettings.m_enableDoxygen = m_page->enableDoxygenCheckBox->isChecked();
 | 
			
		||||
    m_commentsSettings.m_generateBrief = m_page->generateBriefCheckBox->isChecked();
 | 
			
		||||
    m_commentsSettings.m_leadingAsterisks = m_page->leadingAsterisksCheckBox->isChecked();
 | 
			
		||||
    if (QSettings *s = Core::ICore::instance()->settings())
 | 
			
		||||
        m_commentsSettings.toSettings(QLatin1String(CPPTOOLS_SETTINGSGROUP), s);
 | 
			
		||||
 | 
			
		||||
    emit commentsSettingsChanged(m_commentsSettings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CompletionSettingsPage::matches(const QString &s) const
 | 
			
		||||
@@ -168,3 +193,15 @@ void CompletionSettingsPage::finish()
 | 
			
		||||
    delete m_page;
 | 
			
		||||
    m_page = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CommentsSettings &CompletionSettingsPage::commentsSettings() const
 | 
			
		||||
{
 | 
			
		||||
    return m_commentsSettings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CompletionSettingsPage::requireCommentsSettingsUpdate() const
 | 
			
		||||
{
 | 
			
		||||
    return m_commentsSettings.m_enableDoxygen != m_page->enableDoxygenCheckBox->isChecked()
 | 
			
		||||
        || m_commentsSettings.m_generateBrief != m_page->generateBriefCheckBox->isChecked()
 | 
			
		||||
        || m_commentsSettings.m_leadingAsterisks != m_page->leadingAsterisksCheckBox->isChecked();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,13 +33,17 @@
 | 
			
		||||
#ifndef COMPLETIONSETTINGSPAGE_H
 | 
			
		||||
#define COMPLETIONSETTINGSPAGE_H
 | 
			
		||||
 | 
			
		||||
#include "commentssettings.h"
 | 
			
		||||
 | 
			
		||||
#include <texteditor/completionsettings.h>
 | 
			
		||||
#include <texteditor/texteditoroptionspage.h>
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
namespace Internal {
 | 
			
		||||
 | 
			
		||||
namespace Ui { class CompletionSettingsPage; }
 | 
			
		||||
namespace Ui {
 | 
			
		||||
class CompletionSettingsPage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Move this class to the text editor plugin
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +52,7 @@ class CompletionSettingsPage : public TextEditor::TextEditorOptionsPage
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    CompletionSettingsPage();
 | 
			
		||||
    CompletionSettingsPage(QObject *parent);
 | 
			
		||||
    ~CompletionSettingsPage();
 | 
			
		||||
 | 
			
		||||
    QString id() const;
 | 
			
		||||
@@ -59,12 +63,20 @@ public:
 | 
			
		||||
    void finish();
 | 
			
		||||
    virtual bool matches(const QString &) const;
 | 
			
		||||
 | 
			
		||||
    const CommentsSettings &commentsSettings() const;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void commentsSettingsChanged(const CppTools::CommentsSettings &settings);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    TextEditor::CaseSensitivity caseSensitivity() const;
 | 
			
		||||
    TextEditor::CompletionTrigger completionTrigger() const;
 | 
			
		||||
 | 
			
		||||
    bool requireCommentsSettingsUpdate() const;
 | 
			
		||||
 | 
			
		||||
    Ui::CompletionSettingsPage *m_page;
 | 
			
		||||
    QString m_searchKeywords;
 | 
			
		||||
    CommentsSettings m_commentsSettings;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Internal
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,11 @@
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>393</width>
 | 
			
		||||
    <height>241</height>
 | 
			
		||||
    <width>484</width>
 | 
			
		||||
    <height>376</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
@@ -196,6 +196,65 @@
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QGroupBox" name="docCommentsGroup">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Documentation Comments</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QCheckBox" name="enableDoxygenCheckBox">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Automatically create a Doxygen comment upon pressing enter after a /** or /*!</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Enable Doxygen blocks</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <layout class="QHBoxLayout" name="horizontalLayout_3">
 | 
			
		||||
        <item>
 | 
			
		||||
         <spacer name="horizontalSpacer_5">
 | 
			
		||||
          <property name="orientation">
 | 
			
		||||
           <enum>Qt::Horizontal</enum>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="sizeType">
 | 
			
		||||
           <enum>QSizePolicy::Fixed</enum>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="sizeHint" stdset="0">
 | 
			
		||||
           <size>
 | 
			
		||||
            <width>30</width>
 | 
			
		||||
            <height>20</height>
 | 
			
		||||
           </size>
 | 
			
		||||
          </property>
 | 
			
		||||
         </spacer>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <widget class="QCheckBox" name="generateBriefCheckBox">
 | 
			
		||||
          <property name="toolTip">
 | 
			
		||||
           <string>Generate a <i>brief</i> command with an initial description for the corresponding declaration</string>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Generate brief description</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
       </layout>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QCheckBox" name="leadingAsterisksCheckBox">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Add leading asterisks when continuing comments on new lines</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Add leading asterisks</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <spacer name="verticalSpacer">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
@@ -224,8 +283,8 @@
 | 
			
		||||
     <y>131</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>265</x>
 | 
			
		||||
     <y>182</y>
 | 
			
		||||
     <x>333</x>
 | 
			
		||||
     <y>206</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
@@ -245,5 +304,21 @@
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
  <connection>
 | 
			
		||||
   <sender>enableDoxygenCheckBox</sender>
 | 
			
		||||
   <signal>toggled(bool)</signal>
 | 
			
		||||
   <receiver>generateBriefCheckBox</receiver>
 | 
			
		||||
   <slot>setEnabled(bool)</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>153</x>
 | 
			
		||||
     <y>272</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>204</x>
 | 
			
		||||
     <y>293</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
 </connections>
 | 
			
		||||
</ui>
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,9 @@ HEADERS += completionsettingspage.h \
 | 
			
		||||
    cppcodestylesettings.h \
 | 
			
		||||
    cppcodestylepreferencesfactory.h \
 | 
			
		||||
    cppcodestylepreferences.h \
 | 
			
		||||
    cpptoolsreuse.h
 | 
			
		||||
    cpptoolsreuse.h \
 | 
			
		||||
    doxygengenerator.h \
 | 
			
		||||
    commentssettings.h
 | 
			
		||||
 | 
			
		||||
SOURCES += completionsettingspage.cpp \
 | 
			
		||||
    cppclassesfilter.cpp \
 | 
			
		||||
@@ -62,7 +64,9 @@ SOURCES += completionsettingspage.cpp \
 | 
			
		||||
    cppcodestylesettings.cpp \
 | 
			
		||||
    cppcodestylepreferencesfactory.cpp \
 | 
			
		||||
    cppcodestylepreferences.cpp \
 | 
			
		||||
    cpptoolsreuse.cpp
 | 
			
		||||
    cpptoolsreuse.cpp \
 | 
			
		||||
    doxygengenerator.cpp \
 | 
			
		||||
    commentssettings.cpp
 | 
			
		||||
 | 
			
		||||
FORMS += completionsettingspage.ui \
 | 
			
		||||
    cppfilesettingspage.ui \
 | 
			
		||||
 
 | 
			
		||||
@@ -122,7 +122,6 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
 | 
			
		||||
    addAutoReleasedObject(new CppClassesFilter(m_modelManager));
 | 
			
		||||
    addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
 | 
			
		||||
    addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, core->editorManager()));
 | 
			
		||||
    addAutoReleasedObject(new CompletionSettingsPage);
 | 
			
		||||
    addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
 | 
			
		||||
    addAutoReleasedObject(new SymbolsFindFilter(m_modelManager));
 | 
			
		||||
    addAutoReleasedObject(new CppCodeStyleSettingsPage);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,11 +34,14 @@
 | 
			
		||||
#include "cpptoolsconstants.h"
 | 
			
		||||
#include "cppcodestylepreferences.h"
 | 
			
		||||
#include "cppcodestylepreferencesfactory.h"
 | 
			
		||||
#include "commentssettings.h"
 | 
			
		||||
#include "completionsettingspage.h"
 | 
			
		||||
 | 
			
		||||
#include <texteditor/texteditorsettings.h>
 | 
			
		||||
#include <texteditor/texteditorsettings.h>
 | 
			
		||||
#include <texteditor/tabsettings.h>
 | 
			
		||||
#include <texteditor/codestylepool.h>
 | 
			
		||||
#include <extensionsystem/pluginmanager.h>
 | 
			
		||||
 | 
			
		||||
#include <utils/settingsutils.h>
 | 
			
		||||
#include <utils/qtcassert.h>
 | 
			
		||||
@@ -48,6 +51,7 @@
 | 
			
		||||
static const char *idKey = "CppGlobal";
 | 
			
		||||
 | 
			
		||||
using namespace CppTools;
 | 
			
		||||
using namespace CppTools::Internal;
 | 
			
		||||
using TextEditor::TabSettings;
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
@@ -56,7 +60,13 @@ namespace Internal {
 | 
			
		||||
class CppToolsSettingsPrivate
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    CppToolsSettingsPrivate()
 | 
			
		||||
        : m_globalCodeStyle(0)
 | 
			
		||||
        , m_completionSettingsPage(0)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    CppCodeStylePreferences *m_globalCodeStyle;
 | 
			
		||||
    CompletionSettingsPage *m_completionSettingsPage;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Internal
 | 
			
		||||
@@ -70,8 +80,17 @@ CppToolsSettings::CppToolsSettings(QObject *parent)
 | 
			
		||||
{
 | 
			
		||||
    QTC_ASSERT(!m_instance, return);
 | 
			
		||||
    m_instance = this;
 | 
			
		||||
 | 
			
		||||
    qRegisterMetaType<CppTools::CppCodeStyleSettings>("CppTools::CppCodeStyleSettings");
 | 
			
		||||
 | 
			
		||||
    d->m_completionSettingsPage = new CompletionSettingsPage(this);
 | 
			
		||||
    ExtensionSystem::PluginManager::instance()->addObject(d->m_completionSettingsPage);
 | 
			
		||||
 | 
			
		||||
    connect(d->m_completionSettingsPage,
 | 
			
		||||
            SIGNAL(commentsSettingsChanged(CppTools::CommentsSettings)),
 | 
			
		||||
            this,
 | 
			
		||||
            SIGNAL(commentsSettingsChanged(CppTools::CommentsSettings)));
 | 
			
		||||
 | 
			
		||||
    TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
 | 
			
		||||
 | 
			
		||||
    // code style factory
 | 
			
		||||
@@ -224,6 +243,8 @@ CppToolsSettings::CppToolsSettings(QObject *parent)
 | 
			
		||||
 | 
			
		||||
CppToolsSettings::~CppToolsSettings()
 | 
			
		||||
{
 | 
			
		||||
    ExtensionSystem::PluginManager::instance()->removeObject(d->m_completionSettingsPage);
 | 
			
		||||
 | 
			
		||||
    delete d;
 | 
			
		||||
 | 
			
		||||
    m_instance = 0;
 | 
			
		||||
@@ -239,3 +260,7 @@ CppCodeStylePreferences *CppToolsSettings::cppCodeStyle() const
 | 
			
		||||
    return d->m_globalCodeStyle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CommentsSettings &CppToolsSettings::commentsSettings() const
 | 
			
		||||
{
 | 
			
		||||
    return d->m_completionSettingsPage->commentsSettings();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@
 | 
			
		||||
namespace CppTools
 | 
			
		||||
{
 | 
			
		||||
class CppCodeStylePreferences;
 | 
			
		||||
 | 
			
		||||
class CommentsSettings;
 | 
			
		||||
 | 
			
		||||
namespace Internal
 | 
			
		||||
{
 | 
			
		||||
@@ -61,6 +61,10 @@ public:
 | 
			
		||||
    static CppToolsSettings *instance();
 | 
			
		||||
 | 
			
		||||
    CppCodeStylePreferences *cppCodeStyle() const;
 | 
			
		||||
    const CommentsSettings &commentsSettings() const;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void commentsSettingsChanged(const CppTools::CommentsSettings &settings);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Internal::CppToolsSettingsPrivate *d;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										289
									
								
								src/plugins/cpptools/doxygengenerator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								src/plugins/cpptools/doxygengenerator.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,289 @@
 | 
			
		||||
#include "doxygengenerator.h"
 | 
			
		||||
 | 
			
		||||
#include <cplusplus/SimpleLexer.h>
 | 
			
		||||
#include <cplusplus/BackwardsScanner.h>
 | 
			
		||||
#include <cplusplus/Token.h>
 | 
			
		||||
#include <cplusplus/TranslationUnit.h>
 | 
			
		||||
#include <cplusplus/AST.h>
 | 
			
		||||
#include <cplusplus/Symbols.h>
 | 
			
		||||
#include <cplusplus/CppDocument.h>
 | 
			
		||||
#include <cplusplus/Scope.h>
 | 
			
		||||
#include <cplusplus/LookupContext.h>
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QStringBuilder>
 | 
			
		||||
#include <QtGui/QTextDocument>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
using namespace CppTools;
 | 
			
		||||
using namespace CPlusPlus;
 | 
			
		||||
 | 
			
		||||
DoxygenGenerator::DoxygenGenerator()
 | 
			
		||||
    : m_addLeadingAsterisks(true)
 | 
			
		||||
    , m_generateBrief(true)
 | 
			
		||||
    , m_startComment(true)
 | 
			
		||||
    , m_style(QtStyle)
 | 
			
		||||
    , m_commentOffset(0)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::setStyle(DocumentationStyle style)
 | 
			
		||||
{
 | 
			
		||||
    m_style = style;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::setStartComment(bool start)
 | 
			
		||||
{
 | 
			
		||||
    m_startComment = start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::setGenerateBrief(bool get)
 | 
			
		||||
{
 | 
			
		||||
    m_generateBrief = get;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::setAddLeadingAsterisks(bool add)
 | 
			
		||||
{
 | 
			
		||||
    m_addLeadingAsterisks = add;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString DoxygenGenerator::generate(QTextCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
    const QChar &c = cursor.document()->characterAt(cursor.position());
 | 
			
		||||
    if (!c.isLetter() && c != QLatin1Char('_'))
 | 
			
		||||
        return QString();
 | 
			
		||||
 | 
			
		||||
    // Try to find what would be the declaration we are interested in.
 | 
			
		||||
    SimpleLexer lexer;
 | 
			
		||||
    QTextBlock block = cursor.block();
 | 
			
		||||
    while (block.isValid()) {
 | 
			
		||||
        const QString &text = block.text();
 | 
			
		||||
        const QList<Token> &tks = lexer(text);
 | 
			
		||||
        foreach (const Token &tk, tks) {
 | 
			
		||||
            if (tk.is(T_SEMICOLON) || tk.is(T_LBRACE)) {
 | 
			
		||||
                // No need to continue beyond this, we might already have something meaningful.
 | 
			
		||||
                cursor.setPosition(block.position() + tk.end(), QTextCursor::KeepAnchor);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cursor.hasSelection())
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        block = block.next();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!cursor.hasSelection())
 | 
			
		||||
        return QString();
 | 
			
		||||
 | 
			
		||||
    QString declCandidate = cursor.selectedText();
 | 
			
		||||
    declCandidate.replace(QChar::ParagraphSeparator, QLatin1Char('\n'));
 | 
			
		||||
 | 
			
		||||
    // Let's append a closing brace in the case we got content like 'class MyType {'
 | 
			
		||||
    if (declCandidate.endsWith(QLatin1Char('{')))
 | 
			
		||||
        declCandidate.append(QLatin1Char('}'));
 | 
			
		||||
 | 
			
		||||
    Document::Ptr doc = Document::create(QLatin1String("<doxygen>"));
 | 
			
		||||
    doc->setSource(declCandidate.toUtf8());
 | 
			
		||||
    doc->parse(Document::ParseDeclaration);
 | 
			
		||||
    doc->check(Document::FastCheck);
 | 
			
		||||
 | 
			
		||||
    if (!doc->translationUnit()
 | 
			
		||||
            || !doc->translationUnit()->ast()
 | 
			
		||||
            || !doc->translationUnit()->ast()->asDeclaration()) {
 | 
			
		||||
        return QString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return generate(cursor, doc->translationUnit()->ast()->asDeclaration());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString DoxygenGenerator::generate(QTextCursor cursor, CPlusPlus::DeclarationAST *decl)
 | 
			
		||||
{
 | 
			
		||||
    SpecifierAST *spec = 0;
 | 
			
		||||
    DeclaratorAST *decltr = 0;
 | 
			
		||||
    if (SimpleDeclarationAST *simpleDecl = decl->asSimpleDeclaration()) {
 | 
			
		||||
        if (simpleDecl->declarator_list
 | 
			
		||||
                && simpleDecl->declarator_list->value) {
 | 
			
		||||
            decltr = simpleDecl->declarator_list->value;
 | 
			
		||||
        } else if (simpleDecl->decl_specifier_list
 | 
			
		||||
                   && simpleDecl->decl_specifier_list->value) {
 | 
			
		||||
            spec = simpleDecl->decl_specifier_list->value;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (FunctionDefinitionAST * defDecl = decl->asFunctionDefinition()) {
 | 
			
		||||
        decltr = defDecl->declarator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assignCommentOffset(cursor);
 | 
			
		||||
 | 
			
		||||
    QString comment;
 | 
			
		||||
    if (m_startComment)
 | 
			
		||||
        writeStart(&comment);
 | 
			
		||||
    writeNewLine(&comment);
 | 
			
		||||
    writeContinuation(&comment);
 | 
			
		||||
 | 
			
		||||
    if (decltr
 | 
			
		||||
            && decltr->core_declarator
 | 
			
		||||
            && decltr->core_declarator->asDeclaratorId()
 | 
			
		||||
            && decltr->core_declarator->asDeclaratorId()->name) {
 | 
			
		||||
        CoreDeclaratorAST *coreDecl = decltr->core_declarator;
 | 
			
		||||
        if (m_generateBrief)
 | 
			
		||||
            writeBrief(&comment, m_printer.prettyName(coreDecl->asDeclaratorId()->name->name));
 | 
			
		||||
        else
 | 
			
		||||
            writeNewLine(&comment);
 | 
			
		||||
 | 
			
		||||
        if (decltr->postfix_declarator_list
 | 
			
		||||
                && decltr->postfix_declarator_list->value
 | 
			
		||||
                && decltr->postfix_declarator_list->value->asFunctionDeclarator()) {
 | 
			
		||||
            FunctionDeclaratorAST *funcDecltr =
 | 
			
		||||
                    decltr->postfix_declarator_list->value->asFunctionDeclarator();
 | 
			
		||||
            if (funcDecltr->parameter_declaration_clause
 | 
			
		||||
                    && funcDecltr->parameter_declaration_clause->parameter_declaration_list) {
 | 
			
		||||
                for (ParameterDeclarationListAST *it =
 | 
			
		||||
                        funcDecltr->parameter_declaration_clause->parameter_declaration_list;
 | 
			
		||||
                     it;
 | 
			
		||||
                     it = it->next) {
 | 
			
		||||
                    ParameterDeclarationAST *paramDecl = it->value;
 | 
			
		||||
                    if (paramDecl->declarator
 | 
			
		||||
                            && paramDecl->declarator->core_declarator
 | 
			
		||||
                            && paramDecl->declarator->core_declarator->asDeclaratorId()
 | 
			
		||||
                            && paramDecl->declarator->core_declarator->asDeclaratorId()->name) {
 | 
			
		||||
                        DeclaratorIdAST *paramId =
 | 
			
		||||
                                paramDecl->declarator->core_declarator->asDeclaratorId();
 | 
			
		||||
                        writeContinuation(&comment);
 | 
			
		||||
                        writeCommand(&comment,
 | 
			
		||||
                                     ParamCommand,
 | 
			
		||||
                                     m_printer.prettyName(paramId->name->name));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (funcDecltr->symbol
 | 
			
		||||
                    && funcDecltr->symbol->returnType().type()
 | 
			
		||||
                    && !funcDecltr->symbol->returnType()->isVoidType()
 | 
			
		||||
                    && !funcDecltr->symbol->returnType()->isUndefinedType()) {
 | 
			
		||||
                writeContinuation(&comment);
 | 
			
		||||
                writeCommand(&comment, ReturnCommand);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (spec && m_generateBrief) {
 | 
			
		||||
        bool briefWritten = false;
 | 
			
		||||
        if (ClassSpecifierAST *classSpec = spec->asClassSpecifier()) {
 | 
			
		||||
            if (classSpec->name) {
 | 
			
		||||
                QString aggregate;
 | 
			
		||||
                if (classSpec->symbol->isClass())
 | 
			
		||||
                    aggregate = QLatin1String("class");
 | 
			
		||||
                else if (classSpec->symbol->isStruct())
 | 
			
		||||
                    aggregate = QLatin1String("struct");
 | 
			
		||||
                else
 | 
			
		||||
                    aggregate = QLatin1String("union");
 | 
			
		||||
                writeBrief(&comment,
 | 
			
		||||
                           m_printer.prettyName(classSpec->name->name),
 | 
			
		||||
                           QLatin1String("The"),
 | 
			
		||||
                           aggregate);
 | 
			
		||||
                briefWritten = true;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (EnumSpecifierAST *enumSpec = spec->asEnumSpecifier()) {
 | 
			
		||||
            if (enumSpec->name) {
 | 
			
		||||
                writeBrief(&comment,
 | 
			
		||||
                           m_printer.prettyName(enumSpec->name->name),
 | 
			
		||||
                           QLatin1String("The"),
 | 
			
		||||
                           QLatin1String("enum"));
 | 
			
		||||
                briefWritten = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!briefWritten)
 | 
			
		||||
            writeNewLine(&comment);
 | 
			
		||||
    } else {
 | 
			
		||||
        writeNewLine(&comment);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    writeEnd(&comment);
 | 
			
		||||
 | 
			
		||||
    return comment;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QChar DoxygenGenerator::startMark() const
 | 
			
		||||
{
 | 
			
		||||
    if (m_style == QtStyle)
 | 
			
		||||
        return QLatin1Char('!');
 | 
			
		||||
    return QLatin1Char('*');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QChar DoxygenGenerator::styleMark() const
 | 
			
		||||
{
 | 
			
		||||
    if (m_style == QtStyle)
 | 
			
		||||
        return QLatin1Char('\\');
 | 
			
		||||
    return QLatin1Char('@');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString DoxygenGenerator::commandSpelling(Command command)
 | 
			
		||||
{
 | 
			
		||||
    if (command == ParamCommand)
 | 
			
		||||
        return QLatin1String("param ");
 | 
			
		||||
    if (command == ReturnCommand)
 | 
			
		||||
        return QLatin1String("return ");
 | 
			
		||||
 | 
			
		||||
    Q_ASSERT(command == BriefCommand);
 | 
			
		||||
    return QLatin1String("brief ");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeStart(QString *comment) const
 | 
			
		||||
{
 | 
			
		||||
    comment->append(offsetString() % QLatin1String("/*") % startMark());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeEnd(QString *comment) const
 | 
			
		||||
{
 | 
			
		||||
    comment->append(offsetString() % QLatin1String(" */"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeContinuation(QString *comment) const
 | 
			
		||||
{
 | 
			
		||||
    if (m_addLeadingAsterisks)
 | 
			
		||||
        comment->append(offsetString() % QLatin1String(" *"));
 | 
			
		||||
    else
 | 
			
		||||
        comment->append(offsetString() % QLatin1String("  "));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeNewLine(QString *comment) const
 | 
			
		||||
{
 | 
			
		||||
    comment->append(QLatin1Char('\n'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeCommand(QString *comment,
 | 
			
		||||
                                    Command command,
 | 
			
		||||
                                    const QString &commandContent) const
 | 
			
		||||
{
 | 
			
		||||
    comment->append(QLatin1Char(' ')
 | 
			
		||||
                    % styleMark()
 | 
			
		||||
                    % commandSpelling(command)
 | 
			
		||||
                    % commandContent
 | 
			
		||||
                    % QLatin1Char('\n'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::writeBrief(QString *comment,
 | 
			
		||||
                                  const QString &brief,
 | 
			
		||||
                                  const QString &prefix,
 | 
			
		||||
                                  const QString &suffix)
 | 
			
		||||
{
 | 
			
		||||
    QString content = prefix % QLatin1Char(' ') % brief % QLatin1Char(' ') % suffix;
 | 
			
		||||
    writeCommand(comment, BriefCommand, content.trimmed());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DoxygenGenerator::assignCommentOffset(QTextCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
    if (cursor.hasSelection()) {
 | 
			
		||||
        if (cursor.anchor() < cursor.position())
 | 
			
		||||
            cursor.setPosition(cursor.anchor());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_commentOffset = cursor.positionInBlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString DoxygenGenerator::offsetString() const
 | 
			
		||||
{
 | 
			
		||||
    // Note: Currently we don't indent comments, but simply preserve them in the original
 | 
			
		||||
    // relative positions. What we do here is just to make sure that such positions are correct,
 | 
			
		||||
    // although they might still be wrong from an indentation point of view (for instance,
 | 
			
		||||
    // using spaces instead of tabs). Therefore, the content generated should still have
 | 
			
		||||
    // the indentation strings fixed.
 | 
			
		||||
 | 
			
		||||
    return QString(m_commentOffset, QLatin1Char(' '));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								src/plugins/cpptools/doxygengenerator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/plugins/cpptools/doxygengenerator.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#ifndef DOXYGEGENERATOR_H
 | 
			
		||||
#define DOXYGEGENERATOR_H
 | 
			
		||||
 | 
			
		||||
#include "cpptools_global.h"
 | 
			
		||||
 | 
			
		||||
#include <cplusplus/Overview.h>
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QLatin1String>
 | 
			
		||||
#include <QtGui/QTextCursor>
 | 
			
		||||
 | 
			
		||||
namespace CPlusPlus {
 | 
			
		||||
class DeclarationAST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
 | 
			
		||||
class CPPTOOLS_EXPORT DoxygenGenerator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    DoxygenGenerator();
 | 
			
		||||
 | 
			
		||||
    enum DocumentationStyle {
 | 
			
		||||
        JavaStyle,
 | 
			
		||||
        QtStyle
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void setStyle(DocumentationStyle style);
 | 
			
		||||
    void setStartComment(bool start);
 | 
			
		||||
    void setGenerateBrief(bool gen);
 | 
			
		||||
    void setAddLeadingAsterisks(bool add);
 | 
			
		||||
 | 
			
		||||
    QString generate(QTextCursor cursor);
 | 
			
		||||
    QString generate(QTextCursor cursor, CPlusPlus::DeclarationAST *decl);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QChar startMark() const;
 | 
			
		||||
    QChar styleMark() const;
 | 
			
		||||
 | 
			
		||||
    enum Command {
 | 
			
		||||
        BriefCommand,
 | 
			
		||||
        ParamCommand,
 | 
			
		||||
        ReturnCommand
 | 
			
		||||
    };
 | 
			
		||||
    static QString commandSpelling(Command command);
 | 
			
		||||
 | 
			
		||||
    void writeStart(QString *comment) const;
 | 
			
		||||
    void writeEnd(QString *comment) const;
 | 
			
		||||
    void writeContinuation(QString *comment) const;
 | 
			
		||||
    void writeNewLine(QString *comment) const;
 | 
			
		||||
    void writeCommand(QString *comment,
 | 
			
		||||
                      Command command,
 | 
			
		||||
                      const QString &commandContent = QString()) const;
 | 
			
		||||
    void writeBrief(QString *comment,
 | 
			
		||||
                    const QString &brief,
 | 
			
		||||
                    const QString &prefix = QString(),
 | 
			
		||||
                    const QString &suffix = QString());
 | 
			
		||||
 | 
			
		||||
    void assignCommentOffset(QTextCursor cursor);
 | 
			
		||||
    QString offsetString() const;
 | 
			
		||||
 | 
			
		||||
    bool m_addLeadingAsterisks;
 | 
			
		||||
    bool m_generateBrief;
 | 
			
		||||
    bool m_startComment;
 | 
			
		||||
    DocumentationStyle m_style;
 | 
			
		||||
    CPlusPlus::Overview m_printer;
 | 
			
		||||
    int m_commentOffset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // CppTools
 | 
			
		||||
 | 
			
		||||
#endif // DOXYGEGENERATOR_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user