-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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 for GraphQL comments #4970
Conversation
👍 I think this is absolutely on the right track! Let me know if I can do anything particular to help this work along. |
75b4f32
to
9c20720
Compare
@rmosolgo could you please approve CI pipeline run? Thanks Next steps for us is to implement support for multi-line comments, we'd need to be able to parse them. For printing (output), we were thinking of for allowing newline characters if user wished to have multiline output. This would mean the
We think it's good enough API for users to format it this way instead of some complex solution, such as allowing to pass lists or having some kind of automated mechanism (e.g. break after 80 chars). If you think that printing multiple line comments is something that's not needed or wanted, we're OK with not having it. |
lib/graphql/language/parser.rb
Outdated
@@ -269,6 +275,7 @@ def definition | |||
else | |||
loc = pos | |||
desc = at?(:STRING) ? string_value : nil | |||
comment = at?(:COMMENT) ? value : comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is not very easy to read, to be honest we added it because one of the tests was failing and this one worked.
I agree that working from line breaks is the right way to render multiline comments. Ideally, GraphQL-Ruby would be able to parse SDL with multiline comments and print them back out exactly as they were originally written. (For your use case with |
Yeah exactly, we should respect that during parsing that's for sure. Yes for We'll try to polish this first and have the tests pass, which will probably require us to figure out multiline comments in the process 👍 |
62ea569
to
0a1135d
Compare
@rmosolgo 👋 hello, is it possible to approve running pipelines on this PR? We're in the process of fixing specs and it'd be nice if we could see results in CI. 🙇 |
👀 I see the button to allow CI once, but I'm not sure how enable it for a PR. I couldn't find a doc from GitHub on how to do it -- do you know how? |
Ah... yes, there is a setting there: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#controlling-changes-from-forks-to-workflows-in-public-repositories I switched it so only "new GitHub accounts" need me to approve them. Hopefully that will do it 🤞 |
Wrong button 🤦 |
aecce31
to
1e5af44
Compare
75eca02
to
7a4ddf2
Compare
@rmosolgo Hello, we've got to a point where most of the tests are passing (of course the changes themselves are far from final) but we are stuck on the c-parser integration. It's a little mysterious how it works to us and we could use some guidance how to fix it and what the best approach here would be. Could you help us please? cc @comatory |
👋 Sure thing. I'd be happy to take care of the C-Parser changes whenever the Ruby implementation is ready to go. Or, if you're interested in investigating it yourself, I think the main thing is updating the C parser to pass First, the lexer would need to be updated to actually emit comment tokens. Currently, they're ignored: graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/lexer.rl Lines 385 to 388 in 843014f
That Then, the parser would need to be updated to match comments wherever they appear. Since descriptions are very similar, structurally, I think a similar approach would work. Define a rule for optionally matching a comment (eg, graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/parser.y Lines 521 to 525 in 843014f
Then add graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/parser.y Lines 539 to 540 in 843014f
graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/parser.y Lines 586 to 587 in 843014f
graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/parser.y Lines 658 to 659 in 843014f
Then, since Yacc uses indexes to reference matched tokens, all the indexes in those rules would have to be updated. ( Finally, you'd have to pass
Finally, you'd have to make sure that the graphql-ruby/lib/graphql/language/nodes.rb Lines 320 to 322 in 843014f
But a couple of nodes have custom definitions for one reason or another, so those would need to be manually updated to receive graphql-ruby/lib/graphql/language/nodes.rb Line 411 in 843014f
graphql-ruby/lib/graphql/language/nodes.rb Line 448 in 843014f
I think that after that, the C Parser would be making ASTs identical to the Ruby parser's ASTs, so we'd be done. But there are always surprises 😅 |
@rmosolgo Wow, thanks for such a detailed answer. The required work is more or less what I expected we'll need to do, and with the guidance of what you wrote above, I think I will be able to do it. |
Happy to! Thanks for all your work on this feature so far 🍻 |
cb224d0
to
0c9582a
Compare
0c9582a
to
bfa7744
Compare
@@ -524,6 +524,12 @@ type_system_definition: | |||
/* none */ { $$ = Qnil; } | |||
| description | |||
|
|||
comment: STRING |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh... I realize I missed a spot when I described the changes required here. We also need a YACC token type for COMMENT
.
The token types are configured in two places. First, they're laid out in an enum in lexer.rl:
graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/lexer.rl
Lines 150 to 193 in 18fdf6f
typedef enum TokenType { | |
AMP, | |
BANG, | |
COLON, | |
DIRECTIVE, | |
DIR_SIGN, | |
ENUM, | |
ELLIPSIS, | |
EQUALS, | |
EXTEND, | |
FALSE_LITERAL, | |
FLOAT, | |
FRAGMENT, | |
IDENTIFIER, | |
INPUT, | |
IMPLEMENTS, | |
INT, | |
INTERFACE, | |
LBRACKET, | |
LCURLY, | |
LPAREN, | |
MUTATION, | |
NULL_LITERAL, | |
ON, | |
PIPE, | |
QUERY, | |
RBRACKET, | |
RCURLY, | |
REPEATABLE, | |
RPAREN, | |
SCALAR, | |
SCHEMA, | |
STRING, | |
SUBSCRIPTION, | |
TRUE_LITERAL, | |
TYPE_LITERAL, | |
UNION, | |
VAR_SIGN, | |
BLOCK_STRING, | |
QUOTED_STRING, | |
UNKNOWN_CHAR, | |
COMMENT, | |
BAD_UNICODE_ESCAPE | |
} TokenType; |
It looks like COMMENT is already on the list there 👍
Then, the enum values are mapped to YACC token types here:
graphql-ruby/graphql-c_parser/ext/graphql_c_parser_ext/parser.y
Lines 61 to 98 in 18fdf6f
// YACC Declarations | |
%token AMP 200 | |
%token BANG 201 | |
%token COLON 202 | |
%token DIRECTIVE 203 | |
%token DIR_SIGN 204 | |
%token ENUM 205 | |
%token ELLIPSIS 206 | |
%token EQUALS 207 | |
%token EXTEND 208 | |
%token FALSE_LITERAL 209 | |
%token FLOAT 210 | |
%token FRAGMENT 211 | |
%token IDENTIFIER 212 | |
%token INPUT 213 | |
%token IMPLEMENTS 214 | |
%token INT 215 | |
%token INTERFACE 216 | |
%token LBRACKET 217 | |
%token LCURLY 218 | |
%token LPAREN 219 | |
%token MUTATION 220 | |
%token NULL_LITERAL 221 | |
%token ON 222 | |
%token PIPE 223 | |
%token QUERY 224 | |
%token RBRACKET 225 | |
%token RCURLY 226 | |
%token REPEATABLE 227 | |
%token RPAREN 228 | |
%token SCALAR 229 | |
%token SCHEMA 230 | |
%token STRING 231 | |
%token SUBSCRIPTION 232 | |
%token TRUE_LITERAL 233 | |
%token TYPE_LITERAL 234 | |
%token UNION 235 | |
%token VAR_SIGN 236 |
COMMENT
is not on the list there, since it was previously excluded from the token stream. It needs to be added. Those integer values are based on their position in the enum declaration in lexer.rl, so I think we need to add %token COMMENT 240
.
After that, you could define this rule as comment: COMMENT
.
6e240de
to
2ba54c2
Compare
Adds comments to the object type fields.
2ba54c2
to
1cdc52c
Compare
I did some updates to the C parser to accept comments in a70db53 (I would have pushed it to your branch but it looks like "allow commits from maintainers" isn't turned on.) It parses again, but there's a new challenge. When I suggested parsing comments as "real" tokens (instead of ignoring them), I didn't realize that it would require expecting comments anywhere that they could occur. They could occur anywhere, so it would be very hard to go back and account for that possibility. Here's an example where a comment breaks the current implementation: 18dd7af - query ($sizes: [ImageSize]) # Anonymous inline comment
+ query # Comment between parts of a query
+ ($sizes: [ImageSize]) # Anonymous inline comment I think we've got to go back to ignoring comments, but keeping a reference to the last one that we parsed (or something?) so that we can tack it on to parsed nodes. 🤔 I'll give something a try next week. Thanks so much for all your work on this change! I'm going to help get it across the finish line next week so we can get int released. |
@rmosolgo Hi, and thank you very much for helping us with this! I was think about it over the weekend and I thought whether we need to parse the comments at all. I mean I don't see the use case for it. What we were trying to achieve here is to be able to generate comments into the schema. We never thought we would need it other way around. We went down the rabbit hole of parsing only because there were certain tests parsing and printing the schema and expecting the structure would be the same. If only we ignored comments there, it would work again. The thing is the parsing as you mentioned is incredibly difficult to be done right, the comments as you said could be anywhere. Regarding the contributes, we sent you an invite to the repo, if it doesn't work. I'll make the fork to my personal github and reopen the PR from there as I will have a full control over the settings. Let us know :-) |
👍 Sounds good to me to reduce the scope of this change to only go Ruby-to-GraphQL. I forgot that was the real goal here 😅 If we want to add parsing later, we can always do it. |
Excellent, I'm on it 👍 |
FYI I'm working on the changes in a separate branch. I will open the PR once I have most of the work done. |
Thanks again for all your work here ... and sorry I sent you down a road to nowhere 😖! |
Resolves #4905
This PR is in draft state, we want to get feedback early so we know we're on the right track.
The idea is that we expanded methods that construct the schema with new
comment
parameter (we should cover most of them like types, unions, enums). By passing string value to this new parameter, the resulting schema will contain comments such as this:The reasons for adding this are mentioned in the linked issue but in a nutshell, we want to leverage comments for tooling (
eslint
), using descriptions is not desireable because those would leak into documentation.The next steps are to add support for comments to every possible place according to GraphQL specification, e.g. on definitions for enums, inputs, unions etc.
At the moment, we are fine with having single-line comments and expand to multi-line comments in subsequent PRs, which means eventually we want this to be possible:
We haven't yet looked into edge cases such as mixing descriptions with comments, but eventually those should be supported as well.