hugolib: Improve errors in /i18n handlling

See #5324
This commit is contained in:
Bjørn Erik Pedersen 2018-10-22 17:42:06 +02:00
parent 9f74dc2a52
commit 2bf686ee21
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F
5 changed files with 64 additions and 20 deletions

View file

@ -620,7 +620,9 @@ func (c *commandeer) buildSites() (err error) {
func (c *commandeer) handleBuildErr(err error, msg string) { func (c *commandeer) handleBuildErr(err error, msg string) {
c.buildErr = err 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 { if !c.h.quiet && c.h.verbose {
herrors.PrintStackTrace(err) herrors.PrintStackTrace(err)
} }

View 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("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(`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("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) got := ToFileErrorWithOffset("template", test.in, test.offset)
@ -46,7 +47,7 @@ func TestToLineNumberError(t *testing.T) {
le, ok := got.(FileError) le, ok := got.(FileError)
if test.lineNumber > 0 { if test.lineNumber > 0 {
assert.True(ok) assert.True(ok, errMsg)
assert.Equal(test.lineNumber, le.LineNumber(), errMsg) assert.Equal(test.lineNumber, le.LineNumber(), errMsg)
assert.Equal(test.columnNumber, le.ColumnNumber(), errMsg) assert.Equal(test.columnNumber, le.ColumnNumber(), errMsg)
assert.Contains(got.Error(), strconv.Itoa(le.LineNumber())) assert.Contains(got.Error(), strconv.Itoa(le.LineNumber()))

View file

@ -20,13 +20,17 @@ import (
var lineNumberExtractors = []lineNumberExtractor{ var lineNumberExtractors = []lineNumberExtractor{
// Template/shortcode parse errors // Template/shortcode parse errors
newLineNumberErrHandlerFromRegexp("(.*?:)(\\d+)(:)(\\d+)?(.*)"), newLineNumberErrHandlerFromRegexp(".*:(\\d+):(\\d*):"),
newLineNumberErrHandlerFromRegexp(".*:(\\d+):"),
// TOML parse errors // TOML parse errors
newLineNumberErrHandlerFromRegexp("(.*Near line )(\\d+)(\\s.*)"), newLineNumberErrHandlerFromRegexp(".*Near line (\\d+)(\\s.*)"),
// YAML parse errors // YAML parse errors
newLineNumberErrHandlerFromRegexp("(line )(\\d+)(:)"), newLineNumberErrHandlerFromRegexp("line (\\d+):"),
// i18n bundle errors
newLineNumberErrHandlerFromRegexp("\\((\\d+),\\s(\\d*)"),
} }
type lineNumberExtractor func(e error) (int, int) type lineNumberExtractor func(e error) (int, int)
@ -44,10 +48,10 @@ func extractLineNo(re *regexp.Regexp) lineNumberExtractor {
col := 1 col := 1
s := e.Error() s := e.Error()
m := re.FindStringSubmatch(s) m := re.FindStringSubmatch(s)
if len(m) >= 4 { if len(m) >= 2 {
lno, _ := strconv.Atoi(m[2]) lno, _ := strconv.Atoi(m[1])
if len(m) > 4 { if len(m) > 2 {
col, _ = strconv.Atoi(m[4]) col, _ = strconv.Atoi(m[2])
} }
if col <= 0 { if col <= 0 {

View file

@ -861,6 +861,24 @@ func (s *Site) loadData(fs afero.Fs) (err error) {
return 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 { func (s *Site) handleDataFile(r source.ReadableFile) error {
var current map[string]interface{} var current map[string]interface{}
@ -888,14 +906,7 @@ func (s *Site) handleDataFile(r source.ReadableFile) error {
data, err := s.readData(r) data, err := s.readData(r)
if err != nil { if err != nil {
realFilename := r.FileInfo().(hugofs.RealFilenameInfo).RealFilename() return s.errWithFileContext(err, r)
err, _ = herrors.WithFileContextForFile(
_errors.Wrapf(err, "failed to read data file"),
realFilename,
realFilename,
s.SourceSpec.Fs.Source,
herrors.SimpleLineMatcher)
return err
} }
if data == nil { if data == nil {

View file

@ -16,8 +16,11 @@ package i18n
import ( import (
"errors" "errors"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
"github.com/nicksnyder/go-i18n/i18n/bundle" "github.com/nicksnyder/go-i18n/i18n/bundle"
"github.com/nicksnyder/go-i18n/i18n/language" "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 { func addTranslationFile(bundle *bundle.Bundle, r source.ReadableFile) error {
f, err := r.Open() f, err := r.Open()
if err != nil { 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)) err = bundle.ParseTranslationFileBytes(r.LogicalName(), helpers.ReaderToBytes(f))
f.Close()
if err != nil { 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 return nil
} }
@ -97,3 +100,26 @@ func (tp *TranslationProvider) Clone(d *deps.Deps) error {
return nil 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
}