Use new dsymbol code

This commit is contained in:
Hackerpilot 2015-08-03 16:38:40 -07:00
parent eb79c2a7ab
commit b92b8944b5
2 changed files with 79 additions and 66 deletions

View File

@ -20,6 +20,7 @@ module server.autocomplete;
import std.algorithm;
import std.experimental.allocator;
import std.experimental.logger;
import std.array;
import std.conv;
import std.experimental.logger;
@ -48,8 +49,6 @@ import memory.allocators;
import common.constants;
import common.messages;
private alias ASTAllocator = CAllocatorImpl!(AllocatorList!(n => Region!Mallocator(1024 * 64)));
/**
* Gets documentation for the symbol at the cursor
* Params:
@ -57,14 +56,15 @@ private alias ASTAllocator = CAllocatorImpl!(AllocatorList!(n => Region!Mallocat
* Returns:
* the autocompletion response
*/
public AutocompleteResponse getDoc(const AutocompleteRequest request)
public AutocompleteResponse getDoc(const AutocompleteRequest request,
ref ModuleCache moduleCache)
{
// trace("Getting doc comments");
AutocompleteResponse response;
auto allocator = scoped!(ASTAllocator)();
auto cache = StringCache(StringCache.defaultBucketCount);
SymbolStuff stuff = getSymbolsForCompletion(request, CompletionType.ddoc,
allocator, &cache);
allocator, cache, moduleCache);
if (stuff.symbols.length == 0)
warning("Could not find symbol");
else foreach (symbol; stuff.symbols.filter!(a => !a.doc.empty))
@ -79,13 +79,14 @@ public AutocompleteResponse getDoc(const AutocompleteRequest request)
* Returns:
* the autocompletion response
*/
public AutocompleteResponse findDeclaration(const AutocompleteRequest request)
public AutocompleteResponse findDeclaration(const AutocompleteRequest request,
ref ModuleCache moduleCache)
{
AutocompleteResponse response;
auto allocator = scoped!(ASTAllocator)();
auto cache = StringCache(StringCache.defaultBucketCount);
SymbolStuff stuff = getSymbolsForCompletion(request,
CompletionType.location, allocator, &cache);
CompletionType.location, allocator, cache, moduleCache);
scope(exit) stuff.destroy();
if (stuff.symbols.length > 0)
{
@ -104,40 +105,45 @@ public AutocompleteResponse findDeclaration(const AutocompleteRequest request)
* Returns:
* the autocompletion response
*/
public AutocompleteResponse complete(const AutocompleteRequest request)
public AutocompleteResponse complete(const AutocompleteRequest request,
ref ModuleCache moduleCache)
{
const(Token)[] tokenArray;
auto cache = StringCache(StringCache.defaultBucketCount);
auto stringCache = StringCache(StringCache.defaultBucketCount);
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
request.cursorPosition, &cache, tokenArray);
request.cursorPosition, stringCache, tokenArray);
if (beforeTokens.length >= 2)
{
if (beforeTokens[$ - 1] == tok!"(" || beforeTokens[$ - 1] == tok!"[")
{
return parenCompletion(beforeTokens, tokenArray, request.cursorPosition);
return parenCompletion(beforeTokens, tokenArray, request.cursorPosition,
moduleCache);
}
else if (beforeTokens[$ - 1] == tok!",")
{
immutable size_t end = goBackToOpenParen(beforeTokens);
if (end != size_t.max)
return parenCompletion(beforeTokens[0 .. end], tokenArray, request.cursorPosition);
return parenCompletion(beforeTokens[0 .. end], tokenArray,
request.cursorPosition, moduleCache);
}
else
{
ImportKind kind = determineImportKind(beforeTokens);
if (kind == ImportKind.neither)
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition);
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition,
moduleCache);
else
return importCompletion(beforeTokens, kind);
return importCompletion(beforeTokens, kind, moduleCache);
}
}
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition);
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition, moduleCache);
}
/**
*
*/
public AutocompleteResponse symbolSearch(const AutocompleteRequest request)
public AutocompleteResponse symbolSearch(const AutocompleteRequest request,
ref ModuleCache moduleCache)
{
import containers.ttree : TTree;
@ -148,7 +154,7 @@ public AutocompleteResponse symbolSearch(const AutocompleteRequest request)
config, &cache);
auto allocator = scoped!(ASTAllocator)();
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
request.cursorPosition);
request.cursorPosition, moduleCache);
scope(exit) pair.destroy();
static struct SearchResults
@ -183,7 +189,7 @@ public AutocompleteResponse symbolSearch(const AutocompleteRequest request)
{
symbol.getAllPartsNamed(request.searchName, results);
}
foreach (s; ModuleCache.getAllSymbols())
foreach (s; moduleCache.getAllSymbols())
{
s.symbol.getAllPartsNamed(request.searchName, results);
}
@ -203,7 +209,7 @@ public AutocompleteResponse symbolSearch(const AutocompleteRequest request)
/******************************************************************************/
private:
enum ImportKind
enum ImportKind : ubyte
{
selective,
normal,
@ -219,8 +225,8 @@ enum ImportKind
* Returns:
* the autocompletion response
*/
AutocompleteResponse dotCompletion(T)(T beforeTokens,
const(Token)[] tokenArray, size_t cursorPosition)
AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
size_t cursorPosition, ref ModuleCache moduleCache)
{
AutocompleteResponse response;
@ -239,8 +245,8 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens,
// responses when the cursor is in the middle of an identifier instead
// of at the end
auto t = beforeTokens[$ - 1];
partial = t.text[0 .. cursorPosition - t.index];
if (cursorPosition - t.index >= 0 && cursorPosition - t.index <= t.text.length)
partial = t.text[0 .. cursorPosition - t.index];
significantTokenType = tok!"identifier";
beforeTokens = beforeTokens[0 .. $ - 1];
}
@ -291,7 +297,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens,
case tok!"super":
auto allocator = scoped!(ASTAllocator)();
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
cursorPosition);
cursorPosition, moduleCache);
scope(exit) pair.destroy();
response.setCompletions(pair.scope_, getExpression(beforeTokens),
cursorPosition, CompletionType.identifiers, false, partial);
@ -316,11 +322,11 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens,
* a sorted range of tokens before the cursor position
*/
auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
StringCache* cache, out const(Token)[] tokenArray)
ref StringCache cache, out const(Token)[] tokenArray)
{
LexerConfig config;
config.fileName = "";
tokenArray = getTokensForParser(cast(ubyte[]) sourceCode, config, cache);
tokenArray = getTokensForParser(cast(ubyte[]) sourceCode, config, &cache);
auto sortedTokens = assumeSorted(tokenArray);
return sortedTokens.lowerBound(cast(size_t) cursorPosition);
}
@ -334,13 +340,14 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
* the request's source code, cursor position, and completion type.
*/
SymbolStuff getSymbolsForCompletion(const AutocompleteRequest request,
const CompletionType type, IAllocator allocator, StringCache* cache)
const CompletionType type, IAllocator allocator, ref StringCache cache,
ref ModuleCache moduleCache)
{
const(Token)[] tokenArray;
auto beforeTokens = getTokensBeforeCursor(request.sourceCode,
request.cursorPosition, cache, tokenArray);
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
request.cursorPosition);
request.cursorPosition, moduleCache);
auto expression = getExpression(beforeTokens);
return SymbolStuff(getSymbolsByTokenChain(pair.scope_, expression,
request.cursorPosition, type), pair.symbol, pair.scope_);
@ -369,7 +376,7 @@ struct SymbolStuff
* the autocompletion response
*/
AutocompleteResponse parenCompletion(T)(T beforeTokens,
const(Token)[] tokenArray, size_t cursorPosition)
const(Token)[] tokenArray, size_t cursorPosition, ref ModuleCache moduleCache)
{
AutocompleteResponse response;
immutable(string)[] completions;
@ -418,7 +425,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
case tok!"]":
auto allocator = scoped!(ASTAllocator)();
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
cursorPosition);
cursorPosition, moduleCache);
scope(exit) pair.destroy();
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(pair.scope_, expression,
@ -437,7 +444,8 @@ ImportKind determineImportKind(T)(T tokens)
{
assert (tokens.length > 1);
size_t i = tokens.length - 1;
if (!(tokens[i] == tok!":" || tokens[i] == tok!"," || tokens[i] == tok!"." || tokens[i] == tok!"identifier"))
if (!(tokens[i] == tok!":" || tokens[i] == tok!"," || tokens[i] == tok!"."
|| tokens[i] == tok!"identifier"))
return ImportKind.neither;
bool foundColon = false;
while (true) switch (tokens[i].type)
@ -484,7 +492,8 @@ unittest
* import std.algorithm: balancedParens;
* ---
*/
AutocompleteResponse importCompletion(T)(T beforeTokens, ImportKind kind)
AutocompleteResponse importCompletion(T)(T beforeTokens, ImportKind kind,
ref ModuleCache moduleCache)
in
{
assert (beforeTokens.length >= 2);
@ -501,7 +510,7 @@ body
{
while (beforeTokens[i].type != tok!"," && beforeTokens[i].type != tok!"import") i--;
setImportCompletions(beforeTokens[i .. $], response);
setImportCompletions(beforeTokens[i .. $], response, moduleCache);
return response;
}
@ -550,13 +559,13 @@ body
}
}
string resolvedLocation = ModuleCache.resolveImportLocation(path);
string resolvedLocation = moduleCache.resolveImportLocation(path);
if (resolvedLocation is null)
{
warning("Could not resolve location of ", path);
return response;
}
auto symbols = ModuleCache.getModuleSymbol(resolvedLocation);
auto symbols = moduleCache.getModuleSymbol(internString(resolvedLocation));
import containers.hashset : HashSet;
HashSet!string h;
@ -575,8 +584,9 @@ body
foreach (s; symbols.opSlice())
{
if (s.kind == CompletionKind.importSymbol) foreach (sy; s.type.opSlice())
addSymbolToResponses(sy);
if (s.kind == CompletionKind.importSymbol && s.type !is null)
foreach (sy; s.type.opSlice())
addSymbolToResponses(sy);
else
addSymbolToResponses(s);
}
@ -590,7 +600,8 @@ body
* tokens = the tokens after the "import" keyword and before the cursor
* response = the response that should be populated
*/
void setImportCompletions(T)(T tokens, ref AutocompleteResponse response)
void setImportCompletions(T)(T tokens, ref AutocompleteResponse response,
ref ModuleCache cache)
{
response.completionType = CompletionType.identifiers;
string partial = null;
@ -604,7 +615,7 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response)
bool found = false;
foreach (importDirectory; ModuleCache.getImportPaths())
foreach (importDirectory; cache.getImportPaths())
{
string p = buildPath(importDirectory, path);
if (!exists(p))
@ -732,11 +743,11 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
break loop;
}
// Log.trace("looking for ", tokens[i].text, " in ", symbols[0].name);
// trace("looking for ", tokens[i].text, " in ", symbols[0].name);
symbols = symbols[0].getPartsByName(internString(tokens[i].text));
if (symbols.length == 0)
{
// Log.trace("Couldn't find it.");
// trace("Couldn't find it.");
break loop;
}
if (shouldSwapWithType(completionType, symbols[0].kind, i,
@ -820,7 +831,8 @@ void setCompletions(T)(ref AutocompleteResponse response,
// based on the currently entered text.
if (partial !is null && tokens.length == 0)
{
foreach (s; completionScope.getSymbolsInCursorScope(cursorPosition)
auto currentSymbols = completionScope.getSymbolsInCursorScope(cursorPosition);
foreach (s; currentSymbols
.filter!(a => a.name.toUpper().startsWith(partial.toUpper())))
{
response.completionKinds ~= s.kind;
@ -848,26 +860,24 @@ void setCompletions(T)(ref AutocompleteResponse response,
if (symbols.length == 0)
return;
}
foreach (sym; symbols[0].opSlice())
if (symbols[0].kind != CompletionKind.importSymbol)
{
if (sym.kind == CompletionKind.importSymbol) foreach (s; sym.type.opSlice())
foreach (sym; symbols[0].opSlice())
{
response.completionKinds ~= s.kind;
response.completions ~= s.name.dup;
}
else if (sym.name !is null && sym.name.length > 0 && sym.name[0] != '*'
&& (partial is null ? true : sym.name.toUpper().startsWith(partial.toUpper()))
&& !response.completions.canFind(sym.name))
{
response.completionKinds ~= sym.kind;
response.completions ~= sym.name.dup;
if (sym.name !is null && sym.name.length > 0 && sym.name[0] != '*'
&& (partial is null ? true : sym.name.toUpper().startsWith(partial.toUpper()))
&& !response.completions.canFind(sym.name))
{
response.completionKinds ~= sym.kind;
response.completions ~= sym.name.dup;
}
}
}
response.completionType = CompletionType.identifiers;
}
else if (completionType == CompletionType.calltips)
{
// Log.trace("Showing call tips for ", symbols[0].name, " of kind ", symbols[0].kind);
// trace("Showing call tips for ", symbols[0].name, " of kind ", symbols[0].kind);
if (symbols[0].kind != CompletionKind.functionName
&& symbols[0].callTip is null)
{

View File

@ -58,12 +58,13 @@ int main(string[] args)
ushort port = 9166;
bool help;
bool printVersion;
bool ignoreConfig;
string[] importPaths;
try
{
getopt(args, "port|p", &port, "I", &importPaths, "help|h", &help,
"version", & printVersion);
"version", &printVersion, "ignoreConfig", &ignoreConfig);
}
catch (ConvException e)
{
@ -87,7 +88,8 @@ int main(string[] args)
return 0;
}
importPaths ~= loadConfiguredImportDirs();
if (!ignoreConfig)
importPaths ~= loadConfiguredImportDirs();
auto socket = new TcpSocket(AddressFamily.INET);
socket.blocking = true;
@ -102,14 +104,15 @@ int main(string[] args)
info("Sockets shut down.");
}
ModuleCache.addImportPaths(importPaths);
infof("Import directories:\n %-(%s\n %)", ModuleCache.getImportPaths());
ModuleCache cache = ModuleCache(new ASTAllocator);
cache.addImportPaths(importPaths);
infof("Import directories:\n %-(%s\n %)", cache.getImportPaths());
ubyte[] buffer = cast(ubyte[]) Mallocator.it.allocate(1024 * 1024 * 4); // 4 megabytes should be enough for anybody...
scope(exit) Mallocator.it.deallocate(buffer);
sw.stop();
info(ModuleCache.symbolsAllocated, " symbols cached.");
info(cache.symbolsAllocated, " symbols cached.");
info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds.");
// No relative paths
@ -167,7 +170,7 @@ int main(string[] args)
if (request.kind & RequestKind.clearCache)
{
info("Clearing cache.");
ModuleCache.clear();
cache.clear();
}
else if (request.kind & RequestKind.shutdown)
{
@ -184,12 +187,12 @@ int main(string[] args)
}
if (request.kind & RequestKind.addImport)
{
ModuleCache.addImportPaths(request.importPaths);
cache.addImportPaths(request.importPaths);
}
if (request.kind & RequestKind.listImports)
{
AutocompleteResponse response;
response.importPaths = ModuleCache.getImportPaths().array();
response.importPaths = cache.getImportPaths().array();
ubyte[] responseBytes = msgpack.pack(response);
info("Returning import path list");
s.send(responseBytes);
@ -197,7 +200,7 @@ int main(string[] args)
else if (request.kind & RequestKind.autocomplete)
{
info("Getting completions");
AutocompleteResponse response = complete(request);
AutocompleteResponse response = complete(request, cache);
ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes);
}
@ -206,7 +209,7 @@ int main(string[] args)
info("Getting doc comment");
try
{
AutocompleteResponse response = getDoc(request);
AutocompleteResponse response = getDoc(request, cache);
ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes);
}
@ -219,7 +222,7 @@ int main(string[] args)
{
try
{
AutocompleteResponse response = findDeclaration(request);
AutocompleteResponse response = findDeclaration(request, cache);
ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes);
}
@ -230,7 +233,7 @@ int main(string[] args)
}
else if (request.kind & RequestKind.search)
{
AutocompleteResponse response = symbolSearch(request);
AutocompleteResponse response = symbolSearch(request, cache);
ubyte[] responseBytes = msgpack.pack(response);
s.send(responseBytes);
}
@ -304,7 +307,7 @@ string[] loadConfiguredImportDirs()
info("Loading configuration from ", configLocation);
File f = File(configLocation, "rt");
return f.byLine(KeepTerminator.no)
.filter!(a => a.length > 0 && existanceCheck(a))
.filter!(a => a.length > 0 && a[0] != '#' && existanceCheck(a))
.map!(a => a.idup)
.array();
}