def run(self, message): v = OutputPanel('dart.config.check') text = HEADING + '\n' text += ('=' * 80) + '\n' text += 'MESSAGE:\n' text += message + '\n' text += '\n' text += 'CONFIGURATION:\n' text += ('-' * 80) + '\n' text += "editor version: {} ({})".format(sublime.version(), sublime.channel()) text += '\n' text += ('-' * 80) + '\n' text += "os: {} ({})".format(sublime.platform(), sublime.arch()) text += '\n' text += ('-' * 80) + '\n' setts = sublime.load_settings( 'Dart - Plugin Settings.sublime-settings') text += "dart_sdk_path: {}".format(setts.get('dart_sdk_path')) text += '\n' text += '=' * 80 v.write(text) v.show()
def run(self, message): v = OutputPanel('dart.config.check') text = HEADING + '\n' text += ('=' * 80) + '\n' text += 'MESSAGE:\n' text += message + '\n' text += '\n' text += 'CONFIGURATION:\n' text += ('-' * 80) + '\n' text += "editor version: {} ({})".format(sublime.version(), sublime.channel()) text += '\n' text += ('-' * 80) + '\n' text += "os: {} ({})".format(sublime.platform(), sublime.arch()) text += '\n' text += ('-' * 80) + '\n' setts = sublime.load_settings('Dart - Plugin Settings.sublime-settings') text += "dart_sdk_path: {}".format(setts.get('dart_sdk_path')) text += '\n' text += '=' * 80 v.write(text) v.show()
class EditorContext(object): search_id_lock = threading.Lock() # FIXME(guillermooo): This is utterly wrong. This needs to be a singleton. def __init__(self): self._search_id = None self.results_panel = None @property def search_id(self): with EditorContext.search_id_lock: return self._search_id @search_id.setter def search_id(self, value): with EditorContext.search_id_lock: if self._search_id == value: return self.results_panel = OutputPanel('dart.search.results') self.results_panel.set('result_file_regex', r'^\w+\s+-\s+(.*?):(\d+):(\d+)') self._search_id = value @search_id.deleter def search_id(self): with EditorContext.search_id_lock: self._search_id = None def check_token(self, action, token): if action == 'search': if self.search_id is None: return return (token == self.search_id) def append_search_results(self, items): items = list(items) with EditorContext.search_id_lock: if not self.results_panel: return for item in items: self.results_panel.write(item.to_encoded_pos()) self.results_panel.show()
def show_errors(errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' v = sublime.active_window().active_view() # TODO(guillermooo): Use tokens to identify requests:file. if errors.file != v.file_name(): _logger.debug('different view active - aborting') return if len(errors) == 0: clear_ui() return _logger.debug('displaying errors to the user') v.add_regions('dart.infos', list(errors.infos_to_regions(v)), scope='dartlint.mark.info', icon="Packages/Dart/gutter/dartlint-simple-info.png", flags=_flags) v.add_regions('dart.warnings', list(errors.warnings_to_regions(v)), scope='dartlint.mark.warning', icon="Packages/Dart/gutter/dartlint-simple-warning.png", flags=_flags) v.add_regions('dart.errors', list(errors.errors_to_regions(v)), scope='dartlint.mark.error', icon='Packages/Dart/gutter/dartlint-simple-error.png', flags=_flags) # TODO(guillermooo): Add a logger attrib to the OutputPanel. panel = OutputPanel('dart.analyzer') errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) panel.write('\n'.join(set(errors.to_compact_text())))
class EditorContext(object): write_lock = threading.Lock() search_id_lock = threading.Lock() # FIXME(guillermooo): This is utterly wrong. This needs to be a singleton. def __init__(self): self._search_id = None self.results_panel = None self._navigation = None self._errors = [] self._errors_index = -1 @property def search_id(self): with EditorContext.search_id_lock: return self._search_id @search_id.setter def search_id(self, value): with EditorContext.search_id_lock: if self._search_id == value: return self.results_panel = OutputPanel('dart.search.results') self.results_panel.set('result_file_regex', r'^\w+\s+-\s+(.*?):(\d+):(\d+)') self._search_id = value @search_id.deleter def search_id(self): with EditorContext.search_id_lock: self._search_id = None @property def navigation(self): with EditorContext.write_lock: return self._navigation @navigation.setter def navigation(self, value): # TODO(guillermooo): store this data by file with EditorContext.write_lock: self._navigation = value @property def errors(self): with EditorContext.write_lock: return self._errors @errors.setter def errors(self, values): with EditorContext.write_lock: self._errors_index = -1 self._errors = list(values) @property def errors_index(self): with EditorContext.write_lock: return self._errors_index def increment_error_index(self): with EditorContext.write_lock: if self._errors_index == len(self._errors) - 1: raise IndexError('end of errors list') self._errors_index += 1 def decrement_error_index(self): with EditorContext.write_lock: if self._errors_index == 0: raise IndexError('start of errors list') self._errors_index -= 1 def get_current_error(self): return self.errors[self.errors_index] def check_token(self, action, token): if action == 'search': if self.search_id is None: return return (token == self.search_id) def append_search_results(self, items): items = list(items) with EditorContext.search_id_lock: if not self.results_panel: return for item in items: self.results_panel.write(item.to_encoded_pos()) self.results_panel.show()
def __call__(self, errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' view = get_active_view() # TODO(guillermooo): Use tokens to identify requests:file. if not self.compare_paths(errors.file, view.file_name()): _logger.debug('different view active - aborting') return panel = OutputPanel('dart.analyzer') analysis_errors = list(errors.errors) infos, warns, erros = self.group(analysis_errors) if len(infos + warns + erros) == 0: clear_ui() panel.hide() return info_regs = [self.error_to_region(view, item) for item in infos] warn_regs = [self.error_to_region(view, item) for item in warns] errs_regs = [self.error_to_region(view, item) for item in erros] _logger.debug('displaying errors to the user') self.add_regions(view, info_regs, warn_regs, errs_regs) all_sorted = sorted(infos + warns + erros, key=lambda x: x.location.offset) all_errs = (self.to_compact_text(item) for item in all_sorted) # TODO(guillermooo): abstract out the panel stuff into a DartErrorPanel class. panel = OutputPanel('dart.analyzer') # Tried to use .sublime-settings for this, but it won't work well. errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) all_errs = list(all_errs) # Overwrite any previous text in the panel. # We get errors sometimes when writing error lines here. panel.write('\n'.join(all_errs)) # TODO(guillermooo): remove this when .sublime-syntax has been fully # adopted. if sublime.version() >= '3084': panel.view.set_syntax_file( 'Packages/Dart/Support/Analyzer Output.sublime-syntax') else: panel.view.set_syntax_file( 'Packages/Dart/Support/Analyzer Output.tmLanguage') editor_context.errors = all_errs panel.show() try: view.show(view.sel()[0]) except IndexError: pass sublime.status_message("Dart: Errors found")
class DartExecCommand(sublime_plugin.WindowCommand, ProcessListener): def run(self, cmd=None, shell_cmd=None, file_regex="", line_regex="", working_dir="", encoding="utf-8", env={}, quiet=False, kill=False, word_wrap=True, syntax="Packages/Text/Plain text.tmLanguage", preamble='', panel_name='dart.out', # Catches "path" and "shell" **kwargs): if kill: if hasattr(self, 'proc') and self.proc: self.proc.kill() self.proc = None self.append_string(None, "[Cancelled]") return # TODO(guillermooo): We cannot have multiple processes running at the # same time, or processes that use separate output panels. if not hasattr(self, 'out_panel'): # Try not to call get_output_panel until the regexes are assigned self.out_panel = OutputPanel(panel_name) # Default to the current files directory if no working directory was given if (not working_dir and self.window.active_view() and self.window.active_view().file_name()): working_dir = os.path.dirname( self.window.active_view().file_name()) self.out_panel.set("result_file_regex", file_regex) self.out_panel.set("result_line_regex", line_regex) self.out_panel.set("result_base_dir", working_dir) self.out_panel.set("word_wrap", word_wrap) self.out_panel.set("line_numbers", False) self.out_panel.set("gutter", False) self.out_panel.set("scroll_past_end", False) self.out_panel.view.assign_syntax(syntax) self.encoding = encoding self.quiet = quiet self.proc = None if not self.quiet: if shell_cmd: print("Running " + shell_cmd) else: print("Running " + " ".join(cmd)) sublime.status_message("Building") if preamble: self.append_string(self.proc, preamble) show_panel_on_build = sublime.load_settings( "Dart - Plugin Settings.sublime-settings").get("show_panel_on_build", True) if show_panel_on_build: self.out_panel.show() merged_env = env.copy() if self.window.active_view(): user_env = self.window.active_view().settings().get('build_env') if user_env: merged_env.update(user_env) # Change to the working dir, rather than spawning the process with it, # so that emitted working dir relative path names make sense if working_dir: os.chdir(working_dir) self.debug_text = "" if shell_cmd: self.debug_text += "[shell_cmd: " + shell_cmd + "]\n" else: self.debug_text += "[cmd: " + str(cmd) + "]\n" self.debug_text += "[dir: " + str(os.getcwd()) + "]\n" if "PATH" in merged_env: self.debug_text += "[path: " + str(merged_env["PATH"]) + "]" else: self.debug_text += "[path: " + str(os.environ["PATH"]) + "]" try: # Forward kwargs to AsyncProcess self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self, **kwargs) except Exception as e: self.append_string(None, str(e) + "\n") self.append_string(None, self.debug_text + "\n") if not self.quiet: self.append_string(None, "[Finished]") def append_data(self, proc, data): if proc != self.proc: # a second call to exec has been made before the first one # finished, ignore it instead of intermingling the output. if proc: proc.kill() return try: str_ = data.decode(self.encoding) except UnicodeEncodeError: str_ = "[Decode error - output not " + self.encoding + "]\n" proc = None return # Normalize newlines, Sublime Text always uses a single \n separator # in memory. str_ = str_.replace('\r\n', '\n').replace('\r', '\n') self.out_panel.write(str_) def append_string(self, proc, str): self.append_data(proc, str.encode(self.encoding)) def finish(self, proc): if not self.quiet: elapsed = time.time() - proc.start_time exit_code = proc.exit_code() if (exit_code == 0) or (exit_code == None): self.append_string(proc, "[Finished in %.1fs]" % (elapsed)) else: self.append_string(proc, "[Finished in %.1fs with exit code %d]\n" % (elapsed, exit_code)) self.append_string(proc, self.debug_text) if proc != self.proc: return # XXX: What's this for? errs = self.out_panel.view.find_all_results() if len(errs) == 0: sublime.status_message("Build finished") else: sublime.status_message(("Build finished with %d errors") % len(errs)) def on_data(self, proc, data): after(0, functools.partial(self.append_data, proc, data)) def on_finished(self, proc): after(0, functools.partial(self.finish, proc))
def run(self): """Runs forever checking for new linter results and displaying them to the user. """ while True: # Run at intervals. time.sleep(0.250) # We've got results for this buffer. Reset its version count so # the linting cycle can start again. # TODO(guillermooo): It's possible that we'll miss some edits (?). with g_edits_lock: DartLint.edits[self.view.buffer_id()] = 0 lines = self.get_data() if lines is None: continue # TODO(guillermooo): Compose a DartLintOutputPanel from a plain # OutputPanel to abstract all of this away. # Show errors in output panel and enable error navigation via F4. panel = OutputPanel('dart.analyzer') # Capture file name, rowcol and error message information. errors_pattern = r'^\w+\|\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|\d+\|(.+)' panel.set('result_file_regex', errors_pattern) panel.write('\n'.join(lines)) panel.show() pattern = (r'^(?P<severity>\w+)\|(?P<type>\w+)\|(?P<code>\w+)\|' + r'(?P<file_name>.+)\|(?P<line>\d+)\|(?P<col>\d+)\|' + r'(?P<err_length>\d+)\|(?P<message>.+)') msg_pattern_machine = re.compile(pattern) # Collect data needed to generate error messages lint_data = [] lines_out = '' err_count = 0 culp_regions = {} for line in lines: line_out = '' line_data = {} line_groups = msg_pattern_machine.match(line) if line_groups is not None: if line_groups.group('file_name') != self.fileName: # output is for a different file continue line_out = '%s: %s on line %s, col %s: %s\n' % \ (line_groups.group('severity'), line_groups.group('code'), line_groups.group('line'), line_groups.group('col'), line_groups.group('message')) line_data['severity'] = line_groups.group('severity') line_data['col'] = line_groups.group('col') line_data['line'] = line_groups.group('line') line_data['msg'] = line_groups.group('message') line_data['code'] = line_groups.group('code') line_data['type'] = line_groups.group('type') line_data['err_length'] = line_groups.group('err_length') line_data['lint_out'] = line_out line_data['line_pt'] = self.view.text_point( int(line_data['line']) - 1, 0) line_data['point'] = self.view.text_point( int(line_data['line']) - 1, int(line_data['col'])) next_line = self.view.text_point(int(line_data['line']), 0) # Add a region (gutter mark and underline) if int(line_data['err_length']) > 0 and \ int(line_data['point']) + \ (int(line_data['err_length']) - 1) < next_line: # Set the error region line_data['culp_region'] = sublime.Region( int(line_data['point']) - 1, int(line_data['point']) + (int(line_data['err_length']) - 1)) else: # Set the line as the error region line_data['culp_region'] = self.view.line( line_data['line_pt']) # Add the region to the apropriate region collection if ('dartlint_' + line_data['severity']) not in \ culp_regions.keys(): culp_regions['dartlint_%s' % line_data['severity']] = [] culp_regions['dartlint_%s' % line_data['severity']].append( line_data['culp_region']) lines_out += line_out lint_data.append(line_data) err_count += 1 for reg_id in culp_regions.keys(): # set the scope name reg_list = culp_regions[reg_id] this_scope = 'dartlint.mark.warning' if reg_id.endswith('ERROR') is True: this_scope = 'dartlint.mark.error' if reg_id.endswith('INFO') is True: this_scope = 'dartlint.mark.info' # Seperate gutter and underline regions gutter_reg = [] for reg in reg_list: gutter_reg.append(self.view.line(reg.begin())) self.view.add_regions( reg_id + '_gutter', gutter_reg, # set this to this_scope for tinted gutter icons 'dartlint.mark.gutter', icon=GUTTER_Icon[reg_id], flags=SCOPES_Dartlint['dartlint.mark.gutter']['flags']) self.view.add_regions( reg_id, reg_list, this_scope, flags=SCOPES_Dartlint[this_scope]['flags']) # Set icon presidence? if lines_out is '': self.output = None print('No errors.') self.view.set_status('dartlint', 'Dartlint: No errors') else: # Sort list idx = 0 err_keys = [] for entry in lint_data: line_val = '{0:{fill}{align}16}'.format( entry['line'], fill='0', align='>') col_val = '{0:{fill}{align}16}'.format( entry['col'], fill='0', align='>') list_val = '%s-%s-%s' % (line_val, col_val, str(idx)) err_keys.append(list_val) idx += 1 new_err_list = [] err_keys.sort() for ek in err_keys: new_err_list.append(lint_data[int(ek.split('-')[2])]) self.output = new_err_list # Out to console print('\n' + lines_out)
def callback(self, data): panel = OutputPanel('dart.out') panel.write(self.format_data(data)) panel.show()
def show_errors(errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' v = sublime.active_window().active_view() # TODO(guillermooo): Use tokens to identify requests:file. # todo (pp): notifications don't have id; process all if os.path.realpath(errors.file) != os.path.realpath(v.file_name()): _logger.debug('different view active - aborting') return analysis_errs = list(errors.errors) if analysis_errs == 0: clear_ui() return infos = [ae for ae in analysis_errs if (ae.severity == AnalysisErrorSeverity.INFO)] warns = [ae for ae in analysis_errs if (ae.severity == AnalysisErrorSeverity.WARNING)] erros = [ae for ae in analysis_errs if (ae.severity == AnalysisErrorSeverity.ERROR)] def error_to_region(view, error): '''Converts location data to region data. ''' loc = Location(error.location) pt = view.text_point(loc.startLine - 1, loc.startColumn - 1) return sublime.Region(pt, pt + loc.length) info_regs = [error_to_region(v, item) for item in infos] warn_regs = [error_to_region(v, item) for item in warns] errs_regs = [error_to_region(v, item) for item in erros] _logger.debug('displaying errors to the user') v.add_regions('dart.infos', info_regs, scope='dartlint.mark.info', icon="Packages/Dart/gutter/dartlint-simple-info.png", flags=_flags) v.add_regions('dart.warnings', warn_regs, scope='dartlint.mark.warning', icon="Packages/Dart/gutter/dartlint-simple-warning.png", flags=_flags) v.add_regions('dart.errors', errs_regs, scope='dartlint.mark.error', icon='Packages/Dart/gutter/dartlint-simple-error.png', flags=_flags) def to_compact_text(error): return ("{error.severity}|{error.type}|{loc.file}|" "{loc.startLine}|{loc.startColumn}|{error.message}").format( error=error, loc=Location(error.location)) info_patts = [to_compact_text(item) for item in infos] warn_patts = [to_compact_text(item) for item in warns] errs_patts = [to_compact_text(item) for item in erros] all_errs = set(errs_patts + warn_patts + info_patts) panel = OutputPanel('dart.analyzer') errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) panel.write('\n'.join(all_errs))
def __call__(self, errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' view = get_active_view() # TODO(guillermooo): Use tokens to identify requests:file. if not self.compare_paths(errors.file, view.file_name()): _logger.debug('different view active - aborting') return panel = OutputPanel('dart.errors') analysis_errors = list(errors.errors) infos, warns, erros = self.group(analysis_errors) if len(infos + warns + erros) == 0: clear_ui() panel.hide() return info_regs = [self.error_to_region(view, item) for item in infos] warn_regs = [self.error_to_region(view, item) for item in warns] errs_regs = [self.error_to_region(view, item) for item in erros] _logger.debug('displaying errors to the user') self.add_regions(view, info_regs, warn_regs, errs_regs) all_sorted = sorted(infos + warns + erros, key=lambda x: x.location.offset) all_errs = (self.to_compact_text(item) for item in all_sorted) # TODO(guillermooo): abstract out the panel stuff into a DartErrorPanel class. panel = OutputPanel('dart.errors') # Tried to use .sublime-settings for this, but it won't work well. errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) all_errs = list(all_errs) # Overwrite any previous text in the panel. # We get errors sometimes when writing error lines here. panel.write('\n'.join(all_errs)) # TODO(guillermooo): remove this when .sublime-syntax has been fully # adopted. if sublime.version() >= '3084': panel.view.set_syntax_file('Packages/Dart/Support/Analyzer Output.sublime-syntax') else: panel.view.set_syntax_file('Packages/Dart/Support/Analyzer Output.tmLanguage') editor_context.errors = all_errs # To show the panel, use the Command Palette or the key binding. # panel.show() try: view.show(view.sel()[0]) except IndexError: pass sublime.status_message("Dart: Errors found")
def run(self): _logger.info('starting ResponseHandler') try: # Awaiting other threads... self.server.ready_barrier.wait() except threading.BrokenBarrierError: _logger.error('could not start ResponseHandler properly') return response_maker = ResponseMaker(self.server.responses) try: for resp in response_maker.make(): if (resp.type == ResponseType.INTERNAL and resp.internal_request == _SIGNAL_STOP): _logger.info( 'ResponseHandler is exiting by internal request') return elif resp.type == ResponseType.INTERNAL: _logger.debug('got internal response: %s', resp) continue if resp.type == ResponseType.RESULT_ID: _logger.debug('changing search id: %s -> %s', resp.id, resp.result_id) g_editor_context.search_id = resp.result_id if resp.result: _logger.debug('^********************************************') print("FOUND RESULT", resp.result.to_encoded_pos()) _logger.debug('^********************************************') # g_editor_context.append_search_results([resp.result]) continue if resp.type == ResponseType.UNKNOWN: _logger.debug('received unknown type of response: %s', resp) continue if resp.type == 'search.results': _logger.info('received search results') # TODO(guillermooo): pass only result id. if g_editor_context.check_token('search', resp.result_id): _logger.debug('^********************************************') _logger.debug('search results: %s', resp.search_results.results) _logger.debug('^********************************************') rrr = [t.to_encoded_pos() for t in list(resp.search_results.results)] for r in rrr: print("//////////////////////////////////////", r) out = OutputPanel('foo.bar') out.write('\n'.join(rrr)) out.show() # g_editor_context.append_search_results(resp.search_results.results) else: _logger.debug('expired token') continue if resp.type == ResponseType.ERRORS: _logger.info('error data received from server') # Make sure the right type is passed to the async # code. `resp` may point to a different object when # the async code finally has a chance to run. after(0, actions.show_errors, resp.copy()) continue elif resp.type == 'server.status': after(0, sublime.status_message, 'Dart: {}'.format(resp.status.message)) continue except Exception as e: _logger.debug(e) print('Dart: exception while handling response.') print('========================================') print(e) print('========================================')
class DartRunFileCommand(DartBuildCommandBase): '''Runs a file with the most appropriate action. Runs .dart and .html files. ''' observatory = None pub_serve = None is_server_running = False is_script_running = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.panel = None def __del__(self): # FIXME(guillermooo): this doesn't manage to clean up resources when # ST exits. self.stop_server_observatory() self.execute(kill=True) def observatory_port(self): try: return DartRunFileCommand.observatory.port except Exception: _logger.error('could not retrieve Observatory port') return @property def pub_serve_port(self): try: return DartRunFileCommand.pub_serve.port except Exception: _logger.error('could not retrieve pub serve port') return @pub_serve_port.setter def pub_serve_port(self, value): DartRunFileCommand.pub_serve.port = value def run(self, file_name=None, action='primary', kill_only=False): ''' @action One of: primary, secondary @kill_only Whether we should simply kill any running processes. ''' assert kill_only or (file_name and not kill_only), 'wrong call' # First, clean up any existing prosesses. if DartRunFileCommand.is_server_running: self.execute(kill=True) self.pub_serve.stop() DartRunFileCommand.is_server_running = False if self.panel: self.panel.write('[pub serve stopped]\n') self.stop_server_observatory() if kill_only: self.window.run_command("dart_exec", { "kill": True }) DartRunFileCommand.is_script_running = False return try: working_dir = os.path.dirname(find_pubspec(file_name)) except: try: if not working_dir: working_dir = os.path.dirname(file_name) except: _logger.debug('cannot run an unsaved file') return dart_view = DartFile.from_path(file_name) if dart_view.is_server_app: self.run_server_app(file_name, working_dir, action) return if dart_view.is_web_app: self.run_web_app(dart_view, working_dir, action) return # At this point, we are looking at a file that either: # - is not a .dart or .html file # - is outside of a pub package # As a last restort, run the file as a script, but only if the user # requested a 'secondary' action. if action != 'secondary' or not dart_view.is_dart_file: print("Dart: Cannot determine best action for {}".format( dart_view.path )) _logger.debug("cannot determine best run action for %s", dart_view.path) return self.run_server_app(file_name, working_dir, action) def start_default_browser(self, file_name): sdk = SDK() if not sdk.path_to_default_user_browser: _logger.info('no default user browser defined') print("Dart: No default user browser defined " "in Dart plugin settings") return dart_view = DartFile.from_path(file_name) url = 'http://localhost:8080' if dart_view.url_path: url = url + "/" + dart_view.url_path # TODO(guillermooo): make GUIProcess wrapper to abstract out some of # the stuff below? if sublime.platform() == 'osx': bin_ = GenericBinary('open', sdk.path_to_default_user_browser) after(1000, lambda: bin_.start(args=[url])) return elif sublime.platform() == 'windows': # FIXME(guillermooo): On Windows, Firefox won't work when started # from the cmdline only. If it's started first from the shell, it # will work here as well. path = sdk.path_to_default_user_browser bin_ = GenericBinary(path) after(1000, lambda: bin_.start( args=[url], shell=True, cwd=os.path.dirname(path), )) return path = sdk.path_to_default_user_browser bin_ = GenericBinary(path) after(1000, lambda: bin_.start( args=[url], shell=True, cwd=os.path.dirname(path), )) def run_server_app(self, file_name, working_dir, action): if action == 'secondary': # run with observatory # we need to do additional processing in this case, so we don't # use the regular .execute() method to manage the subprocess. self.panel = OutputPanel('dart.out') self.panel.write('=' * 80) self.panel.write('\n') self.panel.write('Running dart with Observatory.\n') self.panel.write('=' * 80) self.panel.write('\n') self.panel.show() DartRunFileCommand.observatory = RunDartWithObservatory( file_name, cwd=working_dir, listener=self) DartRunFileCommand.observatory.start() def start_dartium(): d = Dartium() port = DartRunFileCommand.observatory.port if port is None: _logger.debug('could not capture observatory port') print("Dart: Cannot start Observatory " "because its port couldn't be retrieved") return d.start('http://localhost:{}'.format(port)) after(1000, lambda: start_dartium()) return preamble = '''* Running {0} * (output starts below the next line) ============================================================================== ''' # TODO(guillermooo): improve event args self.execute( cmd=[SDK().path_to_dart, '--checked', file_name], working_dir=working_dir, file_regex=r"'file:///(.+)': error: line (\d+) pos (\d+): (.*)$", preamble=preamble.format(file_name), ) DartRunFileCommand.is_script_running = True def run_web_app(self, dart_view, working_dir, action): sdk = SDK() if action == 'secondary': if not sdk.path_to_default_user_browser: print("Dart: No default browser found") _logger.info('no default browser found') return cmd=[sdk.path_to_pub, 'serve'] if dart_view.is_example: cmd.append('example') self.execute(cmd=cmd, working_dir=working_dir) DartRunFileCommand.is_server_running = True self.start_default_browser(dart_view.path) return self.panel = OutputPanel('dart.out') self.panel.write('=' * 80) self.panel.write('\n') self.panel.write('Running pub serve...\n') self.panel.write('=' * 80) self.panel.write('\n') self.panel.show() DartRunFileCommand.pub_serve = PubServe( cwd=working_dir, is_example=dart_view.is_example, ) pub_serve_listener = PubServeListener(DartRunFileCommand.pub_serve, self.panel, dart_view.url_path) DartRunFileCommand.pub_serve.listener = pub_serve_listener DartRunFileCommand.pub_serve.start() DartRunFileCommand.is_server_running = True def stop_server_observatory(self): if DartRunFileCommand.observatory: DartRunFileCommand.observatory.stop() DartRunFileCommand.observatory = None if self.panel: self.panel.write('[Observatory stopped]\n') def on_data(self, text): self.panel.write(text) def on_error(self, text): self.panel.write(text)
def run(self): _logger.info('starting ResponseHandler') try: # Awaiting other threads... self.server.ready_barrier.wait() except threading.BrokenBarrierError: _logger.error('could not start ResponseHandler properly') return response_maker = ResponseMaker(self.server.responses) try: for resp in response_maker.make(): if (resp.type == ResponseType.INTERNAL and resp.internal_request == _SIGNAL_STOP): _logger.info( 'ResponseHandler is exiting by internal request') return elif resp.type == ResponseType.INTERNAL: _logger.debug('got internal response: %s', resp) continue if resp.type == ResponseType.RESULT_ID: _logger.debug('changing search id: %s -> %s', resp.id, resp.result_id) g_editor_context.search_id = resp.result_id if resp.result: _logger.debug( '^********************************************') print("FOUND RESULT", resp.result.to_encoded_pos()) _logger.debug( '^********************************************') # g_editor_context.append_search_results([resp.result]) continue if resp.type == ResponseType.UNKNOWN: _logger.debug('received unknown type of response: %s', resp) continue if resp.type == 'search.results': _logger.info('received search results') # TODO(guillermooo): pass only result id. if g_editor_context.check_token('search', resp.result_id): _logger.debug( '^********************************************') _logger.debug('search results: %s', resp.search_results.results) _logger.debug( '^********************************************') rrr = [ t.to_encoded_pos() for t in list(resp.search_results.results) ] for r in rrr: print("//////////////////////////////////////", r) out = OutputPanel('foo.bar') out.write('\n'.join(rrr)) out.show() # g_editor_context.append_search_results(resp.search_results.results) else: _logger.debug('expired token') continue if resp.type == ResponseType.ERRORS: _logger.info('error data received from server') # Make sure the right type is passed to the async # code. `resp` may point to a different object when # the async code finally has a chance to run. after(0, actions.show_errors, resp.copy()) continue elif resp.type == 'server.status': after(0, sublime.status_message, 'Dart: {}'.format(resp.status.message)) continue except Exception as e: _logger.debug(e) print('Dart: exception while handling response.') print('========================================') print(e) print('========================================')
def run(self): """Runs forever checking for new linter results and displaying them to the user. """ while True: # Run at intervals. time.sleep(0.250) # We've got results for this buffer. Reset its version count so # the linting cycle can start again. # TODO(guillermooo): It's possible that we'll miss some edits (?). with g_edits_lock: DartLint.edits[self.view.buffer_id()] = 0 lines = self.get_data() if lines is None: continue # TODO(guillermooo): Compose a DartLintOutputPanel from a plain # OutputPanel to abstract all of this away. # Show errors in output panel and enable error navigation via F4. panel = OutputPanel('dart.analyzer') # Capture file name, rowcol and error message information. errors_pattern = r'^\w+\|\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|\d+\|(.+)' panel.set('result_file_regex', errors_pattern) panel.write('\n'.join(lines)) panel.show() pattern = (r'^(?P<severity>\w+)\|(?P<type>\w+)\|(?P<code>\w+)\|' + r'(?P<file_name>.+)\|(?P<line>\d+)\|(?P<col>\d+)\|' + r'(?P<err_length>\d+)\|(?P<message>.+)') msg_pattern_machine = re.compile(pattern) # Collect data needed to generate error messages lint_data = [] lines_out = '' err_count = 0 culp_regions = {} for line in lines: line_out = '' line_data = {} line_groups = msg_pattern_machine.match(line) if line_groups is not None: if line_groups.group('file_name') != self.fileName: # output is for a different file continue line_out = '%s: %s on line %s, col %s: %s\n' % \ (line_groups.group('severity'), line_groups.group('code'), line_groups.group('line'), line_groups.group('col'), line_groups.group('message')) line_data['severity'] = line_groups.group('severity') line_data['col'] = line_groups.group('col') line_data['line'] = line_groups.group('line') line_data['msg'] = line_groups.group('message') line_data['code'] = line_groups.group('code') line_data['type'] = line_groups.group('type') line_data['err_length'] = line_groups.group('err_length') line_data['lint_out'] = line_out line_data['line_pt'] = self.view.text_point( int(line_data['line']) - 1, 0) line_data['point'] = self.view.text_point( int(line_data['line']) - 1, int(line_data['col'])) next_line = self.view.text_point(int(line_data['line']), 0) # Add a region (gutter mark and underline) if int(line_data['err_length']) > 0 and \ int(line_data['point']) + \ (int(line_data['err_length']) - 1) < next_line: # Set the error region line_data['culp_region'] = sublime.Region( int(line_data['point']) - 1, int(line_data['point']) + (int(line_data['err_length']) - 1)) else: # Set the line as the error region line_data['culp_region'] = self.view.line( line_data['line_pt']) # Add the region to the apropriate region collection if ('dartlint_' + line_data['severity']) not in \ culp_regions.keys(): culp_regions['dartlint_%s' % line_data['severity']] = [] culp_regions['dartlint_%s' % line_data['severity']].append( line_data['culp_region']) lines_out += line_out lint_data.append(line_data) err_count += 1 for reg_id in culp_regions.keys(): # set the scope name reg_list = culp_regions[reg_id] this_scope = 'dartlint.mark.warning' if reg_id.endswith('ERROR') is True: this_scope = 'dartlint.mark.error' if reg_id.endswith('INFO') is True: this_scope = 'dartlint.mark.info' # Seperate gutter and underline regions gutter_reg = [] for reg in reg_list: gutter_reg.append(self.view.line(reg.begin())) self.view.add_regions( reg_id + '_gutter', gutter_reg, # set this to this_scope for tinted gutter icons 'dartlint.mark.gutter', icon=GUTTER_Icon[reg_id], flags=SCOPES_Dartlint['dartlint.mark.gutter']['flags']) self.view.add_regions( reg_id, reg_list, this_scope, flags=SCOPES_Dartlint[this_scope]['flags']) # Set icon presidence? if lines_out is '': self.output = None print('No errors.') self.view.set_status('dartlint', 'Dartlint: No errors') else: # Sort list idx = 0 err_keys = [] for entry in lint_data: line_val = '{0:{fill}{align}16}'.format(entry['line'], fill='0', align='>') col_val = '{0:{fill}{align}16}'.format(entry['col'], fill='0', align='>') list_val = '%s-%s-%s' % (line_val, col_val, str(idx)) err_keys.append(list_val) idx += 1 new_err_list = [] err_keys.sort() for ek in err_keys: new_err_list.append(lint_data[int(ek.split('-')[2])]) self.output = new_err_list # Out to console print('\n' + lines_out)
class DartRunFileCommand(DartBuildCommandBase): '''Runs a file with the most appropriate action. Runs .dart and .html files. ''' observatory = None pub_serve = None is_server_running = False is_script_running = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.panel = None def __del__(self): # FIXME(guillermooo): this doesn't manage to clean up resources when # ST exits. self.stop_server_observatory() self.execute(kill=True) def observatory_port(self): try: return DartRunFileCommand.observatory.port except Exception: _logger.error('could not retrieve Observatory port') return @property def pub_serve_port(self): try: return DartRunFileCommand.pub_serve.port except Exception: _logger.error('could not retrieve pub serve port') return @pub_serve_port.setter def pub_serve_port(self, value): DartRunFileCommand.pub_serve.port = value def _cleanup(self): # Stop up any existing processes. if DartRunFileCommand.is_server_running: self.execute(kill=True) self.pub_serve.stop() DartRunFileCommand.is_server_running = False if self.panel: self.panel.write('[pub serve stopped]\n') self.stop_server_observatory() def _kill(self): self.window.run_command("dart_exec", { "kill": True }) DartRunFileCommand.is_script_running = False def run(self, file_name=None, action='primary', kill_only=False): ''' @action One of: [primary, secondary] @kill_only If `True`, simply kill any running processes we've started. ''' assert kill_only or file_name, 'wrong call' self._cleanup() if kill_only: self._kill() return working_dir = None try: working_dir = os.path.dirname(find_pubspec(file_name)) except (TypeError, AttributeError): try: if not working_dir: working_dir = os.path.dirname(file_name) except TypeError as e: _logger.debug('cannot run an unsaved file') _logger.debug(e) return except Exception as e: _logger.error('programmer error: this exception needs to be handled') _logger.error(e) return except Exception as e: _logger.error('programmer error: this exception needs to be handled') _logger.error(e) return dart_view = DartFile.from_path(file_name) if dart_view.is_server_app: self.run_server_app(file_name, working_dir, action) return if dart_view.is_web_app: self.run_web_app(dart_view, working_dir, action) return # TODO: improve detection of runnable file (for example, don't attempt # to run a part of a library). # At this point, we are looking at a file that either: # - is not a .dart or .html file # - is outside of a pub package # As a last resort, try to run the file as a script. if action != 'primary' or not dart_view.is_dart_file: print("Dart: Cannot determine best action for {}".format( dart_view.path )) _logger.debug("cannot determine best run action for %s", dart_view.path) return self.run_server_app(file_name, working_dir, action) def start_default_browser(self, file_name): sdk = SDK() if not sdk.path_to_default_user_browser: _logger.info('no default user browser defined') print("Dart: No default user browser defined " "in Dart plugin settings") return dart_view = DartFile.from_path(file_name) url = 'http://localhost:8080' if dart_view.url_path: url = url + "/" + dart_view.url_path # TODO(guillermooo): make GUIProcess wrapper to abstract out some of # the stuff below? if sublime.platform() == 'osx': bin_ = GenericBinary('open', sdk.path_to_default_user_browser) after(1000, lambda: bin_.start(args=[url])) return elif sublime.platform() == 'windows': # FIXME(guillermooo): On Windows, Firefox won't work when started # from the cmdline only. If it's started first from the shell, it # will work here as well. path = sdk.path_to_default_user_browser bin_ = GenericBinary(path) after(1000, lambda: bin_.start( args=[url], shell=True, cwd=os.path.dirname(path), )) return path = sdk.path_to_default_user_browser bin_ = GenericBinary(path) after(1000, lambda: bin_.start( args=[url], shell=True, cwd=os.path.dirname(path), )) def run_server_app(self, file_name, working_dir, action): if action == 'secondary': # run with observatory # we need to do additional processing in this case, so we don't # use the regular .execute() method to manage the subprocess. self.panel = OutputPanel('dart.out') self.panel.write('=' * 80) self.panel.write('\n') self.panel.write('Running dart with Observatory.\n') self.panel.write('=' * 80) self.panel.write('\n') self.panel.show() DartRunFileCommand.observatory = RunDartWithObservatory( file_name, cwd=working_dir, listener=self) DartRunFileCommand.observatory.start() def start_dartium(): d = Dartium() port = DartRunFileCommand.observatory.port if port is None: _logger.debug('could not capture observatory port') print("Dart: Cannot start Observatory " "because its port couldn't be retrieved") return d.start('http://localhost:{}'.format(port)) after(1000, lambda: start_dartium()) return preamble = '''* Running {0} * (output starts below the next line) ============================================================================== ''' # TODO(guillermooo): improve event args self.execute( cmd=[SDK().path_to_dart, '--checked', file_name], working_dir=working_dir, file_regex=r"'file:///(.+)': error: line (\d+) pos (\d+): (.*)$", preamble=preamble.format(file_name), ) DartRunFileCommand.is_script_running = True def run_web_app(self, dart_view, working_dir, action): sdk = SDK() if action == 'secondary': if not sdk.path_to_default_user_browser: print("Dart: No default browser found") _logger.info('no default browser found') return cmd=[sdk.path_to_pub, 'serve'] if dart_view.is_example: cmd.append('example') self.execute(cmd=cmd, working_dir=working_dir) DartRunFileCommand.is_server_running = True self.start_default_browser(dart_view.path) return self.panel = OutputPanel('dart.out') self.panel.write('=' * 80) self.panel.write('\n') self.panel.write('Running pub serve...\n') self.panel.write('=' * 80) self.panel.write('\n') self.panel.show() DartRunFileCommand.pub_serve = PubServe( cwd=working_dir, is_example=dart_view.is_example, ) pub_serve_listener = PubServeListener(DartRunFileCommand.pub_serve, self.panel, dart_view.url_path) DartRunFileCommand.pub_serve.listener = pub_serve_listener DartRunFileCommand.pub_serve.start() DartRunFileCommand.is_server_running = True def stop_server_observatory(self): if DartRunFileCommand.observatory: DartRunFileCommand.observatory.stop() DartRunFileCommand.observatory = None if self.panel: self.panel.write('[Observatory stopped]\n') def on_data(self, text): self.panel.write(text) def on_error(self, text): self.panel.write(text)
def show_errors(errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' v = sublime.active_window().active_view() # TODO(guillermooo): Use tokens to identify requests:file. # todo (pp): notifications don't have id; process all if os.path.realpath(errors.file) != os.path.realpath(v.file_name()): _logger.debug('different view active - aborting') return analysis_errors = list(errors.errors) if analysis_errors == 0: clear_ui() return infos = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.INFO) and ( ae.type != AnalysisErrorType.TODO) ] warns = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.WARNING) ] erros = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.ERROR) ] def error_to_region(view, error): '''Converts location data to region data. ''' pass loc = error.location pt = view.text_point(loc.startLine - 1, loc.startColumn - 1) return sublime.Region(pt, pt + loc.length) info_regs = [error_to_region(v, item) for item in infos] warn_regs = [error_to_region(v, item) for item in warns] errs_regs = [error_to_region(v, item) for item in erros] _logger.debug('displaying errors to the user') v.add_regions(DAS_UI_REGIONS_INFOS, info_regs, scope=DAS_SCOPE_INFO, icon="Packages/Dart/gutter/dartlint-simple-info.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_WARNINGS, warn_regs, scope=DAS_SCOPE_WARNING, icon="Packages/Dart/gutter/dartlint-simple-warning.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_ERRORS, errs_regs, scope=DAS_SCOPE_ERROR, icon='Packages/Dart/gutter/dartlint-simple-error.png', flags=_flags) def to_compact_text(error): return ("{error.severity}|{error.type}|{loc.file}|" "{loc.startLine}|{loc.startColumn}|{error.message}").format( error=error, loc=error.location) info_patts = [to_compact_text(item) for item in infos] warn_patts = [to_compact_text(item) for item in warns] errs_patts = [to_compact_text(item) for item in erros] all_errs = set(errs_patts + warn_patts + info_patts) panel = OutputPanel('dart.analyzer') if not all_errs: editor_context.errors = [] panel.hide() return errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) # This will overwrite any previous text. panel.write('\n' + '\n'.join(all_errs)) # FIXME: It appears that if ST dev find a .sublime-syntax and a .tmLanguage # file, it will load # the first one. But how do we refer to the file then? if sublime.version() >= '3084': panel.view.set_syntax_file( 'Packages/Dart/Support/Analyzer Output.sublime-syntax') else: panel.view.set_syntax_file( 'Packages/Dart/Support/Analyzer Output.tmLanguage') panel.view.settings().set('rulers', []) panel.show() sublime.status_message("Dart: Errors found") editor_context.errors = all_errs
def show_errors(errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' v = sublime.active_window().active_view() # TODO(guillermooo): Use tokens to identify requests:file. # todo (pp): notifications don't have id; process all if os.path.realpath(errors.file) != os.path.realpath(v.file_name()): _logger.debug('different view active - aborting') return analysis_errors = list(errors.errors) if analysis_errors == 0: clear_ui() return infos = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.INFO) ] warns = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.WARNING) ] erros = [ ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.ERROR) ] def error_to_region(view, error): '''Converts location data to region data. ''' loc = error.location pt = view.text_point(loc.startLine - 1, loc.startColumn - 1) return sublime.Region(pt, pt + loc.length) info_regs = [error_to_region(v, item) for item in infos] warn_regs = [error_to_region(v, item) for item in warns] errs_regs = [error_to_region(v, item) for item in erros] _logger.debug('displaying errors to the user') v.add_regions(DAS_UI_REGIONS_INFOS, info_regs, scope=DAS_SCOPE_INFO, icon="Packages/Dart/gutter/dartlint-simple-info.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_WARNINGS, warn_regs, scope=DAS_SCOPE_WARNING, icon="Packages/Dart/gutter/dartlint-simple-warning.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_ERRORS, errs_regs, scope=DAS_SCOPE_ERROR, icon='Packages/Dart/gutter/dartlint-simple-error.png', flags=_flags) def to_compact_text(error): return ("{error.severity}|{error.type}|{loc.file}|" "{loc.startLine}|{loc.startColumn}|{error.message}").format( error=error, loc=error.location) info_patts = [to_compact_text(item) for item in infos] warn_patts = [to_compact_text(item) for item in warns] errs_patts = [to_compact_text(item) for item in erros] all_errs = set(errs_patts + warn_patts + info_patts) panel = OutputPanel('dart.analyzer') errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) panel.write('\n'.join(all_errs))
class DartExecCommand(sublime_plugin.WindowCommand, ProcessListener): def run( self, cmd=None, shell_cmd=None, file_regex="", line_regex="", working_dir="", encoding="utf-8", env={}, quiet=False, kill=False, word_wrap=True, syntax="Packages/Text/Plain text.tmLanguage", preamble='', panel_name='dart.out', # Catches "path" and "shell" **kwargs): if kill: if hasattr(self, 'proc') and self.proc: self.proc.kill() self.proc = None self.append_string(None, "[Cancelled]") return # TODO(guillermooo): We cannot have multiple processes running at the # same time, or processes that use separate output panels. if not hasattr(self, 'out_panel'): # Try not to call get_output_panel until the regexes are assigned self.out_panel = OutputPanel(panel_name) # Default to the current files directory if no working directory was given if (not working_dir and self.window.active_view() and self.window.active_view().file_name()): working_dir = os.path.dirname( self.window.active_view().file_name()) self.out_panel.set("result_file_regex", file_regex) self.out_panel.set("result_line_regex", line_regex) self.out_panel.set("result_base_dir", working_dir) self.out_panel.set("word_wrap", word_wrap) self.out_panel.set("line_numbers", False) self.out_panel.set("gutter", False) self.out_panel.set("scroll_past_end", False) self.out_panel.view.assign_syntax(syntax) self.encoding = encoding self.quiet = quiet self.proc = None if not self.quiet: if shell_cmd: print("Running " + shell_cmd) else: print("Running " + " ".join(cmd)) sublime.status_message("Building") if preamble: self.append_string(self.proc, preamble) show_panel_on_build = sublime.load_settings( "Dart - Plugin Settings.sublime-settings").get( "show_panel_on_build", True) if show_panel_on_build: self.out_panel.show() merged_env = env.copy() if self.window.active_view(): user_env = self.window.active_view().settings().get('build_env') if user_env: merged_env.update(user_env) # Change to the working dir, rather than spawning the process with it, # so that emitted working dir relative path names make sense if working_dir: os.chdir(working_dir) self.debug_text = "" if shell_cmd: self.debug_text += "[shell_cmd: " + shell_cmd + "]\n" else: self.debug_text += "[cmd: " + str(cmd) + "]\n" self.debug_text += "[dir: " + str(os.getcwd()) + "]\n" if "PATH" in merged_env: self.debug_text += "[path: " + str(merged_env["PATH"]) + "]" else: self.debug_text += "[path: " + str(os.environ["PATH"]) + "]" try: # Forward kwargs to AsyncProcess self.proc = AsyncProcess(cmd, shell_cmd, merged_env, self, **kwargs) except Exception as e: self.append_string(None, str(e) + "\n") self.append_string(None, self.debug_text + "\n") if not self.quiet: self.append_string(None, "[Finished]") def append_data(self, proc, data): if proc != self.proc: # a second call to exec has been made before the first one # finished, ignore it instead of intermingling the output. if proc: proc.kill() return try: str_ = data.decode(self.encoding) except UnicodeEncodeError: str_ = "[Decode error - output not " + self.encoding + "]\n" proc = None return # Normalize newlines, Sublime Text always uses a single \n separator # in memory. str_ = str_.replace('\r\n', '\n').replace('\r', '\n') self.out_panel.write(str_) def append_string(self, proc, str): self.append_data(proc, str.encode(self.encoding)) def finish(self, proc): if not self.quiet: elapsed = time.time() - proc.start_time exit_code = proc.exit_code() if (exit_code == 0) or (exit_code == None): self.append_string(proc, "[Finished in %.1fs]" % (elapsed)) else: self.append_string( proc, "[Finished in %.1fs with exit code %d]\n" % (elapsed, exit_code)) self.append_string(proc, self.debug_text) if proc != self.proc: return # XXX: What's this for? errs = self.out_panel.view.find_all_results() if len(errs) == 0: sublime.status_message("Build finished") else: sublime.status_message( ("Build finished with %d errors") % len(errs)) def on_data(self, proc, data): after(0, functools.partial(self.append_data, proc, data)) def on_finished(self, proc): after(0, functools.partial(self.finish, proc))
def show_errors(errors): '''Show errors in the ui. @errors An instance of `ErrorInfoCollection`. ''' v = sublime.active_window().active_view() # TODO(guillermooo): Use tokens to identify requests:file. # todo (pp): notifications don't have id; process all if os.path.realpath(errors.file) != os.path.realpath(v.file_name()): _logger.debug('different view active - aborting') return analysis_errors = list(errors.errors) if analysis_errors == 0: clear_ui() return infos = [ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.INFO) and (ae.type != AnalysisErrorType.TODO)] warns = [ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.WARNING)] erros = [ae for ae in analysis_errors if (ae.severity == AnalysisErrorSeverity.ERROR)] def error_to_region(view, error): '''Converts location data to region data. ''' pass loc = error.location pt = view.text_point(loc.startLine - 1, loc.startColumn - 1) return sublime.Region(pt, pt + loc.length) info_regs = [error_to_region(v, item) for item in infos] warn_regs = [error_to_region(v, item) for item in warns] errs_regs = [error_to_region(v, item) for item in erros] _logger.debug('displaying errors to the user') v.add_regions(DAS_UI_REGIONS_INFOS, info_regs, scope=DAS_SCOPE_INFO, icon="Packages/Dart/gutter/dartlint-simple-info.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_WARNINGS, warn_regs, scope=DAS_SCOPE_WARNING, icon="Packages/Dart/gutter/dartlint-simple-warning.png", flags=_flags) v.add_regions(DAS_UI_REGIONS_ERRORS, errs_regs, scope=DAS_SCOPE_ERROR, icon='Packages/Dart/gutter/dartlint-simple-error.png', flags=_flags) def to_compact_text(error): return ("{error.severity}|{error.type}|{loc.file}|" "{loc.startLine}|{loc.startColumn}|{error.message}").format( error=error, loc=error.location) info_patts = [to_compact_text(item) for item in infos] warn_patts = [to_compact_text(item) for item in warns] errs_patts = [to_compact_text(item) for item in erros] all_errs = set(errs_patts + warn_patts + info_patts) panel = OutputPanel('dart.analyzer') if not all_errs: editor_context.errors = [] panel.hide() return errors_pattern = r'^\w+\|\w+\|(.+)\|(\d+)\|(\d+)\|(.+)$' panel.set('result_file_regex', errors_pattern) # This will overwrite any previous text. panel.write('\n' + '\n'.join(all_errs)) panel.view.set_syntax_file('Packages/Dart/Support/Analyzer Output.sublime-syntax') panel.view.settings().set('rulers', []) panel.show() sublime.status_message("Dart: Errors found") editor_context.errors = all_errs