Chris@0: ($:.unshift '../..'; require 'coderay') unless defined? CodeRay Chris@0: module CodeRay Chris@0: module Encoders Chris@0: Chris@0: # Counts the LoC (Lines of Code). Returns an Integer >= 0. Chris@0: # Chris@0: # Alias: :loc Chris@0: # Chris@0: # Everything that is not comment, markup, doctype/shebang, or an empty line, Chris@0: # is considered to be code. Chris@0: # Chris@0: # For example, Chris@0: # * HTML files not containing JavaScript have 0 LoC Chris@0: # * in a Java class without comments, LoC is the number of non-empty lines Chris@0: # Chris@0: # A Scanner class should define the token kinds that are not code in the Chris@0: # KINDS_NOT_LOC constant, which defaults to [:comment, :doctype]. Chris@0: class LinesOfCode < Encoder Chris@0: Chris@0: register_for :lines_of_code Chris@0: Chris@0: NON_EMPTY_LINE = /^\s*\S.*$/ Chris@0: Chris@0: def compile tokens, options Chris@0: if scanner = tokens.scanner Chris@0: kinds_not_loc = scanner.class::KINDS_NOT_LOC Chris@0: else Chris@0: warn ArgumentError, 'Tokens have no scanner.' if $VERBOSE Chris@0: kinds_not_loc = CodeRay::Scanners::Scanner::KINDS_NOT_LOC Chris@0: end Chris@0: code = tokens.token_class_filter :exclude => kinds_not_loc Chris@0: @loc = code.text.scan(NON_EMPTY_LINE).size Chris@0: end Chris@0: Chris@0: def finish options Chris@0: @loc Chris@0: end Chris@0: Chris@0: end Chris@0: Chris@0: end Chris@0: end Chris@0: Chris@0: if $0 == __FILE__ Chris@0: $VERBOSE = true Chris@0: $: << File.join(File.dirname(__FILE__), '..') Chris@0: eval DATA.read, nil, $0, __LINE__ + 4 Chris@0: end Chris@0: Chris@0: __END__ Chris@0: require 'test/unit' Chris@0: Chris@0: class LinesOfCodeTest < Test::Unit::TestCase Chris@0: Chris@0: def test_creation Chris@0: assert CodeRay::Encoders::LinesOfCode < CodeRay::Encoders::Encoder Chris@0: filter = nil Chris@0: assert_nothing_raised do Chris@0: filter = CodeRay.encoder :loc Chris@0: end Chris@0: assert_kind_of CodeRay::Encoders::LinesOfCode, filter Chris@0: assert_nothing_raised do Chris@0: filter = CodeRay.encoder :lines_of_code Chris@0: end Chris@0: assert_kind_of CodeRay::Encoders::LinesOfCode, filter Chris@0: end Chris@0: Chris@0: def test_lines_of_code Chris@0: tokens = CodeRay.scan <<-RUBY, :ruby Chris@0: #!/usr/bin/env ruby Chris@0: Chris@0: # a minimal Ruby program Chris@0: puts "Hello world!" Chris@0: RUBY Chris@0: assert_equal 1, CodeRay::Encoders::LinesOfCode.new.encode_tokens(tokens) Chris@0: assert_equal 1, tokens.lines_of_code Chris@0: assert_equal 1, tokens.loc Chris@0: end Chris@0: Chris@0: def test_filtering_block_tokens Chris@0: tokens = CodeRay::Tokens.new Chris@0: tokens << ["Hello\n", :world] Chris@0: tokens << ["Hello\n", :space] Chris@0: tokens << ["Hello\n", :comment] Chris@0: assert_equal 2, CodeRay::Encoders::LinesOfCode.new.encode_tokens(tokens) Chris@0: assert_equal 2, tokens.lines_of_code Chris@0: assert_equal 2, tokens.loc Chris@0: end Chris@0: Chris@0: end