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

Merge ObjC categories into docs of the extended class #466

Merged
merged 2 commits into from
Mar 1, 2016

Conversation

esad
Copy link
Collaborator

@esad esad commented Jan 29, 2016

This is work-in-progress on #457.

The idea was to annotate SourceDeclarations representing extensions (both swift and objc) with a link to the parent declaration that is being extended, and then use this as a deduplication key. This kind of unifies the existing approach for swift extensions with new behaviour needed for objc classes/categories.

Furthermore, we found it nice to have category name appear as a mark of the merged methods.

@@ -318,8 +318,8 @@ def self.deduplicate_declarations(declarations)

# Two declarations get merged if they have the same deduplication key.
def self.deduplication_key(decl)
if decl.type.swift_extensible? || decl.type.swift_extension?
[decl.usr]
if (decl.type.swift_extension? || decl.type.objc_category?) && !decl.extension_parent.nil?
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe add a helper method for extension_type?

@pcantrell
Copy link
Collaborator

Thanks for this, Esad! Two families of questions as I digest the code:

First, what’s the rationale behind computing the extension_parent? It looks like you’re doing it just to replace the deduplication key of [decl.usr] with deduplication_key(decl.extension_parent); is that correct? I’m guessing that’s because Obj-C extensions come back with USRs different from the type they extend…?

If so, I wonder if perhaps the regexp dance you did in your first crack at this was a better plan. It takes a lot of code in this PR to construct extension_parent. Writing an extract_extended_type_usr method might be preferable.

What do those Obj-C USRs look like? Can you provide some examples?


Second, I wonder if it might make sense to unify Swift & Obj-C a bit more, e.g. extension? as a shortcut for swift_extension? || objc_category?, in order to simplify some of those tangled conditionals.

I vaguely remember @jpsim saying that he has a preference for keeping Swift things and Objective-C things somewhat separate, but if he’s amenable to some judicious cross-language generalizing, it could tidy things a bit.

If we are going to keep things separate, then extension_name should be category_name, because extensions are anonymous in Swift.

Nice idea using the category name as a marker, BTW.

@esad
Copy link
Collaborator Author

esad commented Feb 1, 2016

Hi @pcantrell, thanks for your feedback!

Yes, the purpose of going through all extensions to find and set the extension_parent is the deduplication - it struck me as more elegant to simply say "for this extension, use the dedup key of the extended type" than to manually make it match. The extension_name is later used when setting the mark for the merged methods.

The USRs itself in Objective-C look like c:objc(cy)SomeClass@SomeCategory for the category and c:objc(cs)SomeClass for the class itself.

I'll try to refactor this back to a more simple solution, let's see how it looks.

@esad
Copy link
Collaborator Author

esad commented Feb 1, 2016

I've updated the PR with a simpler approach. What I really disliked about my first try was manually twiddling USRs so that they match, now I rely on extracted extended class name instead.

Same method that is is used to extract the extended class name also extracts the category name, which is used for the mark.

(The new approach should also merge fine with #462)

@segiddins
Copy link
Collaborator

Before merging, this will need a rebase to get rid of the merge commit

# of the extended objc class and the category name itself, i.e.
# ["NSString", "MyMethods"], nil otherwise.
def objc_category_name
type.objc_category? && name.split(/[\(\)]/) || nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could just be name.split(/[\(\)]/) if type.objc_category?

@segiddins
Copy link
Collaborator

This warrants adding categories to an integration spec, I think

@esad esad mentioned this pull request Feb 4, 2016
@esad
Copy link
Collaborator Author

esad commented Feb 4, 2016

I addressed the above PR remarks, but I'm blocked by integration specs not passing on the current master. Waiting to resolve this first before I update them.

@pcantrell
Copy link
Collaborator

I like the way this ended up. Not too complicated; things makes sense. I'm dropping a few minor notes into the code, and after those I'd say it's good to merge.

+1 to Sam’s comment that this warrants an addition to the specs, perhaps just a small addition to misc_jazzy_features — though I think, given this project’s somewhat loose coupling between features and tests, that could be a separate PR if it proves to be a hassle.

# of the extended objc class and the category name itself, i.e.
# ["NSString", "MyMethods"], nil otherwise.
def objc_category_name
name.split(/[\(\)]/) if type.objc_category?
Copy link
Collaborator

Choose a reason for hiding this comment

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

The name objc_category_name implies that this returns a string, not an array — and that seems like the right behavior.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you think I should split this method into two: one to return the category name and the other to return the extended class name? Or rename the above one to match the method signature?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Now that I understand better how you’re using it, I'd suggest renaming it to make it clear that it returns two values.

@esad
Copy link
Collaborator Author

esad commented Feb 9, 2016

@segiddins What would be the best way forward to add integration tests for the above? I tried adding some objc categories to the MiscJazzyFeatures project, but the SourceKitten ignores those (even though I added them to the umbrella header).

It seems that jazzy currently doesn't support mixed Swift/ObjC projects? Should I add a new MiscJazzyObjcFeatures project to the integration specs?

@segiddins
Copy link
Collaborator

Yeah, I think a new MiscJazzyObjcFeatures project would probably be the best bet

@esad
Copy link
Collaborator Author

esad commented Feb 11, 2016

I've added integration specs for this feature. As pointed out in the child PR, I'm bit unsure how this workflow with 2 dependent separate repos should work. Can you merge the child PR first, so that I can point to it here and we can have CI pass on this PR?

@esad
Copy link
Collaborator Author

esad commented Feb 11, 2016

After integration specs pass I'll address the remaining code style issues.

@pcantrell
Copy link
Collaborator

The integration specs process is a bit of a mystery to me too at times, but I merged your PR and hopefully that unblocks this merge.

As you do the last little tidying work, please feel free to edit .rubocop.yml to make it so you can do name, _ = instead of name, =. Anybody else feel free to pipe up in disagreement, but I find the latter terrible.

Thanks for bearing with this whole process!

@esad
Copy link
Collaborator Author

esad commented Feb 12, 2016

@pcantrell @segiddins I've addressed all issues we discussed above, added integration specs and rebased the PR. Let me know if you feel there's something else missing.

@esad
Copy link
Collaborator Author

esad commented Feb 24, 2016

I just wanted to let you know that we've rebuilt PSPDFKit docs with this patch applied and it worked fine, with categories getting merged nicely into the class docs.

@pcantrell
Copy link
Collaborator

I'd love to get this merged! It's only blocked on the CI failing. It looks like the integration specs are building Moya with a slightly different version of AF that the expected output recorded.

I have to speed-prep a talk I'm doing tonight, but @esad (or anyone else), if you have a chance to update the expected output, I can approve the merges.

@esad
Copy link
Collaborator Author

esad commented Mar 1, 2016

@pcantrell As soon as https://github.com/realm/jazzy-integration-specs/pull/11/commits in jazzy-integration-specs gets merged I will update this PR

@esad
Copy link
Collaborator Author

esad commented Mar 1, 2016

@pcantrell Looks like the specs are passing again!

@pcantrell
Copy link
Collaborator

Merging! Hooray!

Thanks for all the hard work and the patience.

pcantrell added a commit that referenced this pull request Mar 1, 2016
Merge ObjC categories into docs of the extended class
@pcantrell pcantrell merged commit 7d7c120 into realm:master Mar 1, 2016
@jpsim
Copy link
Collaborator

jpsim commented Mar 18, 2016

This is great! Thanks @esad for your hard work, and @pcantrell & @segiddins for the reviews! 👍

@esad esad mentioned this pull request Mar 30, 2016
jpsim added a commit that referenced this pull request Mar 30, 2016
@pigeondotdev pigeondotdev modified the milestone: The Past Nov 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants