Class: FeatureMap::Private::FeatureMetricsCalculator
- Inherits:
-
Object
- Object
- FeatureMap::Private::FeatureMetricsCalculator
- Defined in:
- lib/feature_map/private/feature_metrics_calculator.rb
Constant Summary collapse
- ABC_SIZE_METRIC =
'abc_size'
- CYCLOMATIC_COMPLEXITY_METRIC =
'cyclomatic_complexity'
- LINES_OF_CODE_METRIC =
'lines_of_code'
- TODO_LOCATIONS_METRIC =
'todo_locations'
- COMPLEXITY_RATIO_METRIC =
'complexity_ratio'
- ENCAPSULATION_RATIO_METRIC =
'encapsulation_ratio'
- SUPPORTED_METRICS =
[ ABC_SIZE_METRIC, CYCLOMATIC_COMPLEXITY_METRIC, LINES_OF_CODE_METRIC, TODO_LOCATIONS_METRIC, COMPLEXITY_RATIO_METRIC, ENCAPSULATION_RATIO_METRIC ].freeze
Class Method Summary collapse
- .calculate_for_feature(file_paths) ⇒ Object
- .calculate_for_file(file_path) ⇒ Object
- .complexity_ratio(aggregate_metrics) ⇒ Object
- .encapsulation_ratio(file_paths, aggregate_metrics) ⇒ Object
Class Method Details
.calculate_for_feature(file_paths) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/feature_map/private/feature_metrics_calculator.rb', line 24 def self.calculate_for_feature(file_paths) metrics = file_paths.map { |file| calculate_for_file(file) } # Handle numeric metrics aggregate_metrics = [ABC_SIZE_METRIC, CYCLOMATIC_COMPLEXITY_METRIC, LINES_OF_CODE_METRIC].each_with_object({}) do |metric_key, agg| agg[metric_key] = metrics.sum { |m| m[metric_key] || 0 } end # Handle additional supported metrics todo_locations = metrics.map { |m| m[TODO_LOCATIONS_METRIC] }.compact.reduce({}, :merge) aggregate_metrics[TODO_LOCATIONS_METRIC] = todo_locations aggregate_metrics[COMPLEXITY_RATIO_METRIC] = complexity_ratio(aggregate_metrics) aggregate_metrics[ENCAPSULATION_RATIO_METRIC] = encapsulation_ratio(file_paths, aggregate_metrics) aggregate_metrics end |
.calculate_for_file(file_path) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/feature_map/private/feature_metrics_calculator.rb', line 41 def self.calculate_for_file(file_path) metrics = { LINES_OF_CODE_METRIC => LinesOfCodeCalculator.new(file_path).calculate, TODO_LOCATIONS_METRIC => TodoInspector.new(file_path).calculate } return metrics unless file_path.end_with?('.rb') file_content = File.read(file_path) source = RuboCop::ProcessedSource.new(file_content, RUBY_VERSION.to_f) return metrics unless source.ast # NOTE: We're using some internal RuboCop classes to calculate complexity metrics # for each file. Doing this tightly couples our functionality with RuboCop, # which does introduce some risk, should RuboCop decide to change the interface # of these classes. That being said, this is a tradeoff we're willing to # make right now. abc_calculator = RuboCop::Cop::Metrics::Utils::AbcSizeCalculator.new(source.ast) cyclomatic_calculator = CyclomaticComplexityCalculator.new(source.ast) metrics.merge( ABC_SIZE_METRIC => abc_calculator.calculate.first.round(2), CYCLOMATIC_COMPLEXITY_METRIC => cyclomatic_calculator.calculate ) end |
.complexity_ratio(aggregate_metrics) ⇒ Object
68 69 70 71 72 |
# File 'lib/feature_map/private/feature_metrics_calculator.rb', line 68 def self.complexity_ratio(aggregate_metrics) return 0.0 if aggregate_metrics[LINES_OF_CODE_METRIC].nil? || aggregate_metrics[CYCLOMATIC_COMPLEXITY_METRIC].nil? || aggregate_metrics[CYCLOMATIC_COMPLEXITY_METRIC].zero? aggregate_metrics[LINES_OF_CODE_METRIC].to_f / aggregate_metrics[CYCLOMATIC_COMPLEXITY_METRIC] end |
.encapsulation_ratio(file_paths, aggregate_metrics) ⇒ Object
74 75 76 77 78 |
# File 'lib/feature_map/private/feature_metrics_calculator.rb', line 74 def self.encapsulation_ratio(file_paths, aggregate_metrics) return 0.0 if file_paths.nil? || aggregate_metrics[LINES_OF_CODE_METRIC].nil? || aggregate_metrics[LINES_OF_CODE_METRIC].zero? file_paths.length.to_f / aggregate_metrics[LINES_OF_CODE_METRIC] end |