/// has been externally modified? Can be reset by the user.
mutable bool externally_modified_;
+ ///Binding LaTeX lines with buffer positions.
+ //Common routine for LaTeX and Reference errors listing.
+ void traverseErrors(TeXErrors::Errors::const_iterator err,
+ TeXErrors::Errors::const_iterator end,
+ ErrorList & errorList) const;
+
private:
/// So we can force access via the accessors.
mutable Buffer const * parent_buffer;
}
-void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
+void Buffer::Impl::traverseErrors(TeXErrors::Errors::const_iterator err, TeXErrors::Errors::const_iterator end, ErrorList & errorList) const
{
- for (auto const & err : terr) {
+ for (; err != end; ++err) {
TexRow::TextEntry start = TexRow::text_none, end = TexRow::text_none;
- int errorRow = err.error_in_line;
+ int errorRow = err->error_in_line;
Buffer const * buf = 0;
- Impl const * p = d;
- if (err.child_name.empty())
+ Impl const * p = this;
+ if (err->child_name.empty())
tie(start, end) = p->texrow.getEntriesFromRow(errorRow);
else {
// The error occurred in a child
- for (Buffer const * child : getDescendents()) {
+ for (Buffer const * child : owner_->getDescendents()) {
string const child_name =
DocFileName(changeExtension(child->absFileName(), "tex")).
mangledFileName();
- if (err.child_name != child_name)
+ if (err->child_name != child_name)
continue;
tie(start, end) = child->d->texrow.getEntriesFromRow(errorRow);
if (!TexRow::isNone(start)) {
- buf = d->cloned_buffer_
+ buf = this->cloned_buffer_
? child->d->cloned_buffer_->d->owner_
: child->d->owner_;
p = child->d;
}
}
}
- errorList.push_back(ErrorItem(err.error_desc, err.error_text,
+ errorList.push_back(ErrorItem(err->error_desc, err->error_text,
start, end, buf));
}
}
+void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
+{
+ TeXErrors::Errors::const_iterator err = terr.begin();
+ TeXErrors::Errors::const_iterator end = terr.end();
+
+ d->traverseErrors(err, end, errorList);
+}
+
+
+void Buffer::bufferRefs(TeXErrors const & terr, ErrorList & errorList) const
+{
+ TeXErrors::Errors::const_iterator err = terr.begin_ref();
+ TeXErrors::Errors::const_iterator end = terr.end_ref();
+
+ d->traverseErrors(err, end, errorList);
+}
+
+
void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
{
LBUFERR(!text().paragraphs().empty());
public:
/// Fill in the ErrorList with the TeXErrors
void bufferErrors(TeXErrors const &, ErrorList &) const;
+ /// Fill in the Citation/Reference ErrorList from the TeXErrors
+ void bufferRefs(TeXErrors const &, ErrorList &) const;
enum OutputWhat {
FullSource,
if (result & LaTeX::ERRORS)
buffer.bufferErrors(terr, errorList);
+ if ((result & LaTeX::UNDEF_CIT) || (result & LaTeX::UNDEF_REF)) {
+ buffer.bufferRefs(terr, errorList);
+ if (errorList.empty())
+ errorList.push_back(ErrorItem(_("Undefined reference"),
+ _("Undefined reference or citation was found during the build, please check the Log."),
+ &buffer));
+ }
+
if (!errorList.empty()) {
// We will show the LaTeX Errors GUI later which contains
// specific error messages so it would be repetitive to give
int const ERROR_MASK =
LaTeX::NO_LOGFILE |
LaTeX::ERRORS |
+ LaTeX::UNDEF_CIT |
+ LaTeX::UNDEF_REF |
LaTeX::NO_OUTPUT;
return (result & ERROR_MASK) == 0 ? SUCCESS : FAILURE;
}
+void TeXErrors::insertRef(int line, docstring const & error_desc,
+ docstring const & error_text,
+ string const & child_name)
+{
+ Error newerr(line, error_desc, error_text, child_name);
+ undef_ref.push_back(newerr);
+}
+
+
bool operator==(AuxInfo const & a, AuxInfo const & o)
{
return a.aux_file == o.aux_file
}
+//helper func for scanLogFile; gets line number X from strings "... on input line X ..."
+//returns 0 if none is found
+int getLineNumber(const string &token){
+ string l = support::token(token, ' ', tokenPos(token,' ',"line") + 1);
+ return l.empty() ? 0 : convert<int>(l);
+}
+
+
int LaTeX::scanLogFile(TeXErrors & terr)
{
int last_line = -1;
stack <pair<string, int> > child;
children.clear();
+ terr.clearRefs();
+
string token;
while (getline(ifs, token)) {
// MikTeX sometimes inserts \0 in the log file. They can't be
if (contains(token, "file:line:error style messages enabled"))
fle_style = true;
+ //Handles both "LaTeX Warning:" & "Package natbib Warning:"
+ //Various handlers for missing citations below won't catch the problem if citation
+ //key is long (>~25chars), because pdflatex splits output at line length 80.
+ if (contains(token, "There were undefined citations."))
+ retval |= UNDEF_CIT;
+
if (prefixIs(token, "LaTeX Warning:") ||
prefixIs(token, "! pdfTeX warning")) {
// Here shall we handle different
} else if (contains(token, "Etaremune labels have changed")) {
retval |= ERROR_RERUN;
LYXERR(Debug::LATEX, "Force rerun.");
+ //"Citation `cit' on page X undefined on input line X."
} else if (contains(token, "Citation")
- && contains(token, "on page")
+ //&& contains(token, "on input line") //often split to newline
&& contains(token, "undefined")) {
retval |= UNDEF_CIT;
- } else if (contains(token, "Citation")
- && contains(token, "on input line")
+ terr.insertRef(getLineNumber(token), from_ascii("Citation undefined"),
+ from_utf8(token), child_name);
+ //"Reference `X' on page Y undefined on input line Z."
+ } else if (contains(token, "Reference")
+ //&& contains(token, "on input line")) //often split to new line
&& contains(token, "undefined")) {
- retval |= UNDEF_CIT;
+ retval |= UNDEF_REF;
+ terr.insertRef(getLineNumber(token), from_ascii("Reference undefined"),
+ from_utf8(token), child_name);
+
+ //If label is too long pdlaftex log line splitting will make the above fail
+ //so we catch at least this generic statement occuring for both CIT & REF.
+ } else if (contains(token, "There were undefined references.")) {
+ if (!(retval & UNDEF_CIT)) //if not handled already
+ retval |= UNDEF_REF;
}
+
} else if (prefixIs(token, "Package")) {
// Package warnings
retval |= PACKAGE_WARNING;
&& contains(token, "on page")
&& contains(token, "undefined")) {
retval |= UNDEF_CIT;
+ //Unf only keys up to ~6 chars will make it due to line splits
+ terr.insertRef(getLineNumber(token), from_ascii("Citation undefined"),
+ from_utf8(token), child_name);
}
} else if (contains(token, "run BibTeX")) {
retval |= UNDEF_CIT;
///
Errors::const_iterator end() const { return errors.end(); }
///
+ Errors::const_iterator begin_ref() const { return undef_ref.begin(); }
+ ///
+ Errors::const_iterator end_ref() const { return undef_ref.end(); }
+ ///
void insertError(int line, docstring const & error_desc,
docstring const & error_text,
std::string const & child_name = empty_string());
///
void clearErrors() { errors.clear(); }
+ ///
+ void insertRef(int line, docstring const & error_desc,
+ docstring const & error_text,
+ std::string const & child_name = empty_string());
+ ///
+ void clearRefs() { undef_ref.clear(); }
private:
///
Errors errors;
+ /// For missing Citation and references
+ Errors undef_ref;
};