Class: PmdTester::RuleSetBuilder

Inherits:
Object
  • Object
show all
Includes:
PmdTester
Defined in:
lib/pmdtester/builders/rule_set_builder.rb

Overview

This class is responsible for generation dynamic configuration according to the difference between base and patch branch of Pmd. Attention: we only consider java rulesets now.

Constant Summary collapse

PATH_TO_DYNAMIC_CONFIG =
'target/dynamic-config.xml'
NO_RULES_CHANGED_MESSAGE =
'No regression tested rules have been changed!'

Constants included from PmdTester

BASE, PATCH, PR_NUM_ENV_VAR, VERSION

Instance Method Summary collapse

Methods included from PmdTester

#logger, logger

Constructor Details

#initialize(options) ⇒ RuleSetBuilder

Returns a new instance of RuleSetBuilder.



15
16
17
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 15

def initialize(options)
  @options = options
end

Instance Method Details

#build?Boolean

Creates a dynamic ruleset based on the changed sources. Returns true, when rules are affected by the changed sources. Returns false, when no rules are affected and regression tester can be skipped.

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 24

def build?
  languages = determine_languages
  filenames = diff_filenames(languages)
  run_required, rule_refs = get_rule_refs(filenames)
  if run_required
    output_filter_set(rule_refs)
    build_config_file(rule_refs)
    logger.debug "Dynamic configuration: #{[rule_refs]}"
  else
    logger.info NO_RULES_CHANGED_MESSAGE
  end
  run_required
end

#build_config_file(rule_refs) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 90

def build_config_file(rule_refs)
  if rule_refs.empty?
    logger.debug 'All rules are used. Not generating a dynamic ruleset.'
    logger.debug "Using the configured/default ruleset base_config=#{@options.base_config} "\
                 "patch_config=#{@options.patch_config}"
    return
  end

  write_dynamic_file(rule_refs)
end

#calculate_filter_setObject



38
39
40
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 38

def calculate_filter_set
  output_filter_set([])
end

#get_rule_refs(filenames) ⇒ Object

Determines the rules or category rulesets, that are potentially affected by the change. Returns an empty set, if all rules are affected and there is no filtering possible or if no rules are affected. Whether to run the regression test is returned as an additional boolean flag.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 73

def get_rule_refs(filenames)
  run_required, categories, rules = determine_categories_rules(filenames)
  logger.debug "Regression test required: #{run_required}"
  logger.debug "Categories: #{categories}"
  logger.debug "Rules: #{rules}"

  # filter out all individual rules that are already covered by a complete category
  categories.each do |cat|
    rules.delete_if { |e| e.start_with?(cat) }
  end

  refs = Set[]
  refs.merge(categories)
  refs.merge(rules)
  [run_required, refs]
end

#output_filter_set(rule_refs) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 42

def output_filter_set(rule_refs)
  if rule_refs.empty?
    if @options.mode == Options::ONLINE && @options.filter_with_patch_config
      @options.filter_set = Set[]
      doc = File.open(@options.patch_config) { |f| Nokogiri::XML(f) }
      rules = doc.css('ruleset rule')
      rules.each do |r|
        ref = r.attributes['ref'].content
        ref.delete_prefix!('category/')
        @options.filter_set.add(ref)
      end

      logger.info "Using filter based on patch config #{@options.patch_config}: " \
                   "#{@options.filter_set}"
    else
      # if `rule_refs` is empty, then no filter can be used when comparing to the baseline
      logger.info 'No filter when comparing patch to baseline'
      @options.filter_set = nil
    end
  else
    logger.info "Filter is now #{rule_refs}"
    @options.filter_set = rule_refs
  end
end

#write_dynamic_file(rule_refs) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/pmdtester/builders/rule_set_builder.rb', line 101

def write_dynamic_file(rule_refs)
  logger.debug "Generating dynamic configuration for: #{[rule_refs]}"
  builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
    xml.ruleset('xmlns' => 'http://pmd.sourceforge.net/ruleset/2.0.0',
                'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                'xsi:schemaLocation' => 'http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd',
                'name' => 'Dynamic PmdTester Ruleset') do
      xml.description 'The ruleset generated by PmdTester dynamically'
      rule_refs.each do |entry|
        xml.rule('ref' => "category/#{entry}")
      end
    end
  end
  doc = builder.to_xml(indent: 4, encoding: 'UTF-8')
  File.open(PATH_TO_DYNAMIC_CONFIG, 'w') do |x|
    x << doc.gsub(/\n\s+\n/, "\n")
  end
  @options.base_config = PATH_TO_DYNAMIC_CONFIG
  @options.patch_config = PATH_TO_DYNAMIC_CONFIG
end