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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +2 -2
- data/README.md +26 -5
- data/lib/rubocop/cop/iotventure/schema_definition_per_response.rb +193 -0
- data/lib/rubocop/cop/iotventure_cops.rb +1 -0
- data/lib/rubocop/iotventure/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d7b5e0864c57af9dfe62005ea09865ac27c92fcc5fcc34d4019045aa7d54946
|
4
|
+
data.tar.gz: 0c4174349f69ab40a37a476e1613c8a564ce8eb2982d15f05f4de821fb6a6544
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bab135bc00dc0221d376696da3adc36dad336635ad85209cc4a32eab525646ecbd69e0f77f85d5c9fc5de32fec8278970ff987152ff58697b78a68dc6ad76c78
|
7
|
+
data.tar.gz: 3a91e6bf9c5cb446919b89409ef921561d615466c27fd590edd3170c47915970b0bd8a3f7125d09e0968aee662a702831e87fbea6530eacbf9e88a77d0fa2e71
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Rubocop::Iotventure
|
2
2
|
|
3
|
-
|
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
|
-
###
|
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
|
-
###
|
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
|
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.
|
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-
|
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.
|
162
|
+
rubygems_version: 3.3.7
|
162
163
|
signing_key:
|
163
164
|
specification_version: 4
|
164
165
|
summary: Rswag cops.
|