diff --git a/CHANGELOG.md b/CHANGELOG.md index 15d63c3eb2..e48b4c6100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ `ignore: [!foo/bar.proto]`. Previously they parsed as empty strings, now they rejected with an error. - Fix lint comment ignores on proto2 `group` fields being ignored. +- Update the LSP to support named generation templates such as `buf.go.gen.yaml` and + `buf.gen.go.yaml`. - Improve the `buf curl` error message for methods that accept a single request message. - Deduplicate remote input fetches within a single command invocation, so that multiple `inputs` in a `buf.gen.yaml` that resolve to the same archive, git repository, or image diff --git a/private/buf/buflsp/buf_gen_yaml.go b/private/buf/buflsp/buf_gen_yaml.go index d0b09b9cb1..ecf6e48333 100644 --- a/private/buf/buflsp/buf_gen_yaml.go +++ b/private/buf/buflsp/buf_gen_yaml.go @@ -21,6 +21,7 @@ import ( "log/slog" "os" "path/filepath" + "strings" "sync" "buf.build/go/standard/xos/xexec" @@ -38,9 +39,13 @@ const CommandRunGenerate = "buf.generate.run" // plugins in a buf.gen.yaml file and publish informational diagnostics for any that are outdated. const CommandCheckPluginUpdates = "buf.generate.checkPluginUpdates" -// isBufGenYAMLURI reports whether uri refers to a buf.gen.yaml file. +// isBufGenYAMLURI reports whether uri refers to a buf.gen.yaml file. Named +// templates such as buf.go.gen.yaml and buf.gen.go.yaml are also matched, since +// they are commonly passed to buf generate with --template. func isBufGenYAMLURI(uri protocol.URI) bool { - return filepath.Base(uri.Filename()) == bufconfig.DefaultBufGenYAMLFileName + name := filepath.Base(uri.Filename()) + return (strings.HasPrefix(name, "buf.") && strings.HasSuffix(name, ".gen.yaml")) || + (strings.HasPrefix(name, "buf.gen.") && strings.HasSuffix(name, ".yaml")) } // bufGenYAMLManager tracks open buf.gen.yaml files in the LSP session. @@ -213,8 +218,9 @@ func (m *bufGenYAMLManager) GetCodeLenses(uri protocol.URI) []protocol.CodeLens return lenses } -// ExecuteRunGenerate runs buf generate in the directory containing the given -// buf.gen.yaml URI. Results are reported to the user via ShowMessage. +// ExecuteRunGenerate runs buf generate with the given buf.gen.yaml URI as the +// template, from the directory containing it. Results are reported to the user +// via ShowMessage. func (m *bufGenYAMLManager) ExecuteRunGenerate(ctx context.Context, uri protocol.URI) error { dirPath := filepath.Dir(uri.Filename()) executable, err := os.Executable() @@ -225,7 +231,7 @@ func (m *bufGenYAMLManager) ExecuteRunGenerate(ctx context.Context, uri protocol msg := "buf generate completed successfully" var outBuf bytes.Buffer if err := xexec.Run(ctx, executable, - xexec.WithArgs("generate"), + xexec.WithArgs(bufGenerateArgs(uri)...), xexec.WithDir(dirPath), xexec.WithStdout(&outBuf), xexec.WithStderr(&outBuf), @@ -240,6 +246,15 @@ func (m *bufGenYAMLManager) ExecuteRunGenerate(ctx context.Context, uri protocol return nil } +// bufGenerateArgs returns the buf generate arguments for the template at uri. +func bufGenerateArgs(uri protocol.URI) []string { + name := filepath.Base(uri.Filename()) + if name == bufconfig.DefaultBufGenYAMLFileName { + return []string{"generate"} + } + return []string{"generate", "--template", name} +} + // ExecuteCheckPluginUpdates queries the BSR for the latest version of each // versioned remote plugin in the buf.gen.yaml file and publishes an // informational diagnostic on any plugin line where a newer version is diff --git a/private/buf/buflsp/buf_gen_yaml_lsp_test.go b/private/buf/buflsp/buf_gen_yaml_lsp_test.go index fd86e6290f..208a47adcf 100644 --- a/private/buf/buflsp/buf_gen_yaml_lsp_test.go +++ b/private/buf/buflsp/buf_gen_yaml_lsp_test.go @@ -631,6 +631,14 @@ func TestBufGenYAMLCodeLens(t *testing.T) { wantRunLensLine: 0, wantCheckLensLine: 1, // plugins: key is on line 1 }, + { + name: "named_template", + fixture: "testdata/buf_gen_yaml/named_template/buf.go.gen.yaml", + wantCount: 2, + wantTitles: []string{"Run buf generate", "Check for plugin updates"}, + wantRunLensLine: 0, + wantCheckLensLine: 1, + }, } for _, tc := range tests { diff --git a/private/buf/buflsp/buf_yaml_test.go b/private/buf/buflsp/buf_yaml_test.go index a4a39777ee..5a27c08209 100644 --- a/private/buf/buflsp/buf_yaml_test.go +++ b/private/buf/buflsp/buf_yaml_test.go @@ -133,8 +133,18 @@ func TestIsBufGenYAMLURI(t *testing.T) { expected bool }{ {"file:///home/user/project/buf.gen.yaml", true}, + {"file:///home/user/project/buf.go.gen.yaml", true}, + {"file:///home/user/project/buf.connect-go.gen.yaml", true}, + {"file:///home/user/project/buf.gen.go.yaml", true}, + {"file:///home/user/project/buf.gen-private.yaml", false}, + {"file:///home/user/project/buf-go.gen.yaml", false}, + {"file:///home/user/project/bufgo.gen.yaml", false}, + {"file:///home/user/project/buf.generated.yaml", false}, {"file:///home/user/project/buf.yaml", false}, + {"file:///home/user/project/buf.work.yaml", false}, + {"file:///home/user/project/buf.policy.yaml", false}, {"file:///home/user/project/buf.gen.yaml.bak", false}, + {"file:///home/user/project/mybuf.gen.yaml", false}, {"file:///home/user/project/foo.proto", false}, } @@ -146,6 +156,25 @@ func TestIsBufGenYAMLURI(t *testing.T) { } } +func TestBufGenerateArgs(t *testing.T) { + t.Parallel() + + tests := []struct { + uri protocol.URI + expected []string + }{ + {"file:///home/user/project/buf.gen.yaml", []string{"generate"}}, + {"file:///home/user/project/buf.go.gen.yaml", []string{"generate", "--template", "buf.go.gen.yaml"}}, + } + + for _, tt := range tests { + t.Run(string(tt.uri), func(t *testing.T) { + t.Parallel() + assert.Equal(t, tt.expected, bufGenerateArgs(tt.uri)) + }) + } +} + func TestIsBufPolicyYAMLURI(t *testing.T) { t.Parallel() diff --git a/private/buf/buflsp/testdata/buf_gen_yaml/named_template/buf.go.gen.yaml b/private/buf/buflsp/testdata/buf_gen_yaml/named_template/buf.go.gen.yaml new file mode 100644 index 0000000000..c2e1b52320 --- /dev/null +++ b/private/buf/buflsp/testdata/buf_gen_yaml/named_template/buf.go.gen.yaml @@ -0,0 +1,11 @@ +version: v2 +plugins: + - remote: buf.build/protocolbuffers/go + out: gen/go + - remote: buf.build/bufbuild/es:v2.2.2 + out: gen/es + - local: protoc-gen-custom + out: gen/custom +inputs: + - module: buf.build/acme/petapis + - directory: proto