Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion protoc-gen-twirpy/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func buildTwirpServiceDescription(messagesToFiles map[string]string, fd *descrip
FileName: name,
}

imports := newImportBuilder(messagesToFiles)
imports := newImportBuilder(messagesToFiles, name)

for _, service := range fd.GetService() {
serviceURL := fmt.Sprintf("%s.%s", fd.GetPackage(), service.GetName())
Expand Down
14 changes: 10 additions & 4 deletions protoc-gen-twirpy/generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import (
)

func TestImportBuilder(t *testing.T) {
// The current file being generated is in twirp/twitch/example/
testImportBuilder := newImportBuilder(map[string]string{
"twirp.twitch.example.Hat": "twirp/twitch/example/haberdasher.proto",
"twirp.twitch.example.Price": "twirp/twitch/example/haberdasher.proto",
"twirp.twitch.example.Color": "twirp/twitch/example_folder/haberdasher.proto",
"twirp.twitch.example.Size": "twirp/twitch/example/haberdasher_extension.proto",
"google.protobuf.Empty": "google/protobuf/empty.proto",
})
}, "twirp/twitch/example/service.proto")

testCases := []struct {
typeToImport string
Expand All @@ -24,26 +25,29 @@ func TestImportBuilder(t *testing.T) {
expectedImport *TwirpImport
}{
{
// Same package → relative import
typeToImport: "twirp.twitch.example.Hat",
importKey: "twirp.twitch.example.haberdasher_pb2",
qualifiedImport: "_haberdasher_pb2.Hat",
expectedImport: &TwirpImport{
From: "twirp.twitch.example",
From: ".",
Import: "haberdasher_pb2",
Alias: "_haberdasher_pb2",
},
},
{
// Same package, same file → reuses existing import
typeToImport: "twirp.twitch.example.Price",
importKey: "twirp.twitch.example.haberdasher_pb2",
qualifiedImport: "_haberdasher_pb2.Price",
expectedImport: &TwirpImport{
From: "twirp.twitch.example",
From: ".",
Import: "haberdasher_pb2",
Alias: "_haberdasher_pb2",
},
},
{
// Different package → absolute import
typeToImport: "twirp.twitch.example.Color",
importKey: "twirp.twitch.example_folder.haberdasher_pb2",
qualifiedImport: "_haberdasher_pb2_1.Color",
Expand All @@ -54,16 +58,18 @@ func TestImportBuilder(t *testing.T) {
},
},
{
// Same package, different file → relative import
typeToImport: "twirp.twitch.example.Size",
importKey: "twirp.twitch.example.haberdasher_extension_pb2",
qualifiedImport: "_haberdasher_extension_pb2.Size",
expectedImport: &TwirpImport{
From: "twirp.twitch.example",
From: ".",
Import: "haberdasher_extension_pb2",
Alias: "_haberdasher_extension_pb2",
},
},
{
// External package → absolute import
typeToImport: "google.protobuf.Empty",
importKey: "google.protobuf.empty_pb2",
qualifiedImport: "_empty_pb2.Empty",
Expand Down
18 changes: 17 additions & 1 deletion protoc-gen-twirpy/generator/import_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,25 @@ type importBuilder struct {
seenAliases map[string]struct{}
imports map[string]*TwirpImport
messagesToFile map[string]string
currentFileDir string
}

func newImportBuilder(messagesToFile map[string]string) *importBuilder {
func newImportBuilder(messagesToFile map[string]string, currentFileName string) *importBuilder {
// Extract directory from proto filename: "crypto/v1.proto" -> "crypto"
dir := ""
parts := strings.Split(currentFileName, "/")
if len(parts) > 1 {
dirParts := parts[:len(parts)-1]
for i, p := range dirParts {
dirParts[i] = strings.ReplaceAll(p, "-", "_")
}
dir = strings.Join(dirParts, ".")
}
return &importBuilder{
messagesToFile: messagesToFile,
seenAliases: make(map[string]struct{}),
imports: make(map[string]*TwirpImport),
currentFileDir: dir,
}
}

Expand All @@ -34,6 +46,10 @@ func (ib *importBuilder) addImportAndQualify(typeToImport string) (string, error
moduleNameSlice := strings.Split(moduleName, ".")
strippedModuleName := moduleNameSlice[len(moduleNameSlice)-1]
modulePath := strings.Join(moduleNameSlice[:len(moduleNameSlice)-1], ".")
// Use relative import when the module is in the same package as the file being generated
if modulePath == ib.currentFileDir {
modulePath = "."
}
alias := ib.generateAlias(strippedModuleName)
ib.imports[moduleName] = &TwirpImport{
From: modulePath,
Expand Down
Loading