rubocop-rhino-project 0.21.0.beta.35 → 0.21.0.beta.38

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22e138d8dfc9aa01209d58d208b2d7d4e1d9c571dea924e606da446a35f1108e
4
- data.tar.gz: f61cbc2949ad06a3f0b841fd476a47df1283bbd4a8a97978d8a37b440b362ba5
3
+ metadata.gz: a9e03d22a4a2592db9f1d8ab043d3aeff065bc1398ec035e707418d68ef6c2e6
4
+ data.tar.gz: e2720fc71261d851c75ccc52bd2781c0fa9f00482d0f9e5ebbff264550581d8e
5
5
  SHA512:
6
- metadata.gz: d6ef46c456de287126e82161412eb27612ed6125a31f9937e3295494547072f756294fbf0bfe271c4d9497cde5135af033b5f2e3e9f25f6991a45172555add31
7
- data.tar.gz: f518c2b126f09b79fbaa8e9634c53b75658ff259360ca5232da29c353f4b691b006abe93eab9a104e0f0c5c98a428964b6779208a1eac8f5444bb4feaf46bb77
6
+ metadata.gz: 37446aa28dbb529fb3feb8f3e3cd2c4c7721ba0dd0cf02046610d122ceb918d9a8cf266223d9b08321286abb28d3e7b6dffe1a72dc6a83f19302f16035165fd0
7
+ data.tar.gz: e66e5e8f4403316080fe0c8d4fa62ede3db7ef98a3617dbe6bd568abf46495e4eaffee0357dbb6c80a79205ce2ea500e0059a9d6095331565e618d439f9a81d3
data/config/default.yml CHANGED
@@ -16,6 +16,11 @@ AllCops:
16
16
  - storage/**/*
17
17
 
18
18
  RhinoProject/DuplicateRhinoReferences:
19
- Description: ''
19
+ Description: 'Check for duplicate rhino_reference calls in the same file.'
20
+ Enabled: true
21
+ SafeAutoCorrect: false
22
+
23
+ RhinoProject/OwnerSpecified:
24
+ Description: 'Check for rhino_owner_global, rhino_owner_base or rhino_owner calls'
20
25
  Enabled: true
21
26
  SafeAutoCorrect: false
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parser/current"
4
+ module RuboCop
5
+ module Cop
6
+ module RhinoProject
7
+ # Call `rhino_owner`, `rhino_owner_base` or `rhino_owner_global` for the model class.
8
+ #
9
+ #
10
+ # @example
11
+ # # bad
12
+ # class Blog < ApplicationRecord
13
+ # belongs_to :user
14
+ # belongs_to :category
15
+ #
16
+ # rhino_references %i[user]
17
+ # end
18
+ #
19
+ # # good
20
+ # class Blog < ApplicationRecord
21
+ # belongs_to :user
22
+ # belongs_to :category
23
+ #
24
+ # rhino_owner :user
25
+ # rhino_references %i[user category]
26
+ # end
27
+ #
28
+ class OwnerSpecified < Cop
29
+ MSG = "ActiveRecord models listed in rhino.rb must specify exactly one ownership method (rhino_owner_global, rhino_owner_reference, or rhino_owner :symbol)."
30
+
31
+ REQUIRED_METHODS = [:rhino_owner_global, :rhino_owner_base, :rhino_owner].freeze
32
+
33
+ def investigate(processed_source)
34
+ return unless applicable_model?(processed_source)
35
+
36
+ class_node = find_class_node(processed_source.ast)
37
+ return unless class_node
38
+
39
+ method_calls = find_rhino_owner_calls(class_node)
40
+
41
+ if method_calls.size != 1
42
+ add_offense(class_node, message: MSG)
43
+ end
44
+ end
45
+
46
+ private
47
+ def applicable_model?(processed_source)
48
+ model_name = extract_class_name(processed_source)
49
+
50
+ return false if inherits_from_rhino?(processed_source)
51
+
52
+ rhino_resources.include?(model_name)
53
+ end
54
+
55
+ def extract_class_name(processed_source)
56
+ class_node = find_class_node(processed_source.ast)
57
+ return unless class_node
58
+
59
+ class_name_node = class_node.children[0]
60
+ class_name_node.const_name
61
+ end
62
+
63
+ def find_rhino_owner_calls(class_node)
64
+ # Search only within the class body for Rhino ownership method calls
65
+ body_node = class_node.children[2]
66
+ find_descendants(body_node).select do |send_node|
67
+ send_node.type == :send && REQUIRED_METHODS.include?(send_node.children[1])
68
+ end
69
+ end
70
+
71
+ def find_class_node(ast)
72
+ find_descendants(ast).find { |node| node.type == :class }
73
+ end
74
+
75
+ # Check if the class inherits from a Rhino:: class
76
+ def inherits_from_rhino?(processed_source)
77
+ class_node = find_class_node(processed_source.ast)
78
+ return false unless class_node
79
+
80
+ superclass_node = class_node.children[1]
81
+ return false unless superclass_node
82
+
83
+ superclass_name = superclass_node.const_name
84
+ superclass_name&.start_with?("Rhino::")
85
+ end
86
+
87
+ def rhino_resources
88
+ @rhino_resources ||= read_rhino_resources
89
+ end
90
+
91
+ def read_rhino_resources
92
+ rhino_initializer_path = File.join(Dir.pwd, "config", "initializers", "rhino.rb")
93
+ return [] unless File.exist?(rhino_initializer_path)
94
+
95
+ rhino_initializer_content = File.read(rhino_initializer_path)
96
+ ast = Parser::CurrentRuby.parse(rhino_initializer_content)
97
+ parse_rhino_resources(ast)
98
+ end
99
+
100
+ # Parse the rhino.rb AST and extract the resources added to config.resources
101
+ def parse_rhino_resources(ast)
102
+ resources = []
103
+
104
+ find_resources_assignments(ast).each do |assignment_node|
105
+ next unless assignment_node
106
+
107
+ # Looking for array elements in `config.resources += [...]`
108
+ array_node = assignment_node.children[2] # Accessing the right-hand side of `+=`
109
+ if array_node&.type == :array
110
+ resources.concat(array_node.children.map { |node| extract_string(node) })
111
+ end
112
+ end
113
+
114
+ resources.compact
115
+ end
116
+
117
+ # Now looking for `op_asgn` nodes that represent `config.resources += [...]`
118
+ def find_resources_assignments(ast)
119
+ find_descendants(ast).select do |node|
120
+ node.type == :op_asgn && node.children[1] == :+
121
+ end
122
+ end
123
+
124
+ def extract_string(node)
125
+ return unless node.type == :str
126
+
127
+ node.children[0]
128
+ end
129
+
130
+ # Custom method to recursively find descendants in a generic AST node (Parser or RuboCop)
131
+ def find_descendants(node, &block)
132
+ return [] unless node.is_a?(Parser::AST::Node)
133
+
134
+ results = [node]
135
+ node.children.each do |child|
136
+ next unless child.is_a?(Parser::AST::Node)
137
+
138
+ results.concat(find_descendants(child, &block))
139
+ end
140
+ results
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "rhino_project/duplicate_rhino_references"
4
+ require_relative "rhino_project/owner_specified"
@@ -10,7 +10,7 @@ module RubocopRhinoProject
10
10
  MAJOR = 0
11
11
  MINOR = 21
12
12
  TINY = 0
13
- PRE = "beta.35"
13
+ PRE = "beta.38"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rhino-project
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0.beta.35
4
+ version: 0.21.0.beta.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Rosevear
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-06 00:00:00.000000000 Z
11
+ date: 2024-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -88,6 +88,7 @@ files:
88
88
  - config/default.yml
89
89
  - lib/rubocop-rhino-project.rb
90
90
  - lib/rubocop/cop/rhino_project/duplicate_rhino_references.rb
91
+ - lib/rubocop/cop/rhino_project/owner_specified.rb
91
92
  - lib/rubocop/cop/rhino_project_cops.rb
92
93
  - lib/rubocop/rhino_project.rb
93
94
  - lib/rubocop/rhino_project/inject.rb
@@ -98,7 +99,7 @@ homepage: ''
98
99
  licenses:
99
100
  - MIT
100
101
  metadata: {}
101
- post_install_message:
102
+ post_install_message:
102
103
  rdoc_options: []
103
104
  require_paths:
104
105
  - lib
@@ -114,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
115
  version: '0'
115
116
  requirements: []
116
117
  rubygems_version: 3.5.16
117
- signing_key:
118
+ signing_key:
118
119
  specification_version: 4
119
120
  summary: ''
120
121
  test_files: []