def lint(view, view_has_changed, lock, reason=None): """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ # We call `get_linters_for_view` first and unconditionally for its # side-effect. Yeah, it's a *getter* LOL. with lock: # We're already debounced, so races are actually unlikely. linters = get_linters_for_view(view) linters = [linter for linter in linters if linter.should_lint(reason)] if not linters: return # Very, very unlikely that `view_has_changed` is already True at this # point, but it also implements the kill_switch, so we ask here if view_has_changed(): # abort early return bid = view.buffer_id() if persist.settings.get('kill_old_processes'): kill_active_popen_calls(bid) events.broadcast(events.LINT_START, {'buffer_id': bid}) with remember_runtime("Linting '{}' took {{:.2f}}s".format( util.canonical_filename(view))): sink = partial(group_by_filename_and_update, bid, view_has_changed) backend.lint_view(linters, view, view_has_changed, sink) events.broadcast(events.LINT_END, {'buffer_id': bid})
def check_syntax(self, view): """ Check and return if view's syntax has changed. If the syntax has changed, a new linter is assigned. """ if not view: return vid = view.id() syntax = util.get_syntax(view) # Syntax either has never been set or just changed if vid not in self.view_syntax or self.view_syntax[vid] != syntax: bid = view.buffer_id() persist.errors[bid].clear() for linter in persist.view_linters.get(vid, []): events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': [] }) self.view_syntax[vid] = syntax self.linted_views.discard(vid) Linter.assign(view) return True else: return False
def lint(view, view_has_changed, lock): """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ # We call `get_linters_for_view` first and unconditionally for its # side-effect. Yeah, it's a *getter* LOL. with lock: # We're already debounced, so races are actually unlikely. linters = get_linters_for_view(view) if not linters: return # Very, very unlikely that `view_has_changed` is already True at this # point, but it also implements the kill_switch, so we ask here if view_has_changed(): # abort early return bid = view.buffer_id() events.broadcast(events.LINT_START, {'buffer_id': bid}) next = partial(update_buffer_errors, bid, view_has_changed) backend.lint_view(linters, view, view_has_changed, next) events.broadcast(events.LINT_END, {'buffer_id': bid})
def lint(view, view_has_changed, lock, reason): # type: (sublime.View, ViewChangedFn, threading.Lock, Reason) -> None """Lint the view with the given id. This function MUST run on a thread because it blocks! """ linters = list(elect.assignable_linters_for_view(view, reason)) with lock: _assign_linters_to_view(view, {linter['name'] for linter in linters}) runnable_linters = list(elect.filter_runnable_linters(linters)) if not runnable_linters: return window = view.window() bid = view.buffer_id() filename = util.get_filename(view) # Very, very unlikely that `view_has_changed` is already True at this # point, but it also implements the kill_switch, so we ask here if view_has_changed(): # abort early return if persist.settings.get('kill_old_processes'): kill_active_popen_calls(bid) events.broadcast(events.LINT_START, {'buffer_id': bid}) with remember_runtime("Linting '{}' took {{:.2f}}s".format( util.canonical_filename(view))): sink = partial(group_by_filename_and_update, window, filename, view_has_changed, reason) backend.lint_view(runnable_linters, view, view_has_changed, sink) events.broadcast(events.LINT_END, {'buffer_id': bid})
def force_redraw(): for bid, errors in persist.errors.items(): for linter_name, linter_errors in group_by_linter(errors).items(): events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter_name, 'errors': linter_errors })
def force_redraw(): for filename, errors in persist.file_errors.items(): for linter_name, linter_errors in group_by_linter(errors).items(): events.broadcast( events.LINT_RESULT, { 'filename': filename, 'linter_name': linter_name, 'errors': linter_errors })
def update_file_errors(filename, linter, errors, reason=None): # type: (FileName, LinterName, List[LintError], Optional[Reason]) -> None """Persist lint error changes and broadcast.""" update_errors_store(filename, linter, errors) events.broadcast( events.LINT_RESULT, { 'filename': filename, 'linter_name': linter, 'errors': errors, 'reason': reason })
def update_buffer_errors(bid, linter, errors, reason=None): # type: (Bid, LinterName, List[LintError], Optional[Reason]) -> None """Persist lint error changes and broadcast.""" update_errors_store(bid, linter, errors) events.broadcast( events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter, 'errors': errors, 'reason': reason })
def update_buffer_errors(bid, view_has_changed, linter, errors): """Persist lint error changes and broadcast.""" if view_has_changed(): # abort early return update_errors_store(bid, linter.name, errors) events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': errors })
def update_buffer_errors(bid, view_has_changed, linter, errors): # type: (Bid, ViewChangedFn, Linter, List[LintError]) -> None """Persist lint error changes and broadcast.""" if view_has_changed(): # abort early return update_errors_store(bid, linter.name, errors) events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': errors })
def lint(self, view, view_has_changed): """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ if view_has_changed(): # abort early return events.broadcast(events.LINT_START, {'buffer_id': view.buffer_id()}) next = partial(self.highlight, view, view_has_changed) backend.lint_view(view, view_has_changed, next) events.broadcast(events.LINT_END, {'buffer_id': view.buffer_id()})
def update_buffer_errors(bid, view_has_changed, linter, errors): """Persist lint error changes and broadcast.""" if view_has_changed(): # abort early return all_errors = [ error for error in persist.errors[bid] if error['linter'] != linter.name ] + errors persist.errors[bid] = all_errors events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': errors })
def update_on_filename_change(old_filename, new_filename): # type: (FileName, FileName) -> None # update the error store if old_filename in persist.file_errors: errors = persist.file_errors.pop(old_filename) persist.file_errors[new_filename] = errors # update the affected filenames if old_filename in persist.affected_filenames_per_filename: filenames = persist.affected_filenames_per_filename.pop(old_filename) persist.affected_filenames_per_filename[new_filename] = filenames # notify the views events.broadcast('renamed_file', { 'new_filename': new_filename, 'old_filename': old_filename })
def highlight(self, view, view_has_changed, linter, errors): """ Highlight any errors found during a lint of the given view. This method is called by Linter.lint_view after linting is finished. """ if view_has_changed(): # abort early return bid = view.buffer_id() all_errors = [error for error in persist.errors[bid] if error['linter'] != linter.name] + errors persist.errors[bid] = all_errors events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': errors })
def highlight(self, view, view_has_changed, linter, errors): """ Highlight any errors found during a lint of the given view. This method is called by Linter.lint_view after linting is finished. """ if view_has_changed(): # abort early return bid = view.buffer_id() all_errors = [ error for error in persist.errors[bid] if error['linter'] != linter.name ] + errors persist.errors[bid] = all_errors events.broadcast(events.LINT_RESULT, { 'buffer_id': bid, 'linter_name': linter.name, 'errors': errors })
def lint(view, view_has_changed, lock): """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ # We call `get_linters_for_view` first and unconditionally for its # side-effect. Yeah, it's a *getter* LOL. with lock: # We're already debounced, so races are actually unlikely. linters = get_linters_for_view(view) linters = [linter for linter in linters if not skip_linter(linter, view)] if not linters: return # Very, very unlikely that `view_has_changed` is already True at this # point, but it also implements the kill_switch, so we ask here if view_has_changed(): # abort early return if not environment_is_ready(): hit(view) return bid = view.buffer_id() if persist.settings.get('kill_old_processes'): kill_active_popen_calls(bid) events.broadcast(events.LINT_START, {'buffer_id': bid}) start_time = time.time() next = partial(update_buffer_errors, bid, view_has_changed) backend.lint_view(linters, view, view_has_changed, next) end_time = time.time() runtime = end_time - start_time logger.info('Linting buffer {} took {:.2f}s'.format(bid, runtime)) remember_runtime(runtime) events.broadcast(events.LINT_END, {'buffer_id': bid})
def lint(view, view_has_changed, lock): """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ if view_has_changed(): # abort early return bid = view.buffer_id() # We're already debounced, so races are actually unlikely with lock: linters = get_linters_for_view(view) if linters: events.broadcast(events.LINT_START, {'buffer_id': bid}) next = partial(update_buffer_errors, bid, view_has_changed) backend.lint_view(linters, view, view_has_changed, next) events.broadcast(events.LINT_END, {'buffer_id': bid})
def lint(view, view_has_changed, lock, reason=None): # type: (sublime.View, ViewChangedFn, threading.Lock, Optional[str]) -> None """Lint the view with the given id. This method is called asynchronously by queue.Daemon when a lint request is pulled off the queue. """ # We call `get_linters_for_view` first and unconditionally for its # side-effect. Yeah, it's a *getter* LOL. with lock: # We're already debounced, so races are actually unlikely. linters = get_linters_for_view(view) linters = [ linter for linter in linters if linter.should_lint(reason)] if not linters: return # Very, very unlikely that `view_has_changed` is already True at this # point, but it also implements the kill_switch, so we ask here if view_has_changed(): # abort early return bid = view.buffer_id() if persist.settings.get('kill_old_processes'): kill_active_popen_calls(bid) events.broadcast(events.LINT_START, {'buffer_id': bid}) with remember_runtime( "Linting '{}' took {{:.2f}}s".format(util.canonical_filename(view)) ): sink = partial(group_by_filename_and_update, bid, view_has_changed) backend.lint_view(linters, view, view_has_changed, sink) events.broadcast(events.LINT_END, {'buffer_id': bid})