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

Support for GraphQL comments #4970

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 82 additions & 84 deletions graphql-c_parser/ext/graphql_c_parser_ext/lexer.c

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions graphql-c_parser/ext/graphql_c_parser_ext/lexer.rl
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,7 @@ void emit(TokenType tt, char *ts, char *te, Meta *meta) {
INT2FIX(200 + (int)tt)
);

if (tt != COMMENT) {
rb_ary_push(meta->tokens, token);
}
rb_ary_push(meta->tokens, token);
meta->preceeded_by_number = this_token_is_number;
}
// Bump the column counter for the next token
Expand Down
807 changes: 405 additions & 402 deletions graphql-c_parser/ext/graphql_c_parser_ext/parser.c

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions graphql-c_parser/ext/graphql_c_parser_ext/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ SETUP_NODE_CLASS_VARIABLE(SchemaExtension)
%token TYPE_LITERAL 234
%token UNION 235
%token VAR_SIGN 236
%token COMMENT 240

%%

Expand Down Expand Up @@ -524,6 +525,12 @@ type_system_definition:
/* none */ { $$ = Qnil; }
| description

comment: COMMENT

comment_opt:
/* none */ { $$ = Qnil; }
| comment

scalar_type_definition:
description_opt SCALAR name directives_list_opt {
$$ = MAKE_AST_NODE(ScalarTypeDefinition, 5,
Expand Down
1 change: 1 addition & 0 deletions lib/graphql/language.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require "graphql/language/block_string"
require "graphql/language/comment"
require "graphql/language/printer"
require "graphql/language/sanitized_printer"
require "graphql/language/document_from_schema_definition"
Expand Down
18 changes: 18 additions & 0 deletions lib/graphql/language/comment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true
module GraphQL
module Language
module Comment
def self.print(str, indent: '')
lines = str.split("\n").map do |line|
comment_str = "".dup
comment_str << indent
comment_str << "# "
comment_str << line
comment_str.rstrip
end

lines.join("\n") + "\n"
end
end
end
end
9 changes: 7 additions & 2 deletions lib/graphql/language/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def advance
when ByteFor::PUNCTUATION
@scanner.pos += 1
PUNCTUATION_NAME_FOR_BYTE[next_byte]
when ByteFor::COMMENT
@scanner.skip(COMMENT_REGEXP)
:COMMENT
when ByteFor::NAME
if len = @scanner.skip(KEYWORD_REGEXP)
case len
Expand Down Expand Up @@ -165,14 +168,14 @@ def raise_parse_error(message, line = line_number, col = column_number)

IGNORE_REGEXP = %r{
(?:
[, \c\r\n\t]+ |
\#.*$
[, \c\r\n\t]+
)*
}x
IDENTIFIER_REGEXP = /[_A-Za-z][_0-9A-Za-z]*/
INT_REGEXP = /-?(?:[0]|[1-9][0-9]*)/
FLOAT_DECIMAL_REGEXP = /[.][0-9]+/
FLOAT_EXP_REGEXP = /[eE][+-]?[0-9]+/
COMMENT_REGEXP = /#.*/
# TODO: FLOAT_EXP_REGEXP should not be allowed to follow INT_REGEXP, integers are not allowed to have exponent parts.
NUMERIC_REGEXP = /#{INT_REGEXP}(#{FLOAT_DECIMAL_REGEXP}#{FLOAT_EXP_REGEXP}|#{FLOAT_DECIMAL_REGEXP}|#{FLOAT_EXP_REGEXP})?/

Expand Down Expand Up @@ -296,6 +299,7 @@ module ByteFor
ELLIPSIS = 3
IDENTIFIER = 4 # identifier, *not* a keyword
PUNCTUATION = 5
COMMENT = 6
end

(0..9).each { |i| FIRST_BYTES[i.to_s.ord] = ByteFor::NUMBER }
Expand All @@ -306,6 +310,7 @@ module ByteFor
FIRST_BYTES['_'.ord] = ByteFor::IDENTIFIER
FIRST_BYTES['.'.ord] = ByteFor::ELLIPSIS
FIRST_BYTES['"'.ord] = ByteFor::STRING
FIRST_BYTES['#'.ord] = ByteFor::COMMENT
KEYWORDS.each { |kw| FIRST_BYTES[kw.getbyte(0)] = ByteFor::NAME }
Punctuation.constants.each do |punct_name|
punct = Punctuation.const_get(punct_name)
Expand Down
58 changes: 36 additions & 22 deletions lib/graphql/language/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ def generate_initialize

scalar_method_names = @scalar_methods
# TODO: These probably should be scalar methods, but `types` returns an array
[:types, :description].each do |extra_method|
[:types, :description, :comment].each do |extra_method|
if method_defined?(extra_method)
scalar_method_names += [extra_method]
end
Expand Down Expand Up @@ -338,6 +338,14 @@ def marshal_load(values)
end
end

class OrphanComment < AbstractNode
attr_reader :comment

def initialize(comment: nil)
@comment = comment
end
end

# Base class for non-null type names and list type names
class WrapperType < AbstractNode
scalar_methods :of_type
Expand Down Expand Up @@ -375,7 +383,7 @@ class DirectiveLocation < NameOnlyNode
end

class DirectiveDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name, :repeatable
children_methods(
arguments: Nodes::Argument,
Expand All @@ -394,11 +402,12 @@ class NullValue < NameOnlyNode

# A single selection in a GraphQL query.
class Field < AbstractNode
def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, comment: nil, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
@name = name
@arguments = arguments || NONE
@directives = directives || NONE
@selections = selections || NONE
@comment = comment
# oops, alias is a keyword:
@alias = field_alias
@line = line
Expand All @@ -408,19 +417,19 @@ def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, f
@source = source
end

def self.from_a(filename, line, col, field_alias, name, arguments, directives, selections) # rubocop:disable Metrics/ParameterLists
self.new(filename: filename, line: line, col: col, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selections)
def self.from_a(filename, line, col, field_alias, name, arguments, directives, selections, comment) # rubocop:disable Metrics/ParameterLists
self.new(filename: filename, line: line, col: col, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selections, comment: comment)
end

def marshal_dump
[line, col, @filename, @name, @arguments, @directives, @selections, @alias]
[line, col, @filename, @name, @arguments, @directives, @selections, @alias, @comment]
end

def marshal_load(values)
@line, @col, @filename, @name, @arguments, @directives, @selections, @alias = values
@line, @col, @filename, @name, @arguments, @directives, @selections, @alias, @comment = values
end

scalar_methods :name, :alias
scalar_methods :comment, :name, :alias
children_methods({
arguments: GraphQL::Language::Nodes::Argument,
selections: GraphQL::Language::Nodes::Field,
Expand All @@ -433,28 +442,31 @@ def marshal_load(values)

# A reusable fragment, defined at document-level.
class FragmentDefinition < AbstractNode
def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source: nil, line: nil, col: nil)
attr_reader :comment

def initialize(name: nil, type: nil, directives: NONE, selections: NONE, comment: nil, filename: nil, pos: nil, source: nil, line: nil, col: nil)
@name = name
@type = type
@directives = directives
@selections = selections
@comment = comment
@filename = filename
@pos = pos
@source = source
@line = line
@col = col
end

def self.from_a(filename, line, col, name, type, directives, selections)
self.new(filename: filename, line: line, col: col, name: name, type: type, directives: directives, selections: selections)
def self.from_a(filename, line, col, name, type, directives, selections, comment) # rubocop:disable Metrics/ParameterLists
self.new(filename: filename, line: line, col: col, name: name, type: type, directives: directives, selections: selections, comment: comment)
end

def marshal_dump
[line, col, @filename, @name, @type, @directives, @selections]
[line, col, @filename, @name, @type, @directives, @selections, @comment]
end

def marshal_load(values)
@line, @col, @filename, @name, @type, @directives, @selections = values
@line, @col, @filename, @name, @type, @directives, @selections, @comment = values
end

scalar_methods :name, :type
Expand All @@ -468,6 +480,7 @@ def marshal_load(values)

# Application of a named fragment in a selection
class FragmentSpread < AbstractNode
attr_reader :comment
scalar_methods :name
children_methods(directives: GraphQL::Language::Nodes::Directive)

Expand Down Expand Up @@ -558,6 +571,7 @@ class VariableDefinition < AbstractNode
# May be anonymous or named.
# May be explicitly typed (eg `mutation { ... }`) or implicitly a query (eg `{ ... }`).
class OperationDefinition < AbstractNode
attr_accessor :comment
scalar_methods :operation_type, :name
children_methods({
variables: GraphQL::Language::Nodes::VariableDefinition,
Expand Down Expand Up @@ -635,7 +649,7 @@ class SchemaExtension < AbstractNode
end

class ScalarTypeDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -652,7 +666,7 @@ class ScalarTypeExtension < AbstractNode
end

class InputValueDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name, :type, :default_value
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -661,7 +675,7 @@ class InputValueDefinition < AbstractNode
end

class FieldDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name, :type
children_methods({
arguments: GraphQL::Language::Nodes::InputValueDefinition,
Expand All @@ -681,7 +695,7 @@ def merge(new_options)
end

class ObjectTypeDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name, :interfaces
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -700,7 +714,7 @@ class ObjectTypeExtension < AbstractNode
end

class InterfaceTypeDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name
children_methods({
interfaces: GraphQL::Language::Nodes::TypeName,
Expand All @@ -721,7 +735,7 @@ class InterfaceTypeExtension < AbstractNode
end

class UnionTypeDefinition < AbstractNode
attr_reader :description, :types
attr_reader :comment, :description, :types
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -739,7 +753,7 @@ class UnionTypeExtension < AbstractNode
end

class EnumValueDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -748,7 +762,7 @@ class EnumValueDefinition < AbstractNode
end

class EnumTypeDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand All @@ -767,7 +781,7 @@ class EnumTypeExtension < AbstractNode
end

class InputObjectTypeDefinition < AbstractNode
attr_reader :description
attr_reader :comment, :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
Expand Down
Loading
Loading