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()