forked from qt-creator/qt-creator
Allow not only a colon as a keyword-text divider in todos.
This makes possible to scan such things as doxygen \todo, @todo entries where colons cannot be added after a keyword. Change-Id: I13c757294c94a1f4758e7dc9634a79ea6e91c68f Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
This commit is contained in:
committed by
Eike Ziller
parent
b6b2441e55
commit
9fe784115a
@@ -35,6 +35,7 @@
|
|||||||
#include "keyword.h"
|
#include "keyword.h"
|
||||||
#include "ui_keyworddialog.h"
|
#include "ui_keyworddialog.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "lineparser.h"
|
||||||
|
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
|
|
||||||
@@ -124,7 +125,7 @@ void KeywordDialog::setupColorWidgets(const QColor &color)
|
|||||||
bool KeywordDialog::canAccept()
|
bool KeywordDialog::canAccept()
|
||||||
{
|
{
|
||||||
if (!isKeywordNameCorrect()) {
|
if (!isKeywordNameCorrect()) {
|
||||||
showError(tr("Keyword cannot be empty, contain spaces or colons."));
|
showError(tr("Keyword cannot be empty, contain spaces, colons, slashes or asterisks."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +147,7 @@ bool KeywordDialog::isKeywordNameCorrect()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < name.size(); ++i)
|
for (int i = 0; i < name.size(); ++i)
|
||||||
if (name.at(i).isSpace() || name.at(i) == QLatin1Char(':'))
|
if (LineParser::isKeywordSeparator(name.at(i)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -38,10 +38,6 @@
|
|||||||
namespace Todo {
|
namespace Todo {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
LineParser::LineParser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LineParser::LineParser(const KeywordList &keywordList)
|
LineParser::LineParser(const KeywordList &keywordList)
|
||||||
{
|
{
|
||||||
setKeywordList(keywordList);
|
setKeywordList(keywordList);
|
||||||
@@ -59,6 +55,14 @@ QList<TodoItem> LineParser::parse(const QString &line)
|
|||||||
return todoItemsFromKeywordEntries(entries);
|
return todoItemsFromKeywordEntries(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LineParser::isKeywordSeparator(const QChar &ch)
|
||||||
|
{
|
||||||
|
return ch.isSpace()
|
||||||
|
|| (ch == QLatin1Char(':'))
|
||||||
|
|| (ch == QLatin1Char('/'))
|
||||||
|
|| (ch == QLatin1Char('*'));
|
||||||
|
}
|
||||||
|
|
||||||
LineParser::KeywordEntryCandidates LineParser::findKeywordEntryCandidates(const QString &line)
|
LineParser::KeywordEntryCandidates LineParser::findKeywordEntryCandidates(const QString &line)
|
||||||
{
|
{
|
||||||
KeywordEntryCandidates entryCandidates;
|
KeywordEntryCandidates entryCandidates;
|
||||||
@@ -66,27 +70,40 @@ LineParser::KeywordEntryCandidates LineParser::findKeywordEntryCandidates(const
|
|||||||
for (int i = 0; i < m_keywords.count(); ++i) {
|
for (int i = 0; i < m_keywords.count(); ++i) {
|
||||||
int searchFrom = -1;
|
int searchFrom = -1;
|
||||||
forever {
|
forever {
|
||||||
const int index = line.lastIndexOf(m_keywords.at(i).name
|
const int index = line.lastIndexOf(m_keywords.at(i).name, searchFrom);
|
||||||
+ QLatin1Char(':'), searchFrom);
|
|
||||||
|
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
break; // 'forever' loop exit condition
|
break; // 'forever' loop exit condition
|
||||||
|
|
||||||
searchFrom = index - line.length() - 1;
|
searchFrom = index - line.length() - 1;
|
||||||
|
|
||||||
if (!isFirstCharOfTheWord(index, line))
|
if (isKeywordAt(index, line, m_keywords.at(i).name))
|
||||||
continue;
|
entryCandidates.insert(index, i);
|
||||||
|
|
||||||
entryCandidates.insert(index, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entryCandidates;
|
return entryCandidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LineParser::isKeywordAt(int index, const QString &line, const QString &keyword)
|
||||||
|
{
|
||||||
|
if (!isFirstCharOfTheWord(index, line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!isLastCharOfTheWord(index + keyword.length() - 1, line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool LineParser::isFirstCharOfTheWord(int index, const QString &line)
|
bool LineParser::isFirstCharOfTheWord(int index, const QString &line)
|
||||||
{
|
{
|
||||||
return (index == 0) || !line.at(index - 1).isLetterOrNumber();
|
return (index == 0) || isKeywordSeparator(line.at(index - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LineParser::isLastCharOfTheWord(int index, const QString &line)
|
||||||
|
{
|
||||||
|
return (index == line.length() - 1) || isKeywordSeparator(line.at(index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
||||||
@@ -109,15 +126,15 @@ QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
|||||||
entry.keywordStart = i.key();
|
entry.keywordStart = i.key();
|
||||||
entry.keywordIndex = i.value();
|
entry.keywordIndex = i.value();
|
||||||
|
|
||||||
int keywordLength = m_keywords.at(entry.keywordIndex).name.length() + 1; // include colon
|
int keywordLength = m_keywords.at(entry.keywordIndex).name.length();
|
||||||
|
|
||||||
int entryTextLength = -1;
|
int entryTextLength = -1;
|
||||||
if (!entries.empty())
|
if (!entries.empty())
|
||||||
entryTextLength = entries.last().keywordStart - (entry.keywordStart + keywordLength);
|
entryTextLength = entries.last().keywordStart - (entry.keywordStart + keywordLength);
|
||||||
|
|
||||||
entry.text = line.mid(entry.keywordStart + keywordLength, entryTextLength).trimmed();
|
entry.text = line.mid(entry.keywordStart + keywordLength, entryTextLength);
|
||||||
|
|
||||||
if (entry.text.isEmpty() && !entries.empty())
|
if (trimSeparators(entry.text).isEmpty() && !entries.empty())
|
||||||
// Take the text form the previous entry, consider:
|
// Take the text form the previous entry, consider:
|
||||||
// '<keyword1>: <keyword2>: <some text>'
|
// '<keyword1>: <keyword2>: <some text>'
|
||||||
entry.text = entries.last().text;
|
entry.text = entries.last().text;
|
||||||
@@ -128,14 +145,36 @@ QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString LineParser::trimSeparators(const QString &string)
|
||||||
|
{
|
||||||
|
QString result = string.trimmed();
|
||||||
|
|
||||||
|
while (startsWithSeparator(result))
|
||||||
|
result = result.right(result.length() - 1);
|
||||||
|
|
||||||
|
while (endsWithSeparator(result))
|
||||||
|
result = result.left(result.length() - 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LineParser::startsWithSeparator(const QString &string)
|
||||||
|
{
|
||||||
|
return !string.isEmpty() && isKeywordSeparator(string.at(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LineParser::endsWithSeparator(const QString &string)
|
||||||
|
{
|
||||||
|
return !string.isEmpty() && isKeywordSeparator(string.at(string.length() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
QList<TodoItem> LineParser::todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries)
|
QList<TodoItem> LineParser::todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries)
|
||||||
{
|
{
|
||||||
QList<TodoItem> todoItems;
|
QList<TodoItem> todoItems;
|
||||||
|
|
||||||
foreach (const KeywordEntry &entry, entries) {
|
foreach (const KeywordEntry &entry, entries) {
|
||||||
TodoItem item;
|
TodoItem item;
|
||||||
item.text = m_keywords.at(entry.keywordIndex).name
|
item.text = m_keywords.at(entry.keywordIndex).name + entry.text;
|
||||||
+ QLatin1String(": ") + entry.text;
|
|
||||||
item.color = m_keywords.at(entry.keywordIndex).color;
|
item.color = m_keywords.at(entry.keywordIndex).color;
|
||||||
item.iconResource = m_keywords.at(entry.keywordIndex).iconResource;
|
item.iconResource = m_keywords.at(entry.keywordIndex).iconResource;
|
||||||
todoItems << item;
|
todoItems << item;
|
||||||
|
@@ -43,12 +43,14 @@ namespace Internal {
|
|||||||
class LineParser
|
class LineParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LineParser();
|
|
||||||
explicit LineParser(const KeywordList &keywordList);
|
explicit LineParser(const KeywordList &keywordList);
|
||||||
|
|
||||||
void setKeywordList(const KeywordList &keywordList);
|
void setKeywordList(const KeywordList &keywordList);
|
||||||
QList<TodoItem> parse(const QString &line);
|
QList<TodoItem> parse(const QString &line);
|
||||||
|
|
||||||
|
// This can also be used from KeywordDialog to avoid code duplication
|
||||||
|
static bool isKeywordSeparator(const QChar &ch);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// map key here is keyword start position in the text line
|
// map key here is keyword start position in the text line
|
||||||
@@ -62,8 +64,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
KeywordEntryCandidates findKeywordEntryCandidates(const QString &line);
|
KeywordEntryCandidates findKeywordEntryCandidates(const QString &line);
|
||||||
|
bool isKeywordAt(int index, const QString &line, const QString &keyword);
|
||||||
bool isFirstCharOfTheWord(int index, const QString &line);
|
bool isFirstCharOfTheWord(int index, const QString &line);
|
||||||
|
bool isLastCharOfTheWord(int index, const QString &line);
|
||||||
QList<KeywordEntry> keywordEntriesFromCandidates(const QMap<int, int> &candidates, const QString &line);
|
QList<KeywordEntry> keywordEntriesFromCandidates(const QMap<int, int> &candidates, const QString &line);
|
||||||
|
QString trimSeparators(const QString &string);
|
||||||
|
bool startsWithSeparator(const QString &string);
|
||||||
|
bool endsWithSeparator(const QString &string);
|
||||||
QList<TodoItem> todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries);
|
QList<TodoItem> todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries);
|
||||||
|
|
||||||
KeywordList m_keywords;
|
KeywordList m_keywords;
|
||||||
|
Reference in New Issue
Block a user