Move third phase to its own module (#708)
This commit is contained in:
parent
0f69db00fb
commit
1c54fc9873
|
@ -25,6 +25,7 @@ import dparse.rollback_allocator;
|
||||||
import dsymbol.cache_entry;
|
import dsymbol.cache_entry;
|
||||||
import dsymbol.conversion.first;
|
import dsymbol.conversion.first;
|
||||||
import dsymbol.conversion.second;
|
import dsymbol.conversion.second;
|
||||||
|
import dsymbol.conversion.third;
|
||||||
import dsymbol.modulecache;
|
import dsymbol.modulecache;
|
||||||
import dsymbol.scope_;
|
import dsymbol.scope_;
|
||||||
import dsymbol.semantic;
|
import dsymbol.semantic;
|
||||||
|
@ -49,75 +50,7 @@ ScopeSymbolPair generateAutocompleteTrees(const(Token)[] tokens,
|
||||||
|
|
||||||
secondPass(first.rootSymbol, first.moduleScope, cache);
|
secondPass(first.rootSymbol, first.moduleScope, cache);
|
||||||
|
|
||||||
void tryResolve(Scope* sc, ref ModuleCache cache)
|
thirdPass(first.moduleScope, cache, cursorPosition);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
auto r = move(first.rootSymbol.acSymbol);
|
auto r = move(first.rootSymbol.acSymbol);
|
||||||
typeid(SemanticSymbol).destroy(first.rootSymbol);
|
typeid(SemanticSymbol).destroy(first.rootSymbol);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue