codeclimate-yaml 0.0.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 +7 -0
- data/lib/cc/yaml.rb +26 -0
- data/lib/cc/yaml/nodes.rb +23 -0
- data/lib/cc/yaml/nodes/engine.rb +9 -0
- data/lib/cc/yaml/nodes/engine_list.rb +9 -0
- data/lib/cc/yaml/nodes/exclude_path.rb +8 -0
- data/lib/cc/yaml/nodes/exclude_path_list.rb +9 -0
- data/lib/cc/yaml/nodes/mapping.rb +173 -0
- data/lib/cc/yaml/nodes/node.rb +122 -0
- data/lib/cc/yaml/nodes/open_mapping.rb +18 -0
- data/lib/cc/yaml/nodes/root.rb +22 -0
- data/lib/cc/yaml/nodes/scalar.rb +112 -0
- data/lib/cc/yaml/nodes/sequence.rb +122 -0
- data/lib/cc/yaml/parser.rb +11 -0
- data/lib/cc/yaml/parser/psych.rb +223 -0
- data/lib/cc/yaml/serializer.rb +10 -0
- data/lib/cc/yaml/serializer/generic.rb +114 -0
- data/lib/cc/yaml/serializer/json.rb +74 -0
- data/lib/cc/yaml/version.rb +5 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dac3e3ac75a2d03d789a2f8a444e79e26045698b
|
4
|
+
data.tar.gz: c25e962bc3e09d8d9f1ebdbc151189c26ce69f8c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8973baee70e58c3dbeddfd13fb45ba6d1ffadbd6e86ef79e932c36f71c853fcf1efdcdb35eb29fff6a66c44c92036ff18fe5074d799e20fa70bc6399b7e28fa6
|
7
|
+
data.tar.gz: 5f584e502651441c49993fba4743ad2d53473099f37ff7a57099a09f4febd9fddcd332e774974a827696c2bb1aa36fea04ee5d308bd44084c7266fae72c1d5e5
|
data/lib/cc/yaml.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module CC
|
2
|
+
module Yaml
|
3
|
+
autoload :Nodes, "cc/yaml/nodes"
|
4
|
+
autoload :Parser, "cc/yaml/parser"
|
5
|
+
autoload :Serializer, "cc/yaml/serializer"
|
6
|
+
|
7
|
+
def self.parse(value)
|
8
|
+
Parser.parse(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse!(value, file_name = ".codeclimate.yml", logger = Kernel)
|
12
|
+
result = parse(value)
|
13
|
+
|
14
|
+
result.nested_warnings.each do |key, message|
|
15
|
+
logger.warn key.empty? ? "#{file_name}: #{message}" :
|
16
|
+
"#{file_name}: #{key.join(?.)} section - #{message}"
|
17
|
+
end
|
18
|
+
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.new
|
23
|
+
Nodes::Root.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CC
|
2
|
+
module Yaml
|
3
|
+
module Nodes
|
4
|
+
autoload :Engine, "cc/yaml/nodes/engine"
|
5
|
+
autoload :EngineList, "cc/yaml/nodes/engine_list"
|
6
|
+
autoload :ExcludePath, "cc/yaml/nodes/exclude_path"
|
7
|
+
autoload :ExcludePathList, "cc/yaml/nodes/exclude_path_list"
|
8
|
+
autoload :Mapping, "cc/yaml/nodes/mapping"
|
9
|
+
autoload :Node, "cc/yaml/nodes/node"
|
10
|
+
autoload :OpenMapping, "cc/yaml/nodes/open_mapping"
|
11
|
+
autoload :Root, "cc/yaml/nodes/root"
|
12
|
+
autoload :Scalar, "cc/yaml/nodes/scalar"
|
13
|
+
autoload :Sequence, "cc/yaml/nodes/sequence"
|
14
|
+
|
15
|
+
def self.[](key)
|
16
|
+
return key if key.respond_to? :new
|
17
|
+
name = constants.detect { |c| c.downcase == key }
|
18
|
+
raise ArgumentError, "unknown node type %p" % key unless name
|
19
|
+
const_get(name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module CC::Yaml
|
2
|
+
module Nodes
|
3
|
+
class Mapping < Node
|
4
|
+
def self.mapping
|
5
|
+
@mapping ||= superclass.respond_to?(:mapping) ? superclass.mapping.dup : {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.required
|
9
|
+
@required ||= superclass.respond_to?(:required) ? superclass.required.dup : []
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.aliases
|
13
|
+
@aliases ||= superclass.respond_to?(:aliases) ? superclass.aliases.dup : {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.map(*list)
|
17
|
+
options = Hash === list.last ? list.pop : {}
|
18
|
+
list.each do |key|
|
19
|
+
required << key.to_s if options[:required]
|
20
|
+
define_map_accessor(key)
|
21
|
+
case options[:to]
|
22
|
+
when Symbol then aliases[key.to_s] = options[:to].to_s
|
23
|
+
when Module then mapping[key.to_s] = options[:to]
|
24
|
+
when nil then mapping[key.to_s] = Nodes[key]
|
25
|
+
else raise ArgumentError, 'unexpected value for to: %p' % options[:to]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.define_map_accessor(key)
|
31
|
+
define_method(key) { | | self[key] } unless method_defined? key
|
32
|
+
define_method("#{key}=") { |v| self[key] = v } unless method_defined? "#{key}="
|
33
|
+
define_method("#{key}?") { | | !!self[key] } unless method_defined? "#{key}?"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.subnode_for(key)
|
37
|
+
mapping[aliases.fetch(key.to_s, key.to_s)]
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :mapping
|
41
|
+
alias_method :__getobj__, :mapping
|
42
|
+
|
43
|
+
def prepare
|
44
|
+
@mapping = {}
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def visit_mapping(visitor, value)
|
49
|
+
visitor.apply_mapping(self, value)
|
50
|
+
end
|
51
|
+
|
52
|
+
def visit_pair(visitor, key, value)
|
53
|
+
key = visitor.generate_key(self, key)
|
54
|
+
visit_key_value(visitor, key, value)
|
55
|
+
end
|
56
|
+
|
57
|
+
def visit_key_value(visitor, key, value)
|
58
|
+
return warning("unexpected key %p, dropping", key) unless node = subnode_for(key)
|
59
|
+
warning("has multiple %p entries, keeping last entry", key) if self[key]
|
60
|
+
self[key] = node
|
61
|
+
visitor.accept(node, value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def []=(key, value)
|
65
|
+
if mapped_key = mapped_key(key)
|
66
|
+
unless value.is_a? Node
|
67
|
+
node = subnode_for(mapped_key)
|
68
|
+
value = node if Parser::Ruby.new(value).parse(node)
|
69
|
+
end
|
70
|
+
@mapping[mapped_key] = value
|
71
|
+
else
|
72
|
+
warning("unexpected key %p, dropping", key)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def [](key)
|
77
|
+
@mapping[mapped_key(key)]
|
78
|
+
end
|
79
|
+
|
80
|
+
def include?(key)
|
81
|
+
@mapping.include? mapped_key(key)
|
82
|
+
end
|
83
|
+
|
84
|
+
def empty?
|
85
|
+
@mapping.empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
def mapped_key(key)
|
89
|
+
key = self.class.aliases.fetch(key.to_s, key.to_s)
|
90
|
+
key if accept_key?(key)
|
91
|
+
end
|
92
|
+
|
93
|
+
def accept_key?(key)
|
94
|
+
self.class.mapping.include? key
|
95
|
+
end
|
96
|
+
|
97
|
+
def subnode_for(key)
|
98
|
+
type = self.class.subnode_for(key)
|
99
|
+
type.new(self) if type
|
100
|
+
end
|
101
|
+
|
102
|
+
def inspect
|
103
|
+
@mapping.inspect
|
104
|
+
end
|
105
|
+
|
106
|
+
def ==(other)
|
107
|
+
other = other.mapping if other.is_a? Mapping
|
108
|
+
if other.respond_to? :to_hash and other.to_hash.size == @mapping.size
|
109
|
+
other.to_hash.all? { |k, v| include?(k) and self[k] == v }
|
110
|
+
else
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def verify
|
116
|
+
verify_errors
|
117
|
+
verify_required
|
118
|
+
verify_errors
|
119
|
+
end
|
120
|
+
|
121
|
+
def verify_required
|
122
|
+
self.class.required.each do |key|
|
123
|
+
next if @mapping.include? key
|
124
|
+
type = self.class.subnode_for(key)
|
125
|
+
if type.has_default?
|
126
|
+
warning "missing key %p, defaulting to %p", key, type.default
|
127
|
+
@mapping[key] = type.new(self)
|
128
|
+
else
|
129
|
+
error "missing key %p", key
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def verify_errors
|
135
|
+
@mapping.delete_if do |key, value|
|
136
|
+
if value.errors?
|
137
|
+
warning "dropping %p section: %s", key, value.errors.join(', ')
|
138
|
+
true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def deep_verify
|
144
|
+
@mapping.each_value(&:deep_verify)
|
145
|
+
super
|
146
|
+
end
|
147
|
+
|
148
|
+
def nested_warnings(*prefix)
|
149
|
+
@mapping.inject(super) do |list, (key, value)|
|
150
|
+
list = value.nested_warnings(*prefix, key) + list
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def with_value!(value)
|
155
|
+
value = value.mapping while value.is_a? Mapping
|
156
|
+
value.each { |key, value| self[key] = value }
|
157
|
+
end
|
158
|
+
|
159
|
+
def each_scalar(type = nil, &block)
|
160
|
+
return enum_for(:each_scalar, type) unless block
|
161
|
+
@mapping.each_value { |v| v.each_scalar(type, &block) }
|
162
|
+
end
|
163
|
+
|
164
|
+
protected
|
165
|
+
|
166
|
+
def dup_values
|
167
|
+
duped_mapping = @mapping.map { |key, value| [key.dup, value.dup] }
|
168
|
+
@mapping = Hash[duped_mapping]
|
169
|
+
self
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module CC
|
2
|
+
module Yaml
|
3
|
+
module Nodes
|
4
|
+
class Node
|
5
|
+
def self.has_default?
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :parent
|
10
|
+
|
11
|
+
def initialize(parent)
|
12
|
+
@nested_warnings = []
|
13
|
+
@parent = parent
|
14
|
+
prepare
|
15
|
+
yield self if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def warnings?
|
19
|
+
warnings.any?
|
20
|
+
end
|
21
|
+
|
22
|
+
def errors?
|
23
|
+
errors.any?
|
24
|
+
end
|
25
|
+
|
26
|
+
def warnings
|
27
|
+
@warnings ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
def nested_warning(message, *prefix)
|
31
|
+
@nested_warnings << [prefix, message]
|
32
|
+
end
|
33
|
+
|
34
|
+
def nested_warnings(*prefix)
|
35
|
+
messages = errors + warnings
|
36
|
+
prefixed = messages.map { |warning| [prefix, warning] }
|
37
|
+
prefixed += @nested_warnings.map { |p, w| [prefix + p, w] }
|
38
|
+
prefixed
|
39
|
+
end
|
40
|
+
|
41
|
+
def errors
|
42
|
+
@errors ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def warning(message, *params)
|
46
|
+
warnings << message % params
|
47
|
+
end
|
48
|
+
|
49
|
+
def error(message, *params)
|
50
|
+
errors << message % params
|
51
|
+
end
|
52
|
+
|
53
|
+
def prepare
|
54
|
+
end
|
55
|
+
|
56
|
+
def verify
|
57
|
+
end
|
58
|
+
|
59
|
+
def deep_verify
|
60
|
+
verify
|
61
|
+
end
|
62
|
+
|
63
|
+
def visit_unexpected(visitor, value, message = nil)
|
64
|
+
error(message || "unexpected %p", value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_mapping(visitor, value)
|
68
|
+
error("unexpected mapping")
|
69
|
+
end
|
70
|
+
|
71
|
+
def visit_pair(visitor, key, value)
|
72
|
+
error("unexpected pair")
|
73
|
+
end
|
74
|
+
|
75
|
+
def visit_scalar(visitor, type, value, implicit = true)
|
76
|
+
error("unexpected scalar") unless type == :null
|
77
|
+
end
|
78
|
+
|
79
|
+
def visit_sequence(visitor, value)
|
80
|
+
error("unexpected sequence")
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_child(visitor, value)
|
84
|
+
error("unexpected child")
|
85
|
+
end
|
86
|
+
|
87
|
+
def respond_to_missing?(method, include_private = false)
|
88
|
+
__getobj__.respond_to?(method, false)
|
89
|
+
end
|
90
|
+
|
91
|
+
def method_missing(method, *args, &block)
|
92
|
+
return super unless __getobj__.respond_to?(method)
|
93
|
+
__getobj__.public_send(method, *args, &block)
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
__getobj__.to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_json(options = nil)
|
101
|
+
Serializer::Json.serialize(self, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
def with_value(value)
|
105
|
+
node = dup
|
106
|
+
node.with_value!(value)
|
107
|
+
node
|
108
|
+
end
|
109
|
+
|
110
|
+
def dup
|
111
|
+
super.dup_values
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
def dup_values
|
117
|
+
self
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CC::Yaml
|
2
|
+
module Nodes
|
3
|
+
class OpenMapping < Mapping
|
4
|
+
def self.default_type(identifier = nil)
|
5
|
+
@default_type = Nodes[identifier] if identifier
|
6
|
+
@default_type ||= superclass.respond_to?(:default_type) ? superclass.default_type : Scalar
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.subnode_for(key)
|
10
|
+
super(key) || default_type
|
11
|
+
end
|
12
|
+
|
13
|
+
def accept_key?(key)
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CC
|
2
|
+
module Yaml
|
3
|
+
module Nodes
|
4
|
+
class Root < Mapping
|
5
|
+
map :exclude_paths, to: ExcludePathList
|
6
|
+
map :engines, to: EngineList
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def nested_warnings(*)
|
13
|
+
super.uniq
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
"#<#{self.class.name}:#{super}>"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module CC::Yaml
|
2
|
+
module Nodes
|
3
|
+
class Scalar < Node
|
4
|
+
def self.[](*types)
|
5
|
+
Class.new(self) do
|
6
|
+
default_type(types.first)
|
7
|
+
cast(*types)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.cast?(type)
|
12
|
+
cast.include? type
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.cast(*types)
|
16
|
+
@cast ||= superclass.respond_to?(:cast) ? superclass.cast.dup : []
|
17
|
+
@cast.concat(types) if types.any?
|
18
|
+
@cast
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.default_type(type = nil)
|
22
|
+
@default_type = type if type
|
23
|
+
@default_type ||= superclass.respond_to?(:default_type) ? superclass.default_type : :str
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.default(value = nil)
|
27
|
+
@default = value if value
|
28
|
+
@default ||= nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.has_default?
|
32
|
+
!default.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :value
|
36
|
+
alias_method :__getobj__, :value
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
value.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare
|
43
|
+
self.value = self.class.default
|
44
|
+
@multiple = false
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(other)
|
49
|
+
other = other.value if other.is_a? self.class
|
50
|
+
other == value
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_type
|
54
|
+
self.class.default_type
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect
|
58
|
+
value.inspect
|
59
|
+
end
|
60
|
+
|
61
|
+
def visit_scalar(visitor, type, value, implicit = true)
|
62
|
+
return self.value = cast(visitor, type, value) if cast? type
|
63
|
+
return self.value = cast(visitor, default_type, value) if implicit
|
64
|
+
error "%p not supported, dropping %p", type.to_s, cast(visitor, :str, value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_sequence(visitor, value)
|
68
|
+
@multiple = false
|
69
|
+
visitor.apply_sequence(self, value)
|
70
|
+
end
|
71
|
+
|
72
|
+
def visit_child(visitor, value)
|
73
|
+
if @multiple
|
74
|
+
value = cast(visitor, :str, value) rescue value
|
75
|
+
warning "does not support multiple values, dropping %p", value
|
76
|
+
else
|
77
|
+
@multiple = true
|
78
|
+
visitor.accept(self, value)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def cast(visitor, type, value)
|
83
|
+
visitor.cast(type, value)
|
84
|
+
rescue ArgumentError => error
|
85
|
+
error "failed to parse %p - %s", type.to_s, error.message.sub("():", ":")
|
86
|
+
end
|
87
|
+
|
88
|
+
def cast?(type)
|
89
|
+
self.class.cast?(type) or type == default_type
|
90
|
+
end
|
91
|
+
|
92
|
+
def !@
|
93
|
+
!value
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_value(value)
|
97
|
+
return value.dup if value.is_a? self.class
|
98
|
+
value = value.value while value.is_a? Scalar
|
99
|
+
super(value)
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_value!(value)
|
103
|
+
self.value = value
|
104
|
+
end
|
105
|
+
|
106
|
+
def each_scalar(type = nil, &block)
|
107
|
+
return enum_for(:each_scalar, type) unless block
|
108
|
+
yield value if type.nil? or type === value
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module CC::Yaml
|
2
|
+
module Nodes
|
3
|
+
class Sequence < Node
|
4
|
+
attr_reader :children
|
5
|
+
alias_method :__getobj__, :children
|
6
|
+
|
7
|
+
def self.[](node_type)
|
8
|
+
node_type = Scalar[node_type] unless node_type.is_a? Node
|
9
|
+
Class.new(self) { type(node_type) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.type(identifier = nil)
|
13
|
+
@type = Nodes[identifier] if identifier
|
14
|
+
@type ||= superclass.respond_to?(:type) ? superclass.type : Scalar
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepare
|
18
|
+
@children = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def visit_sequence(visitor, value)
|
22
|
+
visitor.apply_sequence(self, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_scalar(visitor, type, value, implicit = true)
|
26
|
+
visit_child(visitor, value) if type != :null
|
27
|
+
end
|
28
|
+
|
29
|
+
def visit_mapping(visitor, value)
|
30
|
+
visit_child(visitor, value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_child(visitor, value)
|
34
|
+
child = self.class.type.new(self)
|
35
|
+
visitor.accept(child, value)
|
36
|
+
@children << child
|
37
|
+
end
|
38
|
+
|
39
|
+
def nested_warnings(*prefix)
|
40
|
+
@children.inject(super) do |list, value|
|
41
|
+
list = value.nested_warnings(*prefix) + list
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def ==(other)
|
46
|
+
other = other.children if other.is_a? Sequence
|
47
|
+
if other.respond_to? :to_a and other.to_a.size == children.size
|
48
|
+
children.zip(other.to_a).all? { |a, b| a == b }
|
49
|
+
else
|
50
|
+
identifier == other
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def empty?
|
55
|
+
@children.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
identifier.inspect
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
identifier.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def identifier
|
67
|
+
@children.size == 1 ? @children.first : @children
|
68
|
+
end
|
69
|
+
|
70
|
+
def verify
|
71
|
+
verify_children
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
def verify_children
|
76
|
+
@children.delete_if do |child|
|
77
|
+
next unless child.errors?
|
78
|
+
child.errors.each { |message| warning(message) }
|
79
|
+
true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def deep_verify
|
84
|
+
@children.each(&:deep_verify)
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
def each_scalar(type = nil, &block)
|
89
|
+
return enum_for(:each_scalar, type) unless block
|
90
|
+
@children.each { |c| c.each_scalar(type, &block) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def with_value(value)
|
94
|
+
return value.dup if value.is_a? self.class
|
95
|
+
value = value.children if value.is_a? Sequence
|
96
|
+
value = value.value while value.is_a? Scalar
|
97
|
+
Parser::Ruby.new(Array(value)).parse self.class.new(parent)
|
98
|
+
end
|
99
|
+
|
100
|
+
def with_value!(value)
|
101
|
+
children.replace with_value(value).children
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_value(value)
|
105
|
+
added = with_value(self)
|
106
|
+
added.add_value!(value)
|
107
|
+
added
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_value!(value)
|
111
|
+
children.concat(with_value(value).children)
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
def dup_values
|
117
|
+
@children = @children.map { |child| child.dup }
|
118
|
+
self
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'psych'
|
2
|
+
require 'delegate'
|
3
|
+
|
4
|
+
module CC::Yaml
|
5
|
+
module Parser
|
6
|
+
class Psych
|
7
|
+
class SetNode < DelegateClass(::Psych::Nodes::Mapping)
|
8
|
+
def children
|
9
|
+
super.select.with_index { |_,i| i.even? }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ScalarSequence < DelegateClass(::Psych::Nodes::Mapping)
|
14
|
+
def children
|
15
|
+
[__getobj__]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
MAP = /\A(?:tag:yaml\.org,2002:|!!?)map\z/
|
20
|
+
OMAP = /\A(?:tag:yaml\.org,2002:|!!?)omap\z/
|
21
|
+
PAIRS = /\A(?:tag:yaml\.org,2002:|!!?)pairs\z/
|
22
|
+
SET = /\A(?:tag:yaml\.org,2002:|!!?)set\z/
|
23
|
+
SEQ = /\A(?:tag:yaml\.org,2002:|!!?)seq\z/
|
24
|
+
BINARY = /\A(?:tag:yaml\.org,2002:|!!?)binary\z/
|
25
|
+
BOOL = /\A(?:tag:yaml\.org,2002:|!!?)bool\z/
|
26
|
+
FLOAT = /\A(?:tag:yaml\.org,2002:|!!?)float\z/
|
27
|
+
INT = /\A(?:tag:yaml\.org,2002:|!!?)int\z/
|
28
|
+
MERGE = /\A(?:tag:yaml\.org,2002:|!!?)merge\z/
|
29
|
+
NULL = /\A(?:tag:yaml\.org,2002:|!!?)null\z/
|
30
|
+
STR = /\A(?:tag:yaml\.org,2002:|!!?)str\z/
|
31
|
+
TIMESTAMP = /\A(?:tag:yaml\.org,2002:|!!?)timestamp\z/
|
32
|
+
VALUE = /\A(?:tag:yaml\.org,2002:|!!?)value\z/
|
33
|
+
YAML = /\A(?:tag:yaml\.org,2002:|!!?)yaml\z/
|
34
|
+
SECURE = /\A!(?:encrypted|secure|decrypted)\z/
|
35
|
+
TRUE = /\A(?:y|Y|yes|Yes|YES|true|True|TRUE|on|On|ON)\z/
|
36
|
+
FALSE = /\A(?:n|N|no|No|NO|false|False|FALSE|off|Off|OFF)\z/
|
37
|
+
REGEXP = /\A!(?:ruby\/)?regexp\z/
|
38
|
+
REG_FLAGS = { 'i' => Regexp::IGNORECASE, 'm' => Regexp::MULTILINE, 'x' => Regexp::EXTENDED }
|
39
|
+
FORMATS = {
|
40
|
+
'!bool' => Regexp.union(TRUE, FALSE),
|
41
|
+
'!float' => ::Psych::ScalarScanner::FLOAT,
|
42
|
+
'!null' => /\A(:?~|null|Null|NULL|)\z/,
|
43
|
+
'!timestamp' => ::Psych::ScalarScanner::TIME,
|
44
|
+
'!int' => ::Psych::ScalarScanner::INTEGER,
|
45
|
+
'!regexp' => /\A\/(.*)\/([imx]*)\z/
|
46
|
+
}
|
47
|
+
|
48
|
+
if defined? ::Psych::ClassLoader
|
49
|
+
CLASS_LOADER = ::Psych::ClassLoader.new
|
50
|
+
class ScalarScanner < ::Psych::ScalarScanner
|
51
|
+
def initialize
|
52
|
+
super(CLASS_LOADER)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
ScalarScanner = ::Psych::ScalarScanner
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parses?(value)
|
60
|
+
return true if value.is_a?(::Psych::Nodes::Node)
|
61
|
+
return true if value.is_a?(String) or value.is_a?(IO)
|
62
|
+
return true if defined?(StringIO) and value.is_a?(StringIO)
|
63
|
+
value.respond_to?(:to_str) or value.respond_to?(:to_io)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.parse(value)
|
67
|
+
new(value).parse
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize(value)
|
71
|
+
value = value.to_str if value.respond_to? :to_str
|
72
|
+
value = value.to_io if value.respond_to? :to_io
|
73
|
+
@value = value
|
74
|
+
@scanner = ScalarScanner.new
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse(root = nil)
|
78
|
+
root ||= CC::Yaml::Nodes::Root.new
|
79
|
+
parsed = @value if @value.is_a? ::Psych::Nodes::Node
|
80
|
+
parsed ||= ::Psych.parse(@value)
|
81
|
+
accept(root, parsed)
|
82
|
+
root
|
83
|
+
rescue ::Psych::SyntaxError => error
|
84
|
+
root.verify
|
85
|
+
root.warnings.clear
|
86
|
+
root.error("syntax error: %s", error.message)
|
87
|
+
root
|
88
|
+
end
|
89
|
+
|
90
|
+
def accept(node, value)
|
91
|
+
case value
|
92
|
+
when ::Psych::Nodes::Scalar then accept_scalar node, value
|
93
|
+
when ::Psych::Nodes::Mapping then accept_mapping node, value
|
94
|
+
when ::Psych::Nodes::Sequence then accept_sequence node, value
|
95
|
+
when ::Psych::Nodes::Alias then accept_alias node, value
|
96
|
+
when ::Psych::Nodes::Document then accept node, value.root
|
97
|
+
when ::Psych::Nodes::Stream then accept_sequence node, value
|
98
|
+
else node.visit_unexpected(self, value) if value
|
99
|
+
end
|
100
|
+
node.verify
|
101
|
+
end
|
102
|
+
|
103
|
+
def accept_sequence(node, value)
|
104
|
+
case value.tag
|
105
|
+
when SET, SEQ
|
106
|
+
node.visit_sequence self, value
|
107
|
+
when nil
|
108
|
+
value = ScalarSequence.new(value) unless value.is_a? ::Psych::Nodes::Sequence
|
109
|
+
node.visit_sequence self, value
|
110
|
+
else
|
111
|
+
node.visit_sequence self, ScalarSequence.new(value)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def accept_mapping(node, value)
|
116
|
+
case value.tag
|
117
|
+
when MAP, OMAP, PAIRS then node.visit_mapping self, value
|
118
|
+
when SET then node.visit_sequence self, SetNode.new(value)
|
119
|
+
when SEQ then node.visit_sequence self, value
|
120
|
+
when nil
|
121
|
+
if value.children.size == 2 and value.children.first.value == 'secure'
|
122
|
+
secret_value = value.children.last
|
123
|
+
if secret_value.is_a? ::Psych::Nodes::Scalar
|
124
|
+
secret_value.tag ||= '!secure'
|
125
|
+
node.visit_scalar(self, :secure, secret_value, false)
|
126
|
+
else
|
127
|
+
node.visit_unexpected(self, value, "secret value needs to be a string")
|
128
|
+
end
|
129
|
+
else
|
130
|
+
node.visit_mapping(self, value)
|
131
|
+
end
|
132
|
+
else
|
133
|
+
node.visit_unexpected self, value, "unexpected tag %p for mapping" % value.tag
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def accept_scalar(node, value)
|
138
|
+
case tag = scalar_tag(value)
|
139
|
+
when BINARY then node.visit_scalar self, :binary, value, value.tag.nil?
|
140
|
+
when BOOL then node.visit_scalar self, :bool, value, value.tag.nil?
|
141
|
+
when FLOAT then node.visit_scalar self, :float, value, value.tag.nil?
|
142
|
+
when INT then node.visit_scalar self, :int, value, value.tag.nil?
|
143
|
+
when NULL then node.visit_scalar self, :null, value, value.tag.nil?
|
144
|
+
when STR then node.visit_scalar self, :str, value, value.tag.nil?
|
145
|
+
when TIMESTAMP then node.visit_scalar self, :time, value, value.tag.nil?
|
146
|
+
when SECURE then node.visit_scalar self, :secure, value, value.tag.nil?
|
147
|
+
when NULL then node.visit_scalar self, :null, value, value.tag.nil?
|
148
|
+
when REGEXP then node.visit_scalar self, :regexp, value, value.tag.nil?
|
149
|
+
else node.visit_unexpected self, value, "unexpected tag %p for scalar %p" % [tag, simple(value)]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def simple(value)
|
154
|
+
case value
|
155
|
+
when ::Psych::Nodes::Scalar then value.value
|
156
|
+
when ::Psych::Nodes::Mapping then simple_mapping(value)
|
157
|
+
when ::Psych::Nodes::Sequence then value.children.map { |c| simple(c) }
|
158
|
+
when ::Psych::Nodes::Document then simple(value.root)
|
159
|
+
when ::Psych::Nodes::Stream then value.children.map { |c| simple(c) }
|
160
|
+
else value
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def simple_mapping(value)
|
165
|
+
children = {}
|
166
|
+
keys, values = value.children.group_by.with_index { |_,i| i.even? }.values_at(true, false)
|
167
|
+
keys.zip(values) { |key, value| children[simple(key)] = simple(value) } if keys and values
|
168
|
+
children
|
169
|
+
end
|
170
|
+
|
171
|
+
def scalar_tag(value)
|
172
|
+
return value.tag if value.tag
|
173
|
+
return '!str' if value.quoted
|
174
|
+
FORMATS.each do |tag, format|
|
175
|
+
return tag if value.value =~ format
|
176
|
+
end
|
177
|
+
'!str'
|
178
|
+
end
|
179
|
+
|
180
|
+
def regexp(pattern)
|
181
|
+
return pattern if pattern.is_a? Regexp
|
182
|
+
return Regexp.new(pattern) unless pattern =~ FORMATS['!regexp']
|
183
|
+
flag = $2.chars.inject(0) { |f,c| f | REG_FLAGS.fetch(c, 0) }
|
184
|
+
Regexp.new($1, flag)
|
185
|
+
rescue RegexpError => error
|
186
|
+
raise ArgumentError, "broken regular expression - #{error.message}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def cast(type, value)
|
190
|
+
case type
|
191
|
+
when :str then value.value
|
192
|
+
when :binary then value.value.unpack('m').first
|
193
|
+
when :bool then value.value !~ FALSE
|
194
|
+
when :float then Float @scanner.tokenize(value.value)
|
195
|
+
when :int then Integer @scanner.tokenize(value.value)
|
196
|
+
when :time then @scanner.parse_time(value.value)
|
197
|
+
when :secure then SecureString.new(value.value, value.tag != '!decrypted')
|
198
|
+
when :regexp then regexp(value.value)
|
199
|
+
when :null then nil
|
200
|
+
else raise ArgumentError, 'unknown scalar type %p' % type
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def apply_mapping(node, value)
|
205
|
+
keys, values = value.children.group_by.with_index { |_,i| i.even? }.values_at(true, false)
|
206
|
+
keys.zip(values) { |key, value| node.visit_pair(self, key, value) } if keys and values
|
207
|
+
end
|
208
|
+
|
209
|
+
def apply_sequence(node, value)
|
210
|
+
value.children.each { |child| node.visit_child(self, child) }
|
211
|
+
end
|
212
|
+
|
213
|
+
def generate_key(node, value)
|
214
|
+
if value.respond_to? :value and (value.tag.nil? || value.tag == STR)
|
215
|
+
value = value.value.to_s
|
216
|
+
value.start_with?(?:) ? value[1..-1] : value
|
217
|
+
else
|
218
|
+
node.visit_unexpected(self, value, "expected string as key")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module CC::Yaml
|
2
|
+
module Serializer
|
3
|
+
class Generic
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
def self.serialize(node, options = nil)
|
7
|
+
new(options).serialize(node)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(options = nil)
|
11
|
+
@options = options || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def symbol_keys?
|
15
|
+
!!options[:symbol_keys]
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize(node)
|
19
|
+
case node
|
20
|
+
when Nodes::Root then serialize_root(node)
|
21
|
+
when Nodes::Scalar then serialize_scalar(node)
|
22
|
+
when Nodes::Mapping then serialize_mapping(node)
|
23
|
+
when Nodes::Sequence then serialize_sequence(node)
|
24
|
+
else raise NotSupportedError, 'do not know how to serialize %p' % node.class
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize_scalar(node)
|
29
|
+
case value = node.value
|
30
|
+
when true, false then serialize_bool(value)
|
31
|
+
when Float then serialize_float(value)
|
32
|
+
when Integer then serialize_integer(value)
|
33
|
+
when Time then serialize_time(value)
|
34
|
+
when SecureString then serialize_secure(value)
|
35
|
+
when Regexp then serialize_regexp(value)
|
36
|
+
when String
|
37
|
+
value.encoding == Encoding::BINARY ? serialize_binary(value) : serialize_str(value)
|
38
|
+
else
|
39
|
+
serialize_value(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def serialize_bool(value)
|
44
|
+
serialize_value(value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def serialize_float(value)
|
48
|
+
serialize_value(value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def serialize_time(value)
|
52
|
+
serialize_value(value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def serialize_secure(value)
|
56
|
+
case options[:secure]
|
57
|
+
when :decrypted
|
58
|
+
raise ArgumentError, 'secure option is set decrypted, but a secure value is not decrypted' unless value.decrypted?
|
59
|
+
serialize_decrypted(value)
|
60
|
+
when :encrypted
|
61
|
+
raise ArgumentError, 'secure option is set encrypted, but a secure value is not encrypted' unless value.encrypted?
|
62
|
+
serialize_encrypted(value)
|
63
|
+
else
|
64
|
+
raise ArgumentError, 'unexpected value for secure option: %p' % options[:secure] if options[:secure]
|
65
|
+
value.encrypted? ? serialize_encrypted(value) : serialize_decrypted(value)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def serialize_encrypted(value)
|
70
|
+
serialize_value(value)
|
71
|
+
end
|
72
|
+
|
73
|
+
def serialize_decrypted(value)
|
74
|
+
serialize_value(value)
|
75
|
+
end
|
76
|
+
|
77
|
+
def serialize_regexp(value)
|
78
|
+
serialize_value(value)
|
79
|
+
end
|
80
|
+
|
81
|
+
def serialize_str(value)
|
82
|
+
serialize_value(value)
|
83
|
+
end
|
84
|
+
|
85
|
+
def serialize_binary(value)
|
86
|
+
serialize_str(value)
|
87
|
+
end
|
88
|
+
|
89
|
+
def serialize_bool(value)
|
90
|
+
serialize_value(value)
|
91
|
+
end
|
92
|
+
|
93
|
+
def serialize_value(node)
|
94
|
+
raise NotSupportedError, 'cannot serialize %p with %p' % [node.class, self.class]
|
95
|
+
end
|
96
|
+
|
97
|
+
def serialize_root(node)
|
98
|
+
serialize_mapping(node)
|
99
|
+
end
|
100
|
+
|
101
|
+
def serialize_mapping(node)
|
102
|
+
node.map { |key, value| [serialize_key(key), serialize(value)] }
|
103
|
+
end
|
104
|
+
|
105
|
+
def serialize_sequence(node)
|
106
|
+
node.map { |value| serialize(value) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def serialize_key(value)
|
110
|
+
symbol_keys? ? value.to_sym : value.to_s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module CC
|
2
|
+
module Yaml
|
3
|
+
module Serializer
|
4
|
+
class Json < Generic
|
5
|
+
MAP = { # mapping stolen from json gem
|
6
|
+
"\x0" => '\u0000', "\x1" => '\u0001', "\x2" => '\u0002', "\x3" => '\u0003', "\x4" => '\u0004', "\x5" => '\u0005',
|
7
|
+
"\x6" => '\u0006', "\x7" => '\u0007', "\b" => '\b', "\t" => '\t', "\n" => '\n', "\xb" => '\u000b',
|
8
|
+
"\f" => '\f', "\r" => '\r', "\xe" => '\u000e', "\xf" => '\u000f', "\x10" => '\u0010', "\x11" => '\u0011',
|
9
|
+
"\x12" => '\u0012', "\x13" => '\u0013', "\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016', "\x17" => '\u0017',
|
10
|
+
"\x18" => '\u0018', "\x19" => '\u0019', "\x1a" => '\u001a', "\x1b" => '\u001b', "\x1c" => '\u001c', "\x1d" => '\u001d',
|
11
|
+
"\x1e" => '\u001e', "\x1f" => '\u001f', '"' => '\"', '\\' => '\\\\'
|
12
|
+
}
|
13
|
+
|
14
|
+
def pretty?
|
15
|
+
!!options[:pretty]
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_float(value)
|
19
|
+
raise NotSupportedError, 'cannot serialize infinity as JSON' if value.infinite?
|
20
|
+
"#{value}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialize_encrypted(value)
|
24
|
+
key_value("secure", serialize_str(value.encrypted_string), "{%s}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize_decrypted(value)
|
28
|
+
serialize_str(value.decrypted_string)
|
29
|
+
end
|
30
|
+
|
31
|
+
def serialize_str(value)
|
32
|
+
string = value.encode('utf-8')
|
33
|
+
string.force_encoding('binary')
|
34
|
+
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
|
35
|
+
string.force_encoding('utf-8')
|
36
|
+
"\"#{string}\""
|
37
|
+
end
|
38
|
+
|
39
|
+
def serialize_binary(value)
|
40
|
+
raise NotSupportedError, 'cannot serialize binary data as JSON'
|
41
|
+
end
|
42
|
+
|
43
|
+
def serialize_bool(value)
|
44
|
+
value ? "true" : "false"
|
45
|
+
end
|
46
|
+
|
47
|
+
def serialize_mapping(node)
|
48
|
+
lines('{%s}', super.map { |key, value| key_value(key, value) })
|
49
|
+
end
|
50
|
+
|
51
|
+
def serialize_sequence(node)
|
52
|
+
lines('[%s]', super)
|
53
|
+
end
|
54
|
+
|
55
|
+
def key_value(key, value, wrapper = "%s")
|
56
|
+
space = pretty? ? " " : ""
|
57
|
+
wrapper % "#{serialize_str(key)}:#{space}#{value}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def lines(wrapper, lines)
|
61
|
+
return wrapper % lines.join(',') unless pretty?
|
62
|
+
return wrapper % "" if lines.empty?
|
63
|
+
return wrapper % " #{lines.first} " unless lines.size > 1 or lines.first.include?("\n") or lines.first.size > 50
|
64
|
+
lines = "\n " + lines.join(",\n").strip.gsub("\n", "\n ") + "\n"
|
65
|
+
wrapper % lines
|
66
|
+
end
|
67
|
+
|
68
|
+
def serialize_key(value)
|
69
|
+
value.to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: codeclimate-yaml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Code Climate
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Code Climate YAML parser
|
14
|
+
email: hello@codeclimate.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/cc/yaml.rb
|
20
|
+
- lib/cc/yaml/nodes.rb
|
21
|
+
- lib/cc/yaml/nodes/engine.rb
|
22
|
+
- lib/cc/yaml/nodes/engine_list.rb
|
23
|
+
- lib/cc/yaml/nodes/exclude_path.rb
|
24
|
+
- lib/cc/yaml/nodes/exclude_path_list.rb
|
25
|
+
- lib/cc/yaml/nodes/mapping.rb
|
26
|
+
- lib/cc/yaml/nodes/node.rb
|
27
|
+
- lib/cc/yaml/nodes/open_mapping.rb
|
28
|
+
- lib/cc/yaml/nodes/root.rb
|
29
|
+
- lib/cc/yaml/nodes/scalar.rb
|
30
|
+
- lib/cc/yaml/nodes/sequence.rb
|
31
|
+
- lib/cc/yaml/parser.rb
|
32
|
+
- lib/cc/yaml/parser/psych.rb
|
33
|
+
- lib/cc/yaml/serializer.rb
|
34
|
+
- lib/cc/yaml/serializer/generic.rb
|
35
|
+
- lib/cc/yaml/serializer/json.rb
|
36
|
+
- lib/cc/yaml/version.rb
|
37
|
+
homepage: https://codeclimate.com
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata: {}
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 2.4.5
|
58
|
+
signing_key:
|
59
|
+
specification_version: 4
|
60
|
+
summary: Code Climate YAML
|
61
|
+
test_files: []
|