Repository navigation
Conversation
Owner
|
Thanks for all of these, @we4sz. I've merged your other PRs and they'll go out in the next release. I'm going to close this one, though. Missing properties don't cause problems often enough to justify a change as sweeping as adding |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slack adds fields to its objects faster than SlackNet can add properties for them, and today only events (and message search results) have a way to get at the ones SlackNet doesn't know about yet:
Event.ExtraProperties, which I used in #264 before it got real properties. Every other model silently drops them. I ran into it building an app on SlackNet that needsis_email_confirmedfromusers.info:Userhas no property for it, so I read the raw response next to the typed one, and the same response also hadwho_can_share_contact_card,display_name_normalized,image_1024andis_custom_image. A property for each is its own change, and the next missing field will be on another type, so this gives every model what events have, once. It is eight commits, each one builds and passes the tests.SlackObject, an abstract base class withExtraProperties: a[JsonExtensionData]dictionary likeEventhas, declared once.User,UserProfile,Conversation,File,Team,BotInfo,UserGroup, ...), the Web API responses and what they contain, blocks and their elements, and the interaction, event, RTM and Socket Mode models. That is 252 classes, which makes 416 concrete types; the 129 events and four other types already had a catch-all of their own.ModelLintTests, in the style ofApiLintTestsandBlockLintTests. It fails for a public model that has no way to keep unknown properties, so the next model added has to derive fromSlackObject, and it checks that everySlackObjectkeeps an unknown property.Userwith its profile and enterprise user, aConversationwith its topic, and a section block with its text, through the API client and the event deserializer the way an app would, and a readme section.Compatibility
Additive: nothing that is sent to Slack changes. The dictionary is read-only for Json.NET (
WriteData = false): it is filled when Slack's JSON is read and never written, so an app that sends back an object it received, the blocks of a message for example, sends what SlackNet knows about and nothing else. I did that on purpose, because Slack may not accept on input everything it sends on output, and a catch-all for reading shouldn't change what is sent.Event.ExtraPropertiesis still written back, as before, soEventkeeps its own instead of deriving fromSlackObject.Which types don't derive from it:
Event,MessageSearchResult,Icons,ErrorResponseandWebApiResponsehave extension data of their own (Icons.Images,ErrorResponse.InfoandWebApiResponse.Dataare made from it). Json.NET fills one extension data member per type, the most derived one, so deriving as well would leaveExtraPropertiesempty. The lint names them.SlackRequestContextandSocketModeConnectionOptionslook like models to the lint but are local state and configuration, so it names them too.Link,FileUpload, theMessageResponsewrappers) are only built in code and sent, so Json.NET never fills them, and the internal response wrappers (UserResponseand so on) only carry the object an API method returns, which callers never see.Models that are only ever sent (
Message,Dialog, the view definitions, ...) have it too, and it is never filled. The rule is every model Json.NET can fill, which a lint can check, and I didn't want to guess which way each one goes.A class that derives from a SlackNet model and declares its own
[JsonExtensionData]keeps working: Json.NET fills that member and the inheritedExtraPropertiesstays empty (I checked with a subclass ofUser).Testing
ModelLintTestscovers all 549 concrete models SlackNet has: 416 derive fromSlackObject, 129 are events and 4 have their own. A new model that forgets the base failsAllModelsHaveACatchAllForUnknownProperties(I tried it), andUnknownPropertiesAreReadButNotWrittenfails for all 416 if the dictionary is made to write back (I tried that too).ExtraPropertiesTestsfollows the API client tests: unknown properties on aUser, its profile and its enterprise user, on aConversationand its topic, and on a section block and its text; a user with only known properties having nothing inExtraProperties; and a block read with an unknown property not sending it back../do testpasses on every commit (783 tests, then 785 and 790 once the lint and the other tests are in). It also builds in Release without new warnings.Not verified:
users.list.ChatApibuilds its arguments fromMessageproperty by property, so it wouldn't just fall out of this one.object(string,bool,long,double,JObject,JArray), the same as on events. I haven't wrapped them in anything.