On Thu, Jun 06, 2019 at 03:42:05PM +0200, Pavel Sanda wrote:
> Looks little bit difficult within the current machinery (if I understand
> it correctly). Cits can be fixed by incremental runs and we see that in
> updated result value of scanres of LaTeX::run, i.e. if fixed it does not
> contain UNDEF_CIT anymore.
> The accompanying structure of errors "terr" does not get reset, so once
> you push there some info about missing citation it's not going away.
> At the end if you by re-runing fix citation problem but there still remain
> some other problem user will wrongly see it within the list of errors...
> 
> I actually do not understand why not reseting "ter" before each run.
> Seems reasonable to me, but it's hard to test without having examples
> which produced all the trickery in the code.
> Otherwise we could just grep in scanLog for the label/citation name
> and push it to the error dialog.

Ok this is result of todays hacking, ref/cits will get proper information 
in error dialog as well.

Many citations won't make it because pdflatex splits line at 80 chars
and line-based parsing will fail.

I tested plain bibtex & natbib, I don't use the other engines so have
very little clue what happens there.
Pavel
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index c995f825f5..41d2cc9aad 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -4930,6 +4930,42 @@ void Buffer::bufferErrors(TeXErrors const & terr, 
ErrorList & errorList) const
 }
 
 
+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();
+
+       for (; err != end; ++err) {
+               TexRow::TextEntry start = TexRow::text_none, end = 
TexRow::text_none;
+               int errorRow = err->error_in_line;
+               Buffer const * buf = 0;
+               Impl const * p = d;
+               if (err->child_name.empty())
+                       tie(start, end) = p->texrow.getEntriesFromRow(errorRow);
+               else {
+                       // The error occurred in a child
+                       for (Buffer const * child : getDescendents()) {
+                               string const child_name =
+                                       
DocFileName(changeExtension(child->absFileName(), "tex")).
+                                       mangledFileName();
+                               if (err->child_name != child_name)
+                                       continue;
+                               tie(start, end) = 
child->d->texrow.getEntriesFromRow(errorRow);
+                               if (!TexRow::isNone(start)) {
+                                       buf = d->cloned_buffer_
+                                               ? 
child->d->cloned_buffer_->d->owner_
+                                               : child->d->owner_;
+                                       p = child->d;
+                                       break;
+                               }
+                       }
+               }
+               errorList.push_back(ErrorItem(err->error_desc, err->error_text,
+                                             start, end, buf));
+       }
+}
+
+
 void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
 {
        LBUFERR(!text().paragraphs().empty());
diff --git a/src/Buffer.h b/src/Buffer.h
index f1bd1f5e79..7ba3262775 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -287,6 +287,7 @@ private:
 public:
        /// Fill in the ErrorList with the TeXErrors
        void bufferErrors(TeXErrors const &, ErrorList &) const;
+       void bufferRefs(TeXErrors const &, ErrorList &) const;
 
        enum OutputWhat {
                FullSource,
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 8c22b1c42a..4dab2413db 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -881,6 +881,14 @@ Converters::RetVal Converters::runLaTeX(Buffer const & 
buffer, string const & co
        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
@@ -909,6 +917,8 @@ Converters::RetVal Converters::runLaTeX(Buffer const & 
buffer, string const & co
        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;
diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp
index 0144e1cf16..ffbba14e8a 100644
--- a/src/LaTeX.cpp
+++ b/src/LaTeX.cpp
@@ -73,6 +73,15 @@ void TeXErrors::insertError(int line, docstring const & 
error_desc,
 }
 
 
+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
@@ -682,6 +691,14 @@ bool LaTeX::runBibTeX(vector<AuxInfo> const & bibtex_info,
 }
 
 
+//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;
@@ -706,6 +723,8 @@ int LaTeX::scanLogFile(TeXErrors & terr)
        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
@@ -752,6 +771,12 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                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
@@ -771,15 +796,28 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                        } 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 handled already
+                                        retval |= UNDEF_REF;
                        }
+
                } else if (prefixIs(token, "Package")) {
                        // Package warnings
                        retval |= PACKAGE_WARNING;
@@ -789,6 +827,9 @@ int LaTeX::scanLogFile(TeXErrors & terr)
                                    && 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;
diff --git a/src/LaTeX.h b/src/LaTeX.h
index a57cebc83b..ba088bb5cc 100644
--- a/src/LaTeX.h
+++ b/src/LaTeX.h
@@ -60,14 +60,26 @@ public:
        ///
        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;
 };
 
 

Reply via email to