Repository: go
Issue: cmd/go: set module root directory so editors/scripts see filenames in error messages relative to current directory
Labels: NeedsDecision,FeatureRequest,GoCommand,modules,Tools

<!--
Please answer these questions before submitting your issue. Thanks!
For questions please use one of our forums: https://github.com/golang/go/wiki/Questions
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.16.6 linux/amd64

</pre>

### Does this issue reproduce with the latest release?



### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jwatte/.cache/go-build"
GOENV="/home/jwatte/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/jwatte/observe/code/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/jwatte/observe/code/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.6"
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-build1083558025=/tmp/go-build -gno-record-gcc-switches"

</pre></details>

### What did you do?

First: This issue is created based on the discussion of https://github.com/golang/go/issues/47363 but given that that issue was closed without any resolution to the underlying problem, as it didn't make the problem clear enough, here is the refined issue.

### What did you see?

This issue is a "user story" (in the sense of "a legitimate user need that is currently not fulfilled") and could be solved in more than one way. Abbreviating from the conclusion, the behavior "the working directory determines the module" coupled with the behavior "diagnostic file names are printed relative to the working directory" breaks a lot of existing tooling in real-world projects.

  * If `go build|run|test ./path/to/directory` used the indicated directory as the root from which to discover which module it's in
  * If the `go` command had an option `--module-path` that overrode what the current directory was when determining which module it's in
  * If there existed an option `--print-full-paths` that made `go` tooling print full paths to files in error/failure messages, rather than relative to the current working directory

### What did you expect to see?

The problem is one of "I'm a user of go, Typescript, C++, protobuf, and a number of other languages, that all live in a single monorepo, and I want editors to be able to build and test code, and open the correct file when it fails, no matter what particular language is involved in the failure."

One of the subdirectories of this repo contains go code. The root of this monorepo is not a go module. I may not even be focused on a go module when I want to build integration tests.

The working directory of the editor (be it vim, emacs, vscode, or something else) is the root of the monorepo, which is not inside the go module.

Build and test commands invoked by the editor end up being run from the current working directory of the editor, which is the root of the monorepo ;they provide the relative path of the file in question from the editor working directory as argument. This works fine for all the other languages we use.

Currently, I can't find a good way of gluing this presumably not uncommon setup into the go build system, such that the error parser of each kind of editor (vim, emacs, vscode, and more) will find and open the correct file for a test failure (or build failure.)

For the tooling and editors we use, the following things are true:

* Working directory is the root of the monorepo, e g `/home/me/checkout`
* Builds/tests may span more than one language/module, and do something like `make -C cpp/path/module` that's appropriate for each language
* Errors are printed relative to the CWD, thus an error in a cpp file will say `subdir/path/module/include/someheader.h:123: template is too complex`, or errors are printed with full paths to filenames.
* All existing tooling and editors work great in building and testing, and they find the file to open

`go` builds used to do `go test ./go/src/whatever/package` and that used to work (and with `GO111MODULE` still works)
With `GO111MODULE` turned off, that invocation now errors out, complaining that the CWD is not within a module, even though the interesting directory in question is within a module.

For purposes of this comment, let's consider an overall project that looks like:

<pre>/home/me/mything:
  cpp/
  docs/
  go/
    src/
      whatever/
        go.mod
        vendor/
        package/
          some_test.go
  haskell/
  typescript/
  react/
</pre>

If I were to change the build command for the go package to do something like `cd go/src/whatever && go test ./package` then the filename printed will be `package/myfile_test.go:123: insufficient shoe size` which is relative to `go/src/whatever`, not relative to the editor CWD, and thus the editor won't find and open the file.

Best would be "if a directory is the argument to the command, then determine the module based on that directory, not based on the CWD" which would make the current setup Just Work.

Second best would be "allow the module-to-assume to be specified using a separate command line option" which means we could specify the go build/test command as go test --module-root=./go/src/whatever whatever/package -- this is a little more cumbersome because of the duplication of "whatever" in the path (it's both the root of the module, and the root package name) but it can be made to work.

Third best would be a command line option that forces the tooling to always output full path filenames. This will let the editor find the right file no matter what the working directory is. We'd invoke it like cd go/src/whatever && go test --print-full-paths whatever/package