forked from qt-creator/qt-creator
CppEditor: Generate doxygen comments for functions with macros
...at least for object-like macros. This handles the common case where a macro before the function signature annotates the DLL import/export. Task-number: QTCREATORBUG-15819 Change-Id: I79f22508188019402fb7345222408aaf90106f20 Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
@@ -757,8 +757,23 @@ void Snapshot::insert(Document::Ptr doc)
|
||||
}
|
||||
}
|
||||
|
||||
static QList<Macro> macrosDefinedUntilLine(const QList<Macro> ¯os, int line)
|
||||
{
|
||||
QList<Macro> filtered;
|
||||
|
||||
foreach (const Macro ¯o, macros) {
|
||||
if (macro.line() <= unsigned(line))
|
||||
filtered.append(macro);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source,
|
||||
const Utils::FileName &fileName) const
|
||||
const Utils::FileName &fileName,
|
||||
int withDefinedMacrosFromDocumentUntilLine) const
|
||||
{
|
||||
Document::Ptr newDoc = Document::create(fileName.toString());
|
||||
if (Document::Ptr thisDocument = document(fileName)) {
|
||||
@@ -768,10 +783,15 @@ Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source,
|
||||
newDoc->_resolvedIncludes = thisDocument->_resolvedIncludes;
|
||||
newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes;
|
||||
newDoc->setLanguageFeatures(thisDocument->languageFeatures());
|
||||
if (withDefinedMacrosFromDocumentUntilLine != -1) {
|
||||
newDoc->_definedMacros = macrosDefinedUntilLine(thisDocument->_definedMacros,
|
||||
withDefinedMacrosFromDocumentUntilLine);
|
||||
}
|
||||
}
|
||||
|
||||
FastPreprocessor pp(*this);
|
||||
const QByteArray preprocessedCode = pp.run(newDoc, source);
|
||||
const bool mergeDefinedMacrosOfDocument = !newDoc->_definedMacros.isEmpty();
|
||||
const QByteArray preprocessedCode = pp.run(newDoc, source, mergeDefinedMacrosOfDocument);
|
||||
newDoc->setUtf8Source(preprocessedCode);
|
||||
return newDoc;
|
||||
}
|
||||
|
||||
@@ -425,10 +425,16 @@ public:
|
||||
Snapshot simplified(Document::Ptr doc) const;
|
||||
|
||||
Document::Ptr preprocessedDocument(const QByteArray &source,
|
||||
const Utils::FileName &fileName) const;
|
||||
const Utils::FileName &fileName,
|
||||
int withDefinedMacrosFromDocumentUntilLine = -1) const;
|
||||
Document::Ptr preprocessedDocument(const QByteArray &source,
|
||||
const QString &fileName) const
|
||||
{ return preprocessedDocument(source, Utils::FileName::fromString(fileName)); }
|
||||
const QString &fileName,
|
||||
int withDefinedMacrosFromDocumentUntilLine = -1) const
|
||||
{
|
||||
return preprocessedDocument(source,
|
||||
Utils::FileName::fromString(fileName),
|
||||
withDefinedMacrosFromDocumentUntilLine);
|
||||
}
|
||||
|
||||
Document::Ptr documentFromSource(const QByteArray &preprocessedDocument,
|
||||
const QString &fileName) const;
|
||||
|
||||
@@ -38,7 +38,9 @@ FastPreprocessor::FastPreprocessor(const Snapshot &snapshot)
|
||||
, _addIncludesToCurrentDoc(false)
|
||||
{ }
|
||||
|
||||
QByteArray FastPreprocessor::run(Document::Ptr newDoc, const QByteArray &source)
|
||||
QByteArray FastPreprocessor::run(Document::Ptr newDoc,
|
||||
const QByteArray &source,
|
||||
bool mergeDefinedMacrosOfDocument)
|
||||
{
|
||||
std::swap(newDoc, _currentDoc);
|
||||
_addIncludesToCurrentDoc = _currentDoc->resolvedIncludes().isEmpty()
|
||||
@@ -57,6 +59,9 @@ QByteArray FastPreprocessor::run(Document::Ptr newDoc, const QByteArray &source)
|
||||
|
||||
foreach (const Document::Include &i, doc->resolvedIncludes())
|
||||
mergeEnvironment(i.resolvedFileName());
|
||||
|
||||
if (mergeDefinedMacrosOfDocument)
|
||||
_env.addMacros(_currentDoc->definedMacros());
|
||||
}
|
||||
|
||||
const QByteArray preprocessed = _preproc.run(fileName, source);
|
||||
|
||||
@@ -51,7 +51,9 @@ class CPLUSPLUS_EXPORT FastPreprocessor: public Client
|
||||
public:
|
||||
FastPreprocessor(const Snapshot &snapshot);
|
||||
|
||||
QByteArray run(Document::Ptr newDoc, const QByteArray &source);
|
||||
QByteArray run(Document::Ptr newDoc,
|
||||
const QByteArray &source,
|
||||
bool mergeDefinedMacrosOfDocument = false);
|
||||
|
||||
// CPlusPlus::Client
|
||||
virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType mode,
|
||||
|
||||
@@ -268,7 +268,8 @@ bool handleDoxygenContinuation(QTextCursor &cursor,
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
bool trySplitComment(TextEditor::TextEditorWidget *editorWidget)
|
||||
bool trySplitComment(TextEditor::TextEditorWidget *editorWidget,
|
||||
const CPlusPlus::Snapshot &snapshot)
|
||||
{
|
||||
const CommentsSettings &settings = CppToolsSettings::instance()->commentsSettings();
|
||||
if (!settings.m_enableDoxygen && !settings.m_leadingAsterisks)
|
||||
@@ -310,7 +311,9 @@ bool trySplitComment(TextEditor::TextEditorWidget *editorWidget)
|
||||
}
|
||||
|
||||
if (!cursor.atEnd()) {
|
||||
const QString &comment = doxygen.generate(cursor);
|
||||
const QString &comment = doxygen.generate(cursor,
|
||||
snapshot,
|
||||
editorWidget->textDocument()->filePath());
|
||||
if (!comment.isEmpty()) {
|
||||
cursor.beginEditBlock();
|
||||
cursor.setPosition(pos);
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
#include "cppeditor_global.h"
|
||||
|
||||
namespace TextEditor { class TextEditorWidget; }
|
||||
namespace CPlusPlus { class Snapshot; }
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
bool trySplitComment(TextEditor::TextEditorWidget *editorWidget);
|
||||
bool trySplitComment(TextEditor::TextEditorWidget *editorWidget,
|
||||
const CPlusPlus::Snapshot &snapshot);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor
|
||||
|
||||
@@ -281,6 +281,18 @@ void DoxygenTest::testBasic_data()
|
||||
"*foo /*\n"
|
||||
" \n"
|
||||
);
|
||||
|
||||
QTest::newRow("withMacroFromDocumentBeforeFunction") << _(
|
||||
"#define API\n"
|
||||
"/**|\n"
|
||||
"API void f();\n"
|
||||
) << _(
|
||||
"#define API\n"
|
||||
"/**\n"
|
||||
" * @brief f\n"
|
||||
" */\n"
|
||||
"API void f();\n"
|
||||
);
|
||||
}
|
||||
|
||||
void DoxygenTest::testBasic()
|
||||
@@ -290,6 +302,25 @@ void DoxygenTest::testBasic()
|
||||
runTest(given, expected);
|
||||
}
|
||||
|
||||
void DoxygenTest::testWithMacroFromHeaderBeforeFunction()
|
||||
{
|
||||
const QByteArray given =
|
||||
"#include \"header.h\"\n"
|
||||
"/**|\n"
|
||||
"API void f();\n";
|
||||
|
||||
const QByteArray expected =
|
||||
"#include \"header.h\"\n"
|
||||
"/**\n"
|
||||
" * @brief f\n"
|
||||
" */\n"
|
||||
"API void f();\n";
|
||||
|
||||
const TestDocument headerDocumentDefiningMacro("header.h", "#define API\n");
|
||||
|
||||
runTest(given, expected, /*settings=*/ 0, { headerDocumentDefiningMacro });
|
||||
}
|
||||
|
||||
void DoxygenTest::testNoLeadingAsterisks_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("given");
|
||||
@@ -323,8 +354,10 @@ void DoxygenTest::verifyCleanState() const
|
||||
}
|
||||
|
||||
/// The '|' in the input denotes the cursor position.
|
||||
void DoxygenTest::runTest(const QByteArray &original, const QByteArray &expected,
|
||||
CppTools::CommentsSettings *settings)
|
||||
void DoxygenTest::runTest(const QByteArray &original,
|
||||
const QByteArray &expected,
|
||||
CppTools::CommentsSettings *settings,
|
||||
const TestDocuments &includedHeaderDocuments)
|
||||
{
|
||||
// Write files to disk
|
||||
CppTools::Tests::TemporaryDir temporaryDir;
|
||||
@@ -334,6 +367,10 @@ void DoxygenTest::runTest(const QByteArray &original, const QByteArray &expected
|
||||
testDocument.m_source.remove(testDocument.m_cursorPosition, 1);
|
||||
testDocument.setBaseDirectory(temporaryDir.path());
|
||||
QVERIFY(testDocument.writeToDisk());
|
||||
foreach (TestDocument testDocument, includedHeaderDocuments) {
|
||||
testDocument.setBaseDirectory(temporaryDir.path());
|
||||
QVERIFY(testDocument.writeToDisk());
|
||||
}
|
||||
|
||||
// Update Code Model
|
||||
QVERIFY(TestCase::parseFiles(testDocument.filePath()));
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef CPPDOXYGEN_TEST_H
|
||||
#define CPPDOXYGEN_TEST_H
|
||||
|
||||
#include "cppeditortestcase.h"
|
||||
|
||||
#include <cpptools/commentssettings.h>
|
||||
|
||||
#include <QObject>
|
||||
@@ -48,13 +50,17 @@ private slots:
|
||||
void testBasic_data();
|
||||
void testBasic();
|
||||
|
||||
void testWithMacroFromHeaderBeforeFunction();
|
||||
|
||||
void testNoLeadingAsterisks_data();
|
||||
void testNoLeadingAsterisks();
|
||||
|
||||
private:
|
||||
void verifyCleanState() const;
|
||||
void runTest(const QByteArray &original, const QByteArray &expected,
|
||||
CppTools::CommentsSettings *settings = 0);
|
||||
void runTest(const QByteArray &original,
|
||||
const QByteArray &expected,
|
||||
CppTools::CommentsSettings *settings = 0,
|
||||
const TestDocuments &includedHeaderDocuments = TestDocuments());
|
||||
|
||||
QScopedPointer<CppTools::CommentsSettings> oldSettings;
|
||||
};
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include <texteditor/refactoroverlay.h>
|
||||
|
||||
#include <cplusplus/ASTPath.h>
|
||||
#include <cplusplus/FastPreprocessor.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QAction>
|
||||
@@ -603,7 +604,7 @@ void CppEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
return;
|
||||
|
||||
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
||||
if (trySplitComment(this)) {
|
||||
if (trySplitComment(this, semanticInfo().snapshot)) {
|
||||
e->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include <cpptools/cpptoolstestcase.h>
|
||||
|
||||
#include <QVector>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
@@ -55,6 +57,8 @@ public:
|
||||
CppEditorWidget *m_editorWidget;
|
||||
};
|
||||
|
||||
using TestDocuments = QVector<TestDocument>;
|
||||
|
||||
class TestCase : public CppTools::Tests::TestCase
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -25,15 +25,20 @@
|
||||
|
||||
#include "doxygengenerator.h"
|
||||
|
||||
#include <texteditor/convenience.h>
|
||||
|
||||
#include <cplusplus/BackwardsScanner.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QStringBuilder>
|
||||
#include <QTextDocument>
|
||||
#include <QDebug>
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace CppTools;
|
||||
using namespace CPlusPlus;
|
||||
|
||||
@@ -64,8 +69,24 @@ void DoxygenGenerator::setAddLeadingAsterisks(bool add)
|
||||
m_addLeadingAsterisks = add;
|
||||
}
|
||||
|
||||
QString DoxygenGenerator::generate(QTextCursor cursor)
|
||||
static int lineBeforeCursor(const QTextCursor &cursor)
|
||||
{
|
||||
int line, column;
|
||||
const bool converted = TextEditor::Convenience::convertPosition(cursor.document(),
|
||||
cursor.position(),
|
||||
&line,
|
||||
&column);
|
||||
QTC_ASSERT(converted, return std::numeric_limits<int>::max());
|
||||
|
||||
return line - 1;
|
||||
}
|
||||
|
||||
QString DoxygenGenerator::generate(QTextCursor cursor,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const Utils::FileName &documentFilePath)
|
||||
{
|
||||
const QTextCursor initialCursor = cursor;
|
||||
|
||||
const QChar &c = cursor.document()->characterAt(cursor.position());
|
||||
if (!c.isLetter() && c != QLatin1Char('_'))
|
||||
return QString();
|
||||
@@ -100,8 +121,9 @@ QString DoxygenGenerator::generate(QTextCursor cursor)
|
||||
if (declCandidate.endsWith(QLatin1Char('{')))
|
||||
declCandidate.append(QLatin1Char('}'));
|
||||
|
||||
Document::Ptr doc = Document::create(QLatin1String("<doxygen>"));
|
||||
doc->setUtf8Source(declCandidate.toUtf8());
|
||||
Document::Ptr doc = snapshot.preprocessedDocument(declCandidate.toUtf8(),
|
||||
documentFilePath,
|
||||
lineBeforeCursor(initialCursor));
|
||||
doc->parse(Document::ParseDeclaration);
|
||||
doc->check(Document::FastCheck);
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
QT_FORWARD_DECLARE_CLASS(QTextCursor)
|
||||
|
||||
namespace CPlusPlus { class DeclarationAST; }
|
||||
namespace CPlusPlus { class Snapshot; }
|
||||
namespace Utils { class FileName; }
|
||||
|
||||
namespace CppTools {
|
||||
|
||||
@@ -53,7 +55,9 @@ public:
|
||||
void setGenerateBrief(bool gen);
|
||||
void setAddLeadingAsterisks(bool add);
|
||||
|
||||
QString generate(QTextCursor cursor);
|
||||
QString generate(QTextCursor cursor,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const Utils::FileName &documentFilePath);
|
||||
QString generate(QTextCursor cursor, CPlusPlus::DeclarationAST *decl);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user