WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
72835
Web Inspector: [protocol] generate C++ classes for protocol JSON named types
https://bugs.webkit.org/show_bug.cgi?id=72835
Summary
Web Inspector: [protocol] generate C++ classes for protocol JSON named types
Peter Rybin
Reported
2011-11-20 13:10:05 PST
Extend CodeGeneratorInspector.py functionality in a wake of preparing internal typed C++ API for WebKit Remote Debugging protocol.
Attachments
Patch
(22.71 KB, patch)
2011-11-20 13:23 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Sample generated file (condensed form with C preprocessor defines)
(77.13 KB, text/plain)
2011-11-21 00:23 PST
,
Peter Rybin
no flags
Details
Sample generated file (long form)
(127.73 KB, text/plain)
2011-11-21 00:24 PST
,
Peter Rybin
no flags
Details
Patch
(23.42 KB, patch)
2011-11-21 00:42 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Sample generated file (condensed form with C preprocessor defines)
(82.10 KB, text/plain)
2011-11-21 00:45 PST
,
Peter Rybin
no flags
Details
Patch
(20.67 KB, patch)
2011-11-24 12:46 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Sample generated file (caseq template technique)
(123.58 KB, text/plain)
2011-11-24 12:48 PST
,
Peter Rybin
no flags
Details
Patch
(21.51 KB, patch)
2011-11-25 08:23 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Patch
(21.42 KB, patch)
2011-12-04 11:51 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Patch
(21.38 KB, patch)
2011-12-05 16:27 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Patch
(21.63 KB, patch)
2011-12-08 12:02 PST
,
Peter Rybin
no flags
Details
Formatted Diff
Diff
Builder usage example
(2.79 KB, patch)
2011-12-12 07:29 PST
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Show Obsolete
(7)
View All
Add attachment
proposed patch, testcase, etc.
Peter Rybin
Comment 1
2011-11-20 13:23:20 PST
Created
attachment 115996
[details]
Patch
Timothy Hatcher
Comment 2
2011-11-20 14:19:07 PST
What is the C/C++ API going to be used for? (Just curious.)
Peter Rybin
Comment 3
2011-11-20 15:29:41 PST
(In reply to
comment #2
)
> What is the C/C++ API going to be used for? (Just curious.)
While our remote debugging protocol is well-defined and published nowdays, we don't have even runtime asserts that actual outgoing messages conform. This API will provide compile-time guarantee that C++ code builds outgoing messages strictly as as declared.
Ilya Tikhonovsky
Comment 4
2011-11-20 21:47:41 PST
Comment on
attachment 115996
[details]
Patch could you please also provide a sample file and InspectorBackendDispatcher.cpp/h files
Peter Rybin
Comment 5
2011-11-21 00:23:24 PST
Created
attachment 116041
[details]
Sample generated file (condensed form with C preprocessor defines)
Peter Rybin
Comment 6
2011-11-21 00:24:06 PST
Created
attachment 116042
[details]
Sample generated file (long form)
Peter Rybin
Comment 7
2011-11-21 00:42:24 PST
Created
attachment 116046
[details]
Patch
Peter Rybin
Comment 8
2011-11-21 00:45:27 PST
Created
attachment 116047
[details]
Sample generated file (condensed form with C preprocessor defines)
Ilya Tikhonovsky
Comment 9
2011-11-23 00:17:43 PST
Comment on
attachment 116046
[details]
Patch After the next round of review I decided that I'm against this implementation of native data classes for Inspector protocol. The plain version looks too long and complex. The variant with macros just masks this complexity. The generator code with support for both versions looks weird.
Ilya Tikhonovsky
Comment 10
2011-11-23 00:22:19 PST
(In reply to
comment #9
)
> (From update of
attachment 116046
[details]
) > After the next round of review I decided that I'm against this implementation of native data classes for Inspector protocol. The plain version looks too long and complex. The variant with macros just masks this complexity. The generator code with support for both versions looks weird.
the sample template based version for discussion. #include <string> #include <iostream> #include <map> typedef std::map<std::string, std::string> map_type; // sample data container class ProtocolObjectFoo { public: enum { NO_FIELDS_SET = 0, FOO_SET = 1, BAR_SET = 2, BAZZ_SET = 4, ALL_FIELDS_SET = (FOO_SET | BAR_SET | BAZZ_SET) }; template<int n> class Builder { private: friend class ProtocolObjectFoo; Builder<n>() { static_assert(n == 0, "Builder<n> with n not equal to 0 was called"); m_result = new map_type(); } template<int m> operator Builder<m>& () { return *reinterpret_cast<Builder<m>*>(this); } map_type *m_result; public: Builder<n | FOO_SET>& setFoo(std::string value) { static_assert((n & FOO_SET) == 0, "ProtocolObjectFoo::setFoo was called second time"); (*m_result)["foo"] = value; return *this; } Builder<n | BAR_SET>& setBar(std::string value) { static_assert((n & BAR_SET) == 0, "ProtocolObjectFoo::setBar was called second time"); (*m_result)["bar"] = value; return *this; } Builder<n | BAZZ_SET>& setBazz(std::string value) { static_assert((n & BAZZ_SET) == 0, "ProtocolObjectFoo::setBazz was called second time"); (*m_result)["buzz"] = value; return *this; } operator map_type*() { static_assert(n == ALL_FIELDS_SET, "ProtocolObjectFoo not all the properties were set"); return m_result; } }; static Builder<NO_FIELDS_SET> create() { return Builder<NO_FIELDS_SET>(); } }; int main() { map_type* result1 = ProtocolObjectFoo::create() .setBazz("bbb") .setFoo("fff") .setBazz("bbb") // compile time for second .setBar("rrr"); map_type* result2 = ProtocolObjectFoo::create() .setBazz("bbb") // .setFoo("fff") // compile time error when not all the properties were set .setBar("rrr"); for (map_type::const_iterator it = result1->begin(); it != result1->end(); ++it) std::cout << it->first << ": " << it->second << std::endl; }
Yury Semikhatsky
Comment 11
2011-11-24 06:33:32 PST
Comment on
attachment 116046
[details]
Patch r- as we decided to use template based approach.
Peter Rybin
Comment 12
2011-11-24 12:46:24 PST
Created
attachment 116532
[details]
Patch
Peter Rybin
Comment 13
2011-11-24 12:48:29 PST
Created
attachment 116533
[details]
Sample generated file (caseq template technique)
Yury Semikhatsky
Comment 14
2011-11-25 00:13:54 PST
Comment on
attachment 116532
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=116532&action=review
> Source/WebCore/inspector/CodeGeneratorInspector.py:534 > + template<int STEP> inline Builder<STATE | STEP>& castState()
Do we really need all these methods to be inline?
Andrey Kosyakov
Comment 15
2011-11-25 00:42:23 PST
(In reply to
comment #13
)
> Sample generated file (caseq template technique)
I generally like the result, but still got a few notes: - reinterpret_cast from InspectorObject to a specific object type looks quite unfortunate. Why not use a concrete type for m_result? - why do we need explicit inlines on every method? - let's pass string parameters by a const reference; - Builder constructor should by private, with outer class a friend; - it's probably worth implementing cast operator for PassRefPtr via cast operator for RefPtr;
Peter Rybin
Comment 16
2011-11-25 07:57:46 PST
> > Source/WebCore/inspector/CodeGeneratorInspector.py:534 > > + template<int STEP> inline Builder<STATE | STEP>& castState() > > Do we really need all these methods to be inline?
Fixed
Peter Rybin
Comment 17
2011-11-25 08:22:24 PST
> I generally like the result, but still got a few notes: > - reinterpret_cast from InspectorObject to a specific object type looks quite unfortunate. Why not use a concrete type for m_result?
done
> - why do we need explicit inlines on every method?
done
> - let's pass string parameters by a const reference;
done
> - Builder constructor should by private, with outer class a friend;
done
> - it's probably worth implementing cast operator for PassRefPtr via cast operator for RefPtr;
done
Peter Rybin
Comment 18
2011-11-25 08:23:32 PST
Created
attachment 116625
[details]
Patch
Ilya Tikhonovsky
Comment 19
2011-11-25 11:15:18 PST
Comment on
attachment 116625
[details]
Patch lgtm
Ilya Tikhonovsky
Comment 20
2011-11-28 04:31:06 PST
Comment on
attachment 116625
[details]
Patch Clearing flags on attachment: 116625 Committed
r101249
: <
http://trac.webkit.org/changeset/101249
>
Ilya Tikhonovsky
Comment 21
2011-11-28 04:31:18 PST
All reviewed patches have been landed. Closing bug.
Peter Rybin
Comment 22
2011-12-04 11:35:40 PST
Reopening.
Peter Rybin
Comment 23
2011-12-04 11:51:05 PST
Created
attachment 117803
[details]
Patch
WebKit Review Bot
Comment 24
2011-12-05 08:56:17 PST
Comment on
attachment 117803
[details]
Patch Clearing flags on attachment: 117803 Committed
r102004
: <
http://trac.webkit.org/changeset/102004
>
WebKit Review Bot
Comment 25
2011-12-05 08:56:24 PST
All reviewed patches have been landed. Closing bug.
Csaba Osztrogonác
Comment 26
2011-12-05 09:07:39 PST
It broke the --minimal build:
http://build.webkit.org/builders/Qt%20Linux%20Release%20minimal/builds/38215/steps/compile-webkit/logs/stdio
Could you fix it, please?
Andrey Kosyakov
Comment 27
2011-12-05 15:06:10 PST
Comment on
attachment 117803
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=117803&action=review
> Source/WebCore/inspector/CodeGeneratorInspector.py:110 > + def lower_camel_case_to_upper(str): > + if len(str) > 0 and str[0].islower(): > + str = str[0].upper() + str[1:] > + return str
String.capitalize()?
> Source/WebCore/inspector/CodeGeneratorInspector.py:138 > + pos = 0 > + while pos < len(output): > + output[pos] = output[pos].upper() > + pos += 1 > + return "_".join(output)
Why not just "_".join(output).upper()?
> Source/WebCore/inspector/CodeGeneratorInspector.py:152 > + def split_camel_case_(str): > + output = [] > + pos_being = 0 > + pos = 1 > + has_oneletter = False > + while pos < len(str): > + if str[pos].isupper(): > + output.append(str[pos_being:pos].upper()) > + if pos - pos_being == 1: > + has_oneletter = True > + pos_being = pos > + pos += 1
This looks as it were ported from COBOL. Can this be rewritten into python -- e.g., use regexps?
> Source/WebCore/inspector/CodeGeneratorInspector.py:459 > + output.append("namespace ") > + output.append(json_type["id"]) > + output.append(" {\n")
Consider using interpolation for better readability.
> Source/WebCore/inspector/CodeGeneratorInspector.py:466 > + item_c_name = enum_item.replace('-', '_') > + output.append("const char* const ") > + output.append(Capitalizer.upper_camel_case_to_lower(item_c_name)) > + output.append(" = \"") > + output.append(enum_item) > + output.append("\";\n")
ditto
> Source/WebCore/inspector/CodeGeneratorInspector.py:732 > + def fill_recursive(path_part, depth): > + if depth <= 0 or path_part == '/': > + return > + fill_recursive(os.path.dirname(path_part), depth - 1) > + components.append(os.path.basename(path_part))
Does this have to be recursive? Also, consider os.path.split(). Or, given that you join them back with "/".join() below, you could as well have used a regexp.
Peter Rybin
Comment 28
2011-12-05 16:21:53 PST
> > Source/WebCore/inspector/CodeGeneratorInspector.py:110 > > + def lower_camel_case_to_upper(str): > > + if len(str) > 0 and str[0].islower(): > > + str = str[0].upper() + str[1:] > > + return str > String.capitalize()?
No. According to documentation it makes all letters but first lowercase.
> > Source/WebCore/inspector/CodeGeneratorInspector.py:138 > > + pos = 0 > > + while pos < len(output): > > + output[pos] = output[pos].upper() > > + pos += 1 > > + return "_".join(output) > Why not just "_".join(output).upper()?
Done
> > Source/WebCore/inspector/CodeGeneratorInspector.py:152 > > + def split_camel_case_(str): > > + output = [] > > + pos_being = 0 > > + pos = 1 > > + has_oneletter = False > > + while pos < len(str): > > + if str[pos].isupper(): > > + output.append(str[pos_being:pos].upper()) > > + if pos - pos_being == 1: > > + has_oneletter = True > > + pos_being = pos > > + pos += 1 > This looks as it were ported from COBOL. Can this be rewritten into python -- e.g., use regexps?
I don't really see how it can be re-written nicer. At least in 15 minutes.
> > Source/WebCore/inspector/CodeGeneratorInspector.py:459 > > + output.append("namespace ") > > + output.append(json_type["id"]) > > + output.append(" {\n") > Consider using interpolation for better readability.
I do use a lot of interpolation throughout the script. I'm not convinced it always gives better readability.
> > Source/WebCore/inspector/CodeGeneratorInspector.py:732 > > + def fill_recursive(path_part, depth): > > + if depth <= 0 or path_part == '/': > > + return > > + fill_recursive(os.path.dirname(path_part), depth - 1) > > + components.append(os.path.basename(path_part)) > Does this have to be recursive? Also, consider os.path.split(). Or, given that you join them back with "/".join() below, you could as well have used a regexp.
I don't know. I have to split path into components. Given I only can get the last component per time, recursion looked pretty nice solution. I don't like to use regexp, because I'm not sure about Windows stuff.
Peter Rybin
Comment 29
2011-12-05 16:27:13 PST
Created
attachment 117952
[details]
Patch
Peter Rybin
Comment 30
2011-12-05 16:35:40 PST
Comment on
attachment 117952
[details]
Patch This is only a response for caseq's codereivew. The patch is still not ready -- it break qt-minimal.
http://build.webkit.org/builders/Qt%20Linux%20Release%20minimal/builds/38215/steps/compile-webkit/logs/stdio
Peter Rybin
Comment 31
2011-12-08 12:02:36 PST
Created
attachment 118440
[details]
Patch
Yury Semikhatsky
Comment 32
2011-12-09 00:33:15 PST
Comment on
attachment 118440
[details]
Patch Clearing flags on attachment: 118440 Committed
r102440
: <
http://trac.webkit.org/changeset/102440
>
Yury Semikhatsky
Comment 33
2011-12-09 00:33:29 PST
All reviewed patches have been landed. Closing bug.
Yury Semikhatsky
Comment 34
2011-12-09 00:38:24 PST
Peter, please don't remove (OOPS!) from generated ChangeLog entries, otherwise our scripts won't be able to substitute reviewer's name and we will get changelog with Reviwed by NOBODY. line like here:
http://trac.webkit.org/changeset/102440/trunk/Source/WebCore/ChangeLog
Patrick R. Gansterer
Comment 35
2011-12-10 07:50:30 PST
This patch breaks Windows CE. After this patch you generate a class with the RGBA. RGBA is a macro on windows and will cause sooner or later problems on the other windows platforms too (depending on the include order). What about giving the classes a prefix?
Peter Rybin
Comment 36
2011-12-10 13:50:53 PST
(In reply to
comment #35
)
> This patch breaks Windows CE. After this patch you generate a class with the RGBA. RGBA is a macro on windows and will cause sooner or later problems on the other windows platforms too (depending on the include order). > What about giving the classes a prefix?
Probably prefix would be too heavyweight solution. I think it's worth keeping a manually-filled map of exceptions for typenames. I'm going to prepare a patch.
Peter Rybin
Comment 37
2011-12-11 17:21:49 PST
I filed the bug and it has been closed by now.
https://bugs.webkit.org/show_bug.cgi?id=74247
Yury Semikhatsky
Comment 38
2011-12-12 06:09:46 PST
Today when trying to use the new typed API for building memory report in
http://trac.webkit.org/changeset/102569/trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp
I encountered several problems which I think we need to address: 1. Sometimes result construction may be spread over a method or even several methods. In this case we have to either first calculate all properties and then set all of them in one statement: RefPtr<DOMGroup> result = DOMGroup::create() .setSize(size_var) .setTitle(title_var) .setNodeCount(node_count_var); would be more convenient to have some result object which we could incrementally fill with the properties but with current approach we would have to declare variables types like Memory::DOMGroup::Builder<TITLE_SET | NODE_COUNT_SET> which is too cumbersome. 2. In case result is populated in several methods we need to pass one builder as a parameter and return another builder as a result. Type declaration is still quite long.
Yury Semikhatsky
Comment 39
2011-12-12 07:29:40 PST
Created
attachment 118785
[details]
Builder usage example
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug