From 1b67f493d450e5194724c7f7ecec08ddd672f075 Mon Sep 17 00:00:00 2001 From: Vushu Date: Sun, 5 Mar 2023 18:00:50 +0100 Subject: [PATCH] Adding return type symbol (#720) --- dsymbol/src/dsymbol/conversion/first.d | 9 +-- dsymbol/src/dsymbol/conversion/second.d | 37 ++++------ dsymbol/src/dsymbol/tests.d | 95 +++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 27 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e488566..14d3269 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -37,6 +37,7 @@ import std.experimental.allocator; import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.logger; import std.typecons : Rebindable; +import std.array : appender; /** * First Pass handles the following: @@ -148,6 +149,10 @@ final class FirstPass : ASTVisitor processParameters(currentSymbol, dec.returnType, currentSymbol.acSymbol.name, dec.parameters, dec.templateParameters); } + + if (dec.returnType !is null){ + addTypeToLookups(currentSymbol.typeLookups, dec.returnType); + } } override void visit(const FunctionLiteralExpression exp) @@ -778,7 +783,6 @@ private: void createConstructor() { - import std.array : appender; import std.range : zip; auto app = appender!string(); @@ -1064,7 +1068,6 @@ private: istring formatCallTip(const Type returnType, string name, const Parameters parameters, const TemplateParameters templateParameters) { - import std.array : appender; auto app = appender!string(); if (returnType !is null) @@ -1136,7 +1139,6 @@ private: lookup.breadcrumbs.insert(POINTER_SYMBOL_NAME); else if (suffix.delegateOrFunction != tok!"") { - import std.array : appender; auto app = appender!string(); formatNode(app, type); istring callTip = istring(app.data); @@ -1341,7 +1343,6 @@ void writeIotcTo(T)(const IdentifierOrTemplateChain iotc, ref T output) nothrow static istring convertChainToImportPath(const IdentifierChain ic) { import std.path : dirSeparator; - import std.array : appender; auto app = appender!string(); foreach (i, ident; ic.identifiers) { diff --git a/dsymbol/src/dsymbol/conversion/second.d b/dsymbol/src/dsymbol/conversion/second.d index 9142d16..a94795f 100644 --- a/dsymbol/src/dsymbol/conversion/second.d +++ b/dsymbol/src/dsymbol/conversion/second.d @@ -33,6 +33,8 @@ import std.experimental.allocator.gc_allocator : GCAllocator; import std.experimental.logger; import dparse.ast; import dparse.lexer; +import std.algorithm : filter; +import std.range; void secondPass(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache) { @@ -312,8 +314,6 @@ private: void resolveInheritance(DSymbol* symbol, ref TypeLookups typeLookups, Scope* moduleScope, ref ModuleCache cache) { - import std.algorithm : filter; - outer: foreach (TypeLookup* lookup; typeLookups[]) { if (lookup.kind != TypeLookupKind.inherit) @@ -355,9 +355,6 @@ void resolveInheritance(DSymbol* symbol, ref TypeLookups typeLookups, void resolveAliasThis(DSymbol* symbol, ref TypeLookups typeLookups, Scope* moduleScope, ref ModuleCache cache) { - import std.algorithm : filter; - import std.array : array; - foreach (aliasThis; typeLookups[].filter!(a => a.kind == TypeLookupKind.aliasThis)) { assert(aliasThis.breadcrumbs.length > 0); @@ -379,8 +376,6 @@ void resolveAliasThis(DSymbol* symbol, void resolveMixinTemplates(DSymbol* symbol, ref TypeLookups typeLookups, Scope* moduleScope, ref ModuleCache cache) { - import std.algorithm : filter; - foreach (mix; typeLookups[].filter!(a => a.kind == TypeLookupKind.mixinTemplate)) { assert(mix.breadcrumbs.length > 0); @@ -414,22 +409,18 @@ void resolveMixinTemplates(DSymbol* symbol, void resolveType(DSymbol* symbol, ref TypeLookups typeLookups, Scope* moduleScope, ref ModuleCache cache) { - - import std.conv; - - if (typeLookups.length == 0) - return; - assert(typeLookups.length == 1); - auto lookup = typeLookups.front; - if (lookup.kind == TypeLookupKind.varOrFunType) - resolveTypeFromType(symbol, lookup, moduleScope, cache, null); - else if (lookup.kind == TypeLookupKind.initializer) - resolveTypeFromInitializer(symbol, lookup, moduleScope, cache); - // issue 94 - else if (lookup.kind == TypeLookupKind.inherit) - resolveInheritance(symbol, typeLookups, moduleScope, cache); - else - assert(false, "How did this happen?"); + // going through the lookups + foreach(lookup; typeLookups) { + if (lookup.kind == TypeLookupKind.varOrFunType) + resolveTypeFromType(symbol, lookup, moduleScope, cache, null); + else if (lookup.kind == TypeLookupKind.initializer) + resolveTypeFromInitializer(symbol, lookup, moduleScope, cache); + // issue 94 + else if (lookup.kind == TypeLookupKind.inherit) + resolveInheritance(symbol, typeLookups, moduleScope, cache); + else + assert(false, "How did this happen?"); + } } void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup, diff --git a/dsymbol/src/dsymbol/tests.d b/dsymbol/src/dsymbol/tests.d index 3652388..1f8a946 100644 --- a/dsymbol/src/dsymbol/tests.d +++ b/dsymbol/src/dsymbol/tests.d @@ -126,6 +126,101 @@ unittest } } +unittest +{ + ModuleCache cache; + writeln("Get return type name"); + auto source = q{ int meaningOfLife() { return 42; } }; + auto pair = generateAutocompleteTrees(source, cache); + auto meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type.name == "int"); +} + +unittest +{ + ModuleCache cache; + writeln("Get return type name from class method"); + auto source = q{ class Life { uint meaningOfLife() { return 42; } }}; + auto pair = generateAutocompleteTrees(source, cache); + auto lifeClass = pair.symbol.getFirstPartNamed(istring("Life")); + auto meaningOfLife = lifeClass.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type.name == "uint"); +} + +unittest +{ + ModuleCache cache; + writeln("Return type of auto should be null"); + auto source = q{ class Life { auto meaningOfLife() { return 42; } }}; + auto pair = generateAutocompleteTrees(source, cache); + auto lifeClass = pair.symbol.getFirstPartNamed(istring("Life")); + auto meaningOfLife = lifeClass.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type is null); +} + +unittest +{ + ModuleCache cache; + writeln("Return type of scope should be null"); + auto source = q{ class Life { scope meaningOfLife() { return 42; } }}; + auto pair = generateAutocompleteTrees(source, cache); + auto lifeClass = pair.symbol.getFirstPartNamed(istring("Life")); + auto meaningOfLife = lifeClass.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type is null); +} + +unittest +{ + ModuleCache cache; + writeln("Templated return type should be deduced correctly"); + auto source = q{ + struct AnswerToLife(T) { + T life; + } + AnswerToLife!int meaningOfLife() { return AnswerToLife!int(42); } + + }; + ScopeSymbolPair pair = generateAutocompleteTrees(source, cache); + auto answerToLife = pair.symbol.getFirstPartNamed(istring("AnswerToLife")); + DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type.name == "AnswerToLife"); + assert(meaningOfLife.type is answerToLife); + +} + +unittest +{ + ModuleCache cache; + writeln("Array return type should be deduced correctly"); + auto source = q{ + int[] meaningOfLife() { return [42]; } + + }; + ScopeSymbolPair pair = generateAutocompleteTrees(source, cache); + DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife")); + assert(meaningOfLife.type.name == "*arr*"); + +} + +unittest +{ + ModuleCache cache; + writeln("Int* return type should be deduced correctly"); + auto source = q{ + int* meaningOfLife() + { + auto life = 42; + return &life; + } + + }; + ScopeSymbolPair pair = generateAutocompleteTrees(source, cache); + DSymbol* meaningOfLife = pair.symbol.getFirstPartNamed(istring("meaningOfLife")); + writeln(meaningOfLife.type.name); + assert(meaningOfLife.type.name == "int"); +} + + unittest { ModuleCache cache;