Skip to content

Commit

Permalink
Refactor Underscore function
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianczech committed Apr 4, 2024
1 parent ab94bbf commit 1739eca
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 49 deletions.
108 changes: 59 additions & 49 deletions pkg/naming/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,88 +74,98 @@ func (o *Namer) NewSlug(name string) string {
// sections within the string, preserving their original form.
func CamelCase(prefix, value, suffix string, capitalizeFirstRune bool) string {
var builder strings.Builder
builder.Grow(len(prefix) + len(value) + len(suffix))

builder.WriteString(prefix)
prepareStringBuilder(prefix, value, suffix, builder)

isFirstCharacter := true
hasFirstRuneBeenCapitalized := false
isIgnoringTemplate := false

for _, runeValue := range value {
switch runeValue {
case '{':
isIgnoringTemplate = true
isFirstCharacter = true // Reset for the content after template
continue
case '}':
isIgnoringTemplate = false
if isTemplateDelimiter(runeValue, &isIgnoringTemplate) {
continue
}

if isIgnoringTemplate {
continue
}

if shouldResetFirstCharacterFlag(runeValue) {
isFirstCharacter = true
} else if isFirstCharacter {
capitalizeAndWriteRune(&builder, runeValue, hasFirstRuneBeenCapitalized || capitalizeFirstRune)
hasFirstRuneBeenCapitalized = true
isFirstCharacter = false
} else {
builder.WriteRune(runeValue)
}
writeRuneAndApplyChangesForCamelCase(runeValue, &builder, &isFirstCharacter, &hasFirstRuneBeenCapitalized, &capitalizeFirstRune)
}

builder.WriteString(suffix)
return builder.String()
}

// writeRuneAndApplyChangesForCamelCase contains logic to check all conditions for create CamelCase names and writes rune value.
func writeRuneAndApplyChangesForCamelCase(runeValue int32, builder *strings.Builder, isFirstCharacter *bool, hasFirstRuneBeenCapitalized *bool, capitalizeFirstRune *bool) {
if shouldResetFirstCharacterFlag(runeValue) {
*isFirstCharacter = true
} else if *isFirstCharacter {
capitalizeAndWriteRune(builder, runeValue, *hasFirstRuneBeenCapitalized || *capitalizeFirstRune)
*hasFirstRuneBeenCapitalized = true
*isFirstCharacter = false
} else {
builder.WriteRune(runeValue)
}
}

// Underscore converts a string to under_score format, allowing for optional prefixes/suffixes.
// It also skips over templated sections within the string, preserving their original form.
func Underscore(prefix, value, suffix string) string {
var builder strings.Builder
builder.Grow(len(prefix) + len(value) + len(suffix))

builder.WriteString(prefix)
prepareStringBuilder(prefix, value, suffix, builder)

isFirstCharacter := true
isIgnoringTemplate := false

for _, runeValue := range value {
switch runeValue {
case '{':
isIgnoringTemplate = true
isFirstCharacter = true // Reset for the content after template
continue
case '}':
isIgnoringTemplate = false
continue
}

if isIgnoringTemplate {
if isTemplateDelimiter(runeValue, &isIgnoringTemplate) {
continue
}

if shouldResetFirstCharacterFlag(runeValue) {
builder.WriteRune('_')
isFirstCharacter = true
} else if isFirstCharacter {
builder.WriteRune(unicode.ToLower(runeValue))
isFirstCharacter = false
} else if unicode.IsUpper(runeValue) {
builder.WriteRune('_')
builder.WriteRune(unicode.ToLower(runeValue))
} else {
builder.WriteRune(unicode.ToLower(runeValue))
}
writeRuneAndApplyChangesForUnderscore(runeValue, &builder, &isFirstCharacter)
}

builder.WriteString(suffix)
return builder.String()
}

// writeRuneAndApplyChangesForUnderscore contains logic to check all conditions for create under_score names and writes rune value.
func writeRuneAndApplyChangesForUnderscore(runeValue int32, builder *strings.Builder, isFirstCharacter *bool) {
if shouldResetFirstCharacterFlag(runeValue) {
appendUnderscore(builder)
*isFirstCharacter = true
} else if *isFirstCharacter {
capitalizeAndWriteRune(builder, runeValue, false)
*isFirstCharacter = false
} else if unicode.IsUpper(runeValue) {
appendUnderscore(builder)
capitalizeAndWriteRune(builder, runeValue, false)
} else {
capitalizeAndWriteRune(builder, runeValue, false)
}
}

// appendUnderscore add _ to builder, from which final result is built.
func appendUnderscore(builder *strings.Builder) {
builder.WriteRune('_')
}

// isTemplateDelimiter return true, if { or } are runeValue or isIgnoringTemplate is set to true.
func isTemplateDelimiter(runeValue int32, isIgnoringTemplate *bool) bool {
switch runeValue {
case '{':
*isIgnoringTemplate = true
return true
case '}':
*isIgnoringTemplate = false
return true // if we finish template, then we always ignore that character, even if set isIgnoringTemplate to false
}

return *isIgnoringTemplate
}

func prepareStringBuilder(prefix string, value string, suffix string, builder strings.Builder) {
builder.Grow(len(prefix) + len(value) + len(suffix))
builder.WriteString(prefix)
}

// shouldResetFirstCharacterFlag checks if the given rune is a separator that should trigger
// the next character to be capitalized in CamelCase conversion.
func shouldResetFirstCharacterFlag(r rune) bool {
Expand Down
5 changes: 5 additions & 0 deletions pkg/naming/names_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import (
func TestCamelCase(t *testing.T) {
assert.Equal(t, "CamelCase", CamelCase("", "camel_case", "", true))
assert.Equal(t, "camelCase", CamelCase("", "camel_case", "", false))
assert.Equal(t, "camelCase", CamelCase("", "camel_case", "", false))
assert.Equal(t, "camelCase", CamelCase("", "camel_{template_example}case", "", false))
assert.Equal(t, "camelCase", CamelCase("", "camel_case{template_example}", "", false))
}

func TestUnderscore(t *testing.T) {
assert.Equal(t, "under_score", Underscore("", "under score", ""))
assert.Equal(t, "under_score", Underscore("", "under_score", ""))
assert.Equal(t, "under_score", Underscore("", "UnderScore", ""))
assert.Equal(t, "under_score", Underscore("", "underScore", ""))
assert.Equal(t, "under_score", Underscore("", "underScore{template_example}", ""))
assert.Equal(t, "under_score", Underscore("", "under{template_example}Score", ""))
}

func TestAlphaNumeric(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions pkg/translate/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package translate

import "github.com/paloaltonetworks/pan-os-codegen/pkg/imports"

// RenderImports render string, which contains import required in entry, location or service template.
func RenderImports(templateType string) (string, error) {
manager := imports.NewManager()

Expand Down

0 comments on commit 1739eca

Please sign in to comment.