More import fixes

This commit is contained in:
Hackerpilot 2014-09-03 08:39:39 +00:00
parent c97fca76ee
commit 02063b87a3
4 changed files with 98 additions and 43 deletions

View File

@ -394,12 +394,25 @@ body
HashSet!string h; HashSet!string h;
foreach (s; symbols.parts[]) foreach (s; symbols.parts[])
{ {
auto a = ACSymbol(s.name); if (s.kind == CompletionKind.importSymbol) foreach (sy; s.type.parts[])
if (!builtinSymbols.contains(&a) && !h.contains(s.name))
{ {
response.completionKinds ~= s.kind; auto a = ACSymbol(sy.name);
response.completions ~= s.name; if (!builtinSymbols.contains(&a) && sy.name !is null && !h.contains(sy.name))
h.insert(s.name); {
response.completionKinds ~= sy.kind;
response.completions ~= sy.name;
h.insert(sy.name);
}
}
else
{
auto a = ACSymbol(s.name);
if (!builtinSymbols.contains(&a) && s.name !is null && !h.contains(s.name))
{
response.completionKinds ~= s.kind;
response.completions ~= s.name;
h.insert(s.name);
}
} }
} }
response.completionType = CompletionType.identifiers; response.completionType = CompletionType.identifiers;

View File

@ -37,6 +37,11 @@ struct SecondPass
{ {
public: public:
/**
* Construct this with the results of the first pass
* Params:
* first = the first pass
*/
this(FirstPass first) this(FirstPass first)
{ {
this.rootSymbol = first.rootSymbol; this.rootSymbol = first.rootSymbol;
@ -44,6 +49,9 @@ public:
this.symbolAllocator = first.symbolAllocator; this.symbolAllocator = first.symbolAllocator;
} }
/**
* Runs the second pass on the module.
*/
void run() void run()
{ {
rootSymbol.acSymbol.parts.insert(builtinSymbols[]); rootSymbol.acSymbol.parts.insert(builtinSymbols[]);
@ -51,12 +59,26 @@ public:
resolveImports(moduleScope); resolveImports(moduleScope);
} }
/**
* Allocator used for allocating autocomplete symbols.
*/
CAllocator symbolAllocator; CAllocator symbolAllocator;
/**
* The root symbol from the first pass
*/
SemanticSymbol* rootSymbol; SemanticSymbol* rootSymbol;
/**
* The module scope from the first pass
*/
Scope* moduleScope; Scope* moduleScope;
private: private:
/**
* Assigns symbols to scopes based on their location.
*/
void assignToScopes(ACSymbol* currentSymbol) void assignToScopes(ACSymbol* currentSymbol)
{ {
Scope* s = moduleScope.getScopeByCursor(currentSymbol.location); Scope* s = moduleScope.getScopeByCursor(currentSymbol.location);
@ -71,12 +93,19 @@ private:
/** /**
* Creates package symbols as necessary to contain the given module symbol * Creates package symbols as necessary to contain the given module symbol
* Params:
* info = the import information for the module being imported
* currentScope = the scope in which the import statement is located
* moduleSymbol = the module being imported
* Returns: A package symbol that can be used for auto-completing qualified
* symbol names.
*/ */
ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope, ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope,
ACSymbol* moduleSymbol) ACSymbol* moduleSymbol)
in in
{ {
assert (info !is null); assert (info !is null);
assert (currentScope !is null);
assert (moduleSymbol !is null); assert (moduleSymbol !is null);
} }
body body
@ -89,7 +118,6 @@ private:
else else
firstSymbol = allocate!ACSymbol(symbolAllocator, firstPart, firstSymbol = allocate!ACSymbol(symbolAllocator, firstPart,
CompletionKind.packageName); CompletionKind.packageName);
currentScope.symbols.insert(firstSymbol);
ACSymbol* currentSymbol = firstSymbol; ACSymbol* currentSymbol = firstSymbol;
size_t i = 0; size_t i = 0;
foreach (string importPart; info.importParts[]) foreach (string importPart; info.importParts[])
@ -99,9 +127,17 @@ private:
if (i + 2 >= info.importParts.length) // Skip the last item as it's the module name if (i + 2 >= info.importParts.length) // Skip the last item as it's the module name
break; break;
symbols = currentSymbol.getPartsByName(importPart); symbols = currentSymbol.getPartsByName(importPart);
ACSymbol* s = symbols.length > 0 ACSymbol* s = null;
? cast(ACSymbol*) symbols[0] : allocate!ACSymbol(symbolAllocator, if (symbols.length > 0) foreach (sy; symbols)
importPart, CompletionKind.packageName); {
if (sy.kind == CompletionKind.packageName)
{
s = sy;
break;
}
}
if (s is null)
s = allocate!ACSymbol(symbolAllocator, importPart, CompletionKind.packageName);
currentSymbol.parts.insert(s); currentSymbol.parts.insert(s);
currentSymbol = s; currentSymbol = s;
} }
@ -120,45 +156,50 @@ private:
if (symbol is null) if (symbol is null)
continue; continue;
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol); ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol);
currentScope.symbols.insert(symbol.parts[]);
if (importInfo.importedSymbols.length == 0) if (importInfo.importedSymbols.length == 0)
{ {
if (importInfo.isPublic && currentScope.parent is null) if (importInfo.isPublic && currentScope.parent is null)
{
rootSymbol.acSymbol.parts.insert(allocate!ACSymbol(symbolAllocator, rootSymbol.acSymbol.parts.insert(allocate!ACSymbol(symbolAllocator,
IMPORT_SYMBOL_NAME, CompletionKind.importSymbol, symbol)); IMPORT_SYMBOL_NAME, CompletionKind.importSymbol, symbol));
} else
currentScope.symbols.insert(symbol.parts[]);
continue; continue;
} }
symbolLoop: foreach (sym; symbol.parts[])
foreach (tup; importInfo.importedSymbols[])
{ {
foreach (tup; importInfo.importedSymbols[]) ACSymbol needle = ACSymbol(tup[0]);
ACSymbol* sym;
auto r = symbol.parts.equalRange(&needle);
if (r.empty) foreach (sy; symbol.parts[])
{ {
if (tup[0] != symbol.name) if (sy.kind != CompletionKind.importSymbol || sy.type is null)
continue symbolLoop; continue;
if (tup[1] !is null) auto ra = sy.type.parts.equalRange(&needle);
{ if (ra.empty)
ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[1], continue;
sym.kind, sym.type); sym = ra.front;
s.parts.insert(sym.parts[]);
s.callTip = sym.callTip;
s.doc = sym.doc;
s.qualifier = sym.qualifier;
s.location = sym.location;
s.symbolFile = sym.symbolFile;
currentScope.symbols.insert(s);
moduleSymbol.parts.insert(s);
if (importInfo.isPublic && currentScope.parent is null)
rootSymbol.acSymbol.parts.insert(s);
}
else
{
moduleSymbol.parts.insert(sym);
currentScope.symbols.insert(sym);
if (importInfo.isPublic && currentScope.parent is null)
rootSymbol.acSymbol.parts.insert(sym);
}
} }
else
sym = r.front;
if (sym is null)
continue;
if (tup[1] !is null)
{
ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[1],
sym.kind, sym.type);
s.parts.insert(sym.parts[]);
s.callTip = sym.callTip;
s.doc = sym.doc;
s.qualifier = sym.qualifier;
s.location = sym.location;
s.symbolFile = sym.symbolFile;
sym = s;
}
moduleSymbol.parts.insert(sym);
currentScope.symbols.insert(sym);
if (importInfo.isPublic && currentScope.parent is null)
rootSymbol.acSymbol.parts.insert(sym);
} }
} }
foreach (childScope; currentScope.children) foreach (childScope; currentScope.children)

View File

@ -95,6 +95,7 @@ static this()
*/ */
struct ModuleCache struct ModuleCache
{ {
/// No copying.
@disable this(); @disable this();
/** /**
@ -219,7 +220,7 @@ struct ModuleCache
{ {
string dotDi = buildPath(path, moduleName) ~ ".di"; string dotDi = buildPath(path, moduleName) ~ ".di";
string dotD = dotDi[0 .. $ - 1]; string dotD = dotDi[0 .. $ - 1];
string withoutSuffix = dotDi[0 .. $ - 2]; string withoutSuffix = dotDi[0 .. $ - 3];
if (exists(dotD) && isFile(dotD)) if (exists(dotD) && isFile(dotD))
alternatives = (dotD) ~ alternatives; alternatives = (dotD) ~ alternatives;
else if (exists(dotDi) && isFile(dotDi)) else if (exists(dotDi) && isFile(dotDi))
@ -244,6 +245,7 @@ struct ModuleCache
return importPaths[]; return importPaths[];
} }
/// Count of autocomplete symbols that have been allocated
static uint symbolsAllocated; static uint symbolsAllocated;
private: private:

View File

@ -99,10 +99,9 @@ int main(string[] args)
scope(exit) Mallocator.it.deallocate(buffer); scope(exit) Mallocator.it.deallocate(buffer);
sw.stop(); sw.stop();
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds"); Log.info(ModuleCache.symbolsAllocated, " symbols cached.");
// float symbolMegs = (cast(float) (ACSymbol.sizeof * ModuleCache.symbolsAllocated)) / (1024f * 1024f); Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds.");
// Log.info(ModuleCache.symbolsAllocated, " symbols allocated, taking up ",
// symbolMegs, " megabytes");
// No relative paths // No relative paths
version (Posix) chdir("/"); version (Posix) chdir("/");