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

feat: extract type by node + add schema fuzz test #2138

Merged
merged 1 commit into from
Jul 24, 2024

Conversation

worstell
Copy link
Contributor

this change also allows us to support type Foo = external.Bar aliases

@worstell worstell requested a review from alecthomas as a code owner July 23, 2024 21:32
@worstell worstell requested review from a team and deniseli and removed request for a team July 23, 2024 21:32
@ftl-robot ftl-robot mentioned this pull request Jul 23, 2024
@worstell worstell force-pushed the worstell/20240718-wip branch 3 times, most recently from d955f10 to 8398587 Compare July 23, 2024 22:16
Comment on lines 59 to 79
if strings.HasPrefix(symbol, "[]") {
return &schema.Array{Element: getSchemaType(symbol[2:])}
}
if strings.HasPrefix(symbol, "map[") {
idx := strings.Index(symbol, "]")
if idx == 5 {
// handle map[[]...]...
idx = strings.Index(symbol[6:], "]") + 6
}
key := getSchemaType(symbol[4:idx])
value := getSchemaType(symbol[idx+1:])
return &schema.Map{Key: key, Value: value}
}
if strings.HasPrefix(symbol, "ftl.Option[") {
return &schema.Optional{Type: getSchemaType(symbol[11 : len(symbol)-1])}
}
panic(fmt.Sprintf("unexpected symbol: %s", symbol))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a ton of context here, but this seems a bit brittle. Is this just how things have to work here with string checking?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleaned up a little and added some comments to make it clearer, e.g. indexing after 4 because map[ is 4 characters log

Comment on lines 82 to 84
codeBuilder.WriteString("package test\n\n")
codeBuilder.WriteString(`import (` + "\n")
codeBuilder.WriteString(` "context"` + "\n")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better/easier to use raw string literals here instead of this codeBuilder? It seems a bit hard to write and update like this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true! looks better

}

// generate all possible permutations for slices, maps and ftl.Option[...]
func generatePermutations(symbols []string) []string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

niiiiice I wonder if we'll want to make this available as a general test util eventually

permutations = append(permutations, "[]"+symbol)
permutations = append(permutations, "ftl.Option["+symbol+"]")
for _, nestedSymbol := range symbols {
permutations = append(permutations, fmt.Sprintf("map[%s]%s", symbol, nestedSymbol))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would we ever need nested arrays like map[%s][]%s, or is that way overkill?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah i omitted because the performance becomes exponentially worse and it seemed untenable

Comment on lines 63 to 64
idx := strings.Index(symbol, "]")
if idx == 5 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this mistakenly capture map[a]blah where a is some single-character alias of a supported type, or have we already swapped out all aliased types for their underlying values by this point? I wonder if it'd safer to just strings.HasPrefix(symbol, "map[[]") even if it duplicates part of the check... at least it would let us remove the comment

}
}

func generateSourceCode(symbol string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we could templatize this to make it a bit more readable/maintainable? I've only used https://pkg.go.dev/text/template#Must in the past but it's very similar to the scaffolder stuff we have (maybe it's built on top of this... I never actually checked)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea!

verb sourceFunc(Unit) %s
}
`, typename, typename, typename, typename, typename, typename, typename, typename, valueenum, typeenum, typename,
typename, typename, typename, typename, typename, typename, typename) // there simply must be a better way
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think you could use https://pkg.go.dev/text/template#Must here too!

Comment on lines 87 to 99
unquoted, err := strconv.Unquote(tag.Value)
if err != nil {
common.Wrapf(pass, f, err, "failed to unquote tag value %q", tag.Value)
fieldErrors = true
}
tagContent := reflect.StructTag(unquoted).Get(aliasFieldTag)
tagParts := strings.Split(tagContent, ",")
jsonFieldName := ""
if len(tagParts) > 0 {
jsonFieldName = tagParts[0]
}

if jsonFieldName != "" {
metadata = append(metadata, &schema.MetadataAlias{
Pos: common.GoPosToSchemaPos(pass.Fset, node.Pos()),
Kind: schema.AliasKindJSON,
Alias: jsonFieldName,
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move this into a helper function (parseTag or something like that)?

@worstell worstell force-pushed the worstell/20240718-wip branch 9 times, most recently from a83d83f to 0e62479 Compare July 24, 2024 00:35
this change allows us to support `type Foo = external.Bar` aliases
@worstell worstell force-pushed the worstell/20240718-wip branch from 0e62479 to 5769ba0 Compare July 24, 2024 00:36
@worstell worstell merged commit 4275025 into main Jul 24, 2024
59 checks passed
@worstell worstell deleted the worstell/20240718-wip branch July 24, 2024 00:41
worstell added a commit that referenced this pull request Jul 24, 2024
worstell added a commit that referenced this pull request Jul 24, 2024
worstell added a commit that referenced this pull request Jul 24, 2024
this change also allows us to support `type Foo = external.Bar` aliases

fixes #2145
worstell added a commit that referenced this pull request Jul 24, 2024
user requested support for `type Foo = other.Bar` pattern when declaring type aliases. this allows them to leverage member functions of the underlying type.

after this change, the above pattern as well as the prior pattern, `type Foo other.Bar` will be supported for type aliasing.

also fixes #2145
worstell added a commit that referenced this pull request Jul 24, 2024
user requested support for `type Foo = other.Bar` pattern when declaring
type aliases. this allows them to leverage member functions of the
underlying type.

after this change, the above pattern as well as the prior pattern, `type
Foo other.Bar` will be supported for type aliasing.

also fixes #2145
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

Successfully merging this pull request may close these issues.

3 participants