mbeditor 0.5.3 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -0
- data/README.md +7 -0
- data/app/assets/javascripts/mbeditor/application.js +3 -0
- data/app/assets/javascripts/mbeditor/components/ChangelogView.js +145 -0
- data/app/assets/javascripts/mbeditor/components/DiffViewer.js +1 -1
- data/app/assets/javascripts/mbeditor/components/EditorPanel.js +359 -31
- data/app/assets/javascripts/mbeditor/components/FileTree.js +177 -116
- data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +952 -143
- data/app/assets/javascripts/mbeditor/components/TabBar.js +9 -0
- data/app/assets/javascripts/mbeditor/conflict_parser.js +48 -0
- data/app/assets/javascripts/mbeditor/editor_plugins.js +420 -67
- data/app/assets/javascripts/mbeditor/editor_store.js +1 -0
- data/app/assets/javascripts/mbeditor/file_service.js +34 -6
- data/app/assets/javascripts/mbeditor/git_service.js +2 -1
- data/app/assets/javascripts/mbeditor/history_service.js +177 -0
- data/app/assets/javascripts/mbeditor/search_service.js +1 -0
- data/app/assets/javascripts/mbeditor/tab_manager.js +8 -5
- data/app/assets/stylesheets/mbeditor/application.css +112 -0
- data/app/assets/stylesheets/mbeditor/editor.css +443 -78
- data/app/channels/mbeditor/editor_channel.rb +5 -41
- data/app/controllers/mbeditor/application_controller.rb +8 -1
- data/app/controllers/mbeditor/editors_controller.rb +276 -654
- data/app/controllers/mbeditor/git_controller.rb +2 -61
- data/app/services/mbeditor/availability_probe.rb +83 -0
- data/app/services/mbeditor/code_search_service.rb +42 -0
- data/app/services/mbeditor/editor_state_service.rb +91 -0
- data/app/services/mbeditor/exclusion_matcher.rb +23 -0
- data/app/services/mbeditor/file_operation_service.rb +68 -0
- data/app/services/mbeditor/file_tree_service.rb +69 -0
- data/app/services/mbeditor/git_combined_diff_service.rb +43 -0
- data/app/services/mbeditor/git_commit_detail_service.rb +46 -0
- data/app/services/mbeditor/git_info_service.rb +151 -0
- data/app/services/mbeditor/git_service.rb +36 -26
- data/app/services/mbeditor/js_definition_service.rb +59 -0
- data/app/services/mbeditor/js_members_service.rb +62 -0
- data/app/services/mbeditor/process_runner.rb +48 -0
- data/app/services/mbeditor/rails_related_files_service.rb +282 -0
- data/app/services/mbeditor/ruby_definition_service.rb +77 -101
- data/app/services/mbeditor/schema_service.rb +270 -0
- data/app/services/mbeditor/search_replace_service.rb +184 -0
- data/app/services/mbeditor/test_runner_service.rb +5 -27
- data/app/views/layouts/mbeditor/application.html.erb +2 -2
- data/config/routes.rb +8 -1
- data/lib/mbeditor/configuration.rb +4 -2
- data/lib/mbeditor/version.rb +1 -1
- data/public/monaco-editor/vs/language/css/cssMode.js +13 -0
- data/public/monaco-editor/vs/language/css/cssWorker.js +77 -0
- data/public/monaco-editor/vs/language/html/htmlMode.js +13 -0
- data/public/monaco-editor/vs/language/html/htmlWorker.js +454 -0
- data/public/monaco-editor/vs/language/json/jsonMode.js +19 -0
- data/public/monaco-editor/vs/language/json/jsonWorker.js +42 -0
- metadata +26 -3
- data/app/services/mbeditor/unused_methods_service.rb +0 -139
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "open3"
|
|
4
|
-
require "timeout"
|
|
5
|
-
|
|
6
|
-
module Mbeditor
|
|
7
|
-
# Finds method definitions in a file that have no call-sites anywhere in the
|
|
8
|
-
# workspace. Uses a single ripgrep (or grep) subprocess with an alternation
|
|
9
|
-
# pattern so cost is O(1) subprocesses regardless of how many methods the
|
|
10
|
-
# file contains.
|
|
11
|
-
#
|
|
12
|
-
# Results are cached per-file; entries are invalidated when the file's mtime
|
|
13
|
-
# changes OR when the entry is older than CACHE_TTL_SECONDS (handles edits
|
|
14
|
-
# to other files that may add or remove call-sites).
|
|
15
|
-
#
|
|
16
|
-
# Usage:
|
|
17
|
-
# UnusedMethodsService.call(workspace_root, abs_path,
|
|
18
|
-
# excluded_dirnames: [], excluded_paths: [])
|
|
19
|
-
# → [{ name: "my_method", line: 42 }, ...]
|
|
20
|
-
class UnusedMethodsService
|
|
21
|
-
CACHE_TTL_SECONDS = 30
|
|
22
|
-
RG_TIMEOUT = 10
|
|
23
|
-
GREP_TIMEOUT = 30
|
|
24
|
-
|
|
25
|
-
@cache = {}
|
|
26
|
-
@cache_mutex = Mutex.new
|
|
27
|
-
|
|
28
|
-
class << self
|
|
29
|
-
def call(workspace_root, file_path, excluded_dirnames: [], excluded_paths: [])
|
|
30
|
-
file_path = file_path.to_s
|
|
31
|
-
|
|
32
|
-
begin
|
|
33
|
-
mtime = File.mtime(file_path).to_f
|
|
34
|
-
rescue StandardError
|
|
35
|
-
return []
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Return cached result if file mtime matches and the entry is fresh.
|
|
39
|
-
cached = @cache_mutex.synchronize { @cache[file_path] }
|
|
40
|
-
if cached && cached[:mtime] == mtime &&
|
|
41
|
-
(Process.clock_gettime(Process::CLOCK_MONOTONIC) - cached[:ts]) < CACHE_TTL_SECONDS
|
|
42
|
-
return cached[:result]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Ensure the file is indexed (populates module_names / include_calls too).
|
|
46
|
-
defs = RubyDefinitionService.defs_in_file(file_path)
|
|
47
|
-
if defs.empty?
|
|
48
|
-
# File not yet in cache; trigger a parse of just this one file by
|
|
49
|
-
# calling the definition service with a dummy symbol.
|
|
50
|
-
RubyDefinitionService.call(workspace_root, "__mbeditor_warmup__",
|
|
51
|
-
excluded_dirnames: excluded_dirnames,
|
|
52
|
-
excluded_paths: excluded_paths)
|
|
53
|
-
defs = RubyDefinitionService.defs_in_file(file_path)
|
|
54
|
-
end
|
|
55
|
-
return [] if defs.empty?
|
|
56
|
-
|
|
57
|
-
method_names = defs.keys
|
|
58
|
-
counts = count_occurrences(method_names, workspace_root.to_s,
|
|
59
|
-
excluded_dirnames: excluded_dirnames,
|
|
60
|
-
excluded_paths: excluded_paths)
|
|
61
|
-
|
|
62
|
-
# A method with ≤1 total occurrence has only its own `def` line; no call-sites.
|
|
63
|
-
unused = method_names.select { |n| counts.fetch(n, 0) <= 1 }
|
|
64
|
-
result = unused.filter_map do |name|
|
|
65
|
-
entries = defs[name]
|
|
66
|
-
next unless entries&.any?
|
|
67
|
-
{ name: name, line: entries.first[:line] }
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
71
|
-
@cache_mutex.synchronize do
|
|
72
|
-
@cache[file_path] = { mtime: mtime, ts: ts, result: result }
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
result
|
|
76
|
-
rescue StandardError
|
|
77
|
-
[]
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Exposed for tests.
|
|
81
|
-
def clear_cache!
|
|
82
|
-
@cache_mutex.synchronize { @cache.clear }
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
private
|
|
86
|
-
|
|
87
|
-
RG_AVAILABLE = system("which rg > /dev/null 2>&1")
|
|
88
|
-
|
|
89
|
-
def count_occurrences(method_names, workspace_root, excluded_dirnames:, excluded_paths:)
|
|
90
|
-
# Build one alternation pattern matching any of the method names as
|
|
91
|
-
# whole identifiers. We escape each name and join with |.
|
|
92
|
-
escaped = method_names.map { |n| Regexp.escape(n) }
|
|
93
|
-
pattern = "\\b(#{escaped.join('|')})\\b"
|
|
94
|
-
|
|
95
|
-
if RG_AVAILABLE
|
|
96
|
-
run_ripgrep(pattern, method_names, workspace_root, excluded_paths)
|
|
97
|
-
else
|
|
98
|
-
run_grep(pattern, method_names, workspace_root, excluded_dirnames)
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# ripgrep: --only-matching outputs one match per line (just the matched text).
|
|
103
|
-
def run_ripgrep(pattern, method_names, workspace_root, excluded_paths)
|
|
104
|
-
args = %w[rg --only-matching --no-filename --no-ignore --glob **/*.rb]
|
|
105
|
-
excluded_paths.each { |p| args += ["--glob", "!#{p}"] }
|
|
106
|
-
args += ["-e", pattern, workspace_root]
|
|
107
|
-
|
|
108
|
-
counts = Hash.new(0)
|
|
109
|
-
name_set = method_names.to_set
|
|
110
|
-
Timeout.timeout(RG_TIMEOUT) do
|
|
111
|
-
IO.popen(args, err: File::NULL) do |io|
|
|
112
|
-
io.each_line { |line| name = line.chomp; counts[name] += 1 if name_set.include?(name) }
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
counts
|
|
116
|
-
rescue StandardError
|
|
117
|
-
{}
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# grep -oh: -o outputs only the matching part, -h suppresses filenames.
|
|
121
|
-
def run_grep(pattern, method_names, workspace_root, excluded_dirnames)
|
|
122
|
-
args = ["grep", "-roh", "-E", pattern, "--include=*.rb"]
|
|
123
|
-
excluded_dirnames.each { |d| args += ["--exclude-dir=#{d}"] }
|
|
124
|
-
args << workspace_root
|
|
125
|
-
|
|
126
|
-
counts = Hash.new(0)
|
|
127
|
-
name_set = method_names.to_set
|
|
128
|
-
Timeout.timeout(GREP_TIMEOUT) do
|
|
129
|
-
IO.popen(args, err: File::NULL) do |io|
|
|
130
|
-
io.each_line { |line| name = line.chomp; counts[name] += 1 if name_set.include?(name) }
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
counts
|
|
134
|
-
rescue StandardError
|
|
135
|
-
{}
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|