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

Support all_extension_numbers_of_type reflection requests #1680

Merged
merged 10 commits into from
Oct 24, 2023

Conversation

stefanadranca
Copy link
Collaborator

@stefanadranca stefanadranca commented Oct 20, 2023

Motivation:

The reflection service should provide the possibility for users to request the list with all the field numbers of
the extensions of a type.

Modifications:

  • Implemented the dictionary that stores the arrays of integers representing the field numbers of the extensions
    for each type that has extensions.
  • Implemented the methods of the Reflection Service that create the specific response with the array of integers
    representing the field numbers or an empty array for the case that the type doesn't have any extensions (but is a valid type).
  • Implemented integration and Unit tests.

Result:

The Reflection Service will enable users to find all the extension field numbers for a specific type they requested.

…ion Service.

Motivation:

The reflection service should provide the possibility for users to request the list with all the field numbers of
the extensions of a type.

Modifications:

- Implemented the dictionary that stores the arrays of integers representing the field numbers of the extensions
for each type that has extensions.
- Implemented the methods of the Reflection Service that create the specific response with the array of integers
representing the field numbers or an empty array for the case that the type doesn't have any extensions (but is a valid type).
- Implemented integration and Unit tests.

Result:

The Reflection Service will enable users to find all the extension field numbers for a specific type they requested.
@stefanadranca stefanadranca marked this pull request as draft October 20, 2023 14:47
…ith a dot, and the typeName in the internal data structures of the registry is the fully qualified name of each type
@stefanadranca stefanadranca marked this pull request as ready for review October 23, 2023 13:18
Comment on lines 122 to 129
if self.fieldNumbersByType[typeName] == nil {
self.fieldNumbersByType[typeName] = []
}
let numberPosition = self.fieldNumbersByType[typeName]!.count
self.fieldNumbersByType[typeName]?.insert(
`extension`.number,
at: numberPosition
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

A couple of notes:

  1. Don't use insert if you want to add an element to the end of the array, use append
  2. We don't need to check whether there's a value in the dictionary and then insert an empty array. Instead we can use https://developer.apple.com/documentation/swift/dictionary/subscript(_:default:)

Comment on lines 138 to 143
internal static func extractTypeNameFrom(fullyQualifiedName name: String) -> String {
var nameCopy = name
if nameCopy.first == "." {
nameCopy.removeFirst()
}
return nameCopy
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't need a whole function for this, it's just a one liner:String(name.drop(while: { $0 == "." }))

fieldNumber number: Int32
) -> String? {
let key = ExtensionDescriptor(extendeeTypeName: extendeeName, fieldNumber: number)
return self.fileNameByExtensionDescriptor[key]
}

internal func extensionsFieldNumbersOfType(named typeName: String) -> [Int32]? {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional collections are rarely the right thing to do. Are we sure that we should return [Int32]? here vs [Int32]?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was following the pattern used for the other requests too, meaning that the functions of the registry could return nil, when the thing we are requesting for doesn't exist and the Reflection Service itself "decides" whether or not it should throw an error / send an error response. Should I change this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Does it make sense to distinguish between a nil-array and an empty one? If it does make sense then don't change this but document the distinction.

fieldNumber number: Int32
) -> String? {
let key = ExtensionDescriptor(extendeeTypeName: extendeeName, fieldNumber: number)
return self.fileNameByExtensionDescriptor[key]
}

// Returns nil if the type has no extensions or if it doesn't exist.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This behaviour is surprising: nil usually means the thing we were looking for didn't exist (e.g. consider dictionary["foo"]). Having it also return nil when the type exists but doesn't have any extensions isn't a good API because it places the onus on the caller to work out whether the type exists or not.

In this case we should probably just do the work upfront and ensure that fieldNumbersByType contains the right information, i.e. empty arrays when the type exists but has no extensions.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is still not right: the only reason we store messageTypeNames is to check whether a message exists in this function, it isn't used anywhere else.

When we create and populate fieldNumbersByType we should do so such it has a value for every type we know about, even if the value is an empty array. It means we do the work upfront and the semantics are clear: if a value exists then the type exists, if no value exists then we don't know about the type.

fieldNumber number: Int32
) -> String? {
let key = ExtensionDescriptor(extendeeTypeName: extendeeName, fieldNumber: number)
return self.fileNameByExtensionDescriptor[key]
}

// Returns nil if the type has no extensions or if it doesn't exist.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is still not right: the only reason we store messageTypeNames is to check whether a message exists in this function, it isn't used anywhere else.

When we create and populate fieldNumbersByType we should do so such it has a value for every type we know about, even if the value is an empty array. It means we do the work upfront and the semantics are clear: if a value exists then the type exists, if no value exists then we don't know about the type.

@glbrntt glbrntt merged commit ef5a0fe into grpc:main Oct 24, 2023
14 checks passed
@glbrntt glbrntt added the semver/patch No public API change. label Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants