Display template parameters for the code completion
This commit is contained in:
parent
5d1cfb6db2
commit
1be5d16f5e
|
@ -250,10 +250,16 @@ final class FirstPass : ASTVisitor
|
||||||
void processTypeIdentifierPart(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TypeIdentifierPart tip)
|
void processTypeIdentifierPart(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TypeIdentifierPart tip)
|
||||||
{
|
{
|
||||||
if (tip.identifierOrTemplateInstance)
|
if (tip.identifierOrTemplateInstance)
|
||||||
|
{
|
||||||
processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance);
|
processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance);
|
||||||
|
if (current)
|
||||||
|
current.calltip = buildCalltip(tip.identifierOrTemplateInstance.tokens);
|
||||||
|
}
|
||||||
|
|
||||||
if (tip.typeIdentifierPart)
|
if (tip.typeIdentifierPart)
|
||||||
|
{
|
||||||
processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart);
|
processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: handle `tip.dot` and `tip.indexer`
|
// TODO: handle `tip.dot` and `tip.indexer`
|
||||||
}
|
}
|
||||||
|
@ -348,6 +354,31 @@ final class FirstPass : ASTVisitor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string buildCalltip(const(Token)[] tokens)
|
||||||
|
{
|
||||||
|
string calltip;
|
||||||
|
foreach(tk; tokens)
|
||||||
|
{
|
||||||
|
if (tk == tok!"!")
|
||||||
|
calltip ~= "!";
|
||||||
|
else if (tk == tok!"(")
|
||||||
|
calltip ~= "(";
|
||||||
|
else if (tk == tok!")")
|
||||||
|
calltip ~= ")";
|
||||||
|
else if (tk == tok!"[")
|
||||||
|
calltip ~= "[";
|
||||||
|
else if (tk == tok!"]")
|
||||||
|
calltip ~= "]";
|
||||||
|
else if (tk == tok!",")
|
||||||
|
calltip ~= ",";
|
||||||
|
else if (tk == tok!"")
|
||||||
|
calltip ~= " ";
|
||||||
|
else
|
||||||
|
calltip ~= tk.text;
|
||||||
|
}
|
||||||
|
return calltip;
|
||||||
|
}
|
||||||
|
|
||||||
void traverseUnaryExpression(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue)
|
void traverseUnaryExpression(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue)
|
||||||
{
|
{
|
||||||
if (PrimaryExpression pe = ue.primaryExpression)
|
if (PrimaryExpression pe = ue.primaryExpression)
|
||||||
|
@ -449,8 +480,11 @@ final class FirstPass : ASTVisitor
|
||||||
if (dec.type && dec.type.type2 && dec.type.type2.typeIdentifierPart)
|
if (dec.type && dec.type.type2 && dec.type.type2.typeIdentifierPart)
|
||||||
{
|
{
|
||||||
TypeIdentifierPart typeIdentifierPart = cast(TypeIdentifierPart) dec.type.type2.typeIdentifierPart;
|
TypeIdentifierPart typeIdentifierPart = cast(TypeIdentifierPart) dec.type.type2.typeIdentifierPart;
|
||||||
|
|
||||||
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)();
|
||||||
|
|
||||||
|
if (typeIdentifierPart.identifierOrTemplateInstance)
|
||||||
|
lookup.ctx.calltip = buildCalltip(typeIdentifierPart.identifierOrTemplateInstance.tokens);
|
||||||
|
|
||||||
processTypeIdentifierPart(symbol, lookup, &lookup.ctx, lookup.ctx.root, typeIdentifierPart);
|
processTypeIdentifierPart(symbol, lookup, &lookup.ctx, lookup.ctx.root, typeIdentifierPart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import dparse.ast;
|
||||||
import dparse.lexer;
|
import dparse.lexer;
|
||||||
import std.algorithm : filter;
|
import std.algorithm : filter;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
|
void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
|
||||||
{
|
{
|
||||||
|
@ -165,13 +166,12 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
|
||||||
{
|
{
|
||||||
assert(type);
|
assert(type);
|
||||||
DSymbol* newType = GCAllocator.instance.make!DSymbol("dummy", CompletionKind.dummy, null);
|
DSymbol* newType = GCAllocator.instance.make!DSymbol("dummy", CompletionKind.dummy, null);
|
||||||
newType.name = type.name;
|
newType.name = ti ? istring(ti.calltip) : istring(lookup.ctx.calltip);
|
||||||
newType.kind = type.kind;
|
newType.kind = type.kind;
|
||||||
newType.qualifier = type.qualifier;
|
newType.qualifier = type.qualifier;
|
||||||
newType.protection = type.protection;
|
newType.protection = type.protection;
|
||||||
newType.symbolFile = type.symbolFile;
|
newType.symbolFile = type.symbolFile;
|
||||||
newType.doc = type.doc;
|
newType.doc = type.doc;
|
||||||
newType.callTip = type.callTip;
|
|
||||||
newType.type = type.type;
|
newType.type = type.type;
|
||||||
DSymbol*[string] mapping;
|
DSymbol*[string] mapping;
|
||||||
|
|
||||||
|
@ -189,7 +189,6 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto key = part.name;
|
auto key = part.name;
|
||||||
|
|
||||||
DSymbol* first;
|
DSymbol* first;
|
||||||
bool isBuiltin;
|
bool isBuiltin;
|
||||||
foreach(i, crumb; ti.args[count].chain)
|
foreach(i, crumb; ti.args[count].chain)
|
||||||
|
@ -234,7 +233,6 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// HACK: to support functions with template arguments that return a generic type
|
// HACK: to support functions with template arguments that return a generic type
|
||||||
// first.d in processParameters only store the function's return type in the callTip
|
// first.d in processParameters only store the function's return type in the callTip
|
||||||
// maybe it's time to properly handle it by creating a proper symbol, so we can have
|
// maybe it's time to properly handle it by creating a proper symbol, so we can have
|
||||||
|
@ -334,7 +332,7 @@ void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, Va
|
||||||
if (current.chain.length == 0) return; // TODO: should not be empty, happens for simple stuff Inner inner;
|
if (current.chain.length == 0) return; // TODO: should not be empty, happens for simple stuff Inner inner;
|
||||||
|
|
||||||
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
|
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
|
||||||
|
//writeln(">>", variableSym.name, " > ", newType.name);
|
||||||
variableSym.type = newType;
|
variableSym.type = newType;
|
||||||
variableSym.ownType = true;
|
variableSym.ownType = true;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +522,7 @@ do
|
||||||
suffix.ownType = false;
|
suffix.ownType = false;
|
||||||
symbol.type = lastSuffix;
|
symbol.type = lastSuffix;
|
||||||
symbol.ownType = true;
|
symbol.ownType = true;
|
||||||
|
|
||||||
if (currentSymbol is null && !remainingImports.empty)
|
if (currentSymbol is null && !remainingImports.empty)
|
||||||
{
|
{
|
||||||
// info("Deferring type resolution for ", symbol.name);
|
// info("Deferring type resolution for ", symbol.name);
|
||||||
|
|
|
@ -48,6 +48,8 @@ struct VariableContext
|
||||||
string[] chain;
|
string[] chain;
|
||||||
TypeInstance*[] args;
|
TypeInstance*[] args;
|
||||||
string name;
|
string name;
|
||||||
|
string calltip;
|
||||||
}
|
}
|
||||||
TypeInstance* root;
|
TypeInstance* root;
|
||||||
|
string calltip;
|
||||||
}
|
}
|
Loading…
Reference in New Issue