From eed27603ef4a9813c89fffb0f366f6c01a1e9a4e Mon Sep 17 00:00:00 2001 From: Denis Krivak Date: Fri, 10 Nov 2023 11:29:14 +0100 Subject: [PATCH] Fix consistency check when using `line` compiler directive. --- getters.go | 8 ++++++-- godot_test.go | 17 +++++++++++++++++ testdata/line/main.go | 12 ++++++++++++ testdata/line/main.tpl | 1 + 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 testdata/line/main.go create mode 100644 testdata/line/main.tpl diff --git a/getters.go b/getters.go index 1c059ef..7d3d22f 100644 --- a/getters.go +++ b/getters.go @@ -58,9 +58,13 @@ func newParsedFile(file *ast.File, fset *token.FileSet) (*parsedFile, error) { return nil, errUnsuitableInput } - // Check consistency to avoid checking slice indexes in each function + // Check consistency to avoid checking slice indexes in each function. + // Note that `PositionFor` is used with `adjusted=false` to skip `//line` + // directives that can set references to other files (e.g. templates) + // instead of the real ones, and break consistency here. + // Issue: https://github.com/tetafro/godot/issues/32 lastComment := pf.file.Comments[len(pf.file.Comments)-1] - if p := pf.fset.Position(lastComment.End()); len(pf.lines) < p.Line { + if p := pf.fset.PositionFor(lastComment.End(), false); len(pf.lines) < p.Line { return nil, fmt.Errorf("inconsistency between file and AST: %s", p.Filename) } diff --git a/godot_test.go b/godot_test.go index 17058d8..31c9c08 100644 --- a/godot_test.go +++ b/godot_test.go @@ -40,6 +40,23 @@ func TestRun(t *testing.T) { } }) + t.Run("line directive", func(t *testing.T) { + testFile := filepath.Join("testdata", "line", "main.go") + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, testFile, nil, parser.ParseComments) + if err != nil { + t.Fatalf("Failed to parse input file: %v", err) + } + + issues, err := Run(f, fset, Settings{}) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if len(issues) > 0 { + t.Fatal("Unexpected issues") + } + }) + testFile := filepath.Join("testdata", "check", "main.go") fset := token.NewFileSet() file, err := parser.ParseFile(fset, testFile, nil, parser.ParseComments) diff --git a/testdata/line/main.go b/testdata/line/main.go new file mode 100644 index 0000000..e2c0b83 --- /dev/null +++ b/testdata/line/main.go @@ -0,0 +1,12 @@ +// This is a test for `//line` compiler directive. It can add references +// to other files, for parsed code. If it happens, it breaks consistency +// between the source code and the parsed files, which godot relies on. +package main + +import "fmt" + +func main() { +//line main.tpl:100 + fmt.Println("Template") + // Bye! +} diff --git a/testdata/line/main.tpl b/testdata/line/main.tpl new file mode 100644 index 0000000..af5d858 --- /dev/null +++ b/testdata/line/main.tpl @@ -0,0 +1 @@ +Template file