Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: gopls imports -w <file> does not update the imports statement #58891

Open
nickwells opened this issue Mar 6, 2023 · 0 comments
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.

Comments

@nickwells
Copy link

ATTENTION: Please answer these questions BEFORE submitting your issue. Thanks!

What did you do?

When I run "gopls" from within a Go program (using the exec package) against a file in a temporary directory in macOS the imports statement is not updated if I give the full pathname but is if I give a relative pathname.

Note:

  • this only happens on a Mac, not on Linux
  • It only happens if I run gopls from within a Go program, running it from the command line works
  • it only happens if I run it for a file within a newly created temp dir as generated by calling os.MkdirTemp("", ...), a temp dir in my home directory doesn't have this problem (but one in "/tmp" has the same problem)
  • only the imports subcommand has a problem, "gopls format -w " successfully updates the file
  • other import statement generators work - "goimports -w " successfully updates the file

The following program demonstrates the issue:

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

const (
	filename      = "ggg.go"
	progname      = "ggg"
	tmpDirPattern = "ggg-*"

	fileTextStr = `package main
func main() {
fmt.Println("Hello")
}

`
)

var fileText = []byte(fileTextStr)

// execCmd ...
func execCmd(prog string, args ...string) {
	name := prog + " " + strings.Join(args, " ")
	fmt.Println(name)

	cmd := exec.Command(prog, args...)
	cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
	err := cmd.Run()

	reportErr(name, err)
}

// reportErr reports the error if not nil and exits
func reportErr(name string, err error) {
	if err == nil {
		return
	}
	fmt.Println(name+": Error: ", err)
	os.Exit(1)
}

// cmp compares the contents of the file with the supplied original text. If
// they differ it will report the difference
func cmp(origText []byte, fileName string, showFileDiffs bool) {
	text, err := os.ReadFile(fileName)
	reportErr("reading file: "+fileName, err)
	differs := len(origText) != len(text)

	if !differs {
		for i, ch := range origText {
			if text[i] != ch {
				differs = true
				break
			}
		}
	}

	if !differs {
		fmt.Println("File is unchanged")
	} else {
		fmt.Println("File has changed")
		if showFileDiffs {
			fmt.Println("Before")
			fmt.Println(string(origText))
			fmt.Println("After")
			fmt.Println(string(text))
		}
	}
}

func main() {
	var desc,
		tmpDir string
	var goplsAct = "imports"

	var useRelName,
		useGoImports,
		showFileDiffs bool

	flag.BoolVar(&useRelName, "rel", false, "use the relative pathname")
	flag.BoolVar(&showFileDiffs, "show", false, "show the differences")
	flag.BoolVar(&useGoImports, "use-goimp", false, "use goimports not gopls")
	flag.StringVar(&tmpDir, "tmp", "", "use this as base temp dir")
	flag.StringVar(&goplsAct, "act", "imports", "the gopls action")
	flag.Parse()

	desc = `MkdirTemp("` + tmpDir + `", "` + tmpDirPattern + `")`
	fmt.Println(desc)
	dir, err := os.MkdirTemp(tmpDir, tmpDirPattern)
	reportErr(desc, err)

	desc = "Chdir " + dir
	fmt.Println(desc)
	err = os.Chdir(dir)
	reportErr(desc, err)

	execCmd("go", "mod", "init", progname)

	desc = "WriteFile " + filename
	fmt.Println(desc)
	err = os.WriteFile(filename, fileText, 0666)
	reportErr(desc, err)

	filePath := filepath.Join(dir, filename)
	if useRelName {
		filePath = filename
	}
	if useGoImports {
		execCmd("goimports", "-w", filePath)
	} else {
		execCmd("gopls", goplsAct, "-w", filePath)
	}
	cmp(fileText, filePath, showFileDiffs)

	execCmd("go", "mod", "tidy")

	execCmd("go", "build")

	execPath := filepath.Join(dir, progname)
	execCmd(execPath)
}

What did you expect to see?

I expected the Go program to have the imports statement filled in

What did you see instead?

The file was unchanged

Build info

the OS version as given by uname -a is

Darwin Nicholass-MBP.broadband 21.6.0 Darwin Kernel Version 21.6.0: Mon Dec 19 20:44:01 PST 2022; root:xnu-8020.240.18~2/RELEASE_X86_64 x86_64

golang.org/x/tools/gopls v0.11.0
    golang.org/x/tools/gopls@v0.11.0 h1:/nvKHdTtePQmrv9XN3gIUN9MOdUrKzO/dcqgbG6x8EY=
    github.com/BurntSushi/toml@v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
    github.com/google/go-cmp@v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
    github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
    golang.org/x/exp@v0.0.0-20221031165847-c99f073a8326 h1:QfTh0HpN6hlw6D3vu8DAwC8pBIwikq0AI1evdm+FksE=
    golang.org/x/exp/typeparams@v0.0.0-20221031165847-c99f073a8326 h1:fl8k2zg28yA23264d82M4dp+YlJ3ngDcpuB1bewkQi4=
    golang.org/x/mod@v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
    golang.org/x/sync@v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
    golang.org/x/sys@v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
    golang.org/x/text@v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
    golang.org/x/tools@v0.3.1-0.20221213193459-ca17b2c27ca8 h1:7/HkGkN/2ktghBCSRRgp31wAww4syfsW52tj7yirjWk=
    golang.org/x/vuln@v0.0.0-20221109205719-3af8368ee4fe h1:qptQiQwEpETwDiz85LKtChqif9xhVkAm8Nhxs0xnTww=
    honnef.co/go/tools@v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA=
    mvdan.cc/gofumpt@v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM=
    mvdan.cc/xurls/v2@v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
go: go1.20.1
@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Mar 6, 2023
@gopherbot gopherbot added this to the Unreleased milestone Mar 6, 2023
@hyangah hyangah modified the milestones: Unreleased, gopls/unplanned Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

3 participants