run a lightweight version of second phase to make sure no symbols are left out

This commit is contained in:
ryuukk 2023-05-19 23:57:52 +02:00 committed by Jan Jurzitza
parent 33fd0db07d
commit 953d32f2fa
3 changed files with 129 additions and 93 deletions

View File

@ -51,7 +51,7 @@ ScopeSymbolPair generateAutocompleteTrees(const(Token)[] tokens,
secondPass(first.rootSymbol, first.moduleScope, cache);
thirdPass(first.moduleScope, cache, cursorPosition);
thirdPass(first.rootSymbol, first.moduleScope, cache, cursorPosition);
auto ufcsSymbols = getUFCSSymbolsForCursor(first.moduleScope, tokens, cursorPosition);

View File

@ -311,6 +311,97 @@ do
}
}
void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
Scope* moduleScope, ref ModuleCache cache)
{
if (lookup.breadcrumbs.length == 0)
return;
DSymbol* currentSymbol = null;
size_t i = 0;
auto crumbs = lookup.breadcrumbs[];
foreach (crumb; crumbs)
{
if (i == 0)
{
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
symbolNameToTypeName(crumb), symbol.location);
if (currentSymbol is null)
return;
}
else if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
{
auto arr = GCAllocator.instance.make!(DSymbol)(ARRAY_LITERAL_SYMBOL_NAME, CompletionKind.dummy, currentSymbol);
arr.qualifier = SymbolQualifier.array;
currentSymbol = arr;
}
else if (crumb == ARRAY_SYMBOL_NAME)
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
// Index expressions can be on a pointer, an array or an AA
if (currentSymbol.qualifier == SymbolQualifier.array
|| currentSymbol.qualifier == SymbolQualifier.assocArray
|| currentSymbol.qualifier == SymbolQualifier.pointer
|| currentSymbol.kind == CompletionKind.aliasName)
{
if (currentSymbol.type !is null)
currentSymbol = currentSymbol.type;
else
return;
}
else
{
auto opIndex = currentSymbol.getFirstPartNamed(internString("opIndex"));
if (opIndex !is null)
currentSymbol = opIndex.type;
else
return;
}
}
else if (crumb == "foreach")
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
if (currentSymbol.qualifier == SymbolQualifier.array
|| currentSymbol.qualifier == SymbolQualifier.assocArray)
{
currentSymbol = currentSymbol.type;
break;
}
auto front = currentSymbol.getFirstPartNamed(internString("front"));
if (front !is null)
{
currentSymbol = front.type;
break;
}
auto opApply = currentSymbol.getFirstPartNamed(internString("opApply"));
if (opApply !is null)
{
currentSymbol = opApply.type;
break;
}
}
else
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
}
++i;
if (currentSymbol is null)
return;
}
typeSwap(currentSymbol);
symbol.type = currentSymbol;
symbol.ownType = false;
}
private:
void resolveInheritance(DSymbol* symbol, ref TypeLookups typeLookups,
@ -425,97 +516,6 @@ void resolveType(DSymbol* symbol, ref TypeLookups typeLookups,
}
}
void resolveTypeFromInitializer(DSymbol* symbol, TypeLookup* lookup,
Scope* moduleScope, ref ModuleCache cache)
{
if (lookup.breadcrumbs.length == 0)
return;
DSymbol* currentSymbol = null;
size_t i = 0;
auto crumbs = lookup.breadcrumbs[];
foreach (crumb; crumbs)
{
if (i == 0)
{
currentSymbol = moduleScope.getFirstSymbolByNameAndCursor(
symbolNameToTypeName(crumb), symbol.location);
if (currentSymbol is null)
return;
}
else if (crumb == ARRAY_LITERAL_SYMBOL_NAME)
{
auto arr = GCAllocator.instance.make!(DSymbol)(ARRAY_LITERAL_SYMBOL_NAME, CompletionKind.dummy, currentSymbol);
arr.qualifier = SymbolQualifier.array;
currentSymbol = arr;
}
else if (crumb == ARRAY_SYMBOL_NAME)
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
// Index expressions can be on a pointer, an array or an AA
if (currentSymbol.qualifier == SymbolQualifier.array
|| currentSymbol.qualifier == SymbolQualifier.assocArray
|| currentSymbol.qualifier == SymbolQualifier.pointer
|| currentSymbol.kind == CompletionKind.aliasName)
{
if (currentSymbol.type !is null)
currentSymbol = currentSymbol.type;
else
return;
}
else
{
auto opIndex = currentSymbol.getFirstPartNamed(internString("opIndex"));
if (opIndex !is null)
currentSymbol = opIndex.type;
else
return;
}
}
else if (crumb == "foreach")
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
if (currentSymbol.qualifier == SymbolQualifier.array
|| currentSymbol.qualifier == SymbolQualifier.assocArray)
{
currentSymbol = currentSymbol.type;
break;
}
auto front = currentSymbol.getFirstPartNamed(internString("front"));
if (front !is null)
{
currentSymbol = front.type;
break;
}
auto opApply = currentSymbol.getFirstPartNamed(internString("opApply"));
if (opApply !is null)
{
currentSymbol = opApply.type;
break;
}
}
else
{
typeSwap(currentSymbol);
if (currentSymbol is null)
return;
currentSymbol = currentSymbol.getFirstPartNamed(crumb);
}
++i;
if (currentSymbol is null)
return;
}
typeSwap(currentSymbol);
symbol.type = currentSymbol;
symbol.ownType = false;
}
void typeSwap(ref DSymbol* currentSymbol)
{
while (currentSymbol !is null && currentSymbol.type !is currentSymbol

View File

@ -34,10 +34,46 @@ import containers.hashset;
* If it is, then it'll set its type
* If the symbol is not found, then it'll do nothing
*/
void thirdPass(Scope* mscope, ref ModuleCache cache, size_t cursorPosition)
void thirdPass(SemanticSymbol* root, Scope* mscope, ref ModuleCache cache, size_t cursorPosition)
{
auto desired = mscope.getScopeByCursor(cursorPosition);
tryResolve(desired, cache);
// Check if there are any left out symbols
// Check issue 717 and test tc717
checkMissingTypes(root, mscope, cache);
}
void checkMissingTypes(SemanticSymbol* currentSymbol, Scope* moduleScope, ref ModuleCache cache)
{
import dsymbol.conversion.second;
import dsymbol.type_lookup;
with (CompletionKind) switch (currentSymbol.acSymbol.kind)
{
case withSymbol:
case variableName:
case memberVariableName:
case functionName:
case ufcsName:
case aliasName:
if (currentSymbol.acSymbol.type is null)
{
if (currentSymbol.typeLookups.length == 0)
break;
auto lookup = currentSymbol.typeLookups.front;
if (lookup.kind == TypeLookupKind.varOrFunType)
resolveTypeFromType(currentSymbol.acSymbol, lookup, moduleScope, cache, null);
else if (lookup.kind == TypeLookupKind.initializer)
resolveTypeFromInitializer(currentSymbol.acSymbol, lookup, moduleScope, cache);
}
break;
default:
break;
}
foreach (child; currentSymbol.children)
checkMissingTypes(child, moduleScope, cache);
}
/**