Move third phase to its own module (#708)

This commit is contained in:
ryuukk 2023-02-06 15:38:10 +01:00 committed by GitHub
parent 0f69db00fb
commit 1c54fc9873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 69 deletions

View File

@ -25,6 +25,7 @@ import dparse.rollback_allocator;
import dsymbol.cache_entry;
import dsymbol.conversion.first;
import dsymbol.conversion.second;
import dsymbol.conversion.third;
import dsymbol.modulecache;
import dsymbol.scope_;
import dsymbol.semantic;
@ -49,75 +50,7 @@ ScopeSymbolPair generateAutocompleteTrees(const(Token)[] tokens,
secondPass(first.rootSymbol, first.moduleScope, cache);
void tryResolve(Scope* sc, ref ModuleCache cache)
{
if (sc is null) return;
auto symbols = sc.symbols;
foreach (item; symbols)
{
DSymbol* target = item.type;
void resolvePart(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 typeSymbolName, 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[0];
return;
}
else
{
if (part.symbolFile == "stdin") return;
auto moduleSymbol = cache.getModuleSymbol(part.symbolFile);
auto first = moduleSymbol.getFirstPartNamed(istring(typeName));
if (first !is null)
{
part.type = first;
return;
}
else
{
// type couldn't be found, that's stuff like templates
// now we could try to resolve them!
// warning("can't resolve: ", part.name, " callTip: ", typeName);
return;
}
}
}
if (part.type !is null)
{
foreach (typePart; part.type.opSlice())
resolvePart(typePart, sc, visited);
}
}
if (target !is null)
{
HashSet!size_t visited;
foreach (part; target.opSlice())
{
resolvePart(part, sc, visited);
}
}
}
if (sc.parent !is null) tryResolve(sc.parent, cache);
}
auto desired = first.moduleScope.getScopeByCursor(cursorPosition);
tryResolve(desired, cache);
thirdPass(first.moduleScope, cache, cursorPosition);
auto r = move(first.rootSymbol.acSymbol);
typeid(SemanticSymbol).destroy(first.rootSymbol);

View File

@ -0,0 +1,111 @@
/**
* This file is part of DCD, a development tool for the D programming language.
* Copyright (C) 2014 Brian Schott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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;
/**
* Used to resolve the type of remaining symbols that were left out due to modules being parsed from other modules that depend on each other (public imports)
* It will start from the scope of interest at the cursorPosition, and it'll traverse the scope from bottom to top and check if the symbol's type is know
* 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)
{
auto desired = mscope.getScopeByCursor(cursorPosition);
tryResolve(desired, cache);
}
/**
* Used to resolve missing symbols within a scope
*/
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(part, sc, cache, visited);
}
}
}
if (sc.parent !is null) tryResolve(sc.parent, cache);
}
void resolvePart(DSymbol* part, Scope* sc, ref ModuleCache cache, ref HashSet!size_t visited)
{
if (visited.contains(cast(size_t) part))
return;
visited.insert(cast(size_t) part);
// no type but a typeSymbolName, 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[0];
return;
}
else
{
if (part.symbolFile == "stdin") return;
auto moduleSymbol = cache.getModuleSymbol(part.symbolFile);
auto first = moduleSymbol.getFirstPartNamed(istring(typeName));
if (first !is null)
{
part.type = first;
return;
}
else
{
// type couldn't be found, that's stuff like templates
// now we could try to resolve them!
// warning("can't resolve: ", part.name, " callTip: ", typeName);
return;
}
}
}
if (part.type !is null)
{
foreach (typePart; part.type.opSlice())
resolvePart(typePart, sc, cache, visited);
}
}