From 7cd4b1d85766727b03c407cc83925558d9ff063e Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 16:06:35 +0100 Subject: [PATCH 1/6] resolve template arguments --- dsymbol/src/dsymbol/conversion/first.d | 21 +++++++++++ dsymbol/src/dsymbol/conversion/second.d | 49 +++++++++++++++++++++++++ dsymbol/src/dsymbol/symbol.d | 5 +++ 3 files changed, 75 insertions(+) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e488566..e1713c4 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -255,6 +255,27 @@ final class FirstPass : ASTVisitor // TODO: remove this cast. See the note on structFieldTypes structFieldTypes.insert(cast() dec.type); } + if (dec.type.type2 && dec.type.type2.typeIdentifierPart) + { + auto typeIdentifierPart = dec.type.type2.typeIdentifierPart; + if (typeIdentifierPart && typeIdentifierPart.identifierOrTemplateInstance && + typeIdentifierPart.identifierOrTemplateInstance.templateInstance) + { + auto templateInstance = typeIdentifierPart.identifierOrTemplateInstance.templateInstance; + if (templateInstance.templateArguments.templateArgumentList) + { + foreach(i, targ; templateInstance.templateArguments.templateArgumentList.items) + { + // TODO: support template with multiple arguments + } + } + else if (typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument) + { + auto singleArg = typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument; + symbol.acSymbol.tmplArgNames.insert(istring(singleArg.token.text)); + } + } + } } if (dec.autoDeclaration !is null) { diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 433cd66..f39f1cb 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -55,6 +55,13 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups, moduleScope, cache); } + + if (currentSymbol.acSymbol.tmplArgNames.length > 0 && currentSymbol.acSymbol.type) + { + auto type = currentSymbol.acSymbol.type; + if (type.kind == structName || type.kind == className) + resolveTemplate(currentSymbol.acSymbol, type, moduleScope, cache); + } break; case importSymbol: if (currentSymbol.acSymbol.type is null) @@ -99,6 +106,48 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac } } +/** + * Resolve template arguments + */ +void resolveTemplate(DSymbol* sym, DSymbol* type, Scope* moduleScope, ref ModuleCache cache) +{ + if (sym.tmplArgNames.length > 1) return; + auto argName = sym.tmplArgNames.back; + auto result = moduleScope.getSymbolsAtGlobalScope(argName); + if (result.length > 0) + { + auto argSymbol = result[0]; + DSymbol* newType = GCAllocator.instance.make!DSymbol(type.name, type.kind, null); + newType.qualifier = type.qualifier; + newType.protection = type.protection; + newType.symbolFile = type.symbolFile; + newType.doc = type.doc; + newType.callTip = type.callTip; + foreach(part; type.opSlice()) + { + if (part.kind == typeTmpParam) + { } + else if (part.type && part.type.kind == typeTmpParam) + { + DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, argSymbol); + newPart.qualifier = part.qualifier; + newPart.protection = part.protection; + newPart.symbolFile = part.symbolFile; + newPart.doc = part.doc; + newPart.callTip = part.callTip; + newType.addChild(newPart, true); + } + else + { + newType.addChild(part, false); + } + } + + sym.type = newType; + sym.ownType = true; + } +} + void resolveImport(DSymbol* acSymbol, ref TypeLookups typeLookups, ref ModuleCache cache) in diff --git a/dsymbol/src/dsymbol/symbol.d b/dsymbol/src/dsymbol/symbol.d index f6d2abb..ad61b5c 100644 --- a/dsymbol/src/dsymbol/symbol.d +++ b/dsymbol/src/dsymbol/symbol.d @@ -381,6 +381,11 @@ struct DSymbol // TODO: remove since we have function arguments UnrolledList!(istring) argNames; + /** + * Names of template arguments + */ + UnrolledList!(istring) tmplArgNames; + /** * Function parameter symbols */ From cb9d5b063dd56c5628a151a2e81528de45fc5418 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 16:14:04 +0100 Subject: [PATCH 2/6] forgot enum type --- dsymbol/src/dsymbol/conversion/second.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index f39f1cb..aad3e5d 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -125,9 +125,9 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, Scope* moduleScope, ref Module newType.callTip = type.callTip; foreach(part; type.opSlice()) { - if (part.kind == typeTmpParam) + if (part.kind == CompletionKind.typeTmpParam) { } - else if (part.type && part.type.kind == typeTmpParam) + else if (part.type && part.type.kind == CompletionKind.typeTmpParam) { DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, argSymbol); newPart.qualifier = part.qualifier; From 2b248747fadd7c19521659b472f9a3f14deddb35 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 18:15:08 +0100 Subject: [PATCH 3/6] make sure templates from parts are also resolved --- dsymbol/src/dsymbol/conversion/first.d | 2 +- dsymbol/src/dsymbol/conversion/second.d | 44 +++++++++++++++++-------- dsymbol/src/dsymbol/symbol.d | 2 +- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e1713c4..a3da11f 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -272,7 +272,7 @@ final class FirstPass : ASTVisitor else if (typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument) { auto singleArg = typeIdentifierPart.identifierOrTemplateInstance.templateInstance.templateArguments.templateSingleArgument; - symbol.acSymbol.tmplArgNames.insert(istring(singleArg.token.text)); + symbol.acSymbol.tmplArgNames ~= istring(singleArg.token.text); } } } diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index aad3e5d..f10453c 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -33,6 +33,7 @@ import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.logger; import dparse.ast; import dparse.lexer; +import std.compiler; void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache) { @@ -55,13 +56,6 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups, moduleScope, cache); } - - if (currentSymbol.acSymbol.tmplArgNames.length > 0 && currentSymbol.acSymbol.type) - { - auto type = currentSymbol.acSymbol.type; - if (type.kind == structName || type.kind == className) - resolveTemplate(currentSymbol.acSymbol, type, moduleScope, cache); - } break; case importSymbol: if (currentSymbol.acSymbol.type is null) @@ -101,6 +95,19 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac resolveMixinTemplates(currentSymbol.acSymbol, currentSymbol.typeLookups, moduleScope, cache); break; + case variableName: + if (currentSymbol.acSymbol.tmplArgNames.length > 0 && currentSymbol.acSymbol.type) + { + auto tArgNames = currentSymbol.acSymbol.tmplArgNames; + auto type = currentSymbol.acSymbol.type; + if (type.kind == structName || type.kind == className) + resolveTemplate(currentSymbol.acSymbol, type, tArgNames, moduleScope, cache); + } + else + { + warning("no type: ", currentSymbol.acSymbol.name," ", currentSymbol.acSymbol.kind); + } + break; default: break; } @@ -109,24 +116,30 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac /** * Resolve template arguments */ -void resolveTemplate(DSymbol* sym, DSymbol* type, Scope* moduleScope, ref ModuleCache cache) +void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgNames, Scope* moduleScope, ref ModuleCache cache) { - if (sym.tmplArgNames.length > 1) return; - auto argName = sym.tmplArgNames.back; + if (tmplArgNames.length > 1) return; + auto argName = tmplArgNames[0]; auto result = moduleScope.getSymbolsAtGlobalScope(argName); if (result.length > 0) { auto argSymbol = result[0]; - DSymbol* newType = GCAllocator.instance.make!DSymbol(type.name, type.kind, null); + DSymbol* newType = GCAllocator.instance.make!DSymbol("", CompletionKind.dummy, null); + newType.name = type.name; + newType.kind = type.kind; newType.qualifier = type.qualifier; newType.protection = type.protection; newType.symbolFile = type.symbolFile; newType.doc = type.doc; newType.callTip = type.callTip; + + DSymbol* currentT = null; foreach(part; type.opSlice()) { if (part.kind == CompletionKind.typeTmpParam) - { } + { + currentT = part; + } else if (part.type && part.type.kind == CompletionKind.typeTmpParam) { DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, argSymbol); @@ -135,14 +148,19 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, Scope* moduleScope, ref Module newPart.symbolFile = part.symbolFile; newPart.doc = part.doc; newPart.callTip = part.callTip; + newPart.type = argSymbol; newType.addChild(newPart, true); } else { + if (part.tmplArgNames.length > 0) + { + auto innerArg = part.tmplArgNames[0]; + resolveTemplate(part, part.type, [argName], moduleScope, cache); + } newType.addChild(part, false); } } - sym.type = newType; sym.ownType = true; } diff --git a/dsymbol/src/dsymbol/symbol.d b/dsymbol/src/dsymbol/symbol.d index ad61b5c..6494f7a 100644 --- a/dsymbol/src/dsymbol/symbol.d +++ b/dsymbol/src/dsymbol/symbol.d @@ -384,7 +384,7 @@ struct DSymbol /** * Names of template arguments */ - UnrolledList!(istring) tmplArgNames; + istring[] tmplArgNames; /** * Function parameter symbols From 0e2f50d6f9b2bd13e97567e56e86e43c2f38175f Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 18:17:40 +0100 Subject: [PATCH 4/6] we don't need that import --- dsymbol/src/dsymbol/conversion/second.d | 1 - 1 file changed, 1 deletion(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index f10453c..f538442 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -33,7 +33,6 @@ import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.logger; import dparse.ast; import dparse.lexer; -import std.compiler; void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache) { From 55b28fe8981cd6995d27aec00198136a744b1b0a Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 20:29:21 +0100 Subject: [PATCH 5/6] added support for functions --- dsymbol/src/dsymbol/conversion/second.d | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) mode change 100644 => 100755 dsymbol/src/dsymbol/conversion/second.d diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d old mode 100644 new mode 100755 index f538442..6ab991a --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -95,6 +95,7 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac moduleScope, cache); break; case variableName: + case functionName: if (currentSymbol.acSymbol.tmplArgNames.length > 0 && currentSymbol.acSymbol.type) { auto tArgNames = currentSymbol.acSymbol.tmplArgNames; @@ -148,6 +149,13 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgN newPart.doc = part.doc; newPart.callTip = part.callTip; newPart.type = argSymbol; + if (part.kind == CompletionKind.functionName) + { + if (part.type && part.type.kind == CompletionKind.typeTmpParam) + { + newPart.type = argSymbol; + } + } newType.addChild(newPart, true); } else @@ -155,7 +163,8 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgN if (part.tmplArgNames.length > 0) { auto innerArg = part.tmplArgNames[0]; - resolveTemplate(part, part.type, [argName], moduleScope, cache); + if (innerArg == currentT.name) + resolveTemplate(part, part.type, [argName], moduleScope, cache); } newType.addChild(part, false); } From 220dcb0445242e42ee474e9c17956436f985f364 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 6 Feb 2023 21:42:20 +0100 Subject: [PATCH 6/6] added depth limit --- dsymbol/src/dsymbol/conversion/second.d | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) mode change 100755 => 100644 dsymbol/src/dsymbol/conversion/second.d diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d old mode 100755 new mode 100644 index 6ab991a..4622f06 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -101,7 +101,10 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac auto tArgNames = currentSymbol.acSymbol.tmplArgNames; auto type = currentSymbol.acSymbol.type; if (type.kind == structName || type.kind == className) - resolveTemplate(currentSymbol.acSymbol, type, tArgNames, moduleScope, cache); + { + int depth; + resolveTemplate(currentSymbol.acSymbol, type, tArgNames, moduleScope, cache, depth); + } } else { @@ -116,8 +119,9 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac /** * Resolve template arguments */ -void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgNames, Scope* moduleScope, ref ModuleCache cache) +void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgNames, Scope* moduleScope, ref ModuleCache cache, ref int depth) { + depth += 1; if (tmplArgNames.length > 1) return; auto argName = tmplArgNames[0]; auto result = moduleScope.getSymbolsAtGlobalScope(argName); @@ -164,7 +168,10 @@ void resolveTemplate(DSymbol* sym, DSymbol* type, scope const istring[] tmplArgN { auto innerArg = part.tmplArgNames[0]; if (innerArg == currentT.name) - resolveTemplate(part, part.type, [argName], moduleScope, cache); + { + if (depth < 50) + resolveTemplate(part, part.type, [argName], moduleScope, cache, depth); + } } newType.addChild(part, false); }