Closed
Bug 796983
Opened 13 years ago
Closed 13 years ago
Create a way to generate an example class declaration for a given WebIDL interface
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
RESOLVED
FIXED
mozilla19
People
(Reporter: bzbarsky, Assigned: bzbarsky)
References
(Blocks 1 open bug)
Details
(Keywords: dev-doc-complete)
Attachments
(4 files, 1 obsolete file)
I was kinda against it, but people seem to want it a lot...
This will be different from what bug 787574 did in that it will create declarations for all the methods.
Comment 1•13 years ago
|
||
Wait, why is this a good idea? We can't really generate a good class without reading the programmer's mind, can we?
| Assignee | ||
Comment 2•13 years ago
|
||
To some extent, yes.
And I'm not _entirely_ convinced it's a good idea. ;)
The proposal is to generate what your skeleton generator generates, plus declarations (not implementations) for the WebIDL methods based on the current annotations in the conf file and whatnot. So this won't tell people that they can have non-refcounted return values, and it won't tell people that they can make the methods const or virtual or inline or whatnot... but it'll tell them the right arguments, for the most part, and more or less the right return values (modulo the non-refcounting bit). From there, they can edit things as needed.
Comment 3•13 years ago
|
||
(In reply to comment #2)
> To some extent, yes.
>
> And I'm not _entirely_ convinced it's a good idea. ;)
>
> The proposal is to generate what your skeleton generator generates, plus
> declarations (not implementations) for the WebIDL methods based on the current
> annotations in the conf file and whatnot. So this won't tell people that they
> can have non-refcounted return values, and it won't tell people that they can
> make the methods const or virtual or inline or whatnot... but it'll tell them
> the right arguments, for the most part, and more or less the right return
> values (modulo the non-refcounting bit). From there, they can edit things as
> needed.
I fear that by generating method signatures, we will in practice discourage people from making them better (such as by using non-refcounted return values). If people are just interested in knowing the expected return type and the arguments, they can just look at the generated bindings file, and as someone who has used this stuff mostly as a consumer, I think that works fine in practice.
I'm still entirely unconvinced that this will not do more harm than good.
Comment 4•13 years ago
|
||
(In reply to Ehsan Akhgari [:ehsan] from comment #3)
> I fear that by generating method signatures, we will in practice discourage
> people from making them better (such as by using non-refcounted return
> values).
Why would this make any difference as to whether people use good annotations or not? If they don't know they can annotate for non-refcounted return value (as an example) why would having the exact signature generated based on the WebIDL and annotations change anything?
Comment 5•13 years ago
|
||
BTW, you can't exactly tell the argument types from the binding file, see for example NonNull<> (we definitely don't want people using NonNull<T>& instead of T&).
Comment 6•13 years ago
|
||
(In reply to comment #4)
> (In reply to Ehsan Akhgari [:ehsan] from comment #3)
> > I fear that by generating method signatures, we will in practice discourage
> > people from making them better (such as by using non-refcounted return
> > values).
>
> Why would this make any difference as to whether people use good annotations or
> not? If they don't know they can annotate for non-refcounted return value (as
> an example) why would having the exact signature generated based on the WebIDL
> and annotations change anything?
Well, it depends on what signature we generate, right? For example, for a getter returning an object of type Class, which one of the following signatures will we generate?
Class* Foo();
Class* Foo() const;
already_AddRefed<Class> Foo();
// etc.
Comment 7•13 years ago
|
||
(In reply to Ehsan Akhgari [:ehsan] from comment #6)
> Class* Foo();
> Class* Foo() const;
You didn't say anything about annotations, so I presume it's not marked as returning non-addrefed things. So none of the above, they are misleading since we'd addref the pointer anyway.
> already_AddRefed<Class> Foo();
This, it points exactly to what happens, we take a strong reference. I'd actually personally make it
already_AddRefed<Class> Foo() const;
people will have to remove the const if it doesn't work for them.
I'm worried about people using the wrong types here, you have to read the docs to find the right types. The docs are good, but the script can know exactly the right types based on the WebIDL and the annotations. I don't particularly care about giving a useful class (for which there are also multiple solutions, as opposed to just the one that the script from bug 787574 generates), so if you have a better idea of how to give the right types without the downsides of having precanned signatures, please share.
| Assignee | ||
Comment 8•13 years ago
|
||
For what it's worth, the skeleton can look like this:
// Annotate 'foo' as 'resultNotAddRefed' if you don't need to addref before returning
already_AddRefed<Class> Foo() const;
I guess the second question is whether we want to output a full class a la the existing skeleton generator or just a dump of the WebIDL method/prop declarations...
Comment 9•13 years ago
|
||
(In reply to comment #8)
> For what it's worth, the skeleton can look like this:
>
> // Annotate 'foo' as 'resultNotAddRefed' if you don't need to addref before
> returning
> already_AddRefed<Class> Foo() const;
Yeah, other than what Boris suggests here, I can't think of better ideas, Peter. :/
> I guess the second question is whether we want to output a full class a la the
> existing skeleton generator or just a dump of the WebIDL method/prop
> declarations...
If we're going to generate the signatures, we might as well generate the whole class, right?
| Assignee | ||
Comment 10•13 years ago
|
||
Well, sort of. If I'm just generating the signatures, I can just dump them to stdout. If I'm doing the whole class, I should probably do separate .cpp and .h files and actually put them somewhere... ;)
Comment 11•13 years ago
|
||
(In reply to comment #10)
> Well, sort of. If I'm just generating the signatures, I can just dump them to
> stdout. If I'm doing the whole class, I should probably do separate .cpp and
> .h files and actually put them somewhere... ;)
Hmm, you can just have a skeleton thing and push stuff inside it using sed or something. :-)
| Assignee | ||
Comment 12•13 years ago
|
||
Well, sure.
I mean, I can stick the .h and .cpp in the objdir. I guess I'll just do that....
| Assignee | ||
Comment 13•13 years ago
|
||
Attachment #668316 -
Flags: review?(peterv)
| Assignee | ||
Comment 14•13 years ago
|
||
allows us to just use the isStatic() for the IDLMember to mark our
declarations static.
To generate an example interface implementation, just "make
interfacename-example" in $objdir/dom/bindings. This will place files
called interfacename-example.h and interfacename-example.cpp in that
directory. For example, "make XMLHttpRequest-example" will get you
$objdir/dom/bindings/XMLHttpRequest-example.h and
$objdir/dom/bindings/XMLHttpRequest-example.cpp.
Attribute getters currently default to const methods, while setters
and operations default to non-const methods.
Attachment #668317 -
Flags: review?(peterv)
| Assignee | ||
Comment 15•13 years ago
|
||
In case you want to take a look at what output looks like.
I'm not sure whether I need to #include more stuff (like Nullable.h or BindingUtils.h to pick up Optional<T>).
| Assignee | ||
Comment 16•13 years ago
|
||
I manually compared this to what we have in TestBindingHeader.h, and it seems to match. Again, in case you want to see how various edge cases are handled.
| Assignee | ||
Updated•13 years ago
|
Whiteboard: [need review]
| Assignee | ||
Comment 17•13 years ago
|
||
Attachment #668678 -
Flags: review?(peterv)
| Assignee | ||
Updated•13 years ago
|
Attachment #668317 -
Attachment is obsolete: true
Attachment #668317 -
Flags: review?(peterv)
| Assignee | ||
Updated•13 years ago
|
Attachment #668316 -
Flags: review?(jst)
| Assignee | ||
Updated•13 years ago
|
Attachment #668678 -
Flags: review?(jst)
| Assignee | ||
Updated•13 years ago
|
Keywords: dev-doc-needed
Updated•13 years ago
|
Attachment #668316 -
Flags: review?(jst) → review+
| Assignee | ||
Updated•13 years ago
|
Attachment #668316 -
Flags: review?(peterv)
Comment 18•13 years ago
|
||
Comment on attachment 668678 [details] [diff] [review]
Part 2 with fix to make regression tests pass
Looks good to me. I suspect that this will be something we'll iterate on a bit as people start to use this etc, but that should be easy once this is in the tree. It's unfortunate that there's no easy way to generate code that would actually try to call into these example classes to make sure we don't generate code that doesn't compile... Keeping this up to date will take some amount of work, especially w/o an automated way of detecting when the code generator diverges from the example generator.
Either way, I think this is a huge value add for developers using our new bindings! r=jst
Attachment #668678 -
Flags: review?(jst) → review+
| Assignee | ||
Comment 19•13 years ago
|
||
> It's unfortunate that there's no easy way to generate code that would actually try to
> call into these example classes to make sure we don't generate code that doesn't
> compile...
It wouldn't be too bad. I considered switching out our TestCodeGen stuff for such a setup, then decided it would be better to leave that as-is for now. But I could add a second testing interface which would in fact exercise the generated example. Filed bug 802636.
Blocks: 802636
| Assignee | ||
Comment 20•13 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/d8798b6331be
https://hg.mozilla.org/integration/mozilla-inbound/rev/50d6355b80c4
Whiteboard: [need review]
Target Milestone: --- → mozilla19
| Assignee | ||
Comment 21•13 years ago
|
||
Added some basic documentation.
Keywords: dev-doc-needed → dev-doc-complete
| Assignee | ||
Updated•13 years ago
|
Flags: in-testsuite+
Comment 22•13 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/d8798b6331be
https://hg.mozilla.org/mozilla-central/rev/50d6355b80c4
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Comment 23•13 years ago
|
||
Comment on attachment 668678 [details] [diff] [review]
Part 2 with fix to make regression tests pass
Review of attachment 668678 [details] [diff] [review]:
-----------------------------------------------------------------
Looks great.
::: dom/bindings/Codegen.py
@@ +5757,5 @@
> +
> + def define(self):
> + static = "static " if self.member.isStatic() else ""
> + # Mark our getters, which are attrs that have a non-void return type,
> + # as const.
Except if they have a type that's passed as an outparam?
@@ +5923,5 @@
> + if type.isObject():
> + if type.nullable():
> + declType = "%s*"
> + else:
> + if optional:
Nit: elif
@@ +6017,5 @@
> + if descriptor.wrapperCache:
> + wrapFunc = (" virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope,\n"
> + " bool* aTriedToWrap);\n")
> + else:
> + wrapFunc = " virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);\n"
Should we add a comment that this only needs to be virtual if this might be subclassed?
@@ +6021,5 @@
> + wrapFunc = " virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);\n"
> +
> + classDecl = CGWrapper(
> + CGGeneric("public nsISupports,\n"
> + "public nsWrapperCache"),
This makes it inherit from nsWrapperCache even if wrapperCache is False, should we add a comment about how it can be non-nsWrapperCache or even non-nsISupports?
Attachment #668678 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 24•13 years ago
|
||
> Except if they have a type that's passed as an outparam?
No, why would that prevent the method from being const?
> Nit: elif
Will do.
> Should we add a comment that this only needs to be virtual if this might be subclassed?
Actually, going to just make it non-virtual for non-wrappercached things. That's really easy with the refactored codegen after bug 779048 whereas a comment is hard.
> This makes it inherit from nsWrapperCache even if wrapperCache is False,
Hmm. Filed bug 808694 on making this actually work right and put in comments for nwow.
| Assignee | ||
Comment 25•13 years ago
|
||
Pushed https://hg.mozilla.org/integration/mozilla-inbound/rev/5f887e05fc16 to address comment 23.
Comment 26•13 years ago
|
||
Updated•7 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•