Skip to content

Commit

Permalink
Fix handling of folder_exclude_patterns in projects (#2237)
Browse files Browse the repository at this point in the history
  • Loading branch information
rchl authored Apr 22, 2023
1 parent fde4afa commit 2a1d4f3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 13 deletions.
13 changes: 2 additions & 11 deletions plugin/core/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,19 +359,10 @@ def should_ignore_diagnostics(self, uri: DocumentUri, configuration: ClientConfi
if matches_pattern(path, settings.get("file_exclude_patterns")):
return "matches a pattern in file_exclude_patterns"
patterns = [sublime_pattern_to_glob(pattern, True) for pattern in settings.get("folder_exclude_patterns") or []]
project_data = self.window.project_data()
if project_data:
for folder in project_data.get('folders', []):
for pattern in folder.get('folder_exclude_patterns', []):
if pattern.startswith('//'):
patterns.append(sublime_pattern_to_glob(pattern, True, folder['path']))
elif pattern.startswith('/'):
patterns.append(sublime_pattern_to_glob(pattern, True))
else:
patterns.append(sublime_pattern_to_glob('//' + pattern, True, folder['path']))
patterns.append(sublime_pattern_to_glob('//**/' + pattern, True, folder['path']))
if matches_pattern(path, patterns):
return "matches a pattern in folder_exclude_patterns"
if self._workspace.includes_excluded_path(path):
return "matches a project's folder_exclude_patterns"
return None

def on_post_exit_async(self, session: Session, exit_code: int, exception: Optional[Exception]) -> None:
Expand Down
43 changes: 41 additions & 2 deletions plugin/core/workspace.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .protocol import WorkspaceFolder as LspWorkspaceFolder
from .types import diff
from .types import matches_pattern
from .types import sublime_pattern_to_glob
from .typing import Any, List, Union
from .url import filename_to_uri
import sublime
Expand Down Expand Up @@ -56,9 +58,32 @@ class ProjectFolders(object):
def __init__(self, window: sublime.Window) -> None:
self._window = window
self.folders = self._window.folders() # type: List[str]
# Per-folder ignore patterns. The list order matches the order of self.folders.
self._folders_exclude_patterns = [] # type: List[List[str]]
self._update_exclude_patterns(self.folders)

def _update_exclude_patterns(self, folders: List[str]) -> None:
self._folders_exclude_patterns = []
project_data = self._window.project_data()
if not isinstance(project_data, dict):
return
for i, folder in enumerate(project_data.get('folders', [])):
exclude_patterns = []
# Use canoncial path from `window.folders` rather than potentially relative path from project data.
path = folders[i]
for pattern in folder.get('folder_exclude_patterns', []):
if pattern.startswith('//'):
exclude_patterns.append(sublime_pattern_to_glob(pattern, True, path))
elif pattern.startswith('/'):
exclude_patterns.append(sublime_pattern_to_glob(pattern, True))
else:
exclude_patterns.append(sublime_pattern_to_glob('//' + pattern, True, path))
exclude_patterns.append(sublime_pattern_to_glob('//**/' + pattern, True, path))
self._folders_exclude_patterns.append(exclude_patterns)

def update(self) -> bool:
new_folders = self._window.folders()
self._update_exclude_patterns(new_folders)
added, removed = diff(self.folders, new_folders)
if added or removed:
self.folders = new_folders
Expand All @@ -68,8 +93,22 @@ def update(self) -> bool:
def includes_path(self, file_path: str) -> bool:
if self.folders:
return any(is_subpath_of(file_path, folder) for folder in self.folders)
else:
return True
return True

def includes_excluded_path(self, file_path: str) -> bool:
"""Path is excluded if it's within one or more workspace folders and in at least one of the folders it's not
excluded using `folder_exclude_patterns`."""
if not self.folders:
return False
is_excluded = False
for i, folder in enumerate(self.folders):
if not is_subpath_of(file_path, folder):
continue
exclude_patterns = self._folders_exclude_patterns[i]
is_excluded = matches_pattern(file_path, exclude_patterns)
if not is_excluded:
break
return is_excluded

def contains(self, view_or_file_name: Union[str, sublime.View]) -> bool:
file_path = view_or_file_name.file_name() if isinstance(view_or_file_name, sublime.View) else view_or_file_name
Expand Down

0 comments on commit 2a1d4f3

Please sign in to comment.