Merge branch '0.4.0-dev' of https://github.com/Hackerpilot/DCD into 0.4.0-dev
This commit is contained in:
commit
3b79e2e6ad
|
@ -151,6 +151,48 @@ function M.gotoDeclaration()
|
||||||
end
|
end
|
||||||
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)
|
events.connect(events.CALL_TIP_CLICK, function(arrow)
|
||||||
if buffer:get_lexer() ~= "dmd" then return end
|
if buffer:get_lexer() ~= "dmd" then return end
|
||||||
if arrow == 1 then
|
if arrow == 1 then
|
||||||
|
|
|
@ -32,6 +32,8 @@ import std.d.lexer;
|
||||||
import messages;
|
import messages;
|
||||||
import string_interning;
|
import string_interning;
|
||||||
|
|
||||||
|
import std.range : isOutputRange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any special information about a variable declaration symbol.
|
* Any special information about a variable declaration symbol.
|
||||||
*/
|
*/
|
||||||
|
@ -128,6 +130,21 @@ public:
|
||||||
return app.data();
|
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
|
* 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:
|
private:
|
||||||
|
|
||||||
|
|
25
src/client.d
25
src/client.d
|
@ -44,13 +44,14 @@ int main(string[] args)
|
||||||
bool symbolLocation;
|
bool symbolLocation;
|
||||||
bool doc;
|
bool doc;
|
||||||
bool query;
|
bool query;
|
||||||
|
string search;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
getopt(args, "cursorPos|c", &cursorPos, "I", &importPaths,
|
getopt(args, "cursorPos|c", &cursorPos, "I", &importPaths,
|
||||||
"port|p", &port, "help|h", &help, "shutdown", &shutdown,
|
"port|p", &port, "help|h", &help, "shutdown", &shutdown,
|
||||||
"clearCache", &clearCache, "symbolLocation|l", &symbolLocation,
|
"clearCache", &clearCache, "symbolLocation|l", &symbolLocation,
|
||||||
"doc|d", &doc, "query|q", &query);
|
"doc|d", &doc, "query|q", &query, "search|s", &search);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +114,7 @@ int main(string[] args)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cursorPos == size_t.max)
|
else if (search == null && cursorPos == size_t.max)
|
||||||
{
|
{
|
||||||
// cursor position is a required argument
|
// cursor position is a required argument
|
||||||
printHelp(args[0]);
|
printHelp(args[0]);
|
||||||
|
@ -151,11 +152,14 @@ int main(string[] args)
|
||||||
request.importPaths = importPaths;
|
request.importPaths = importPaths;
|
||||||
request.sourceCode = sourceCode;
|
request.sourceCode = sourceCode;
|
||||||
request.cursorPosition = cursorPos;
|
request.cursorPosition = cursorPos;
|
||||||
|
request.searchName = search;
|
||||||
|
|
||||||
if (symbolLocation)
|
if (symbolLocation)
|
||||||
request.kind |= RequestKind.symbolLocation;
|
request.kind |= RequestKind.symbolLocation;
|
||||||
else if (doc)
|
else if (doc)
|
||||||
request.kind |= RequestKind.doc;
|
request.kind |= RequestKind.doc;
|
||||||
|
else if(search)
|
||||||
|
request.kind |= RequestKind.search;
|
||||||
else
|
else
|
||||||
request.kind |= RequestKind.autocomplete;
|
request.kind |= RequestKind.autocomplete;
|
||||||
|
|
||||||
|
@ -171,12 +175,16 @@ int main(string[] args)
|
||||||
printLocationResponse(response);
|
printLocationResponse(response);
|
||||||
else if (doc)
|
else if (doc)
|
||||||
printDocResponse(response);
|
printDocResponse(response);
|
||||||
|
else if (search !is null)
|
||||||
|
printSearchResponse(response);
|
||||||
else
|
else
|
||||||
printCompletionResponse(response);
|
printCompletionResponse(response);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
void printHelp(string programName)
|
void printHelp(string programName)
|
||||||
{
|
{
|
||||||
writefln(
|
writefln(
|
||||||
|
@ -211,6 +219,10 @@ Options:
|
||||||
Gets documentation comments associated with the symbol at the cursor
|
Gets documentation comments associated with the symbol at the cursor
|
||||||
location.
|
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 | -q
|
||||||
Query the server statis. Returns 0 if the server is running. Returns
|
Query the server statis. Returns 0 if the server is running. Returns
|
||||||
1 if the server could not be contacted.
|
1 if the server could not be contacted.
|
||||||
|
@ -299,3 +311,12 @@ void printCompletionResponse(AutocompleteResponse response)
|
||||||
writeln(line);
|
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,
|
doc = 0b00100000,
|
||||||
/// Query server status
|
/// Query server status
|
||||||
query = 0b01000000,
|
query = 0b01000000,
|
||||||
|
/// Search for symbol
|
||||||
|
search = 0b10000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,6 +163,11 @@ struct AutocompleteRequest
|
||||||
* The cursor position
|
* The cursor position
|
||||||
*/
|
*/
|
||||||
size_t cursorPosition;
|
size_t cursorPosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of symbol searched for
|
||||||
|
*/
|
||||||
|
string searchName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,4 +205,9 @@ struct AutocompleteResponse
|
||||||
* completion type is a function argument list.
|
* completion type is a function argument list.
|
||||||
*/
|
*/
|
||||||
char[] completionKinds;
|
char[] completionKinds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbol locations for symbol searches.
|
||||||
|
*/
|
||||||
|
size_t[] locations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,11 @@ struct ModuleCache
|
||||||
return importPaths[];
|
return importPaths[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static auto getAllSymbols()
|
||||||
|
{
|
||||||
|
return cache[];
|
||||||
|
}
|
||||||
|
|
||||||
/// Count of autocomplete symbols that have been allocated
|
/// Count of autocomplete symbols that have been allocated
|
||||||
static uint symbolsAllocated;
|
static uint symbolsAllocated;
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,12 @@ int main(string[] args)
|
||||||
Log.error("Could not get symbol location", e.msg);
|
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");
|
Log.info("Request processed in ", requestWatch.peek().to!("msecs", float), " milliseconds");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue