Created
August 12, 2023 19:11
-
-
Save WebFreak001/2c0fd403ca96bb65f9e195b21869b14e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d | |
index c9ac1b6..196bd22 100644 | |
--- a/dsymbol/src/dsymbol/conversion/first.d | |
+++ b/dsymbol/src/dsymbol/conversion/first.d | |
@@ -237,10 +237,192 @@ final class FirstPass : ASTVisitor | |
currentSymbol.addChild(symbol, true); | |
symbol.acSymbol.protection = protection.current; | |
} | |
+ | |
+ | |
+ void processIdentifierOrTemplate(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, IdentifierOrTemplateInstance ioti) | |
+ { | |
+ if (ioti.identifier != tok!"") | |
+ current.chain ~= ioti.identifier.text; | |
+ else if (ioti.templateInstance) | |
+ processTemplateInstance(symbol, lookup, ctx, current, ioti.templateInstance); | |
+ } | |
+ | |
+ void processTypeIdentifierPart(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TypeIdentifierPart tip) | |
+ { | |
+ if (tip.identifierOrTemplateInstance) | |
+ processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance); | |
+ | |
+ if (tip.typeIdentifierPart) | |
+ processTypeIdentifierPart(symbol, lookup, ctx, current, tip.typeIdentifierPart); | |
+ | |
+ // TODO: handle `tip.dot` and `tip.indexer` | |
+ } | |
+ | |
+ void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs) | |
+ { | |
+ if (targs.namedTemplateArgumentList) | |
+ { | |
+ foreach(i, targ; targs.namedTemplateArgumentList.items) | |
+ { | |
+ // TODO: handle targ.assignExpression | |
+ if (targ.type is null) continue; | |
+ if (targ.type.type2 is null) continue; | |
+ | |
+ auto part = targ.type.type2.typeIdentifierPart; | |
+ if (part is null) | |
+ { | |
+ if (targ.type.type2.builtinType == tok!"") continue; | |
+ auto builtInName = getBuiltinTypeName(targ.type.type2.builtinType); | |
+ auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); | |
+ newArg.chain ~= builtInName; | |
+ current.args ~= newArg; | |
+ continue; | |
+ } | |
+ | |
+ auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); | |
+ current.args ~= newArg; | |
+ | |
+ if (part.identifierOrTemplateInstance) | |
+ { | |
+ processIdentifierOrTemplate(symbol, lookup, ctx, newArg, part.identifierOrTemplateInstance); | |
+ } | |
+ if (part.typeIdentifierPart) | |
+ { | |
+ if (part.typeIdentifierPart.identifierOrTemplateInstance) | |
+ processIdentifierOrTemplate(symbol, lookup, ctx, newArg, part.typeIdentifierPart.identifierOrTemplateInstance); | |
+ } | |
+ } | |
+ } | |
+ else if (targs.templateSingleArgument) | |
+ { | |
+ auto singleArg = targs.templateSingleArgument; | |
+ auto arg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); | |
+ arg.name = singleArg.token.text; | |
+ arg.chain ~= arg.name; | |
+ current.args ~= arg; | |
+ } | |
+ } | |
+ | |
+ void processTemplateInstance(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateInstance ti) | |
+ { | |
+ if (ti.identifier != tok!"") | |
+ current.chain ~= ti.identifier.text; | |
+ | |
+ if (ti.templateArguments) | |
+ processTemplateArguments(symbol, lookup, ctx, current, ti.templateArguments); | |
+ } | |
+ | |
+ void buildChain(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, TypeIdentifierPart tip) | |
+ { | |
+ if (tip.identifierOrTemplateInstance) | |
+ buildChainTemplateOrIdentifier(symbol, lookup, ctx, tip.identifierOrTemplateInstance); | |
+ if (tip.typeIdentifierPart) | |
+ buildChain(symbol, lookup, ctx, tip.typeIdentifierPart); | |
+ // TODO: handle `tip.indexer` | |
+ } | |
+ | |
+ void buildChainTemplateOrIdentifier(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, IdentifierOrTemplateInstance iot) | |
+ { | |
+ auto crumb = iot.identifier; | |
+ if (crumb != tok!"") | |
+ lookup.breadcrumbs.insert(istring(crumb.text)); | |
+ | |
+ if (iot.templateInstance) | |
+ { | |
+ if (iot.templateInstance.identifier != tok!"") | |
+ lookup.breadcrumbs.insert(istring(iot.templateInstance.identifier.text)); | |
+ | |
+ // TODO: finish handling `iot.templateInstance.templateArguments` | |
+ if (iot.templateInstance.templateArguments) | |
+ { | |
+ if (iot.templateInstance.templateArguments.templateSingleArgument) | |
+ { | |
+ auto tsaTok = iot.templateInstance.templateArguments.templateSingleArgument.token; | |
+ if (tsaTok.text == "") | |
+ lookup.breadcrumbs.insert(istring(str(tsaTok.type))); | |
+ // TODO: investigate why this break everything | |
+ // else | |
+ // lookup.breadcrumbs.insert(istring(tsaTok.text)); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ void traverseUnaryExpression(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue) | |
+ { | |
+ if (PrimaryExpression pe = ue.primaryExpression) | |
+ { | |
+ if (pe.identifierOrTemplateInstance) | |
+ buildChainTemplateOrIdentifier(symbol, lookup, ctx, pe.identifierOrTemplateInstance); | |
+ | |
+ if (pe.basicType != tok!"") | |
+ lookup.breadcrumbs.insert(internString(str(pe.basicType.type))); | |
+ switch (pe.primary.type) | |
+ { | |
+ case tok!"identifier": | |
+ lookup.breadcrumbs.insert(internString(pe.primary.text)); | |
+ break; | |
+ case tok!"doubleLiteral": | |
+ lookup.breadcrumbs.insert(DOUBLE_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"floatLiteral": | |
+ lookup.breadcrumbs.insert(FLOAT_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"idoubleLiteral": | |
+ lookup.breadcrumbs.insert(IDOUBLE_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"ifloatLiteral": | |
+ lookup.breadcrumbs.insert(IFLOAT_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"intLiteral": | |
+ lookup.breadcrumbs.insert(INT_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"longLiteral": | |
+ lookup.breadcrumbs.insert(LONG_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"realLiteral": | |
+ lookup.breadcrumbs.insert(REAL_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"irealLiteral": | |
+ lookup.breadcrumbs.insert(IREAL_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"uintLiteral": | |
+ lookup.breadcrumbs.insert(UINT_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"ulongLiteral": | |
+ lookup.breadcrumbs.insert(ULONG_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"characterLiteral": | |
+ lookup.breadcrumbs.insert(CHAR_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"dstringLiteral": | |
+ lookup.breadcrumbs.insert(DSTRING_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"stringLiteral": | |
+ lookup.breadcrumbs.insert(STRING_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"wstringLiteral": | |
+ lookup.breadcrumbs.insert(WSTRING_LITERAL_SYMBOL_NAME); | |
+ break; | |
+ case tok!"false": | |
+ case tok!"true": | |
+ lookup.breadcrumbs.insert(BOOL_VALUE_SYMBOL_NAME); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (IdentifierOrTemplateInstance iot = ue.identifierOrTemplateInstance) | |
+ buildChainTemplateOrIdentifier(symbol, lookup, ctx, iot); | |
+ | |
+ if(ue.unaryExpression) traverseUnaryExpression(symbol, lookup, ctx, ue.unaryExpression); | |
+ } | |
override void visit(const VariableDeclaration dec) | |
{ | |
assert (currentSymbol); | |
+ | |
foreach (declarator; dec.declarators) | |
{ | |
SemanticSymbol* symbol = allocateSemanticSymbol( | |
@@ -261,6 +443,16 @@ final class FirstPass : ASTVisitor | |
// TODO: remove this cast. See the note on structFieldTypes | |
structFieldTypes.insert(cast() dec.type); | |
} | |
+ | |
+ auto lookup = symbol.typeLookups.front; | |
+ | |
+ 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)(); | |
+ processTypeIdentifierPart(symbol, lookup, &lookup.ctx, lookup.ctx.root, typeIdentifierPart); | |
+ } | |
} | |
if (dec.autoDeclaration !is null) | |
{ | |
@@ -283,6 +475,66 @@ final class FirstPass : ASTVisitor | |
// TODO: remove this cast. See the note on structFieldTypes | |
structFieldTypes.insert(null); | |
} | |
+ | |
+ auto lookup = symbol.typeLookups.front; | |
+ | |
+ auto initializer = part.initializer.nonVoidInitializer; | |
+ if (initializer && initializer.assignExpression) | |
+ { | |
+ UnaryExpression unary = cast(UnaryExpression) initializer.assignExpression; | |
+ | |
+ if (unary && (unary.newExpression || unary.indexExpression)) | |
+ continue; | |
+ | |
+ lookup.breadcrumbs.clear(); | |
+ if (unary) | |
+ { | |
+ if (CastExpression castExpression = unary.castExpression) | |
+ { | |
+ if (castExpression.type && castExpression.type.type2) | |
+ { | |
+ Type2 t2 = castExpression.type.type2; | |
+ if (t2 && t2.typeIdentifierPart) | |
+ buildChain(symbol, lookup, &lookup.ctx, t2.typeIdentifierPart); | |
+ } | |
+ continue; | |
+ } | |
+ else if (FunctionCallExpression fc = unary.functionCallExpression) | |
+ unary = fc.unaryExpression; | |
+ // build chain | |
+ traverseUnaryExpression(symbol, lookup, &lookup.ctx, unary); | |
+ // needs to be reversed because it got added in order (right->left) | |
+ auto crumbs = &lookup.breadcrumbs; | |
+ istring[] result; | |
+ foreach(c; *crumbs) | |
+ result ~= c; | |
+ | |
+ crumbs.clear(); | |
+ foreach_reverse(c; result) | |
+ lookup.breadcrumbs.insert(c); | |
+ | |
+ // check template | |
+ if (IdentifierOrTemplateInstance iot = unary.identifierOrTemplateInstance) | |
+ { | |
+ if (iot.templateInstance) | |
+ { | |
+ lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)(); | |
+ processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, iot.templateInstance); | |
+ } | |
+ } | |
+ else if (PrimaryExpression pe = unary.primaryExpression) | |
+ { | |
+ if (pe.identifierOrTemplateInstance) | |
+ { | |
+ if (pe.identifierOrTemplateInstance.templateInstance) | |
+ { | |
+ lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)(); | |
+ processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, pe.identifierOrTemplateInstance.templateInstance); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
} | |
} | |
} | |
diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d | |
index a7b3580..394faa8 100644 | |
--- a/dsymbol/src/dsymbol/conversion/second.d | |
+++ b/dsymbol/src/dsymbol/conversion/second.d | |
@@ -57,6 +57,22 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac | |
resolveType(currentSymbol.acSymbol, currentSymbol.typeLookups, | |
moduleScope, cache); | |
} | |
+ | |
+ if (currentSymbol.acSymbol.type && currentSymbol.typeLookups.length > 0) | |
+ { | |
+ TypeLookup* lookup = currentSymbol.typeLookups.front; | |
+ if (lookup.ctx.root) | |
+ { | |
+ auto type = currentSymbol.acSymbol.type; | |
+ if (type.kind == structName || type.kind == className || type.kind == functionName) | |
+ if (lookup.ctx.root.args.length > 0) | |
+ { | |
+ DSymbol*[string] mapping; | |
+ int depth; | |
+ resolveTemplate(currentSymbol.acSymbol, type, lookup, lookup.ctx.root, moduleScope, cache, depth, mapping); | |
+ } | |
+ } | |
+ } | |
break; | |
case importSymbol: | |
if (currentSymbol.acSymbol.type is null) | |
@@ -81,8 +97,22 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac | |
break; | |
} | |
+ // let's be methodic about the way we traverse symbols | |
+ // so that childs have access to resolved symbols | |
+ // functions should be last, because inside, there might be symbols that references | |
+ // code from the parent not yet resolved (templates) | |
+ foreach (child; currentSymbol.children) | |
+ if (child.acSymbol.kind != CompletionKind.variableName && child.acSymbol.kind != CompletionKind.functionName) | |
+ secondPass(child, moduleScope, cache); | |
+ | |
foreach (child; currentSymbol.children) | |
- secondPass(child, moduleScope, cache); | |
+ if (child.acSymbol.kind == CompletionKind.variableName) | |
+ secondPass(child, moduleScope, cache); | |
+ | |
+ foreach (child; currentSymbol.children) | |
+ if (child.acSymbol.kind == CompletionKind.functionName) | |
+ secondPass(child, moduleScope, cache); | |
+ | |
// Alias this and mixin templates are resolved after child nodes are | |
// resolved so that the correct symbol information will be available. | |
@@ -100,6 +130,214 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac | |
break; | |
} | |
} | |
+/** | |
+ * Extract the return type from the callTip of a function symbol | |
+ */ | |
+string extractReturnType(string callTip) | |
+{ | |
+ import std.string: indexOf; | |
+ | |
+ auto spaceIndex = callTip.indexOf(" "); | |
+ if (spaceIndex <= 0) return ""; | |
+ | |
+ auto retPart = callTip[0 .. spaceIndex]; | |
+ auto returnTypeConst = retPart.length > 6 ? retPart[0 .. 6] == "const(" : false; | |
+ auto returnTypeInout = retPart.length > 6 ? retPart[0 .. 6] == "inout(" : false; | |
+ if (returnTypeConst || returnTypeInout) | |
+ { | |
+ retPart = retPart[retPart.indexOf("(") + 1 .. $]; | |
+ retPart = retPart[0 .. retPart.indexOf(")")]; | |
+ } | |
+ auto returnTypePtr = retPart[$-1] == '*'; | |
+ auto returnTypeArr = retPart[$-1] == ']'; | |
+ if (returnTypePtr) | |
+ { | |
+ retPart = retPart[0 .. $-1]; | |
+ } | |
+ return retPart; | |
+} | |
+ | |
+/** | |
+ * Copy a Type symbol with templates arguments | |
+ * Returns: Copy of Type symbol | |
+ */ | |
+DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableContext.TypeInstance* ti, ref ModuleCache cache, Scope* moduleScope, ref int depth, DSymbol*[string] m) | |
+{ | |
+ assert(type); | |
+ DSymbol* newType = GCAllocator.instance.make!DSymbol("dummy", 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; | |
+ newType.type = type.type; | |
+ DSymbol*[string] mapping; | |
+ | |
+ int count = 0; | |
+ if (ti.args.length > 0) | |
+ { | |
+ foreach(part; type.opSlice()) | |
+ { | |
+ if (part.kind == CompletionKind.typeTmpParam) | |
+ { | |
+ scope(exit) count++; | |
+ if (count >= ti.args.length) | |
+ { | |
+ // warning("too many T for args available, investigate"); | |
+ continue; | |
+ } | |
+ auto key = part.name; | |
+ | |
+ DSymbol* first; | |
+ bool isBuiltin; | |
+ foreach(i, crumb; ti.args[count].chain) | |
+ { | |
+ auto argName = crumb; | |
+ if (i == 0) | |
+ { | |
+ if (m && key in m) | |
+ { | |
+ argName = m[key].name; | |
+ } | |
+ | |
+ // check if that's a built in type | |
+ // if it is, then use it and skip the type creation step | |
+ foreach(builtin; builtinSymbols) | |
+ { | |
+ if (builtin.name == crumb) | |
+ { | |
+ first = builtin; | |
+ isBuiltin = true; | |
+ break; | |
+ } | |
+ } | |
+ auto result = moduleScope.getSymbolsAtGlobalScope(istring(argName)); | |
+ if (result.length == 0) | |
+ { | |
+ break; | |
+ } | |
+ first = result[0]; | |
+ } | |
+ else | |
+ first = first.getFirstPartNamed(istring(argName)); | |
+ } | |
+ | |
+ if (first is null) | |
+ continue; | |
+ | |
+ auto ca = ti.args[count]; | |
+ if (ca.chain.length > 0) | |
+ mapping[key] = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); | |
+ } | |
+ } | |
+ } | |
+ | |
+ | |
+ // 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 | |
+ // maybe it's time to properly handle it by creating a proper symbol, so we can have | |
+ // proper support for functions that return complex types such as templates | |
+ if (type.kind == CompletionKind.functionName) | |
+ { | |
+ auto callTip = type.callTip; | |
+ if (callTip && callTip.length > 1) | |
+ { | |
+ auto retType = extractReturnType(callTip); | |
+ if (retType in mapping) | |
+ { | |
+ auto result = mapping[retType]; | |
+ newType.ownType = result.kind == CompletionKind.keyword ? false : true; | |
+ newType.type = result; | |
+ } | |
+ } | |
+ } | |
+ | |
+ assert(newType); | |
+ string[] T_names; | |
+ foreach(part; type.opSlice()) | |
+ { | |
+ if (part.kind == CompletionKind.typeTmpParam) | |
+ { | |
+ T_names ~= part.name; | |
+ } | |
+ else if (part.type && part.type.kind == CompletionKind.typeTmpParam) | |
+ { | |
+ DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, null); | |
+ newPart.qualifier = part.qualifier; | |
+ newPart.protection = part.protection; | |
+ newPart.symbolFile = part.symbolFile; | |
+ newPart.doc = part.doc; | |
+ newPart.callTip = part.callTip; | |
+ | |
+ if (part.type.name in mapping) | |
+ { | |
+ auto result = mapping[part.type.name]; | |
+ newPart.ownType = result.kind == CompletionKind.keyword ? false : true; | |
+ newPart.type = result; | |
+ } | |
+ else if (m && part.type.name in m) | |
+ { | |
+ auto result = m[part.type.name]; | |
+ newPart.ownType = result.kind == CompletionKind.keyword ? false : true; | |
+ newPart.type = result; | |
+ } | |
+ | |
+ newType.addChild(newPart, true); | |
+ } | |
+ else | |
+ { | |
+ // BUG: doing it recursively messes with the mapping | |
+ // i need to debug this and figure out perhaps a better way to do this stuff | |
+ // maybe move the VariableContext to the symbol directly | |
+ // i'll need to experiemnt with it | |
+ | |
+ //DSymbol* part_T; | |
+ //if (depth < 50) | |
+ //if (part.type && part.kind == CompletionKind.variableName) | |
+ //foreach(partPart; part.type.opSlice()) | |
+ //{ | |
+ // if (partPart.kind == CompletionKind.typeTmpParam) | |
+ // { | |
+ // part_T = part; | |
+ // foreach(arg; ti.args) | |
+ // { | |
+ // warning(" > ", arg.chain); | |
+ // foreach(aa; arg.args) | |
+ // warning(" > ", aa.chain); | |
+ // } | |
+ // warning("go agane ".blue, part.name, " ", part.type.name, " with arg: ", ti.chain," Ts: ", T_names); | |
+ // resolveTemplate(part, part.type, lookup, ti, moduleScope, cache, depth, mapping); | |
+ // break; | |
+ // } | |
+ // //else if (partPart.type && partPart.type.kind == CompletionKind.typeTmpParam) | |
+ // //{ | |
+ // // warning("here!".red," ", partPart.name," ", partPart.type.name); | |
+ // //} | |
+ //} | |
+ newType.addChild(part, false); | |
+ } | |
+ } | |
+ return newType; | |
+} | |
+ | |
+/** | |
+ * Resolve template arguments | |
+ */ | |
+void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, VariableContext.TypeInstance* current, Scope* moduleScope, ref ModuleCache cache, ref int depth, DSymbol*[string] mapping = null) | |
+{ | |
+ depth += 1; | |
+ | |
+ if (variableSym is null || type is null) return; | |
+ | |
+ 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); | |
+ | |
+ variableSym.type = newType; | |
+ variableSym.ownType = true; | |
+} | |
void resolveImport(DSymbol* acSymbol, ref TypeLookups typeLookups, | |
ref ModuleCache cache) | |
@@ -281,6 +519,7 @@ do | |
if (lastSuffix !is null) | |
{ | |
assert(suffix !is null); | |
+ typeSwap(currentSymbol); | |
suffix.type = currentSymbol; | |
suffix.ownType = false; | |
symbol.type = lastSuffix; | |
diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d | |
index 2260e57..c417c53 100644 | |
--- a/dsymbol/src/dsymbol/type_lookup.d | |
+++ b/dsymbol/src/dsymbol/type_lookup.d | |
@@ -37,4 +37,17 @@ struct TypeLookup | |
UnrolledList!istring breadcrumbs; | |
/// The kind of type lookup | |
TypeLookupKind kind; | |
+ /// To store information about template instances | |
+ VariableContext ctx; | |
} | |
+ | |
+struct VariableContext | |
+{ | |
+ struct TypeInstance | |
+ { | |
+ string[] chain; | |
+ TypeInstance*[] args; | |
+ string name; | |
+ } | |
+ TypeInstance* root; | |
+} | |
\ No newline at end of file | |
diff --git a/dub.json b/dub.json | |
index f5bade8..7571586 100644 | |
--- a/dub.json | |
+++ b/dub.json | |
@@ -8,7 +8,7 @@ | |
"license": "GPL-3.0", | |
"dependencies": { | |
":dsymbol": "*", | |
- "libdparse": ">=0.23.0 <0.24.0", | |
+ "libdparse": ">=0.23.2 <0.24.0", | |
":common": "*", | |
"emsi_containers": "~>0.9.0" | |
}, | |
diff --git a/dub.selections.json b/dub.selections.json | |
index 6513ec2..6c91206 100644 | |
--- a/dub.selections.json | |
+++ b/dub.selections.json | |
@@ -3,7 +3,7 @@ | |
"versions": { | |
"dsymbol": "0.14.1", | |
"emsi_containers": "0.9.0", | |
- "libdparse": "0.23.0", | |
+ "libdparse": "0.23.2", | |
"msgpack-d": "1.0.4", | |
"stdx-allocator": "2.77.5" | |
} | |
diff --git a/msgpack-d b/msgpack-d | |
index 26ef07e..480f3bf 160000 | |
--- a/msgpack-d | |
+++ b/msgpack-d | |
@@ -1 +1 @@ | |
-Subproject commit 26ef07e16023483ad93e3f86374b19d0e541c924 | |
+Subproject commit 480f3bf9ee80ccf6695ed900cfcc1850ba8da991 | |
diff --git a/tests/tc027/expected1.txt b/tests/tc027/expected1.txt | |
index 3ce878f..d338689 100644 | |
--- a/tests/tc027/expected1.txt | |
+++ b/tests/tc027/expected1.txt | |
@@ -1,9 +1,8 @@ | |
identifiers | |
-C h | |
-alignof k | |
-i v | |
-init k | |
-mangleof k | |
-sizeof k | |
-stringof k | |
-tupleof k | |
+alignof k | |
+i v int i stdin 21 int | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
diff --git a/tests/tc027/run.sh b/tests/tc027/run.sh | |
index 2f0f9e4..876777b 100755 | |
--- a/tests/tc027/run.sh | |
+++ b/tests/tc027/run.sh | |
@@ -1,5 +1,5 @@ | |
set -e | |
set -u | |
-../../bin/dcd-client $1 file.d -c66 > actual1.txt | |
+../../bin/dcd-client $1 file.d --extended -c66 > actual1.txt | |
diff actual1.txt expected1.txt --strip-trailing-cr | |
diff --git a/tests/tc_extended_types/expected1.txt b/tests/tc_extended_types/expected1.txt | |
index fd102a5..0b5ff23 100644 | |
--- a/tests/tc_extended_types/expected1.txt | |
+++ b/tests/tc_extended_types/expected1.txt | |
@@ -1,2 +1,2 @@ | |
identifiers | |
-bar v foo bar stdin 92 | |
+bar v stdin 92 | |
diff --git a/tests/tc_templates_resolve/complex.d b/tests/tc_templates_resolve/complex.d | |
new file mode 100644 | |
index 0000000..9f1cb03 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/complex.d | |
@@ -0,0 +1,94 @@ | |
+struct Data | |
+{ | |
+ int inside_data; | |
+ Inner inner; | |
+} | |
+ | |
+struct Inner | |
+{ | |
+ int inside_inner; | |
+} | |
+ | |
+struct AganeOne(T) | |
+{ | |
+ int inside_aganeone; | |
+ T yo; | |
+} | |
+ | |
+struct AganeTwo(T, U) | |
+{ | |
+ int inside_aganetwo; | |
+ T yo_T; | |
+ U yo_U; | |
+} | |
+ | |
+struct Other(T) | |
+{ | |
+ int inside_other; | |
+ T what; | |
+ AganeOne!(T) agane_T; | |
+ AganeOne!(Inner) agane_inner; | |
+} | |
+ | |
+struct One(T){ T inside_one; } | |
+ | |
+struct Outter { | |
+ struct Two(T, U){ int inside_two; T agane_one; U agane_two; One!(T) one_agane_one; T get_T(T)(){return T.init;} U get_U(){return U.init;} } | |
+} | |
+ | |
+struct A{ int inside_a;} | |
+struct B{ int inside_b;} | |
+struct C{ int inside_c;} | |
+ | |
+struct What | |
+{ | |
+ int inside_what; | |
+ const(V) get_it(T, U, V)() { return T.init; } | |
+} | |
+ | |
+void main() | |
+{ | |
+ auto from_auto = Outter.Two!( | |
+ AganeOne!(Other!(Data)), | |
+ AganeTwo!(A, B) | |
+ )(); | |
+ | |
+ Outter.Two!( | |
+ AganeOne!(Other!(Data)), | |
+ AganeTwo!(A, Other!(B)) | |
+ ) from_normal; | |
+ | |
+ auto u = from_auto.get_U(); | |
+ auto uuu = from_normal.agane_two; | |
+ | |
+ auto v = from_normal.get_U(); | |
+ | |
+ What what; | |
+ auto it = what.get_it!(A, B, C)(); | |
+ | |
+ { | |
+ from_auto.agane_one. | |
+ } | |
+ { | |
+ from_auto.agane_two. | |
+ } | |
+ { | |
+ from_normal.agane_two. | |
+ } | |
+ { | |
+ from_normal.agane_two. | |
+ } | |
+ { | |
+ u. | |
+ } | |
+ { | |
+ uuu. | |
+ } | |
+ { | |
+ uuu. | |
+ } | |
+ { | |
+ it. | |
+ } | |
+ | |
+} | |
\ No newline at end of file | |
diff --git a/tests/tc_templates_resolve/expected_1_1.txt b/tests/tc_templates_resolve/expected_1_1.txt | |
new file mode 100644 | |
index 0000000..7a7b156 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_1_1.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+one_t v One one_t stdin 103 One | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_t v A value_t stdin 0 A | |
diff --git a/tests/tc_templates_resolve/expected_1_2.txt b/tests/tc_templates_resolve/expected_1_2.txt | |
new file mode 100644 | |
index 0000000..7485291 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_1_2.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_t v A value_t stdin 0 A | |
+value_u v B value_u stdin 0 B | |
diff --git a/tests/tc_templates_resolve/expected_2_1.txt b/tests/tc_templates_resolve/expected_2_1.txt | |
new file mode 100644 | |
index 0000000..7a7b156 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_2_1.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+one_t v One one_t stdin 103 One | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_t v A value_t stdin 0 A | |
diff --git a/tests/tc_templates_resolve/expected_2_2.txt b/tests/tc_templates_resolve/expected_2_2.txt | |
new file mode 100644 | |
index 0000000..7485291 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_2_2.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_t v A value_t stdin 0 A | |
+value_u v B value_u stdin 0 B | |
diff --git a/tests/tc_templates_resolve/expected_3_1.txt b/tests/tc_templates_resolve/expected_3_1.txt | |
new file mode 100644 | |
index 0000000..3172011 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_3_1.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_key v int value_key stdin 0 int | |
+value_value v int value_value stdin 0 int | |
diff --git a/tests/tc_templates_resolve/expected_3_2.txt b/tests/tc_templates_resolve/expected_3_2.txt | |
new file mode 100644 | |
index 0000000..3172011 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_3_2.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_key v int value_key stdin 0 int | |
+value_value v int value_value stdin 0 int | |
diff --git a/tests/tc_templates_resolve/expected_3_3.txt b/tests/tc_templates_resolve/expected_3_3.txt | |
new file mode 100644 | |
index 0000000..3172011 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_3_3.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_key v int value_key stdin 0 int | |
+value_value v int value_value stdin 0 int | |
diff --git a/tests/tc_templates_resolve/expected_3_4.txt b/tests/tc_templates_resolve/expected_3_4.txt | |
new file mode 100644 | |
index 0000000..3172011 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_3_4.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+value_key v int value_key stdin 0 int | |
+value_value v int value_value stdin 0 int | |
diff --git a/tests/tc_templates_resolve/expected_3_5.txt b/tests/tc_templates_resolve/expected_3_5.txt | |
new file mode 100644 | |
index 0000000..9e9e562 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_3_5.txt | |
@@ -0,0 +1,8 @@ | |
+identifiers | |
+alignof k | |
+init k int | |
+mangleof k | |
+max k int | |
+min k int | |
+sizeof k | |
+stringof k | |
diff --git a/tests/tc_templates_resolve/expected_complex_1.txt b/tests/tc_templates_resolve/expected_complex_1.txt | |
new file mode 100644 | |
index 0000000..e2285c4 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_1.txt | |
@@ -0,0 +1,9 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganeone v int inside_aganeone stdin 124 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo v Other yo stdin 0 Other | |
diff --git a/tests/tc_templates_resolve/expected_complex_2.txt b/tests/tc_templates_resolve/expected_complex_2.txt | |
new file mode 100644 | |
index 0000000..4e6e8b6 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_2.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v B yo_U stdin 0 B | |
diff --git a/tests/tc_templates_resolve/expected_complex_3.txt b/tests/tc_templates_resolve/expected_complex_3.txt | |
new file mode 100644 | |
index 0000000..cafd0e5 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_3.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v Other yo_U stdin 0 Other | |
diff --git a/tests/tc_templates_resolve/expected_complex_4.txt b/tests/tc_templates_resolve/expected_complex_4.txt | |
new file mode 100644 | |
index 0000000..cafd0e5 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_4.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v Other yo_U stdin 0 Other | |
diff --git a/tests/tc_templates_resolve/expected_complex_5.txt b/tests/tc_templates_resolve/expected_complex_5.txt | |
new file mode 100644 | |
index 0000000..4e6e8b6 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_5.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v B yo_U stdin 0 B | |
diff --git a/tests/tc_templates_resolve/expected_complex_6.txt b/tests/tc_templates_resolve/expected_complex_6.txt | |
new file mode 100644 | |
index 0000000..cafd0e5 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_6.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v Other yo_U stdin 0 Other | |
diff --git a/tests/tc_templates_resolve/expected_complex_7.txt b/tests/tc_templates_resolve/expected_complex_7.txt | |
new file mode 100644 | |
index 0000000..cafd0e5 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_7.txt | |
@@ -0,0 +1,10 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_aganetwo v int inside_aganetwo stdin 186 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
+yo_T v A yo_T stdin 0 A | |
+yo_U v Other yo_U stdin 0 Other | |
diff --git a/tests/tc_templates_resolve/expected_complex_8.txt b/tests/tc_templates_resolve/expected_complex_8.txt | |
new file mode 100644 | |
index 0000000..eda0ac9 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_complex_8.txt | |
@@ -0,0 +1,8 @@ | |
+identifiers | |
+alignof k | |
+init k | |
+inside_c v int inside_c stdin 605 int | |
+mangleof k | |
+sizeof k | |
+stringof k | |
+tupleof k | |
diff --git a/tests/tc_templates_resolve/expected_extra_1.txt b/tests/tc_templates_resolve/expected_extra_1.txt | |
new file mode 100644 | |
index 0000000..3a23887 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/expected_extra_1.txt | |
@@ -0,0 +1,2 @@ | |
+identifiers | |
+read_test f void read_test() stdin 38 void | |
diff --git a/tests/tc_templates_resolve/file1.d b/tests/tc_templates_resolve/file1.d | |
new file mode 100644 | |
index 0000000..16fa8cf | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/file1.d | |
@@ -0,0 +1,31 @@ | |
+struct A | |
+{ | |
+ int inside_a; | |
+} | |
+struct B | |
+{ | |
+ int inside_b; | |
+} | |
+struct One(T) | |
+{ | |
+ T value_t; | |
+ One!T one_t; | |
+} | |
+ | |
+struct Two(T, U) | |
+{ | |
+ T value_t; | |
+ U value_u; | |
+} | |
+ | |
+void main() | |
+{ | |
+ auto from_auto_one = One!A(); | |
+ auto from_auto_two = Two!(A, B)(); | |
+ { | |
+ from_auto_one. | |
+ } | |
+ { | |
+ from_auto_two. | |
+ } | |
+} | |
diff --git a/tests/tc_templates_resolve/file2.d b/tests/tc_templates_resolve/file2.d | |
new file mode 100644 | |
index 0000000..25e561b | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/file2.d | |
@@ -0,0 +1,31 @@ | |
+struct A | |
+{ | |
+ int inside_a; | |
+} | |
+struct B | |
+{ | |
+ int inside_b; | |
+} | |
+struct One(T) | |
+{ | |
+ T value_t; | |
+ One!T one_t; | |
+} | |
+ | |
+struct Two(T, U) | |
+{ | |
+ T value_t; | |
+ U value_u; | |
+} | |
+ | |
+void main() | |
+{ | |
+ One!A from_normal_one; | |
+ Two!(A, B) from_normal_two; | |
+ { | |
+ from_normal_one. | |
+ } | |
+ { | |
+ from_normal_two. | |
+ } | |
+} | |
diff --git a/tests/tc_templates_resolve/file3.d b/tests/tc_templates_resolve/file3.d | |
new file mode 100644 | |
index 0000000..946c176 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/file3.d | |
@@ -0,0 +1,49 @@ | |
+struct TopHashMap(Key, Value) | |
+{ | |
+ Key value_key; | |
+ Value value_value; | |
+} | |
+ | |
+void main() | |
+{ | |
+ auto top = TopHashMap!(int, int)(); | |
+ auto bottom = BottomHashMap!(int, int)(); | |
+ { | |
+ top. | |
+ } | |
+ { | |
+ auto copy = top; | |
+ copy. | |
+ } | |
+ { | |
+ bottom. | |
+ } | |
+ { | |
+ auto copy = bottom; | |
+ copy. | |
+ } | |
+ { | |
+ auto wf = WithFunction!(int, int)(); | |
+ auto gkey = wf.get_key(); | |
+ gkey. | |
+ } | |
+} | |
+ | |
+struct BottomHashMap(Key, Value) | |
+{ | |
+ Key value_key; | |
+ Value value_value; | |
+} | |
+ | |
+struct WithFunction(Key, Value) | |
+{ | |
+ Key get_key() | |
+ { | |
+ return Key.init; | |
+ } | |
+ | |
+ Value get_value() | |
+ { | |
+ return Value.init; | |
+ } | |
+} | |
diff --git a/tests/tc_templates_resolve/file4.d b/tests/tc_templates_resolve/file4.d | |
new file mode 100644 | |
index 0000000..2a9ab33 | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/file4.d | |
@@ -0,0 +1,12 @@ | |
+struct ReaderTest(bool LE) | |
+{ | |
+ void read_test(){} | |
+} | |
+alias ReaderTestBE = ReaderTest!true; | |
+struct Test | |
+{ | |
+ void read(ReaderTestBE* reader) | |
+ { | |
+ reader.re | |
+ } | |
+} | |
diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh | |
new file mode 100755 | |
index 0000000..afb5f9f | |
--- /dev/null | |
+++ b/tests/tc_templates_resolve/run.sh | |
@@ -0,0 +1,63 @@ | |
+#!/bin/bash | |
+ | |
+set -e | |
+set -u | |
+ | |
+MODE=$1 | |
+ | |
+function check () { | |
+ echo "$1 $2" | |
+ ../../bin/dcd-client $MODE $1.d --extended -c $2 > $3.txt | |
+ diff $3.txt $4.txt --strip-trailing-cr | |
+} | |
+ | |
+ | |
+#echo "extra" | |
+check file4 165 actual_extra_1 expected_extra_1 | |
+ | |
+ | |
+#echo "test1" | |
+check file1 280 actual_1_1 expected_1_1 | |
+ | |
+ | |
+#echo "test2" | |
+check file1 315 actual_1_2 expected_1_2 | |
+ | |
+ | |
+#echo "test3" | |
+check file2 268 actual_2_1 expected_2_1 | |
+ | |
+ | |
+#echo "test4" | |
+check file2 305 actual_2_2 expected_2_2 | |
+ | |
+ | |
+#echo "test5" | |
+check file3 195 actual_3_1 expected_3_1 | |
+ | |
+ | |
+#echo "test6" | |
+check file3 246 actual_3_2 expected_3_2 | |
+ | |
+ | |
+#echo "test7" | |
+check file3 274 actual_3_3 expected_3_3 | |
+ | |
+ | |
+#echo "test8" | |
+check file3 328 actual_3_4 expected_3_4 | |
+ | |
+ | |
+#echo "test9" | |
+check file3 433 actual_3_5 expected_3_5 | |
+ | |
+ | |
+#echo "test complex" | |
+check complex 1121 actual_complex_1 expected_complex_1 | |
+check complex 1162 actual_complex_2 expected_complex_2 | |
+check complex 1205 actual_complex_3 expected_complex_3 | |
+check complex 1248 actual_complex_4 expected_complex_4 | |
+check complex 1271 actual_complex_5 expected_complex_5 | |
+check complex 1296 actual_complex_6 expected_complex_6 | |
+check complex 1321 actual_complex_7 expected_complex_7 | |
+check complex 1345 actual_complex_8 expected_complex_8 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment