rubocop-iotventure 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: 5d0d7b568c5726071030b7e7726c8b23c03a6169e717faf47112d76b6c375fc5
4
- data.tar.gz: 229e07f5b7b072d3fcaca91b735227c2e639814f3efc949c135b2c47f8df3d8f
3
+ metadata.gz: 8d7b5e0864c57af9dfe62005ea09865ac27c92fcc5fcc34d4019045aa7d54946
4
+ data.tar.gz: 0c4174349f69ab40a37a476e1613c8a564ce8eb2982d15f05f4de821fb6a6544
5
5
  SHA512:
6
- metadata.gz: 8c79b83a2cb794ffe161438753b0e161e09afec8b9b845b54d62affe8ed25189efc2932932fd56eee60575c98f0631f944502f55853bed59c52a70fe76e2cde0
7
- data.tar.gz: cc8f99a6df08bab9d5351aee184403086d6466727b66df22624187ebae6ff2d226f65f82dc2e17289bb18dc96b27f1b5d762b0183f50adc82ea702deb2fa460a
6
+ metadata.gz: bab135bc00dc0221d376696da3adc36dad336635ad85209cc4a32eab525646ecbd69e0f77f85d5c9fc5de32fec8278970ff987152ff58697b78a68dc6ad76c78
7
+ data.tar.gz: 3a91e6bf9c5cb446919b89409ef921561d615466c27fd590edd3170c47915970b0bd8a3f7125d09e0968aee662a702831e87fbea6530eacbf9e88a77d0fa2e71
data/.rubocop.yml CHANGED
@@ -15,6 +15,9 @@ Metrics/BlockLength:
15
15
  - '**/spec/**/*'
16
16
  - 'rubocop-iotventure.gemspec'
17
17
 
18
+ Metrics/ClassLength:
19
+ CountAsOne: ['array', 'hash', 'heredoc']
20
+
18
21
  Naming/FileName:
19
22
  Exclude:
20
23
  - lib/rubocop-iotventure.rb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2022-05-12
4
+
5
+ - FB-111 Add SchemaDefinitionPerResponse cop
6
+
7
+ ## [0.1.1] - 2022-04-18
8
+
9
+ - Fix error for nonexistent response definition
10
+
3
11
  ## [0.1.0] - 2022-04-18
4
12
 
5
13
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-iotventure (0.1.1)
4
+ rubocop-iotventure (0.2.0)
5
5
  rubocop (~> 1.0)
6
6
  rubocop-rake (~> 0.6.0)
7
7
 
@@ -71,4 +71,4 @@ DEPENDENCIES
71
71
  simplecov
72
72
 
73
73
  BUNDLED WITH
74
- 2.2.32
74
+ 2.3.13
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Rubocop::Iotventure
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rubocop/iotventure`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ This is a gem running some internal checks for IoTVenture. All of the existing cops are for RSwag, but that might change in the future.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,7 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- ### Rswag/DuplicateResponseCode
23
+ ### Iotventure/DuplicateResponseCode
26
24
 
27
25
  ```ruby
28
26
  # bad
@@ -36,7 +34,7 @@ response 401, 'response description 2' {}
36
34
 
37
35
  This cop prevents duplicated response code blocks. Those would overwrite each other when generating the `swagger.yaml` file.
38
36
 
39
- ### Rswag/SaveRequestExample
37
+ ### Iotventure/SaveRequestExample
40
38
 
41
39
  ```ruby
42
40
  # bad
@@ -50,6 +48,29 @@ response 200, 'response description', save_request_example: :param1 {}
50
48
 
51
49
  This cop enforces usage of the `save_request_example` parameter in `api` files (saves the body parameter). This should only be enabled when there is custom logic reacting to this parameter.
52
50
 
51
+ ### Iotventure/SchemaDefinitionPerResponse
52
+
53
+ ```ruby
54
+ # bad
55
+ response 200, 'response description' do
56
+ context 'context' do
57
+ schema '$ref' => '#/components/schemas/object'
58
+ end
59
+ end
60
+
61
+ # bad
62
+ schema '$ref' => '#/components/schemas/object'
63
+ response 200, 'response description' {}
64
+
65
+
66
+ # good
67
+ response 200, 'response description' do
68
+ schema '$ref' => '#/components/schemas/object'
69
+ end
70
+ ```
71
+
72
+ This cop checks that there is exactly one top-level schema definition per response block. This makes sure that they do not overwrite each other.
73
+
53
74
  ## Development
54
75
 
55
76
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Iotventure
6
+ # This cop checks that there is exactly one top-level schema definition per response declaration.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ #
12
+ # response 200, 'response description' {}
13
+ #
14
+ #
15
+ # @example
16
+ #
17
+ # # bad
18
+ #
19
+ # response 200, 'response description' do
20
+ # context 'context' do
21
+ # schema '$ref' => '#/components/schemas/object'
22
+ # end
23
+ # end
24
+ #
25
+ #
26
+ # @example
27
+ #
28
+ # # bad
29
+ #
30
+ # response 200, 'response description' do
31
+ # schema '$ref' => '#/components/schemas/object1'
32
+ # schema '$ref' => '#/components/schemas/object2'
33
+ # end
34
+ #
35
+ #
36
+ # @example
37
+ #
38
+ # # bad
39
+ #
40
+ # schema '$ref' => '#/components/schemas/object'
41
+ # response 200, 'response description' {}
42
+ #
43
+ #
44
+ # @example
45
+ #
46
+ # # good
47
+ #
48
+ # response 200, 'response description' do
49
+ # schema '$ref' => '#/components/schemas/object'
50
+ # end
51
+ #
52
+ #
53
+ class SchemaDefinitionPerResponse < Base
54
+ MISSING_MSG = 'Schema definition is missing for response declaration at %<current>s.'
55
+ DUPLICATED_MSG = 'Schema definition is defined both at %<first>s and %<second>s '\
56
+ 'for response declaration at %<current>s.'
57
+ MISPLACED_MSG = 'Schema definition for %<schema_name>s is defined at %<current>s, '\
58
+ 'but should be defined immediately after response declaration at %<other>s.'
59
+ MISPLACED_WITHOUT_RESPONSE_DEFINITION_MSG = 'Schema definition for %<schema_name>s is '\
60
+ 'outside of response declaration.'
61
+
62
+ # @!method response_block?(node)
63
+ def_node_matcher :response_block, <<~PATTERN
64
+ (block
65
+ (send nil? :response
66
+ (int _)
67
+ ...)
68
+ ...
69
+ )
70
+ PATTERN
71
+
72
+ # @!method schema_definition?(node)
73
+ def_node_matcher :schema_definition, <<~PATTERN
74
+ (send nil? :schema
75
+ (hash
76
+ ...
77
+ )
78
+ )
79
+ PATTERN
80
+
81
+ # @!method schema_name(node)
82
+ def_node_matcher :schema_name, <<~PATTERN
83
+ (send nil? :schema
84
+ (hash
85
+ (pair
86
+ (str "$ref")
87
+ (str $_)
88
+ )
89
+ )
90
+ )
91
+ PATTERN
92
+
93
+ # @!method schema_definition_by_child?(node)
94
+ def_node_matcher :schema_definition_by_child, <<~PATTERN
95
+ ({block | begin}
96
+ <
97
+ $(send nil? :schema
98
+ (hash
99
+ ...
100
+ )
101
+ )
102
+ ...
103
+ >
104
+ )
105
+ PATTERN
106
+
107
+ def on_block(node)
108
+ return check_schema_definition_count(node) if response_block(node)
109
+
110
+ return if begin_inside_response_block?(node)
111
+
112
+ check_for_misplaced_schema(node)
113
+ end
114
+ alias on_begin on_block
115
+
116
+ private
117
+
118
+ # Checks that schema is missing completely. Does not check where schema is defined exactly,
119
+ # that will be picked up by check_for_misplaced_schema
120
+ def check_schema_definition_count(node)
121
+ schema_definitions = schema_definitions(node)
122
+
123
+ return if schema_definitions.count == 1
124
+
125
+ return add_missing_offense(node) if schema_definitions.empty?
126
+
127
+ add_duplicated_offense(node, schema_definitions)
128
+ end
129
+
130
+ def add_missing_offense(node)
131
+ message = format(MISSING_MSG, current: source_location(node))
132
+ add_offense(node.loc.expression, message: message)
133
+ end
134
+
135
+ def add_duplicated_offense(node, schema_definitions)
136
+ message = format(
137
+ DUPLICATED_MSG,
138
+ current: source_location(node),
139
+ first: source_location(schema_definitions[0]),
140
+ second: source_location(schema_definitions[1])
141
+ )
142
+ add_offense(node.loc.expression, message: message)
143
+ end
144
+
145
+ def check_for_misplaced_schema(node)
146
+ schema_definition = schema_definition_by_child(node)
147
+ return unless schema_definition
148
+
149
+ correct_node = response_definition_ancestor(node)
150
+ message = message_for_misplaced(schema_definition, correct_node)
151
+ add_offense(schema_definition.loc.expression, message: message)
152
+ end
153
+
154
+ def message_for_misplaced(schema_definition, correct_node)
155
+ if correct_node
156
+ return format(MISPLACED_MSG,
157
+ schema_name: find_schema_name(schema_definition),
158
+ other: source_location(correct_node),
159
+ current: source_location(schema_definition))
160
+ end
161
+
162
+ format(MISPLACED_WITHOUT_RESPONSE_DEFINITION_MSG, schema_name: find_schema_name(schema_definition))
163
+ end
164
+
165
+ def begin_inside_response_block?(node)
166
+ node.begin_type? && response_block(node.parent)
167
+ end
168
+
169
+ def schema_definitions(node)
170
+ node.each_descendant.filter do |d|
171
+ schema_definition(d)
172
+ end
173
+ end
174
+
175
+ def response_definition_ancestor(node)
176
+ ancestor = node.parent
177
+ ancestor = ancestor.parent until ancestor.nil? || response_block(ancestor)
178
+ ancestor
179
+ end
180
+
181
+ def find_schema_name(schema_definition)
182
+ schema_name(schema_definition) || 'composite schema declaration'
183
+ end
184
+
185
+ def source_location(node)
186
+ range = node.location.expression
187
+ path = smart_path(range.source_buffer.name)
188
+ "#{path}:#{range.line}"
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -2,3 +2,4 @@
2
2
 
3
3
  require_relative 'iotventure/duplicate_response_code'
4
4
  require_relative 'iotventure/save_request_example'
5
+ require_relative 'iotventure/schema_definition_per_response'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Iotventure
5
- VERSION = '0.1.1'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-iotventure
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
  - Fynn Starke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-18 00:00:00.000000000 Z
11
+ date: 2022-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -130,6 +130,7 @@ files:
130
130
  - lib/rubocop-iotventure.rb
131
131
  - lib/rubocop/cop/iotventure/duplicate_response_code.rb
132
132
  - lib/rubocop/cop/iotventure/save_request_example.rb
133
+ - lib/rubocop/cop/iotventure/schema_definition_per_response.rb
133
134
  - lib/rubocop/cop/iotventure_cops.rb
134
135
  - lib/rubocop/iotventure.rb
135
136
  - lib/rubocop/iotventure/inject.rb
@@ -158,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
159
  - !ruby/object:Gem::Version
159
160
  version: '0'
160
161
  requirements: []
161
- rubygems_version: 3.2.32
162
+ rubygems_version: 3.3.7
162
163
  signing_key:
163
164
  specification_version: 4
164
165
  summary: Rswag cops.