Import directories are handled much better now
This commit is contained in:
parent
126e101e78
commit
fe11e9d359
67
acvisitor.d
67
acvisitor.d
|
|
@ -23,6 +23,10 @@ import stdx.d.parser;
|
|||
import stdx.d.ast;
|
||||
import stdx.d.lexer;
|
||||
import std.stdio;
|
||||
import std.algorithm;
|
||||
import std.path;
|
||||
import std.range;
|
||||
import std.conv;
|
||||
|
||||
import actypes;
|
||||
import messages;
|
||||
|
|
@ -34,6 +38,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(Unittest dec)
|
||||
{
|
||||
// writeln("Unitttest visit");
|
||||
auto symbol = new ACSymbol("*unittest*");
|
||||
auto p = parentSymbol;
|
||||
parentSymbol = symbol;
|
||||
|
|
@ -43,6 +48,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(StructDeclaration dec)
|
||||
{
|
||||
// writeln("StructDeclaration visit");
|
||||
auto symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
symbol.location = dec.name.startIndex;
|
||||
|
|
@ -52,6 +58,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(ClassDeclaration dec)
|
||||
{
|
||||
// writeln("ClassDeclaration visit");
|
||||
auto symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
symbol.location = dec.name.startIndex;
|
||||
|
|
@ -61,6 +68,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(InterfaceDeclaration dec)
|
||||
{
|
||||
// writeln("InterfaceDeclaration visit");
|
||||
auto symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
symbol.location = dec.name.startIndex;
|
||||
|
|
@ -70,6 +78,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(StructBody structBody)
|
||||
{
|
||||
// writeln("StructBody visit");
|
||||
auto s = scope_;
|
||||
scope_ = new Scope(structBody.startLocation, structBody.endLocation);
|
||||
scope_.symbols ~= new ACSymbol("this", CompletionKind.variableName,
|
||||
|
|
@ -82,17 +91,43 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(EnumDeclaration dec)
|
||||
{
|
||||
// TODO: Store type
|
||||
// writeln("EnumDeclaration visit");
|
||||
auto symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
symbol.location = dec.name.startIndex;
|
||||
symbol.kind = CompletionKind.enumName;
|
||||
mixin (visitAndAdd);
|
||||
auto type = dec.type;
|
||||
auto p = parentSymbol;
|
||||
parentSymbol = symbol;
|
||||
|
||||
if (dec.enumBody !is null)
|
||||
{
|
||||
foreach (member; dec.enumBody.enumMembers)
|
||||
{
|
||||
auto s = new ACSymbol;
|
||||
s.kind = CompletionKind.enumMember;
|
||||
s.name = member.name.value;
|
||||
s.location = member.name.startIndex;
|
||||
if (type is null)
|
||||
s.resolvedType = scope_.findSymbolInScope("int");
|
||||
else
|
||||
s.type = type;
|
||||
if (parentSymbol !is null)
|
||||
parentSymbol.parts ~= s;
|
||||
}
|
||||
}
|
||||
|
||||
parentSymbol = p;
|
||||
if (parentSymbol is null)
|
||||
symbols ~= symbol;
|
||||
else
|
||||
parentSymbol.parts ~= symbol;
|
||||
scope_.symbols ~= symbol;
|
||||
}
|
||||
|
||||
override void visit(FunctionDeclaration dec)
|
||||
{
|
||||
// TODO: Parameters need to be added to the function body scope
|
||||
// writeln("FunctionDeclaration visit");
|
||||
ACSymbol symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
symbol.location = dec.name.startIndex;
|
||||
|
|
@ -115,13 +150,14 @@ class AutocompleteVisitor : ASTVisitor
|
|||
}
|
||||
|
||||
// writeln("Parameter symbols added");
|
||||
if (dec.returnType !is null)
|
||||
if (dec.returnType !is null && dec.parameters !is null)
|
||||
{
|
||||
symbol.calltip = format("%s %s%s", dec.returnType.toString(),
|
||||
dec.name.value, dec.parameters.toString());
|
||||
}
|
||||
auto p = parentSymbol;
|
||||
parentSymbol = symbol;
|
||||
// writeln("Call tip created");
|
||||
|
||||
BlockStatement functionBody = dec.functionBody is null ? null
|
||||
: (dec.functionBody.bodyStatement !is null
|
||||
|
|
@ -153,18 +189,9 @@ class AutocompleteVisitor : ASTVisitor
|
|||
scope_.symbols ~= symbol;
|
||||
}
|
||||
|
||||
override void visit(EnumMember member)
|
||||
{
|
||||
auto s = new ACSymbol;
|
||||
s.kind = CompletionKind.enumMember;
|
||||
s.name = member.name.value;
|
||||
s.location = member.name.startIndex;
|
||||
if (parentSymbol !is null)
|
||||
parentSymbol.parts ~= s;
|
||||
}
|
||||
|
||||
override void visit(VariableDeclaration dec)
|
||||
{
|
||||
// writeln("VariableDeclaration visit");
|
||||
foreach (d; dec.declarators)
|
||||
{
|
||||
auto symbol = new ACSymbol;
|
||||
|
|
@ -216,17 +243,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
private static string convertChainToImportPath(IdentifierChain chain)
|
||||
{
|
||||
string rVal;
|
||||
bool first = true;
|
||||
foreach (identifier; chain.identifiers)
|
||||
{
|
||||
if (!first)
|
||||
rVal ~= "/";
|
||||
rVal ~= identifier.value;
|
||||
first = false;
|
||||
}
|
||||
rVal ~= ".d";
|
||||
return rVal;
|
||||
return to!string(chain.identifiers.map!"a.value"().join(dirSeparator).array) ~ ".d";
|
||||
}
|
||||
|
||||
ACSymbol[] symbols;
|
||||
|
|
|
|||
30
client.d
30
client.d
|
|
@ -22,6 +22,9 @@ import std.socket;
|
|||
import std.stdio;
|
||||
import std.getopt;
|
||||
import std.array;
|
||||
import std.process;
|
||||
import std.algorithm;
|
||||
import std.path;
|
||||
|
||||
import msgpack;
|
||||
import messages;
|
||||
|
|
@ -51,8 +54,7 @@ int main(string[] args)
|
|||
printHelp(args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shutdown || clearCache)
|
||||
else if (shutdown || clearCache)
|
||||
{
|
||||
AutocompleteRequest request;
|
||||
if (shutdown)
|
||||
|
|
@ -71,10 +73,26 @@ int main(string[] args)
|
|||
messageBuffer[8 .. $] = message[];
|
||||
return socket.send(messageBuffer) == messageBuffer.length ? 0 : 1;
|
||||
}
|
||||
|
||||
// cursor position is a required argument
|
||||
if (cursorPos == size_t.max)
|
||||
else if (importPaths.length > 0)
|
||||
{
|
||||
AutocompleteRequest request;
|
||||
request.kind = RequestKind.addImport;
|
||||
request.importPaths = importPaths.map!(a => isRooted(a) ? a : absolutePath(a)).array;
|
||||
auto socket = new TcpSocket(AddressFamily.INET);
|
||||
scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); }
|
||||
socket.connect(new InternetAddress("127.0.0.1", port));
|
||||
socket.blocking = true;
|
||||
socket.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, 1);
|
||||
ubyte[] message = msgpack.pack(request);
|
||||
ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof];
|
||||
auto messageLength = message.length;
|
||||
messageBuffer[0 .. 8] = (cast(ubyte*) &messageLength)[0 .. 8];
|
||||
messageBuffer[8 .. $] = message[];
|
||||
return socket.send(messageBuffer) == messageBuffer.length ? 0 : 1;
|
||||
}
|
||||
else if (cursorPos == size_t.max)
|
||||
{
|
||||
// cursor position is a required argument
|
||||
printHelp(args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -114,7 +132,7 @@ int main(string[] args)
|
|||
scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); }
|
||||
socket.connect(new InternetAddress("127.0.0.1", port));
|
||||
socket.blocking = true;
|
||||
socket.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, 1);
|
||||
//socket.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, 1);
|
||||
ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof];
|
||||
auto messageLength = message.length;
|
||||
messageBuffer[0 .. 8] = (cast(ubyte*) &messageLength)[0 .. 8];
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ function M.autocomplete(ch)
|
|||
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName
|
||||
local p = io.popen(command, "r")
|
||||
local r = p:read("*a")
|
||||
print(r)
|
||||
if r ~= "\n" then
|
||||
if r:match("^identifiers.*") then
|
||||
showCompletionList(r)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import stdx.d.parser;
|
|||
import stdx.d.ast;
|
||||
import std.stdio;
|
||||
import std.array;
|
||||
import std.path;
|
||||
|
||||
import acvisitor;
|
||||
import actypes;
|
||||
|
|
@ -56,6 +57,11 @@ struct ModuleCache
|
|||
static void addImportPath(string path)
|
||||
{
|
||||
importPaths ~= path;
|
||||
foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth))
|
||||
{
|
||||
writeln("Loading and caching completions for ", fileName);
|
||||
getSymbolsInModule(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -73,6 +79,9 @@ struct ModuleCache
|
|||
if (!needsReparsing(location))
|
||||
return cache[location].symbols;
|
||||
|
||||
auto visitor = new AutocompleteVisitor;
|
||||
try
|
||||
{
|
||||
File f = File(location);
|
||||
ubyte[] source = uninitializedArray!(ubyte[])(f.size);
|
||||
f.rawRead(source);
|
||||
|
|
@ -80,9 +89,15 @@ struct ModuleCache
|
|||
LexerConfig config;
|
||||
auto tokens = source.byToken(config).array();
|
||||
Module mod = parseModule(tokens, location, &doesNothing);
|
||||
auto visitor = new AutocompleteVisitor;
|
||||
|
||||
visitor.visit(mod);
|
||||
visitor.scope_.resolveSymbolTypes();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
writeln("Couln't parse ", location);
|
||||
return [];
|
||||
}
|
||||
SysTime access;
|
||||
SysTime modification;
|
||||
getTimes(location, access, modification);
|
||||
|
|
@ -103,6 +118,9 @@ struct ModuleCache
|
|||
static string resolveImportLoctation(string moduleName)
|
||||
{
|
||||
writeln("Resolving location of ", moduleName);
|
||||
if (isRooted(moduleName))
|
||||
return moduleName;
|
||||
|
||||
foreach (path; importPaths)
|
||||
{
|
||||
string filePath = path ~ "/" ~ moduleName;
|
||||
|
|
|
|||
8
server.d
8
server.d
|
|
@ -64,8 +64,10 @@ int main(string[] args)
|
|||
socket.listen(0);
|
||||
scope (exit)
|
||||
{
|
||||
writeln("Shutting down sockets...");
|
||||
socket.shutdown(SocketShutdown.BOTH);
|
||||
socket.close();
|
||||
writeln("Sockets shut down.");
|
||||
}
|
||||
ubyte[1024 * 1024 * 4] buffer = void; // 4 megabytes should be enough for anybody...
|
||||
while (true)
|
||||
|
|
@ -102,7 +104,11 @@ int main(string[] args)
|
|||
msgpack.unpack(buffer[8 .. bytesReceived], request);
|
||||
if (request.kind == RequestKind.addImport)
|
||||
{
|
||||
//ModuleCache.addImportPath();
|
||||
foreach (path; request.importPaths)
|
||||
{
|
||||
ModuleCache.addImportPath(path);
|
||||
}
|
||||
|
||||
}
|
||||
else if (request.kind == RequestKind.clearCache)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue