Use the new infrastructure to select rows during error reporting

This commit is contained in:
Guillaume Munch 2016-10-09 21:34:12 +02:00
parent dbe0c6991b
commit e1492a3ab1
8 changed files with 60 additions and 123 deletions

View File

@ -949,15 +949,13 @@ int Buffer::readHeader(Lexer & lex)
"%1$s %2$s\n"),
from_utf8(token),
lex.getDocString());
errorList.push_back(ErrorItem(_("Document header error"),
s, -1, 0, 0));
errorList.push_back(ErrorItem(_("Document header error"), s));
}
}
}
if (begin_header_line) {
docstring const s = _("\\begin_header is missing");
errorList.push_back(ErrorItem(_("Document header error"),
s, -1, 0, 0));
errorList.push_back(ErrorItem(_("Document header error"), s));
}
params().makeDocumentClass();
@ -979,8 +977,7 @@ bool Buffer::readDocument(Lexer & lex)
if (!lex.checkFor("\\begin_document")) {
docstring const s = _("\\begin_document is missing");
errorList.push_back(ErrorItem(_("Document header error"),
s, -1, 0, 0));
errorList.push_back(ErrorItem(_("Document header error"), s));
}
readHeader(lex);
@ -1707,17 +1704,17 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
errorList.push_back(ErrorItem(msg, _("Some characters of your document are probably not "
"representable in the chosen encoding.\n"
"Changing the document encoding to utf8 could help."),
e.par_id, e.pos, e.pos + 1));
{e.par_id, e.pos}, {e.par_id, e.pos + 1}));
failed_export = true;
}
catch (iconv_codecvt_facet_exception const & e) {
errorList.push_back(ErrorItem(_("iconv conversion failed"),
_(e.what()), -1, 0, 0));
_(e.what())));
failed_export = true;
}
catch (exception const & e) {
errorList.push_back(ErrorItem(_("conversion failed"),
_(e.what()), -1, 0, 0));
_(e.what())));
failed_export = true;
}
catch (...) {
@ -4474,56 +4471,33 @@ Buffer::ReadStatus Buffer::loadThisLyXFile(FileName const & fn)
void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
{
TeXErrors::Errors::const_iterator it = terr.begin();
TeXErrors::Errors::const_iterator end = terr.end();
ListOfBuffers clist = getDescendents();
ListOfBuffers::const_iterator cen = clist.end();
for (; it != end; ++it) {
int id_start = -1;
int pos_start = -1;
int errorRow = it->error_in_line;
for (auto const & err : terr) {
TextEntry start, end = TexRow::text_none;
int errorRow = err.error_in_line;
Buffer const * buf = 0;
Impl const * p = d;
if (it->child_name.empty())
p->texrow.getIdFromRow(errorRow, id_start, pos_start);
if (err.child_name.empty())
tie(start, end) = p->texrow.getEntriesFromRow(errorRow);
else {
// The error occurred in a child
ListOfBuffers::const_iterator cit = clist.begin();
for (; cit != cen; ++cit) {
for (Buffer const * child : getDescendents()) {
string const child_name =
DocFileName(changeExtension(
(*cit)->absFileName(), "tex")).
DocFileName(changeExtension(child->absFileName(), "tex")).
mangledFileName();
if (it->child_name != child_name)
if (err.child_name != child_name)
continue;
(*cit)->d->texrow.getIdFromRow(errorRow,
id_start, pos_start);
if (id_start != -1) {
tie(start, end) = child->d->texrow.getEntriesFromRow(errorRow);
if (!TexRow::isNone(start)) {
buf = d->cloned_buffer_
? (*cit)->d->cloned_buffer_->d->owner_
: (*cit)->d->owner_;
p = (*cit)->d;
? child->d->cloned_buffer_->d->owner_
: child->d->owner_;
p = child->d;
break;
}
}
}
int id_end = -1;
int pos_end = -1;
bool found;
do {
++errorRow;
found = p->texrow.getIdFromRow(errorRow, id_end, pos_end);
} while (found && id_start == id_end && pos_start == pos_end);
if (id_start != id_end) {
// Next registered position is outside the inset where
// the error occurred, so signal end-of-paragraph
pos_end = 0;
}
errorList.push_back(ErrorItem(it->error_desc,
it->error_text, id_start, pos_start, pos_end, buf));
errorList.push_back(ErrorItem(err.error_desc, err.error_text,
start, end, buf));
}
}

View File

@ -751,8 +751,8 @@ void switchBetweenClasses(DocumentClassConstPtr oldone,
if (added_one || newlayouts.find(name) != newlayouts.end()) {
// Warn the user.
docstring const s = bformat(_("Layout `%1$s' was not found."), name);
errorlist.push_back(
ErrorItem(_("Layout Not Found"), s, it->id(), 0, it->size()));
errorlist.push_back(ErrorItem(_("Layout Not Found"), s,
{it->id(), 0}, {it->id(), -1}));
}
if (in.usePlainLayout())
@ -787,8 +787,9 @@ void switchBetweenClasses(DocumentClassConstPtr oldone,
layoutName, oldname, newname);
// To warn the user that something had to be done.
errorlist.push_back(ErrorItem(
_("Undefined flex inset"),
s, it.paragraph().id(), it.pos(), it.pos() + 1));
_("Undefined flex inset"), s,
{it.paragraph().id(), it.pos()},
{it.paragraph().id(), it.pos()+1}));
} else if (code == TABULAR_CODE) {
// The recursion above does not catch paragraphs in "hidden" cells,
// i.e., ones that are part of a multirow or multicolum. So we need

View File

@ -18,15 +18,21 @@ namespace lyx {
ErrorItem::ErrorItem(docstring const & error_, docstring const & description_,
int par_id_, pos_type pos_start_, pos_type pos_end_,
TextEntry start_, TextEntry end_, Buffer const * buffer_)
: error(error_), description(description_), start(start_), end(end_),
buffer(buffer_)
{}
ErrorItem::ErrorItem(docstring const & error_, docstring const & description_,
Buffer const * buffer_)
: error(error_), description(description_), par_id(par_id_),
pos_start(pos_start_), pos_end(pos_end_), buffer(buffer_)
: error(error_), description(description_), start(TexRow::text_none),
end(TexRow::text_none), buffer(buffer_)
{}
ErrorItem::ErrorItem()
: par_id(-1), pos_start(0), pos_end(0), buffer(0)
: start(TexRow::text_none), end(TexRow::text_none)
{}

View File

@ -12,6 +12,8 @@
#ifndef ERRORLIST_H
#define ERRORLIST_H
#include "TexRow.h"
#include "support/docstring.h"
#include "support/types.h"
@ -27,12 +29,16 @@ class ErrorItem {
public:
docstring error;
docstring description;
int par_id;
pos_type pos_start;
pos_type pos_end;
// To generalise into RowEntries
TextEntry start;
TextEntry end;
Buffer const * buffer;
// With a start position and an end position
ErrorItem(docstring const & error, docstring const & description,
TextEntry start, TextEntry end,
Buffer const * buf = 0);
// Error outside the document body
ErrorItem(docstring const & error, docstring const & description,
int parid, pos_type posstart, pos_type posend,
Buffer const * buf = 0);
ErrorItem();
};

View File

@ -217,19 +217,6 @@ void TexRow::append(TexRow other)
}
bool TexRow::getIdFromRow(int row, int & id, int & pos) const
{
LYXERR(Debug::LATEX, "getIdFromRow: row " << row << " requested");
TextEntry t = text_none;
if (row <= int(rowlist_.size()))
while (row > 0 && isNone(t = rowlist_[row - 1].getTextEntry()))
--row;
id = t.id;
pos = t.pos;
return !isNone(t);
}
pair<TextEntry, TextEntry> TexRow::getEntriesFromRow(int const row) const
{
LYXERR(Debug::LATEX, "getEntriesFromRow: row " << row << " requested");

View File

@ -179,8 +179,6 @@ public:
std::pair<DocIterator, DocIterator> getDocIteratorsFromRow(
int row,
Buffer const & buf) const;
//TODO: remove the following by replacing it with the above
bool getIdFromRow(int row, int & id, int & pos) const;
/// Finds the best pair of rows for dit
/// returns (-1,-1) if not found.

View File

@ -376,8 +376,8 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
if (added_one) {
// Warn the user.
docstring const s = bformat(_("Layout `%1$s' was not found."), layoutname);
errorList.push_back(
ErrorItem(_("Layout Not Found"), s, par.id(), 0, par.size()));
errorList.push_back(ErrorItem(_("Layout Not Found"), s,
{par.id(), 0}, {par.id(), -1}));
}
par.setLayout(bp.documentClass()[layoutname]);
@ -403,7 +403,7 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
lex.eatLine();
docstring line = lex.getDocString();
errorList.push_back(ErrorItem(_("Unknown Inset"), line,
par.id(), 0, par.size()));
{par.id(), 0}, {par.id(), -1}));
}
} else if (token == "\\family") {
lex.next();
@ -520,8 +520,7 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
"missing until the corresponding tracked changes "
"are merged or this user edits the file again.\n"),
aid),
par.id(), par.size(), par.size() + 1
));
{par.id(), par.size()}, {par.id(), par.size() + 1}));
bp.addAuthor(Author(aid));
}
if (token == "\\change_inserted")
@ -531,9 +530,10 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
} else {
lex.eatLine();
errorList.push_back(ErrorItem(_("Unknown token"),
bformat(_("Unknown token: %1$s %2$s\n"), from_utf8(token),
bformat(_("Unknown token: %1$s %2$s\n"),
from_utf8(token),
lex.getDocString()),
par.id(), 0, par.size()));
{par.id(), 0}, {par.id(), -1}));
}
}

View File

@ -23,6 +23,7 @@
#include "LyX.h"
#include "ParIterator.h"
#include "Text.h"
#include "TexRow.h"
#include "support/debug.h"
#include "support/gettext.h"
@ -162,8 +163,7 @@ bool GuiErrorList::initialiseParams(string const & data)
bool GuiErrorList::goTo(int item)
{
ErrorItem const & err = errorList()[item];
if (err.par_id == -1)
if (TexRow::isNone(err.start))
return false;
Buffer const * errbuf = err.buffer ? err.buffer : buf_;
@ -174,42 +174,7 @@ bool GuiErrorList::goTo(int item)
FuncRequest fr(LFUN_BUFFER_SWITCH, errbuf->absFileName());
dispatch(fr);
}
DocIterator dit = errbuf->getParFromID(err.par_id);
if (dit == doc_iterator_end(errbuf)) {
// FIXME: Happens when loading a read-only doc with
// unknown layout. Should this be the case?
LYXERR0("par id " << err.par_id << " not found");
return false;
}
// Don't try to highlight the content of non-editable insets
while (!dit.inset().editable())
dit.backwardPos();
// Now make the selection.
BufferView * bv = const_cast<BufferView *>(bufferview());
if (bv->selectIfEmpty(dit)) {
// The paragraph is empty but can be selected
bv->processUpdateFlags(Update::Force | Update::FitCursor);
return true;
}
if (dit.empty()) {
// The paragraph is empty and cannot be selected
return false;
}
// if pos_end is 0, this means it is end-of-paragraph
pos_type const s = dit.lastpos();
pos_type const end = err.pos_end ? min(err.pos_end, s) : s;
pos_type const start = min(err.pos_start, end);
pos_type const range = end == start ? s - start : end - start;
// end-of-paragraph cannot be highlighted, so highlight the last thing
dit.pos() = range ? start : end - 1;
// FIXME LFUN
// If we used an LFUN, we would not need these lines:
bv->putSelectionAt(dit, max(range, pos_type(1)), false);
bv->processUpdateFlags(Update::Force | Update::FitCursor);
dispatch(TexRow::goToFunc(err.start, err.end));
return true;
}