rubocop-iotventure 0.2.0 → 0.3.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: 8d7b5e0864c57af9dfe62005ea09865ac27c92fcc5fcc34d4019045aa7d54946
4
- data.tar.gz: 0c4174349f69ab40a37a476e1613c8a564ce8eb2982d15f05f4de821fb6a6544
3
+ metadata.gz: beea57247dc2b420f2cdff17108b0b0b4a7f542e242b4a01d3515ae3f16d5337
4
+ data.tar.gz: 4ce49ecad2def1b3879ea73cfa6c147af01c606e0a5ffc237812e3dcc3bb394c
5
5
  SHA512:
6
- metadata.gz: bab135bc00dc0221d376696da3adc36dad336635ad85209cc4a32eab525646ecbd69e0f77f85d5c9fc5de32fec8278970ff987152ff58697b78a68dc6ad76c78
7
- data.tar.gz: 3a91e6bf9c5cb446919b89409ef921561d615466c27fd590edd3170c47915970b0bd8a3f7125d09e0968aee662a702831e87fbea6530eacbf9e88a77d0fa2e71
6
+ metadata.gz: 9d55967ddcd84b5c83e12c2e27efbc80d628c4de15cb187f9aebd954a042eff85f5260fe7967db59e4a077156395fd6ea5f6b82a81bf5167691a9225ea15257c
7
+ data.tar.gz: 543147561c54fc3bdbe7d6009773df9a65a8c951271125b6d907b7ad0a2753c0380fed021331c24d440780bf6652b89cfa653db1c018403a3d19e756650e6ae6
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- ## [Unreleased]
1
+ # Changelog
2
+
3
+ ## [0.3.0] - 2023-06-01
4
+
5
+ - BU-64 Add AdditionalProperties cop
6
+
7
+ ## [0.2.1] - 2023-04-21
8
+
9
+ - Fix SchemaDefinitionPerResponse cop for 204 No Content responses
2
10
 
3
11
  ## [0.2.0] - 2022-05-12
4
12
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-iotventure (0.2.0)
4
+ rubocop-iotventure (0.3.0)
5
5
  rubocop (~> 1.0)
6
6
  rubocop-rake (~> 0.6.0)
7
7
 
data/README.md CHANGED
@@ -12,14 +12,45 @@ gem 'rubocop-iotventure', require: false
12
12
 
13
13
  And then execute:
14
14
 
15
- $ bundle install
15
+ ```shell
16
+ bundle install
17
+ ```
16
18
 
17
- Or install it yourself as:
19
+ Or install it yourself using:
18
20
 
19
- $ gem install rubocop-iotventure
21
+ ```shell
22
+ gem install rubocop-iotventure
23
+ ```
20
24
 
21
25
  ## Usage
22
26
 
27
+ ### IotVenture/AdditionalProperties
28
+
29
+ ```ruby
30
+ # bad
31
+ {
32
+ type: :object,
33
+ properties: {
34
+ prop1: { type: :string },
35
+ prop2: { type: :string }
36
+ }
37
+ }
38
+
39
+ # good
40
+ {
41
+ type: :object,
42
+ properties: {
43
+ prop1: { type: :string },
44
+ prop2: { type: :string }
45
+ },
46
+ additionalProperties: false
47
+ }
48
+ ```
49
+
50
+ This cop checks that all object schemas have the `additionalProperties` property set to `false` or a useful matcher (not `true`). This is to prevent unexpected properties from being added to the object.
51
+
52
+ Note: This only works for schemas defined as Ruby hashes.
53
+
23
54
  ### Iotventure/DuplicateResponseCode
24
55
 
25
56
  ```ruby
@@ -69,7 +100,7 @@ response 200, 'response description' do
69
100
  end
70
101
  ```
71
102
 
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.
103
+ This cop checks that there is exactly one top-level schema definition per response block (except 204 No Content blocks, those should not have any schema definitions). Multiple or misplaced schema definitions might overwrite each other.
73
104
 
74
105
  ## Development
75
106
 
@@ -79,7 +110,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
79
110
 
80
111
  ## Contributing
81
112
 
82
- Bug reports and pull requests are welcome on Bitbucket at https://bitbucket.org/iotventure/rubocop-iotventure. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://bitbucket.org/iotventure/rubocop-iotventure/src/master/CODE_OF_CONDUCT.md).
113
+ Bug reports and pull requests are welcome on Bitbucket at <https://bitbucket.org/iotventure/rubocop-iotventure>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://bitbucket.org/iotventure/rubocop-iotventure/src/master/CODE_OF_CONDUCT.md).
83
114
 
84
115
  ## License
85
116
 
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Iotventure
6
+ # This cop checks that every array and object schema has additionalProperties (defined or set to false).
7
+ # Note: This only works for schemas defined as Ruby hashes.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ #
13
+ # {
14
+ # type: :object,
15
+ # properties: {
16
+ # foo: { type: :string },
17
+ # bar: { type: :boolean }
18
+ # }
19
+ # }
20
+ #
21
+ # @example
22
+ #
23
+ # # bad
24
+ #
25
+ # {
26
+ # type: :object,
27
+ # properties: {
28
+ # foo: { type: :string },
29
+ # bar: { type: :boolean }
30
+ # },
31
+ # additionalProperties: true
32
+ # }
33
+ #
34
+ #
35
+ # @example
36
+ #
37
+ # # good
38
+ #
39
+ # {
40
+ # type: :object,
41
+ # properties: {
42
+ # foo: { type: :string },
43
+ # bar: { type: :boolean }
44
+ # },
45
+ # additionalProperties: false
46
+ # }
47
+ #
48
+ #
49
+ #
50
+ class AdditionalProperties < Base
51
+ MISSING_MSG = 'Schema is missing additionalProperties. ' \
52
+ 'Please add it to the schema at %<current>s'
53
+ ALWAYS_TRUE_MSG = 'Schema has additionalProperties set to true. ' \
54
+ 'Please set it to false or define a rule at %<current>s'
55
+
56
+ # @!method schema_definition_with_properties?(node)
57
+ def_node_matcher :schema_object_definition_with_properties?, <<~PATTERN
58
+ (hash<
59
+ (pair
60
+ (sym :type)
61
+ {(sym :object) (str "object")}
62
+ )
63
+ (pair
64
+ <{(sym :properties) (sym :patternProperties)}>
65
+ ...
66
+ )
67
+ ...
68
+ >)
69
+ PATTERN
70
+
71
+ # @!method always_true_schema?(node)
72
+ def_node_matcher :always_true_schema?, <<~PATTERN
73
+ {
74
+ (true)
75
+ (hash) # Empty hash is also always true in JSON Schema
76
+ }
77
+ PATTERN
78
+
79
+ def on_hash(node)
80
+ return unless schema_object_definition_with_properties?(node)
81
+
82
+ additional_properties = node.pairs.find { |pair| pair.key.value == :additionalProperties }
83
+ return add_missing_offense(node) unless additional_properties
84
+
85
+ add_always_true_offense(node) if always_true_schema?(additional_properties.value)
86
+ end
87
+
88
+ private
89
+
90
+ def add_missing_offense(node)
91
+ add_offense(node, message: format(MISSING_MSG, current: source_location(node)))
92
+ end
93
+
94
+ def add_always_true_offense(node)
95
+ add_offense(node, message: format(ALWAYS_TRUE_MSG, current: source_location(node)))
96
+ end
97
+
98
+ def source_location(node)
99
+ range = node.location.expression
100
+ path = smart_path(range.source_buffer.name)
101
+ "#{path}:#{range.line}"
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -43,6 +43,15 @@ module RuboCop
43
43
  #
44
44
  # @example
45
45
  #
46
+ # # bad
47
+ #
48
+ # response 204, 'response description' do
49
+ # schema '$ref' => '#/components/schemas/object'
50
+ # end
51
+ #
52
+ #
53
+ # @example
54
+ #
46
55
  # # good
47
56
  #
48
57
  # response 200, 'response description' do
@@ -50,6 +59,14 @@ module RuboCop
50
59
  # end
51
60
  #
52
61
  #
62
+ # @example
63
+ #
64
+ # # good
65
+ #
66
+ # response 204, 'response description' do
67
+ # end
68
+ #
69
+ #
53
70
  class SchemaDefinitionPerResponse < Base
54
71
  MISSING_MSG = 'Schema definition is missing for response declaration at %<current>s.'
55
72
  DUPLICATED_MSG = 'Schema definition is defined both at %<first>s and %<second>s '\
@@ -58,6 +75,8 @@ module RuboCop
58
75
  'but should be defined immediately after response declaration at %<other>s.'
59
76
  MISPLACED_WITHOUT_RESPONSE_DEFINITION_MSG = 'Schema definition for %<schema_name>s is '\
60
77
  'outside of response declaration.'
78
+ NO_CONTENT_SCHEMA_MSG = 'Schema definition for %<schema_name>s is defined at %<current>s, '\
79
+ 'but 204 response should not have schema.'
61
80
 
62
81
  # @!method response_block?(node)
63
82
  def_node_matcher :response_block, <<~PATTERN
@@ -69,6 +88,18 @@ module RuboCop
69
88
  )
70
89
  PATTERN
71
90
 
91
+ # @!method no_content_response(node)
92
+ def_node_matcher :no_content_response, <<~PATTERN
93
+ (block
94
+ (send nil? :response
95
+ (:int 204)
96
+ (:str _)
97
+ ...
98
+ )
99
+ ...
100
+ )
101
+ PATTERN
102
+
72
103
  # @!method schema_definition?(node)
73
104
  def_node_matcher :schema_definition, <<~PATTERN
74
105
  (send nil? :schema
@@ -119,6 +150,7 @@ module RuboCop
119
150
  # that will be picked up by check_for_misplaced_schema
120
151
  def check_schema_definition_count(node)
121
152
  schema_definitions = schema_definitions(node)
153
+ return check_no_schemas(schema_definitions) if no_content_response(node)
122
154
 
123
155
  return if schema_definitions.count == 1
124
156
 
@@ -127,6 +159,14 @@ module RuboCop
127
159
  add_duplicated_offense(node, schema_definitions)
128
160
  end
129
161
 
162
+ def check_no_schemas(schema_definitions)
163
+ schema_definitions.each do |schema_definition|
164
+ message = format(NO_CONTENT_SCHEMA_MSG, schema_name: find_schema_name(schema_definition),
165
+ current: source_location(schema_definition))
166
+ add_offense(schema_definition.loc.expression, message: message)
167
+ end
168
+ end
169
+
130
170
  def add_missing_offense(node)
131
171
  message = format(MISSING_MSG, current: source_location(node))
132
172
  add_offense(node.loc.expression, message: message)
@@ -3,3 +3,4 @@
3
3
  require_relative 'iotventure/duplicate_response_code'
4
4
  require_relative 'iotventure/save_request_example'
5
5
  require_relative 'iotventure/schema_definition_per_response'
6
+ require_relative 'iotventure/additional_properties'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Iotventure
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.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.2.0
4
+ version: 0.3.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-05-12 00:00:00.000000000 Z
11
+ date: 2023-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -128,6 +128,7 @@ files:
128
128
  - bin/setup
129
129
  - config/default.yml
130
130
  - lib/rubocop-iotventure.rb
131
+ - lib/rubocop/cop/iotventure/additional_properties.rb
131
132
  - lib/rubocop/cop/iotventure/duplicate_response_code.rb
132
133
  - lib/rubocop/cop/iotventure/save_request_example.rb
133
134
  - lib/rubocop/cop/iotventure/schema_definition_per_response.rb
@@ -159,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
160
  - !ruby/object:Gem::Version
160
161
  version: '0'
161
162
  requirements: []
162
- rubygems_version: 3.3.7
163
+ rubygems_version: 3.2.3
163
164
  signing_key:
164
165
  specification_version: 4
165
166
  summary: Rswag cops.