prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Provide a context key to check if LSP has a specific capability
  <del>
  Possible use case of the context key is to define custom keybind for go to definitions.
  With the context key, it allows me to bind `super+alt+down` to both `goto_definition` and `lsp_symbol_definition`.
  
  
  ```js
  { 
     // this is the default key for `goto_definition`
    "keys": ["super+alt+down"], "command": "goto_definition" 
  },
  { 
    "keys": ["super+alt+down"], "command": "lsp_symbol_definition" ,
    "context": [
  			{ "key": "lsp.is.active", "operator": "equal", "operand": true }
  		]
  }
  ```
  </del>
  
  
  Update: @rwols pointed out that there is `lsp_active` to check, so this issue is now requesting a key for checking more specific capability.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `plugin/core/documents.py`
  Content:
  ```
  1 from .registry import get_position
  2 from .registry import LSPViewEventListener
  3 from .session_view import SessionView
  4 from .sessions import Session
  5 from .typing import Any, Callable, Optional, Dict, Generator, Iterable
  6 from .windows import AbstractViewListener
  7 import sublime
  8 import threading
  9 
  10 
  11 SUBLIME_WORD_MASK = 515
  12 
  13 
  14 def is_at_word(view: sublime.View, event: Optional[dict]) -> bool:
  15     pos = get_position(view, event)
  16     return position_is_word(view, pos)
  17 
  18 
  19 def position_is_word(view: sublime.View, position: int) -> bool:
  20     point_classification = view.classify(position)
  21     if point_classification & SUBLIME_WORD_MASK:
  22         return True
  23     else:
  24         return False
  25 
  26 
  27 def is_transient_view(view: sublime.View) -> bool:
  28     window = view.window()
  29     if window:
  30         if window.get_view_index(view)[1] == -1:
  31             return True  # Quick panel transient views
  32         return view == window.transient_view_in_group(window.active_group())
  33     else:
  34         return True
  35 
  36 
  37 def _clear_async(lock: threading.Lock, session_views: Dict[str, SessionView]) -> Callable[[], None]:
  38 
  39     def run() -> None:
  40         with lock:
  41             session_views.clear()
  42 
  43     return run
  44 
  45 
  46 class DocumentSyncListener(LSPViewEventListener, AbstractViewListener):
  47 
  48     @classmethod
  49     def applies_to_primary_view_only(cls) -> bool:
  50         return False
  51 
  52     def __init__(self, view: sublime.View) -> None:
  53         super().__init__(view)
  54         self._file_name = ''
  55         self._session_views = {}  # type: Dict[str, SessionView]
  56         self._session_views_lock = threading.Lock()
  57 
  58     def __del__(self) -> None:
  59         self._clear_async()
  60 
  61     def _clear_async(self) -> None:
  62         sublime.set_timeout_async(_clear_async(self._session_views_lock, self._session_views))
  63 
  64     def on_session_initialized_async(self, session: Session) -> None:
  65         assert not self.view.is_loading()
  66         with self._session_views_lock:
  67             if session.config.name not in self._session_views:
  68                 self._session_views[session.config.name] = SessionView(self, session)
  69                 self.view.settings().set("lsp_active", True)
  70 
  71     def on_session_shutdown_async(self, session: Session) -> None:
  72         with self._session_views_lock:
  73             self._session_views.pop(session.config.name, None)
  74             if not self._session_views:
  75                 self.view.settings().erase("lsp_active")
  76 
  77     def session_views(self) -> Generator[SessionView, None, None]:
  78         yield from self._session_views.values()
  79 
  80     def _register_async(self) -> None:
  81         file_name = self.view.file_name()
  82         if file_name:
  83             self._file_name = file_name
  84             self.manager.register_listener_async(self)
  85 
  86     def _is_regular_view(self) -> bool:
  87         v = self.view
  88         # Not from the quick panel (CTRL+P), must have a filename on-disk, and not a special view like a console,
  89         # output panel or find-in-files panels.
  90         return not is_transient_view(v) and bool(v.file_name()) and v.element() is None
  91 
  92     def on_load_async(self) -> None:
  93         if self._is_regular_view():
  94             self._register_async()
  95 
  96     def on_activated_async(self) -> None:
  97         if self._is_regular_view() and not self.view.is_loading():
  98             self._register_async()
  99 
  100     def purge_changes(self) -> None:
  101         with self._session_views_lock:
  102             for sv in self.session_views():
  103                 sv.purge_changes()
  104 
  105     def on_text_changed(self, changes: Iterable[sublime.TextChange]) -> None:
  106         if self.view.is_primary():
  107             with self._session_views_lock:
  108                 for sv in self.session_views():
  109                     sv.on_text_changed(changes)
  110 
  111     def on_pre_save(self) -> None:
  112         with self._session_views_lock:
  113             for sv in self.session_views():
  114                 sv.on_pre_save()
  115 
  116     def on_post_save(self) -> None:
  117         if self.view.file_name() != self._file_name:
  118             self._file_name = ''
  119             self._clear_async()
  120             sublime.set_timeout_async(self._register_async)
  121             return
  122         with self._session_views_lock:
  123             for sv in self.session_views():
  124                 sv.on_post_save()
  125 
  126     def on_close(self) -> None:
  127         self._clear_async()
  128 
  129     def on_query_context(self, key: str, operator: str, operand: Any, match_all: bool) -> bool:
  130         capability_prefix = "lsp.capabilities."
  131         if key.startswith(capability_prefix):
  132             return isinstance(self.view.settings().get(key[len(capability_prefix):]), dict)
  133         elif key in ("lsp.sessions", "setting.lsp_active"):
  134             return bool(self._session_views)
  135         else:
  136             return False
  137 
  138     def __str__(self) -> str:
  139         return str(self.view.id())
  140
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/plugin/core/documents.py b/plugin/core/documents.py
  --- a/plugin/core/documents.py
  +++ b/plugin/core/documents.py
  @@ -126,10 +126,14 @@
       def on_close(self) -> None:
           self._clear_async()
   
  -    def on_query_context(self, key: str, operator: str, operand: Any, match_all: bool) -> bool:
  -        capability_prefix = "lsp.capabilities."
  -        if key.startswith(capability_prefix):
  -            return isinstance(self.view.settings().get(key[len(capability_prefix):]), dict)
  +    def on_query_context(self, key: str, operator: int, operand: Any, match_all: bool) -> bool:
  +        if key == "lsp.session_with_capability" and operator == sublime.OP_EQUAL and isinstance(operand, str):
  +            capabilities = [s.strip() for s in operand.split("|")]
  +            get = self.view.settings().get
  +            for capability in capabilities:
  +                if isinstance(get(capability), dict):
  +                    return True
  +            return False
           elif key in ("lsp.sessions", "setting.lsp_active"):
               return bool(self._session_views)
           else:
  
verification_info: {"golden_diff": "diff --git a/plugin/core/documents.py b/plugin/core/documents.py\n--- a/plugin/core/documents.py\n+++ b/plugin/core/documents.py\n@@ -126,10 +126,14 @@\n     def on_close(self) -> None:\n         self._clear_async()\n \n-    def on_query_context(self, key: str, operator: str, operand: Any, match_all: bool) -> bool:\n-        capability_prefix = \"lsp.capabilities.\"\n-        if key.startswith(capability_prefix):\n-            return isinstance(self.view.settings().get(key[len(capability_prefix):]), dict)\n+    def on_query_context(self, key: str, operator: int, operand: Any, match_all: bool) -> bool:\n+        if key == \"lsp.session_with_capability\" and operator == sublime.OP_EQUAL and isinstance(operand, str):\n+            capabilities = [s.strip() for s in operand.split(\"|\")]\n+            get = self.view.settings().get\n+            for capability in capabilities:\n+                if isinstance(get(capability), dict):\n+                    return True\n+            return False\n         elif key in (\"lsp.sessions\", \"setting.lsp_active\"):\n             return bool(self._session_views)\n         else:\n", "issue": "Provide a context key to check if LSP has a specific capability\n<del>\r\nPossible use case of the context key is to define custom keybind for go to definitions.\r\nWith the context key, it allows me to bind `super+alt+down` to both `goto_definition` and `lsp_symbol_definition`.\r\n\r\n\r\n```js\r\n{ \r\n   // this is the default key for `goto_definition`\r\n  \"keys\": [\"super+alt+down\"], \"command\": \"goto_definition\" \r\n},\r\n{ \r\n  \"keys\": [\"super+alt+down\"], \"command\": \"lsp_symbol_definition\" ,\r\n  \"context\": [\r\n\t\t\t{ \"key\": \"lsp.is.active\", \"operator\": \"equal\", \"operand\": true }\r\n\t\t]\r\n}\r\n```\r\n</del>\r\n\r\n\r\nUpdate: @rwols pointed out that there is `lsp_active` to check, so this issue is now requesting a key for checking more specific capability.\n", "before_files": [{"content": "from .registry import get_position\nfrom .registry import LSPViewEventListener\nfrom .session_view import SessionView\nfrom .sessions import Session\nfrom .typing import Any, Callable, Optional, Dict, Generator, Iterable\nfrom .windows import AbstractViewListener\nimport sublime\nimport threading\n\n\nSUBLIME_WORD_MASK = 515\n\n\ndef is_at_word(view: sublime.View, event: Optional[dict]) -> bool:\n    pos = get_position(view, event)\n    return position_is_word(view, pos)\n\n\ndef position_is_word(view: sublime.View, position: int) -> bool:\n    point_classification = view.classify(position)\n    if point_classification & SUBLIME_WORD_MASK:\n        return True\n    else:\n        return False\n\n\ndef is_transient_view(view: sublime.View) -> bool:\n    window = view.window()\n    if window:\n        if window.get_view_index(view)[1] == -1:\n            return True  # Quick panel transient views\n        return view == window.transient_view_in_group(window.active_group())\n    else:\n        return True\n\n\ndef _clear_async(lock: threading.Lock, session_views: Dict[str, SessionView]) -> Callable[[], None]:\n\n    def run() -> None:\n        with lock:\n            session_views.clear()\n\n    return run\n\n\nclass DocumentSyncListener(LSPViewEventListener, AbstractViewListener):\n\n    @classmethod\n    def applies_to_primary_view_only(cls) -> bool:\n        return False\n\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self._file_name = ''\n        self._session_views = {}  # type: Dict[str, SessionView]\n        self._session_views_lock = threading.Lock()\n\n    def __del__(self) -> None:\n        self._clear_async()\n\n    def _clear_async(self) -> None:\n        sublime.set_timeout_async(_clear_async(self._session_views_lock, self._session_views))\n\n    def on_session_initialized_async(self, session: Session) -> None:\n        assert not self.view.is_loading()\n        with self._session_views_lock:\n            if session.config.name not in self._session_views:\n                self._session_views[session.config.name] = SessionView(self, session)\n                self.view.settings().set(\"lsp_active\", True)\n\n    def on_session_shutdown_async(self, session: Session) -> None:\n        with self._session_views_lock:\n            self._session_views.pop(session.config.name, None)\n            if not self._session_views:\n                self.view.settings().erase(\"lsp_active\")\n\n    def session_views(self) -> Generator[SessionView, None, None]:\n        yield from self._session_views.values()\n\n    def _register_async(self) -> None:\n        file_name = self.view.file_name()\n        if file_name:\n            self._file_name = file_name\n            self.manager.register_listener_async(self)\n\n    def _is_regular_view(self) -> bool:\n        v = self.view\n        # Not from the quick panel (CTRL+P), must have a filename on-disk, and not a special view like a console,\n        # output panel or find-in-files panels.\n        return not is_transient_view(v) and bool(v.file_name()) and v.element() is None\n\n    def on_load_async(self) -> None:\n        if self._is_regular_view():\n            self._register_async()\n\n    def on_activated_async(self) -> None:\n        if self._is_regular_view() and not self.view.is_loading():\n            self._register_async()\n\n    def purge_changes(self) -> None:\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.purge_changes()\n\n    def on_text_changed(self, changes: Iterable[sublime.TextChange]) -> None:\n        if self.view.is_primary():\n            with self._session_views_lock:\n                for sv in self.session_views():\n                    sv.on_text_changed(changes)\n\n    def on_pre_save(self) -> None:\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.on_pre_save()\n\n    def on_post_save(self) -> None:\n        if self.view.file_name() != self._file_name:\n            self._file_name = ''\n            self._clear_async()\n            sublime.set_timeout_async(self._register_async)\n            return\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.on_post_save()\n\n    def on_close(self) -> None:\n        self._clear_async()\n\n    def on_query_context(self, key: str, operator: str, operand: Any, match_all: bool) -> bool:\n        capability_prefix = \"lsp.capabilities.\"\n        if key.startswith(capability_prefix):\n            return isinstance(self.view.settings().get(key[len(capability_prefix):]), dict)\n        elif key in (\"lsp.sessions\", \"setting.lsp_active\"):\n            return bool(self._session_views)\n        else:\n            return False\n\n    def __str__(self) -> str:\n        return str(self.view.id())\n", "path": "plugin/core/documents.py"}], "after_files": [{"content": "from .registry import get_position\nfrom .registry import LSPViewEventListener\nfrom .session_view import SessionView\nfrom .sessions import Session\nfrom .typing import Any, Callable, Optional, Dict, Generator, Iterable\nfrom .windows import AbstractViewListener\nimport sublime\nimport threading\n\n\nSUBLIME_WORD_MASK = 515\n\n\ndef is_at_word(view: sublime.View, event: Optional[dict]) -> bool:\n    pos = get_position(view, event)\n    return position_is_word(view, pos)\n\n\ndef position_is_word(view: sublime.View, position: int) -> bool:\n    point_classification = view.classify(position)\n    if point_classification & SUBLIME_WORD_MASK:\n        return True\n    else:\n        return False\n\n\ndef is_transient_view(view: sublime.View) -> bool:\n    window = view.window()\n    if window:\n        if window.get_view_index(view)[1] == -1:\n            return True  # Quick panel transient views\n        return view == window.transient_view_in_group(window.active_group())\n    else:\n        return True\n\n\ndef _clear_async(lock: threading.Lock, session_views: Dict[str, SessionView]) -> Callable[[], None]:\n\n    def run() -> None:\n        with lock:\n            session_views.clear()\n\n    return run\n\n\nclass DocumentSyncListener(LSPViewEventListener, AbstractViewListener):\n\n    @classmethod\n    def applies_to_primary_view_only(cls) -> bool:\n        return False\n\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self._file_name = ''\n        self._session_views = {}  # type: Dict[str, SessionView]\n        self._session_views_lock = threading.Lock()\n\n    def __del__(self) -> None:\n        self._clear_async()\n\n    def _clear_async(self) -> None:\n        sublime.set_timeout_async(_clear_async(self._session_views_lock, self._session_views))\n\n    def on_session_initialized_async(self, session: Session) -> None:\n        assert not self.view.is_loading()\n        with self._session_views_lock:\n            if session.config.name not in self._session_views:\n                self._session_views[session.config.name] = SessionView(self, session)\n                self.view.settings().set(\"lsp_active\", True)\n\n    def on_session_shutdown_async(self, session: Session) -> None:\n        with self._session_views_lock:\n            self._session_views.pop(session.config.name, None)\n            if not self._session_views:\n                self.view.settings().erase(\"lsp_active\")\n\n    def session_views(self) -> Generator[SessionView, None, None]:\n        yield from self._session_views.values()\n\n    def _register_async(self) -> None:\n        file_name = self.view.file_name()\n        if file_name:\n            self._file_name = file_name\n            self.manager.register_listener_async(self)\n\n    def _is_regular_view(self) -> bool:\n        v = self.view\n        # Not from the quick panel (CTRL+P), must have a filename on-disk, and not a special view like a console,\n        # output panel or find-in-files panels.\n        return not is_transient_view(v) and bool(v.file_name()) and v.element() is None\n\n    def on_load_async(self) -> None:\n        if self._is_regular_view():\n            self._register_async()\n\n    def on_activated_async(self) -> None:\n        if self._is_regular_view() and not self.view.is_loading():\n            self._register_async()\n\n    def purge_changes(self) -> None:\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.purge_changes()\n\n    def on_text_changed(self, changes: Iterable[sublime.TextChange]) -> None:\n        if self.view.is_primary():\n            with self._session_views_lock:\n                for sv in self.session_views():\n                    sv.on_text_changed(changes)\n\n    def on_pre_save(self) -> None:\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.on_pre_save()\n\n    def on_post_save(self) -> None:\n        if self.view.file_name() != self._file_name:\n            self._file_name = ''\n            self._clear_async()\n            sublime.set_timeout_async(self._register_async)\n            return\n        with self._session_views_lock:\n            for sv in self.session_views():\n                sv.on_post_save()\n\n    def on_close(self) -> None:\n        self._clear_async()\n\n    def on_query_context(self, key: str, operator: int, operand: Any, match_all: bool) -> bool:\n        if key == \"lsp.session_with_capability\" and operator == sublime.OP_EQUAL and isinstance(operand, str):\n            capabilities = [s.strip() for s in operand.split(\"|\")]\n            get = self.view.settings().get\n            for capability in capabilities:\n                if isinstance(get(capability), dict):\n                    return True\n            return False\n        elif key in (\"lsp.sessions\", \"setting.lsp_active\"):\n            return bool(self._session_views)\n        else:\n            return False\n\n    def __str__(self) -> str:\n        return str(self.view.id())\n", "path": "plugin/core/documents.py"}]}