<commit_before>require 'pdk'
require 'pdk/cli/exec'
require 'pdk/validators/base_validator'
require 'pdk/util/bundler'
require 'pathname'

module PDK
  module Validate
    class MetadataJSONLint < BaseValidator
      # Validate each metadata file separately, as metadata-json-lint does not
      # support multiple targets.
      INVOKE_STYLE = :per_target

      def self.name
        'metadata-json-lint'
      end

      def self.cmd
        'metadata-json-lint'
      end

      def self.spinner_text(targets = nil)
        _('Checking metadata (%{targets})') % {
          targets: targets.map { |t| Pathname.new(t).absolute? ? Pathname.new(t).relative_path_from(Pathname.pwd) : t }.join(' '),
        }
      end

      def self.pattern
        'metadata.json'
      end

      def self.parse_options(_options, targets)
        cmd_options = ['--format', 'json']

        cmd_options.concat(targets)
      end

      def self.parse_output(report, result, targets)
        begin
          json_data = JSON.parse(result[:stdout])
        rescue JSON::ParserError
          json_data = []
        end

        raise ArgumentError, 'More that 1 target provided to PDK::Validate::MetadataJSONLint' if targets.count > 1

        if json_data.empty?
          report.add_event(
            file:     targets.first,
            source:   cmd,
            state:    :passed,
            severity: :ok,
          )
        else
          json_data.delete('result')
          json_data.keys.each do |type|
            json_data[type].each do |offense|
              # metadata-json-lint groups the offenses by type, so the type ends
              # up being `warnings` or `errors`. We want to convert that to the
              # singular noun for the event.
              event_type = type[%r{\A(.+?)s?\Z}, 1]

              report.add_event(
                file:     targets.first,
                source:   cmd,
                message:  offense['msg'],
                test:     offense['check'],
                severity: event_type,
                state:    :failure,
              )
            end
          end
        end
      end
    end
  end
end<commit_msg>(maint) Handle metadata-json-lint producing no output differently to bad JSON<commit_after>require 'pdk'
require 'pdk/cli/exec'
require 'pdk/validators/base_validator'
require 'pdk/util/bundler'
require 'pathname'

module PDK
  module Validate
    class MetadataJSONLint < BaseValidator
      # Validate each metadata file separately, as metadata-json-lint does not
      # support multiple targets.
      INVOKE_STYLE = :per_target

      def self.name
        'metadata-json-lint'
      end

      def self.cmd
        'metadata-json-lint'
      end

      def self.spinner_text(targets = nil)
        _('Checking metadata (%{targets})') % {
          targets: targets.map { |t| Pathname.new(t).absolute? ? Pathname.new(t).relative_path_from(Pathname.pwd) : t }.join(' '),
        }
      end

      def self.pattern
        'metadata.json'
      end

      def self.parse_options(_options, targets)
        cmd_options = ['--format', 'json']

        cmd_options.concat(targets)
      end

      def self.parse_output(report, result, targets)
        if result[:stdout].strip.empty?
          # metadata-json-lint will print nothing if there are no problems with
          # the file being linted. This should be handled separately to
          # metadata-json-lint generating output that can not be parsed as JSON
          # (unhandled exception in metadata-json-lint).
          json_data = {}
        else
          begin
            json_data = JSON.parse(result[:stdout])
          rescue JSON::ParserError
            report.add_event(
              file:     targets.first,
              source:   name,
              state:    :error,
              severity: :error,
              message:  result[:stdout],
            )
            return
          end
        end

        raise ArgumentError, 'More that 1 target provided to PDK::Validate::MetadataJSONLint' if targets.count > 1

        if json_data.empty?
          report.add_event(
            file:     targets.first,
            source:   name,
            state:    :passed,
            severity: :ok,
          )
        else
          json_data.delete('result')
          json_data.keys.each do |type|
            json_data[type].each do |offense|
              # metadata-json-lint groups the offenses by type, so the type ends
              # up being `warnings` or `errors`. We want to convert that to the
              # singular noun for the event.
              event_type = type[%r{\A(.+?)s?\Z}, 1]

              report.add_event(
                file:     targets.first,
                source:   name,
                message:  offense['msg'],
                test:     offense['check'],
                severity: event_type,
                state:    :failure,
              )
            end
          end
        end
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.09221844368873774, 'fraction_numerical': 0.001200240048009602, 'mean_word_length': 1.658160552897395, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4326128', 'n_tokens_mistral': 1414, 'n_tokens_neox': 1378, 'n_words': 372}