diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e488566..a3da11f 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 ~= 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..4622f06 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -94,11 +94,93 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac resolveMixinTemplates(currentSymbol.acSymbol, currentSymbol.typeLookups, moduleScope, cache); break; + case variableName: + case functionName: + 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) + { + int depth; + resolveTemplate(currentSymbol.acSymbol, type, tArgNames, moduleScope, cache, depth); + } + } + else + { + warning("no type: ", currentSymbol.acSymbol.name," ", currentSymbol.acSymbol.kind); + } + break; default: break; } } +/** + * Resolve template arguments + */ +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); + if (result.length > 0) + { + auto argSymbol = result[0]; + 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); + newPart.qualifier = part.qualifier; + newPart.protection = part.protection; + newPart.symbolFile = part.symbolFile; + 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 + { + if (part.tmplArgNames.length > 0) + { + auto innerArg = part.tmplArgNames[0]; + if (innerArg == currentT.name) + { + if (depth < 50) + resolveTemplate(part, part.type, [argName], moduleScope, cache, depth); + } + } + 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..6494f7a 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 + */ + istring[] tmplArgNames; + /** * Function parameter symbols */