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

models: IsInterface doesn't work with named interfaces #33

Closed
switchupcb opened this issue Nov 25, 2022 · 1 comment
Closed

models: IsInterface doesn't work with named interfaces #33

switchupcb opened this issue Nov 25, 2022 · 1 comment
Labels
edge case An error occurred. enhancement New feature or request

Comments

@switchupcb
Copy link
Owner

Problem

The Field.IsInterface() function doesn't work for named interfaces. This occurs because — while parsing — named field's are deepcopied, then have their definition's replaced. Such that a string comparison of that definition (i.e NamedInterface[9:] == "interface") would return false. This function used to be resolved by checking a .Collection field (of models.Field), but that field was removed due to being unnecessary... until now.

Solution

Collection

The previous .Collection field specifies which type of collection (f.IsPointer() || (f.IsArray() || f.IsSlice() || f.IsMap() || f.IsChan()) || f.IsFunc() || f.IsInterface()) the field is. This field was removed in a previous version because it was being used to account for the actual type definition of the field (i.e *Account where Definition == "Account" and Collection == *). Not only did this contribute to confusion, but it also made generating type-to-type code harder.

Adding back the Collection field would not cause confusion anymore because it would not be used for any other portion of the code. However, expanding the purpose of this field to represent an Underlying type of the field may be more useful. Currently, there is no way to determine the underlying type of a field. As an example, a field id Number will have a Name=="id" and Definition=="Number"; Number is an alias to a string. However, there is currently no way to find more information about the underlying field string that Number represents.

Underlying

An Underlying field of a models.Field would represent the actual underlying type (in a models.Field object) if it exists. There is a distinction between the go/types Underlying() method and models.Field Underlying() method. In go/types, the underlying function represents a unique instance of a go/type, and can represent go/types that have underlying go/types (such that a "Named' type is nothing more than a go/types.Named type). In contrast, the models.Field underlying field represents a default type (in colloquial terms), which likely shares an instance with other default underlying types.

To be specific, models.Field objects typically represent the copygen definition of a field: These objects are created in a context which always gives them a Name (either in the Copygen Interface function parameters func(to string) from string or as a field of other models.Field structs, etc). In contrast, the model.Field present in the Field.Underlying field would represent actual default types (basic types, map, struct, interface, category.go) which a user (developer) can use to determine more information about a field's Go Type.

The objects contained in a .Underlying models.Field field should represent the same object when it represents the same Go type. As an example, id Number and word Word models.Field objects represent two different models.Field. However, since the underlying type of each models.Field.Definition is an alias (Number, Word) to a string, the Field.Underlying of each models.Field should point to the same object (which is a models.Field representation of a string).

Thus, it would be expected for users who — for whatever reason — modify the Underlying field of a models.Field to also modify the .Underlying field of every other models.Field that references it. Otherwise, the user can always use field.Deepcopy() prior to modifying that field, if that is ever necessary.

@switchupcb switchupcb added edge case An error occurred. enhancement New feature or request labels Nov 25, 2022
@switchupcb
Copy link
Owner Author

copygen is essentially becoming an abstraction of go/types which is centered around fields rather than types. It is also easier to get started since the UI is a visual interface, everything is parsed for you, and the generator doesn't have to be compiled for usage. The one thing that go/types has that Copygen does not is a way to find the type you are looking for without information. Well, in actuality it requires you to parse the AST, but then you can use a map to find your object from there. One way we could provide this functionality is by implementing a global map that maps the Function.Name + FullVariableName() of a field to it's models.Field representation.

@switchupcb switchupcb mentioned this issue Nov 25, 2022
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
edge case An error occurred. enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant