sarif-ruby 0.1.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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE +21 -0
  5. data/README.md +191 -0
  6. data/Rakefile +10 -0
  7. data/lib/sarif/address.rb +67 -0
  8. data/lib/sarif/artifact.rb +76 -0
  9. data/lib/sarif/artifact_change.rb +46 -0
  10. data/lib/sarif/artifact_content.rb +49 -0
  11. data/lib/sarif/artifact_location.rb +52 -0
  12. data/lib/sarif/attachment.rb +52 -0
  13. data/lib/sarif/code_flow.rb +46 -0
  14. data/lib/sarif/configuration_override.rb +46 -0
  15. data/lib/sarif/conversion.rb +49 -0
  16. data/lib/sarif/edge.rb +52 -0
  17. data/lib/sarif/edge_traversal.rb +52 -0
  18. data/lib/sarif/exception.rb +52 -0
  19. data/lib/sarif/external_properties.rb +100 -0
  20. data/lib/sarif/external_property_file_reference.rb +49 -0
  21. data/lib/sarif/external_property_file_references.rb +88 -0
  22. data/lib/sarif/fix.rb +46 -0
  23. data/lib/sarif/graph.rb +49 -0
  24. data/lib/sarif/graph_traversal.rb +58 -0
  25. data/lib/sarif/invocation.rb +115 -0
  26. data/lib/sarif/location.rb +58 -0
  27. data/lib/sarif/location_relationship.rb +49 -0
  28. data/lib/sarif/log.rb +52 -0
  29. data/lib/sarif/logical_location.rb +58 -0
  30. data/lib/sarif/message.rb +52 -0
  31. data/lib/sarif/multiformat_message_string.rb +46 -0
  32. data/lib/sarif/node.rb +52 -0
  33. data/lib/sarif/notification.rb +64 -0
  34. data/lib/sarif/physical_location.rb +52 -0
  35. data/lib/sarif/property_bag.rb +40 -0
  36. data/lib/sarif/rectangle.rb +55 -0
  37. data/lib/sarif/region.rb +73 -0
  38. data/lib/sarif/replacement.rb +46 -0
  39. data/lib/sarif/reporting_configuration.rb +52 -0
  40. data/lib/sarif/reporting_descriptor.rb +79 -0
  41. data/lib/sarif/reporting_descriptor_reference.rb +52 -0
  42. data/lib/sarif/reporting_descriptor_relationship.rb +49 -0
  43. data/lib/sarif/result.rb +127 -0
  44. data/lib/sarif/result_provenance.rb +58 -0
  45. data/lib/sarif/run.rb +121 -0
  46. data/lib/sarif/run_automation_details.rb +52 -0
  47. data/lib/sarif/schema/sarif-schema-2.1.0.json +3389 -0
  48. data/lib/sarif/special_locations.rb +43 -0
  49. data/lib/sarif/stack.rb +46 -0
  50. data/lib/sarif/stack_frame.rb +52 -0
  51. data/lib/sarif/suppression.rb +55 -0
  52. data/lib/sarif/thread_flow.rb +55 -0
  53. data/lib/sarif/thread_flow_location.rb +79 -0
  54. data/lib/sarif/tool.rb +46 -0
  55. data/lib/sarif/tool_component.rb +121 -0
  56. data/lib/sarif/tool_component_reference.rb +49 -0
  57. data/lib/sarif/translation_metadata.rb +58 -0
  58. data/lib/sarif/version.rb +5 -0
  59. data/lib/sarif/version_control_details.rb +58 -0
  60. data/lib/sarif/web_request.rb +64 -0
  61. data/lib/sarif/web_response.rb +64 -0
  62. data/lib/sarif.rb +121 -0
  63. data/sig/sarif.rbs +4 -0
  64. metadata +106 -0
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # Defines locations of special significance to SARIF consumers.
5
+ class SpecialLocations
6
+ attr_accessor :display_base, :properties
7
+
8
+ def initialize(display_base: nil, properties: nil)
9
+ @display_base = display_base
10
+ @properties = properties
11
+ end
12
+
13
+ def to_h
14
+ h = {}
15
+ h["displayBase"] = @display_base&.to_h unless @display_base.nil?
16
+ h["properties"] = @properties unless @properties.nil?
17
+ h
18
+ end
19
+
20
+ def to_json(pretty: false)
21
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
22
+ end
23
+
24
+ def self.from_hash(h)
25
+ return nil if h.nil?
26
+ new(
27
+ display_base: ArtifactLocation.from_hash(h["displayBase"]),
28
+ properties: h["properties"]
29
+ )
30
+ end
31
+
32
+ def ==(other)
33
+ return false unless other.is_a?(SpecialLocations)
34
+ @display_base == other.display_base && @properties == other.properties
35
+ end
36
+
37
+ alias eql? ==
38
+
39
+ def hash
40
+ [@display_base, @properties].hash
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # A call stack that is relevant to a result.
5
+ class Stack
6
+ attr_accessor :message, :frames, :properties
7
+
8
+ def initialize(message: nil, frames:, properties: nil)
9
+ @message = message
10
+ @frames = frames
11
+ @properties = properties
12
+ end
13
+
14
+ def to_h
15
+ h = {}
16
+ h["message"] = @message&.to_h unless @message.nil?
17
+ h["frames"] = @frames&.map(&:to_h)
18
+ h["properties"] = @properties unless @properties.nil?
19
+ h
20
+ end
21
+
22
+ def to_json(pretty: false)
23
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
24
+ end
25
+
26
+ def self.from_hash(h)
27
+ return nil if h.nil?
28
+ new(
29
+ message: Message.from_hash(h["message"]),
30
+ frames: h["frames"]&.map { |v| StackFrame.from_hash(v) },
31
+ properties: h["properties"]
32
+ )
33
+ end
34
+
35
+ def ==(other)
36
+ return false unless other.is_a?(Stack)
37
+ @message == other.message && @frames == other.frames && @properties == other.properties
38
+ end
39
+
40
+ alias eql? ==
41
+
42
+ def hash
43
+ [@message, @frames, @properties].hash
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # A function call within a stack trace.
5
+ class StackFrame
6
+ attr_accessor :location, :module_name, :thread_id, :parameters, :properties
7
+
8
+ def initialize(location: nil, module_name: nil, thread_id: nil, parameters: [], properties: nil)
9
+ @location = location
10
+ @module_name = module_name
11
+ @thread_id = thread_id
12
+ @parameters = parameters
13
+ @properties = properties
14
+ end
15
+
16
+ def to_h
17
+ h = {}
18
+ h["location"] = @location&.to_h unless @location.nil?
19
+ h["module"] = @module_name unless @module_name.nil?
20
+ h["threadId"] = @thread_id unless @thread_id.nil?
21
+ h["parameters"] = @parameters if @parameters&.any?
22
+ h["properties"] = @properties unless @properties.nil?
23
+ h
24
+ end
25
+
26
+ def to_json(pretty: false)
27
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
28
+ end
29
+
30
+ def self.from_hash(h)
31
+ return nil if h.nil?
32
+ new(
33
+ location: Location.from_hash(h["location"]),
34
+ module_name: h["module"],
35
+ thread_id: h["threadId"],
36
+ parameters: h["parameters"] || [],
37
+ properties: h["properties"]
38
+ )
39
+ end
40
+
41
+ def ==(other)
42
+ return false unless other.is_a?(StackFrame)
43
+ @location == other.location && @module_name == other.module_name && @thread_id == other.thread_id && @parameters == other.parameters && @properties == other.properties
44
+ end
45
+
46
+ alias eql? ==
47
+
48
+ def hash
49
+ [@location, @module_name, @thread_id, @parameters, @properties].hash
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # A suppression that is relevant to a result.
5
+ class Suppression
6
+ attr_accessor :guid, :kind, :status, :justification, :location, :properties
7
+
8
+ def initialize(guid: nil, kind:, status: nil, justification: nil, location: nil, properties: nil)
9
+ @guid = guid
10
+ @kind = kind
11
+ @status = status
12
+ @justification = justification
13
+ @location = location
14
+ @properties = properties
15
+ end
16
+
17
+ def to_h
18
+ h = {}
19
+ h["guid"] = @guid unless @guid.nil?
20
+ h["kind"] = @kind&.to_s
21
+ h["status"] = @status&.to_s unless @status.nil?
22
+ h["justification"] = @justification unless @justification.nil?
23
+ h["location"] = @location&.to_h unless @location.nil?
24
+ h["properties"] = @properties unless @properties.nil?
25
+ h
26
+ end
27
+
28
+ def to_json(pretty: false)
29
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
30
+ end
31
+
32
+ def self.from_hash(h)
33
+ return nil if h.nil?
34
+ new(
35
+ guid: h["guid"],
36
+ kind: h["kind"],
37
+ status: h["status"],
38
+ justification: h["justification"],
39
+ location: Location.from_hash(h["location"]),
40
+ properties: h["properties"]
41
+ )
42
+ end
43
+
44
+ def ==(other)
45
+ return false unless other.is_a?(Suppression)
46
+ @guid == other.guid && @kind == other.kind && @status == other.status && @justification == other.justification && @location == other.location && @properties == other.properties
47
+ end
48
+
49
+ alias eql? ==
50
+
51
+ def hash
52
+ [@guid, @kind, @status, @justification, @location, @properties].hash
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # Describes a sequence of code locations that specify a path through a single thread of execution such as an operating system or fiber.
5
+ class ThreadFlow
6
+ attr_accessor :id, :message, :initial_state, :immutable_state, :locations, :properties
7
+
8
+ def initialize(id: nil, message: nil, initial_state: nil, immutable_state: nil, locations:, properties: nil)
9
+ @id = id
10
+ @message = message
11
+ @initial_state = initial_state
12
+ @immutable_state = immutable_state
13
+ @locations = locations
14
+ @properties = properties
15
+ end
16
+
17
+ def to_h
18
+ h = {}
19
+ h["id"] = @id unless @id.nil?
20
+ h["message"] = @message&.to_h unless @message.nil?
21
+ h["initialState"] = @initial_state unless @initial_state.nil?
22
+ h["immutableState"] = @immutable_state unless @immutable_state.nil?
23
+ h["locations"] = @locations&.map(&:to_h)
24
+ h["properties"] = @properties unless @properties.nil?
25
+ h
26
+ end
27
+
28
+ def to_json(pretty: false)
29
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
30
+ end
31
+
32
+ def self.from_hash(h)
33
+ return nil if h.nil?
34
+ new(
35
+ id: h["id"],
36
+ message: Message.from_hash(h["message"]),
37
+ initial_state: h["initialState"],
38
+ immutable_state: h["immutableState"],
39
+ locations: h["locations"]&.map { |v| ThreadFlowLocation.from_hash(v) },
40
+ properties: h["properties"]
41
+ )
42
+ end
43
+
44
+ def ==(other)
45
+ return false unless other.is_a?(ThreadFlow)
46
+ @id == other.id && @message == other.message && @initial_state == other.initial_state && @immutable_state == other.immutable_state && @locations == other.locations && @properties == other.properties
47
+ end
48
+
49
+ alias eql? ==
50
+
51
+ def hash
52
+ [@id, @message, @initial_state, @immutable_state, @locations, @properties].hash
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # A location visited by an analysis tool while simulating or monitoring the execution of a program.
5
+ class ThreadFlowLocation
6
+ attr_accessor :index, :location, :stack, :kinds, :taxa, :module_name, :state, :nesting_level, :execution_order, :execution_time_utc, :importance, :web_request, :web_response, :properties
7
+
8
+ def initialize(index: -1, location: nil, stack: nil, kinds: [], taxa: [], module_name: nil, state: nil, nesting_level: nil, execution_order: -1, execution_time_utc: nil, importance: "important", web_request: nil, web_response: nil, properties: nil)
9
+ @index = index
10
+ @location = location
11
+ @stack = stack
12
+ @kinds = kinds
13
+ @taxa = taxa
14
+ @module_name = module_name
15
+ @state = state
16
+ @nesting_level = nesting_level
17
+ @execution_order = execution_order
18
+ @execution_time_utc = execution_time_utc
19
+ @importance = importance
20
+ @web_request = web_request
21
+ @web_response = web_response
22
+ @properties = properties
23
+ end
24
+
25
+ def to_h
26
+ h = {}
27
+ h["index"] = @index if @index && @index != -1
28
+ h["location"] = @location&.to_h unless @location.nil?
29
+ h["stack"] = @stack&.to_h unless @stack.nil?
30
+ h["kinds"] = @kinds if @kinds&.any?
31
+ h["taxa"] = @taxa&.map(&:to_h) if @taxa&.any?
32
+ h["module"] = @module_name unless @module_name.nil?
33
+ h["state"] = @state unless @state.nil?
34
+ h["nestingLevel"] = @nesting_level unless @nesting_level.nil?
35
+ h["executionOrder"] = @execution_order if @execution_order && @execution_order != -1
36
+ h["executionTimeUtc"] = @execution_time_utc unless @execution_time_utc.nil?
37
+ h["importance"] = @importance&.to_s if @importance && @importance != "important"
38
+ h["webRequest"] = @web_request&.to_h unless @web_request.nil?
39
+ h["webResponse"] = @web_response&.to_h unless @web_response.nil?
40
+ h["properties"] = @properties unless @properties.nil?
41
+ h
42
+ end
43
+
44
+ def to_json(pretty: false)
45
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
46
+ end
47
+
48
+ def self.from_hash(h)
49
+ return nil if h.nil?
50
+ new(
51
+ index: h["index"] || -1,
52
+ location: Location.from_hash(h["location"]),
53
+ stack: Stack.from_hash(h["stack"]),
54
+ kinds: h["kinds"] || [],
55
+ taxa: h["taxa"]&.map { |v| ReportingDescriptorReference.from_hash(v) } || [],
56
+ module_name: h["module"],
57
+ state: h["state"],
58
+ nesting_level: h["nestingLevel"],
59
+ execution_order: h["executionOrder"] || -1,
60
+ execution_time_utc: h["executionTimeUtc"],
61
+ importance: h["importance"] || "important",
62
+ web_request: WebRequest.from_hash(h["webRequest"]),
63
+ web_response: WebResponse.from_hash(h["webResponse"]),
64
+ properties: h["properties"]
65
+ )
66
+ end
67
+
68
+ def ==(other)
69
+ return false unless other.is_a?(ThreadFlowLocation)
70
+ @index == other.index && @location == other.location && @stack == other.stack && @kinds == other.kinds && @taxa == other.taxa && @module_name == other.module_name && @state == other.state && @nesting_level == other.nesting_level && @execution_order == other.execution_order && @execution_time_utc == other.execution_time_utc && @importance == other.importance && @web_request == other.web_request && @web_response == other.web_response && @properties == other.properties
71
+ end
72
+
73
+ alias eql? ==
74
+
75
+ def hash
76
+ [@index, @location, @stack, @kinds, @taxa, @module_name, @state, @nesting_level, @execution_order, @execution_time_utc, @importance, @web_request, @web_response, @properties].hash
77
+ end
78
+ end
79
+ end
data/lib/sarif/tool.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # The analysis tool that was run.
5
+ class Tool
6
+ attr_accessor :driver, :extensions, :properties
7
+
8
+ def initialize(driver:, extensions: [], properties: nil)
9
+ @driver = driver
10
+ @extensions = extensions
11
+ @properties = properties
12
+ end
13
+
14
+ def to_h
15
+ h = {}
16
+ h["driver"] = @driver&.to_h
17
+ h["extensions"] = @extensions&.map(&:to_h) if @extensions&.any?
18
+ h["properties"] = @properties unless @properties.nil?
19
+ h
20
+ end
21
+
22
+ def to_json(pretty: false)
23
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
24
+ end
25
+
26
+ def self.from_hash(h)
27
+ return nil if h.nil?
28
+ new(
29
+ driver: ToolComponent.from_hash(h["driver"]),
30
+ extensions: h["extensions"]&.map { |v| ToolComponent.from_hash(v) } || [],
31
+ properties: h["properties"]
32
+ )
33
+ end
34
+
35
+ def ==(other)
36
+ return false unless other.is_a?(Tool)
37
+ @driver == other.driver && @extensions == other.extensions && @properties == other.properties
38
+ end
39
+
40
+ alias eql? ==
41
+
42
+ def hash
43
+ [@driver, @extensions, @properties].hash
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # A component, such as a plug-in or the driver, of the analysis tool that was run.
5
+ class ToolComponent
6
+ attr_accessor :guid, :name, :organization, :product, :product_suite, :short_description, :full_description, :full_name, :version, :semantic_version, :dotted_quad_file_version, :release_date_utc, :download_uri, :information_uri, :global_message_strings, :notifications, :rules, :taxa, :locations, :language, :contents, :is_comprehensive, :localized_data_semantic_version, :minimum_required_localized_data_semantic_version, :associated_component, :translation_metadata, :supported_taxonomies, :properties
7
+
8
+ def initialize(guid: nil, name:, organization: nil, product: nil, product_suite: nil, short_description: nil, full_description: nil, full_name: nil, version: nil, semantic_version: nil, dotted_quad_file_version: nil, release_date_utc: nil, download_uri: nil, information_uri: nil, global_message_strings: nil, notifications: [], rules: [], taxa: [], locations: [], language: "en-US", contents: ["localizedData", "nonLocalizedData"], is_comprehensive: false, localized_data_semantic_version: nil, minimum_required_localized_data_semantic_version: nil, associated_component: nil, translation_metadata: nil, supported_taxonomies: [], properties: nil)
9
+ @guid = guid
10
+ @name = name
11
+ @organization = organization
12
+ @product = product
13
+ @product_suite = product_suite
14
+ @short_description = short_description
15
+ @full_description = full_description
16
+ @full_name = full_name
17
+ @version = version
18
+ @semantic_version = semantic_version
19
+ @dotted_quad_file_version = dotted_quad_file_version
20
+ @release_date_utc = release_date_utc
21
+ @download_uri = download_uri
22
+ @information_uri = information_uri
23
+ @global_message_strings = global_message_strings
24
+ @notifications = notifications
25
+ @rules = rules
26
+ @taxa = taxa
27
+ @locations = locations
28
+ @language = language
29
+ @contents = contents
30
+ @is_comprehensive = is_comprehensive
31
+ @localized_data_semantic_version = localized_data_semantic_version
32
+ @minimum_required_localized_data_semantic_version = minimum_required_localized_data_semantic_version
33
+ @associated_component = associated_component
34
+ @translation_metadata = translation_metadata
35
+ @supported_taxonomies = supported_taxonomies
36
+ @properties = properties
37
+ end
38
+
39
+ def to_h
40
+ h = {}
41
+ h["guid"] = @guid unless @guid.nil?
42
+ h["name"] = @name
43
+ h["organization"] = @organization unless @organization.nil?
44
+ h["product"] = @product unless @product.nil?
45
+ h["productSuite"] = @product_suite unless @product_suite.nil?
46
+ h["shortDescription"] = @short_description&.to_h unless @short_description.nil?
47
+ h["fullDescription"] = @full_description&.to_h unless @full_description.nil?
48
+ h["fullName"] = @full_name unless @full_name.nil?
49
+ h["version"] = @version unless @version.nil?
50
+ h["semanticVersion"] = @semantic_version unless @semantic_version.nil?
51
+ h["dottedQuadFileVersion"] = @dotted_quad_file_version unless @dotted_quad_file_version.nil?
52
+ h["releaseDateUtc"] = @release_date_utc unless @release_date_utc.nil?
53
+ h["downloadUri"] = @download_uri unless @download_uri.nil?
54
+ h["informationUri"] = @information_uri unless @information_uri.nil?
55
+ h["globalMessageStrings"] = @global_message_strings unless @global_message_strings.nil?
56
+ h["notifications"] = @notifications&.map(&:to_h) if @notifications&.any?
57
+ h["rules"] = @rules&.map(&:to_h) if @rules&.any?
58
+ h["taxa"] = @taxa&.map(&:to_h) if @taxa&.any?
59
+ h["locations"] = @locations&.map(&:to_h) if @locations&.any?
60
+ h["language"] = @language if @language && @language != "en-US"
61
+ h["contents"] = @contents&.map(&:to_s) if @contents&.any?
62
+ h["isComprehensive"] = @is_comprehensive if @is_comprehensive
63
+ h["localizedDataSemanticVersion"] = @localized_data_semantic_version unless @localized_data_semantic_version.nil?
64
+ h["minimumRequiredLocalizedDataSemanticVersion"] = @minimum_required_localized_data_semantic_version unless @minimum_required_localized_data_semantic_version.nil?
65
+ h["associatedComponent"] = @associated_component&.to_h unless @associated_component.nil?
66
+ h["translationMetadata"] = @translation_metadata&.to_h unless @translation_metadata.nil?
67
+ h["supportedTaxonomies"] = @supported_taxonomies&.map(&:to_h) if @supported_taxonomies&.any?
68
+ h["properties"] = @properties unless @properties.nil?
69
+ h
70
+ end
71
+
72
+ def to_json(pretty: false)
73
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
74
+ end
75
+
76
+ def self.from_hash(h)
77
+ return nil if h.nil?
78
+ new(
79
+ guid: h["guid"],
80
+ name: h["name"],
81
+ organization: h["organization"],
82
+ product: h["product"],
83
+ product_suite: h["productSuite"],
84
+ short_description: MultiformatMessageString.from_hash(h["shortDescription"]),
85
+ full_description: MultiformatMessageString.from_hash(h["fullDescription"]),
86
+ full_name: h["fullName"],
87
+ version: h["version"],
88
+ semantic_version: h["semanticVersion"],
89
+ dotted_quad_file_version: h["dottedQuadFileVersion"],
90
+ release_date_utc: h["releaseDateUtc"],
91
+ download_uri: h["downloadUri"],
92
+ information_uri: h["informationUri"],
93
+ global_message_strings: h["globalMessageStrings"],
94
+ notifications: h["notifications"]&.map { |v| ReportingDescriptor.from_hash(v) } || [],
95
+ rules: h["rules"]&.map { |v| ReportingDescriptor.from_hash(v) } || [],
96
+ taxa: h["taxa"]&.map { |v| ReportingDescriptor.from_hash(v) } || [],
97
+ locations: h["locations"]&.map { |v| ArtifactLocation.from_hash(v) } || [],
98
+ language: h["language"] || "en-US",
99
+ contents: h.key?("contents") ? h["contents"] : ["localizedData", "nonLocalizedData"],
100
+ is_comprehensive: h.key?("isComprehensive") ? h["isComprehensive"] : false,
101
+ localized_data_semantic_version: h["localizedDataSemanticVersion"],
102
+ minimum_required_localized_data_semantic_version: h["minimumRequiredLocalizedDataSemanticVersion"],
103
+ associated_component: ToolComponentReference.from_hash(h["associatedComponent"]),
104
+ translation_metadata: TranslationMetadata.from_hash(h["translationMetadata"]),
105
+ supported_taxonomies: h["supportedTaxonomies"]&.map { |v| ToolComponentReference.from_hash(v) } || [],
106
+ properties: h["properties"]
107
+ )
108
+ end
109
+
110
+ def ==(other)
111
+ return false unless other.is_a?(ToolComponent)
112
+ @guid == other.guid && @name == other.name && @organization == other.organization && @product == other.product && @product_suite == other.product_suite && @short_description == other.short_description && @full_description == other.full_description && @full_name == other.full_name && @version == other.version && @semantic_version == other.semantic_version && @dotted_quad_file_version == other.dotted_quad_file_version && @release_date_utc == other.release_date_utc && @download_uri == other.download_uri && @information_uri == other.information_uri && @global_message_strings == other.global_message_strings && @notifications == other.notifications && @rules == other.rules && @taxa == other.taxa && @locations == other.locations && @language == other.language && @contents == other.contents && @is_comprehensive == other.is_comprehensive && @localized_data_semantic_version == other.localized_data_semantic_version && @minimum_required_localized_data_semantic_version == other.minimum_required_localized_data_semantic_version && @associated_component == other.associated_component && @translation_metadata == other.translation_metadata && @supported_taxonomies == other.supported_taxonomies && @properties == other.properties
113
+ end
114
+
115
+ alias eql? ==
116
+
117
+ def hash
118
+ [@guid, @name, @organization, @product, @product_suite, @short_description, @full_description, @full_name, @version, @semantic_version, @dotted_quad_file_version, @release_date_utc, @download_uri, @information_uri, @global_message_strings, @notifications, @rules, @taxa, @locations, @language, @contents, @is_comprehensive, @localized_data_semantic_version, @minimum_required_localized_data_semantic_version, @associated_component, @translation_metadata, @supported_taxonomies, @properties].hash
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # Identifies a particular toolComponent object, either the driver or an extension.
5
+ class ToolComponentReference
6
+ attr_accessor :name, :index, :guid, :properties
7
+
8
+ def initialize(name: nil, index: -1, guid: nil, properties: nil)
9
+ @name = name
10
+ @index = index
11
+ @guid = guid
12
+ @properties = properties
13
+ end
14
+
15
+ def to_h
16
+ h = {}
17
+ h["name"] = @name unless @name.nil?
18
+ h["index"] = @index if @index && @index != -1
19
+ h["guid"] = @guid unless @guid.nil?
20
+ h["properties"] = @properties unless @properties.nil?
21
+ h
22
+ end
23
+
24
+ def to_json(pretty: false)
25
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
26
+ end
27
+
28
+ def self.from_hash(h)
29
+ return nil if h.nil?
30
+ new(
31
+ name: h["name"],
32
+ index: h["index"] || -1,
33
+ guid: h["guid"],
34
+ properties: h["properties"]
35
+ )
36
+ end
37
+
38
+ def ==(other)
39
+ return false unless other.is_a?(ToolComponentReference)
40
+ @name == other.name && @index == other.index && @guid == other.guid && @properties == other.properties
41
+ end
42
+
43
+ alias eql? ==
44
+
45
+ def hash
46
+ [@name, @index, @guid, @properties].hash
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # Provides additional metadata related to translation.
5
+ class TranslationMetadata
6
+ attr_accessor :name, :full_name, :short_description, :full_description, :download_uri, :information_uri, :properties
7
+
8
+ def initialize(name:, full_name: nil, short_description: nil, full_description: nil, download_uri: nil, information_uri: nil, properties: nil)
9
+ @name = name
10
+ @full_name = full_name
11
+ @short_description = short_description
12
+ @full_description = full_description
13
+ @download_uri = download_uri
14
+ @information_uri = information_uri
15
+ @properties = properties
16
+ end
17
+
18
+ def to_h
19
+ h = {}
20
+ h["name"] = @name
21
+ h["fullName"] = @full_name unless @full_name.nil?
22
+ h["shortDescription"] = @short_description&.to_h unless @short_description.nil?
23
+ h["fullDescription"] = @full_description&.to_h unless @full_description.nil?
24
+ h["downloadUri"] = @download_uri unless @download_uri.nil?
25
+ h["informationUri"] = @information_uri unless @information_uri.nil?
26
+ h["properties"] = @properties unless @properties.nil?
27
+ h
28
+ end
29
+
30
+ def to_json(pretty: false)
31
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
32
+ end
33
+
34
+ def self.from_hash(h)
35
+ return nil if h.nil?
36
+ new(
37
+ name: h["name"],
38
+ full_name: h["fullName"],
39
+ short_description: MultiformatMessageString.from_hash(h["shortDescription"]),
40
+ full_description: MultiformatMessageString.from_hash(h["fullDescription"]),
41
+ download_uri: h["downloadUri"],
42
+ information_uri: h["informationUri"],
43
+ properties: h["properties"]
44
+ )
45
+ end
46
+
47
+ def ==(other)
48
+ return false unless other.is_a?(TranslationMetadata)
49
+ @name == other.name && @full_name == other.full_name && @short_description == other.short_description && @full_description == other.full_description && @download_uri == other.download_uri && @information_uri == other.information_uri && @properties == other.properties
50
+ end
51
+
52
+ alias eql? ==
53
+
54
+ def hash
55
+ [@name, @full_name, @short_description, @full_description, @download_uri, @information_uri, @properties].hash
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sarif
4
+ # Specifies the information necessary to retrieve a desired revision from a version control system.
5
+ class VersionControlDetails
6
+ attr_accessor :repository_uri, :revision_id, :branch, :revision_tag, :as_of_time_utc, :mapped_to, :properties
7
+
8
+ def initialize(repository_uri:, revision_id: nil, branch: nil, revision_tag: nil, as_of_time_utc: nil, mapped_to: nil, properties: nil)
9
+ @repository_uri = repository_uri
10
+ @revision_id = revision_id
11
+ @branch = branch
12
+ @revision_tag = revision_tag
13
+ @as_of_time_utc = as_of_time_utc
14
+ @mapped_to = mapped_to
15
+ @properties = properties
16
+ end
17
+
18
+ def to_h
19
+ h = {}
20
+ h["repositoryUri"] = @repository_uri
21
+ h["revisionId"] = @revision_id unless @revision_id.nil?
22
+ h["branch"] = @branch unless @branch.nil?
23
+ h["revisionTag"] = @revision_tag unless @revision_tag.nil?
24
+ h["asOfTimeUtc"] = @as_of_time_utc unless @as_of_time_utc.nil?
25
+ h["mappedTo"] = @mapped_to&.to_h unless @mapped_to.nil?
26
+ h["properties"] = @properties unless @properties.nil?
27
+ h
28
+ end
29
+
30
+ def to_json(pretty: false)
31
+ pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
32
+ end
33
+
34
+ def self.from_hash(h)
35
+ return nil if h.nil?
36
+ new(
37
+ repository_uri: h["repositoryUri"],
38
+ revision_id: h["revisionId"],
39
+ branch: h["branch"],
40
+ revision_tag: h["revisionTag"],
41
+ as_of_time_utc: h["asOfTimeUtc"],
42
+ mapped_to: ArtifactLocation.from_hash(h["mappedTo"]),
43
+ properties: h["properties"]
44
+ )
45
+ end
46
+
47
+ def ==(other)
48
+ return false unless other.is_a?(VersionControlDetails)
49
+ @repository_uri == other.repository_uri && @revision_id == other.revision_id && @branch == other.branch && @revision_tag == other.revision_tag && @as_of_time_utc == other.as_of_time_utc && @mapped_to == other.mapped_to && @properties == other.properties
50
+ end
51
+
52
+ alias eql? ==
53
+
54
+ def hash
55
+ [@repository_uri, @revision_id, @branch, @revision_tag, @as_of_time_utc, @mapped_to, @properties].hash
56
+ end
57
+ end
58
+ end