Changeset 11653d2154f46ac5076effeccc5e8a9db11cbdc8
- Timestamp:
- 03/14/2008 02:35:12 PM (10 months ago)
- git-parent:
[1311be2abb56f15be166183c6135216546c35833], [629f9cab359caeb39a81c40233f3369d904a7629]
- Files:
-
- ext/ohcount_native/generator.rb (modified) (2 diffs)
- ext/ohcount_native/ruby_binding.c (modified) (2 diffs)
- lib/ohcount/detector.rb (modified) (7 diffs)
- lib/ohcount/detector.rb.orig (added)
- lib/ohcount/sloc_info.rb (modified) (1 diff)
- test/detect_files/uses_cpp_headers.h (added)
- test/detect_files/uses_cpp_keywords.h (added)
- test/detect_files/uses_cpp_stdlib_headers.h (added)
- test/detect_files/uses_no_cpp.h (added)
- test/expected_dir/c1.c/c/blanks (added)
- test/expected_dir/c1.c/c/code (added)
- test/expected_dir/c1.c/c/comment (added)
- test/expected_dir/c1.c/cncpp/blanks (deleted)
- test/expected_dir/c1.c/cncpp/code (deleted)
- test/expected_dir/c1.c/cncpp/comment (deleted)
- test/expected_dir/c2.h.in/c/blanks (added)
- test/expected_dir/c2.h.in/c/code (added)
- test/expected_dir/c2.h.in/c/comment (added)
- test/expected_dir/c2.h.in/cncpp/blanks (deleted)
- test/expected_dir/c2.h.in/cncpp/code (deleted)
- test/expected_dir/c2.h.in/cncpp/comment (deleted)
- test/expected_dir/c_str.c/c/blanks (added)
- test/expected_dir/c_str.c/c/code (added)
- test/expected_dir/c_str.c/c/comment (added)
- test/expected_dir/c_str.c/cncpp/blanks (deleted)
- test/expected_dir/c_str.c/cncpp/code (deleted)
- test/expected_dir/c_str.c/cncpp/comment (deleted)
- test/unit/c_test.rb (modified) (1 diff)
- test/unit/detector_test.rb (modified) (2 diffs)
- test/unit/diff_test.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
ext/ohcount_native/generator.rb
r1311be2 r11653d2 27 27 boo = PythonMonoglot.new("boo") 28 28 clearsilver = CMonoglot.new("clearsilver", '#', nil, true, true) 29 cncpp = CMonoglot.new("cncpp", '//', [e('/*'), e('*/')], true, true) 30 csharp = CMonoglot.new("csharp", '//', [e('/*'), e('*/')], true, true) 29 c = CMonoglot.new("c", '//', [e('/*'), e('*/')], true, true) 30 cpp = CMonoglot.new("cpp", '//', [e('/*'), e('*/')], true, true) 31 csharp = CMonoglot.new("csharp", '//', [e('/*'), e('*/')], true, false) 31 32 css = CMonoglot.new("css", nil, [e('/*'), e('*/')], false, false) 32 33 dylan = CMonoglot.new("dylan", '//', nil, true, false) … … 74 75 boo , 75 76 clearsilver , 76 cncpp , 77 c , 78 cpp , 77 79 csharp , 78 80 css , ext/ohcount_native/ruby_binding.c
r101d05d r629f9ca 105 105 * # Print each line to the console, labeled as code or comments 106 106 * buffer = File.read("helloworld.c") 107 * results = Ohcount::parse(buffer, 'c ncpp') do |language, semantic, line|107 * results = Ohcount::parse(buffer, 'c') do |language, semantic, line| 108 108 * puts "#{semantic.to_s} #{line}" 109 109 * end … … 113 113 * # Print total lines of code 114 114 * buffer = File.read("helloworld.c") 115 * results = Ohcount::parse(buffer, 'c ncpp')115 * results = Ohcount::parse(buffer, 'c') 116 116 * results.each do |result| 117 117 * puts "Lines of #{result.name} code: #{ result.code.split("\n").size }" lib/ohcount/detector.rb
r1311be2 r11653d2 39 39 # Example: 40 40 # 41 # # List all C /C++files in the 'src' directory41 # # List all C files in the 'src' directory 42 42 # Dir.entries("src").each do |file| 43 43 # context = Ohcount::SimpleFileContext.new(file) 44 44 # polyglot = Ohcount::Detector.detect(context) 45 # puts "#{file}" if polyglot == 'c ncpp'45 # puts "#{file}" if polyglot == 'c' 46 46 # end 47 47 # 48 48 def self.detect(file_context) 49 49 # start with extension 50 polyglot = EXTENSION_MAP[File.extname(file_context.filename).downcase] 50 polyglot = EXTENSION_MAP[File.extname(file_context.filename)] 51 polyglot = EXTENSION_MAP[File.extname(file_context.filename).downcase] unless polyglot 51 52 case polyglot 52 53 when String … … 107 108 '.bat' => "bat", 108 109 '.boo' => "boo", 109 '.c' => "cncpp", 110 '.cc' => "cncpp", 111 '.cpp' => "cncpp", 110 '.c' => "c", 111 '.C' => "cpp", 112 '.cc' => "cpp", 113 '.cpp' => "cpp", 112 114 '.css' => "css", 113 '.c++' => "c ncpp",114 '.cxx' => "c ncpp",115 '.c++' => "cpp", 116 '.cxx' => "cpp", 115 117 '.el' => "emacslisp", 116 118 # '.cbl' => "cobol", … … 133 135 '.groovy'=> "groovy", 134 136 '.h' => :disambiguate_h_header, 135 '.hpp' => "cncpp", 136 '.h++' => "cncpp", 137 '.H' => "cpp", 138 '.hpp' => "cpp", 139 '.h++' => "cpp", 137 140 '.hs' => "haskell", 138 '.hxx' => "c ncpp",139 '.hh' => "c ncpp",141 '.hxx' => "cpp", 142 '.hh' => "cpp", 140 143 '.hrl' => "erlang", 141 144 '.htm' => "html", … … 226 229 end 227 230 228 # For *.h files, differentiates C /C++ fromObjective-C.231 # For *.h files, differentiates C, C++ and Objective-C. 229 232 # 230 233 # This is done with a weighted heuristic that 231 234 # scans the *.h file contents for Objective-C keywords, 232 # and also checks for the presence of matching *.m files. 235 # C++ keywords and C++ headers, and also checks for the 236 # presence of matching *.m files. 233 237 def self.disambiguate_h_header(file_context) 234 238 buffer = file_context.contents 235 236 objective_c = 0237 239 238 240 # could it be realistically be objective_c ? are there any .m files at all? … … 243 245 file_context.filenames.contains_pike_or_pmod = file_context.filenames.select { |a| a =~ /\.p(ike|mod)$/ }.any? 244 246 end 245 unless file_context.filenames.contains_pike_or_pmod246 return 'cncpp' unless file_context.filenames.contains_m247 end248 247 249 248 if file_context.filenames.contains_m … … 256 255 # ok - it just might be objective_c, let's check contents for objective_c signatures 257 256 objective_c_signatures = /(^\s*@interface)|(^\s*@end)/ 258 objective_c += lines_matching(buffer, objective_c_signatures) 259 257 objective_c = lines_matching(buffer, objective_c_signatures) 260 258 return 'objective_c' if objective_c > 1 261 259 end … … 268 266 end 269 267 270 271 return 'cncpp' 268 disambiguate_c_cpp(buffer) 269 end 270 271 # A map of headers that indicate C++, but that do not have C++-specific file 272 # extensions. This list is made from the Standard, plus Technical Report 1. 273 CPP_HEADERS_MAP = %w[ 274 algorithm 275 array 276 bitset 277 cassert 278 ccomplex 279 cctype 280 cerrno 281 cfenv 282 cfloat 283 cinttypes 284 ciso646 285 climits 286 clocale 287 cmath 288 csetjmp 289 csignal 290 cstdarg 291 cstdbool 292 cstddef 293 cstdint 294 cstdio 295 cstdlib 296 cstring 297 ctgmath 298 ctime 299 cwchar 300 cwctype 301 deque 302 exception 303 fstream 304 functional 305 iomanip 306 ios 307 iosfwd 308 iostream 309 istream 310 iterator 311 limits 312 list 313 locale 314 map 315 memory 316 new 317 numeric 318 ostream 319 queue 320 random 321 regex 322 set 323 sstream 324 stack 325 stdexcept 326 streambuf 327 string 328 system_error 329 tuple 330 type_traits 331 typeinfo 332 unordered_map 333 unordered_set 334 utility 335 valarray 336 vector 337 tr1/array 338 tr1/ccomplex 339 tr1/cctype 340 tr1/cfenv 341 tr1/cfloat 342 tr1/cinttypes 343 tr1/climits 344 tr1/cmath 345 tr1/complex 346 tr1/cstdarg 347 tr1/cstdbool 348 tr1/cstdint 349 tr1/cstdio 350 tr1/cstdlib 351 tr1/ctgmath 352 tr1/ctime 353 tr1/cwchar 354 tr1/cwctype 355 tr1/memory 356 tr1/random 357 tr1/regex 358 tr1/tuple 359 tr1/type_traits 360 tr1/unordered_map 361 tr1/unordered_set 362 tr1/utility 363 ].inject({}) { | h, k | h[k] = true ; h } 364 365 # A map of keywords that indicate C++. 366 CPP_KEYWORDS_MAP = %w[ 367 template 368 typename 369 class 370 namespace 371 ].inject({}) { | h, k | h[k] = true ; h } 372 373 # For *.h files that we know aren't Objective-C, differentiates C and C++. 374 # 375 # This is done with a weighted heuristic that 376 # scans the *.h file contents for C++ keywords and C++ headers. 377 def self.disambiguate_c_cpp(buffer) 378 # Look for C++ headers 379 return 'cpp' if extract_c_cpp_headers(buffer).detect do | header | 380 EXTENSION_MAP[File.extname(header)] == 'cpp' or CPP_HEADERS_MAP.include? header 381 end 382 383 # Look for C++ keywords. This could check for comments, but doesn't. 384 return 'cpp' if buffer.find do | line | 385 line.split(/\W/).find do | word | 386 CPP_KEYWORDS_MAP.include? word 387 end 388 end 389 390 # Nothing to suggest C++ 391 'c' 392 end 393 394 # Return a list of files included in a C or C++ source file. 395 def self.extract_c_cpp_headers(buffer) 396 buffer.map do | line | 397 m = line.match(/^#\s*include\s+[<"](.*)[>"]/) and m[1] 398 end.find_all { | a | a } 272 399 end 273 400 lib/ohcount/sloc_info.rb
r16a63b7 r11653d2 45 45 'bat' => {:nice_name => 'DOS batch script' , :category => 0}, 46 46 'boo' => {:nice_name => 'Boo' , :category => 0}, 47 'cncpp' => {:nice_name => 'C/C++' , :category => 0}, 47 'c' => {:nice_name => 'C' , :category => 0}, 48 'cpp' => {:nice_name => 'C++' , :category => 0}, 48 49 'clearsilver' => {:nice_name => 'ClearSilver' , :category => 0}, 49 50 'csharp' => {:nice_name => 'C#' , :category => 0}, test/unit/c_test.rb
rcb242a3 r11653d2 4 4 5 5 def test_comments 6 lb = [Ohcount::LanguageBreakdown.new("c ncpp", "", "//comment", 0)]7 assert_equal lb, Ohcount::parse(" //comment", "c ncpp")6 lb = [Ohcount::LanguageBreakdown.new("c", "", "//comment", 0)] 7 assert_equal lb, Ohcount::parse(" //comment", "c") 8 8 end 9 9 10 10 def test_empty_comments 11 lb = [Ohcount::LanguageBreakdown.new("c ncpp", "","//\n", 0)]12 assert_equal lb, Ohcount::parse(" //\n", "c ncpp")11 lb = [Ohcount::LanguageBreakdown.new("c", "","//\n", 0)] 12 assert_equal lb, Ohcount::parse(" //\n", "c") 13 13 end 14 14 15 15 16 16 def test_block_comment 17 lb = [Ohcount::LanguageBreakdown.new("c ncpp", "","/*c*/", 0)]18 assert_equal lb, Ohcount::parse("/*c*/", "c ncpp")17 lb = [Ohcount::LanguageBreakdown.new("c", "","/*c*/", 0)] 18 assert_equal lb, Ohcount::parse("/*c*/", "c") 19 19 end 20 20 test/unit/detector_test.rb
rac2c8db r629f9ca 38 38 39 39 def test_detect_polyglot 40 assert_equal "cncpp", do_detect("foo.c") 40 assert_equal "c", do_detect("foo.c") 41 assert_equal "c", do_detect("uses_no_cpp.h") 42 assert_equal "cpp", do_detect("uses_cpp_headers.h") 43 assert_equal "cpp", do_detect("uses_cpp_stdlib_headers.h") 44 assert_equal "cpp", do_detect("uses_cpp_keywords.h") 41 45 assert_equal "ruby", do_detect("foo.rb") 42 46 assert_equal "matlab", do_detect("foo_matlab.m", ["foo_matlab.m", "bar.m", "README"]) … … 53 57 54 58 def test_upper_case_extensions 55 assert_equal "c ncpp", do_detect("foo_upper_case.C")59 assert_equal "cpp", do_detect("foo_upper_case.C") 56 60 assert_equal "ruby", do_detect("foo_upper_case.RB") 57 61 end test/unit/diff_test.rb
r101d05d r629f9ca 25 25 sloc_infos = Ohcount.diff_files(src_dir + 'diff2_old.c', src_dir + 'diff2_new.c') 26 26 27 c = Ohcount::SlocInfo.new('c ncpp')27 c = Ohcount::SlocInfo.new('c') 28 28 c.code_added, c.code_removed = [1,1] 29 29 c.comments_added, c.comments_removed = [1,1]