forked from qt-creator/qt-creator
Snippets: Split error messages out of the parsed snippet
Change-Id: Ic5d6664c86405c558e8bb133b854521e4eaef58a Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -70,6 +70,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
QString SnippetParseError::htmlMessage() const
|
||||
{
|
||||
QString message = errorMessage;
|
||||
if (pos < 0 || pos > 50)
|
||||
return message;
|
||||
QString detail = text.left(50);
|
||||
if (detail != text)
|
||||
detail.append("...");
|
||||
detail.replace(QChar::Space, " ");
|
||||
message.append("<br><code>" + detail + "<br>");
|
||||
for (int i = 0; i < pos; ++i)
|
||||
message.append(" ");
|
||||
message.append("^</code>");
|
||||
return message;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Snippet:
|
||||
// --------------------------------------------------------------------
|
||||
@@ -189,7 +205,12 @@ QString Snippet::generateTip() const
|
||||
{'<', "<"},
|
||||
{'>', ">"}};
|
||||
|
||||
ParsedSnippet parsedSnippet = Snippet::parse(m_content);
|
||||
SnippetParseResult result = Snippet::parse(m_content);
|
||||
|
||||
if (Utils::holds_alternative<SnippetParseError>(result))
|
||||
return Utils::get<SnippetParseError>(result).htmlMessage();
|
||||
QTC_ASSERT(Utils::holds_alternative<ParsedSnippet>(result), return {});
|
||||
auto parsedSnippet = Utils::get<ParsedSnippet>(result);
|
||||
|
||||
QString tip("<nobr>");
|
||||
int pos = 0;
|
||||
@@ -215,7 +236,7 @@ QString Snippet::generateTip() const
|
||||
return tip;
|
||||
}
|
||||
|
||||
ParsedSnippet Snippet::parse(const QString &snippet)
|
||||
SnippetParseResult Snippet::parse(const QString &snippet)
|
||||
{
|
||||
static UppercaseMangler ucMangler;
|
||||
static LowercaseMangler lcMangler;
|
||||
@@ -228,15 +249,10 @@ ParsedSnippet Snippet::parse(const QString &snippet)
|
||||
= Utils::TemplateEngine::processText(Utils::globalMacroExpander(), snippet,
|
||||
&errorMessage);
|
||||
|
||||
result.success = errorMessage.isEmpty();
|
||||
if (!result.success) {
|
||||
result.text = snippet;
|
||||
result.errorMessage = errorMessage;
|
||||
return result;
|
||||
}
|
||||
if (!errorMessage.isEmpty())
|
||||
return {SnippetParseError{errorMessage, {}, -1}};
|
||||
|
||||
const int count = preprocessedSnippet.count();
|
||||
bool success = true;
|
||||
int start = -1;
|
||||
NameMangler *mangler = nullptr;
|
||||
|
||||
@@ -260,8 +276,9 @@ ParsedSnippet Snippet::parse(const QString &snippet)
|
||||
}
|
||||
|
||||
if (mangler) {
|
||||
success = false;
|
||||
break;
|
||||
return SnippetParseResult{SnippetParseError{tr("Expected delimiter after mangler id"),
|
||||
preprocessedSnippet,
|
||||
i}};
|
||||
}
|
||||
|
||||
if (current == QLatin1Char(':') && start >= 0) {
|
||||
@@ -272,8 +289,11 @@ ParsedSnippet Snippet::parse(const QString &snippet)
|
||||
} else if (next == QLatin1Char('c')) {
|
||||
mangler = &tcMangler;
|
||||
} else {
|
||||
success = false;
|
||||
break;
|
||||
return SnippetParseResult{
|
||||
SnippetParseError{tr("Expected mangler id 'l'(lowercase), 'u'(uppercase), "
|
||||
"or 'c'(titlecase) after colon"),
|
||||
preprocessedSnippet,
|
||||
i}};
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
@@ -288,17 +308,12 @@ ParsedSnippet Snippet::parse(const QString &snippet)
|
||||
result.text.append(current);
|
||||
}
|
||||
|
||||
if (start >= 0)
|
||||
success = false;
|
||||
|
||||
result.success = success;
|
||||
|
||||
if (!success) {
|
||||
result.ranges.clear();
|
||||
result.text = preprocessedSnippet;
|
||||
if (start >= 0) {
|
||||
return SnippetParseResult{
|
||||
SnippetParseError{tr("Missing closing variable delimiter"), result.text, start}};
|
||||
}
|
||||
|
||||
return result;
|
||||
return SnippetParseResult(result);
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
@@ -418,17 +433,19 @@ void Internal::TextEditorPlugin::testSnippetParsing()
|
||||
Q_ASSERT(ranges_start.count() == ranges_length.count()); // sanity check for the test data
|
||||
Q_ASSERT(ranges_start.count() == ranges_mangler.count()); // sanity check for the test data
|
||||
|
||||
ParsedSnippet result = Snippet::parse(input);
|
||||
SnippetParseResult result = Snippet::parse(input);
|
||||
QCOMPARE(Utils::holds_alternative<ParsedSnippet>(result), success);
|
||||
|
||||
QCOMPARE(result.text, text);
|
||||
QCOMPARE(result.success, success);
|
||||
QCOMPARE(result.ranges.count(), ranges_start.count());
|
||||
ParsedSnippet snippet = Utils::get<ParsedSnippet>(result);
|
||||
|
||||
QCOMPARE(snippet.text, text);
|
||||
QCOMPARE(snippet.ranges.count(), ranges_start.count());
|
||||
for (int i = 0; i < ranges_start.count(); ++i) {
|
||||
QCOMPARE(result.ranges.at(i).start, ranges_start.at(i));
|
||||
QCOMPARE(result.ranges.at(i).length, ranges_length.at(i));
|
||||
QCOMPARE(snippet.ranges.at(i).start, ranges_start.at(i));
|
||||
QCOMPARE(snippet.ranges.at(i).length, ranges_length.at(i));
|
||||
Utils::Id id = NOMANGLER_ID;
|
||||
if (result.ranges.at(i).mangler)
|
||||
id = result.ranges.at(i).mangler->id();
|
||||
if (snippet.ranges.at(i).mangler)
|
||||
id = snippet.ranges.at(i).mangler->id();
|
||||
QCOMPARE(id, ranges_mangler.at(i));
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <texteditor/texteditor_global.h>
|
||||
|
||||
#include <utils/id.h>
|
||||
#include <utils/variant.h>
|
||||
|
||||
#include <QChar>
|
||||
#include <QList>
|
||||
@@ -48,8 +49,6 @@ class TEXTEDITOR_EXPORT ParsedSnippet
|
||||
{
|
||||
public:
|
||||
QString text;
|
||||
QString errorMessage;
|
||||
bool success;
|
||||
struct Range {
|
||||
Range(int s, int l, NameMangler *m) : start(s), length(l), mangler(m) { }
|
||||
int start;
|
||||
@@ -59,8 +58,21 @@ public:
|
||||
QList<Range> ranges;
|
||||
};
|
||||
|
||||
class TEXTEDITOR_EXPORT SnippetParseError
|
||||
{
|
||||
public:
|
||||
QString errorMessage;
|
||||
QString text;
|
||||
int pos;
|
||||
|
||||
QString htmlMessage() const;
|
||||
};
|
||||
|
||||
using SnippetParseResult = Utils::variant<ParsedSnippet, SnippetParseError>;
|
||||
|
||||
class TEXTEDITOR_EXPORT Snippet
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Snippet)
|
||||
public:
|
||||
explicit Snippet(const QString &groupId = QString(), const QString &id = QString());
|
||||
~Snippet();
|
||||
@@ -91,7 +103,7 @@ public:
|
||||
static const QChar kVariableDelimiter;
|
||||
static const QChar kEscapeChar;
|
||||
|
||||
static ParsedSnippet parse(const QString &snippet);
|
||||
static SnippetParseResult parse(const QString &snippet);
|
||||
|
||||
private:
|
||||
bool m_isRemoved = false;
|
||||
|
@@ -2700,15 +2700,14 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
|
||||
void TextEditorWidget::insertCodeSnippet(const QTextCursor &cursor_arg, const QString &snippet)
|
||||
{
|
||||
ParsedSnippet data = Snippet::parse(snippet);
|
||||
|
||||
if (!data.success) {
|
||||
QString message = QString::fromLatin1("Cannot parse snippet \"%1\".").arg(snippet);
|
||||
if (!data.errorMessage.isEmpty())
|
||||
message += QLatin1String("\nParse error: ") + data.errorMessage;
|
||||
QMessageBox::warning(this, QLatin1String("Snippet Parse Error"), message);
|
||||
SnippetParseResult result = Snippet::parse(snippet);
|
||||
if (Utils::holds_alternative<SnippetParseError>(result)) {
|
||||
const auto &error = Utils::get<SnippetParseError>(result);
|
||||
QMessageBox::warning(this, QLatin1String("Snippet Parse Error"), error.htmlMessage());
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(Utils::holds_alternative<ParsedSnippet>(result), return);
|
||||
ParsedSnippet data = Utils::get<ParsedSnippet>(result);
|
||||
|
||||
QTextCursor cursor = cursor_arg;
|
||||
cursor.beginEditBlock();
|
||||
|
Reference in New Issue
Block a user