<commit_before>require 'semantic'

module StructCore
	class Specparser10X
		# @param version [Semantic::Version]
		def can_parse_version(version)
			version.major == 1 && version.minor == 0
		end

		def parse(spec_version, spec_hash, filename)
			valid_configuration_names = []
			configurations = parse_configurations spec_hash, valid_configuration_names
			raise StandardError.new 'Error: Invalid spec file. Project should have at least one configuration' unless configurations.count > 0

			project_base_dir = File.dirname filename
			return Specfile.new(spec_version, [], configurations, [], project_base_dir) unless spec_hash.key? 'targets'
			raise StandardError.new "Error: Invalid spec file. Key 'targets' should be a hash" unless spec_hash['targets'].is_a?(Hash)

			targets = (spec_hash['targets'] || {}).map { |target_name, target_opts|
				parse_target_data(target_name, target_opts, project_base_dir, valid_configuration_names)
			}.compact

			Specfile.new(spec_version, targets, configurations, [], project_base_dir)
		end

		private
		# @return Array<StructCore::Specfile::Configuration>
		def parse_configurations(spec_hash, valid_configuration_names)
			return [] unless spec_hash.has_key? 'configurations'
			return [] unless spec_hash['configurations'].is_a?(Hash)

			spec_hash['configurations'].map { |name, config|
				unless config.is_a?(Hash)
					puts Paint["Warning: Configuration with name '#{name}' was skipped as it was invalid"]
					next nil
				end

				unless config != nil and config.key? 'profiles' and config['profiles'].is_a?(Array) and config['profiles'].count > 0
					puts Paint["Warning: Configuration with name '#{name}' was skipped as it was invalid"]
					next nil
				end

				overrides = config['overrides'] || {}
				unless overrides.is_a?(Hash)
					overrides = {}
					puts Paint["Warning: Configuration with name '#{name}' had improperly formatted overrides, overrides were skipped for this configuration block"]
				end

				type = config['type']
				unless type == nil || type.is_a?(String)
					type = nil
					puts Paint["Warning: Configuration with name '#{name}' had an improperly formatted type, the type was skipped for this configuration block"]
				end

				valid_configuration_names << name
				config = Specfile::Configuration.new(name, config['profiles'], overrides || {}, type)

				unless config.type != nil
					puts Paint["Warning: Configuration with name '#{name}' was skipped as its type did not match one of: debug, release"]
					next nil
				end

				next config
			}.compact
		end

		# @return StructCore::Specfile::Target
		def parse_target_data(target_name, target_opts, project_base_dir, valid_config_names)
			# Parse target type
			unless target_opts.key? 'type'
				puts Paint["Warning: Target #{target_name} has no target type. Ignoring target...", :yellow]
				return nil
			end

			type = target_opts['type']
			if type.is_a?(Symbol)
				type = type.to_s
			end
			# : at the start of the type is shorthand for 'com.apple.product-type.'
			if type.start_with? ':'
				type[0] = ''
				raw_type = type
				type = "com.apple.product-type.#{type}"
			else
				raw_type = type
			end<commit_msg>Refactored configuration parsing for 10X<commit_after>require 'semantic'

module StructCore
	class Specparser10X
		# @param version [Semantic::Version]
		def can_parse_version(version)
			version.major == 1 && version.minor.zero?
		end

		def parse(spec_version, spec_hash, filename)
			valid_configuration_names = []
			configurations = parse_configurations spec_hash, valid_configuration_names
			raise StandardError.new 'Error: Invalid spec file. Project should have at least one configuration' unless configurations.count > 0

			project_base_dir = File.dirname filename
			return Specfile.new(spec_version, [], configurations, [], project_base_dir) unless spec_hash.key? 'targets'
			raise StandardError.new "Error: Invalid spec file. Key 'targets' should be a hash" unless spec_hash['targets'].is_a?(Hash)

			targets = (spec_hash['targets'] || {}).map { |target_name, target_opts|
				parse_target_data(target_name, target_opts, project_base_dir, valid_configuration_names)
			}.compact

			Specfile.new(spec_version, targets, configurations, [], project_base_dir)
		end

		# @return Array<StructCore::Specfile::Configuration>
		private def parse_configurations(spec_hash, valid_configuration_names)
			return [] unless spec_hash.key? 'configurations'
			return [] unless spec_hash['configurations'].is_a? Hash

			spec_hash['configurations'].map { |name, config|
				unless config.is_a?(Hash)
					puts Paint["Warning: Configuration with name '#{name}' was skipped as it was invalid"]
					next nil
				end

				if config.nil? || !config.key?('profiles') || !config['profiles'].is_a?(Array) || config['profiles'].empty?
					puts Paint["Warning: Configuration with name '#{name}' was skipped as it was invalid"]
					next nil
				end

				overrides = parse_config_overrides config, name
				type = parse_config_type config, name

				valid_configuration_names << name
				config = Specfile::Configuration.new(name, config['profiles'], overrides || {}, type)

				if config.type.nil?
					puts Paint["Warning: Configuration with name '#{name}' was skipped as its type did not match one of: debug, release"]
					next nil
				end

				next config
			}.compact
		end

		private def parse_config_overrides(config, name)
			overrides = config['overrides'] || {}

			unless overrides.is_a?(Hash)
				overrides = {}
				puts Paint["Warning: Configuration with name '#{name}' had improperly formatted overrides, overrides were skipped for this configuration block"]
			end

			overrides
		end

		private def parse_config_type(config, name)
			type = config['type']
			unless type.nil? || type.is_a?(String)
				type = nil
				puts Paint["Warning: Configuration with name '#{name}' had an improperly formatted type, the type was skipped for this configuration block"]
			end

			type
		end

		# @return StructCore::Specfile::Target
		private def parse_target_data(target_name, target_opts, project_base_dir, valid_config_names)
			# Parse target type
			unless target_opts.key? 'type'
				puts Paint["Warning: Target #{target_name} has no target type. Ignoring target...", :yellow]
				return nil
			end

			type = target_opts['type']
			if type.is_a?(Symbol)
				type = type.to_s
			end
			# : at the start of the type is shorthand for 'com.apple.product-type.'
			if type.start_with? ':'
				type[0] = ''
				raw_type = type
				type = "com.apple.product-type.#{type}"
			else
				raw_type = type
			end
{'fraction_non_alphanumeric': 0.1061112800243235, 'fraction_numerical': 0.002128306476132563, 'mean_word_length': 4.155956112852665, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 8, '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': '5269304', 'n_tokens_mistral': 2333, 'n_tokens_neox': 1911, 'n_words': 576}