hcl-checker 1.4.0 → 1.6.1

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: 195128a0325ac3b7fa3add01a739dbe3ce0aeb5b3314edfc74d195caa3a0aa61
4
- data.tar.gz: ab84f84386083bdbb9aaea917716ea7e8462eaed2b89a2ab4f887fb4c3b2ee93
3
+ metadata.gz: e385b2693e62154b496432fb0baf5022d64fdc0827b5703d33be6a05dbfb50c6
4
+ data.tar.gz: 931d2e6fe0348c24164bfc17d6686ebd6b64ac41e2acb9884af1d51c189764c1
5
5
  SHA512:
6
- metadata.gz: b53587ad90fa9ed3cf6c2fbfd5cad15f6b526e62e5c63298fbd963a1629d6283a0bac0ab7276674acba8a1d67e38bc2118fe8f9a0a11a5d362afef4957cc745a
7
- data.tar.gz: 4d908d23f548138a2e4e876709cda19321650203d13219f8ac8fe3748cd1427e628f9cb834f80bf684252a7d06d9a97d72663f3ac6c19699a0149593e3450a0d
6
+ metadata.gz: c23f7d1562b29c3523de8be84d57a7690ff5c1f7680a368df049b7c21dd4b3246f2417a79df09f797ad00bd2743ec218effe67ffd020132174a79c5dd2ccaf4a
7
+ data.tar.gz: 8874919303dad9cbb0285fa69a042ddb4a444df7c71d76c41d8cb39639e333fddcdec13768cedb4fffcde4fdabcc3f9c70e805b89c5744cf643b0e267dd7b449
data/.rubocop.yml ADDED
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ Exclude:
4
+ - lib/hcl/lexer.rb
5
+ - lib/hcl/parser.rb
6
+
7
+ Layout/LineLength:
8
+ Enabled: false
9
+
10
+ Metrics/AbcSize:
11
+ Enabled: false
12
+
13
+ Metrics/BlockLength:
14
+ Enabled: false
15
+
16
+ Metrics/ClassLength:
17
+ Enabled: false
18
+
19
+ Metrics/CyclomaticComplexity:
20
+ Enabled: false
21
+
22
+ Metrics/MethodLength:
23
+ Enabled: false
24
+
25
+ Metrics/PerceivedComplexity:
26
+ Enabled: false
27
+
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ Style/FrozenStringLiteralComment:
32
+ EnforcedStyle: never
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # This is needed due https://nvd.nist.gov/vuln/detail/CVE-2018-14404
4
4
  # A NULL pointer dereference vulnerability exists in the xpath.c:xmlXPathCompOpEval()
@@ -7,10 +7,9 @@ source "https://rubygems.org"
7
7
  # with the use of the libxml2 library may be vulnerable to a denial of service attack due
8
8
  # to a crash of the application.
9
9
  # Nokogiri >= 1.8.5 solves this problem
10
- gem "nokogiri", ">= 1.10.8"
10
+ gem 'nokogiri', '>= 1.11.4'
11
11
 
12
-
13
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
12
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
14
13
 
15
14
  # Specify your gem's dependencies in hcl-checker.gemspec
16
15
  gemspec
data/Gemfile.lock CHANGED
@@ -1,20 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hcl-checker (1.4.0)
4
+ hcl-checker (1.6.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- diff-lcs (1.4.4)
9
+ diff-lcs (1.5.0)
10
10
  filesize (0.2.0)
11
11
  jsobfu (0.4.2)
12
12
  rkelly-remix
13
- json (2.3.1)
14
- metasm (1.0.4)
15
- mini_portile2 (2.4.0)
16
- nokogiri (1.10.10)
17
- mini_portile2 (~> 2.4.0)
13
+ json (2.6.1)
14
+ metasm (1.0.5)
15
+ nokogiri (1.13.6-arm64-darwin)
16
+ racc (~> 1.4)
18
17
  racc (1.5.0)
19
18
  rake (12.3.3)
20
19
  rb-readline (0.5.5)
@@ -27,27 +26,27 @@ GEM
27
26
  rb-readline (~> 0)
28
27
  rexical (1.0.7)
29
28
  rkelly-remix (0.0.7)
30
- rspec (3.9.0)
31
- rspec-core (~> 3.9.0)
32
- rspec-expectations (~> 3.9.0)
33
- rspec-mocks (~> 3.9.0)
34
- rspec-core (3.9.2)
35
- rspec-support (~> 3.9.3)
36
- rspec-expectations (3.9.2)
29
+ rspec (3.11.0)
30
+ rspec-core (~> 3.11.0)
31
+ rspec-expectations (~> 3.11.0)
32
+ rspec-mocks (~> 3.11.0)
33
+ rspec-core (3.11.0)
34
+ rspec-support (~> 3.11.0)
35
+ rspec-expectations (3.11.0)
37
36
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.9.0)
39
- rspec-mocks (3.9.1)
37
+ rspec-support (~> 3.11.0)
38
+ rspec-mocks (3.11.1)
40
39
  diff-lcs (>= 1.2.0, < 2.0)
41
- rspec-support (~> 3.9.0)
42
- rspec-support (3.9.3)
40
+ rspec-support (~> 3.11.0)
41
+ rspec-support (3.11.0)
43
42
 
44
43
  PLATFORMS
45
- ruby
44
+ arm64-darwin-21
46
45
 
47
46
  DEPENDENCIES
48
- bundler (~> 2.1.4)
47
+ bundler (~> 2.3.13)
49
48
  hcl-checker!
50
- nokogiri (>= 1.10.8)
49
+ nokogiri (>= 1.11.4)
51
50
  racc (= 1.5.0)
52
51
  rake (~> 12.3.3)
53
52
  rex (= 2.0.12)
@@ -55,4 +54,4 @@ DEPENDENCIES
55
54
  rspec (~> 3.0)
56
55
 
57
56
  BUNDLED WITH
58
- 2.1.4
57
+ 2.3.13
data/README.md CHANGED
@@ -47,21 +47,21 @@ You can validate the `hcl_string` contents with `valid?` method. This will
47
47
  return `true` if is a valid HCL or `false` if not.
48
48
 
49
49
  ```
50
- 2.3.2 :014 > HCL1::Checker.valid? hcl_string
50
+ 2.3.2 :014 > HCL::Checker.valid? hcl_string
51
51
  => true
52
52
  ```
53
53
 
54
54
  You can parse the `hcl_string` into a `Hash` with `parse` method.
55
55
 
56
56
  ```
57
- 2.3.2 :015 > HCL1::Checker.parse(hcl_string)
57
+ 2.3.2 :015 > HCL::Checker.parse(hcl_string)
58
58
  => {"provider"=>{"aws"=>{"region"=>"${var.aws_region}", "access_key"=>"${var.aws_access_key}", "secret_key"=>"${var.aws_secret_key}"}}, "resource"=>{"aws_vpc"=>{"default"=>{"cidr_block"=>"10.0.0.0/16", "enable_dns_hostnames"=>true, "tags"=>{"Name"=>"Event Store VPC"}}}}}
59
59
  ```
60
60
 
61
61
  If after a `parse` you got `false` you can check `last_error` with:
62
62
 
63
63
  ```
64
- 2.4.2 :063 > HCL1::Checker.last_error
64
+ 2.4.2 :063 > HCL::Checker.last_error
65
65
  => "Parse error at \"eec8b16c-ee89-4ea0-bdcc-d094300a42e8\" , (invalid token: ,)"
66
66
  ```
67
67
 
data/Rakefile CHANGED
@@ -1,19 +1,18 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new do |c|
5
- options = ["--color"]
6
- options += ["--format", "documentation"]
5
+ options = ['--color']
6
+ options += ['--format', 'documentation']
7
7
  c.rspec_opts = options
8
8
  end
9
9
 
10
- desc "Generate Grammar files for HCL"
10
+ desc 'Generate Grammar files for HCL'
11
11
  task :build_grammar do
12
12
  print 'Building Lexer'
13
- `rex ./assets/lexer.rex -o ./lib/hcl/lexer.rb`
13
+ `rex ./assets/lexer.rex -o ./lib/hcl/checker/lexer.rb`
14
14
  print "....done\n"
15
15
  print 'Building Parser'
16
- `racc ./assets/parse.y -o ./lib/hcl/parser.rb`
16
+ `racc ./assets/parse.y -o ./lib/hcl/checker/parser.rb`
17
17
  print "....done\n\n"
18
18
  end
19
-
data/assets/lexer.rex CHANGED
@@ -1,8 +1,7 @@
1
-
2
- class HCLLexer
1
+ class HCL::Checker::Lexer
3
2
  option
4
3
  independent
5
-
4
+
6
5
  macro
7
6
  NEWLINE \n|\r
8
7
  BLANK \s+
@@ -20,6 +19,8 @@ macro
20
19
  RIGHTBRACE \}
21
20
  LEFTBRACKET \[
22
21
  RIGHTBRACKET \]
22
+ LEFTPARENTHESES \(
23
+ RIGHTPARENTHESES \)
23
24
  HEREDOCUMENT \<<\-?
24
25
 
25
26
  rule
@@ -36,37 +37,39 @@ rule
36
37
  {QUOTE} { [:STRING, consume_string(text)] }
37
38
  {HEREDOCUMENT} { [:STRING, consume_heredoc] }
38
39
  #-------------------------------------------------------------------------------
39
- {LEFTBRACE} { [:LEFTBRACE, text]}
40
- {RIGHTBRACE} { [:RIGHTBRACE, text]}
41
- {LEFTBRACKET} { [:LEFTBRACKET, text]}
42
- {RIGHTBRACKET} { [:RIGHTBRACKET, text]}
40
+ {LEFTBRACE} { [:LEFTBRACE, text]}
41
+ {RIGHTBRACE} { [:RIGHTBRACE, text]}
42
+ {LEFTBRACKET} { [:LEFTBRACKET, text]}
43
+ {RIGHTBRACKET} { [:RIGHTBRACKET, text]}
44
+ {LEFTPARENTHESES} { [:LEFTPARENTHESES, text]}
45
+ {RIGHTPARENTHESES} { [:RIGHTPARENTHESES, text]}
43
46
  #-------------------------------------------------------------------------------
44
47
  {COMMA} { [:COMMA, text]}
45
48
  {IDENTIFIER} { [:IDENTIFIER, text]}
46
49
  {EQUAL} { [:EQUAL, text]}
47
50
  {MINUS} { [:MINUS, text]}
48
51
 
49
-
50
52
  inner
51
-
52
53
  def lex(input)
53
54
  scan_setup(input)
54
55
  tokens = []
55
56
  while token = next_token
56
57
  tokens << token
57
58
  end
59
+
58
60
  tokens
59
61
  end
60
62
 
61
63
 
62
64
  def to_boolean(input)
63
- input =
64
- if input =~ /true/
65
- true
66
- elsif input =~ /false/
67
- false
68
- end
69
- return input
65
+ case input
66
+ when /true/
67
+ true
68
+ when /false/
69
+ false
70
+ else
71
+ raise "Invalid value for `to_boolean`, expected true/false got #{input}"
72
+ end
70
73
  end
71
74
 
72
75
 
@@ -90,19 +93,21 @@ inner
90
93
  result = ''
91
94
  nested = 0
92
95
 
93
- begin
96
+ loop do
94
97
  case(text = @ss.scan_until(%r{\"|\$\{|\}|\\}))
95
98
  when %r{\$\{\z}
96
99
  nested += 1
97
100
  when %r{\}\z}
98
- nested -= 1 if nested > 0
101
+ nested -= 1 if nested.positive?
99
102
  when %r{\\\z}
100
103
  result += text.chop + @ss.getch
101
104
  next
102
105
  end
103
106
 
104
107
  result += text.to_s
105
- end until nested == 0 && text =~ %r{\"\z}
108
+
109
+ break if nested.zero? && text =~ %r{\"\z}
110
+ end
106
111
 
107
112
  result.chop
108
113
  end
data/assets/parse.y CHANGED
@@ -1,4 +1,4 @@
1
- class HCLParser
1
+ class HCL::Checker::Parser
2
2
  token BOOL
3
3
  FLOAT
4
4
  NUMBER
@@ -12,6 +12,8 @@ token BOOL
12
12
  RIGHTBRACE
13
13
  LEFTBRACKET
14
14
  RIGHTBRACKET
15
+ LEFTPARENTHESES
16
+ RIGHTPARENTHESES
15
17
  PERIOD
16
18
  EPLUS
17
19
  EMINUS
@@ -24,7 +26,6 @@ rule
24
26
  | objectlist
25
27
  ;
26
28
 
27
-
28
29
  objectlist:
29
30
  objectitem COMMA
30
31
  { result = [val[0]] }
@@ -40,7 +41,7 @@ rule
40
41
  LEFTBRACE objectlist RIGHTBRACE
41
42
  { result = flatten_objectlist(val[1]) }
42
43
  | LEFTBRACE RIGHTBRACE
43
- { return }
44
+ { return {} }
44
45
  ;
45
46
 
46
47
  objectkey:
@@ -61,6 +62,10 @@ rule
61
62
  { result = val[0], val[2] }
62
63
  | objectkey EQUAL list
63
64
  { result = val[0], val[2] }
65
+ | objectkey EQUAL IDENTIFIER LEFTPARENTHESES IDENTIFIER RIGHTPARENTHESES
66
+ { result = val[0], "#{val[2]}(#{val[4]})" }
67
+ | objectkey EQUAL IDENTIFIER
68
+ { result = val[0], val[2] }
64
69
  | block
65
70
  { result = val[0] }
66
71
  ;
@@ -83,7 +88,7 @@ rule
83
88
  LEFTBRACKET listitems RIGHTBRACKET
84
89
  { result = val[1] }
85
90
  | LEFTBRACKET RIGHTBRACKET
86
- { return }
91
+ { return [] }
87
92
  ;
88
93
 
89
94
  listitems:
@@ -117,7 +122,7 @@ rule
117
122
  end
118
123
 
119
124
  ---- header
120
- require_relative './lexer'
125
+ require_relative 'lexer'
121
126
 
122
127
  ---- inner
123
128
  #//
@@ -125,19 +130,31 @@ require_relative './lexer'
125
130
  #// keys are encountered.
126
131
  #//
127
132
  #// from decoder.go: if we're at the root or we're directly within
128
- #// a list, decode to hashes, otherwise lists
133
+ #// a list, decode to hashes, otherwise lists
129
134
  #//
130
135
  #// from object.go: there is a flattened list structure
131
136
  #//
137
+ #// if @duplicate_mode is set:
138
+ #// - :array then duplicates will be appended to an array
139
+ #// - :merge then duplicates will be deep merged into a hash
140
+ #//
132
141
  def flatten_objectlist(list)
133
142
  (list || {}).each_with_object({}) do |a, h|
134
- h[a.first] =
135
- case a.last
136
- when Hash
143
+ if h.keys.include?(a.first)
144
+ case @duplicate_mode
145
+ when :array
146
+ if h[a.first].is_a?(Array)
147
+ h[a.first].push(a.last)
148
+ else
149
+ h[a.first] = [ h[a.first], a.last ]
150
+ end
151
+ when :merge
137
152
  deep_merge(h[a.first] || {}, a.last)
138
- else
139
- h[a.first] = a.last
153
+ else raise ArgumentError
140
154
  end
155
+ else
156
+ h[a.first] = a.last
157
+ end
141
158
  end
142
159
  end
143
160
 
@@ -149,10 +166,12 @@ require_relative './lexer'
149
166
  end
150
167
 
151
168
 
152
- def parse(input)
153
- @lexer = HCLLexer.new.lex(input)
169
+ def parse(input, duplicate_mode = :array)
170
+ @duplicate_mode = duplicate_mode
171
+ @lexer = HCL::Checker::Lexer.new.lex(input)
154
172
  do_parse
155
- return @result
173
+
174
+ @result
156
175
  end
157
176
 
158
177
 
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "hcl/checker"
3
+ require 'bundler/setup'
4
+ require 'hcl/checker'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "hcl/checker"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
data/hcl-checker.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'hcl/checker/version'
4
4
 
@@ -17,36 +17,20 @@ Gem::Specification.new do |spec|
17
17
  f.match(%r{^(test|spec|features)/})
18
18
  end
19
19
  spec.require_paths = ['lib']
20
+ spec.required_ruby_version = '>= 2.5.0'
20
21
 
21
- spec.add_development_dependency 'bundler', '~> 2.1.4'
22
- spec.add_development_dependency 'rake', '~> 12.3.3'
23
- spec.add_development_dependency 'rspec', '~> 3.0'
22
+ spec.add_development_dependency 'bundler', '~> 2.3.13'
24
23
  spec.add_development_dependency 'racc', '1.5.0'
24
+ spec.add_development_dependency 'rake', '~> 12.3.3'
25
25
  spec.add_development_dependency 'rex', '2.0.12'
26
26
  spec.add_development_dependency 'rexical', '>= 1.0.7'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
27
28
 
28
- spec.post_install_message = %q{
29
- Hello, I am updating this Gem to support version 2.0 of the HCL.
30
-
31
- In the meantime, it is important that you know that there will be a
32
- compatibility break with the current version, for Gem to support both
33
- versions.
34
-
35
- Therefore, instead of using just HCL::Checker you must tell which
36
- version you are using, like this:
37
-
38
- HCL1::Checker
39
-
40
- Or
41
-
42
- HCL2::Checker
43
-
44
- At the moment both HCL::Checker and HCL1::Checker will work, but with
45
- the release of support for version 2 the HCL::Checker syntax will no
46
- longer work.
29
+ spec.post_install_message = '
30
+ Hello, me again. This version fixes:
47
31
 
48
- So, update your code.
32
+ - Update dependencies due security issues
49
33
 
50
34
  Thank you :)
51
- }
35
+ '
52
36
  end
@@ -4,8 +4,7 @@
4
4
  # from lexical definition file "./assets/lexer.rex".
5
5
  #++
6
6
 
7
-
8
- class HCLLexer
7
+ class HCL::Checker::Lexer
9
8
  require 'strscan'
10
9
 
11
10
  class ScanError < StandardError ; end
@@ -85,16 +84,22 @@ class HCLLexer
85
84
  action { [:STRING, consume_heredoc] }
86
85
 
87
86
  when (text = @ss.scan(/\{/))
88
- action { [:LEFTBRACE, text]}
87
+ action { [:LEFTBRACE, text]}
89
88
 
90
89
  when (text = @ss.scan(/\}/))
91
- action { [:RIGHTBRACE, text]}
90
+ action { [:RIGHTBRACE, text]}
92
91
 
93
92
  when (text = @ss.scan(/\[/))
94
- action { [:LEFTBRACKET, text]}
93
+ action { [:LEFTBRACKET, text]}
95
94
 
96
95
  when (text = @ss.scan(/\]/))
97
- action { [:RIGHTBRACKET, text]}
96
+ action { [:RIGHTBRACKET, text]}
97
+
98
+ when (text = @ss.scan(/\(/))
99
+ action { [:LEFTPARENTHESES, text]}
100
+
101
+ when (text = @ss.scan(/\)/))
102
+ action { [:RIGHTPARENTHESES, text]}
98
103
 
99
104
  when (text = @ss.scan(/\,/))
100
105
  action { [:COMMA, text]}
@@ -129,13 +134,14 @@ class HCLLexer
129
134
  tokens
130
135
  end
131
136
  def to_boolean(input)
132
- input =
133
- if input =~ /true/
134
- true
135
- elsif input =~ /false/
136
- false
137
- end
138
- return input
137
+ case input
138
+ when /true/
139
+ true
140
+ when /false/
141
+ false
142
+ else
143
+ raise "Invalid value for `to_boolean`, expected true/false got #{input}"
144
+ end
139
145
  end
140
146
  def consume_comment(input)
141
147
  nested = 1
@@ -153,18 +159,19 @@ class HCLLexer
153
159
  def consume_string(input)
154
160
  result = ''
155
161
  nested = 0
156
- begin
162
+ loop do
157
163
  case(text = @ss.scan_until(%r{\"|\$\{|\}|\\}))
158
164
  when %r{\$\{\z}
159
165
  nested += 1
160
166
  when %r{\}\z}
161
- nested -= 1 if nested > 0
167
+ nested -= 1 if nested.positive?
162
168
  when %r{\\\z}
163
169
  result += text.chop + @ss.getch
164
170
  next
165
171
  end
166
172
  result += text.to_s
167
- end until nested == 0 && text =~ %r{\"\z}
173
+ break if nested.zero? && text =~ %r{\"\z}
174
+ end
168
175
  result.chop
169
176
  end
170
177
  def consume_heredoc