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