From 1be5d16f5e1c67ac79ac2af8056bd0b7dbbe965a Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 05:26:35 +0200 Subject: [PATCH] Display template parameters for the code completion --- dsymbol/src/dsymbol/conversion/first.d | 36 ++++++++++++++++++++++++- dsymbol/src/dsymbol/conversion/second.d | 9 +++---- dsymbol/src/dsymbol/type_lookup.d | 2 ++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 196bd22..2d17949 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -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); } } diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 394faa8..7d5c1c4 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -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); diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d index c417c53..3619024 100644 --- a/dsymbol/src/dsymbol/type_lookup.d +++ b/dsymbol/src/dsymbol/type_lookup.d @@ -48,6 +48,8 @@ struct VariableContext string[] chain; TypeInstance*[] args; string name; + string calltip; } TypeInstance* root; + string calltip; } \ No newline at end of file