forked from qt-creator/qt-creator
Initial support for doxygen comments.
This commit is contained in:
@@ -54,6 +54,11 @@ bool SimpleToken::isKeyword() const
|
||||
return _kind >= T_FIRST_KEYWORD && _kind < T_FIRST_QT_KEYWORD;
|
||||
}
|
||||
|
||||
bool SimpleToken::isComment() const
|
||||
{
|
||||
return _kind == T_COMMENT || _kind == T_DOXY_COMMENT;
|
||||
}
|
||||
|
||||
SimpleLexer::SimpleLexer()
|
||||
: _lastState(0),
|
||||
_skipComments(false),
|
||||
|
@@ -69,6 +69,7 @@ public:
|
||||
bool isLiteral() const;
|
||||
bool isOperator() const;
|
||||
bool isKeyword() const;
|
||||
bool isComment() const;
|
||||
|
||||
public:
|
||||
int _kind;
|
||||
|
1512
src/plugins/cppeditor/cppdoxygen.cpp
Normal file
1512
src/plugins/cppeditor/cppdoxygen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
160
src/plugins/cppeditor/cppdoxygen.h
Normal file
160
src/plugins/cppeditor/cppdoxygen.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception
|
||||
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
enum DoxygenReservedWord {
|
||||
T_DOXY_IDENTIFIER = 0,
|
||||
|
||||
T_DOXY_ARG,
|
||||
T_DOXY_ATTENTION,
|
||||
T_DOXY_AUTHOR,
|
||||
T_DOXY_CALLGRAPH,
|
||||
T_DOXY_CODE,
|
||||
T_DOXY_DOT,
|
||||
T_DOXY_ELSE,
|
||||
T_DOXY_ENDCODE,
|
||||
T_DOXY_ENDCOND,
|
||||
T_DOXY_ENDDOT,
|
||||
T_DOXY_ENDHTMLONLY,
|
||||
T_DOXY_ENDIF,
|
||||
T_DOXY_ENDLATEXONLY,
|
||||
T_DOXY_ENDLINK,
|
||||
T_DOXY_ENDMANONLY,
|
||||
T_DOXY_ENDVERBATIM,
|
||||
T_DOXY_ENDXMLONLY,
|
||||
T_DOXY_HIDEINITIALIZER,
|
||||
T_DOXY_HTMLONLY,
|
||||
T_DOXY_INTERFACE,
|
||||
T_DOXY_INTERNAL,
|
||||
T_DOXY_INVARIANT,
|
||||
T_DOXY_LATEXONLY,
|
||||
T_DOXY_LI,
|
||||
T_DOXY_MANONLY,
|
||||
T_DOXY_N,
|
||||
T_DOXY_NOSUBGROUPING,
|
||||
T_DOXY_NOTE,
|
||||
T_DOXY_ONLY,
|
||||
T_DOXY_POST,
|
||||
T_DOXY_PRE,
|
||||
T_DOXY_REMARKS,
|
||||
T_DOXY_RETURN,
|
||||
T_DOXY_RETURNS,
|
||||
T_DOXY_SA,
|
||||
T_DOXY_SEE,
|
||||
T_DOXY_SHOWINITIALIZER,
|
||||
T_DOXY_SINCE,
|
||||
T_DOXY_TEST,
|
||||
T_DOXY_TODO,
|
||||
T_DOXY_VERBATIM,
|
||||
T_DOXY_WARNING,
|
||||
T_DOXY_XMLONLY,
|
||||
|
||||
T_DOXY_A,
|
||||
T_DOXY_ADDTOGROUP,
|
||||
T_DOXY_ANCHOR,
|
||||
T_DOXY_B,
|
||||
T_DOXY_C,
|
||||
T_DOXY_CLASS,
|
||||
T_DOXY_COND,
|
||||
T_DOXY_COPYDOC,
|
||||
T_DOXY_DEF,
|
||||
T_DOXY_DONTINCLUDE,
|
||||
T_DOXY_DOTFILE,
|
||||
T_DOXY_E,
|
||||
T_DOXY_ELSEIF,
|
||||
T_DOXY_EM,
|
||||
T_DOXY_ENUM,
|
||||
T_DOXY_EXAMPLE,
|
||||
T_DOXY_EXCEPTION,
|
||||
T_DOXY_EXCEPTIONS,
|
||||
T_DOXY_FILE,
|
||||
T_DOXY_HTMLINCLUDE,
|
||||
T_DOXY_IF,
|
||||
T_DOXY_IFNOT,
|
||||
T_DOXY_INCLUDE,
|
||||
T_DOXY_LINK,
|
||||
T_DOXY_NAMESPACE,
|
||||
T_DOXY_P,
|
||||
T_DOXY_PACKAGE,
|
||||
T_DOXY_REF,
|
||||
T_DOXY_RELATES,
|
||||
T_DOXY_RELATESALSO,
|
||||
T_DOXY_RETVAL,
|
||||
T_DOXY_THROW,
|
||||
T_DOXY_THROWS,
|
||||
T_DOXY_VERBINCLUDE,
|
||||
T_DOXY_VERSION,
|
||||
T_DOXY_XREFITEM,
|
||||
|
||||
T_DOXY_PARAM,
|
||||
|
||||
T_DOXY_IMAGE,
|
||||
|
||||
T_DOXY_DEFGROUP,
|
||||
T_DOXY_PAGE,
|
||||
T_DOXY_PARAGRAPH,
|
||||
T_DOXY_SECTION,
|
||||
T_DOXY_STRUCT,
|
||||
T_DOXY_SUBSECTION,
|
||||
T_DOXY_SUBSUBSECTION,
|
||||
T_DOXY_UNION,
|
||||
T_DOXY_WEAKGROUP,
|
||||
|
||||
T_DOXY_ADDINDEX,
|
||||
T_DOXY_BRIEF,
|
||||
T_DOXY_BUG,
|
||||
T_DOXY_DATE,
|
||||
T_DOXY_DEPRECATED,
|
||||
T_DOXY_FN,
|
||||
T_DOXY_INGROUP,
|
||||
T_DOXY_LINE,
|
||||
T_DOXY_MAINPAGE,
|
||||
T_DOXY_NAME,
|
||||
T_DOXY_OVERLOAD,
|
||||
T_DOXY_PAR,
|
||||
T_DOXY_SHORT,
|
||||
T_DOXY_SKIP,
|
||||
T_DOXY_SKIPLINE,
|
||||
T_DOXY_TYPEDEF,
|
||||
T_DOXY_UNTIL,
|
||||
T_DOXY_VAR,
|
||||
|
||||
};
|
||||
|
||||
int classifyDoxygen(const QChar *s, int n);
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor::Internal
|
||||
|
@@ -15,12 +15,16 @@ HEADERS += cppplugin.h \
|
||||
cppeditorconstants.h \
|
||||
cppeditorenums.h \
|
||||
cppeditor_global.h \
|
||||
cppclasswizard.h
|
||||
cppclasswizard.h \
|
||||
cppdoxygen.h
|
||||
|
||||
SOURCES += cppplugin.cpp \
|
||||
cppeditoractionhandler.cpp \
|
||||
cppeditor.cpp \
|
||||
cpphighlighter.cpp \
|
||||
cpphoverhandler.cpp \
|
||||
cppfilewizard.cpp \
|
||||
cppclasswizard.cpp
|
||||
cppclasswizard.cpp \
|
||||
cppdoxygen.cpp
|
||||
|
||||
RESOURCES += cppeditor.qrc
|
||||
|
@@ -32,6 +32,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "cpphighlighter.h"
|
||||
#include "cppdoxygen.h"
|
||||
|
||||
#include <Token.h>
|
||||
#include <cplusplus/SimpleLexer.h>
|
||||
@@ -115,23 +116,35 @@ void CppHighlighter::highlightBlock(const QString &text)
|
||||
}
|
||||
|
||||
bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor;
|
||||
|
||||
if (highlightAsPreprocessor)
|
||||
highlightAsPreprocessor = false;
|
||||
|
||||
if (i == 0 && tk.is(T_POUND)) {
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
|
||||
highlightAsPreprocessor = true;
|
||||
|
||||
} else if (highlightCurrentWordAsPreprocessor &&
|
||||
(tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text()))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
|
||||
|
||||
else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppNumberFormat]);
|
||||
|
||||
else if (tk.is(T_STRING_LITERAL) || tk.is(T_CHAR_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]);
|
||||
|
||||
else if (tk.is(T_WIDE_STRING_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]);
|
||||
else if (tk.is(T_COMMENT)) {
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppCommentFormat]);
|
||||
|
||||
else if (tk.isComment()) {
|
||||
|
||||
if (tk.is(T_COMMENT))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppCommentFormat]);
|
||||
|
||||
else // a doxygen comment
|
||||
highlightDoxygenComment(text, tk.position(), tk.length());
|
||||
|
||||
// we need to insert a close comment parenthesis, if
|
||||
// - the line starts in a C Comment (initalState != 0)
|
||||
// - the first token of the line is a T_COMMENT (i == 0 && tk.is(T_COMMENT))
|
||||
@@ -145,12 +158,16 @@ void CppHighlighter::highlightBlock(const QString &text)
|
||||
// clear the initial state.
|
||||
initialState = 0;
|
||||
}
|
||||
|
||||
} else if (tk.isKeyword() || isQtKeyword(tk.text()))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]);
|
||||
|
||||
else if (tk.isOperator())
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppOperatorFormat]);
|
||||
|
||||
else if (i == 0 && tokens.size() > 1 && tk.is(T_IDENTIFIER) && tokens.at(1).is(T_COLON))
|
||||
setFormat(tk.position(), tk.length(), m_formats[CppLabelFormat]);
|
||||
|
||||
else if (tk.is(T_IDENTIFIER))
|
||||
highlightWord(tk.text(), tk.position(), tk.length());
|
||||
}
|
||||
@@ -304,3 +321,40 @@ void CppHighlighter::highlightWord(QStringRef word, int position, int length)
|
||||
setFormat(position, length, m_formats[CppTypeFormat]);
|
||||
}
|
||||
}
|
||||
|
||||
void CppHighlighter::highlightDoxygenComment(const QString &text, int position,
|
||||
int length)
|
||||
{
|
||||
int initial = position;
|
||||
int i = position;
|
||||
|
||||
const QChar *uc = text.unicode();
|
||||
const QChar *it = uc + position;
|
||||
|
||||
QTextCharFormat format = m_formats[CppCommentFormat];
|
||||
QTextCharFormat kwFormat = format;
|
||||
kwFormat.setFontWeight(QFont::Bold);
|
||||
kwFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||
|
||||
while (! it->isNull()) {
|
||||
if (it->unicode() == QLatin1Char('\\') ||
|
||||
it->unicode() == QLatin1Char('@')) {
|
||||
++it;
|
||||
|
||||
const QChar *start = it;
|
||||
while (it->isLetterOrNumber() || it->unicode() == '_')
|
||||
++it;
|
||||
|
||||
int k = classifyDoxygen(start, it - start);
|
||||
if (k != T_DOXY_IDENTIFIER) {
|
||||
setFormat(initial, start - uc - initial, format);
|
||||
setFormat(start - uc - 1, it - start + 1, kwFormat);
|
||||
initial = it - uc;
|
||||
}
|
||||
} else
|
||||
++it;
|
||||
}
|
||||
|
||||
setFormat(initial, it - uc - initial, format);
|
||||
}
|
||||
|
||||
|
@@ -61,6 +61,10 @@ public:
|
||||
|
||||
private:
|
||||
void highlightWord(QStringRef word, int position, int length);
|
||||
|
||||
void highlightDoxygenComment(const QString &text, int position,
|
||||
int length);
|
||||
|
||||
bool isPPKeyword(const QStringRef &text) const;
|
||||
bool isQtKeyword(const QStringRef &text) const;
|
||||
|
||||
|
@@ -404,7 +404,7 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
tc.setPosition(pos);
|
||||
static CPlusPlus::TokenUnderCursor tokenUnderCursor;
|
||||
const SimpleToken tk = tokenUnderCursor(tc);
|
||||
if (tk.is(T_COMMENT) || tk.isLiteral()) {
|
||||
if (tk.isComment() || tk.isLiteral()) {
|
||||
if (kind)
|
||||
*kind = T_EOF_SYMBOL;
|
||||
return pos;
|
||||
|
@@ -8,27 +8,27 @@ include(cpptools_dependencies.pri)
|
||||
DEFINES += QT_NO_CAST_TO_ASCII
|
||||
INCLUDEPATH += .
|
||||
DEFINES += CPPTOOLS_LIBRARY
|
||||
HEADERS += cpptools_global.h \
|
||||
cppquickopenfilter.h \
|
||||
HEADERS += completionsettingspage.h \
|
||||
cppclassesfilter.h \
|
||||
searchsymbols.h \
|
||||
cppfunctionsfilter.h \
|
||||
completionsettingspage.h
|
||||
SOURCES += cppquickopenfilter.cpp \
|
||||
cpptoolseditorsupport.cpp \
|
||||
cppclassesfilter.cpp \
|
||||
searchsymbols.cpp \
|
||||
cppfunctionsfilter.cpp \
|
||||
completionsettingspage.cpp
|
||||
|
||||
# Input
|
||||
SOURCES += cpptoolsplugin.cpp \
|
||||
cppmodelmanager.cpp \
|
||||
cppcodecompletion.cpp
|
||||
HEADERS += cpptoolsplugin.h \
|
||||
cppmodelmanager.h \
|
||||
cppcodecompletion.h \
|
||||
cppfunctionsfilter.h \
|
||||
cppmodelmanager.h \
|
||||
cppmodelmanagerinterface.h \
|
||||
cppquickopenfilter.h \
|
||||
cpptools_global.h \
|
||||
cpptoolsconstants.h \
|
||||
cpptoolseditorsupport.h \
|
||||
cpptoolsconstants.h
|
||||
cpptoolsplugin.h \
|
||||
searchsymbols.h
|
||||
|
||||
SOURCES += completionsettingspage.cpp \
|
||||
cppclassesfilter.cpp \
|
||||
cppcodecompletion.cpp \
|
||||
cppfunctionsfilter.cpp \
|
||||
cppmodelmanager.cpp \
|
||||
cppquickopenfilter.cpp \
|
||||
cpptoolseditorsupport.cpp \
|
||||
cpptoolsplugin.cpp \
|
||||
searchsymbols.cpp
|
||||
|
||||
FORMS += completionsettingspage.ui
|
||||
|
@@ -60,7 +60,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
Lexer::Lexer(TranslationUnit *unit)
|
||||
: _translationUnit(unit),
|
||||
_state(Lexer::DefaultState),
|
||||
_state(State_Default),
|
||||
_flags(0),
|
||||
_currentLine(1)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ Lexer::Lexer(TranslationUnit *unit)
|
||||
|
||||
Lexer::Lexer(const char *firstChar, const char *lastChar)
|
||||
: _translationUnit(0),
|
||||
_state(Lexer::DefaultState),
|
||||
_state(State_Default),
|
||||
_flags(0),
|
||||
_currentLine(1)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ void Lexer::scan_helper(Token *tok)
|
||||
_tokenStart = _currentChar;
|
||||
tok->offset = _currentChar - _firstChar;
|
||||
|
||||
if (_state == MultiLineCommentState) {
|
||||
if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) {
|
||||
if (! _yychar) {
|
||||
tok->kind = T_EOF_SYMBOL;
|
||||
return;
|
||||
@@ -209,7 +209,7 @@ void Lexer::scan_helper(Token *tok)
|
||||
yyinp();
|
||||
if (_yychar == '/') {
|
||||
yyinp();
|
||||
_state = DefaultState;
|
||||
_state = State_Default;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,11 @@ void Lexer::scan_helper(Token *tok)
|
||||
if (! _scanCommentTokens)
|
||||
goto _Lagain;
|
||||
|
||||
tok->kind = T_COMMENT;
|
||||
else if (_state == State_MultiLineComment)
|
||||
tok->kind = T_COMMENT;
|
||||
|
||||
else
|
||||
tok->kind = T_DOXY_COMMENT;
|
||||
return; // done
|
||||
}
|
||||
|
||||
@@ -402,14 +406,30 @@ void Lexer::scan_helper(Token *tok)
|
||||
|
||||
case '/':
|
||||
if (_yychar == '/') {
|
||||
do {
|
||||
yyinp();
|
||||
|
||||
bool doxy = false;
|
||||
|
||||
if (_yychar == '/' || _yychar == '!') {
|
||||
yyinp();
|
||||
} while (_yychar && _yychar != '\n');
|
||||
|
||||
if (_yychar != '\n' && std::isspace(_yychar))
|
||||
doxy = true;
|
||||
}
|
||||
|
||||
while (_yychar && _yychar != '\n')
|
||||
yyinp();
|
||||
|
||||
if (! _scanCommentTokens)
|
||||
goto _Lagain;
|
||||
tok->kind = T_COMMENT;
|
||||
|
||||
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
|
||||
|
||||
} else if (_yychar == '*') {
|
||||
yyinp();
|
||||
|
||||
const bool doxy = _yychar == '*' || _yychar == '!';
|
||||
|
||||
while (_yychar) {
|
||||
if (_yychar != '*') {
|
||||
yyinp();
|
||||
@@ -423,11 +443,13 @@ void Lexer::scan_helper(Token *tok)
|
||||
if (_yychar)
|
||||
yyinp();
|
||||
else
|
||||
_state = MultiLineCommentState;
|
||||
_state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment;
|
||||
|
||||
if (! _scanCommentTokens)
|
||||
goto _Lagain;
|
||||
tok->kind = T_COMMENT;
|
||||
|
||||
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
|
||||
|
||||
} else if (_yychar == '=') {
|
||||
yyinp();
|
||||
tok->kind = T_SLASH_EQUAL;
|
||||
|
@@ -66,8 +66,9 @@ class CPLUSPLUS_EXPORT Lexer
|
||||
|
||||
public:
|
||||
enum State {
|
||||
DefaultState,
|
||||
MultiLineCommentState
|
||||
State_Default,
|
||||
State_MultiLineComment,
|
||||
State_MultiLineDoxyComment
|
||||
};
|
||||
|
||||
Lexer(TranslationUnit *unit);
|
||||
|
@@ -58,7 +58,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
|
||||
static const char *token_names[] = {
|
||||
(""), ("<error>"),
|
||||
|
||||
("<comment>"),
|
||||
("<comment>"), ("<doxy comment>"),
|
||||
|
||||
("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"),
|
||||
("<wide char literal>"), ("<string literal>"), ("<wide char literal>"),
|
||||
|
@@ -64,6 +64,7 @@ enum Kind {
|
||||
T_ERROR,
|
||||
|
||||
T_COMMENT,
|
||||
T_DOXY_COMMENT,
|
||||
T_IDENTIFIER,
|
||||
|
||||
T_FIRST_LITERAL,
|
||||
@@ -297,6 +298,9 @@ public:
|
||||
inline bool isKeyword() const
|
||||
{ return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; }
|
||||
|
||||
inline bool isComment() const
|
||||
{ return kind == T_COMMENT || kind == T_DOXY_COMMENT; }
|
||||
|
||||
inline bool isObjCAtKeyword() const
|
||||
{ return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; }
|
||||
|
||||
|
Reference in New Issue
Block a user