Drastic performance increase. Helps address #108
This commit is contained in:
parent
2a812d372b
commit
e6c03b6610
262
actypes.d
262
actypes.d
|
@ -26,6 +26,12 @@ import std.array;
|
|||
import messages;
|
||||
import std.array;
|
||||
import std.typecons;
|
||||
import std.container;
|
||||
|
||||
bool comparitor(const(ACSymbol)* a, const(ACSymbol)* b) pure nothrow
|
||||
{
|
||||
return a.name < b.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any special information about a variable declaration symbol.
|
||||
|
@ -49,6 +55,8 @@ struct ACSymbol
|
|||
{
|
||||
public:
|
||||
|
||||
@disable this();
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
|
@ -56,6 +64,7 @@ public:
|
|||
this(string name)
|
||||
{
|
||||
this.name = name;
|
||||
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,6 +76,7 @@ public:
|
|||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,51 +85,29 @@ public:
|
|||
* kind = the symbol's completion kind
|
||||
* resolvedType = the resolved type of the symbol
|
||||
*/
|
||||
this(string name, CompletionKind kind, const(ACSymbol)* type)
|
||||
this(string name, CompletionKind kind, ACSymbol* type)
|
||||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison operator sorts based on the name field
|
||||
*/
|
||||
int opCmp(string str) const
|
||||
{
|
||||
if (str < this.name) return -1;
|
||||
if (str > this.name) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
int opCmp(const(ACSymbol)* other) const
|
||||
{
|
||||
return this.opCmp(other.name);
|
||||
this.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parts whose name matches the given string.
|
||||
*/
|
||||
const(ACSymbol)*[] getPartsByName(string name) const
|
||||
ACSymbol*[] getPartsByName(string name)
|
||||
{
|
||||
return cast(typeof(return)) parts.filter!(a => a.name == name).array;
|
||||
}
|
||||
|
||||
size_t estimateMemory(size_t runningTotal) const
|
||||
{
|
||||
runningTotal = runningTotal + name.length + callTip.length
|
||||
+ ACSymbol.sizeof;
|
||||
foreach (part; parts)
|
||||
runningTotal = part.estimateMemory(runningTotal);
|
||||
return runningTotal;
|
||||
import std.range;
|
||||
ACSymbol s = ACSymbol(name);
|
||||
return parts.equalRange(&s).array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbols that compose this symbol, such as enum members, class variables,
|
||||
* methods, etc.
|
||||
*/
|
||||
const(ACSymbol)*[] parts;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) parts;
|
||||
|
||||
/**
|
||||
* Symbol's name
|
||||
|
@ -144,7 +132,7 @@ public:
|
|||
/**
|
||||
* The symbol that represents the type.
|
||||
*/
|
||||
const(ACSymbol)* type;
|
||||
ACSymbol* type;
|
||||
|
||||
/**
|
||||
* Symbol location
|
||||
|
@ -164,6 +152,13 @@ public:
|
|||
|
||||
struct Scope
|
||||
{
|
||||
this (size_t begin, size_t end)
|
||||
{
|
||||
this.startLocation = begin;
|
||||
this.endLocation = end;
|
||||
this.symbols = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
}
|
||||
|
||||
Scope* getScopeByCursor(size_t cursorPosition) const
|
||||
{
|
||||
if (cursorPosition < startLocation) return null;
|
||||
|
@ -177,32 +172,38 @@ struct Scope
|
|||
return cast(typeof(return)) &this;
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] getSymbolsInCursorScope(size_t cursorPosition) const
|
||||
ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const
|
||||
{
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
return [];
|
||||
const(ACSymbol)*[] symbols = cast(typeof(return)) s.symbols;
|
||||
auto symbols = s.symbols;
|
||||
Scope* sc = s.parent;
|
||||
while (sc !is null)
|
||||
{
|
||||
symbols ~= sc.symbols;
|
||||
foreach (sym; sc.symbols)
|
||||
symbols.insert(sym);
|
||||
sc = sc.parent;
|
||||
}
|
||||
return symbols;
|
||||
return symbols.array();
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] getSymbolsByName(string name) const
|
||||
ACSymbol*[] getSymbolsByName(string name) const
|
||||
{
|
||||
const(ACSymbol)*[] retVal = cast(typeof(return)) symbols.filter!(a => a.name == name).array();
|
||||
if (retVal.length > 0)
|
||||
return retVal;
|
||||
import std.range;
|
||||
ACSymbol s = ACSymbol(name);
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) t = cast() symbols;
|
||||
auto r = t.equalRange(&s).array();
|
||||
version(assert) foreach (n; r)
|
||||
assert (n.name == name, name);
|
||||
if (r.length > 0)
|
||||
return cast(typeof(return)) r;
|
||||
if (parent is null)
|
||||
return [];
|
||||
return parent.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) const
|
||||
ACSymbol*[] getSymbolsByNameAndCursor(string name, size_t cursorPosition) const
|
||||
{
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
|
@ -210,12 +211,23 @@ struct Scope
|
|||
return s.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] symbols;
|
||||
/// Imports contained in this scope
|
||||
ImportInformation[] importInformation;
|
||||
|
||||
/// The scope that contains this one
|
||||
Scope* parent;
|
||||
|
||||
/// Child scopes
|
||||
Scope*[] children;
|
||||
|
||||
/// Start location of this scope in bytes
|
||||
size_t startLocation;
|
||||
|
||||
/// End location of this scope in bytes
|
||||
size_t endLocation;
|
||||
|
||||
/// Symbols contained in this scope
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) symbols;
|
||||
}
|
||||
|
||||
struct ImportInformation
|
||||
|
@ -236,6 +248,12 @@ struct ImportInformation
|
|||
*/
|
||||
static this()
|
||||
{
|
||||
auto bSym = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
auto arrSym = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
auto asarrSym = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
auto aggSym = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
auto clSym = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
|
||||
auto bool_ = new ACSymbol("bool", CompletionKind.keyword);
|
||||
auto int_ = new ACSymbol("int", CompletionKind.keyword);
|
||||
auto long_ = new ACSymbol("long", CompletionKind.keyword);
|
||||
|
@ -255,46 +273,44 @@ static this()
|
|||
auto stringof_ = new ACSymbol("init", CompletionKind.keyword);
|
||||
auto init = new ACSymbol("stringof", CompletionKind.keyword);
|
||||
|
||||
arraySymbols ~= alignof_;
|
||||
arraySymbols ~= new ACSymbol("dup", CompletionKind.keyword);
|
||||
arraySymbols ~= new ACSymbol("idup", CompletionKind.keyword);
|
||||
arraySymbols ~= init;
|
||||
arraySymbols ~= new ACSymbol("length", CompletionKind.keyword, ulong_);
|
||||
arraySymbols ~= mangleof_;
|
||||
arraySymbols ~= new ACSymbol("ptr", CompletionKind.keyword);
|
||||
arraySymbols ~= new ACSymbol("reverse", CompletionKind.keyword);
|
||||
arraySymbols ~= sizeof_;
|
||||
arraySymbols ~= new ACSymbol("sort", CompletionKind.keyword);
|
||||
arraySymbols ~= stringof_;
|
||||
arraySymbols.sort();
|
||||
arrSym.insert(alignof_);
|
||||
arrSym.insert(new ACSymbol("dup", CompletionKind.keyword));
|
||||
arrSym.insert(new ACSymbol("idup", CompletionKind.keyword));
|
||||
arrSym.insert(init);
|
||||
arrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_));
|
||||
arrSym.insert(mangleof_);
|
||||
arrSym.insert(new ACSymbol("ptr", CompletionKind.keyword));
|
||||
arrSym.insert(new ACSymbol("reverse", CompletionKind.keyword));
|
||||
arrSym.insert(sizeof_);
|
||||
arrSym.insert(new ACSymbol("sort", CompletionKind.keyword));
|
||||
arrSym.insert(stringof_);
|
||||
|
||||
assocArraySymbols ~= alignof_;
|
||||
assocArraySymbols ~= new ACSymbol("byKey", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("byValue", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("dup", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("get", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("init", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("keys", CompletionKind.keyword);
|
||||
assocArraySymbols ~= new ACSymbol("length", CompletionKind.keyword, ulong_);
|
||||
assocArraySymbols ~= mangleof_;
|
||||
assocArraySymbols ~= new ACSymbol("rehash", CompletionKind.keyword);
|
||||
assocArraySymbols ~= sizeof_;
|
||||
assocArraySymbols ~= stringof_;
|
||||
assocArraySymbols ~= init;
|
||||
assocArraySymbols ~= new ACSymbol("values", CompletionKind.keyword);
|
||||
assocArraySymbols.sort();
|
||||
asarrSym.insert(alignof_);
|
||||
asarrSym.insert(new ACSymbol("byKey", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("byValue", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("dup", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("get", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("init", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("keys", CompletionKind.keyword));
|
||||
asarrSym.insert(new ACSymbol("length", CompletionKind.keyword, ulong_));
|
||||
asarrSym.insert(mangleof_);
|
||||
asarrSym.insert(new ACSymbol("rehash", CompletionKind.keyword));
|
||||
asarrSym.insert(sizeof_);
|
||||
asarrSym.insert(stringof_);
|
||||
asarrSym.insert(init);
|
||||
asarrSym.insert(new ACSymbol("values", CompletionKind.keyword));
|
||||
|
||||
foreach (s; [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
|
||||
ulong_, ushort_, wchar_])
|
||||
{
|
||||
s.parts ~= new ACSymbol("init", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("min", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("max", CompletionKind.keyword, s);
|
||||
s.parts ~= alignof_;
|
||||
s.parts ~= sizeof_;
|
||||
s.parts ~= stringof_;
|
||||
s.parts ~= mangleof_;
|
||||
s.parts ~= init;
|
||||
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s));
|
||||
s.parts.insert(alignof_);
|
||||
s.parts.insert(sizeof_);
|
||||
s.parts.insert(stringof_);
|
||||
s.parts.insert(mangleof_);
|
||||
s.parts.insert(init);
|
||||
}
|
||||
|
||||
auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword);
|
||||
|
@ -312,54 +328,54 @@ static this()
|
|||
foreach (s; [cdouble_, cent_, cfloat_, creal_, double_, float_,
|
||||
idouble_, ifloat_, ireal_, real_, ucent_])
|
||||
{
|
||||
s.parts ~= alignof_;
|
||||
s.parts ~= new ACSymbol("dig", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("epsilon", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("infinity", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("init", CompletionKind.keyword, s);
|
||||
s.parts ~= mangleof_;
|
||||
s.parts ~= new ACSymbol("mant_dig", CompletionKind.keyword, int_);
|
||||
s.parts ~= new ACSymbol("max", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("max_10_exp", CompletionKind.keyword, int_);
|
||||
s.parts ~= new ACSymbol("max_exp", CompletionKind.keyword, int_);
|
||||
s.parts ~= new ACSymbol("min", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("min_exp", CompletionKind.keyword, int_);
|
||||
s.parts ~= new ACSymbol("min_10_exp", CompletionKind.keyword, int_);
|
||||
s.parts ~= new ACSymbol("min_normal", CompletionKind.keyword, s);
|
||||
s.parts ~= new ACSymbol("nan", CompletionKind.keyword, s);
|
||||
s.parts ~= sizeof_;
|
||||
s.parts ~= stringof_;
|
||||
s.parts.insert(alignof_);
|
||||
s.parts.insert(new ACSymbol("dig", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("epsilon", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("infinity", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("init", CompletionKind.keyword, s));
|
||||
s.parts.insert(mangleof_);
|
||||
s.parts.insert(new ACSymbol("mant_dig", CompletionKind.keyword, int_));
|
||||
s.parts.insert(new ACSymbol("max", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("max_10_exp", CompletionKind.keyword, int_));
|
||||
s.parts.insert(new ACSymbol("max_exp", CompletionKind.keyword, int_));
|
||||
s.parts.insert(new ACSymbol("min", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("min_exp", CompletionKind.keyword, int_));
|
||||
s.parts.insert(new ACSymbol("min_10_exp", CompletionKind.keyword, int_));
|
||||
s.parts.insert(new ACSymbol("min_normal", CompletionKind.keyword, s));
|
||||
s.parts.insert(new ACSymbol("nan", CompletionKind.keyword, s));
|
||||
s.parts.insert(sizeof_);
|
||||
s.parts.insert(stringof_);
|
||||
}
|
||||
|
||||
aggregateSymbols ~= new ACSymbol("tupleof", CompletionKind.variableName);
|
||||
aggregateSymbols ~= mangleof_;
|
||||
aggregateSymbols ~= alignof_;
|
||||
aggregateSymbols ~= sizeof_;
|
||||
aggregateSymbols ~= stringof_;
|
||||
aggregateSymbols ~= init;
|
||||
aggSym.insert(new ACSymbol("tupleof", CompletionKind.variableName));
|
||||
aggSym.insert(mangleof_);
|
||||
aggSym.insert(alignof_);
|
||||
aggSym.insert(sizeof_);
|
||||
aggSym.insert(stringof_);
|
||||
aggSym.insert(init);
|
||||
|
||||
classSymbols ~= new ACSymbol("classInfo", CompletionKind.variableName);
|
||||
classSymbols ~= new ACSymbol("tupleof", CompletionKind.variableName);
|
||||
classSymbols ~= new ACSymbol("__vptr", CompletionKind.variableName);
|
||||
classSymbols ~= new ACSymbol("__monitor", CompletionKind.variableName);
|
||||
classSymbols ~= mangleof_;
|
||||
classSymbols ~= alignof_;
|
||||
classSymbols ~= sizeof_;
|
||||
classSymbols ~= stringof_;
|
||||
classSymbols ~= init;
|
||||
clSym.insert(new ACSymbol("classInfo", CompletionKind.variableName));
|
||||
clSym.insert(new ACSymbol("tupleof", CompletionKind.variableName));
|
||||
clSym.insert(new ACSymbol("__vptr", CompletionKind.variableName));
|
||||
clSym.insert(new ACSymbol("__monitor", CompletionKind.variableName));
|
||||
clSym.insert(mangleof_);
|
||||
clSym.insert(alignof_);
|
||||
clSym.insert(sizeof_);
|
||||
clSym.insert(stringof_);
|
||||
clSym.insert(init);
|
||||
|
||||
ireal_.parts ~= new ACSymbol("im", CompletionKind.keyword, real_);
|
||||
ifloat_.parts ~= new ACSymbol("im", CompletionKind.keyword, float_);
|
||||
idouble_.parts ~= new ACSymbol("im", CompletionKind.keyword, double_);
|
||||
ireal_.parts ~= new ACSymbol("re", CompletionKind.keyword, real_);
|
||||
ifloat_.parts ~= new ACSymbol("re", CompletionKind.keyword, float_);
|
||||
idouble_.parts ~= new ACSymbol("re", CompletionKind.keyword, double_);
|
||||
ireal_.parts.insert(new ACSymbol("im", CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(new ACSymbol("im", CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(new ACSymbol("im", CompletionKind.keyword, double_));
|
||||
ireal_.parts.insert(new ACSymbol("re", CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(new ACSymbol("re", CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(new ACSymbol("re", CompletionKind.keyword, double_));
|
||||
|
||||
auto void_ = new ACSymbol("void", CompletionKind.keyword);
|
||||
|
||||
builtinSymbols = [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
|
||||
bSym.insert([bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
|
||||
ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_,
|
||||
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_];
|
||||
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_]);
|
||||
|
||||
// _argptr has type void*
|
||||
argptrType = new Type;
|
||||
|
@ -382,12 +398,18 @@ static this()
|
|||
TypeSuffix argumentsTypeSuffix = new TypeSuffix;
|
||||
argumentsTypeSuffix.array = true;
|
||||
argumentsType.typeSuffixes ~= argptrTypeSuffix;
|
||||
|
||||
builtinSymbols = bSym;
|
||||
arraySymbols = arrSym;
|
||||
assocArraySymbols = asarrSym;
|
||||
aggregateSymbols = aggSym;
|
||||
classSymbols = clSym;
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] builtinSymbols;
|
||||
const(ACSymbol)*[] arraySymbols;
|
||||
const(ACSymbol)*[] assocArraySymbols;
|
||||
const(ACSymbol)*[] aggregateSymbols;
|
||||
const(ACSymbol)*[] classSymbols;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols;
|
||||
RedBlackTree!(ACSymbol*, comparitor, true) classSymbols;
|
||||
Type argptrType;
|
||||
Type argumentsType;
|
||||
|
|
146
astconverter.d
146
astconverter.d
|
@ -122,7 +122,7 @@ final class FirstPass : ASTVisitor
|
|||
dec.parameters, dec.comment);
|
||||
symbol.protection = protection;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(dec.comment);
|
||||
symbol.acSymbol.doc = dec.comment;
|
||||
currentSymbol.addChild(symbol);
|
||||
if (dec.functionBody !is null)
|
||||
{
|
||||
|
@ -183,7 +183,7 @@ final class FirstPass : ASTVisitor
|
|||
symbol.type = t;
|
||||
symbol.protection = protection;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(dec.comment);
|
||||
symbol.acSymbol.doc = dec.comment;
|
||||
currentSymbol.addChild(symbol);
|
||||
}
|
||||
}
|
||||
|
@ -251,12 +251,8 @@ final class FirstPass : ASTVisitor
|
|||
currentSymbol = new SemanticSymbol(null, CompletionKind.moduleName,
|
||||
symbolFile);
|
||||
rootSymbol = currentSymbol;
|
||||
|
||||
currentScope = new Scope();
|
||||
currentScope.startLocation = 0;
|
||||
currentScope.endLocation = size_t.max;
|
||||
currentScope = new Scope(0, size_t.max);
|
||||
moduleScope = currentScope;
|
||||
|
||||
mod.accept(this);
|
||||
}
|
||||
|
||||
|
@ -268,7 +264,7 @@ final class FirstPass : ASTVisitor
|
|||
CompletionKind.enumName, symbolFile, dec.name.index);
|
||||
symbol.type = dec.type;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(dec.comment);
|
||||
symbol.acSymbol.doc = dec.comment;
|
||||
currentSymbol = symbol;
|
||||
if (dec.enumBody !is null)
|
||||
dec.enumBody.accept(this);
|
||||
|
@ -283,7 +279,7 @@ final class FirstPass : ASTVisitor
|
|||
CompletionKind.enumMember, symbolFile, member.name.index);
|
||||
symbol.type = member.type;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(member.comment);
|
||||
symbol.acSymbol.doc = member.comment;
|
||||
currentSymbol.addChild(symbol);
|
||||
}
|
||||
|
||||
|
@ -300,16 +296,14 @@ final class FirstPass : ASTVisitor
|
|||
override void visit(StructBody structBody)
|
||||
{
|
||||
// Log.trace(__FUNCTION__, " ", typeof(structBody).stringof);
|
||||
Scope* s = new Scope;
|
||||
s.startLocation = structBody.startLocation;
|
||||
s.endLocation = structBody.endLocation;
|
||||
Scope* s = new Scope(structBody.startLocation, structBody.endLocation);
|
||||
// Log.trace("Added scope ", s.startLocation, " ", s.endLocation);
|
||||
|
||||
ACSymbol* thisSymbol = new ACSymbol("this", CompletionKind.variableName,
|
||||
currentSymbol.acSymbol);
|
||||
thisSymbol.location = s.startLocation;
|
||||
thisSymbol.symbolFile = symbolFile;
|
||||
currentSymbol.acSymbol.parts ~= thisSymbol;
|
||||
currentSymbol.acSymbol.parts.insert(thisSymbol);
|
||||
|
||||
s.parent = currentScope;
|
||||
currentScope = s;
|
||||
|
@ -353,11 +347,10 @@ final class FirstPass : ASTVisitor
|
|||
override void visit(BlockStatement blockStatement)
|
||||
{
|
||||
// Log.trace(__FUNCTION__, " ", typeof(blockStatement).stringof);
|
||||
Scope* s = new Scope;
|
||||
Scope* s = new Scope(blockStatement.startLocation,
|
||||
blockStatement.endLocation);
|
||||
s.parent = currentScope;
|
||||
currentScope.children ~= s;
|
||||
s.startLocation = blockStatement.startLocation;
|
||||
s.endLocation = blockStatement.endLocation;
|
||||
|
||||
if (currentSymbol.acSymbol.kind == CompletionKind.functionName)
|
||||
{
|
||||
|
@ -395,12 +388,12 @@ private:
|
|||
SemanticSymbol* symbol = new SemanticSymbol(getCached(dec.name.text),
|
||||
kind, symbolFile, dec.name.index);
|
||||
if (kind == CompletionKind.className)
|
||||
symbol.acSymbol.parts ~= classSymbols;
|
||||
symbol.acSymbol.parts.insert(classSymbols[]);
|
||||
else
|
||||
symbol.acSymbol.parts ~= aggregateSymbols;
|
||||
symbol.acSymbol.parts.insert(aggregateSymbols[]);
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.protection = protection;
|
||||
symbol.acSymbol.doc = formatComment(dec.comment);
|
||||
symbol.acSymbol.doc = dec.comment;
|
||||
currentSymbol = symbol;
|
||||
dec.accept(this);
|
||||
currentSymbol = symbol.parent;
|
||||
|
@ -415,7 +408,7 @@ private:
|
|||
processParameters(symbol, null, "this", parameters, doc);
|
||||
symbol.protection = protection;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(doc);
|
||||
symbol.acSymbol.doc = doc;
|
||||
currentSymbol.addChild(symbol);
|
||||
if (functionBody !is null)
|
||||
{
|
||||
|
@ -429,10 +422,10 @@ private:
|
|||
{
|
||||
SemanticSymbol* symbol = new SemanticSymbol("~this",
|
||||
CompletionKind.functionName, symbolFile, location);
|
||||
symbol.acSymbol.callTip = /*formatComment(doc) ~*/ "~this()";
|
||||
symbol.acSymbol.callTip = "~this()";
|
||||
symbol.protection = protection;
|
||||
symbol.parent = currentSymbol;
|
||||
symbol.acSymbol.doc = formatComment(doc);
|
||||
symbol.acSymbol.doc = doc;
|
||||
currentSymbol.addChild(symbol);
|
||||
if (functionBody !is null)
|
||||
{
|
||||
|
@ -483,9 +476,6 @@ private:
|
|||
if (returnType is null)
|
||||
return "%s%s".format(name, parameterString);
|
||||
return "%s %s%s".format(formatNode(returnType), name, parameterString);
|
||||
// if (returnType is null)
|
||||
// return "%s%s%s".format(formatComment(doc), name, parameterString);
|
||||
// return "%s%s %s%s".format(formatComment(doc), formatNode(returnType), name, parameterString);
|
||||
}
|
||||
|
||||
/// Current protection type
|
||||
|
@ -537,11 +527,11 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void assignToScopes(const(ACSymbol)* currentSymbol)
|
||||
void assignToScopes(ACSymbol* currentSymbol)
|
||||
{
|
||||
Scope* s = moduleScope.getScopeByCursor(currentSymbol.location);
|
||||
s.symbols ~= currentSymbol;
|
||||
foreach (part; currentSymbol.parts)
|
||||
s.symbols.insert(currentSymbol);
|
||||
foreach (part; currentSymbol.parts[])
|
||||
assignToScopes(part);
|
||||
}
|
||||
|
||||
|
@ -550,19 +540,21 @@ private:
|
|||
Scope* currentScope)
|
||||
{
|
||||
immutable string firstPart = info.importParts[0];
|
||||
const(ACSymbol)*[] symbols = currentScope.getSymbolsByName(firstPart);
|
||||
ACSymbol*[] symbols = currentScope.getSymbolsByName(firstPart);
|
||||
immutable bool found = symbols.length > 0;
|
||||
const(ACSymbol)* firstSymbol = found
|
||||
ACSymbol* firstSymbol = found
|
||||
? symbols[0] : new ACSymbol(firstPart, CompletionKind.packageName);
|
||||
if (!found)
|
||||
currentScope.symbols ~= firstSymbol;
|
||||
{
|
||||
currentScope.symbols.insert(firstSymbol);
|
||||
}
|
||||
ACSymbol* currentSymbol = cast(ACSymbol*) firstSymbol;
|
||||
foreach (size_t i, string importPart; info.importParts[1 .. $])
|
||||
{
|
||||
symbols = currentSymbol.getPartsByName(importPart);
|
||||
ACSymbol* s = symbols.length > 0
|
||||
? cast(ACSymbol*) symbols[0] : new ACSymbol(importPart, CompletionKind.packageName);
|
||||
currentSymbol.parts ~= s;
|
||||
currentSymbol.parts.insert(s);
|
||||
currentSymbol = s;
|
||||
}
|
||||
currentSymbol.kind = CompletionKind.moduleName;
|
||||
|
@ -573,18 +565,16 @@ private:
|
|||
{
|
||||
foreach (importInfo; currentScope.importInformation)
|
||||
{
|
||||
auto symbols = ModuleCache.getSymbolsInModule(
|
||||
ACSymbol*[] symbols = ModuleCache.getSymbolsInModule(
|
||||
ModuleCache.resolveImportLoctation(importInfo.modulePath));
|
||||
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope);
|
||||
currentScope.symbols ~= moduleSymbol;
|
||||
currentScope.symbols ~= symbols;
|
||||
currentScope.symbols.insert(moduleSymbol);
|
||||
currentScope.symbols.insert(symbols);
|
||||
if (importInfo.importedSymbols.length == 0)
|
||||
{
|
||||
currentScope.symbols ~= symbols;
|
||||
moduleSymbol.parts ~= symbols;
|
||||
if (importInfo.isPublic && currentScope.parent is null)
|
||||
{
|
||||
rootSymbol.acSymbol.parts ~= symbols;
|
||||
rootSymbol.acSymbol.parts.insert(symbols);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -606,17 +596,17 @@ private:
|
|||
s.qualifier = symbol.qualifier;
|
||||
s.location = symbol.location;
|
||||
s.symbolFile = symbol.symbolFile;
|
||||
currentScope.symbols ~= s;
|
||||
moduleSymbol.parts ~= s;
|
||||
currentScope.symbols.insert(s);
|
||||
moduleSymbol.parts.insert(s);
|
||||
if (importInfo.isPublic && currentScope.parent is null)
|
||||
rootSymbol.acSymbol.parts ~= s;
|
||||
rootSymbol.acSymbol.parts.insert(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
moduleSymbol.parts ~= symbol;
|
||||
currentScope.symbols ~= symbol;
|
||||
moduleSymbol.parts.insert(symbol);
|
||||
currentScope.symbols.insert(symbol);
|
||||
if (importInfo.isPublic && currentScope.parent is null)
|
||||
rootSymbol.acSymbol.parts ~= symbol;
|
||||
rootSymbol.acSymbol.parts.insert(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,7 +663,7 @@ private:
|
|||
case memberVariableName:
|
||||
case functionName:
|
||||
case aliasName:
|
||||
const(ACSymbol)* t = resolveType(currentSymbol.type,
|
||||
ACSymbol* t = resolveType(currentSymbol.type,
|
||||
currentSymbol.acSymbol.location);
|
||||
while (t !is null && t.kind == CompletionKind.aliasName)
|
||||
t = t.type;
|
||||
|
@ -691,7 +681,6 @@ private:
|
|||
case mixinTemplateName:
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (child; currentSymbol.children)
|
||||
{
|
||||
thirdPass(child);
|
||||
|
@ -703,7 +692,7 @@ private:
|
|||
// Log.trace("Resolving inheritance for ", currentSymbol.acSymbol.name);
|
||||
outer: foreach (string[] base; currentSymbol.baseClasses)
|
||||
{
|
||||
const(ACSymbol)* baseClass;
|
||||
ACSymbol* baseClass;
|
||||
if (base.length == 0)
|
||||
continue;
|
||||
auto symbols = moduleScope.getSymbolsByNameAndCursor(
|
||||
|
@ -718,7 +707,7 @@ private:
|
|||
continue outer;
|
||||
baseClass = symbols[0];
|
||||
}
|
||||
currentSymbol.acSymbol.parts ~= baseClass.parts;
|
||||
currentSymbol.acSymbol.parts.insert(baseClass.parts[]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,11 +721,11 @@ private:
|
|||
// TODO:
|
||||
}
|
||||
|
||||
const(ACSymbol)* resolveType(Type t, size_t location)
|
||||
ACSymbol* resolveType(Type t, size_t location)
|
||||
{
|
||||
if (t is null) return null;
|
||||
if (t.type2 is null) return null;
|
||||
const(ACSymbol)* s;
|
||||
ACSymbol* s;
|
||||
if (t.type2.builtinType != tok!"")
|
||||
s = convertBuiltinType(t.type2);
|
||||
else if (t.type2.typeConstructor != tok!"")
|
||||
|
@ -780,21 +769,24 @@ private:
|
|||
return strings;
|
||||
}
|
||||
|
||||
static const(ACSymbol)* processSuffix(const(ACSymbol)* symbol, const TypeSuffix suffix)
|
||||
static ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix)
|
||||
{
|
||||
import std.container;
|
||||
if (suffix.star)
|
||||
return symbol;
|
||||
if (suffix.array || suffix.type)
|
||||
{
|
||||
ACSymbol* s = new ACSymbol;
|
||||
s.parts = suffix.array ? arraySymbols : assocArraySymbols;
|
||||
ACSymbol* s = new ACSymbol(null);
|
||||
s.parts = new RedBlackTree!(ACSymbol*, comparitor, true);
|
||||
s.parts.insert(suffix.array ? (cast() arraySymbols)[]
|
||||
: (cast() assocArraySymbols)[]);
|
||||
s.type = symbol;
|
||||
s.qualifier = suffix.array ? SymbolQualifier.array : SymbolQualifier.assocArray;
|
||||
return s;
|
||||
}
|
||||
if (suffix.parameters)
|
||||
{
|
||||
ACSymbol* s = new ACSymbol;
|
||||
ACSymbol* s = new ACSymbol(null);
|
||||
s.type = symbol;
|
||||
s.qualifier = SymbolQualifier.func;
|
||||
s.callTip = suffix.delegateOrFunction.text ~ formatNode(suffix.parameters);
|
||||
|
@ -803,22 +795,21 @@ private:
|
|||
return null;
|
||||
}
|
||||
|
||||
static const(ACSymbol)* convertBuiltinType(const Type2 type2)
|
||||
static ACSymbol* convertBuiltinType(const Type2 type2)
|
||||
{
|
||||
string stringRepresentation = str(type2.builtinType);
|
||||
if (stringRepresentation is null) return null;
|
||||
// TODO: Make this use binary search instead
|
||||
foreach (s; builtinSymbols)
|
||||
if (s.name == stringRepresentation)
|
||||
return s;
|
||||
return null;
|
||||
auto t = cast() builtinSymbols;
|
||||
ACSymbol s = ACSymbol(stringRepresentation);
|
||||
return t.equalRange(&s).front();
|
||||
}
|
||||
|
||||
SemanticSymbol* rootSymbol;
|
||||
Scope* moduleScope;
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] convertAstToSymbols(const(Token)[] tokens, string symbolFile)
|
||||
ACSymbol*[] convertAstToSymbols(const(Token)[] tokens, string symbolFile)
|
||||
{
|
||||
Module m = parseModuleSimple(tokens, symbolFile);
|
||||
|
||||
|
@ -831,7 +822,7 @@ const(ACSymbol)*[] convertAstToSymbols(const(Token)[] tokens, string symbolFile)
|
|||
ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope);
|
||||
third.run();
|
||||
|
||||
return cast(typeof(return)) third.rootSymbol.acSymbol.parts;
|
||||
return third.rootSymbol.acSymbol.parts.array();
|
||||
}
|
||||
|
||||
const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile)
|
||||
|
@ -953,28 +944,6 @@ string formatNode(T)(T node)
|
|||
|
||||
private void doesNothing(string a, size_t b, size_t c, string d, bool e) {}
|
||||
|
||||
string formatComment(string comment)
|
||||
{
|
||||
import std.string;
|
||||
import std.regex;
|
||||
enum tripleSlashRegex = `(?:\t )*///`;
|
||||
enum slashStarRegex = `(?:^/\*\*+)|(?:\n?\s*\*+/$)|(?:(?<=\n)\s*\* ?)`;
|
||||
enum slashPlusRegex = `(?:^/\+\++)|(?:\n?\s*\++/$)|(?:(?<=\n)\s*\+ ?)`;
|
||||
if (comment is null)
|
||||
return null;
|
||||
string re;
|
||||
if (comment[0 .. 3] == "///")
|
||||
re = tripleSlashRegex;
|
||||
else if (comment[1] == '+')
|
||||
re = slashPlusRegex;
|
||||
else
|
||||
re = slashStarRegex;
|
||||
return (comment.replaceAll(regex(re), ""))
|
||||
.replaceFirst(regex("^\n"), "")
|
||||
.replaceAll(regex(`\\`), `\\`)
|
||||
.replaceAll(regex("\n"), `\n`).outdent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy doc comment for getCached
|
||||
*/
|
||||
|
@ -983,14 +952,3 @@ string getCached(string s)
|
|||
return s.length == 0 ? ""
|
||||
: ModuleCache.stringCache.cacheGet(cast(const(ubyte)[]) s);
|
||||
}
|
||||
|
||||
//unittest
|
||||
//{
|
||||
// auto comment1 = "/**\n * This is some text\n */";
|
||||
// auto result1 = formatComment(comment1);
|
||||
// assert (result1 == `This is some text\n\n`, result1);
|
||||
//
|
||||
// auto comment2 = "///some\n///text";
|
||||
// auto result2 = formatComment(comment2);
|
||||
// assert (result2 == `some\ntext\n\n`, result2);
|
||||
//}
|
||||
|
|
|
@ -66,7 +66,7 @@ AutocompleteResponse getDoc(const AutocompleteRequest request)
|
|||
const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin");
|
||||
auto expression = getExpression(beforeTokens);
|
||||
|
||||
const(ACSymbol)*[] symbols = getSymbolsByTokenChain(completionScope, expression,
|
||||
ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, expression,
|
||||
request.cursorPosition, CompletionType.ddoc);
|
||||
|
||||
if (symbols.length == 0)
|
||||
|
@ -79,7 +79,7 @@ AutocompleteResponse getDoc(const AutocompleteRequest request)
|
|||
continue;
|
||||
}
|
||||
Log.trace("Adding doc comment for ", symbol.name, ": ", symbol.doc);
|
||||
response.docComments ~= symbol.doc;
|
||||
response.docComments ~= formatComment(symbol.doc);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ AutocompleteResponse findDeclaration(const AutocompleteRequest request)
|
|||
const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin");
|
||||
auto expression = getExpression(beforeTokens);
|
||||
|
||||
const(ACSymbol)*[] symbols = getSymbolsByTokenChain(completionScope, expression,
|
||||
ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, expression,
|
||||
request.cursorPosition, CompletionType.location);
|
||||
|
||||
if (symbols.length > 0)
|
||||
|
@ -156,12 +156,12 @@ bool shouldSwapWithType(CompletionType completionType, CompletionKind kind,
|
|||
return completionType == CompletionType.identifiers && isInteresting;
|
||||
}
|
||||
|
||||
const(ACSymbol)*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope,
|
||||
ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope,
|
||||
T tokens, size_t cursorPosition, CompletionType completionType)
|
||||
{
|
||||
Log.trace("Getting symbols from token chain", tokens.map!"a.text");
|
||||
// Find the symbol corresponding to the beginning of the chain
|
||||
const(ACSymbol)*[] symbols = completionScope.getSymbolsByNameAndCursor(
|
||||
ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor(
|
||||
tokens[0].text, cursorPosition);
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
|
@ -293,7 +293,7 @@ const(ACSymbol)*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope,
|
|||
skip();
|
||||
Parser p = new Parser();
|
||||
p.setTokens(tokens[h .. i].array());
|
||||
const(ACSymbol)*[] overloads;
|
||||
ACSymbol*[] overloads;
|
||||
if (p.isSliceExpression())
|
||||
overloads = symbols[0].getPartsByName("opSlice");
|
||||
else
|
||||
|
@ -395,7 +395,7 @@ dotCompletion:
|
|||
case tok!"stringLiteral":
|
||||
case tok!"wstringLiteral":
|
||||
case tok!"dstringLiteral":
|
||||
foreach (symbol; arraySymbols)
|
||||
foreach (symbol; (cast() arraySymbols)[])
|
||||
{
|
||||
response.completionKinds ~= symbol.kind;
|
||||
response.completions ~= symbol.name;
|
||||
|
@ -478,7 +478,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
if (tokens.length == 0)
|
||||
return;
|
||||
|
||||
const(ACSymbol)*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||
ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||
cursorPosition, completionType);
|
||||
|
||||
if (symbols.length == 0)
|
||||
|
@ -494,7 +494,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
if (symbols.length == 0)
|
||||
return;
|
||||
}
|
||||
foreach (s; symbols[0].parts.filter!(a => a.name !is null
|
||||
foreach (s; symbols[0].parts[].filter!(a => a.name !is null
|
||||
&& a.name.length > 0 && a.name[0] != '*'
|
||||
&& (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper()))
|
||||
&& !response.completions.canFind(a.name)))
|
||||
|
@ -671,3 +671,36 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
string formatComment(string comment)
|
||||
{
|
||||
import std.string;
|
||||
import std.regex;
|
||||
enum tripleSlashRegex = `(?:\t )*///`;
|
||||
enum slashStarRegex = `(?:^/\*\*+)|(?:\n?\s*\*+/$)|(?:(?<=\n)\s*\* ?)`;
|
||||
enum slashPlusRegex = `(?:^/\+\++)|(?:\n?\s*\++/$)|(?:(?<=\n)\s*\+ ?)`;
|
||||
if (comment is null)
|
||||
return null;
|
||||
string re;
|
||||
if (comment[0 .. 3] == "///")
|
||||
re = tripleSlashRegex;
|
||||
else if (comment[1] == '+')
|
||||
re = slashPlusRegex;
|
||||
else
|
||||
re = slashStarRegex;
|
||||
return (comment.replaceAll(regex(re), ""))
|
||||
.replaceFirst(regex("^\n"), "")
|
||||
.replaceAll(regex(`\\`), `\\`)
|
||||
.replaceAll(regex("\n"), `\n`).outdent();
|
||||
}
|
||||
|
||||
//unittest
|
||||
//{
|
||||
// auto comment1 = "/**\n * This is some text\n */";
|
||||
// auto result1 = formatComment(comment1);
|
||||
// assert (result1 == `This is some text\n\n`, result1);
|
||||
//
|
||||
// auto comment2 = "///some\n///text";
|
||||
// auto result2 = formatComment(comment2);
|
||||
// assert (result2 == `some\ntext\n\n`, result2);
|
||||
//}
|
||||
|
|
|
@ -29,16 +29,23 @@ import std.array;
|
|||
import std.path;
|
||||
import std.algorithm;
|
||||
import std.conv;
|
||||
import std.container;
|
||||
|
||||
import actypes;
|
||||
import semantic;
|
||||
import astconverter;
|
||||
import stupidlog;
|
||||
|
||||
struct CacheEntry
|
||||
bool cacheComparitor(CacheEntry* a, CacheEntry* b) pure nothrow
|
||||
{
|
||||
const(ACSymbol)*[] symbols;
|
||||
return cast(ubyte[]) a.path < cast(ubyte[]) b.path;
|
||||
}
|
||||
|
||||
private struct CacheEntry
|
||||
{
|
||||
ACSymbol*[] symbols;
|
||||
SysTime modificationTime;
|
||||
string path;
|
||||
void opAssign(ref const CacheEntry other)
|
||||
{
|
||||
this.symbols = cast(typeof(symbols)) other.symbols;
|
||||
|
@ -54,6 +61,11 @@ bool existanceCheck(A)(A path)
|
|||
return false;
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
ModuleCache.cache = new RedBlackTree!(CacheEntry*, cacheComparitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches pre-parsed module information.
|
||||
*/
|
||||
|
@ -66,7 +78,7 @@ struct ModuleCache
|
|||
*/
|
||||
static void clear()
|
||||
{
|
||||
cache = cache.init;
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,15 +103,18 @@ struct ModuleCache
|
|||
* Returns:
|
||||
* The symbols defined in the given module
|
||||
*/
|
||||
static const(ACSymbol)*[] getSymbolsInModule(string location)
|
||||
static ACSymbol*[] getSymbolsInModule(string location)
|
||||
{
|
||||
if (location is null)
|
||||
return [];
|
||||
|
||||
if (!needsReparsing(location))
|
||||
{
|
||||
if (location in cache)
|
||||
return cache[location].symbols;
|
||||
CacheEntry e;
|
||||
e.path = location;
|
||||
auto r = cache.equalRange(&e);
|
||||
if (!r.empty)
|
||||
return r.front.symbols;
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -107,25 +122,21 @@ struct ModuleCache
|
|||
|
||||
recursionGuard[location] = true;
|
||||
|
||||
const(ACSymbol)*[] symbols;
|
||||
ACSymbol*[] symbols;
|
||||
try
|
||||
{
|
||||
import core.memory;
|
||||
File f = File(location);
|
||||
ubyte[] source = uninitializedArray!(ubyte[])(cast(size_t)f.size);
|
||||
f.rawRead(source);
|
||||
|
||||
GC.disable();
|
||||
LexerConfig config;
|
||||
config.fileName = location;
|
||||
StringCache* cache = new StringCache(StringCache.defaultBucketCount);
|
||||
auto tokens = source.byToken(config, cache).array();
|
||||
symbols = convertAstToSymbols(tokens, location);
|
||||
|
||||
// Parsing allocates a lot of AST nodes. We can greatly reduce the
|
||||
// program's idle memory use by running the GC here.
|
||||
// TODO: Re-visit this when D gets a precise GC.
|
||||
import core.memory;
|
||||
GC.collect();
|
||||
GC.minimize();
|
||||
GC.enable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -135,8 +146,8 @@ struct ModuleCache
|
|||
SysTime access;
|
||||
SysTime modification;
|
||||
getTimes(location, access, modification);
|
||||
CacheEntry c = CacheEntry(symbols, modification);
|
||||
cache[location] = c;
|
||||
CacheEntry* c = new CacheEntry(symbols, modification, location);
|
||||
cache.insert(c);
|
||||
recursionGuard[location] = false;
|
||||
return symbols;
|
||||
}
|
||||
|
@ -202,16 +213,21 @@ private:
|
|||
return true;
|
||||
if (recursionGuard[mod])
|
||||
return false;
|
||||
if (!exists(mod) || mod !in cache)
|
||||
if (!exists(mod))
|
||||
return true;
|
||||
CacheEntry e;
|
||||
e.path = mod;
|
||||
auto r = cache.equalRange(&e);
|
||||
if (r.empty)
|
||||
return true;
|
||||
SysTime access;
|
||||
SysTime modification;
|
||||
getTimes(mod, access, modification);
|
||||
return cache[mod].modificationTime != modification;
|
||||
return r.front.modificationTime != modification;
|
||||
}
|
||||
|
||||
// Mapping of file paths to their cached symbols.
|
||||
static CacheEntry[string] cache;
|
||||
static RedBlackTree!(CacheEntry*, cacheComparitor) cache;
|
||||
|
||||
static bool[string] recursionGuard;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
void addChild(SemanticSymbol* child)
|
||||
{
|
||||
children ~= child;
|
||||
acSymbol.parts ~= child.acSymbol;
|
||||
acSymbol.parts.insert(child.acSymbol);
|
||||
}
|
||||
|
||||
/// Autocompletion symbol
|
||||
|
|
Loading…
Reference in New Issue