-
Notifications
You must be signed in to change notification settings - Fork 32
Add workspace symbols #106
Changes from 10 commits
25d171f
3c6f673
d46052b
10830b1
c3ba087
93704f5
0675f49
81ccecf
df9bc43
a0db775
719c354
c2543fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
require "json" | ||
|
||
module Scry | ||
struct WorkspaceSymbolParams | ||
JSON.mapping({ | ||
query: String, | ||
}, true) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
require "compiler/crystal/syntax" | ||
require "./protocol/workspace_symbol_params" | ||
|
||
module Scry | ||
class SymbolVisitor < Crystal::Visitor | ||
|
@@ -113,6 +114,46 @@ module Scry | |
node.accept(visitor) | ||
|
||
ResponseMessage.new(@text_document.id, visitor.symbols) | ||
rescue | ||
ResponseMessage.new(@text_document.id, [] of SymbolInformation) | ||
end | ||
end | ||
|
||
class WorkspaceSymbolProcessor | ||
@@crystal_path_symbols = [] of SymbolInformation | ||
@query_regex : Regex | ||
|
||
def initialize(@msg_id : Int32 | String, @root_path : String, @query : String) | ||
@workspace_files = Dir.glob(File.join(root_path, "**", "*.cr")) | ||
if @@crystal_path_symbols.empty? | ||
# Memoize crystal stdlib | ||
@@crystal_path_symbols = search_symbols(Dir.glob(File.join(Scry.default_crystal_path, "**", "*.cr")), Regex.new(".*")) | ||
end | ||
@query_regex = Regex.new(@query) | ||
end | ||
|
||
def run | ||
symbols = [] of SymbolInformation | ||
unless @query.empty? | ||
symbols.concat search_symbols(@workspace_files, @query_regex) | ||
symbols.concat @@crystal_path_symbols.select(&.name.match(@query_regex)) | ||
end | ||
ResponseMessage.new(@msg_id, symbols) | ||
end | ||
|
||
def search_symbols(files, query_regex) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if it's a good idea, but you could have @@crystal_path_symbols : Array(SymbolInformation)?
def self.crystal_path_symbols
@@crystal_path_symbols ||= begin
crystal_path_files = Dir.glob(File.join(Scry.default_crystal_path, "**", "*.cr"))
search_symbols(crystal_path_files, Regex.new(".*"))
end
end
# and when you need crystal_path_symbols, you just call the getter, which will return
# `@@crystal_path_symbols` if it's not nil, and will search the symbols if it's nil.
def self.search_symbols(x, y)
end This way you can remove the cvar init from the initiailizer and keep it clean 😃 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
symbols = [] of SymbolInformation | ||
files.each do |file| | ||
visitor = SymbolVisitor.new("file://#{file}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if there is anyway we can reuse the SymbolProcessor here since the code is so similar? Although it would probably need to be decoupled from the ResponseMessage, maybe we can refactor that later. |
||
parser = Crystal::Parser.new(File.read(file)) | ||
parser.filename = file | ||
node = parser.parse | ||
node.accept(visitor) | ||
symbols.concat visitor.symbols.select(&.name.match(query_regex)) | ||
rescue | ||
next | ||
end | ||
symbols | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use regex here? Or add another spec for a regex query?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little
Use File.join
commit ? 😃