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

tools: merge gomodifytags functionality into gopls and use gopls #2002

Open
hyangah opened this issue Jan 7, 2022 · 3 comments
Open

tools: merge gomodifytags functionality into gopls and use gopls #2002

hyangah opened this issue Jan 7, 2022 · 3 comments
Assignees

Comments

@hyangah
Copy link
Contributor

hyangah commented Jan 7, 2022

From #1652

Function: modify tags on structs (go.add.tags, go.remove.tags commands)
Proposal:

  • Option 1: do nothing and keep using gomodifytags.
  • Option 2: implement from gopls: can we refactor gomodifytags and reuse it from gopls? (cc @fatih)
@gopherbot gopherbot added this to the Untriaged milestone Jan 7, 2022
@hyangah hyangah modified the milestones: Untriaged, On Deck Jan 7, 2022
fatih added a commit to fatih/gomodifytags that referenced this issue Jan 17, 2022
This PR moves the `gomodifytags` tool into its own package so it can be
imported by other applications (i.e: `gopls`). It's currently
delibaretly put under `internal`, as I want to make sure it meets the
needs of others.

related: golang/vscode-go#2002
fatih added a commit to fatih/gomodifytags that referenced this issue Jan 17, 2022
This PR moves the `gomodifytags` tool into its package to be imported by other applications (i.e.: `gopls`). It's currently deliberately put under `internal`, as I want to make sure it meets the needs of others.

related: golang/vscode-go#2002
@fatih
Copy link
Member

fatih commented Jan 17, 2022

@hyangah Hi 👋🏼

When I created gomodifytags years ago, I made sure to write it so other applications could import it in the future. Here is a PR for the initial stab on putting it into a package that can be imported (not now, but later): fatih/gomodifytags#89

It's currently inside an internal folder as I want to make sure it works well for gopls before making it part of the public package. For example, the error message contains references to flags, even though in gopls there will be no flags as I know.

Let me know what you think and how you think we should proceed. For example, do we want to make gomodifytags part of gopls by copying the code into the codebase of gopls? Or do we want to import it and keep it under fatih/gomodifytags? I worked years on this project, it's battle tested and has hundreds of regression tests, so I think it's in a perfect position to be either imported or copied into gopls. Again, just let me think what is best for gopls.

@hyangah
Copy link
Contributor Author

hyangah commented Jan 18, 2022

Hi! Thanks a lot @fatih!

cc @findleyr for API & gopls integration advice:

Skimming through your PR, the new API will be like

type Config struct {
	fset *token.FileSet

	File     string
	Output   string
	Quiet    bool
	Write    bool
	Modified io.Reader

	Offset     int
	StructName string
	FieldName  string
	Line       string
	Start, End int
	All        bool

	Remove        []string
	RemoveOptions []string

	Add                  []string
	AddOptions           []string
	Override             bool
	SkipUnexportedFields bool

	Transform   string
	Sort        bool
	ValueFormat string
	Clear       bool
	ClearOption bool
}

// Run runs gomodifytags with the config.
func (c *Config) Run() error {...}

Currently Config specifies the input (io.Reader) and the output is stdout, in addition to the flags that determine the logic of gomodifytags.

Gopls does the custom command integration within the x/tools/internal/lsp/command framework. Gopls manages the snapshot of the parsed file including the overlay treatment, and the framework allows the integrated tool to access data available in source.Snapshot. The output should be communicated back to the client (editor) using LSP messages.

So, I think it would allow us more efficient integration if the API simply lets the caller handle read/parse/output part, takes ast.Node(and the gomodifytags-specific flags) and returns a new ast.Node or the edit. Then, gopls can process the edit or diff and translate it to LSP TextDocumentEdit message. What do you think, (@fatih @findleyr )?

For example, gopls is implementing VS Code's add_import feature like this https://cs.opensource.google/go/x/tools/+/refs/tags/v0.1.8:internal/lsp/command.go;l=684-701.

I think it's better to keep it under fatih/gomodifytags. Exposing the final API as a publicly available package will make our job easier, bug keeping it internal is also ok for short term - we can automate copying if necessary.

@findleyr
Copy link
Contributor

Thank you @fatih!

I also only skimmed the PR, but have a couple thoughts:

  • We need to be able to pass our view of the overlay. It looks like this may be possible via the Config.Modified field? That may work, though being able to pass an *ast.File or *ast.Node directly could be better, as Hana suggests.
  • I agree with @hyangah that we'd rather call a library than maintain our own copy. However, we can't do this until we refactor to allow adding custom commands from the golang.org/x/tools/gopls module (we can't currently add third-party module imports to x/tools). We'll look into this.

@hyangah hyangah modified the milestones: On Deck, Unplanned Feb 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants