Fix bug #7331 (No error highlighting in child documents)

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37845 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Enrico Forestieri 2011-03-04 13:37:14 +00:00
parent 32e842b209
commit 2e18f6a671
6 changed files with 100 additions and 28 deletions

View File

@ -3888,24 +3888,49 @@ Buffer::ReadStatus Buffer::loadThisLyXFile(FileName const & fn)
void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
{
TeXErrors::Errors::const_iterator cit = terr.begin();
TeXErrors::Errors::const_iterator it = terr.begin();
TeXErrors::Errors::const_iterator end = terr.end();
ListOfBuffers clist = getDescendents();
ListOfBuffers::const_iterator cen = clist.end();
for (; cit != end; ++cit) {
for (; it != end; ++it) {
int id_start = -1;
int pos_start = -1;
int errorRow = cit->error_in_line;
bool found = d->texrow.getIdFromRow(errorRow, id_start,
pos_start);
int errorRow = it->error_in_line;
Buffer const * buf = 0;
Impl const * p = d;
p->texrow.getIdFromRow(errorRow, id_start, pos_start);
if (id_start == -1) {
// Check whether the error occurred in a child
ListOfBuffers::const_iterator cit = clist.begin();
for (; cit != cen; ++cit) {
string const child_name =
DocFileName(changeExtension(
(*cit)->absFileName(), "tex")).
mangledFileName();
if (it->child_name != child_name)
continue;
(*cit)->d->texrow.getIdFromRow(errorRow,
id_start, pos_start);
if (id_start != -1) {
buf = d->cloned_buffer_
? (*cit)->d->cloned_buffer_->d->owner_
: (*cit)->d->owner_;
p = (*cit)->d;
break;
}
}
}
int id_end = -1;
int pos_end = -1;
bool found;
do {
++errorRow;
found = d->texrow.getIdFromRow(errorRow, id_end, pos_end);
found = p->texrow.getIdFromRow(errorRow, id_end, pos_end);
} while (found && id_start == id_end && pos_start == pos_end);
errorList.push_back(ErrorItem(cit->error_desc,
cit->error_text, id_start, pos_start, pos_end));
errorList.push_back(ErrorItem(it->error_desc,
it->error_text, id_start, pos_start, pos_end, buf));
}
}

View File

@ -18,14 +18,15 @@ namespace lyx {
ErrorItem::ErrorItem(docstring const & error_, docstring const & description_,
int par_id_, pos_type pos_start_, pos_type pos_end_)
int par_id_, pos_type pos_start_, pos_type pos_end_,
Buffer const * buffer_)
: error(error_), description(description_), par_id(par_id_),
pos_start(pos_start_), pos_end(pos_end_)
pos_start(pos_start_), pos_end(pos_end_), buffer(buffer_)
{}
ErrorItem::ErrorItem()
: par_id(-1), pos_start(0), pos_end(0)
: par_id(-1), pos_start(0), pos_end(0), buffer(0)
{}

View File

@ -31,8 +31,10 @@ public:
int par_id;
pos_type pos_start;
pos_type pos_end;
Buffer const * buffer;
ErrorItem(docstring const & error, docstring const & description,
int parid, pos_type posstart, pos_type posend);
int parid, pos_type posstart, pos_type posend,
Buffer const * buf = 0);
ErrorItem();
};

View File

@ -32,6 +32,7 @@
#include "support/regex.h"
#include <fstream>
#include <stack>
using namespace std;
@ -64,9 +65,10 @@ docstring runMessage(unsigned int count)
*/
void TeXErrors::insertError(int line, docstring const & error_desc,
docstring const & error_text)
docstring const & error_text,
string const & child_name)
{
Error newerr(line, error_desc, error_text);
Error newerr(line, error_desc, error_text, child_name);
errors.push_back(newerr);
}
@ -621,9 +623,13 @@ int LaTeX::scanLogFile(TeXErrors & terr)
ifstream ifs(fn.toFilesystemEncoding().c_str());
bool fle_style = false;
static regex file_line_error(".+\\.\\D+:[0-9]+: (.+)");
static regex child_file(".*([0-9]+[A-Za-z]*_.+\\.tex).*");
// Flag for 'File ended while scanning' message.
// We need to wait for subsequent processing.
string wait_for_error;
string child_name;
int pnest = 0;
stack <pair<string, int> > child;
string token;
while (getline(ifs, token)) {
@ -640,6 +646,29 @@ int LaTeX::scanLogFile(TeXErrors & terr)
if (token.empty())
continue;
// Track child documents
for (size_t i = 0; i < token.length(); ++i) {
if (token[i] == '(') {
++pnest;
size_t j = token.find('(', i + 1);
size_t len = j == string::npos
? token.substr(i + 1).length()
: j - i - 1;
if (regex_match(token.substr(i + 1, len),
sub, child_file)) {
string const name = sub.str(1);
child.push(make_pair(name, pnest));
i += len;
}
} else if (token[i] == ')') {
if (!child.empty()
&& child.top().second == pnest)
child.pop();
--pnest;
}
}
child_name = child.empty() ? empty_string() : child.top().first;
if (contains(token, "file:line:error style messages enabled"))
fle_style = true;
@ -729,6 +758,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
do {
if (!getline(ifs, tmp))
break;
tmp = rtrim(tmp, "\r");
errstr += "\n" + tmp;
if (++count > 5)
break;
@ -736,7 +766,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
terr.insertError(0,
from_local8bit("Emergency stop"),
from_local8bit(errstr));
from_local8bit(errstr),
child_name);
}
// get the next line
@ -745,6 +776,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
do {
if (!getline(ifs, tmp))
break;
tmp = rtrim(tmp, "\r");
if (++count > 10)
break;
} while (!prefixIs(tmp, "l."));
@ -763,6 +795,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
string errstr(tmp, tmp.find(' '));
errstr += '\n';
getline(ifs, tmp);
tmp = rtrim(tmp, "\r");
while (!contains(errstr, "l.")
&& !tmp.empty()
&& !prefixIs(tmp, "! ")
@ -770,6 +803,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
errstr += tmp;
errstr += "\n";
getline(ifs, tmp);
tmp = rtrim(tmp, "\r");
}
LYXERR(Debug::LATEX, "line: " << line << '\n'
<< "Desc: " << desc << '\n' << "Text: " << errstr);
@ -790,7 +824,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
// assume here it can be wrong.
terr.insertError(line,
from_local8bit(desc),
from_local8bit(errstr));
from_local8bit(errstr),
child_name);
++num_errors;
}
}
@ -816,7 +851,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
retval |= ERRORS;
terr.insertError(0,
from_local8bit("pdfTeX Error"),
from_local8bit(token));
from_local8bit(token),
child_name);
}
}
}

View File

@ -39,16 +39,20 @@ private:
///
Error () : error_in_line(0) {}
///
Error(int line, docstring const & desc, docstring const & text)
Error(int line, docstring const & desc, docstring const & text,
std::string const & fname)
: error_in_line(line),
error_desc(desc),
error_text(text) {}
error_text(text),
child_name(fname) {}
/// what line in the TeX file the error occured in
int error_in_line;
/// The kind of error
docstring error_desc;
/// The line/cmd that caused the error.
docstring error_text;
/// The name of the child where error occurred, empty otherwise.
std::string child_name;
};
public:
///
@ -59,7 +63,8 @@ public:
Errors::const_iterator end() const { return errors.end(); }
///
void insertError(int line, docstring const & error_desc,
docstring const & error_text);
docstring const & error_text,
std::string const & child_name = empty_string());
private:
///
Errors errors;

View File

@ -149,20 +149,23 @@ bool GuiErrorList::initialiseParams(string const & data)
bool GuiErrorList::goTo(int item)
{
if (&buffer() != buf_) {
if (!theBufferList().isLoaded(buf_))
return false;
FuncRequest fr(LFUN_BUFFER_SWITCH, buf_->absFileName());
dispatch(fr);
}
ErrorItem const & err = errorList()[item];
if (err.par_id == -1)
return false;
DocIterator dit = buf_->getParFromID(err.par_id);
Buffer const * errbuf = err.buffer ? err.buffer : buf_;
if (dit == doc_iterator_end(buf_)) {
if (&buffer() != errbuf) {
if (!theBufferList().isLoaded(errbuf))
return false;
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");