Repository: go
Issue: go/token: line adjustment is incorrect for comments when imports are present
Labels: NeedsInvestigation

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.17.7 linux/amd64
</pre>

### Does this issue reproduce with the latest release?

Yes.

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/home/user/bin"
GOCACHE="/home/user/.cache/go-build"
GOENV="/home/user/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/user/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/user"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/user/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/user/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.7"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2236448890=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on go.dev/play is best.
-->

https://go.dev/play/p/3FdwLDhsXfD

### What did you expect to see?

Consistent line adjustment independent of the number of imports.
```
0
	dummy.tmpl:8
1
	dummy.tmpl:8
2
	dummy.tmpl:8
3
	dummy.tmpl:8
```

### What did you see instead?

Broken line adjustment if imports exist.

```
0
	dummy.tmpl:8
1
	file.go:9:1
2
	file.go:10:1
3
	file.go:11:1
```

An empty `import ()` also causes this breakage.

Additional note, this appears only to affect comments.

## Cause

This appears to be at least in part due to a discordance between how an `*ast.CommentGroup`'s position is calculated and how a `//line` directive works. When a line directive is part of a comment group, its pos is used to define the position of the comment group, but it refers to the next line. So changing the `Pos` method like so
```
func (g *CommentGroup) Pos() token.Pos {
	for _, c := range g.List {
		if !isDirective(c.Text[2:]) {
			return c.Pos()
		}
	}
	return g.List[0].Pos()
}
```
fixes the issue. This doesn't explain why imports affect the behaviour and I don't believe that it's a sensible fix.

It also raises a question about why the issue is also present when there is a blank line separating the directive from the comment group, when this is the case, the separated lines are still joined into the comment group. The reason for this is [here](https://github.com/golang/go/blob/a064a4f29a97a4fc7398d1ac9d7c53c5ba0bc646/src/go/parser/parser.go#L213) where a single blank line is allowed between comment lines, but I don't understand why separated comments blocks should end up in the same comment group.