From 78ad6a0af76ef3cd4c137f647bcd6d8a821348de Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Sun, 14 Sep 2014 19:15:29 +0000 Subject: [PATCH] #162 --- editors/textadept/modules/dmd/dcd.lua | 42 +++++++++++++++++ src/actypes.d | 17 +++++++ src/autocomplete.d | 65 +++++++++++++++++++++++++++ src/client.d | 25 ++++++++++- src/messages.d | 12 +++++ src/modulecache.d | 5 +++ src/server.d | 6 +++ 7 files changed, 170 insertions(+), 2 deletions(-) diff --git a/editors/textadept/modules/dmd/dcd.lua b/editors/textadept/modules/dmd/dcd.lua index 17698c6..dd065fe 100644 --- a/editors/textadept/modules/dmd/dcd.lua +++ b/editors/textadept/modules/dmd/dcd.lua @@ -151,6 +151,48 @@ function M.gotoDeclaration() end end +function M.searchForSymbol() + local button = -1 + local sybolName = "" + if buffer.selection_empty then + button, symbolName = ui.dialogs.inputbox{ + title = "Search for Symbol", + informative_text = "Name:" + } + if button == -1 then return end + else + symbolName = buffer:get_sel_text() + end + local result = runDCDClient("--search " .. symbolName) + local resultList = {} + local posDict = {} + local i = 0 + for line in result:gmatch("(.-)\n") do + local path, kind, position = line:match("([%w_/.]+)\t(%w)\t(%d+)") + table.insert(resultList, symbolName) + table.insert(resultList, kind) + table.insert(resultList, path) + table.insert(resultList, position) + posDict[i + 1] = {path, tonumber(position)} + i = i + 1 + end + for j, item in ipairs(resultList) do print (item) end + local button2, index = ui.dialogs.filteredlist{ + title = "Go to symbol", + columns = {"Name", "Type", "File", "Position"}, + items = resultList, + search_column = 3 + } + if button2 ~= -1 then + if (posDict[index][1] ~= "stdin") then + io.open_file(posDict[index][1]) + end + buffer:goto_pos(tonumber(posDict[index][2])) + buffer:word_right_end_extend() + end + +end + events.connect(events.CALL_TIP_CLICK, function(arrow) if buffer:get_lexer() ~= "dmd" then return end if arrow == 1 then diff --git a/src/actypes.d b/src/actypes.d index 3ec5617..138ce72 100644 --- a/src/actypes.d +++ b/src/actypes.d @@ -32,6 +32,8 @@ import std.d.lexer; import messages; import string_interning; +import std.range : isOutputRange; + /** * Any special information about a variable declaration symbol. */ @@ -128,6 +130,21 @@ public: return app.data(); } + /** + * Adds all parts and parts of parts with the given name to the given output + * range. + */ + void getAllPartsNamed(OR)(string name, ref OR outputRange) + if (isOutputRange!(OR, ACSymbol*)) + { + foreach (part; parts[]) + { + if (part.name == name) + outputRange.put(part); + part.getAllPartsNamed(name, outputRange); + } + } + /** * Symbol's name */ diff --git a/src/autocomplete.d b/src/autocomplete.d index 937e7f8..c31796d 100644 --- a/src/autocomplete.d +++ b/src/autocomplete.d @@ -115,6 +115,71 @@ public AutocompleteResponse complete(const AutocompleteRequest request) } } +/** + * + */ +public AutocompleteResponse symbolSearch(const AutocompleteRequest request) +{ + import containers.ttree; + + LexerConfig config; + config.fileName = ""; + auto cache = StringCache(StringCache.defaultBucketCount); + const(Token)[] tokenArray = getTokensForParser(cast(ubyte[]) request.sourceCode, + config, &cache); + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024*16))); + Scope* completionScope = generateAutocompleteTrees(tokenArray, allocator); + scope(exit) typeid(Scope).destroy(completionScope); + + static struct SearchResults + { + void put(ACSymbol* symbol) + { + tree.insert(SearchResult(symbol)); + } + + static struct SearchResult + { + ACSymbol* symbol; + + int opCmp(ref const SearchResult other) const pure nothrow + { + if (other.symbol.symbolFile < symbol.symbolFile) + return -1; + if (other.symbol.symbolFile > symbol.symbolFile) + return 1; + if (other.symbol.location < symbol.location) + return -1; + return other.symbol.location > symbol.location; + } + } + + TTree!(SearchResult) tree; + } + + SearchResults results; + + foreach (symbol; completionScope.symbols[]) + { + symbol.getAllPartsNamed(request.searchName, results); + } + foreach (s; ModuleCache.getAllSymbols()) + { + s.symbol.getAllPartsNamed(request.searchName, results); + } + + AutocompleteResponse response; + + foreach (result; results.tree[]) + { + response.locations ~= result.symbol.location; + response.completionKinds ~= result.symbol.kind; + response.completions ~= result.symbol.symbolFile; + } + + return response; +} + /******************************************************************************/ private: diff --git a/src/client.d b/src/client.d index 138f335..de24133 100644 --- a/src/client.d +++ b/src/client.d @@ -44,13 +44,14 @@ int main(string[] args) bool symbolLocation; bool doc; bool query; + string search; try { getopt(args, "cursorPos|c", &cursorPos, "I", &importPaths, "port|p", &port, "help|h", &help, "shutdown", &shutdown, "clearCache", &clearCache, "symbolLocation|l", &symbolLocation, - "doc|d", &doc, "query|q", &query); + "doc|d", &doc, "query|q", &query, "search|s", &search); } catch (Exception e) { @@ -113,7 +114,7 @@ int main(string[] args) return 0; } } - else if (cursorPos == size_t.max) + else if (search == null && cursorPos == size_t.max) { // cursor position is a required argument printHelp(args[0]); @@ -151,11 +152,14 @@ int main(string[] args) request.importPaths = importPaths; request.sourceCode = sourceCode; request.cursorPosition = cursorPos; + request.searchName = search; if (symbolLocation) request.kind |= RequestKind.symbolLocation; else if (doc) request.kind |= RequestKind.doc; + else if(search) + request.kind |= RequestKind.search; else request.kind |= RequestKind.autocomplete; @@ -171,12 +175,16 @@ int main(string[] args) printLocationResponse(response); else if (doc) printDocResponse(response); + else if (search !is null) + printSearchResponse(response); else printCompletionResponse(response); return 0; } +private: + void printHelp(string programName) { writefln( @@ -211,6 +219,10 @@ Options: Gets documentation comments associated with the symbol at the cursor location. + --search | -s symbolName + Searches for symbolName in both stdin / the given file name as well as + others files cached by the server. + --query | -q Query the server statis. Returns 0 if the server is running. Returns 1 if the server could not be contacted. @@ -299,3 +311,12 @@ void printCompletionResponse(AutocompleteResponse response) writeln(line); } } + +void printSearchResponse(const AutocompleteResponse response) +{ + foreach(i; 0 .. response.completions.length) + { + writefln("%s\t%s\t%s", response.completions[i], response.completionKinds[i], + response.locations[i]); + } +} diff --git a/src/messages.d b/src/messages.d index 3d1e367..5b2b570 100644 --- a/src/messages.d +++ b/src/messages.d @@ -130,6 +130,8 @@ enum RequestKind : ubyte doc = 0b00100000, /// Query server status query = 0b01000000, + /// Search for symbol + search = 0b10000000, } /** @@ -161,6 +163,11 @@ struct AutocompleteRequest * The cursor position */ size_t cursorPosition; + + /** + * Name of symbol searched for + */ + string searchName; } /** @@ -198,4 +205,9 @@ struct AutocompleteResponse * completion type is a function argument list. */ char[] completionKinds; + + /** + * Symbol locations for symbol searches. + */ + size_t[] locations; } diff --git a/src/modulecache.d b/src/modulecache.d index 24e02f8..848ee06 100644 --- a/src/modulecache.d +++ b/src/modulecache.d @@ -244,6 +244,11 @@ struct ModuleCache return importPaths[]; } + static auto getAllSymbols() + { + return cache[]; + } + /// Count of autocomplete symbols that have been allocated static uint symbolsAllocated; diff --git a/src/server.d b/src/server.d index f8d8c69..3fa8070 100644 --- a/src/server.d +++ b/src/server.d @@ -202,6 +202,12 @@ int main(string[] args) Log.error("Could not get symbol location", e.msg); } } + else if (request.kind & RequestKind.search) + { + AutocompleteResponse response = symbolSearch(request); + ubyte[] responseBytes = msgpack.pack(response); + s.send(responseBytes); + } Log.info("Request processed in ", requestWatch.peek().to!("msecs", float), " milliseconds"); } return 0;