Commit 4c5ff047 authored by Roberto Raggi's avatar Roberto Raggi

Initial support for doxygen comments.

parent 4a259547
...@@ -54,6 +54,11 @@ bool SimpleToken::isKeyword() const ...@@ -54,6 +54,11 @@ bool SimpleToken::isKeyword() const
return _kind >= T_FIRST_KEYWORD && _kind < T_FIRST_QT_KEYWORD; return _kind >= T_FIRST_KEYWORD && _kind < T_FIRST_QT_KEYWORD;
} }
bool SimpleToken::isComment() const
{
return _kind == T_COMMENT || _kind == T_DOXY_COMMENT;
}
SimpleLexer::SimpleLexer() SimpleLexer::SimpleLexer()
: _lastState(0), : _lastState(0),
_skipComments(false), _skipComments(false),
......
...@@ -69,6 +69,7 @@ public: ...@@ -69,6 +69,7 @@ public:
bool isLiteral() const; bool isLiteral() const;
bool isOperator() const; bool isOperator() const;
bool isKeyword() const; bool isKeyword() const;
bool isComment() const;
public: public:
int _kind; int _kind;
......
This diff is collapsed.
/***************************************************************************
**
** 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 \ ...@@ -15,12 +15,16 @@ HEADERS += cppplugin.h \
cppeditorconstants.h \ cppeditorconstants.h \
cppeditorenums.h \ cppeditorenums.h \
cppeditor_global.h \ cppeditor_global.h \
cppclasswizard.h cppclasswizard.h \
cppdoxygen.h
SOURCES += cppplugin.cpp \ SOURCES += cppplugin.cpp \
cppeditoractionhandler.cpp \ cppeditoractionhandler.cpp \
cppeditor.cpp \ cppeditor.cpp \
cpphighlighter.cpp \ cpphighlighter.cpp \
cpphoverhandler.cpp \ cpphoverhandler.cpp \
cppfilewizard.cpp \ cppfilewizard.cpp \
cppclasswizard.cpp cppclasswizard.cpp \
cppdoxygen.cpp
RESOURCES += cppeditor.qrc RESOURCES += cppeditor.qrc
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
***************************************************************************/ ***************************************************************************/
#include "cpphighlighter.h" #include "cpphighlighter.h"
#include "cppdoxygen.h"
#include <Token.h> #include <Token.h>
#include <cplusplus/SimpleLexer.h> #include <cplusplus/SimpleLexer.h>
...@@ -115,23 +116,35 @@ void CppHighlighter::highlightBlock(const QString &text) ...@@ -115,23 +116,35 @@ void CppHighlighter::highlightBlock(const QString &text)
} }
bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor; bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor;
if (highlightAsPreprocessor) if (highlightAsPreprocessor)
highlightAsPreprocessor = false; highlightAsPreprocessor = false;
if (i == 0 && tk.is(T_POUND)) { if (i == 0 && tk.is(T_POUND)) {
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]); setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
highlightAsPreprocessor = true; highlightAsPreprocessor = true;
} else if (highlightCurrentWordAsPreprocessor && } else if (highlightCurrentWordAsPreprocessor &&
(tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text())) (tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text()))
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]); setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL)) else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL))
setFormat(tk.position(), tk.length(), m_formats[CppNumberFormat]); 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)) 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]); setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]);
else if (tk.is(T_WIDE_STRING_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) else if (tk.is(T_WIDE_STRING_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL))
setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]); 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 // we need to insert a close comment parenthesis, if
// - the line starts in a C Comment (initalState != 0) // - 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)) // - 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) ...@@ -145,12 +158,16 @@ void CppHighlighter::highlightBlock(const QString &text)
// clear the initial state. // clear the initial state.
initialState = 0; initialState = 0;
} }
} else if (tk.isKeyword() || isQtKeyword(tk.text())) } else if (tk.isKeyword() || isQtKeyword(tk.text()))
setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]); setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]);
else if (tk.isOperator()) else if (tk.isOperator())
setFormat(tk.position(), tk.length(), m_formats[CppOperatorFormat]); 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)) 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]); setFormat(tk.position(), tk.length(), m_formats[CppLabelFormat]);
else if (tk.is(T_IDENTIFIER)) else if (tk.is(T_IDENTIFIER))
highlightWord(tk.text(), tk.position(), tk.length()); highlightWord(tk.text(), tk.position(), tk.length());
} }
...@@ -304,3 +321,40 @@ void CppHighlighter::highlightWord(QStringRef word, int position, int length) ...@@ -304,3 +321,40 @@ void CppHighlighter::highlightWord(QStringRef word, int position, int length)
setFormat(position, length, m_formats[CppTypeFormat]); 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: ...@@ -61,6 +61,10 @@ public:
private: private:
void highlightWord(QStringRef word, int position, int length); void highlightWord(QStringRef word, int position, int length);
void highlightDoxygenComment(const QString &text, int position,
int length);
bool isPPKeyword(const QStringRef &text) const; bool isPPKeyword(const QStringRef &text) const;
bool isQtKeyword(const QStringRef &text) const; bool isQtKeyword(const QStringRef &text) const;
......
...@@ -404,7 +404,7 @@ static int startOfOperator(TextEditor::ITextEditable *editor, ...@@ -404,7 +404,7 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
tc.setPosition(pos); tc.setPosition(pos);
static CPlusPlus::TokenUnderCursor tokenUnderCursor; static CPlusPlus::TokenUnderCursor tokenUnderCursor;
const SimpleToken tk = tokenUnderCursor(tc); const SimpleToken tk = tokenUnderCursor(tc);
if (tk.is(T_COMMENT) || tk.isLiteral()) { if (tk.isComment() || tk.isLiteral()) {
if (kind) if (kind)
*kind = T_EOF_SYMBOL; *kind = T_EOF_SYMBOL;
return pos; return pos;
......
...@@ -8,27 +8,27 @@ include(cpptools_dependencies.pri) ...@@ -8,27 +8,27 @@ include(cpptools_dependencies.pri)
DEFINES += QT_NO_CAST_TO_ASCII DEFINES += QT_NO_CAST_TO_ASCII
INCLUDEPATH += . INCLUDEPATH += .
DEFINES += CPPTOOLS_LIBRARY DEFINES += CPPTOOLS_LIBRARY
HEADERS += cpptools_global.h \ HEADERS += completionsettingspage.h \
cppquickopenfilter.h \
cppclassesfilter.h \ cppclassesfilter.h \
searchsymbols.h \ cppcodecompletion.h \
cppfunctionsfilter.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 \ cppmodelmanager.h \
cppcodecompletion.h \
cppmodelmanagerinterface.h \ cppmodelmanagerinterface.h \
cppquickopenfilter.h \
cpptools_global.h \
cpptoolsconstants.h \
cpptoolseditorsupport.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 FORMS += completionsettingspage.ui
...@@ -60,7 +60,7 @@ CPLUSPLUS_BEGIN_NAMESPACE ...@@ -60,7 +60,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
Lexer::Lexer(TranslationUnit *unit) Lexer::Lexer(TranslationUnit *unit)
: _translationUnit(unit), : _translationUnit(unit),
_state(Lexer::DefaultState), _state(State_Default),
_flags(0), _flags(0),
_currentLine(1) _currentLine(1)
{ {
...@@ -71,7 +71,7 @@ Lexer::Lexer(TranslationUnit *unit) ...@@ -71,7 +71,7 @@ Lexer::Lexer(TranslationUnit *unit)
Lexer::Lexer(const char *firstChar, const char *lastChar) Lexer::Lexer(const char *firstChar, const char *lastChar)
: _translationUnit(0), : _translationUnit(0),
_state(Lexer::DefaultState), _state(State_Default),
_flags(0), _flags(0),
_currentLine(1) _currentLine(1)
{ {
...@@ -196,7 +196,7 @@ void Lexer::scan_helper(Token *tok) ...@@ -196,7 +196,7 @@ void Lexer::scan_helper(Token *tok)
_tokenStart = _currentChar; _tokenStart = _currentChar;
tok->offset = _currentChar - _firstChar; tok->offset = _currentChar - _firstChar;
if (_state == MultiLineCommentState) { if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) {
if (! _yychar) { if (! _yychar) {
tok->kind = T_EOF_SYMBOL; tok->kind = T_EOF_SYMBOL;
return; return;
...@@ -209,7 +209,7 @@ void Lexer::scan_helper(Token *tok) ...@@ -209,7 +209,7 @@ void Lexer::scan_helper(Token *tok)
yyinp(); yyinp();
if (_yychar == '/') { if (_yychar == '/') {
yyinp(); yyinp();
_state = DefaultState; _state = State_Default;
break; break;
} }
} }
...@@ -218,7 +218,11 @@ void Lexer::scan_helper(Token *tok) ...@@ -218,7 +218,11 @@ void Lexer::scan_helper(Token *tok)
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
tok->kind = T_COMMENT; else if (_state == State_MultiLineComment)
tok->kind = T_COMMENT;
else
tok->kind = T_DOXY_COMMENT;
return; // done return; // done
} }
...@@ -402,14 +406,30 @@ void Lexer::scan_helper(Token *tok) ...@@ -402,14 +406,30 @@ void Lexer::scan_helper(Token *tok)
case '/': case '/':
if (_yychar == '/') { if (_yychar == '/') {
do { yyinp();
bool doxy = false;
if (_yychar == '/' || _yychar == '!') {
yyinp();
if (_yychar != '\n' && std::isspace(_yychar))
doxy = true;
}
while (_yychar && _yychar != '\n')
yyinp(); yyinp();
} while (_yychar && _yychar != '\n');
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
tok->kind = T_COMMENT;
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
} else if (_yychar == '*') { } else if (_yychar == '*') {
yyinp(); yyinp();
const bool doxy = _yychar == '*' || _yychar == '!';
while (_yychar) { while (_yychar) {
if (_yychar != '*') { if (_yychar != '*') {
yyinp(); yyinp();
...@@ -423,11 +443,13 @@ void Lexer::scan_helper(Token *tok) ...@@ -423,11 +443,13 @@ void Lexer::scan_helper(Token *tok)
if (_yychar) if (_yychar)
yyinp(); yyinp();
else else
_state = MultiLineCommentState; _state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment;
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
tok->kind = T_COMMENT;
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
} else if (_yychar == '=') { } else if (_yychar == '=') {
yyinp(); yyinp();
tok->kind = T_SLASH_EQUAL; tok->kind = T_SLASH_EQUAL;
......
...@@ -66,8 +66,9 @@ class CPLUSPLUS_EXPORT Lexer ...@@ -66,8 +66,9 @@ class CPLUSPLUS_EXPORT Lexer
public: public:
enum State { enum State {
DefaultState, State_Default,
MultiLineCommentState State_MultiLineComment,
State_MultiLineDoxyComment
}; };
Lexer(TranslationUnit *unit); Lexer(TranslationUnit *unit);
......
...@@ -58,7 +58,7 @@ CPLUSPLUS_BEGIN_NAMESPACE ...@@ -58,7 +58,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
static const char *token_names[] = { static const char *token_names[] = {
(""), ("<error>"), (""), ("<error>"),
("<comment>"), ("<comment>"), ("<doxy comment>"),
("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"), ("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"),
("<wide char literal>"), ("<string literal>"), ("<wide char literal>"), ("<wide char literal>"), ("<string literal>"), ("<wide char literal>"),
......
...@@ -64,6 +64,7 @@ enum Kind { ...@@ -64,6 +64,7 @@ enum Kind {
T_ERROR, T_ERROR,
T_COMMENT, T_COMMENT,
T_DOXY_COMMENT,
T_IDENTIFIER, T_IDENTIFIER,
T_FIRST_LITERAL, T_FIRST_LITERAL,
...@@ -297,6 +298,9 @@ public: ...@@ -297,6 +298,9 @@ public:
inline bool isKeyword() const inline bool isKeyword() const
{ return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; } { 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 inline bool isObjCAtKeyword() const
{ return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; } { return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment