yard-sequel 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9284ee1351b6a7f96efc170c14aef164245d849790b08ace886b7e94a86c305f
4
- data.tar.gz: 5c3d39bd376f18edf52a20b4d5e729a0c52ced190435161b5a6cf6fb37dce4ad
3
+ metadata.gz: de753ba555cdc4d50a3529d696acfc430267520084be6be153350a53a7d6f0e0
4
+ data.tar.gz: a2a0b1b504e2e37dd52e484fdf8880186b13a7d7f28f4db8e11082cec38e86ec
5
5
  SHA512:
6
- metadata.gz: 846c464a14c21f7f0c415961f6ced942deb2247143a20675a8b22dd7cde9becb2ed017e7d438f538ccb6a098139695cc1fadf96fae608084c0780a9d1bc3bcc8
7
- data.tar.gz: 95a2d3e008efc2c0f6b4839465b70eaae1fc10de39cdefac228236ab3a62ebf61773314f381b3570d530a9830a45c773fc51b797cc0eb0ace075ef252ef91e58
6
+ metadata.gz: 18d50a853a958f1999996ecd350626c778a9be1c9288a37b45167927c8264e61bf5ac2521f7bf80501734dec183192cfac5d7bbcbc326f355dcf62c730810f0d
7
+ data.tar.gz: 222fcedd00f7b9be0f62ceffa307ca39ce62494447f4be0f76b86cb3ad8e13cad91c5321b0f325f5f5facc88a0d09fd73adf05352be3d10e4340630ee47a6071
data/lib/yard-sequel.rb CHANGED
@@ -10,4 +10,5 @@ Sequel.extension :inflector
10
10
  module YardSequel; end
11
11
 
12
12
  require_relative 'yard-sequel/associations'
13
+ require_relative 'yard-sequel/association_options'
13
14
  require_relative 'yard-sequel/ast_node_hash'
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardSequel
4
+ # Holds the options of an association macro call and makes them easily
5
+ # accessible.
6
+ # @author Kai Moschcau
7
+ class AssociationOptions
8
+ # @param [Hash<Yard::Parser::Ruby::AstNode>] ast_node_hash A Hash created
9
+ # with the {AstNodeHash} module, to get the options from.
10
+ def initialize(ast_node_hash)
11
+ @ast_node_hash = {}
12
+ ast_node_hash.each do |name, parameter|
13
+ @ast_node_hash[parse_symbol_node name] = parse_symbol_node parameter
14
+ end
15
+ end
16
+
17
+ # @param [Symbol] option_name The name of the option, to get the parameter
18
+ # of.
19
+ # @return [Yard::Parser::Ruby::AstNode] the option parameter value.
20
+ def [](option_name)
21
+ @ast_node_hash[option_name]
22
+ end
23
+
24
+ private
25
+
26
+ # Extracts the String content of a Symbol literal AstNode as a Symbol. It
27
+ # gets the source, then removes the leading or trailing colon. Afterwards it
28
+ # removes the leading and trailing quotes, if there are any and returns the
29
+ # result as a Symbol.
30
+ # @param [Yard::Parser::Ruby::AstNode] ast_node The Symbol literal AstNode
31
+ # to get the content from.
32
+ # @return [Symbol] the Symbol literal's content as a Symbol.
33
+ def extract_symbol_content(ast_node)
34
+ ast_node.source.gsub(/(?:^:|:$)/, '').gsub(/(?:^['"]|['"]$)/, '').to_sym
35
+ end
36
+
37
+ # Parses a Symbol literal AstNode, if possible. This will return a Symbol
38
+ # with the Symbol literal's content String, if the literal is a Hash label,
39
+ # a normal Symbol literal or a dynamic Symbol literal without interpolation.
40
+ # @param [Yard::Parser::Ruby::AstNode] symbol_node The AstNode to get the
41
+ # content String from.
42
+ # @return [Symbol] the parsed Symbol.
43
+ # @return [Yard::Parser::Ruby::AstNode] the passed node, if it could not be
44
+ # parsed.
45
+ def parse_symbol_node(symbol_node)
46
+ if %i[symbol_literal label dyna_symbol].include? symbol_node.type
47
+ # Return if the literal contains interpolation
48
+ return symbol_node if symbol_node.jump(:string_embexpr) != symbol_node
49
+
50
+ return extract_symbol_content(symbol_node)
51
+ end
52
+
53
+ symbol_node
54
+ end
55
+ end
56
+ end
@@ -7,13 +7,14 @@ module YardSequel
7
7
  class AssociationHandler < YARD::Handlers::Ruby::DSLHandler
8
8
  def process
9
9
  log.debug { "#{self.class.name}#process call" }
10
+ @association_options = association_options
10
11
  end
11
12
 
12
13
  protected
13
14
 
14
15
  # Adds a parameter tag to a method object.
15
- # @param [YARD::CodeObjects::MethodObject] method
16
- # The method to add the parameter tag to.
16
+ # @param [YARD::CodeObjects::MethodObject] method The method to add the
17
+ # parameter tag to.
17
18
  # @param [String] name The name of the parameter.
18
19
  # @param [String] class_name The class name of the parameter.
19
20
  # @param [String] description The description of the parameter.
@@ -25,15 +26,46 @@ module YardSequel
25
26
  )
26
27
  end
27
28
 
29
+ # @return [String] the association Class without namespace.
30
+ def association_class
31
+ class_param = @association_options&.[](:class)
32
+ return class_param.to_s.split('::').last if
33
+ [String, Symbol].include? class_param.class
34
+
35
+ association_name.classify
36
+ end
37
+
38
+ # @return [String] the namespace of the association class.
39
+ def association_class_namespace
40
+ class_namespace_param = @association_options&.[](:class_namespace)
41
+ return class_namespace_param.to_s if
42
+ [String, Symbol].include? class_namespace_param.class
43
+
44
+ class_param = @association_options&.[](:class)
45
+ return class_param.to_s.rpartition('::').first if
46
+ [String, Symbol].include? class_param.class
47
+ end
48
+
49
+ # @return [String] the association Class with namespace.
50
+ def association_full_class
51
+ [association_class_namespace, association_class].compact.join('::')
52
+ end
53
+
28
54
  # @return [String] the name of the association
29
55
  def association_name
30
56
  @statement.parameters.first.jump(:ident).source
31
57
  end
32
58
 
33
- # @return [Array<YARD::Parser::Ruby::AstNode>] the association nodes
34
- # of the options Hash.
59
+ # @return [nil] If the association does not have an options parameter or
60
+ # it is empty.
61
+ # @return [AssociationOptions] the AssociationOptions of the association.
35
62
  def association_options
36
- @statement.parameters[1].filter { |node| node.type == :assoc }
63
+ option_param = @statement.parameters[1] || return
64
+ AssociationOptions.new AstNodeHash.from_ast(option_param)
65
+ rescue ArgumentError, TypeError => error
66
+ log.warn 'Could not parse association options due to syntax error.'
67
+ log.debug error.message
68
+ nil
37
69
  end
38
70
 
39
71
  # @param [String] name The name of the method object.
@@ -9,11 +9,15 @@ module YardSequel
9
9
  include YardSequel::Associations::ToOneMethods
10
10
  handles method_call(:many_to_one)
11
11
  namespace_only
12
+
12
13
  def process
13
14
  super
15
+ original_group = extra_state.group
16
+ extra_state.group = "Many to one #{association_name} association"
14
17
  create_to_one_getter
15
18
  create_to_one_setter
16
19
  create_dataset_method
20
+ extra_state.group = original_group
17
21
  end
18
22
  end
19
23
  end
@@ -9,8 +9,7 @@ module YardSequel
9
9
  # object.
10
10
  def create_dataset_method
11
11
  method = create_method_object("#{association_name}_dataset")
12
- return_tag(method, 'Sequel::Dataset', 'the association\'s'\
13
- 'dataset.')
12
+ return_tag(method, 'Sequel::Dataset', 'the association\'s dataset.')
14
13
  method
15
14
  end
16
15
  end
@@ -10,12 +10,12 @@ module YardSequel
10
10
  def create_to_many_adder
11
11
  name = association_name
12
12
  method = create_method_object "add_#{name.singularize}"
13
- method.docstring += "Associates the passed #{name.classify} "\
13
+ method.docstring += "Associates the passed #{association_class} "\
14
14
  'with `self`.'
15
- add_param_tag(method, name.singularize, name.classify,
16
- "The #{name.classify} to associate with `self`.")
17
- return_tag(method, name.classify,
18
- "the associated #{name.classify}.")
15
+ add_param_tag(method, name.singularize, association_full_class,
16
+ "The #{association_class} to associate with `self`.")
17
+ return_tag(method, association_full_class,
18
+ "the associated #{association_class}.")
19
19
  method
20
20
  end
21
21
 
@@ -25,7 +25,7 @@ module YardSequel
25
25
  name = association_name
26
26
  method = create_method_object "remove_all_#{name}"
27
27
  method.docstring += 'Removes the association of all '\
28
- "#{name.classify.pluralize} with `self`."
28
+ "#{association_class.pluralize} with `self`."
29
29
  void_return_tag method
30
30
  method
31
31
  end
@@ -35,8 +35,8 @@ module YardSequel
35
35
  def create_to_many_getter
36
36
  name = association_name
37
37
  method = create_method_object name
38
- return_tag(method, "Array<#{name.classify}>",
39
- "the associated #{name.classify.pluralize}.")
38
+ return_tag(method, "Array<#{association_full_class}>",
39
+ "the associated #{association_class.pluralize}.")
40
40
  method
41
41
  end
42
42
 
@@ -46,9 +46,9 @@ module YardSequel
46
46
  name = association_name
47
47
  method = create_method_object "remove_#{name.singularize}"
48
48
  method.docstring += 'Removes the association of the passed '\
49
- "#{name.classify} with `self`."
50
- add_param_tag(method, name.singularize, name.classify,
51
- "The #{name.classify} to remove the association "\
49
+ "#{association_class} with `self`."
50
+ add_param_tag(method, name.singularize, association_full_class,
51
+ "The #{association_class} to remove the association "\
52
52
  'with `self` from.')
53
53
  void_return_tag method
54
54
  method
@@ -10,8 +10,8 @@ module YardSequel
10
10
  def create_to_one_getter
11
11
  name = association_name
12
12
  method = create_method_object name
13
- return_tag(method, name.classify,
14
- "the associated #{name.classify}.")
13
+ return_tag(method, association_full_class,
14
+ "the associated #{association_class}.")
15
15
  method
16
16
  end
17
17
 
@@ -20,12 +20,12 @@ module YardSequel
20
20
  def create_to_one_setter
21
21
  name = association_name
22
22
  method = create_method_object "#{name}="
23
- method.docstring += "Associates the passed #{name.classify} "\
23
+ method.docstring += "Associates the passed #{association_class} "\
24
24
  'with `self`.'
25
- add_param_tag(method, name, name.classify,
26
- "The #{name.classify} to associate with `self`.")
27
- return_tag(method, name.classify,
28
- "the associated #{name.classify}.")
25
+ add_param_tag(method, name, association_full_class,
26
+ "The #{association_class} to associate with `self`.")
27
+ return_tag(method, association_full_class,
28
+ "the associated #{association_class}.")
29
29
  method
30
30
  end
31
31
  end
@@ -9,13 +9,17 @@ module YardSequel
9
9
  include YardSequel::Associations::ToManyMethods
10
10
  handles method_call(:one_to_many)
11
11
  namespace_only
12
+
12
13
  def process
13
14
  super
15
+ original_group = extra_state.group
16
+ extra_state.group = "One to many #{association_name} association"
14
17
  create_to_many_adder
15
18
  create_to_many_clearer
16
19
  create_to_many_getter
17
20
  create_to_many_remover
18
21
  create_dataset_method
22
+ extra_state.group = original_group
19
23
  end
20
24
  end
21
25
  end
@@ -1,16 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YardSequel
4
- # Offers methods to convert an Abstract Syntax Tree to a Hash consisting
5
- # of `YARD::Parser::Ruby::AstNode`s.
4
+ # Offers methods to convert an Abstract Syntax Tree of a Hash literal or named
5
+ # method parameters to a Hash consisting of `YARD::Parser::Ruby::AstNode`s.
6
6
  # @author Kai Moschcau
7
7
  module AstNodeHash
8
8
  class << self
9
+ # Creates a new Hash from the passed AstNode. This is the main method to
10
+ # use, to create a new Hash.
11
+ # @param (see .node_hash_from_node)
12
+ # @raise (see .check_ast)
13
+ # @return (see .node_hash_from_node)
9
14
  def from_ast(ast)
10
15
  check_ast ast
11
16
  node_hash_from_node ast
12
17
  end
13
18
 
19
+ # Checks the passed AstNode for validity. If the AstNode is valid, this
20
+ # method does not raise an error.
21
+ # @raise [TypeError, ArgumentError] If the AstNode is not valid.
22
+ # @param [YARD::Parser::Ruby::AstNode] ast The AstNode to check for
23
+ # validity.
14
24
  def check_ast(ast)
15
25
  check_is_ast_node ast
16
26
  check_is_hash_or_list ast
@@ -22,12 +32,19 @@ module YardSequel
22
32
 
23
33
  private
24
34
 
35
+ # Checks if the given child AstNode has exactly two children.
36
+ # @raise [ArgumentError] If if does not have 2 children.
37
+ # @return [void]
25
38
  def check_assoc_child_has_two_children(child_ast)
26
39
  return if child_ast.children.size == 2
27
40
 
28
41
  raise(ArgumentError, 'each `:assoc` child must have two children')
29
42
  end
30
43
 
44
+ # Checks the children of the given AstNode. Mainly it first checks, if the
45
+ # AstNode has only `:assoc` type children and if each child has two
46
+ # further children.
47
+ # @return [void]
31
48
  def check_children(ast)
32
49
  check_has_only_assoc_children ast
33
50
  ast.children.each do |child_ast|
@@ -35,6 +52,9 @@ module YardSequel
35
52
  end
36
53
  end
37
54
 
55
+ # Checks if the children of the passed AstNode are all of type `:assoc`.
56
+ # @raise [ArgumentError] If there is at least one not of type `:assoc`.
57
+ # @return [void]
38
58
  def check_has_only_assoc_children(ast)
39
59
  return unless ast.children.any? { |child| child.type != :assoc }
40
60
 
@@ -42,12 +62,18 @@ module YardSequel
42
62
  'all children of the passed `ast` have to have the type `:assoc`')
43
63
  end
44
64
 
65
+ # Checks the children of a `:hash` type AstNode. If the AstNode has no
66
+ # children, this does nothing. Otherwise it runs {.check_children}.
67
+ # @return [void]
45
68
  def check_hash_children(ast)
46
69
  return if ast.children.empty?
47
70
 
48
71
  check_children ast
49
72
  end
50
73
 
74
+ # Checks, whether the passed Object is a `YARD::Parser::Ruby::AstNode`.
75
+ # @raise [TypeError] If the passed Object is not of the correct type.
76
+ # @return [void]
51
77
  def check_is_ast_node(ast)
52
78
  return if ast.is_a? YARD::Parser::Ruby::AstNode
53
79
 
@@ -55,6 +81,9 @@ module YardSequel
55
81
  'the passed `ast` has to be a `YARD::Parser::Ruby::AstNode`')
56
82
  end
57
83
 
84
+ # Checks, whether the passed AstNode is of Type `:hash` or `:list`.
85
+ # @raise [ArgumentError] If the passed AstNode is not of the correct type.
86
+ # @return [void]
58
87
  def check_is_hash_or_list(ast)
59
88
  return if %i[hash list].include? ast.type
60
89
 
@@ -62,6 +91,10 @@ module YardSequel
62
91
  "the passed `ast`'s type has to be `:hash` or `:list`")
63
92
  end
64
93
 
94
+ # Checks the children of a `:list` type AstNode. If the AstNode has no
95
+ # children, this raises an error. Otherwise it runs {.check_children}.
96
+ # @raise [ArgumentError] If the passed AstNode has no children.
97
+ # @return [void]
65
98
  def check_list_children(ast)
66
99
  if ast.children.empty?
67
100
  raise(ArgumentError,
@@ -70,6 +103,10 @@ module YardSequel
70
103
  check_children ast
71
104
  end
72
105
 
106
+ # Converts the passed AstNode to a Hash.
107
+ # @param [YARD::Parser::Ruby::AstNode] ast The AstNode to convert to a
108
+ # Hash.
109
+ # @return [Hash<YARD::Parser::Ruby::AstNode>] the converted Hash.
73
110
  def node_hash_from_node(ast)
74
111
  hash = {}
75
112
  ast.children.each { |cn| hash[cn.children[0]] = cn.children[1] }
@@ -7,11 +7,11 @@ module YardSequel
7
7
 
8
8
  # The minor version number.
9
9
  # Used for changes that are backwards compatible.
10
- V_MINOR = 1
10
+ V_MINOR = 2
11
11
 
12
12
  # The build version number.
13
13
  # Used for internal changes.
14
- V_BUILD = 1
14
+ V_BUILD = 0
15
15
 
16
16
  # The version of the Sequel models.
17
17
  VERSION = Gem::Version.new("#{V_MAJOR}.#{V_MINOR}.#{V_BUILD}")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard-sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kai Moschcau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2018-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -122,6 +122,7 @@ extra_rdoc_files: []
122
122
  files:
123
123
  - ".yardopts"
124
124
  - lib/yard-sequel.rb
125
+ - lib/yard-sequel/association_options.rb
125
126
  - lib/yard-sequel/associations.rb
126
127
  - lib/yard-sequel/associations/association_handler.rb
127
128
  - lib/yard-sequel/associations/many_to_one_handler.rb