Autocomplete of enum members and handling of opSlice and opIndex
This commit is contained in:
parent
fe11e9d359
commit
bf3c7ba500
|
|
@ -17,14 +17,13 @@ back to the client.
|
|||
* Autocompletion of class, struct, and interface instances.
|
||||
* Display of call tips (but only for the first overload)
|
||||
* Not working:
|
||||
* Automatic starting of the server by the client
|
||||
* Windows support (I don't know that it won't work, but this program is not tested on Windows yet)
|
||||
* UFCS
|
||||
* Templates
|
||||
* Templated declarations
|
||||
* *auto* declarations
|
||||
* Operator overloading (opIndex, opSlice, etc) when autocompleting
|
||||
* Instances of enum types resolve to the enum itself instead of the enum base type
|
||||
* Determining the type of an enum member when no base type is specified, but the first member has an initialaizer
|
||||
* Public imports
|
||||
* Array and associative array indexing in autocompletion
|
||||
* That one feature that you *REALLY* needed
|
||||
|
||||
#Setup
|
||||
|
|
|
|||
12
actypes.d
12
actypes.d
|
|
@ -216,17 +216,19 @@ public:
|
|||
*/
|
||||
void resolveSymbolTypes()
|
||||
{
|
||||
// TODO: auto declarations.
|
||||
|
||||
// We only care about resolving types of variables, all other symbols
|
||||
// don't have any indirection
|
||||
// TODO: Resolve types of enum members
|
||||
foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName
|
||||
|| a.kind == CompletionKind.functionName
|
||||
|| a.kind == CompletionKind.memberVariableName) && a.resolvedType is null)())
|
||||
|| a.kind == CompletionKind.functionName || a.kind == CompletionKind.memberVariableName
|
||||
|| a.kind == CompletionKind.enumMember) && a.resolvedType is null)())
|
||||
{
|
||||
//writeln("Resolving type of symbol ", s.name);
|
||||
Type type = s.type;
|
||||
if (type is null)
|
||||
continue;
|
||||
|
||||
if (type.type2.builtinType != TokenType.invalid)
|
||||
{
|
||||
// This part is easy. Autocomplete properties of built-in types
|
||||
|
|
@ -264,21 +266,19 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
// ormal array
|
||||
// normal array
|
||||
s.resolvedType.qualifier = SymbolQualifier.array;
|
||||
s.resolvedType.parts ~= arraySymbols;
|
||||
}
|
||||
}
|
||||
else if (suffix.delegateOrFunction.type != TokenType.invalid)
|
||||
{
|
||||
// TODO: figure out how to handle this, if necessary
|
||||
s.resolvedType.qualifier = SymbolQualifier.func;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (c; children)
|
||||
{
|
||||
assert (c !is null);
|
||||
c.resolveSymbolTypes();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
override void visit(EnumDeclaration dec)
|
||||
{
|
||||
// TODO: Set enum type based on initializer of first member
|
||||
// writeln("EnumDeclaration visit");
|
||||
auto symbol = new ACSymbol;
|
||||
symbol.name = dec.name.value;
|
||||
|
|
@ -102,6 +103,8 @@ class AutocompleteVisitor : ASTVisitor
|
|||
|
||||
if (dec.enumBody !is null)
|
||||
{
|
||||
Scope enumBodyScope = new Scope(dec.enumBody.startLocation,
|
||||
dec.enumBody.endLocation);
|
||||
foreach (member; dec.enumBody.enumMembers)
|
||||
{
|
||||
auto s = new ACSymbol;
|
||||
|
|
@ -114,7 +117,10 @@ class AutocompleteVisitor : ASTVisitor
|
|||
s.type = type;
|
||||
if (parentSymbol !is null)
|
||||
parentSymbol.parts ~= s;
|
||||
enumBodyScope.symbols ~= s;
|
||||
}
|
||||
enumBodyScope.parent = scope_;
|
||||
scope_.children ~= enumBodyScope;
|
||||
}
|
||||
|
||||
parentSymbol = p;
|
||||
|
|
|
|||
|
|
@ -154,8 +154,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
CompletionType completionType)
|
||||
{
|
||||
|
||||
writeln("Getting completions for ", map!"a.value"(tokens));
|
||||
writeln("Resolving symbols for editor buffer");
|
||||
visitor.scope_.resolveSymbolTypes();
|
||||
ACSymbol symbol = visitor.scope_.findSymbolInCurrentScope(cursorPosition, tokens[0].value);
|
||||
if (symbol is null)
|
||||
|
|
@ -166,7 +164,8 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
|
||||
if (completionType == CompletionType.identifiers
|
||||
&& symbol.kind == CompletionKind.memberVariableName
|
||||
|| symbol.kind == CompletionKind.variableName)
|
||||
|| symbol.kind == CompletionKind.variableName
|
||||
|| symbol.kind == CompletionKind.enumMember)
|
||||
{
|
||||
symbol = symbol.resolvedType;
|
||||
if (symbol is null)
|
||||
|
|
@ -233,6 +232,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
if (symbol.kind == CompletionKind.variableName
|
||||
|| symbol.kind == CompletionKind.memberVariableName
|
||||
|| symbol.kind == CompletionKind.enumMember
|
||||
|| (symbol.kind == CompletionKind.functionName
|
||||
&& (completionType == CompletionType.identifiers
|
||||
|| i + 1 < tokens.length)))
|
||||
|
|
@ -248,8 +248,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
case lBracket:
|
||||
open = TokenType.lBracket;
|
||||
close = TokenType.rBracket;
|
||||
// TODO: handle opIndex
|
||||
// TODO: handle opSlice
|
||||
if (symbol.qualifier == SymbolQualifier.array)
|
||||
{
|
||||
auto h = i;
|
||||
|
|
@ -266,8 +264,25 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
symbol = symbol.resolvedType;
|
||||
skip();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto h = i;
|
||||
skip();
|
||||
Parser p;
|
||||
p.setTokens(tokens[h .. i].array());
|
||||
ACSymbol overload;
|
||||
if (p.isSliceExpression())
|
||||
overload = symbol.getPartByName("opSlice");
|
||||
else
|
||||
overload = symbol.getPartByName("opIndex");
|
||||
if (overload !is null)
|
||||
{
|
||||
writeln("opIndex or opSlice used, ", overload.name);
|
||||
symbol = overload.resolvedType;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case dot:
|
||||
break;
|
||||
|
|
@ -282,10 +297,10 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
if (completionType == CompletionType.identifiers)
|
||||
{
|
||||
writeln("Writing out the parts of ", symbol.name);
|
||||
writeln("Writing completions for ", symbol.name);
|
||||
foreach (s; symbol.parts)
|
||||
{
|
||||
//writeln("Adding ", s.name, " to the completion list");
|
||||
writeln("Adding ", s.name, " to the completion list");
|
||||
response.completionKinds ~= s.kind;
|
||||
response.completions ~= s.name;
|
||||
}
|
||||
|
|
@ -293,7 +308,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
else
|
||||
{
|
||||
writeln("Adding calltip for ", symbol.name, ": ", symbol.calltip);
|
||||
response.completions ~= symbol.calltip;
|
||||
response.completionType = CompletionType.calltips;
|
||||
}
|
||||
|
|
|
|||
12
server.d
12
server.d
|
|
@ -54,10 +54,6 @@ int main(string[] args)
|
|||
|
||||
importPaths ~= loadConfiguredImportDirs();
|
||||
|
||||
foreach (path; importPaths)
|
||||
ModuleCache.addImportPath(path);
|
||||
writeln("Import directories: ", ModuleCache.getImportPaths());
|
||||
|
||||
auto socket = new TcpSocket(AddressFamily.INET);
|
||||
socket.blocking = true;
|
||||
socket.bind(new InternetAddress("127.0.0.1", port));
|
||||
|
|
@ -69,7 +65,15 @@ int main(string[] args)
|
|||
socket.close();
|
||||
writeln("Sockets shut down.");
|
||||
}
|
||||
|
||||
foreach (path; importPaths)
|
||||
ModuleCache.addImportPath(path);
|
||||
writeln("Import directories: ", ModuleCache.getImportPaths());
|
||||
|
||||
ubyte[1024 * 1024 * 4] buffer = void; // 4 megabytes should be enough for anybody...
|
||||
|
||||
writeln("Startup complete");
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto s = socket.accept();
|
||||
|
|
|
|||
Loading…
Reference in New Issue