lib/xcpretty/parser.rb in xcpretty-0.1.4 vs lib/xcpretty/parser.rb in xcpretty-0.1.5

- old
+ new

@@ -14,14 +14,10 @@ BUILD_TARGET_MATCHER = /^=== BUILD TARGET\s(.*)\sOF PROJECT\s(.*)\sWITH.*CONFIGURATION\s(.*)\s===/ # @regex Nothing returned here for now CHECK_DEPENDENCIES_MATCHER = /^Check dependencies/ - # @regex Captured groups - # $1 = whole error - CLANG_ERROR_MATCHER = /^(clang: error:.*)$/ - # @regex Nothing returned here for now CLEAN_REMOVE_MATCHER = /^Clean.Remove/ # @regex Captured groups # $1 target @@ -36,23 +32,17 @@ # @regex Captured groups # $1 = file CODESIGN_FRAMEWORK_MATCHER = /^CodeSign\s((?:\\ |[^ ])*.framework)\/Versions/ # @regex Captured groups - # $1 = whole error - CODESIGN_ERROR_MATCHER = /^(Code\s?Sign error:.*)$/ - - # @regex Captured groups # $1 file_path # $2 file_name (e.g. KWNull.m) COMPILE_MATCHER = /^CompileC\s.*\s(.*\/(.*\.(?:m|mm|c|cc|cpp|cxx)))\s.*/ # @regex Captured groups - # $1 = file_path - # $2 = file_name - # $3 = reason - COMPILE_ERROR_MATCHER = /^(\/.+\/(.*):.*:.*):(?:\sfatal)?\serror:\s(.*)$/ + # $1 compiler_command + COMPILE_COMMAND_MATCHER = /^\s*(.*\/usr\/bin\/clang\s.*\.o)$/ # @regex Captured groups # $1 file_path # $2 file_name (e.g. MainMenu.xib) COMPILE_XIB_MATCHER = /^CompileXIB\s(.*\/(.*\.xib))/ @@ -64,14 +54,10 @@ # @regex Captured groups # $1 resource CPRESOURCE_MATCHER = /^CpResource\s(.*)\s\// # @regex Captured groups - # $1 cursor (with whitespaces and tildes) - CURSOR_MATCHER = /^([\s~]*\^[\s~]*)$/ - - # @regex Captured groups # EXECUTED_MATCHER = /^\s*Executed/ # @regex Captured groups # $1 = file @@ -79,31 +65,18 @@ # $3 = test_case # $4 = reason FAILING_TEST_MATCHER = /^\s*(.+:\d+):\serror:\s[\+\-]\[(.*)\s(.*)\]\s:(?:\s'.*'\s\[FAILED\],)?\s(.*)/ # @regex Captured groups - # $1 = whole error. - # it varies a lot, not sure if it makes sense to catch everything separately - FATAL_ERROR_MATCHER = /^(fatal error:.*)$/ - - # @regex Captured groups # $1 = dsym GENERATE_DSYM_MATCHER = /^GenerateDSYMFile \/.*\/(.*\.dSYM)/ # @regex Captured groups # $1 = library LIBTOOL_MATCHER = /^Libtool.*\/(.*\.a)/ # @regex Captured groups - # $1 = whole error - LD_ERROR_MATCHER = /^(ld:.*not found for.*)/ - - # @regex Captured groups - # $1 reason - LINKER_FAILURE_MATCHER = /^(Undefined symbols for architecture .*):$/ - - # @regex Captured groups # $1 = target # $2 = build_variants (normal, profile, debug) # $3 = architecture LINKING_MATCHER = /^Ld \/.*\/(.*) (.*) (.*)$/ @@ -121,13 +94,10 @@ # @regex Captured groups # $1 = script_name PHASE_SCRIPT_EXECUTION_MATCHER = /^PhaseScriptExecution\s(.*)\s\// # @regex Captured groups - PODS_ERROR_MATCHER = /^error:\s(.*)/ - - # @regex Captured groups # $1 = file PROCESS_PCH_MATCHER = /^ProcessPCH\s.*\s(.*.pch)/ # @regex Captured groups # $1 = file @@ -140,14 +110,10 @@ # @regex Captured groups # $1 = file PROCESS_INFO_PLIST_MATCHER = /^ProcessInfoPlistFile\s.*\.plist\s(.*\/+(.*\.plist))/ # @regex Captured groups - # $1 = reference - SYMBOL_REFERENCED_FROM_MATCHER = /\s+"(.*)", referenced from:$/ - - # @regex Captured groups # $1 = suite # $2 = time TESTS_RUN_COMPLETION_MATCHER = /^\s*Test Suite '(?:.*\/)?(.*[ox]ctest.*)' finished at (.*)/ # @regex Captured groups @@ -165,15 +131,69 @@ # @regex Captured groups # $1 file_path # $2 file_name TOUCH_MATCHER = /^Touch\s(.*\/([\w+\.]+))/ + + module Errors + # @regex Captured groups + # $1 = whole error + CLANG_ERROR_MATCHER = /^(clang: error:.*)$/ + + # @regex Captured groups + # $1 = whole error + CODESIGN_ERROR_MATCHER = /^(Code\s?Sign error:.*)$/ + + # @regex Captured groups + # $1 = file_path + # $2 = file_name + # $3 = reason + COMPILE_ERROR_MATCHER = /^(\/.+\/(.*):.*:.*):(?:\sfatal)?\serror:\s(.*)$/ + + # @regex Captured groups + # $1 cursor (with whitespaces and tildes) + CURSOR_MATCHER = /^([\s~]*\^[\s~]*)$/ + + # @regex Captured groups + # $1 = whole error. + # it varies a lot, not sure if it makes sense to catch everything separately + FATAL_ERROR_MATCHER = /^(fatal error:.*)$/ + + # @regex Captured groups + # $1 = whole error + LD_ERROR_MATCHER = /^(ld:.*not found for.*)/ + + # @regex Captured groups + # $1 file path + LINKER_DUPLICATE_SYMBOLS_LOCATION_MATCHER = /^\s+(\/.*\.o[\)]?)$/ + + # @regex Captured groups + # $1 reason + LINKER_DUPLICATE_SYMBOLS_MATCHER = /^(duplicate symbol .*):$/ + + # @regex Captured groups + # $1 symbol location + LINKER_UNDEFINED_SYMBOL_LOCATION_MATCHER = /^(.* in .*\.o)$/ + + # @regex Captured groups + # $1 reason + LINKER_UNDEFINED_SYMBOLS_MATCHER = /^(Undefined symbols for architecture .*):$/ + + # @regex Captured groups + PODS_ERROR_MATCHER = /^error:\s(.*)/ + + # @regex Captured groups + # $1 = reference + SYMBOL_REFERENCED_FROM_MATCHER = /\s+"(.*)", referenced from:$/ + end end class Parser include Matchers + include Matchers::Errors + attr_reader :formatter def initialize(formatter) @formatter = formatter end @@ -182,11 +202,12 @@ update_test_state(text) update_error_state(text) update_linker_failure_state(text) return format_compile_error if should_format_error? - return format_linker_failure if should_format_linker_failure? + return format_undefined_symbols if should_format_undefined_symbols? + return format_duplicate_symbols if should_format_duplicate_symbols? case text when ANALYZE_MATCHER formatter.format_analyze($2, $1) when BUILD_TARGET_MATCHER @@ -207,10 +228,12 @@ formatter.format_codesign($1) when CODESIGN_ERROR_MATCHER formatter.format_error($1) when COMPILE_MATCHER formatter.format_compile($2, $1) + when COMPILE_COMMAND_MATCHER + formatter.format_compile_command($1) when COMPILE_XIB_MATCHER formatter.format_compile_xib($2, $1) when CPRESOURCE_MATCHER formatter.format_cpresource($1) when EXECUTED_MATCHER @@ -287,38 +310,50 @@ current_error[:line] = text.chomp end end def update_linker_failure_state(text) - if text =~ LINKER_FAILURE_MATCHER - @formatting_linker_error = true + if text =~ LINKER_UNDEFINED_SYMBOLS_MATCHER || + text =~ LINKER_DUPLICATE_SYMBOLS_MATCHER + current_linker_failure[:message] = $1 - elsif text =~ SYMBOL_REFERENCED_FROM_MATCHER + @formatting_linker_failure = true + end + return unless @formatting_linker_failure + + case text + when SYMBOL_REFERENCED_FROM_MATCHER current_linker_failure[:symbol] = $1 - elsif @formatting_linker_error + when LINKER_UNDEFINED_SYMBOL_LOCATION_MATCHER current_linker_failure[:reference] = text.strip - @formatting_linker_error = false + when LINKER_DUPLICATE_SYMBOLS_LOCATION_MATCHER + current_linker_failure[:files] << $1 end end # TODO: clean up the mess around all this def should_format_error? current_error[:reason] && current_error[:cursor] && current_error[:line] end - def should_format_linker_failure? + def should_format_undefined_symbols? current_linker_failure[:message] && current_linker_failure[:symbol] && current_linker_failure[:reference] end + def should_format_duplicate_symbols? + current_linker_failure[:message] && + current_linker_failure[:files].count > 1 + end + def current_error @current_error ||= {} end def current_linker_failure - @linker_failure ||= {} + @linker_failure ||= { :files => [] } end def format_compile_error error = current_error.dup @current_error = {} @@ -327,15 +362,31 @@ error[:reason], error[:line], error[:cursor]) end - def format_linker_failure - failure = current_linker_failure.dup - @linker_failure = {} - formatter.format_linker_failure(failure[:message], - failure[:symbol], - failure[:reference]) + def format_undefined_symbols + result = formatter.format_undefined_symbols( + current_linker_failure[:message], + current_linker_failure[:symbol], + current_linker_failure[:reference] + ) + reset_linker_format_state + result + end + + def format_duplicate_symbols + result = formatter.format_duplicate_symbols( + current_linker_failure[:message], + current_linker_failure[:files] + ) + reset_linker_format_state + result + end + + def reset_linker_format_state + @linker_failure = nil + @formatting_linker_failure = false end def store_failure(file, test_suite, test_case, reason) failures_per_suite[test_suite] ||= [] failures_per_suite[test_suite] << {