Skip to content

Commit

Permalink
Move third phase to its own module (#708)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryuukk committed Feb 6, 2023
1 parent 0f69db0 commit 1c54fc9
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 69 deletions.
71 changes: 2 additions & 69 deletions dsymbol/src/dsymbol/conversion/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
111 changes: 111 additions & 0 deletions dsymbol/src/dsymbol/conversion/third.d
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 1c54fc9

Please sign in to comment.