hcl-checker 1.1.1 → 1.6.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 +32 -0
- data/Gemfile +3 -4
- data/Gemfile.lock +29 -28
- data/README.md +3 -5
- data/Rakefile +7 -8
- data/assets/lexer.rex +25 -20
- data/assets/parse.y +39 -16
- data/bin/console +3 -3
- data/hcl-checker.gemspec +18 -7
- data/lib/hcl/checker.rb +27 -14
- data/lib/hcl/checker/lexer.rb +182 -0
- data/lib/hcl/checker/parser.rb +496 -0
- data/lib/hcl/checker/version.rb +1 -1
- metadata +37 -34
- data/lib/hcl/lexer.rb +0 -174
- data/lib/hcl/parser.rb +0 -438
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db4fad85fc6cac710e6cf24082498ce2454f89f19204afc977413913a0e58699
|
4
|
+
data.tar.gz: 8d6be4dd1a00565006886e0dadbee8d2737de8d2b0819eed26d76d0573dbddb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 878423137f46f8043861744bbb8ff9026f5472caa0d8f9cfa0eb532f612f82bad0451b5c154b0aec19a98fdd9b568860a578d36903ef55fee9f3efbeec03e6a6
|
7
|
+
data.tar.gz: 63ebcea583cc378a141a41435ab0c32b0a9ee88a21fbbac197b7f0756fd8c46461f55987730fc591e0cfee124b85cb6558be5281e41e1ea52f32ad421f8842f8
|
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
|
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
|
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,22 +1,23 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hcl-checker (1.
|
4
|
+
hcl-checker (1.6.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
10
|
-
filesize (0.
|
9
|
+
diff-lcs (1.4.4)
|
10
|
+
filesize (0.2.0)
|
11
11
|
jsobfu (0.4.2)
|
12
12
|
rkelly-remix
|
13
|
-
json (2.
|
14
|
-
metasm (1.0.
|
15
|
-
mini_portile2 (2.
|
16
|
-
nokogiri (1.
|
17
|
-
mini_portile2 (~> 2.
|
18
|
-
|
19
|
-
|
13
|
+
json (2.3.1)
|
14
|
+
metasm (1.0.4)
|
15
|
+
mini_portile2 (2.5.3)
|
16
|
+
nokogiri (1.11.7)
|
17
|
+
mini_portile2 (~> 2.5.0)
|
18
|
+
racc (~> 1.4)
|
19
|
+
racc (1.5.0)
|
20
|
+
rake (12.3.3)
|
20
21
|
rb-readline (0.5.5)
|
21
22
|
rex (2.0.12)
|
22
23
|
filesize (~> 0)
|
@@ -25,34 +26,34 @@ GEM
|
|
25
26
|
metasm (~> 1)
|
26
27
|
nokogiri (~> 1)
|
27
28
|
rb-readline (~> 0)
|
28
|
-
rexical (1.0.
|
29
|
+
rexical (1.0.7)
|
29
30
|
rkelly-remix (0.0.7)
|
30
|
-
rspec (3.
|
31
|
-
rspec-core (~> 3.
|
32
|
-
rspec-expectations (~> 3.
|
33
|
-
rspec-mocks (~> 3.
|
34
|
-
rspec-core (3.
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-expectations (3.
|
31
|
+
rspec (3.9.0)
|
32
|
+
rspec-core (~> 3.9.0)
|
33
|
+
rspec-expectations (~> 3.9.0)
|
34
|
+
rspec-mocks (~> 3.9.0)
|
35
|
+
rspec-core (3.9.2)
|
36
|
+
rspec-support (~> 3.9.3)
|
37
|
+
rspec-expectations (3.9.2)
|
37
38
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-mocks (3.
|
39
|
+
rspec-support (~> 3.9.0)
|
40
|
+
rspec-mocks (3.9.1)
|
40
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
-
rspec-support (~> 3.
|
42
|
-
rspec-support (3.
|
42
|
+
rspec-support (~> 3.9.0)
|
43
|
+
rspec-support (3.9.3)
|
43
44
|
|
44
45
|
PLATFORMS
|
45
46
|
ruby
|
46
47
|
|
47
48
|
DEPENDENCIES
|
48
|
-
bundler (~>
|
49
|
+
bundler (~> 2.2.10)
|
49
50
|
hcl-checker!
|
50
|
-
nokogiri (>= 1.
|
51
|
-
racc (= 1.
|
52
|
-
rake (~>
|
51
|
+
nokogiri (>= 1.11.4)
|
52
|
+
racc (= 1.5.0)
|
53
|
+
rake (~> 12.3.3)
|
53
54
|
rex (= 2.0.12)
|
54
|
-
rexical (
|
55
|
+
rexical (>= 1.0.7)
|
55
56
|
rspec (~> 3.0)
|
56
57
|
|
57
58
|
BUNDLED WITH
|
58
|
-
|
59
|
+
2.2.20
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Hcl::Checker
|
2
2
|
|
3
|
-
**Hashicorp Configuration Language** syntax checker and parser.
|
3
|
+
**Hashicorp Configuration Language** syntax checker and parser.
|
4
4
|
|
5
5
|
Parser originally created by [Sikula](https://github.com/sikula) and available
|
6
6
|
at [Ruby HCL Repository](https://github.com/sikula/ruby-hcl). Only works with
|
7
|
-
[HCL Version 1](https://github.com/hashicorp/hcl).
|
7
|
+
[HCL Version 1](https://github.com/hashicorp/hcl).
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -84,7 +84,7 @@ $ bundle exec rake build_grammar
|
|
84
84
|
Building Lexer....done
|
85
85
|
Building Parser....done
|
86
86
|
```
|
87
|
-
|
87
|
+
|
88
88
|
## Contributing
|
89
89
|
|
90
90
|
Bug reports and pull requests are welcome on GitHub at
|
@@ -96,5 +96,3 @@ to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
96
96
|
|
97
97
|
The gem is available as open source under the terms of the [MIT
|
98
98
|
License](https://opensource.org/licenses/MIT).
|
99
|
-
|
100
|
-
|
data/Rakefile
CHANGED
@@ -1,19 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new do |c|
|
5
|
-
options = [
|
6
|
-
options += [
|
5
|
+
options = ['--color']
|
6
|
+
options += ['--format', 'documentation']
|
7
7
|
c.rspec_opts = options
|
8
8
|
end
|
9
9
|
|
10
|
-
desc
|
10
|
+
desc 'Generate Grammar files for HCL'
|
11
11
|
task :build_grammar do
|
12
12
|
print 'Building Lexer'
|
13
|
-
`rex
|
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,7 +19,9 @@ macro
|
|
20
19
|
RIGHTBRACE \}
|
21
20
|
LEFTBRACKET \[
|
22
21
|
RIGHTBRACKET \]
|
23
|
-
|
22
|
+
LEFTPARENTHESES \(
|
23
|
+
RIGHTPARENTHESES \)
|
24
|
+
HEREDOCUMENT \<<\-?
|
24
25
|
|
25
26
|
rule
|
26
27
|
# [:state] pattern [actions]
|
@@ -36,37 +37,39 @@ rule
|
|
36
37
|
{QUOTE} { [:STRING, consume_string(text)] }
|
37
38
|
{HEREDOCUMENT} { [:STRING, consume_heredoc] }
|
38
39
|
#-------------------------------------------------------------------------------
|
39
|
-
{LEFTBRACE} { [:LEFTBRACE,
|
40
|
-
{RIGHTBRACE} { [:RIGHTBRACE,
|
41
|
-
{LEFTBRACKET} { [:LEFTBRACKET,
|
42
|
-
{RIGHTBRACKET} { [:RIGHTBRACKET,
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
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,10 +26,13 @@ rule
|
|
24
26
|
| objectlist
|
25
27
|
;
|
26
28
|
|
27
|
-
|
28
29
|
objectlist:
|
29
|
-
objectitem
|
30
|
+
objectitem COMMA
|
31
|
+
{ result = [val[0]] }
|
32
|
+
| objectitem
|
30
33
|
{ result = [val[0]] }
|
34
|
+
| objectlist objectitem COMMA
|
35
|
+
{ result = val[0] << val[1] }
|
31
36
|
| objectlist objectitem
|
32
37
|
{ result = val[0] << val[1] }
|
33
38
|
;
|
@@ -36,7 +41,7 @@ rule
|
|
36
41
|
LEFTBRACE objectlist RIGHTBRACE
|
37
42
|
{ result = flatten_objectlist(val[1]) }
|
38
43
|
| LEFTBRACE RIGHTBRACE
|
39
|
-
{ return }
|
44
|
+
{ return {} }
|
40
45
|
;
|
41
46
|
|
42
47
|
objectkey:
|
@@ -57,6 +62,10 @@ rule
|
|
57
62
|
{ result = val[0], val[2] }
|
58
63
|
| objectkey EQUAL list
|
59
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] }
|
60
69
|
| block
|
61
70
|
{ result = val[0] }
|
62
71
|
;
|
@@ -79,7 +88,7 @@ rule
|
|
79
88
|
LEFTBRACKET listitems RIGHTBRACKET
|
80
89
|
{ result = val[1] }
|
81
90
|
| LEFTBRACKET RIGHTBRACKET
|
82
|
-
{ return }
|
91
|
+
{ return [] }
|
83
92
|
;
|
84
93
|
|
85
94
|
listitems:
|
@@ -113,7 +122,7 @@ rule
|
|
113
122
|
end
|
114
123
|
|
115
124
|
---- header
|
116
|
-
require_relative '
|
125
|
+
require_relative 'lexer'
|
117
126
|
|
118
127
|
---- inner
|
119
128
|
#//
|
@@ -121,19 +130,31 @@ require_relative './lexer'
|
|
121
130
|
#// keys are encountered.
|
122
131
|
#//
|
123
132
|
#// from decoder.go: if we're at the root or we're directly within
|
124
|
-
#// a list, decode
|
133
|
+
#// a list, decode to hashes, otherwise lists
|
125
134
|
#//
|
126
135
|
#// from object.go: there is a flattened list structure
|
127
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
|
+
#//
|
128
141
|
def flatten_objectlist(list)
|
129
|
-
list.each_with_object({}) do |a, h|
|
130
|
-
h
|
131
|
-
case
|
132
|
-
when
|
142
|
+
(list || {}).each_with_object({}) do |a, h|
|
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
|
133
152
|
deep_merge(h[a.first] || {}, a.last)
|
134
|
-
else
|
135
|
-
h[a.first] = a.last
|
153
|
+
else raise ArgumentError
|
136
154
|
end
|
155
|
+
else
|
156
|
+
h[a.first] = a.last
|
157
|
+
end
|
137
158
|
end
|
138
159
|
end
|
139
160
|
|
@@ -145,10 +166,12 @@ require_relative './lexer'
|
|
145
166
|
end
|
146
167
|
|
147
168
|
|
148
|
-
def parse(input)
|
149
|
-
@
|
169
|
+
def parse(input, duplicate_mode = :array)
|
170
|
+
@duplicate_mode = duplicate_mode
|
171
|
+
@lexer = HCL::Checker::Lexer.new.lex(input)
|
150
172
|
do_parse
|
151
|
-
|
173
|
+
|
174
|
+
@result
|
152
175
|
end
|
153
176
|
|
154
177
|
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
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
|
13
|
+
require 'irb'
|
14
14
|
IRB.start(__FILE__)
|
data/hcl-checker.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
lib = File.expand_path('
|
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
|
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = 'hcl-checker'
|
7
7
|
spec.version = HCL::Checker::VERSION
|
8
8
|
spec.authors = ['Marcelo Castellani']
|
9
|
-
spec.email = ['
|
9
|
+
spec.email = ['marcelo@linux.com']
|
10
10
|
|
11
11
|
spec.summary = 'Hashicorp Configuration Language parser for Ruby'
|
12
12
|
spec.description = 'Hashicorp Configuration Language parser and checker for Ruby'
|
@@ -17,12 +17,23 @@ 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', '~>
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency 'racc', '1.4.14'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 2.2.10'
|
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
|
-
spec.add_development_dependency 'rexical', '1.0.
|
26
|
+
spec.add_development_dependency 'rexical', '>= 1.0.7'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
|
29
|
+
spec.post_install_message = '
|
30
|
+
Hello, me again. This version fixes:
|
31
|
+
|
32
|
+
- Add support for multiple elements of the same type
|
33
|
+
- Fix bug where empty objects and empty lists were being parsed as nil
|
34
|
+
- Update bundler version
|
35
|
+
- Update nokogiri version
|
27
36
|
|
37
|
+
Thank you :)
|
38
|
+
'
|
28
39
|
end
|