# typed: strict require 'code_ownership' module DangerPackwerk module Check class DefaultFormatter include OffensesFormatter extend T::Sig sig do params( custom_help_message: T.nilable(String) ).void end def initialize(custom_help_message: nil) @custom_help_message = custom_help_message end sig do override.params( offenses: T::Array[Packwerk::ReferenceOffense], repo_link: String, org_name: String ).returns(String) end def format_offenses(offenses, repo_link, org_name) reference_offense = T.must(offenses.first) violation_types = offenses.map(&:violation_type) referencing_file = reference_offense.reference.relative_path referencing_file_pack = ParsePackwerk.package_from_path(referencing_file).name # We remove leading double colons as they feel like an implementation detail of packwerk. constant_name = reference_offense.reference.constant.name.delete_prefix('::') constant_source_package_name = reference_offense.reference.constant.package.name constant_location = reference_offense.reference.constant.location constant_source_package = T.must(ParsePackwerk.all.find { |p| p.name == constant_source_package_name }) constant_source_package_ownership_info = Private::OwnershipInformation.for_package(constant_source_package, org_name) disclaimer = 'Before you run `bin/packwerk update-deprecations`, check out these quick suggestions:' referencing_code_in_right_pack = "- Does the code you are writing live in the right pack?\n - If not, try `bin/packs move packs/destination_pack #{referencing_file}`" referenced_code_in_right_pack = "- Does #{constant_name} live in the right pack?\n - If not, try `bin/packs move packs/destination_pack #{constant_location}`" dependency_violation_message = "- Do we actually want to depend on #{constant_source_package_name}?\n - If so, try `bin/packs add_dependency #{referencing_file_pack} #{constant_source_package_name}`\n - If not, what can we change about the design so we do not have to depend on #{constant_source_package_name}?" team_to_work_with = constant_source_package_ownership_info.owning_team ? constant_source_package_ownership_info.markdown_link_to_github_members_no_tag : 'the pack owner' privacy_violation_message = "- Does API in #{constant_source_package.name}/public support this use case?\n - If not, can we work with #{team_to_work_with} to create and use a public API?\n - If `#{constant_name}` should already be public, try `bin/packs make_public #{constant_location}`." if violation_types.include?(::DangerPackwerk::DEPENDENCY_VIOLATION_TYPE) && violation_types.include?(::DangerPackwerk::PRIVACY_VIOLATION_TYPE) <<~MESSAGE **Packwerk Violation** - Type: Privacy :lock: + Dependency :knot: - Constant: [`#{constant_name}`](#{repo_link}/blob/main/#{constant_location}) - Owning pack: #{constant_source_package_name} #{constant_source_package_ownership_info.ownership_copy}
Quick suggestions :bulb: #{disclaimer} #{referencing_code_in_right_pack} #{referenced_code_in_right_pack} #{dependency_violation_message} #{privacy_violation_message}
_#{@custom_help_message}_ MESSAGE elsif violation_types.include?(::DangerPackwerk::DEPENDENCY_VIOLATION_TYPE) <<~MESSAGE **Packwerk Violation** - Type: Dependency :knot: - Constant: [`#{constant_name}`](#{repo_link}/blob/main/#{constant_location}) - Owning pack: #{constant_source_package_name} #{constant_source_package_ownership_info.ownership_copy}
Quick suggestions :bulb: #{disclaimer} #{referencing_code_in_right_pack} #{referenced_code_in_right_pack} #{dependency_violation_message}
_#{@custom_help_message}_ MESSAGE else # violation_types.include?(::DangerPackwerk::PRIVACY_VIOLATION_TYPE) <<~MESSAGE **Packwerk Violation** - Type: Privacy :lock: - Constant: [`#{constant_name}`](#{repo_link}/blob/main/#{constant_location}) - Owning pack: #{constant_source_package_name} #{constant_source_package_ownership_info.ownership_copy}
Quick suggestions :bulb: #{disclaimer} #{referencing_code_in_right_pack} #{referenced_code_in_right_pack} #{privacy_violation_message}
_#{@custom_help_message}_ MESSAGE end end end end end