Skip to content

Instantly share code, notes, and snippets.

@ryuukk
Created February 3, 2023 18:30
Show Gist options
  • Save ryuukk/e82474927be68ddb5638b49b847f4ab7 to your computer and use it in GitHub Desktop.
Save ryuukk/e82474927be68ddb5638b49b847f4ab7 to your computer and use it in GitHub Desktop.
module dsymbol.conversion.third;
import dsymbol.modulecache;
import dsymbol.scope_;
import dsymbol.semantic;
import dsymbol.symbol;
import dsymbol.string_interning;
import dsymbol.deferred;
import containers.hashset;
import std.string;
import std.array;
import std.logger;
void thirdPass(Scope* mscope, ref ModuleCache cache, size_t cursorPosition)
{
auto desired = mscope.getScopeByCursor(cursorPosition);
tryResolve(desired, cache);
}
bool tryResolveTemplate(Scope* sc, ref ModuleCache cache, DSymbol* item)
{
auto fnCT = item.typeSymbolName;
if(fnCT is null)
return false;
if (auto spaceIndex = fnCT.indexOf(" ") > 0)
{
bool hasParen = false;
bool isTemplate = false;
auto retPart = fnCT[0 .. spaceIndex];
auto fnPart = fnCT[spaceIndex .. $];
for(int i = 0; i < fnPart.length; i++)
{
if(fnPart[i] ==')')
{
if (hasParen)
{
isTemplate = true;
break;
}
hasParen = true;
}
}
if (isTemplate)
{
auto returnTypePtr = retPart[$-1] == '*';
auto returnTypeArr = retPart[$-1] == ']';
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(")")];
}
if (returnTypePtr)
{
retPart = retPart[0 .. $ - 1];
}
auto typesStr = fnPart[ fnPart.indexOf('(') + 1 .. $ ];
typesStr = typesStr[0 .. typesStr.indexOf(')') ];
auto typesSplit = split(typesStr, ',');
foreach(i, t; typesSplit)
{
auto cleanType = t.strip;
if (retPart == cleanType)
{
if (item.remainingCrumbs.length >= (i+1))
{
auto typeName = item.remainingCrumbs[i];
auto result = sc.getSymbolsAtGlobalScope(istring(typeName));
if (result.length > 0)
{
item.type = result[0];
item.ownType = false;
return true;
}
else
{
if (item.symbolFile is null || item.symbolFile == "stdin")
return false;
auto moduleSymbol = cache.getModuleSymbol(item.symbolFile);
auto first = moduleSymbol.getFirstPartNamed(istring(typeName));
if (first !is null)
{
item.type = first;
item.ownType = false;
return true;
}
else
return false;
}
}
break;
}
}
}
}
return false;
}
void tryResolve(Scope* sc, ref ModuleCache cache)
{
if (sc is null) return;
auto symbols = sc.symbols;
foreach (item; symbols)
{
DSymbol* target = item.type;
if (target !is null)
{
HashSet!size_t visited;
foreach (part; target.opSlice())
{
resolvePart(cache, part, sc, visited);
}
}
if (item.remainingCrumbs.length > 0)
{
if (tryResolveTemplate(sc, cache, item))
{
item.remainingCrumbs = null;
continue;
}
}
// try resolve auto variables
if (item.kind == CompletionKind.variableName && item.type !is null)
{
auto type = item.type;
while (type)
{
if (type.kind == CompletionKind.variableName)
type = type.type;
else break;
}
item.type = type;
}
}
if (sc.parent !is null) tryResolve(sc.parent, cache);
}
void resolvePart(ref ModuleCache cache, DSymbol* part, Scope* sc, ref HashSet!size_t visited)
{
if (visited.contains(cast(size_t) part))
return;
visited.insert(cast(size_t) part);
// no type but a callTip, let's resolve its type
if (part.type is null && part.typeSymbolName !is null)
{
import std.string: indexOf;
auto typeName = part.typeSymbolName;
// check if it is available in the scope
// otherwise grab its module symbol to check if it's publickly available
auto result = sc.getSymbolsAtGlobalScope(istring(typeName));
if (result.length > 0)
{
part.type = result[$-1];
part.ownType = false;
return;
}
else
{
if (part.symbolFile is null || part.symbolFile == "stdin")
return;
auto moduleSymbol = cache.getModuleSymbol(part.symbolFile);
auto first = moduleSymbol.getFirstPartNamed(istring(typeName));
if (first !is null)
{
part.type = first;
part.ownType = false;
return;
}
else
return;
}
}
if (part.type !is null)
{
foreach (typePart; part.type.opSlice())
{
resolvePart(cache, typePart, sc, visited);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment