Skip to content

Commit

Permalink
remove FileOperationFilterChecker, FileOperationFilterMatcher in favo…
Browse files Browse the repository at this point in the history
…r of match_file_operation_filters
  • Loading branch information
predragnikolic committed Jul 2, 2024
1 parent 8ef443c commit d1342b9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 58 deletions.
64 changes: 13 additions & 51 deletions plugin/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .collections import DottedDict
from .file_watcher import FileWatcherEventType
from .logging import debug, set_debug_logging
from .protocol import FileOperationFilter, FileOperationPattern, FileOperationPatternKind, TextDocumentSyncKind
from .protocol import FileOperationFilter, FileOperationPattern, FileOperationPatternKind, FileOperationRegistrationOptions, TextDocumentSyncKind
from .url import filename_to_uri
from .url import parse_uri
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, TypedDict, TypeVar, Union
Expand Down Expand Up @@ -440,69 +440,31 @@ def matches(self, view: sublime.View) -> bool:
"""Does this selector match the view? A selector with no filters matches all views."""
return any(f(view) for f in self.filters) if self.filters else True


class FileOperationFilterChecker:
"""
A file operation filter denotes a view or path through properties like scheme or pattern. An example is a filter
that applies to TypeScript files on disk. Another example is a filter that applies to JSON files with name
package.json:
{
"scheme": "file",
"pattern": {
"glob": "**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}",
"matches": "file"
}
}
"""

__slots__ = ("scheme", "pattern")

def __init__(
self,
scheme: str | None = None,
pattern: FileOperationPattern | None = None
) -> None:
self.scheme = scheme
self.pattern = pattern

def __call__(self, path: str, view: sublime.View | None) -> bool:
if self.scheme and view:
def match_file_operation_filters(file_operation_options: FileOperationRegistrationOptions, path: str, view: sublime.View | None) -> bool:
def matches(file_operation_filter: FileOperationFilter) -> bool:
pattern = file_operation_filter.get('pattern')
scheme = file_operation_filter.get('scheme')
if scheme and view:
uri = view.settings().get("lsp_uri")
if isinstance(uri, str) and parse_uri(uri)[0] != self.scheme:
if isinstance(uri, str) and parse_uri(uri)[0] != scheme:
return False
if self.pattern:
matches = self.pattern.get('matches')
if pattern:
matches = pattern.get('matches')
if matches:
if matches == FileOperationPatternKind.File and os.path.isdir(path):
return False
if matches == FileOperationPatternKind.Folder and os.path.isfile(path):
return False
options = self.pattern.get('options', {})
options = pattern.get('options', {})
flags = GLOBSTAR | BRACE
if options.get('ignoreCase', False):
flags |= IGNORECASE
if not globmatch(path, self.pattern['glob'], flags=flags):
if not globmatch(path, pattern['glob'], flags=flags):
return False
return True


class FileOperationFilterMatcher:
"""
A FileOperationFilterMatcher is a list of FileOperationFilterChecker.
Provides logic to see if a path/view matches the specified FileOperationFilter's.
"""

__slots__ = ("filters",)

def __init__(self, file_filters: list[FileOperationFilter]) -> None:
self.filters = [FileOperationFilterChecker(**file_filter) for file_filter in file_filters]

def __bool__(self) -> bool:
return bool(self.filters)

def matches(self, new_path: str, view: sublime.View | None) -> bool:
"""Does this selector match the view? A selector with no filters matches all views."""
return any(f(new_path, view) for f in self.filters) if self.filters else True
filters = [matches(file_operation_filter) for file_operation_filter in file_operation_options.get('filters')]
return any(filters) if filters else True


# method -> (capability dotted path, optional registration dotted path)
Expand Down
12 changes: 5 additions & 7 deletions plugin/rename_file.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from .core.types import FileOperationFilterMatcher
from .core.types import match_file_operation_filters
from .core.open import open_file_uri
from .core.protocol import Notification, RenameFilesParams, Request, WorkspaceEdit
from .core.registry import LspWindowCommand
Expand Down Expand Up @@ -73,8 +73,8 @@ def run(
self.rename_path(old_path, new_path)
self.notify_did_rename(rename_file_params, new_path, view)
return
filters = (session.get_capability('workspace.fileOperations.willRename') or {}).get('filters')
if filters and FileOperationFilterMatcher(filters).matches(old_path, view):
file_operation_options = session.get_capability('workspace.fileOperations.willRename')
if file_operation_options and match_file_operation_filters(file_operation_options, old_path, view):
request = Request.willRenameFiles(rename_file_params)
session.send_request(
request,
Expand Down Expand Up @@ -126,8 +126,6 @@ def restore_regions(v: sublime.View | None) -> None:

def notify_did_rename(self, rename_file_params: RenameFilesParams, path: str, view: sublime.View | None):
for s in self.sessions():
filters = (s.get_capability('workspace.fileOperations.didRename') or {}).get('filters')
if not filters:
continue
if FileOperationFilterMatcher(filters).matches(path, view):
file_operation_options = s.get_capability('workspace.fileOperations.didRename')
if file_operation_options and match_file_operation_filters(file_operation_options, path, view):
s.send_notification(Notification.didRenameFiles(rename_file_params))

0 comments on commit d1342b9

Please sign in to comment.