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
33 changes: 33 additions & 0 deletions internal/librarian/java/readme.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"path/filepath"
"regexp"
"strings"
"unicode"
"unicode/utf8"
)

var (
Expand Down Expand Up @@ -167,6 +169,37 @@ func extractTitle(filePath string) (string, error) {
return title, nil
}

// toCamelCase converts snake_case, kebab-case, or space-separated strings into CamelCase identifiers.
func toCamelCase(s string) string {
parts := strings.FieldsFunc(s, func(r rune) bool {
return r == '_' || r == '-' || r == ' '
})
var sb strings.Builder
for _, p := range parts {
r, size := utf8.DecodeRuneInString(p)
sb.WriteRune(unicode.ToUpper(r))
sb.WriteString(p[size:])
}
return sb.String()
}

// parseGroupIDArtifactID extracts GroupID and ArtifactID from a Maven distribution name.
func parseGroupIDArtifactID(distributionName string) (string, string) {
groupID, artifactID, _ := strings.Cut(distributionName, ":")
return groupID, artifactID
}

// parseRepoShortName extracts the short repository name from the full repo path.
func parseRepoShortName(repo string) string {
if repo == "" {
return ""
}
if i := strings.LastIndexByte(repo, '/'); i >= 0 {
return repo[i+1:]
}
return repo
}

// collectSnippetFiles recursively scans dir/samples for Java and XML files containing snippets.
func collectSnippetFiles(dir string) ([]string, error) {
samplesDir := filepath.Join(dir, "samples")
Expand Down
110 changes: 110 additions & 0 deletions internal/librarian/java/readme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,116 @@ func TestExtractTitle_Error(t *testing.T) {
}
}

func TestToCamelCase(t *testing.T) {
for _, test := range []struct {
name string
input string
want string
}{
{
name: "snake case",
input: "custom_content",
want: "CustomContent",
},
{
name: "kebab case",
input: "readme-partials",
want: "ReadmePartials",
},
{
name: "space separated",
input: "about us",
want: "AboutUs",
},
{
name: "already camel",
input: "About",
want: "About",
},
{
name: "empty string",
input: "",
want: "",
},
} {
t.Run(test.name, func(t *testing.T) {
got := toCamelCase(test.input)
if diff := cmp.Diff(test.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}

func TestParseGroupIDArtifactID(t *testing.T) {
for _, test := range []struct {
name string
input string
wantGroupID string
wantArtifactID string
}{
{
name: "standard coordinates",
input: "com.google.cloud:google-cloud-storage",
wantGroupID: "com.google.cloud",
wantArtifactID: "google-cloud-storage",
},
{
name: "missing artifact id",
input: "com.google.cloud",
wantGroupID: "com.google.cloud",
wantArtifactID: "",
},
{
name: "empty distribution name",
input: "",
wantGroupID: "",
wantArtifactID: "",
},
} {
t.Run(test.name, func(t *testing.T) {
gotGroup, gotArtifact := parseGroupIDArtifactID(test.input)
if diff := cmp.Diff(test.wantGroupID, gotGroup); diff != "" {
t.Errorf("group ID mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(test.wantArtifactID, gotArtifact); diff != "" {
t.Errorf("artifact ID mismatch (-want +got):\n%s", diff)
}
})
}
}

func TestParseRepoShortName(t *testing.T) {
for _, test := range []struct {
name string
input string
want string
}{
{
name: "full repo path",
input: "googleapis/google-cloud-java",
want: "google-cloud-java",
},
{
name: "short repo name only",
input: "google-cloud-java",
want: "google-cloud-java",
},
{
name: "empty repo string",
input: "",
want: "",
},
} {
t.Run(test.name, func(t *testing.T) {
got := parseRepoShortName(test.input)
if diff := cmp.Diff(test.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}

func TestCollectSnippetFiles(t *testing.T) {
for _, test := range []struct {
name string
Expand Down
Loading