hugolib: Improve errors in /i18n handlling
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 22 Oct 2018 15:42:06 +0000 (17:42 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 22 Oct 2018 18:46:14 +0000 (20:46 +0200)
See #5324

commands/hugo.go
common/herrors/file_error_test.go
common/herrors/line_number_extractors.go
hugolib/site.go
i18n/translationProvider.go

index 2204ae9f35b1dd57bea486802f6a56cbc65eda0e..acc48539d252df4195a02c85072e8b9e74b6797c 100644 (file)
@@ -620,7 +620,9 @@ func (c *commandeer) buildSites() (err error) {
 
 func (c *commandeer) handleBuildErr(err error, msg string) {
        c.buildErr = err
-       c.logger.ERROR.Printf("%s: %s", msg, err)
+
+       c.logger.ERROR.Print(msg + ":\n\n")
+       c.logger.ERROR.Println(helpers.FirstUpper(err.Error()))
        if !c.h.quiet && c.h.verbose {
                herrors.PrintStackTrace(err)
        }
index 0d4e82f6658f2ab808b8e430f4caeda7ec26d563..8b1674ba1cb119b6c674a4ae454f43d839b2139c 100644 (file)
@@ -38,6 +38,7 @@ func TestToLineNumberError(t *testing.T) {
                {errors.New("parse failed: template: _default/bundle-resource-meta.html:11: unexpected in operand"), 0, 11, 1},
                {errors.New(`failed:: template: _default/bundle-resource-meta.html:2:7: executing "main" at <.Titles>`), 0, 2, 7},
                {errors.New("error in front matter: Near line 32 (last key parsed 'title')"), 0, 32, 1},
+               {errors.New(`failed to load translations: (6, 7): was expecting token =, but got "g" instead`), 0, 6, 7},
        } {
 
                got := ToFileErrorWithOffset("template", test.in, test.offset)
@@ -46,7 +47,7 @@ func TestToLineNumberError(t *testing.T) {
                le, ok := got.(FileError)
 
                if test.lineNumber > 0 {
-                       assert.True(ok)
+                       assert.True(ok, errMsg)
                        assert.Equal(test.lineNumber, le.LineNumber(), errMsg)
                        assert.Equal(test.columnNumber, le.ColumnNumber(), errMsg)
                        assert.Contains(got.Error(), strconv.Itoa(le.LineNumber()))
index 8740afdf75ec0a94b12c26e4eccf9130e93efd0e..93969b9676b2bd068f675b26667616023611216c 100644 (file)
@@ -20,13 +20,17 @@ import (
 
 var lineNumberExtractors = []lineNumberExtractor{
        // Template/shortcode parse errors
-       newLineNumberErrHandlerFromRegexp("(.*?:)(\\d+)(:)(\\d+)?(.*)"),
+       newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"),
+       newLineNumberErrHandlerFromRegexp(".*:(\\d+):"),
 
        // TOML parse errors
-       newLineNumberErrHandlerFromRegexp("(.*Near line )(\\d+)(\\s.*)"),
+       newLineNumberErrHandlerFromRegexp(".*Near line (\\d+)(\\s.*)"),
 
        // YAML parse errors
-       newLineNumberErrHandlerFromRegexp("(line )(\\d+)(:)"),
+       newLineNumberErrHandlerFromRegexp("line (\\d+):"),
+
+       // i18n bundle errors
+       newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"),
 }
 
 type lineNumberExtractor func(e error) (int, int)
@@ -44,10 +48,10 @@ func extractLineNo(re *regexp.Regexp) lineNumberExtractor {
                col := 1
                s := e.Error()
                m := re.FindStringSubmatch(s)
-               if len(m) >= 4 {
-                       lno, _ := strconv.Atoi(m[2])
-                       if len(m) > 4 {
-                               col, _ = strconv.Atoi(m[4])
+               if len(m) >= 2 {
+                       lno, _ := strconv.Atoi(m[1])
+                       if len(m) > 2 {
+                               col, _ = strconv.Atoi(m[2])
                        }
 
                        if col <= 0 {
index e3f6d8f8cbc1f02cd99b34c2f8d6a900d18b6779..127b143e53ec924599ce8344328e6b81eee09d03 100644 (file)
@@ -861,6 +861,24 @@ func (s *Site) loadData(fs afero.Fs) (err error) {
        return
 }
 
+func (s *Site) errWithFileContext(err error, f source.File) error {
+       rfi, ok := f.FileInfo().(hugofs.RealFilenameInfo)
+       if !ok {
+               return err
+       }
+
+       realFilename := rfi.RealFilename()
+
+       err, _ = herrors.WithFileContextForFile(
+               err,
+               realFilename,
+               realFilename,
+               s.SourceSpec.Fs.Source,
+               herrors.SimpleLineMatcher)
+
+       return err
+}
+
 func (s *Site) handleDataFile(r source.ReadableFile) error {
        var current map[string]interface{}
 
@@ -888,14 +906,7 @@ func (s *Site) handleDataFile(r source.ReadableFile) error {
 
        data, err := s.readData(r)
        if err != nil {
-               realFilename := r.FileInfo().(hugofs.RealFilenameInfo).RealFilename()
-               err, _ = herrors.WithFileContextForFile(
-                       _errors.Wrapf(err, "failed to read data file"),
-                       realFilename,
-                       realFilename,
-                       s.SourceSpec.Fs.Source,
-                       herrors.SimpleLineMatcher)
-               return err
+               return s.errWithFileContext(err, r)
        }
 
        if data == nil {
index 4e937c5a19e8d19d5d2bb96aaaf444cf0947aa2b..74e144007efdc3e52ec6e5d58b65e1f46970acff 100644 (file)
@@ -16,8 +16,11 @@ package i18n
 import (
        "errors"
 
+       "github.com/gohugoio/hugo/common/herrors"
+
        "github.com/gohugoio/hugo/deps"
        "github.com/gohugoio/hugo/helpers"
+       "github.com/gohugoio/hugo/hugofs"
        "github.com/gohugoio/hugo/source"
        "github.com/nicksnyder/go-i18n/i18n/bundle"
        "github.com/nicksnyder/go-i18n/i18n/language"
@@ -81,12 +84,12 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
 func addTranslationFile(bundle *bundle.Bundle, r source.ReadableFile) error {
        f, err := r.Open()
        if err != nil {
-               return _errors.Wrapf(err, "Failed to open translations file %q:", r.LogicalName())
+               return _errors.Wrapf(err, "failed to open translations file %q:", r.LogicalName())
        }
-       defer f.Close()
        err = bundle.ParseTranslationFileBytes(r.LogicalName(), helpers.ReaderToBytes(f))
+       f.Close()
        if err != nil {
-               return _errors.Wrapf(err, "Failed to load translations in file %q:", r.LogicalName())
+               return errWithFileContext(_errors.Wrapf(err, "failed to load translations"), r)
        }
        return nil
 }
@@ -97,3 +100,26 @@ func (tp *TranslationProvider) Clone(d *deps.Deps) error {
 
        return nil
 }
+
+func errWithFileContext(inerr error, r source.ReadableFile) error {
+       rfi, ok := r.FileInfo().(hugofs.RealFilenameInfo)
+       if !ok {
+               return inerr
+       }
+
+       realFilename := rfi.RealFilename()
+       f, err := r.Open()
+       if err != nil {
+               return inerr
+       }
+       defer f.Close()
+
+       err, _ = herrors.WithFileContext(
+               inerr,
+               realFilename,
+               f,
+               herrors.SimpleLineMatcher)
+
+       return err
+
+}