<commit_before>require 'lint/base_validator'

module Lint
  class StatesValidator < BaseValidator

    def validate
      #7, #8
      check_for_secondary_descriptor_states

      #10, #11, #12, #13 check for the presence of required attributes for all transitions
      check_for_required_state_transition_properties
    end

    private

    def check_for_secondary_descriptor_states
      #7,8 Check for second level egregious errors
      resource_descriptor.states.each do |descriptor|
        add_error('catastrophic.no_states', resource: descriptor[0],
                  filename: filename) if secondary_descriptor_states(descriptor).empty?
      end
    end

    def secondary_descriptor_states(descriptor)
      descriptor[1]
    end

    # core deep dive method looking for missing properties and other syntactical
    # errors down to the transitions of the states: section
    def check_for_required_state_transition_properties
      # build a list of states for all secondary descriptors
      states_list = build_state_list

      resource_descriptor.states.each do |secondary_descriptor|
        secondary_descriptor_states(secondary_descriptor).each do |state|
          curr_state = state[1]
          options = {resource: secondary_descriptor[0], state: curr_state.name, filename: filename}
          #16
          add_warning('states.doc_property_missing', options) unless curr_state.doc

          # if a state does not have transitions, then check to see if it has a location property (e.g. deleted, error)
          if  curr_state.transitions.nil?
            add_warning('states.location_property_missing', options) if curr_state.location.nil?
          else
            check_resource_state_transitions(secondary_descriptor[0], curr_state, states_list)
          end
        end
      end
    end

    # Build a comprehensive list of all states in order to test for transitions pointing to nowhere (#11)
    def build_state_list
      state_array = []
      resource_descriptor.states.each do |secondary_descriptor|
        secondary_descriptor_states(secondary_descriptor).each do |state|
          if state_array.include?(state)
            add_error('states.duplicate_state', resource: secondary_descriptor[0],
                      state: state, filename: filename)
          else
            state_array << state[0]
          end
        end
      end
      state_array
    end

    def check_resource_state_transitions(resource_name, curr_state, states_list)
      state_name = curr_state.name

      curr_state.transitions.each do |transition|
        curr_transition = transition[1]
        options = {resource: resource_name, state: state_name, transition: curr_transition.id,
                   filename: filename}
        #9
        add_error('states.next_property_missing', options) unless curr_transition.next
        #10 Transition next property has no value
        add_error('states.empty_missing_next', options) if curr_transition.next && curr_transition.next.empty?
        #13 Transition conditions property has no value(s)
        add_error('states.no_conditions_values', options) if curr_transition.missing_condition_item?
        #11
        check_for_phantom_state_transitions(states_list, resource_name, state_name, curr_transition)
        #14
        add_warning('states.no_self_property', options) if curr_transition.is_specified_name_property_not_self?
      end
    end

    #11, check to see if any next transition maps to an existing state. Check for null values at every level.
    # No need to check if the next transition points to an external resource (e.g. 'location')
    def check_for_phantom_state_transitions(states_list, resource_name, curr_state_name, curr_transition)
      #
      # TODO: STATES MAY BE AN ARRAY. MAYBE CHECK IF NOT A LOCATION INSTEAD
      #
      if curr_transition.next && curr_transition.is_next_a_string?
        add_error('states.phantom_next_property', secondary_descriptor: resource_name, state: curr_state_name,
                  transition: curr_transition.name, next_state: curr_transition.next_state_name,
                  filename: filename) unless states_list.include?(curr_transition.next_state_name)
      end
    end
  end
end<commit_msg>indentation<commit_after>require 'lint/base_validator'

module Lint
  class StatesValidator < BaseValidator

    def validate
      #7, #8
      check_for_secondary_descriptor_states

      #10, #11, #12, #13 check for the presence of required attributes for all transitions
      check_for_required_state_transition_properties
    end

    private

    def check_for_secondary_descriptor_states
      #7,8 Check for second level egregious errors
      resource_descriptor.states.each do |descriptor|
        add_error('catastrophic.no_states', resource: descriptor[0],
          filename: filename) if secondary_descriptor_states(descriptor).empty?
      end
    end

    def secondary_descriptor_states(descriptor)
      descriptor[1]
    end

    # core deep dive method looking for missing properties and other syntactical
    # errors down to the transitions of the states: section
    def check_for_required_state_transition_properties
      # build a list of states for all secondary descriptors
      states_list = build_state_list

      resource_descriptor.states.each do |secondary_descriptor|
        secondary_descriptor_states(secondary_descriptor).each do |state|
          curr_state = state[1]
          options = {resource: secondary_descriptor[0], state: curr_state.name, filename: filename}
          #16
          add_warning('states.doc_property_missing', options) unless curr_state.doc

          # if a state does not have transitions, then check to see if it has a location property (e.g. deleted, error)
          if  curr_state.transitions.nil?
            add_warning('states.location_property_missing', options) if curr_state.location.nil?
          else
            check_resource_state_transitions(secondary_descriptor[0], curr_state, states_list)
          end
        end
      end
    end

    # Build a comprehensive list of all states in order to test for transitions pointing to nowhere (#11)
    def build_state_list
      state_array = []
      resource_descriptor.states.each do |secondary_descriptor|
        secondary_descriptor_states(secondary_descriptor).each do |state|
          if state_array.include?(state)
            add_error('states.duplicate_state', resource: secondary_descriptor[0],
              state: state, filename: filename)
          else
            state_array << state[0]
          end
        end
      end
      state_array
    end

    def check_resource_state_transitions(resource_name, curr_state, states_list)
      state_name = curr_state.name

      curr_state.transitions.each do |transition|
        curr_transition = transition[1]
        options = {resource: resource_name, state: state_name, transition: curr_transition.id,
          filename: filename}
        #9
        add_error('states.next_property_missing', options) unless curr_transition.next
        #10 Transition next property has no value
        add_error('states.empty_missing_next', options) if curr_transition.next && curr_transition.next.empty?
        #13 Transition conditions property has no value(s)
        add_error('states.no_conditions_values', options) if curr_transition.missing_condition_item?
        #11
        check_for_phantom_state_transitions(states_list, resource_name, state_name, curr_transition)
        #14
        add_warning('states.no_self_property', options) if curr_transition.is_specified_name_property_not_self?
      end
    end

    #11, check to see if any next transition maps to an existing state. Check for null values at every level.
    # No need to check if the next transition points to an external resource (e.g. 'location')
    def check_for_phantom_state_transitions(states_list, resource_name, curr_state_name, curr_transition)
      #
      # TODO: STATES MAY BE AN ARRAY. MAYBE CHECK IF NOT A LOCATION INSTEAD
      #
      if curr_transition.next && curr_transition.is_next_a_string?
        add_error('states.phantom_next_property', secondary_descriptor: resource_name, state: curr_state_name,
          transition: curr_transition.name, next_state: curr_transition.next_state_name,
          filename: filename) unless states_list.include?(curr_transition.next_state_name)
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.06139623088775631, 'fraction_numerical': 0.008296787957804906, 'mean_word_length': 3.198009950248756, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, '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': '4094250', 'n_tokens_mistral': 2273, 'n_tokens_neox': 2239, 'n_words': 633}