Skip to content

Commit

Permalink
Discard diagnostics in a few cases (#1816)
Browse files Browse the repository at this point in the history
- When the file is outside the window folders, ignore diagnostics
- When the file matches binary_exclude_patterns, ignore it
- When the file matches file_exclude_patterns, ignore it
- When the file matches folder_exclude_patterns, ignore it

This doesn't take care of the index_exclude_patterns and
index_exclude_gitignore settings. We could re-invent the
wheel and think about how to parse the .gitignore file. But
it should really be an API endpoint: sublimehq/sublime_text#4712

Also, Sublime Text seems to not report folder-specific exclude
patterns: sublimehq/sublime_text#4717
  • Loading branch information
rwols authored Aug 5, 2021
1 parent 40a05e7 commit ba2d081
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 0 deletions.
2 changes: 2 additions & 0 deletions plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .core.sessions import SessionBufferProtocol
from .core.sessions import unregister_plugin
from .core.types import ClientConfig
from .core.types import matches_pattern
from .core.url import filename_to_uri
from .core.url import uri_to_filename
from .core.version import __version__
Expand All @@ -31,6 +32,7 @@
'FileWatcherEvent',
'FileWatcherEventType',
'FileWatcherProtocol',
'matches_pattern',
'Notification',
'register_file_watcher_implementation',
'register_plugin',
Expand Down
12 changes: 12 additions & 0 deletions plugin/core/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ def get_project_path(self, file_path: str) -> Optional[str]:
"""
pass

@abstractmethod
def should_present_diagnostics(self, uri: DocumentUri) -> Optional[str]:
"""
Should the diagnostics for this URI be shown in the view? Return a reason why not
"""

# Mutators

@abstractmethod
Expand Down Expand Up @@ -1283,6 +1289,12 @@ def m_workspace_applyEdit(self, params: Any, request_id: Any) -> None:
def m_textDocument_publishDiagnostics(self, params: Any) -> None:
"""handles the textDocument/publishDiagnostics notification"""
uri = params["uri"]
mgr = self.manager()
if not mgr:
return
reason = mgr.should_present_diagnostics(uri)
if isinstance(reason, str):
return debug("ignoring unsuitable diagnostics for", uri, "reason:", reason)
sb = self.get_session_buffer_for_uri_async(uri)
if sb:
sb.on_diagnostics_async(params["diagnostics"], params.get("version"))
Expand Down
12 changes: 12 additions & 0 deletions plugin/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from wcmatch.glob import globmatch
from wcmatch.glob import GLOBSTAR
import contextlib
import fnmatch
import os
import socket
import sublime
Expand Down Expand Up @@ -59,6 +60,17 @@ def diff(old: Iterable[T], new: Iterable[T]) -> Tuple[Set[T], Set[T]]:
return added, removed


def matches_pattern(path: str, patterns: Any) -> bool:
if not isinstance(patterns, list):
return False
for pattern in patterns:
if not isinstance(pattern, str):
continue
if fnmatch.fnmatch(path, pattern):
return True
return False


def debounced(f: Callable[[], Any], timeout_ms: int = 0, condition: Callable[[], bool] = lambda: True,
async_thread: bool = False) -> None:
"""
Expand Down
21 changes: 21 additions & 0 deletions plugin/core/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .promise import Promise
from .protocol import Diagnostic
from .protocol import DiagnosticSeverity
from .protocol import DocumentUri
from .protocol import Error
from .protocol import Location
from .sessions import get_plugin
Expand All @@ -20,7 +21,9 @@
from .settings import userprefs
from .transports import create_transport
from .types import ClientConfig
from .types import matches_pattern
from .typing import Optional, Any, Dict, Deque, List, Generator, Tuple, Iterable, Sequence, Union
from .url import parse_uri
from .views import extract_variables
from .views import make_link
from .workspace import ProjectFolders
Expand Down Expand Up @@ -442,6 +445,24 @@ def get_project_path(self, file_path: str) -> Optional[str]:
candidate = folder
return candidate

def should_present_diagnostics(self, uri: DocumentUri) -> Optional[str]:
scheme, path = parse_uri(uri)
if scheme != "file":
return None
if not self._workspace.contains(path):
return "not inside window folders"
view = self._window.active_view()
if not view:
return None
settings = view.settings()
if matches_pattern(path, settings.get("binary_file_patterns")):
return "matches a pattern in binary_file_patterns"
if matches_pattern(path, settings.get("file_exclude_patterns")):
return "matches a pattern in file_exclude_patterns"
if matches_pattern(path, settings.get("folder_exclude_patterns")):
return "matches a pattern in folder_exclude_patterns"
return None

def on_post_exit_async(self, session: Session, exit_code: int, exception: Optional[Exception]) -> None:
self._sessions.discard(session)
for listener in self._listeners:
Expand Down
4 changes: 4 additions & 0 deletions tests/test_session.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from LSP.plugin.core.collections import DottedDict
from LSP.plugin.core.protocol import Diagnostic
from LSP.plugin.core.protocol import DocumentUri
from LSP.plugin.core.protocol import Error
from LSP.plugin.core.protocol import TextDocumentSyncKindFull
from LSP.plugin.core.protocol import TextDocumentSyncKindIncremental
Expand Down Expand Up @@ -32,6 +33,9 @@ def sessions(self, view: sublime.View, capability: Optional[str] = None) -> Gene
def get_project_path(self, file_name: str) -> Optional[str]:
return None

def should_present_diagnostics(self, uri: DocumentUri) -> Optional[str]:
return None

def start_async(self, configuration: ClientConfig, initiating_view: sublime.View) -> None:
pass

Expand Down

0 comments on commit ba2d081

Please sign in to comment.