Skip to content

Commit

Permalink
Public import recurse fix (#706)
Browse files Browse the repository at this point in the history
* Add a 3rd phase to tesolve missing types that were parsed recursively
* store the type name into its own field, so we could resolve templates later

Fixes #678
  • Loading branch information
ryuukk authored Feb 3, 2023
1 parent c2051b0 commit 0f69db0
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 0 deletions.
72 changes: 72 additions & 0 deletions dsymbol/src/dsymbol/conversion/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import dsymbol.string_interning;
import dsymbol.symbol;
import std.algorithm;
import std.experimental.allocator;
import containers.hashset;

/**
* Used by autocompletion.
Expand All @@ -47,6 +48,77 @@ ScopeSymbolPair generateAutocompleteTrees(const(Token)[] tokens,
first.run();

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);

auto r = move(first.rootSymbol.acSymbol);
typeid(SemanticSymbol).destroy(first.rootSymbol);
return ScopeSymbolPair(r, move(first.moduleScope));
Expand Down
4 changes: 4 additions & 0 deletions dsymbol/src/dsymbol/conversion/second.d
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ do
if (symbols.length > 0)
currentSymbol = symbols[0];
else
{
// store the part, that'll be useful to resolve the type later
symbol.typeSymbolName = istring(part);
return;
}
}
}
else
Expand Down
5 changes: 5 additions & 0 deletions dsymbol/src/dsymbol/symbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,11 @@ struct DSymbol
*/
DSymbol*[] functionParameters;

/**
* Used to resolve the type
*/
istring typeSymbolName;

private uint _location;

/**
Expand Down
1 change: 1 addition & 0 deletions tests/tc_recursive_public_import/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import testing; void main() { Hello hello; hello.w }
8 changes: 8 additions & 0 deletions tests/tc_recursive_public_import/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
set -e
set -u

echo "import: $PWD/testing"

../../bin/dcd-client $1 app.d --extended -I $PWD/ -c50 > actual.txt
echo -e "identifiers\nworld\tv\tWorld world\t$PWD/testing/a.d 77\t" > expected.txt
diff actual.txt expected.txt --strip-trailing-cr
11 changes: 11 additions & 0 deletions tests/tc_recursive_public_import/testing/a.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module testing.a;

import testing;

struct Fuck {}

struct Hello
{
World world;
Fuck fuck;
}
8 changes: 8 additions & 0 deletions tests/tc_recursive_public_import/testing/b.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module testing.b;

import testing;

struct World
{
int field;
}
4 changes: 4 additions & 0 deletions tests/tc_recursive_public_import/testing/package.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module testing;

public import testing.a;
public import testing.b;

0 comments on commit 0f69db0

Please sign in to comment.