From d6597ade89b03a5bd5b6732506c23de741cccd53 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 2 Aug 2018 12:35:32 -0700 Subject: [PATCH] go/scanner: continue adding directory to file name Before CL 97795, when go/scanner saw a //line comment, it would clean the path and, if the path was relative, prepend the directory from the file name. This was not the best API because it meant that the behavior changed based on whether the code was running on Windows or not, and it meant that information from the //line directive was lost. So in CL 97795, among other changes, go/scanner was changed to simply return the filename given in the //line comment. Unfortunately existing tools such as unparam and unconvert expected the old behavior. In order to avoid breaking those tools, revert that part of the change. Fixes #26671 Change-Id: Ifa06542bd19cda9d682ac33766ab9080444ba050 Reviewed-on: https://go-review.googlesource.com/127658 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/go/scanner/scanner.go | 8 ++++++++ src/go/scanner/scanner_test.go | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go index 9f5855662d..23bbb2885f 100644 --- a/src/go/scanner/scanner.go +++ b/src/go/scanner/scanner.go @@ -259,6 +259,14 @@ func (s *Scanner) updateLineInfo(next, offs int, text []byte) { filename := string(text[:i-1]) // lop off ":line", and trim white space if filename == "" && ok2 { filename = s.file.Position(s.file.Pos(offs)).Filename + } else if filename != "" { + // Put a relative filename in the current directory. + // This is for compatibility with earlier releases. + // See issue 26671. + filename = filepath.Clean(filename) + if !filepath.IsAbs(filename) { + filename = filepath.Join(s.dir, filename) + } } s.file.AddLineColumnInfo(next, filename, line, col) diff --git a/src/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go index 7cc79fa820..0aad368099 100644 --- a/src/go/scanner/scanner_test.go +++ b/src/go/scanner/scanner_test.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "testing" ) @@ -204,7 +205,9 @@ func newlineCount(s string) int { func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) { pos := fset.Position(p) - if pos.Filename != expected.Filename { + // Check cleaned filenames so that we don't have to worry about + // different os.PathSeparator values. + if pos.Filename != expected.Filename && filepath.Clean(pos.Filename) != filepath.Clean(expected.Filename) { t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename) } if pos.Offset != expected.Offset { @@ -520,7 +523,7 @@ var segments = []segment{ {"\n //line foo:42\n line43", "foo\t", 44, 0}, // bad line comment, ignored (use existing, prior filename) {"\n//line foo 42\n line44", "foo\t", 46, 0}, // bad line comment, ignored (use existing, prior filename) {"\n//line /bar:42\n line45", "/bar", 42, 0}, - {"\n//line ./foo:42\n line46", "./foo", 42, 0}, + {"\n//line ./foo:42\n line46", "foo", 42, 0}, {"\n//line a/b/c/File1.go:100\n line100", "a/b/c/File1.go", 100, 0}, {"\n//line c:\\bar:42\n line200", "c:\\bar", 42, 0}, {"\n//line c:\\dir\\File1.go:100\n line201", "c:\\dir\\File1.go", 100, 0}, @@ -539,9 +542,32 @@ var segments = []segment{ {"\n/*line foo:100:10*/\n\nf2", "foo", 102, 1}, // absolute column since on new line } +var dirsegments = []segment{ + // exactly one token per line since the test consumes one token per segment + {" line1", "TestLineDir/TestLineDirectives", 1, 3}, + {"\n//line File1.go:100\n line100", "TestLineDir/File1.go", 100, 0}, +} + +var dirUnixSegments = []segment{ + {"\n//line /bar:42\n line42", "/bar", 42, 0}, +} + +var dirWindowsSegments = []segment{ + {"\n//line c:\\bar:42\n line42", "c:\\bar", 42, 0}, +} + // Verify that line directives are interpreted correctly. func TestLineDirectives(t *testing.T) { - // make source + testSegments(t, segments, "TestLineDirectives") + testSegments(t, dirsegments, "TestLineDir/TestLineDirectives") + if runtime.GOOS == "windows" { + testSegments(t, dirWindowsSegments, "TestLineDir/TestLineDirectives") + } else { + testSegments(t, dirUnixSegments, "TestLineDir/TestLineDirectives") + } +} + +func testSegments(t *testing.T, segments []segment, filename string) { var src string for _, e := range segments { src += e.srcline @@ -549,7 +575,7 @@ func TestLineDirectives(t *testing.T) { // verify scan var S Scanner - file := fset.AddFile("TestLineDirectives", fset.Base(), len(src)) + file := fset.AddFile(filename, fset.Base(), len(src)) S.Init(file, []byte(src), func(pos token.Position, msg string) { t.Error(Error{pos, msg}) }, dontInsertSemis) for _, s := range segments { p, _, lit := S.Scan()