This commit is contained in:
parent
e3281599e8
commit
78ad6a0af7
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
25
src/client.d
25
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -244,6 +244,11 @@ struct ModuleCache
|
|||
return importPaths[];
|
||||
}
|
||||
|
||||
static auto getAllSymbols()
|
||||
{
|
||||
return cache[];
|
||||
}
|
||||
|
||||
/// Count of autocomplete symbols that have been allocated
|
||||
static uint symbolsAllocated;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue