lib/graphql/language/nodes.rb in graphql-2.1.13 vs lib/graphql/language/nodes.rb in graphql-2.2.0
- old
+ new
@@ -14,34 +14,34 @@
module DefinitionNode
# This AST node's {#line} returns the first line, which may be the description.
# @return [Integer] The first line of the definition (not the description)
attr_reader :definition_line
- def initialize(options = {})
- @definition_line = options.delete(:definition_line)
- super(options)
+ def initialize(definition_line: nil, **_rest)
+ @definition_line = definition_line
+ super(**_rest)
end
end
- attr_reader :line, :col, :filename
+ attr_reader :filename
- # Initialize a node by extracting its position,
- # then calling the class's `initialize_node` method.
- # @param options [Hash] Initial attributes for this node
- def initialize(options = {})
- if options.key?(:position_source)
- position_source = options.delete(:position_source)
- @line = position_source[1]
- @col = position_source[2]
- else
- @line = options.delete(:line)
- @col = options.delete(:col)
+ def line
+ @line ||= (@source_string && @pos) ? @source_string[0..@pos].count("\n") + 1 : nil
+ end
+
+ def col
+ @col ||= if @source_string && @pos
+ if @pos == 0
+ 1
+ else
+ @source_string[0..@pos].split("\n").last.length
+ end
end
+ end
- @filename = options.delete(:filename)
-
- initialize_node(**options)
+ def definition_line
+ @definition_line ||= (@source_string && @definition_pos) ? @source_string[0..@definition_pos].count("\n") + 1 : nil
end
# Value equality
# @return [Boolean] True if `self` is equivalent to `other`
def ==(other)
@@ -194,12 +194,12 @@
if node_type
# Only generate a method if we know what kind of node to make
module_eval <<-RUBY, __FILE__, __LINE__
# Singular method: create a node with these options
# and return a new `self` which includes that node in this list.
- def merge_#{method_name.to_s.sub(/s$/, "")}(node_opts)
- merge(#{method_name}: #{method_name} + [#{node_type.name}.new(node_opts)])
+ def merge_#{method_name.to_s.sub(/s$/, "")}(**node_opts)
+ merge(#{method_name}: #{method_name} + [#{node_type.name}.new(**node_opts)])
end
RUBY
end
end
@@ -224,17 +224,18 @@
RUBY
end
end
if defined?(@scalar_methods)
- if !method_defined?(:initialize_node)
- generate_initialize_node
+ if !@initialize_was_generated
+ @initialize_was_generated = true
+ generate_initialize
else
# This method was defined manually
end
else
- raise "Can't generate_initialize_node because scalar_methods wasn't called; call it before children_methods"
+ raise "Can't generate_initialize because scalar_methods wasn't called; call it before children_methods"
end
end
# These methods return a plain Ruby value, not another node
# - Add reader methods
@@ -259,11 +260,19 @@
end
RUBY
end
end
- def generate_initialize_node
+ DEFAULT_INITIALIZE_OPTIONS = [
+ "line: nil",
+ "col: nil",
+ "pos: nil",
+ "filename: nil",
+ "source_string: nil",
+ ]
+
+ 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|
if method_defined?(extra_method)
scalar_method_names += [extra_method]
@@ -275,20 +284,31 @@
# Rather than complicating this special case,
# let it be overridden (in field)
return
else
arguments = scalar_method_names.map { |m| "#{m}: nil"} +
- @children_methods.keys.map { |m| "#{m}: NO_CHILDREN" }
+ @children_methods.keys.map { |m| "#{m}: NO_CHILDREN" } +
+ DEFAULT_INITIALIZE_OPTIONS
assignments = scalar_method_names.map { |m| "@#{m} = #{m}"} +
@children_methods.keys.map { |m| "@#{m} = #{m}.freeze" }
+ if name.end_with?("Definition") && name != "FragmentDefinition"
+ arguments << "definition_pos: nil"
+ assignments << "@definition_pos = definition_pos"
+ end
+
keywords = scalar_method_names.map { |m| "#{m}: #{m}"} +
@children_methods.keys.map { |m| "#{m}: #{m}" }
module_eval <<-RUBY, __FILE__, __LINE__
- def initialize_node #{arguments.join(", ")}
+ def initialize(#{arguments.join(", ")})
+ @line = line
+ @col = col
+ @pos = pos
+ @filename = filename
+ @source_string = source_string
#{assignments.join("\n")}
end
def self.from_a(filename, line, col, #{(scalar_method_names + @children_methods.keys).join(", ")})
self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
@@ -334,11 +354,10 @@
class DirectiveLocation < NameOnlyNode
end
class DirectiveDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name, :repeatable
children_methods(
arguments: Nodes::Argument,
locations: Nodes::DirectiveLocation,
@@ -363,52 +382,61 @@
})
# @!attribute selections
# @return [Array<Nodes::Field>] Selections on this object (or empty array if this is a scalar field)
- def initialize_node(attributes)
- @name = attributes[:name]
- @arguments = attributes[:arguments] || NONE
- @directives = attributes[:directives] || NONE
- @selections = attributes[:selections] || NONE
+ def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source_string: nil)
+ @name = name
+ @arguments = arguments || NONE
+ @directives = directives || NONE
+ @selections = selections || NONE
# oops, alias is a keyword:
- @alias = attributes[:alias]
+ @alias = field_alias
+ @line = line
+ @col = col
+ @pos = pos
+ @filename = filename
+ @source_string = source_string
end
- def self.from_a(filename, line, col, graphql_alias, name, arguments, directives, selections) # rubocop:disable Metrics/ParameterLists
- self.new(filename: filename, line: line, col: col, alias: graphql_alias, name: name, arguments: arguments, directives: directives, selections: selections)
+ 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)
end
# Override this because default is `:fields`
self.children_method_name = :selections
end
# A reusable fragment, defined at document-level.
class FragmentDefinition < AbstractNode
+ scalar_methods :name, :type
+ children_methods({
+ selections: GraphQL::Language::Nodes::Field,
+ directives: GraphQL::Language::Nodes::Directive,
+ })
+
+ self.children_method_name = :definitions
# @!attribute name
# @return [String] the identifier for this fragment, which may be applied with `...#{name}`
# @!attribute type
# @return [String] the type condition for this fragment (name of type which it may apply to)
- def initialize_node(name: nil, type: nil, directives: [], selections: [])
+ def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source_string: nil, line: nil, col: nil)
@name = name
@type = type
@directives = directives
@selections = selections
+ @filename = filename
+ @pos = pos
+ @source_string = source_string
+ @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)
end
-
- scalar_methods :name, :type
- children_methods({
- selections: GraphQL::Language::Nodes::Field,
- directives: GraphQL::Language::Nodes::Directive,
- })
-
- self.children_method_name = :definitions
end
# Application of a named fragment in a selection
class FragmentSpread < AbstractNode
scalar_methods :name
@@ -560,11 +588,10 @@
class VariableIdentifier < NameOnlyNode
self.children_method_name = :value
end
class SchemaDefinition < AbstractNode
- include DefinitionNode
scalar_methods :query, :mutation, :subscription
children_methods({
directives: GraphQL::Language::Nodes::Directive,
})
self.children_method_name = :definitions
@@ -577,11 +604,10 @@
})
self.children_method_name = :definitions
end
class ScalarTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
})
@@ -595,21 +621,19 @@
})
self.children_method_name = :definitions
end
class InputValueDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name, :type, :default_value
children_methods({
directives: GraphQL::Language::Nodes::Directive,
})
self.children_method_name = :fields
end
class FieldDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name, :type
children_methods({
arguments: GraphQL::Language::Nodes::InputValueDefinition,
directives: GraphQL::Language::Nodes::Directive,
@@ -626,11 +650,10 @@
super
end
end
class ObjectTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name, :interfaces
children_methods({
directives: GraphQL::Language::Nodes::Directive,
fields: GraphQL::Language::Nodes::FieldDefinition,
@@ -646,11 +669,10 @@
})
self.children_method_name = :definitions
end
class InterfaceTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name
children_methods({
interfaces: GraphQL::Language::Nodes::TypeName,
directives: GraphQL::Language::Nodes::Directive,
@@ -668,11 +690,10 @@
})
self.children_method_name = :definitions
end
class UnionTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description, :types
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
})
@@ -687,21 +708,19 @@
})
self.children_method_name = :definitions
end
class EnumValueDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
})
self.children_method_name = :values
end
class EnumTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
values: GraphQL::Language::Nodes::EnumValueDefinition,
@@ -717,10 +736,9 @@
})
self.children_method_name = :definitions
end
class InputObjectTypeDefinition < AbstractNode
- include DefinitionNode
attr_reader :description
scalar_methods :name
children_methods({
directives: GraphQL::Language::Nodes::Directive,
fields: GraphQL::Language::Nodes::InputValueDefinition,