def parse_output_messages_and_show(view, msg, base_dir, exit_code, stderr): '''Parse errors and display resulting errors''' # The process has terminated; parse and display the output: parsed_messages = ParseOutput.parse_output_messages(view, base_dir, stderr) # The unparseable part (for other errors) unparsable = Regexes.OUTPUT_REGEX.sub('', stderr).strip() # Set global error list ParseOutput.set_global_error_messages(parsed_messages) # If we couldn't parse any messages, just show the stderr # Otherwise the parsed errors and the unparsable stderr remainder outputs = [] if parsed_messages: outputs += [ParseOutput.format_output_messages(parsed_messages)] if unparsable: outputs += ['', ''] if unparsable: outputs += ["Collected output:\n", unparsable] ParseOutput.show_output_result_text(view, msg, '\n'.join(outputs), exit_code, base_dir) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(parsed_messages), 0)
def on_autofix(self, corrections): output_messages = [ ParseOutput.OutputMessage( m['source']['file'], HsResultParse.parse_region(m['region']).to_zero_based(), m['level'].capitalize() + ': ' + m['note']['message'].replace('\n', '\n '), m['level']) for m in self.messages ] self.corrections = corrections for corr in self.corrections: corr.message_region.to_zero_based() self.corrections_dict = dict( ((os.path.normpath(c.file), c.message_region.start.line, c.message_region.start.column), c) for c in self.corrections) for omsg in output_messages: okey = (os.path.normpath(omsg.filename), omsg.region.start.line, omsg.region.start.column) if okey in self.corrections_dict: omsg.correction = self.corrections_dict[okey] ParseOutput.set_global_error_messages(output_messages) output_text = ParseOutput.format_output_messages(output_messages) if Settings.PLUGIN.show_error_window: sublime.set_timeout(lambda: ParseOutput.write_output(self.view, output_text, Common.get_cabal_project_dir_of_file(self.filename) or \ os.path.dirname(self.filename), panel_display=not self.fly_mode and len(output_messages)), 0) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(output_messages), 0)
def wait_ghcmod_and_parse(view, filename, msg, cmds_with_args, alter_messages_cb): sublime.set_timeout(lambda: ParseOutput.hide_output(view), 0) parsed_messages = [] file_dir = os.path.dirname(filename) all_cmds_successful = True all_cmds_outputs = [] for (cmd, args) in cmds_with_args: stdout = GHCIMod.call_ghcmod_and_wait(args, filename) # stdout contains NULL as line endings within one message # error_output_regex using indents to determine one message scope # Replace NULLs to indents out = stdout.replace('\0', '\n ') success = len(out.strip()) == 0 if not success: all_cmds_outputs.append(out) Logging.log( u"ghc-mod %s didn't exit with success on '%s'" % (u' '.join(cmd), filename), Logging.LOG_ERROR) all_cmds_successful &= success for parsed in ParseOutput.parse_output_messages(view, file_dir, out): parsed_messages.append((cmd, parsed)) if alter_messages_cb: alter_messages_cb(parsed_messages) concated_messages = [m[1] for m in parsed_messages] # Set global error list ParseOutput.set_global_error_messages(concated_messages) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(concated_messages), 0) output_text = (ParseOutput.format_output_messages(concated_messages) if parsed_messages else '\n'.join(all_cmds_outputs)) exit_code = 0 if all_cmds_successful else 1 ParseOutput.show_output_result_text(view, msg, output_text, exit_code, file_dir)
def on_autofix(self, corrections): # Oh, this looks pretty ugly. But, list comprehensions are supposedly faster than loops. And since this is # is supporting Haskell, why not use the functional approach? :-) output_messages = [ParseOutput.OutputMessage(msg.get('source', {}).get('file', '<no file/command line/OPTIONS_GHC>'), HsResultParse.parse_region(msg.get('region')).to_zero_based() \ if msg.get('region') is not None else Symbols.Region(0), msg.get('level', 'uncategorized').capitalize() + ': ' + \ msg.get('note', {}).get('message', '').replace('\n', '\n '), msg.get('level', 'uncategorized')) for msg in self.msgs] # Hack alert: Region and Position.to_zero_based() return the original object (self) after updating it. 'and' returns the # right hand side, which is never None or a false value. self.corrections_dict = dict( ((os.path.normpath(c.file), c.message_region.start.line, c.message_region.start.column), c) for c in [ corr.message_region.to_zero_based() and corr for corr in corrections or [] ]) for omsg in output_messages: okey = (os.path.normpath(omsg.filename), omsg.region.start.line, omsg.region.start.column) if okey in self.corrections_dict: omsg.correction = self.corrections_dict[okey] ParseOutput.set_global_error_messages(output_messages) output_text = ParseOutput.format_output_messages(output_messages) if Settings.PLUGIN.show_error_window: cabal_proj_dir = Common.get_cabal_project_dir_of_file( self.filename) or os.path.dirname(self.filename) panel_display = not self.fly_mode and output_messages sublime.set_timeout( lambda: ParseOutput.write_output( self.view, output_text, cabal_proj_dir, panel_display), 0) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(output_messages), 0)
def wait_for_chain_to_complete(self, view, cabal_project_dir, msg, cmds, on_done): '''Chains several commands, wait for them to complete, then parse and display the resulting errors.''' # First hide error panel to show that something is going on sublime.set_timeout(lambda: hide_output(view), 0) # run and wait commands, fail on first fail # exit_code has scope outside of the loop # stdout = '' collected_out = [] exit_code = 0 output_log = Common.output_panel( view.window(), '', panel_name=BUILD_LOG_PANEL_NAME, panel_display=Settings.PLUGIN.show_output_window) for cmd in cmds: Common.output_text(output_log, ' '.join(cmd) + '...\n') # Don't tie stderr to stdout, since we're interested in the error messages out = OutputCollector.OutputCollector(output_log, cmd, cwd=cabal_project_dir) exit_code, cmd_out = out.wait() collected_out.append(cmd_out) # Bail if the command failed... if exit_code != 0: break if collected_out or exit_code == 0: # We're going to show the errors in the output panel... Common.hide_panel(view.window(), panel_name=BUILD_LOG_PANEL_NAME) # Notify UI thread that commands are done sublime.set_timeout(on_done, 0) the_stderr = ''.join(collected_out) # The process has terminated; parse and display the output: parsed_messages = ParseOutput.parse_output_messages( view, cabal_project_dir, the_stderr) # The unparseable part (for other errors) unparsable = Regexes.OUTPUT_REGEX.sub('', the_stderr).strip() # Set global error list ParseOutput.set_global_error_messages(parsed_messages) # If we couldn't parse any messages, just show the stderr # Otherwise the parsed errors and the unparsable stderr remainder outputs = [] if parsed_messages: outputs += [ParseOutput.format_output_messages(parsed_messages)] if unparsable: outputs += ['', ''] if unparsable: outputs += ["Collected output:\n", unparsable] ParseOutput.show_output_result_text(view, msg, '\n'.join(outputs), exit_code, cabal_project_dir) sublime.set_timeout( lambda: ParseOutput.mark_messages_in_views(parsed_messages), 0)