Skip to content

Commit

Permalink
Merge pull request #5067 from productboard/feat/vbo-comments-vol-2
Browse files Browse the repository at this point in the history
Support for comments v2
  • Loading branch information
rmosolgo authored Aug 29, 2024
2 parents 155b2f4 + 0211989 commit 23c2770
Show file tree
Hide file tree
Showing 23 changed files with 431 additions and 33 deletions.
24 changes: 22 additions & 2 deletions guides/fields/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The different elements of field definition are addressed below:

- [Names](#field-names) identify the field in GraphQL
- [Return types](#field-return-type) say what kind of data this field returns
- [Documentation](#field-documentation) includes description and deprecation notes
- [Documentation](#field-documentation) includes description, comments and deprecation notes
- [Resolution behavior](#field-resolution) hooks up Ruby code to the GraphQL field
- [Arguments](#field-arguments) allow fields to take input when they're queried
- [Extra field metadata](#extra-field-metadata) for low-level access to the GraphQL-Ruby runtime
Expand Down Expand Up @@ -67,7 +67,7 @@ field :scores, [Integer, null: true] # `[Int]`, may return a list or `nil`, the

## Field Documentation

Fields may be documented with a __description__ and may be __deprecated__.
Fields may be documented with a __description__, __comment__ and may be __deprecated__.

__Descriptions__ can be added with the `field(...)` method as a positional argument, a keyword argument, or inside the block:

Expand All @@ -85,6 +85,26 @@ field :name, String, null: false do
end
```

__Comments__ can be added with the `field(...)` method as a keyword argument, or inside the block:
```ruby
# `comment:` keyword
field :name, String, null: false, comment: "Rename to full name"

# inside the block
field :name, String, null: false do
comment "Rename to full name"
end
```

Generates field name with comment above "Rename to full name" above.

```graphql
type Foo {
# Rename to full name
name: String!
}
```

__Deprecated__ fields can be marked by adding a `deprecation_reason:` keyword argument:

```ruby
Expand Down
1 change: 1 addition & 0 deletions guides/type_definitions/enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ end
Each value may have:

- A description (as the second argument or `description:` keyword)
- A comment (as a `comment:` keyword)
- A deprecation reason (as `deprecation_reason:`), marking this value as deprecated
- A corresponding Ruby value (as `value:`), see below

Expand Down
1 change: 1 addition & 0 deletions guides/type_definitions/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Then, include that into each interface:
```ruby
module Types::RetailItem
include Types::BaseInterface
comment "TODO comment in the RetailItem interface"
description "Something that can be bought"
field :price, Types::Price, "How much this item costs", null: false

Expand Down
1 change: 1 addition & 0 deletions guides/type_definitions/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ end

# then...
class Types::TodoList < Types::BaseObject
comment "Comment of the TodoList type"
description "A list of items which may be completed"

field :name, String, "The unique name of this list", null: false
Expand Down
1 change: 1 addition & 0 deletions guides/type_definitions/scalars.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ end

# app/graphql/types/url.rb
class Types::Url < Types::BaseScalar
comment "TODO comment of the scalar"
description "A valid URL, transported as a string"

def self.coerce_input(input_value, context)
Expand Down
1 change: 1 addition & 0 deletions guides/type_definitions/unions.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Then, extend that one for each union in your schema:

```ruby
class Types::CommentSubject < Types::BaseUnion
comment "TODO comment on the union"
description "Objects which may be commented on"
possible_types Types::Post, Types::Image

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: 9 additions & 0 deletions lib/graphql/language/document_from_schema_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def build_object_type_node(object_type)

GraphQL::Language::Nodes::ObjectTypeDefinition.new(
name: object_type.graphql_name,
comment: object_type.comment,
interfaces: ints,
fields: build_field_nodes(@types.fields(object_type)),
description: object_type.description,
Expand All @@ -68,6 +69,7 @@ def build_object_type_node(object_type)
def build_field_node(field)
GraphQL::Language::Nodes::FieldDefinition.new(
name: field.graphql_name,
comment: field.comment,
arguments: build_argument_nodes(@types.arguments(field)),
type: build_type_name_node(field.type),
description: field.description,
Expand All @@ -78,6 +80,7 @@ def build_field_node(field)
def build_union_type_node(union_type)
GraphQL::Language::Nodes::UnionTypeDefinition.new(
name: union_type.graphql_name,
comment: union_type.comment,
description: union_type.description,
types: @types.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
directives: directives(union_type),
Expand All @@ -87,6 +90,7 @@ def build_union_type_node(union_type)
def build_interface_type_node(interface_type)
GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
name: interface_type.graphql_name,
comment: interface_type.comment,
interfaces: @types.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
description: interface_type.description,
fields: build_field_nodes(@types.fields(interface_type)),
Expand All @@ -97,6 +101,7 @@ def build_interface_type_node(interface_type)
def build_enum_type_node(enum_type)
GraphQL::Language::Nodes::EnumTypeDefinition.new(
name: enum_type.graphql_name,
comment: enum_type.comment,
values: @types.enum_values(enum_type).sort_by(&:graphql_name).map do |enum_value|
build_enum_value_node(enum_value)
end,
Expand All @@ -108,6 +113,7 @@ def build_enum_type_node(enum_type)
def build_enum_value_node(enum_value)
GraphQL::Language::Nodes::EnumValueDefinition.new(
name: enum_value.graphql_name,
comment: enum_value.comment,
description: enum_value.description,
directives: directives(enum_value),
)
Expand All @@ -116,6 +122,7 @@ def build_enum_value_node(enum_value)
def build_scalar_type_node(scalar_type)
GraphQL::Language::Nodes::ScalarTypeDefinition.new(
name: scalar_type.graphql_name,
comment: scalar_type.comment,
description: scalar_type.description,
directives: directives(scalar_type),
)
Expand All @@ -130,6 +137,7 @@ def build_argument_node(argument)

argument_node = GraphQL::Language::Nodes::InputValueDefinition.new(
name: argument.graphql_name,
comment: argument.comment,
description: argument.description,
type: build_type_name_node(argument.type),
default_value: default_value,
Expand All @@ -142,6 +150,7 @@ def build_argument_node(argument)
def build_input_object_node(input_object)
GraphQL::Language::Nodes::InputObjectTypeDefinition.new(
name: input_object.graphql_name,
comment: input_object.comment,
fields: build_argument_nodes(@types.arguments(input_object)),
description: input_object.description,
directives: directives(input_object),
Expand Down
36 changes: 22 additions & 14 deletions lib/graphql/language/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,17 @@ def scalars
"col: nil",
"pos: nil",
"filename: nil",
"source: nil",
"source: nil"
]

IGNORED_MARSHALLING_KEYWORDS = [:comment]

def generate_initialize
return if method_defined?(:marshal_load, false) # checking for `:initialize` doesn't work right

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 @@ -307,6 +309,12 @@ def generate_initialize
keywords = scalar_method_names.map { |m| "#{m}: #{m}"} +
children_method_names.map { |m| "#{m}: #{m}" }

ignored_keywords = IGNORED_MARSHALLING_KEYWORDS.map do |keyword|
"#{keyword.to_s}: nil"
end

marshalling_method_names = all_method_names - IGNORED_MARSHALLING_KEYWORDS

module_eval <<-RUBY, __FILE__, __LINE__
def initialize(#{arguments.join(", ")})
@line = line
Expand All @@ -317,20 +325,20 @@ def initialize(#{arguments.join(", ")})
#{assignments.join("\n")}
end
def self.from_a(filename, line, col, #{all_method_names.join(", ")})
def self.from_a(filename, line, col, #{marshalling_method_names.join(", ")}, #{ignored_keywords.join(", ")})
self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
end
def marshal_dump
[
line, col, # use methods here to force them to be calculated
@filename,
#{all_method_names.map { |n| "@#{n}," }.join}
#{marshalling_method_names.map { |n| "@#{n}," }.join}
]
end
def marshal_load(values)
@line, @col, @filename #{all_method_names.map { |n| ", @#{n}"}.join} = values
@line, @col, @filename #{marshalling_method_names.map { |n| ", @#{n}"}.join} = values
end
RUBY
end
Expand Down Expand Up @@ -635,7 +643,7 @@ class SchemaExtension < AbstractNode
end

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

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

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

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

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

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

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

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

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

0 comments on commit 23c2770

Please sign in to comment.