Display template parameters for the code completion

This commit is contained in:
ryuukk 2023-10-05 05:26:35 +02:00
parent 5d1cfb6db2
commit 1be5d16f5e
3 changed files with 41 additions and 6 deletions

View File

@ -250,10 +250,16 @@ final class FirstPass : ASTVisitor
void processTypeIdentifierPart(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TypeIdentifierPart tip)
{
if (tip.identifierOrTemplateInstance)
{
processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance);
if (current)
current.calltip = buildCalltip(tip.identifierOrTemplateInstance.tokens);
}
if (tip.typeIdentifierPart)
{
processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart);
}
// 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)
{
if (PrimaryExpression pe = ue.primaryExpression)
@ -449,8 +480,11 @@ final class FirstPass : ASTVisitor
if (dec.type && dec.type.type2 && dec.type.type2.typeIdentifierPart)
{
TypeIdentifierPart typeIdentifierPart = cast(TypeIdentifierPart) dec.type.type2.typeIdentifierPart;
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);
}
}

View File

@ -35,6 +35,7 @@ import dparse.ast;
import dparse.lexer;
import std.algorithm : filter;
import std.range;
import std.stdio;
void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
{
@ -165,13 +166,12 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
{
assert(type);
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.qualifier = type.qualifier;
newType.protection = type.protection;
newType.symbolFile = type.symbolFile;
newType.doc = type.doc;
newType.callTip = type.callTip;
newType.type = type.type;
DSymbol*[string] mapping;
@ -189,7 +189,6 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
continue;
}
auto key = part.name;
DSymbol* first;
bool isBuiltin;
foreach(i, crumb; ti.args[count].chain)
@ -233,7 +232,6 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC
}
}
}
// 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
@ -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;
DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping);
//writeln(">>", variableSym.name, " > ", newType.name);
variableSym.type = newType;
variableSym.ownType = true;
}
@ -524,6 +522,7 @@ do
suffix.ownType = false;
symbol.type = lastSuffix;
symbol.ownType = true;
if (currentSymbol is null && !remainingImports.empty)
{
// info("Deferring type resolution for ", symbol.name);

View File

@ -48,6 +48,8 @@ struct VariableContext
string[] chain;
TypeInstance*[] args;
string name;
string calltip;
}
TypeInstance* root;
string calltip;
}