From ce363bccaebaceebd937a0f83c10533f2ad5811e Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 18:41:15 +0100 Subject: [PATCH 01/32] resolve templates --- dsymbol/src/dsymbol/conversion/first.d | 228 ++++++++++++++++++ dsymbol/src/dsymbol/conversion/second.d | 208 ++++++++++++++++ dsymbol/src/dsymbol/type_lookup.d | 15 ++ tests/tc027/expected1.txt | 15 +- tests/tc027/run.sh | 2 +- tests/tc_templates_resolve/complex.d | 94 ++++++++ tests/tc_templates_resolve/expected_1_1.txt | 9 + tests/tc_templates_resolve/expected_1_2.txt | 9 + tests/tc_templates_resolve/expected_2_1.txt | 9 + tests/tc_templates_resolve/expected_2_2.txt | 9 + .../expected_complex_1.txt | 9 + .../expected_complex_2.txt | 10 + .../expected_complex_3.txt | 10 + .../expected_complex_4.txt | 10 + .../expected_complex_5.txt | 10 + .../expected_complex_6.txt | 10 + .../expected_complex_7.txt | 10 + .../expected_complex_8.txt | 8 + tests/tc_templates_resolve/file1.d | 31 +++ tests/tc_templates_resolve/file2.d | 31 +++ tests/tc_templates_resolve/run.sh | 49 ++++ 21 files changed, 777 insertions(+), 9 deletions(-) create mode 100644 tests/tc_templates_resolve/complex.d create mode 100644 tests/tc_templates_resolve/expected_1_1.txt create mode 100644 tests/tc_templates_resolve/expected_1_2.txt create mode 100644 tests/tc_templates_resolve/expected_2_1.txt create mode 100644 tests/tc_templates_resolve/expected_2_2.txt create mode 100644 tests/tc_templates_resolve/expected_complex_1.txt create mode 100644 tests/tc_templates_resolve/expected_complex_2.txt create mode 100644 tests/tc_templates_resolve/expected_complex_3.txt create mode 100644 tests/tc_templates_resolve/expected_complex_4.txt create mode 100644 tests/tc_templates_resolve/expected_complex_5.txt create mode 100644 tests/tc_templates_resolve/expected_complex_6.txt create mode 100644 tests/tc_templates_resolve/expected_complex_7.txt create mode 100644 tests/tc_templates_resolve/expected_complex_8.txt create mode 100644 tests/tc_templates_resolve/file1.d create mode 100644 tests/tc_templates_resolve/file2.d create mode 100644 tests/tc_templates_resolve/run.sh diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e488566..1d4e180 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -231,10 +231,168 @@ 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); + } + + void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs) + { + if (targs.templateArgumentList) + { + foreach(i, targ; targs.templateArgumentList.items) + { + if (targ.type is null) continue; + if (targ.type.type2 is null) continue; + + auto part = targ.type.type2.typeIdentifierPart; + if (part is null) continue; + + auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); + newArg.parent = current; + 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.parent = current; + 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); + } + + 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)); + } + } + + 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( @@ -255,6 +413,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) { @@ -277,6 +445,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 433cd66..cb059d6 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -55,6 +55,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) @@ -98,6 +114,198 @@ 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; + foreach(i, crumb; ti.args[count].chain) + { + auto argName = crumb; + if (i == 0) + { + + if (m) + if (key in m) + { + argName = m[key].name; + } + + 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] = 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) + newType.type = mapping[retType]; + } + } + + 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) + { + newPart.ownType = true; + newPart.type = mapping[part.type.name]; + } + else if (m && part.type.name in m) + { + newPart.ownType = true; + newPart.type = m[part.type.name]; + } + + 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) diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d index 2260e57..f7f79de 100644 --- a/dsymbol/src/dsymbol/type_lookup.d +++ b/dsymbol/src/dsymbol/type_lookup.d @@ -37,4 +37,19 @@ 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* parent; + } + TypeInstance* root; + int num; +} \ No newline at end of file diff --git a/tests/tc027/expected1.txt b/tests/tc027/expected1.txt index 3ce878f..0e9796e 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 +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_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..f6e1453 --- /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 +sizeof k +stringof k +tupleof k +value_t v A value_t stdin 0 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..bc6dc47 --- /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 +value_u v B value_u stdin 0 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..f6e1453 --- /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 +sizeof k +stringof k +tupleof k +value_t v A value_t stdin 0 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..bc6dc47 --- /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 +value_u v B value_u stdin 0 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..fc11a50 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo v Other yo stdin 0 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..62a1edf --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v B yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..62a1edf --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v B yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..a3a129c --- /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 +mangleof k +sizeof k +stringof k +tupleof k 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/run.sh b/tests/tc_templates_resolve/run.sh new file mode 100644 index 0000000..8bd9670 --- /dev/null +++ b/tests/tc_templates_resolve/run.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e +set -u + +MODE=$1 + + +# ../../bin/dcd-client $1 file1.d --extended -c 270 + +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 "test1" +../../bin/dcd-client $1 file1.d --extended -c 280 > actual_1_1.txt +diff actual_1_1.txt expected_1_1.txt --strip-trailing-cr + + +#echo "test2" +../../bin/dcd-client $1 file1.d --extended -c 315 > actual_1_2.txt +diff actual_1_2.txt expected_1_2.txt --strip-trailing-cr + + + +#echo "test3" +../../bin/dcd-client $1 file2.d --extended -c 268 > actual_2_1.txt +diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr + + +#echo "test4" +../../bin/dcd-client $1 file2.d --extended -c 305 > actual_2_2.txt +diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr + + + +#echo "test c omplex" +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 + From aa2dadc768a8667cdd165baace1d7ffccf55164c Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 18:46:07 +0100 Subject: [PATCH 02/32] fix test script permission --- tests/tc_templates_resolve/run.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tests/tc_templates_resolve/run.sh diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh old mode 100644 new mode 100755 From f8a3c5b111129e445aab6742d8d5264d6de2a383 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 21:51:54 +0100 Subject: [PATCH 03/32] make it work with builtin symbols --- dsymbol/src/dsymbol/conversion/first.d | 11 ++++++++++- dsymbol/src/dsymbol/conversion/second.d | 15 +++++++++++++-- tests/tc_templates_resolve/expected_3_1.txt | 9 +++++++++ tests/tc_templates_resolve/file3.d | 11 +++++++++++ tests/tc_templates_resolve/run.sh | 12 +++++++----- 5 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 tests/tc_templates_resolve/expected_3_1.txt create mode 100644 tests/tc_templates_resolve/file3.d diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 1d4e180..c5eb32f 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -260,7 +260,16 @@ final class FirstPass : ASTVisitor if (targ.type.type2 is null) continue; auto part = targ.type.type2.typeIdentifierPart; - if (part is null) continue; + 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.parent = current; + newArg.chain ~= builtInName; + current.args ~= newArg; + continue; + } auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); newArg.parent = current; diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index cb059d6..8a9c521 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -175,18 +175,29 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto key = part.name; DSymbol* first; + bool isBuiltin; foreach(i, crumb; ti.args[count].chain) { auto argName = crumb; if (i == 0) { - if (m) if (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) { @@ -203,7 +214,7 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto ca = ti.args[count]; if (ca.chain.length > 0) - mapping[key] = createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); + mapping[key] = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); } } } 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..6a19b1a --- /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 +value_value v int value_value stdin 0 diff --git a/tests/tc_templates_resolve/file3.d b/tests/tc_templates_resolve/file3.d new file mode 100644 index 0000000..4f2a26a --- /dev/null +++ b/tests/tc_templates_resolve/file3.d @@ -0,0 +1,11 @@ +struct HashMap(Key, Value) +{ + Key value_key; + Value value_value; +} + +void main() +{ + auto hmap = HashMap!(int, int)(); + hmap. +} \ No newline at end of file diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index 8bd9670..8810ffa 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -5,9 +5,6 @@ set -u MODE=$1 - -# ../../bin/dcd-client $1 file1.d --extended -c 270 - function check () { echo "$1 $2" ../../bin/dcd-client $MODE $1.d --extended -c $2 > $3.txt @@ -36,8 +33,13 @@ diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr +#echo "test5" +../../bin/dcd-client $1 file3.d --extended -c 144 > actual_3_1.txt +diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr -#echo "test c omplex" + + +#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 @@ -46,4 +48,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 - +check complex 1413 actual_complex_9 expected_complex_9 From 1f4cd702ba954a8d803c3c9b67b9e204e4526ce3 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 22:01:55 +0100 Subject: [PATCH 04/32] fix test script --- tests/tc_templates_resolve/run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index 8810ffa..b795233 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -48,4 +48,3 @@ 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 -check complex 1413 actual_complex_9 expected_complex_9 From 81da9f4c4bc8abf6bb2494a5ec36101a7459d692 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 22:18:01 +0100 Subject: [PATCH 05/32] fix test --- tests/tc_templates_resolve/run.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index b795233..709d9c2 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -34,11 +34,10 @@ diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr #echo "test5" -../../bin/dcd-client $1 file3.d --extended -c 144 > actual_3_1.txt +../../bin/dcd-client $1 file3.d --extended -c 135 > actual_3_1.txt diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr - #echo "test complex" check complex 1121 actual_complex_1 expected_complex_1 check complex 1162 actual_complex_2 expected_complex_2 From e7a83be721356da02f6de23dd2d4f46401f27560 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Fri, 17 Feb 2023 02:45:40 +0100 Subject: [PATCH 06/32] add more tests --- dsymbol/src/dsymbol/conversion/second.d | 16 ++++++- tests/tc_templates_resolve/expected_3_2.txt | 9 ++++ tests/tc_templates_resolve/expected_3_3.txt | 9 ++++ tests/tc_templates_resolve/expected_3_4.txt | 9 ++++ tests/tc_templates_resolve/expected_3_5.txt | 8 ++++ tests/tc_templates_resolve/file3.d | 46 +++++++++++++++++++-- tests/tc_templates_resolve/run.sh | 32 +++++++++----- 7 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 tests/tc_templates_resolve/expected_3_2.txt create mode 100644 tests/tc_templates_resolve/expected_3_3.txt create mode 100644 tests/tc_templates_resolve/expected_3_4.txt create mode 100644 tests/tc_templates_resolve/expected_3_5.txt diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 8a9c521..d3cd9d0 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -95,8 +95,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) - secondPass(child, moduleScope, cache); + if (child.acSymbol.kind != CompletionKind.variableName && child.acSymbol.kind != CompletionKind.functionName) + secondPass(child, moduleScope, cache); + + foreach (child; currentSymbol.children) + 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. 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..bfc6075 --- /dev/null +++ b/tests/tc_templates_resolve/expected_3_5.txt @@ -0,0 +1,8 @@ +identifiers +alignof k +init k +mangleof k +max k +min k +sizeof k +stringof k diff --git a/tests/tc_templates_resolve/file3.d b/tests/tc_templates_resolve/file3.d index 4f2a26a..946c176 100644 --- a/tests/tc_templates_resolve/file3.d +++ b/tests/tc_templates_resolve/file3.d @@ -1,4 +1,4 @@ -struct HashMap(Key, Value) +struct TopHashMap(Key, Value) { Key value_key; Value value_value; @@ -6,6 +6,44 @@ struct HashMap(Key, Value) void main() { - auto hmap = HashMap!(int, int)(); - hmap. -} \ No newline at end of file + 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/run.sh b/tests/tc_templates_resolve/run.sh index 709d9c2..15b4c03 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -13,29 +13,39 @@ function check () { #echo "test1" -../../bin/dcd-client $1 file1.d --extended -c 280 > actual_1_1.txt -diff actual_1_1.txt expected_1_1.txt --strip-trailing-cr +check file1 280 actual_1_1 expected_1_1 #echo "test2" -../../bin/dcd-client $1 file1.d --extended -c 315 > actual_1_2.txt -diff actual_1_2.txt expected_1_2.txt --strip-trailing-cr - +check file1 315 actual_1_2 expected_1_2 #echo "test3" -../../bin/dcd-client $1 file2.d --extended -c 268 > actual_2_1.txt -diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr +check file2 268 actual_2_1 expected_2_1 #echo "test4" -../../bin/dcd-client $1 file2.d --extended -c 305 > actual_2_2.txt -diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr +check file2 305 actual_2_2 expected_2_2 #echo "test5" -../../bin/dcd-client $1 file3.d --extended -c 135 > actual_3_1.txt -diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr +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" From dd27ab0799a2d845c11d1e072789f00d30631e13 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Fri, 17 Feb 2023 02:49:47 +0100 Subject: [PATCH 07/32] never own builtin symbols --- dsymbol/src/dsymbol/conversion/second.d | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index d3cd9d0..a20f655 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -245,7 +245,11 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC { auto retType = extractReturnType(callTip); if (retType in mapping) - newType.type = mapping[retType]; + { + auto result = mapping[retType]; + newType.ownType = result.kind == CompletionKind.keyword ? false : true; + newType.type = result; + } } } @@ -268,13 +272,15 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC if (part.type.name in mapping) { - newPart.ownType = true; - newPart.type = mapping[part.type.name]; + 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) { - newPart.ownType = true; - newPart.type = m[part.type.name]; + auto result = m[part.type.name]; + newPart.ownType = result.kind == CompletionKind.keyword ? false : true; + newPart.type = result; } newType.addChild(newPart, true); From 0ede218bc6ed04229187b0dd20676309dd991cf1 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 18:41:15 +0100 Subject: [PATCH 08/32] resolve templates --- dsymbol/src/dsymbol/conversion/first.d | 228 ++++++++++++++++++ dsymbol/src/dsymbol/conversion/second.d | 208 ++++++++++++++++ dsymbol/src/dsymbol/type_lookup.d | 15 ++ tests/tc027/expected1.txt | 15 +- tests/tc027/run.sh | 2 +- tests/tc_templates_resolve/complex.d | 94 ++++++++ tests/tc_templates_resolve/expected_1_1.txt | 9 + tests/tc_templates_resolve/expected_1_2.txt | 9 + tests/tc_templates_resolve/expected_2_1.txt | 9 + tests/tc_templates_resolve/expected_2_2.txt | 9 + .../expected_complex_1.txt | 9 + .../expected_complex_2.txt | 10 + .../expected_complex_3.txt | 10 + .../expected_complex_4.txt | 10 + .../expected_complex_5.txt | 10 + .../expected_complex_6.txt | 10 + .../expected_complex_7.txt | 10 + .../expected_complex_8.txt | 8 + tests/tc_templates_resolve/file1.d | 31 +++ tests/tc_templates_resolve/file2.d | 31 +++ tests/tc_templates_resolve/run.sh | 49 ++++ 21 files changed, 777 insertions(+), 9 deletions(-) create mode 100644 tests/tc_templates_resolve/complex.d create mode 100644 tests/tc_templates_resolve/expected_1_1.txt create mode 100644 tests/tc_templates_resolve/expected_1_2.txt create mode 100644 tests/tc_templates_resolve/expected_2_1.txt create mode 100644 tests/tc_templates_resolve/expected_2_2.txt create mode 100644 tests/tc_templates_resolve/expected_complex_1.txt create mode 100644 tests/tc_templates_resolve/expected_complex_2.txt create mode 100644 tests/tc_templates_resolve/expected_complex_3.txt create mode 100644 tests/tc_templates_resolve/expected_complex_4.txt create mode 100644 tests/tc_templates_resolve/expected_complex_5.txt create mode 100644 tests/tc_templates_resolve/expected_complex_6.txt create mode 100644 tests/tc_templates_resolve/expected_complex_7.txt create mode 100644 tests/tc_templates_resolve/expected_complex_8.txt create mode 100644 tests/tc_templates_resolve/file1.d create mode 100644 tests/tc_templates_resolve/file2.d create mode 100644 tests/tc_templates_resolve/run.sh diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index c9ac1b6..1064811 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -237,10 +237,168 @@ 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); + } + + void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs) + { + if (targs.templateArgumentList) + { + foreach(i, targ; targs.templateArgumentList.items) + { + if (targ.type is null) continue; + if (targ.type.type2 is null) continue; + + auto part = targ.type.type2.typeIdentifierPart; + if (part is null) continue; + + auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); + newArg.parent = current; + 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.parent = current; + 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); + } + + 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)); + } + } + + 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 +419,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 +451,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..eb7de5b 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) @@ -100,6 +116,198 @@ 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; + foreach(i, crumb; ti.args[count].chain) + { + auto argName = crumb; + if (i == 0) + { + + if (m) + if (key in m) + { + argName = m[key].name; + } + + 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] = 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) + newType.type = mapping[retType]; + } + } + + 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) + { + newPart.ownType = true; + newPart.type = mapping[part.type.name]; + } + else if (m && part.type.name in m) + { + newPart.ownType = true; + newPart.type = m[part.type.name]; + } + + 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) diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d index 2260e57..f7f79de 100644 --- a/dsymbol/src/dsymbol/type_lookup.d +++ b/dsymbol/src/dsymbol/type_lookup.d @@ -37,4 +37,19 @@ 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* parent; + } + TypeInstance* root; + int num; +} \ No newline at end of file diff --git a/tests/tc027/expected1.txt b/tests/tc027/expected1.txt index 3ce878f..0e9796e 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 +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_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..f6e1453 --- /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 +sizeof k +stringof k +tupleof k +value_t v A value_t stdin 0 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..bc6dc47 --- /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 +value_u v B value_u stdin 0 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..f6e1453 --- /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 +sizeof k +stringof k +tupleof k +value_t v A value_t stdin 0 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..bc6dc47 --- /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 +value_u v B value_u stdin 0 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..fc11a50 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo v Other yo stdin 0 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..62a1edf --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v B yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..62a1edf --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v B yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..fb085b8 --- /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 +mangleof k +sizeof k +stringof k +tupleof k +yo_T v A yo_T stdin 0 +yo_U v Other yo_U stdin 0 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..a3a129c --- /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 +mangleof k +sizeof k +stringof k +tupleof k 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/run.sh b/tests/tc_templates_resolve/run.sh new file mode 100644 index 0000000..8bd9670 --- /dev/null +++ b/tests/tc_templates_resolve/run.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e +set -u + +MODE=$1 + + +# ../../bin/dcd-client $1 file1.d --extended -c 270 + +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 "test1" +../../bin/dcd-client $1 file1.d --extended -c 280 > actual_1_1.txt +diff actual_1_1.txt expected_1_1.txt --strip-trailing-cr + + +#echo "test2" +../../bin/dcd-client $1 file1.d --extended -c 315 > actual_1_2.txt +diff actual_1_2.txt expected_1_2.txt --strip-trailing-cr + + + +#echo "test3" +../../bin/dcd-client $1 file2.d --extended -c 268 > actual_2_1.txt +diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr + + +#echo "test4" +../../bin/dcd-client $1 file2.d --extended -c 305 > actual_2_2.txt +diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr + + + +#echo "test c omplex" +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 + From 220cb954f96589bb350473bacdb3a2bb34030360 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 18:46:07 +0100 Subject: [PATCH 09/32] fix test script permission --- tests/tc_templates_resolve/run.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tests/tc_templates_resolve/run.sh diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh old mode 100644 new mode 100755 From 68d468ca06b448bc06b3da0e89b6f84ca65632e8 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 21:51:54 +0100 Subject: [PATCH 10/32] make it work with builtin symbols --- dsymbol/src/dsymbol/conversion/first.d | 11 ++++++++++- dsymbol/src/dsymbol/conversion/second.d | 15 +++++++++++++-- tests/tc_templates_resolve/expected_3_1.txt | 9 +++++++++ tests/tc_templates_resolve/file3.d | 11 +++++++++++ tests/tc_templates_resolve/run.sh | 12 +++++++----- 5 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 tests/tc_templates_resolve/expected_3_1.txt create mode 100644 tests/tc_templates_resolve/file3.d diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 1064811..78b3189 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -266,7 +266,16 @@ final class FirstPass : ASTVisitor if (targ.type.type2 is null) continue; auto part = targ.type.type2.typeIdentifierPart; - if (part is null) continue; + 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.parent = current; + newArg.chain ~= builtInName; + current.args ~= newArg; + continue; + } auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); newArg.parent = current; diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index eb7de5b..73fa012 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -177,18 +177,29 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto key = part.name; DSymbol* first; + bool isBuiltin; foreach(i, crumb; ti.args[count].chain) { auto argName = crumb; if (i == 0) { - if (m) if (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) { @@ -205,7 +216,7 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto ca = ti.args[count]; if (ca.chain.length > 0) - mapping[key] = createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); + mapping[key] = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); } } } 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..6a19b1a --- /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 +value_value v int value_value stdin 0 diff --git a/tests/tc_templates_resolve/file3.d b/tests/tc_templates_resolve/file3.d new file mode 100644 index 0000000..4f2a26a --- /dev/null +++ b/tests/tc_templates_resolve/file3.d @@ -0,0 +1,11 @@ +struct HashMap(Key, Value) +{ + Key value_key; + Value value_value; +} + +void main() +{ + auto hmap = HashMap!(int, int)(); + hmap. +} \ No newline at end of file diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index 8bd9670..8810ffa 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -5,9 +5,6 @@ set -u MODE=$1 - -# ../../bin/dcd-client $1 file1.d --extended -c 270 - function check () { echo "$1 $2" ../../bin/dcd-client $MODE $1.d --extended -c $2 > $3.txt @@ -36,8 +33,13 @@ diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr +#echo "test5" +../../bin/dcd-client $1 file3.d --extended -c 144 > actual_3_1.txt +diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr -#echo "test c omplex" + + +#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 @@ -46,4 +48,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 - +check complex 1413 actual_complex_9 expected_complex_9 From 00d399faebc48b907fd4170bb7079ae575f2ebde Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 22:01:55 +0100 Subject: [PATCH 11/32] fix test script --- tests/tc_templates_resolve/run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index 8810ffa..b795233 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -48,4 +48,3 @@ 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 -check complex 1413 actual_complex_9 expected_complex_9 From d055ed69a4449f8964810f63abb7a827c4bcf237 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Tue, 14 Feb 2023 22:18:01 +0100 Subject: [PATCH 12/32] fix test --- tests/tc_templates_resolve/run.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index b795233..709d9c2 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -34,11 +34,10 @@ diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr #echo "test5" -../../bin/dcd-client $1 file3.d --extended -c 144 > actual_3_1.txt +../../bin/dcd-client $1 file3.d --extended -c 135 > actual_3_1.txt diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr - #echo "test complex" check complex 1121 actual_complex_1 expected_complex_1 check complex 1162 actual_complex_2 expected_complex_2 From 48c89d7fc120e0bf02984d4b18d024d5547eab95 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Fri, 17 Feb 2023 02:45:40 +0100 Subject: [PATCH 13/32] add more tests --- dsymbol/src/dsymbol/conversion/second.d | 16 ++++++- tests/tc_templates_resolve/expected_3_2.txt | 9 ++++ tests/tc_templates_resolve/expected_3_3.txt | 9 ++++ tests/tc_templates_resolve/expected_3_4.txt | 9 ++++ tests/tc_templates_resolve/expected_3_5.txt | 8 ++++ tests/tc_templates_resolve/file3.d | 46 +++++++++++++++++++-- tests/tc_templates_resolve/run.sh | 32 +++++++++----- 7 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 tests/tc_templates_resolve/expected_3_2.txt create mode 100644 tests/tc_templates_resolve/expected_3_3.txt create mode 100644 tests/tc_templates_resolve/expected_3_4.txt create mode 100644 tests/tc_templates_resolve/expected_3_5.txt diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 73fa012..2136202 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -97,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) - secondPass(child, moduleScope, cache); + if (child.acSymbol.kind != CompletionKind.variableName && child.acSymbol.kind != CompletionKind.functionName) + secondPass(child, moduleScope, cache); + + foreach (child; currentSymbol.children) + 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. 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..6a19b1a --- /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 +value_value v int value_value stdin 0 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..bfc6075 --- /dev/null +++ b/tests/tc_templates_resolve/expected_3_5.txt @@ -0,0 +1,8 @@ +identifiers +alignof k +init k +mangleof k +max k +min k +sizeof k +stringof k diff --git a/tests/tc_templates_resolve/file3.d b/tests/tc_templates_resolve/file3.d index 4f2a26a..946c176 100644 --- a/tests/tc_templates_resolve/file3.d +++ b/tests/tc_templates_resolve/file3.d @@ -1,4 +1,4 @@ -struct HashMap(Key, Value) +struct TopHashMap(Key, Value) { Key value_key; Value value_value; @@ -6,6 +6,44 @@ struct HashMap(Key, Value) void main() { - auto hmap = HashMap!(int, int)(); - hmap. -} \ No newline at end of file + 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/run.sh b/tests/tc_templates_resolve/run.sh index 709d9c2..15b4c03 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -13,29 +13,39 @@ function check () { #echo "test1" -../../bin/dcd-client $1 file1.d --extended -c 280 > actual_1_1.txt -diff actual_1_1.txt expected_1_1.txt --strip-trailing-cr +check file1 280 actual_1_1 expected_1_1 #echo "test2" -../../bin/dcd-client $1 file1.d --extended -c 315 > actual_1_2.txt -diff actual_1_2.txt expected_1_2.txt --strip-trailing-cr - +check file1 315 actual_1_2 expected_1_2 #echo "test3" -../../bin/dcd-client $1 file2.d --extended -c 268 > actual_2_1.txt -diff actual_2_1.txt expected_2_1.txt --strip-trailing-cr +check file2 268 actual_2_1 expected_2_1 #echo "test4" -../../bin/dcd-client $1 file2.d --extended -c 305 > actual_2_2.txt -diff actual_2_2.txt expected_2_2.txt --strip-trailing-cr +check file2 305 actual_2_2 expected_2_2 #echo "test5" -../../bin/dcd-client $1 file3.d --extended -c 135 > actual_3_1.txt -diff actual_3_1.txt expected_3_1.txt --strip-trailing-cr +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" From 8098d80435197c7687895296b9a985fb33a83f6c Mon Sep 17 00:00:00 2001 From: ryuukk Date: Fri, 17 Feb 2023 02:49:47 +0100 Subject: [PATCH 14/32] never own builtin symbols --- dsymbol/src/dsymbol/conversion/second.d | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 2136202..0b615c1 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -247,7 +247,11 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC { auto retType = extractReturnType(callTip); if (retType in mapping) - newType.type = mapping[retType]; + { + auto result = mapping[retType]; + newType.ownType = result.kind == CompletionKind.keyword ? false : true; + newType.type = result; + } } } @@ -270,13 +274,15 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC if (part.type.name in mapping) { - newPart.ownType = true; - newPart.type = mapping[part.type.name]; + 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) { - newPart.ownType = true; - newPart.type = m[part.type.name]; + auto result = m[part.type.name]; + newPart.ownType = result.kind == CompletionKind.keyword ? false : true; + newPart.type = result; } newType.addChild(newPart, true); From e5bade2878e26ced075d2f9500f87115e44b0acf Mon Sep 17 00:00:00 2001 From: ryuukk Date: Wed, 9 Aug 2023 18:11:56 +0200 Subject: [PATCH 15/32] Apply changes from latest libdparse version --- dsymbol/src/dsymbol/conversion/first.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 78b3189..af012fc 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -258,9 +258,9 @@ final class FirstPass : ASTVisitor void processTemplateArguments(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, VariableContext.TypeInstance* current, TemplateArguments targs) { - if (targs.templateArgumentList) + if (targs.namedTemplateArgumentList) { - foreach(i, targ; targs.templateArgumentList.items) + foreach(i, targ; targs.namedTemplateArgumentList.items) { if (targ.type is null) continue; if (targ.type.type2 is null) continue; From 5e809b1d4ab8f3bd2f91ea37ed46a5e12594c835 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Wed, 9 Aug 2023 18:34:19 +0200 Subject: [PATCH 16/32] Try latest version of libdparse --- dub.json | 4 ++-- libdparse | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dub.json b/dub.json index f5bade8..1662bfe 100644 --- a/dub.json +++ b/dub.json @@ -8,11 +8,11 @@ "license": "GPL-3.0", "dependencies": { ":dsymbol": "*", - "libdparse": ">=0.23.0 <0.24.0", + ":libdparse": "*", ":common": "*", "emsi_containers": "~>0.9.0" }, - "subPackages": ["dsymbol", "common"], + "subPackages": ["dsymbol", "common", "libdparse"], "versions": ["built_with_dub"], "configurations": [ { diff --git a/libdparse b/libdparse index 86c9bf4..1065837 160000 --- a/libdparse +++ b/libdparse @@ -1 +1 @@ -Subproject commit 86c9bf44c96e1666eb175c749cc26f62c2008979 +Subproject commit 10658375b22f284e2fcb44074a862c213309cfb3 From 7cbe5289f76c6472390a9a44b4775b63682346ac Mon Sep 17 00:00:00 2001 From: ryuukk Date: Wed, 9 Aug 2023 18:51:26 +0200 Subject: [PATCH 17/32] Apply some code review suggestions --- dsymbol/src/dsymbol/conversion/first.d | 11 +++++++---- dsymbol/src/dsymbol/conversion/second.d | 3 +-- dsymbol/src/dsymbol/type_lookup.d | 2 -- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index af012fc..ba3ec6e 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -254,6 +254,8 @@ final class FirstPass : ASTVisitor 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) @@ -262,6 +264,7 @@ final class FirstPass : ASTVisitor { foreach(i, targ; targs.namedTemplateArgumentList.items) { + // TODO: handle targ.assignExpression if (targ.type is null) continue; if (targ.type.type2 is null) continue; @@ -271,14 +274,12 @@ final class FirstPass : ASTVisitor if (targ.type.type2.builtinType == tok!"") continue; auto builtInName = getBuiltinTypeName(targ.type.type2.builtinType); auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); - newArg.parent = current; newArg.chain ~= builtInName; current.args ~= newArg; continue; } auto newArg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); - newArg.parent = current; current.args ~= newArg; if (part.identifierOrTemplateInstance) @@ -296,7 +297,6 @@ final class FirstPass : ASTVisitor { auto singleArg = targs.templateSingleArgument; auto arg = GCAllocator.instance.make!(VariableContext.TypeInstance)(); - arg.parent = current; arg.name = singleArg.token.text; arg.chain ~= arg.name; current.args ~= arg; @@ -318,6 +318,7 @@ final class FirstPass : ASTVisitor 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) @@ -330,10 +331,12 @@ final class FirstPass : ASTVisitor { if (iot.templateInstance.identifier != tok!"") lookup.breadcrumbs.insert(istring(iot.templateInstance.identifier.text)); + + // TODO: handle `iot.templateInstance.templateArguments` } } - void traverseUnaryExpression( SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue) + void traverseUnaryExpression(SemanticSymbol* symbol, TypeLookup* lookup, VariableContext* ctx, UnaryExpression ue) { if (PrimaryExpression pe = ue.primaryExpression) { diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 0b615c1..96c2f2b 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -197,8 +197,7 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto argName = crumb; if (i == 0) { - if (m) - if (key in m) + if (m && key in m) { argName = m[key].name; } diff --git a/dsymbol/src/dsymbol/type_lookup.d b/dsymbol/src/dsymbol/type_lookup.d index f7f79de..c417c53 100644 --- a/dsymbol/src/dsymbol/type_lookup.d +++ b/dsymbol/src/dsymbol/type_lookup.d @@ -48,8 +48,6 @@ struct VariableContext string[] chain; TypeInstance*[] args; string name; - TypeInstance* parent; } TypeInstance* root; - int num; } \ No newline at end of file From 8833f42ea1c0997c8a826cfb67a35739f2d69dd1 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Wed, 9 Aug 2023 19:01:01 +0200 Subject: [PATCH 18/32] Make dub to use latest libdparse revision --- dub.json | 4 ++-- dub.selections.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dub.json b/dub.json index 1662bfe..7571586 100644 --- a/dub.json +++ b/dub.json @@ -8,11 +8,11 @@ "license": "GPL-3.0", "dependencies": { ":dsymbol": "*", - ":libdparse": "*", + "libdparse": ">=0.23.2 <0.24.0", ":common": "*", "emsi_containers": "~>0.9.0" }, - "subPackages": ["dsymbol", "common", "libdparse"], + "subPackages": ["dsymbol", "common"], "versions": ["built_with_dub"], "configurations": [ { 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" } From d4d8f40cda0c71b36f52565ca81f04c437e2faac Mon Sep 17 00:00:00 2001 From: ryuukk Date: Fri, 11 Aug 2023 23:26:27 +0200 Subject: [PATCH 19/32] Update tests 'expected' files --- tests/tc_templates_resolve/expected_1_1.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_1_2.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_2_1.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_2_2.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_3_1.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_3_2.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_3_3.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_3_4.txt | 16 ++++++++-------- tests/tc_templates_resolve/expected_3_5.txt | 14 +++++++------- .../expected_complex_1.txt | 16 ++++++++-------- .../expected_complex_2.txt | 18 +++++++++--------- .../expected_complex_3.txt | 18 +++++++++--------- .../expected_complex_4.txt | 18 +++++++++--------- .../expected_complex_5.txt | 18 +++++++++--------- .../expected_complex_6.txt | 18 +++++++++--------- .../expected_complex_7.txt | 18 +++++++++--------- .../expected_complex_8.txt | 14 +++++++------- 17 files changed, 140 insertions(+), 140 deletions(-) diff --git a/tests/tc_templates_resolve/expected_1_1.txt b/tests/tc_templates_resolve/expected_1_1.txt index f6e1453..7a7b156 100644 --- a/tests/tc_templates_resolve/expected_1_1.txt +++ b/tests/tc_templates_resolve/expected_1_1.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -one_t v One one_t stdin 103 -sizeof k -stringof k -tupleof k -value_t v A value_t stdin 0 +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 index bc6dc47..7485291 100644 --- a/tests/tc_templates_resolve/expected_1_2.txt +++ b/tests/tc_templates_resolve/expected_1_2.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_t v A value_t stdin 0 -value_u v B value_u stdin 0 +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 index f6e1453..7a7b156 100644 --- a/tests/tc_templates_resolve/expected_2_1.txt +++ b/tests/tc_templates_resolve/expected_2_1.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -one_t v One one_t stdin 103 -sizeof k -stringof k -tupleof k -value_t v A value_t stdin 0 +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 index bc6dc47..7485291 100644 --- a/tests/tc_templates_resolve/expected_2_2.txt +++ b/tests/tc_templates_resolve/expected_2_2.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_t v A value_t stdin 0 -value_u v B value_u stdin 0 +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 index 6a19b1a..3172011 100644 --- a/tests/tc_templates_resolve/expected_3_1.txt +++ b/tests/tc_templates_resolve/expected_3_1.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_key v int value_key stdin 0 -value_value v int value_value stdin 0 +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 index 6a19b1a..3172011 100644 --- a/tests/tc_templates_resolve/expected_3_2.txt +++ b/tests/tc_templates_resolve/expected_3_2.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_key v int value_key stdin 0 -value_value v int value_value stdin 0 +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 index 6a19b1a..3172011 100644 --- a/tests/tc_templates_resolve/expected_3_3.txt +++ b/tests/tc_templates_resolve/expected_3_3.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_key v int value_key stdin 0 -value_value v int value_value stdin 0 +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 index 6a19b1a..3172011 100644 --- a/tests/tc_templates_resolve/expected_3_4.txt +++ b/tests/tc_templates_resolve/expected_3_4.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -mangleof k -sizeof k -stringof k -tupleof k -value_key v int value_key stdin 0 -value_value v int value_value stdin 0 +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 index bfc6075..9e9e562 100644 --- a/tests/tc_templates_resolve/expected_3_5.txt +++ b/tests/tc_templates_resolve/expected_3_5.txt @@ -1,8 +1,8 @@ identifiers -alignof k -init k -mangleof k -max k -min k -sizeof k -stringof k +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 index fc11a50..e2285c4 100644 --- a/tests/tc_templates_resolve/expected_complex_1.txt +++ b/tests/tc_templates_resolve/expected_complex_1.txt @@ -1,9 +1,9 @@ identifiers -alignof k -init k -inside_aganeone v int inside_aganeone stdin 124 -mangleof k -sizeof k -stringof k -tupleof k -yo v Other yo stdin 0 +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 index 62a1edf..4e6e8b6 100644 --- a/tests/tc_templates_resolve/expected_complex_2.txt +++ b/tests/tc_templates_resolve/expected_complex_2.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v B yo_U stdin 0 +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 index fb085b8..cafd0e5 100644 --- a/tests/tc_templates_resolve/expected_complex_3.txt +++ b/tests/tc_templates_resolve/expected_complex_3.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v Other yo_U stdin 0 +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 index fb085b8..cafd0e5 100644 --- a/tests/tc_templates_resolve/expected_complex_4.txt +++ b/tests/tc_templates_resolve/expected_complex_4.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v Other yo_U stdin 0 +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 index 62a1edf..4e6e8b6 100644 --- a/tests/tc_templates_resolve/expected_complex_5.txt +++ b/tests/tc_templates_resolve/expected_complex_5.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v B yo_U stdin 0 +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 index fb085b8..cafd0e5 100644 --- a/tests/tc_templates_resolve/expected_complex_6.txt +++ b/tests/tc_templates_resolve/expected_complex_6.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v Other yo_U stdin 0 +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 index fb085b8..cafd0e5 100644 --- a/tests/tc_templates_resolve/expected_complex_7.txt +++ b/tests/tc_templates_resolve/expected_complex_7.txt @@ -1,10 +1,10 @@ identifiers -alignof k -init k -inside_aganetwo v int inside_aganetwo stdin 186 -mangleof k -sizeof k -stringof k -tupleof k -yo_T v A yo_T stdin 0 -yo_U v Other yo_U stdin 0 +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 index a3a129c..eda0ac9 100644 --- a/tests/tc_templates_resolve/expected_complex_8.txt +++ b/tests/tc_templates_resolve/expected_complex_8.txt @@ -1,8 +1,8 @@ identifiers -alignof k -init k -inside_c v int inside_c stdin 605 -mangleof k -sizeof k -stringof k -tupleof k +alignof k +init k +inside_c v int inside_c stdin 605 int +mangleof k +sizeof k +stringof k +tupleof k From 9c08819a0fab8e26e4eb8b0428d3149eb9875381 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Sat, 12 Aug 2023 00:20:22 +0200 Subject: [PATCH 20/32] Make sure aliases are properly resolved --- dsymbol/src/dsymbol/conversion/second.d | 1 + tests/tc_templates_resolve/expected_extra_1.txt | 2 ++ tests/tc_templates_resolve/file4.d | 12 ++++++++++++ tests/tc_templates_resolve/run.sh | 4 ++++ 4 files changed, 19 insertions(+) create mode 100644 tests/tc_templates_resolve/expected_extra_1.txt create mode 100644 tests/tc_templates_resolve/file4.d diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 96c2f2b..394faa8 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -519,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/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/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 index 15b4c03..afb5f9f 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -12,6 +12,10 @@ function check () { } +#echo "extra" +check file4 165 actual_extra_1 expected_extra_1 + + #echo "test1" check file1 280 actual_1_1 expected_1_1 From c24981f9ba949a7ca399c3ce4bd807b5cd6cb340 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Sat, 12 Aug 2023 02:00:17 +0200 Subject: [PATCH 21/32] Fix test --- dsymbol/src/dsymbol/conversion/first.d | 14 +++++++++++++- tests/tc_extended_types/expected1.txt | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index ba3ec6e..196bd22 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -332,7 +332,19 @@ final class FirstPass : ASTVisitor if (iot.templateInstance.identifier != tok!"") lookup.breadcrumbs.insert(istring(iot.templateInstance.identifier.text)); - // TODO: handle `iot.templateInstance.templateArguments` + // 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)); + } + } } } 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 From 5d1cfb6db2a2ff081d31a4774eb9fd08c49f0834 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Sat, 12 Aug 2023 02:03:39 +0200 Subject: [PATCH 22/32] Update tc027 'expected' file --- tests/tc027/expected1.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/tc027/expected1.txt b/tests/tc027/expected1.txt index 0e9796e..d338689 100644 --- a/tests/tc027/expected1.txt +++ b/tests/tc027/expected1.txt @@ -1,8 +1,8 @@ identifiers -alignof k -i v int i stdin 21 -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 From 1be5d16f5e1c67ac79ac2af8056bd0b7dbbe965a Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 05:26:35 +0200 Subject: [PATCH 23/32] 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 From aa9865535a2f37fd6644cf774458a9e321584830 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 05:42:05 +0200 Subject: [PATCH 24/32] skip pointers --- dsymbol/src/dsymbol/conversion/second.d | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 7d5c1c4..93d3bf7 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -61,16 +61,20 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac 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); + foreach(lookup; currentSymbol.typeLookups[]) { + if (lookup.ctx.root) + { + auto type = currentSymbol.acSymbol.type; + if (type.kind == structName || type.kind == className || type.kind == functionName || type.kind) + { + 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; + } + } } } } @@ -327,12 +331,18 @@ void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, Va { depth += 1; - if (variableSym is null || type is null) return; + if (variableSym is null || type is null){ + writeln("fuck here"); + return; + } - if (current.chain.length == 0) return; // TODO: should not be empty, happens for simple stuff Inner inner; + if (current.chain.length == 0){ + writeln("why empty ", variableSym.name, " ", current.calltip); + 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); + writeln(">>", variableSym.name, " > ", newType.name); variableSym.type = newType; variableSym.ownType = true; } From 978c7a1bfa1837d777d3e9e393bb812ecebe2186 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 05:44:02 +0200 Subject: [PATCH 25/32] Remove debugging left over --- dsymbol/src/dsymbol/conversion/second.d | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 93d3bf7..497ee5c 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -331,15 +331,8 @@ void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, Va { depth += 1; - if (variableSym is null || type is null){ - writeln("fuck here"); - return; - } - - if (current.chain.length == 0){ - writeln("why empty ", variableSym.name, " ", current.calltip); - return; // TODO: should not be empty, happens for simple stuff Inner inner; - } + 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; TODO: i forgot why, add a test DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping); writeln(">>", variableSym.name, " > ", newType.name); From 05c8e4fcedb7df899508b1058d1d25f98c6d1487 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 06:58:47 +0200 Subject: [PATCH 26/32] Saving progress + debugging bits on purpose --- dsymbol/src/dsymbol/conversion/first.d | 24 ++++++++++++++++ dsymbol/src/dsymbol/conversion/second.d | 38 +++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 2d17949..e6b0b7c 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -253,7 +253,9 @@ final class FirstPass : ASTVisitor { processIdentifierOrTemplate(symbol, lookup, ctx, current, tip.identifierOrTemplateInstance); if (current) + { current.calltip = buildCalltip(tip.identifierOrTemplateInstance.tokens); + } } if (tip.typeIdentifierPart) @@ -297,6 +299,16 @@ final class FirstPass : ASTVisitor if (part.typeIdentifierPart.identifierOrTemplateInstance) processIdentifierOrTemplate(symbol, lookup, ctx, newArg, part.typeIdentifierPart.identifierOrTemplateInstance); } + + foreach(suffix; targ.type.typeSuffixes) + { + if (suffix.type) + current.calltip ~= "[.]"; + else if (suffix.array) + current.calltip ~= "[]"; + else if (suffix.star != tok!"") + current.calltip ~= "*"; + } } } else if (targs.templateSingleArgument) @@ -371,6 +383,8 @@ final class FirstPass : ASTVisitor calltip ~= "]"; else if (tk == tok!",") calltip ~= ","; + else if (tk == tok!"*") + calltip ~= "*"; else if (tk == tok!"") calltip ~= " "; else @@ -485,6 +499,16 @@ final class FirstPass : ASTVisitor if (typeIdentifierPart.identifierOrTemplateInstance) lookup.ctx.calltip = buildCalltip(typeIdentifierPart.identifierOrTemplateInstance.tokens); + foreach(suffix; dec.type.typeSuffixes) + { + if (suffix.type) + lookup.ctx.calltip ~= "[.]"; + else if (suffix.array) + lookup.ctx.calltip ~= "[]"; + else if (suffix.star != tok!"") + lookup.ctx.calltip ~= "*"; + } + 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 497ee5c..7086d14 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -62,6 +62,8 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac if (currentSymbol.acSymbol.type && currentSymbol.typeLookups.length > 0) { foreach(lookup; currentSymbol.typeLookups[]) { + + writeln("lookup: ", lookup.breadcrumbs[]); if (lookup.ctx.root) { auto type = currentSymbol.acSymbol.type; @@ -171,6 +173,14 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC assert(type); DSymbol* newType = GCAllocator.instance.make!DSymbol("dummy", CompletionKind.dummy, null); newType.name = ti ? istring(ti.calltip) : istring(lookup.ctx.calltip); + + // TODO: need to set the name in first.d + if (newType.name.length == 0) + newType.name = type.name; + + writeln(" >>", type.name, " > ", newType.name, " ::", ti ); + writeln(" >> args: ", ti.args); + newType.kind = type.kind; newType.qualifier = type.qualifier; newType.protection = type.protection; @@ -189,10 +199,12 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC scope(exit) count++; if (count >= ti.args.length) { - // warning("too many T for args available, investigate"); + writeln("too many T for args available, investigate"); continue; } auto key = part.name; + + writeln(" check: ", key); DSymbol* first; bool isBuiltin; foreach(i, crumb; ti.args[count].chain) @@ -219,20 +231,34 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto result = moduleScope.getSymbolsAtGlobalScope(istring(argName)); if (result.length == 0) { + writeln(" modulescope: symbol not found: ", argName); break; } first = result[0]; + writeln(" modulescope: symbol found: ", argName, " -> ", first.name); } else + { first = first.getFirstPartNamed(istring(argName)); + if (first) + writeln(" symbol found: ", argName, " -> ", first.name); + else + writeln(" symbol not found: ", argName); + } } if (first is null) continue; + writeln(">> ok"); auto ca = ti.args[count]; if (ca.chain.length > 0) - mapping[key] = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); + { + auto stomap = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); + mapping[key] = stomap; + + writeln(" mapping[",key,"] -> ", stomap.name); + } } } } @@ -336,6 +362,12 @@ void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, Va DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping); writeln(">>", variableSym.name, " > ", newType.name); + + if (depth == 1) + { + newType.name = istring(lookup.ctx.calltip); + } + variableSym.type = newType; variableSym.ownType = true; } @@ -517,7 +549,7 @@ do return; } - if (lastSuffix !is null) + if (lastSuffix !is null && lastSuffix.qualifier == SymbolQualifier.none) { assert(suffix !is null); typeSwap(currentSymbol); From 76bba560e0c38e578fec5c137b27d6f54a2d5df3 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 07:08:23 +0200 Subject: [PATCH 27/32] update dsymbol test --- dsymbol/src/dsymbol/tests.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsymbol/src/dsymbol/tests.d b/dsymbol/src/dsymbol/tests.d index 7527f19..fcb6311 100644 --- a/dsymbol/src/dsymbol/tests.d +++ b/dsymbol/src/dsymbol/tests.d @@ -199,7 +199,7 @@ unittest }; ScopeSymbolPair pair = generateAutocompleteTrees(source, cache); DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife")); - assert(meaningOfLife.type.name == "*arr*"); + assert(meaningOfLife.type.name == "int[]"); } From 0088c05a2ffc0bf129200072ebec659c3a82bf6d Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 18:49:22 +0200 Subject: [PATCH 28/32] Save progress --- dsymbol/src/dsymbol/conversion/first.d | 42 +++++++++++++++++++-- dsymbol/src/dsymbol/conversion/second.d | 36 ++++++++++++++++-- tests/tc_templates_resolve/expected_1_1.txt | 2 +- tests/tc_templates_resolve/expected_2_1.txt | 2 +- tests/tc_templates_resolve/file1.d | 2 +- tests/tc_templates_resolve/run.sh | 8 ++-- 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e6b0b7c..44ea31a 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -39,6 +39,7 @@ import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.logger; import std.meta : AliasSeq; import std.typecons : Rebindable; +import std.stdio; /** * First Pass handles the following: @@ -341,10 +342,6 @@ final class FirstPass : ASTVisitor 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!"") @@ -364,6 +361,11 @@ final class FirstPass : ASTVisitor } } } + else + { + auto crumb = iot.identifier; + lookup.breadcrumbs.insert(istring(crumb.text)); + } } string buildCalltip(const(Token)[] tokens) @@ -536,6 +538,12 @@ final class FirstPass : ASTVisitor auto lookup = symbol.typeLookups.front; + istring[] original; + foreach(c; lookup.breadcrumbs[]) + original ~= c; + writeln("## var: ", symbol.acSymbol.name); + writeln("## lookup breadcrumbs: ", lookup.breadcrumbs[]); + auto initializer = part.initializer.nonVoidInitializer; if (initializer && initializer.assignExpression) { @@ -567,6 +575,7 @@ final class FirstPass : ASTVisitor foreach(c; *crumbs) result ~= c; + writeln("## result: ", result); crumbs.clear(); foreach_reverse(c; result) lookup.breadcrumbs.insert(c); @@ -579,6 +588,19 @@ final class FirstPass : ASTVisitor lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)(); processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, iot.templateInstance); } + else + { + writeln("something else2; ", iot.identifier.text, " original: ", original); + + if (original.length > 0 && original[$-1] == "*arr*") + { + lookup.breadcrumbs.clear(); + foreach(c; original) + lookup.breadcrumbs.insert(c); + foreach_reverse(c; result) + lookup.breadcrumbs.insert(c); + } + } } else if (PrimaryExpression pe = unary.primaryExpression) { @@ -589,7 +611,19 @@ final class FirstPass : ASTVisitor lookup.ctx.root = GCAllocator.instance.make!(VariableContext.TypeInstance)(); processTemplateInstance(symbol, lookup, &lookup.ctx, lookup.ctx.root, pe.identifierOrTemplateInstance.templateInstance); } + else + { + writeln("something else2; ", pe.identifierOrTemplateInstance.identifier.text); + } } + else + { + writeln("something else other"); + } + } + else + { + writeln("something else final"); } } } diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 7086d14..7c946d3 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -63,9 +63,9 @@ void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCac { foreach(lookup; currentSymbol.typeLookups[]) { - writeln("lookup: ", lookup.breadcrumbs[]); + writeln("lookup: ", lookup.breadcrumbs[], " ctx: ", lookup.ctx.root); if (lookup.ctx.root) - { + { auto type = currentSymbol.acSymbol.type; if (type.kind == structName || type.kind == className || type.kind == functionName || type.kind) { @@ -179,6 +179,7 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC newType.name = type.name; writeln(" >>", type.name, " > ", newType.name, " ::", ti ); + writeln(" >> ct: ", ti.calltip); writeln(" >> args: ", ti.args); newType.kind = type.kind; @@ -593,6 +594,9 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, size_t i = 0; auto crumbs = lookup.breadcrumbs[]; + + writeln(">> crumbs: ", crumbs); + writeln(">> name: ", symbol.name); foreach (crumb; crumbs) { if (i == 0) @@ -601,7 +605,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, symbolNameToTypeName(crumb), symbol.location); if (currentSymbol is null) + { + writeln("return 0"); return; + } } else if (crumb == ARRAY_LITERAL_SYMBOL_NAME) { @@ -613,7 +620,10 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, { typeSwap(currentSymbol); if (currentSymbol is null) + { + writeln("return"); return; + } // Index expressions can be on a pointer, an array or an AA if (currentSymbol.qualifier == SymbolQualifier.array @@ -622,9 +632,15 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, || currentSymbol.kind == CompletionKind.aliasName) { if (currentSymbol.type !is null) + { + writeln("here! ", currentSymbol.type.name); currentSymbol = currentSymbol.type; + } else + { + writeln("nope!"); return; + } } else { @@ -632,7 +648,11 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, if (opIndex !is null) currentSymbol = opIndex.type; else - return; + { + writeln("return weird"); + writeln("s: ", currentSymbol.name, " ", currentSymbol.qualifier); + continue; + } } } else if (crumb == "foreach") @@ -661,18 +681,28 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, } else { + writeln("here"); typeSwap(currentSymbol); if (currentSymbol is null) + { + + writeln("return", i); return; + } currentSymbol = currentSymbol.getFirstPartNamed(crumb); } ++i; if (currentSymbol is null) + { + writeln("return end", i); return; + } } typeSwap(currentSymbol); symbol.type = currentSymbol; symbol.ownType = false; + + writeln(">> type: ", currentSymbol.name); } private: diff --git a/tests/tc_templates_resolve/expected_1_1.txt b/tests/tc_templates_resolve/expected_1_1.txt index 7a7b156..395d3c7 100644 --- a/tests/tc_templates_resolve/expected_1_1.txt +++ b/tests/tc_templates_resolve/expected_1_1.txt @@ -2,7 +2,7 @@ identifiers alignof k init k mangleof k -one_t v One one_t stdin 103 One +one_t v One!T one_t stdin 103 One!T sizeof k stringof k tupleof k diff --git a/tests/tc_templates_resolve/expected_2_1.txt b/tests/tc_templates_resolve/expected_2_1.txt index 7a7b156..395d3c7 100644 --- a/tests/tc_templates_resolve/expected_2_1.txt +++ b/tests/tc_templates_resolve/expected_2_1.txt @@ -2,7 +2,7 @@ identifiers alignof k init k mangleof k -one_t v One one_t stdin 103 One +one_t v One!T one_t stdin 103 One!T sizeof k stringof k tupleof k diff --git a/tests/tc_templates_resolve/file1.d b/tests/tc_templates_resolve/file1.d index 16fa8cf..35b7ce2 100644 --- a/tests/tc_templates_resolve/file1.d +++ b/tests/tc_templates_resolve/file1.d @@ -20,7 +20,7 @@ struct Two(T, U) void main() { - auto from_auto_one = One!A(); + auto from_auto_one = One!(A)(); auto from_auto_two = Two!(A, B)(); { from_auto_one. diff --git a/tests/tc_templates_resolve/run.sh b/tests/tc_templates_resolve/run.sh index afb5f9f..81c6ed8 100755 --- a/tests/tc_templates_resolve/run.sh +++ b/tests/tc_templates_resolve/run.sh @@ -6,8 +6,8 @@ set -u MODE=$1 function check () { - echo "$1 $2" - ../../bin/dcd-client $MODE $1.d --extended -c $2 > $3.txt + echo ":: :: check: $1 $2 $3" + ../../bin/dcd-client.exe $MODE $1.d --extended -c $2 > $3.txt diff $3.txt $4.txt --strip-trailing-cr } @@ -17,11 +17,11 @@ check file4 165 actual_extra_1 expected_extra_1 #echo "test1" -check file1 280 actual_1_1 expected_1_1 +check file1 282 actual_1_1 expected_1_1 #echo "test2" -check file1 315 actual_1_2 expected_1_2 +check file1 317 actual_1_2 expected_1_2 #echo "test3" From 64d647198b5d44c9172a2a7a20f983f9b7178af6 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 18:58:10 +0200 Subject: [PATCH 29/32] Save progress --- dsymbol/src/dsymbol/conversion/first.d | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 44ea31a..f9294e6 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -463,7 +463,8 @@ final class FirstPass : ASTVisitor if (IdentifierOrTemplateInstance iot = ue.identifierOrTemplateInstance) buildChainTemplateOrIdentifier(symbol, lookup, ctx, iot); - if(ue.unaryExpression) traverseUnaryExpression(symbol, lookup, ctx, ue.unaryExpression); + if(ue.unaryExpression) + traverseUnaryExpression(symbol, lookup, ctx, ue.unaryExpression); } override void visit(const VariableDeclaration dec) @@ -580,6 +581,8 @@ final class FirstPass : ASTVisitor foreach_reverse(c; result) lookup.breadcrumbs.insert(c); + again: + // check template if (IdentifierOrTemplateInstance iot = unary.identifierOrTemplateInstance) { @@ -624,6 +627,17 @@ final class FirstPass : ASTVisitor else { writeln("something else final"); + if (unary.unaryExpression) + { + unary = unary.unaryExpression; + goto again; + } + else + { + foreach(c; original) + lookup.breadcrumbs.insert(c); + } + } } } From 7a64de71a11b9d35edbaaecda2e5d48aa8882ce2 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Thu, 5 Oct 2023 20:58:08 +0200 Subject: [PATCH 30/32] Save progress --- dsymbol/src/dsymbol/conversion/second.d | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 7c946d3..ccd5619 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -550,7 +550,7 @@ do return; } - if (lastSuffix !is null && lastSuffix.qualifier == SymbolQualifier.none) + if (lastSuffix !is null) { assert(suffix !is null); typeSwap(currentSymbol); @@ -702,7 +702,8 @@ void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, symbol.type = currentSymbol; symbol.ownType = false; - writeln(">> type: ", currentSymbol.name); + if (currentSymbol) + writeln(">> type: ", currentSymbol.name); } private: @@ -827,4 +828,4 @@ void typeSwap(ref DSymbol* currentSymbol) || currentSymbol.kind == CompletionKind.withSymbol || currentSymbol.kind == CompletionKind.aliasName)) currentSymbol = currentSymbol.type; -} +} \ No newline at end of file From 0471759b6cc2e68f9b92edf93bfeda1a672b096f Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 9 Oct 2023 02:32:13 +0200 Subject: [PATCH 31/32] Add support for arrays --- dsymbol/src/dsymbol/conversion/second.d | 96 +++++++++++++++++++++---- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index ccd5619..950f26d 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -36,6 +36,7 @@ import dparse.lexer; import std.algorithm : filter; import std.range; import std.stdio; +import io = std.stdio; void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache) { @@ -178,9 +179,8 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC if (newType.name.length == 0) newType.name = type.name; - writeln(" >>", type.name, " > ", newType.name, " ::", ti ); - writeln(" >> ct: ", ti.calltip); - writeln(" >> args: ", ti.args); + print_tab(depth); io.write(">>", type.name, " > ", newType.name, " ::", ti," args: ", ti.args.length, " ct: ", ti.calltip); + writeln(); newType.kind = type.kind; newType.qualifier = type.qualifier; @@ -200,12 +200,19 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC scope(exit) count++; if (count >= ti.args.length) { - writeln("too many T for args available, investigate"); + print_tab(depth);writeln("too many T for args available, investigate"); continue; } auto key = part.name; - writeln(" check: ", key); + print_tab(depth);writeln("> check template arg: ", key); + print_tab(depth);io.write("chain: "); + foreach(i, crumb; ti.args[count].chain) + { + io.write(crumb, ", "); + } + writeln(""); + DSymbol* first; bool isBuiltin; foreach(i, crumb; ti.args[count].chain) @@ -232,35 +239,44 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC auto result = moduleScope.getSymbolsAtGlobalScope(istring(argName)); if (result.length == 0) { - writeln(" modulescope: symbol not found: ", argName); + print_tab(depth);writeln("modulescope: symbol not found: ", argName); break; } first = result[0]; - writeln(" modulescope: symbol found: ", argName, " -> ", first.name); + print_tab(depth);writeln("modulescope: symbol found: ", argName, " -> ", first.name); } else { first = first.getFirstPartNamed(istring(argName)); if (first) - writeln(" symbol found: ", argName, " -> ", first.name); + { + print_tab(depth);writeln("symbol found: ", argName, " -> ", first.name); + } else - writeln(" symbol not found: ", argName); + { + print_tab(depth);writeln("symbol not found: ", argName); + } } } if (first is null) continue; - writeln(">> ok"); + print_tab(depth);writeln(">> ok"); auto ca = ti.args[count]; if (ca.chain.length > 0) { - auto stomap = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, depth, null); + int indepth = depth + 1; + auto stomap = isBuiltin ? first : createTypeWithTemplateArgs(first, lookup, ca, cache, moduleScope, indepth, null); mapping[key] = stomap; - writeln(" mapping[",key,"] -> ", stomap.name); + print_tab(depth);writeln("mapping[",key,"] -> ", stomap.name, " builtin: ", isBuiltin); } } + else + { + //writeln(">>>>>>>>>>>>>>> what: ", part.kind," ", part.name); + } } } @@ -283,6 +299,8 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC } } + writeln(""); + assert(newType); string[] T_names; foreach(part; type.opSlice()) @@ -293,6 +311,8 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC } else if (part.type && part.type.kind == CompletionKind.typeTmpParam) { + + print_tab(depth); writeln("part: ", part.name,": ", part.type.name); DSymbol* newPart = GCAllocator.instance.make!DSymbol(part.name, part.kind, null); newPart.qualifier = part.qualifier; newPart.protection = part.protection; @@ -315,8 +335,25 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC newType.addChild(newPart, true); } + else if (part.type && part.type.name == "*arr*" && part.type.type && part.type.type.kind == CompletionKind.typeTmpParam) + { + auto arrSymbol = part.type; + auto arrTypeTSymbol = arrSymbol.type; + + print_tab(depth); writeln("array: ", part.name,": ", arrTypeTSymbol.name,"[]"); + + if (arrTypeTSymbol.name in mapping) + { + auto result = mapping[arrTypeTSymbol.name]; + arrSymbol.type = result; + print_tab(depth); writeln(" ", arrTypeTSymbol.name, " =>: ", result.name); + } + + newType.addChild(part, false); + } 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 @@ -336,8 +373,9 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC // 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); + // int indepth = depth; + // warning("go agane ", part.name, " ", part.type.name, " with arg: ", ti.chain," Ts: ", T_names); + // resolveTemplate(part, part.type, lookup, ti, moduleScope, cache, indepth, mapping); // break; // } // //else if (partPart.type && partPart.type.kind == CompletionKind.typeTmpParam) @@ -351,6 +389,12 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC return newType; } +void print_tab(int index) +{ + enum C = 4; + for(int i =0; i < index*4; i++) io.write(" "); +} + /** * Resolve template arguments */ @@ -361,8 +405,30 @@ void resolveTemplate(DSymbol* variableSym, DSymbol* type, TypeLookup* lookup, Va 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; TODO: i forgot why, add a test + writeln("> Resolve template for: ",variableSym.name, ": ", type.name); + writeln("ctx callTip: ", lookup.ctx.calltip); + + + void printti(VariableContext.TypeInstance* it, ref int index) + { + print_tab(index); io.write("chain:", it.chain, "name: ", it.name, " ct: ", it.calltip, " args: ", it.args.length, "\n"); + index += 1; + foreach(itt; it.args) + { + int inindex = index; + printti(itt, inindex); + } + } + int index = 0; + printti(lookup.ctx.root, index); + + writeln(""); + writeln(""); DSymbol* newType = createTypeWithTemplateArgs(type, lookup, current, cache, moduleScope, depth, mapping); - writeln(">>", variableSym.name, " > ", newType.name); + + + writeln(""); + writeln("resolved:", variableSym.name, " > ", newType.name); if (depth == 1) { From 2f63d750ba5c8ddc53b9b2f403e730b223762126 Mon Sep 17 00:00:00 2001 From: ryuukk Date: Mon, 9 Oct 2023 03:16:23 +0200 Subject: [PATCH 32/32] Properly build new array symbol --- dsymbol/src/dsymbol/conversion/second.d | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 950f26d..56961ba 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -299,7 +299,7 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC } } - writeln(""); + writeln("-"); assert(newType); string[] T_names; @@ -309,7 +309,8 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC { T_names ~= part.name; } - else if (part.type && part.type.kind == CompletionKind.typeTmpParam) + else + if (part.type && part.type.kind == CompletionKind.typeTmpParam) { print_tab(depth); writeln("part: ", part.name,": ", part.type.name); @@ -342,18 +343,34 @@ DSymbol* createTypeWithTemplateArgs(DSymbol* type, TypeLookup* lookup, VariableC print_tab(depth); writeln("array: ", part.name,": ", arrTypeTSymbol.name,"[]"); + + 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; + + // create new array shit + + if (arrTypeTSymbol.name in mapping) { auto result = mapping[arrTypeTSymbol.name]; - arrSymbol.type = result; print_tab(depth); writeln(" ", arrTypeTSymbol.name, " =>: ", result.name); + + auto newarr = GCAllocator.instance.make!DSymbol(arrSymbol.name , arrSymbol.kind, result); + newarr.ownType = false; + newPart.type = newarr; + newPart.ownType = true; } - newType.addChild(part, false); + newType.addChild(newPart, false); } else { + print_tab(depth); writeln("missing part: ", part.name,": ", part.type); // 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