Pull symbol resolution code out into dsymbol folder
This commit is contained in:
parent
4cc67f0ea2
commit
ae83e447a4
|
@ -117,7 +117,7 @@ A line containing the string "calltips", followed by zero or more lines, each
|
|||
containing a call tip for an overload of the given function.
|
||||
##### Example output
|
||||
calltips
|
||||
ACSymbol findSymbolInCurrentScope(size_t cursorPosition, string name)
|
||||
Symbol findSymbolInCurrentScope(size_t cursorPosition, string name)
|
||||
|
||||
## Doc comment display
|
||||
```dcd-client --doc -c 4298```
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
module dsymbol.builtin.names;
|
||||
|
||||
import std.d.lexer;
|
||||
import dsymbol.string_interning;
|
||||
|
||||
package immutable(istring[24]) builtinTypeNames;
|
||||
|
||||
/// Constants for buit-in or dummy symbol names
|
||||
immutable istring IMPORT_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring WITH_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring CONSTRUCTOR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DESTRUCTOR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ARGPTR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ARGUMENTS_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring THIS_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring SUPER_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring UNITTEST_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DOUBLE_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring FLOAT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IDOUBLE_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IFLOAT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring INT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring LONG_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring REAL_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IREAL_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring UINT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ULONG_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring CHAR_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DSTRING_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring STRING_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring WSTRING_LITERAL_SYMBOL_NAME;
|
||||
|
||||
/**
|
||||
* Translates the IDs for built-in types into an interned string.
|
||||
*/
|
||||
istring getBuiltinTypeName(IdType id) nothrow pure @nogc @safe
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case tok!"int": return builtinTypeNames[0];
|
||||
case tok!"uint": return builtinTypeNames[1];
|
||||
case tok!"double": return builtinTypeNames[2];
|
||||
case tok!"idouble": return builtinTypeNames[3];
|
||||
case tok!"float": return builtinTypeNames[4];
|
||||
case tok!"ifloat": return builtinTypeNames[5];
|
||||
case tok!"short": return builtinTypeNames[6];
|
||||
case tok!"ushort": return builtinTypeNames[7];
|
||||
case tok!"long": return builtinTypeNames[8];
|
||||
case tok!"ulong": return builtinTypeNames[9];
|
||||
case tok!"char": return builtinTypeNames[10];
|
||||
case tok!"wchar": return builtinTypeNames[11];
|
||||
case tok!"dchar": return builtinTypeNames[12];
|
||||
case tok!"bool": return builtinTypeNames[13];
|
||||
case tok!"void": return builtinTypeNames[14];
|
||||
case tok!"cent": return builtinTypeNames[15];
|
||||
case tok!"ucent": return builtinTypeNames[16];
|
||||
case tok!"real": return builtinTypeNames[17];
|
||||
case tok!"ireal": return builtinTypeNames[18];
|
||||
case tok!"byte": return builtinTypeNames[19];
|
||||
case tok!"ubyte": return builtinTypeNames[20];
|
||||
case tok!"cdouble": return builtinTypeNames[21];
|
||||
case tok!"cfloat": return builtinTypeNames[22];
|
||||
case tok!"creal": return builtinTypeNames[23];
|
||||
default: assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes builtin types and the various properties of builtin types
|
||||
*/
|
||||
static this()
|
||||
{
|
||||
builtinTypeNames[0] = internString("int");
|
||||
builtinTypeNames[1] = internString("uint");
|
||||
builtinTypeNames[2] = internString("double");
|
||||
builtinTypeNames[3] = internString("idouble");
|
||||
builtinTypeNames[4] = internString("float");
|
||||
builtinTypeNames[5] = internString("ifloat");
|
||||
builtinTypeNames[6] = internString("short");
|
||||
builtinTypeNames[7] = internString("ushort");
|
||||
builtinTypeNames[8] = internString("long");
|
||||
builtinTypeNames[9] = internString("ulong");
|
||||
builtinTypeNames[10] = internString("char");
|
||||
builtinTypeNames[11] = internString("wchar");
|
||||
builtinTypeNames[12] = internString("dchar");
|
||||
builtinTypeNames[13] = internString("bool");
|
||||
builtinTypeNames[14] = internString("void");
|
||||
builtinTypeNames[15] = internString("cent");
|
||||
builtinTypeNames[16] = internString("ucent");
|
||||
builtinTypeNames[17] = internString("real");
|
||||
builtinTypeNames[18] = internString("ireal");
|
||||
builtinTypeNames[19] = internString("byte");
|
||||
builtinTypeNames[20] = internString("ubyte");
|
||||
builtinTypeNames[21] = internString("cdouble");
|
||||
builtinTypeNames[22] = internString("cfloat");
|
||||
builtinTypeNames[23] = internString("creal");
|
||||
|
||||
IMPORT_SYMBOL_NAME = internString("public");
|
||||
WITH_SYMBOL_NAME = internString("with");
|
||||
CONSTRUCTOR_SYMBOL_NAME = internString("*constructor*");
|
||||
DESTRUCTOR_SYMBOL_NAME = internString("~this");
|
||||
ARGPTR_SYMBOL_NAME = internString("_argptr");
|
||||
ARGUMENTS_SYMBOL_NAME = internString("_arguments");
|
||||
THIS_SYMBOL_NAME = internString("this");
|
||||
SUPER_SYMBOL_NAME = internString("super");
|
||||
UNITTEST_SYMBOL_NAME = internString("*unittest*");
|
||||
DOUBLE_LITERAL_SYMBOL_NAME = internString("*double");
|
||||
FLOAT_LITERAL_SYMBOL_NAME = internString("*float");
|
||||
IDOUBLE_LITERAL_SYMBOL_NAME = internString("*idouble");
|
||||
IFLOAT_LITERAL_SYMBOL_NAME = internString("*ifloat");
|
||||
INT_LITERAL_SYMBOL_NAME = internString("*int");
|
||||
LONG_LITERAL_SYMBOL_NAME = internString("*long");
|
||||
REAL_LITERAL_SYMBOL_NAME = internString("*real");
|
||||
IREAL_LITERAL_SYMBOL_NAME = internString("*ireal");
|
||||
UINT_LITERAL_SYMBOL_NAME = internString("*uint");
|
||||
ULONG_LITERAL_SYMBOL_NAME = internString("*ulong");
|
||||
CHAR_LITERAL_SYMBOL_NAME = internString("*char");
|
||||
DSTRING_LITERAL_SYMBOL_NAME = internString("*dstring");
|
||||
STRING_LITERAL_SYMBOL_NAME = internString("*string");
|
||||
WSTRING_LITERAL_SYMBOL_NAME = internString("*wstring");
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
module dsymbol.builtin.symbols;
|
||||
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.builtin.names;
|
||||
import dsymbol.string_interning;
|
||||
import containers.ttree;
|
||||
import std.allocator;
|
||||
import std.d.lexer;
|
||||
|
||||
/**
|
||||
* Symbols for the built in types
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) builtinSymbols;
|
||||
|
||||
/**
|
||||
* Array properties
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) arraySymbols;
|
||||
|
||||
/**
|
||||
* Associative array properties
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) assocArraySymbols;
|
||||
|
||||
/**
|
||||
* Struct, enum, union, class, and interface properties
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) aggregateSymbols;
|
||||
|
||||
/**
|
||||
* Class properties
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) classSymbols;
|
||||
|
||||
static this()
|
||||
{
|
||||
auto bool_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[13], CompletionKind.keyword);
|
||||
auto int_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[0], CompletionKind.keyword);
|
||||
auto long_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[8], CompletionKind.keyword);
|
||||
auto byte_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[19], CompletionKind.keyword);
|
||||
auto char_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[10], CompletionKind.keyword);
|
||||
auto dchar_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[12], CompletionKind.keyword);
|
||||
auto short_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[6], CompletionKind.keyword);
|
||||
auto ubyte_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[20], CompletionKind.keyword);
|
||||
auto uint_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[1], CompletionKind.keyword);
|
||||
auto ulong_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[9], CompletionKind.keyword);
|
||||
auto ushort_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[7], CompletionKind.keyword);
|
||||
auto wchar_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[11], CompletionKind.keyword);
|
||||
|
||||
auto alignof_ = allocate!DSymbol(Mallocator.it, internString("alignof"), CompletionKind.keyword);
|
||||
auto mangleof_ = allocate!DSymbol(Mallocator.it, internString("mangleof"), CompletionKind.keyword);
|
||||
auto sizeof_ = allocate!DSymbol(Mallocator.it, internString("sizeof"), CompletionKind.keyword);
|
||||
auto stringof_ = allocate!DSymbol(Mallocator.it, internString("init"), CompletionKind.keyword);
|
||||
auto init = allocate!DSymbol(Mallocator.it, internString("stringof"), CompletionKind.keyword);
|
||||
|
||||
arraySymbols.insert(alignof_);
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword));
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("idup"), CompletionKind.keyword));
|
||||
arraySymbols.insert(init);
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_));
|
||||
arraySymbols.insert(mangleof_);
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("ptr"), CompletionKind.keyword));
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("reverse"), CompletionKind.keyword));
|
||||
arraySymbols.insert(sizeof_);
|
||||
arraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("sort"), CompletionKind.keyword));
|
||||
arraySymbols.insert(stringof_);
|
||||
|
||||
assocArraySymbols.insert(alignof_);
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("byKey"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("byValue"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("get"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("init"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("keys"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_));
|
||||
assocArraySymbols.insert(mangleof_);
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("rehash"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(sizeof_);
|
||||
assocArraySymbols.insert(stringof_);
|
||||
assocArraySymbols.insert(init);
|
||||
assocArraySymbols.insert(allocate!DSymbol(Mallocator.it, internString("values"), CompletionKind.keyword));
|
||||
|
||||
DSymbol*[11] integralTypeArray;
|
||||
integralTypeArray[0] = bool_;
|
||||
integralTypeArray[1] = int_;
|
||||
integralTypeArray[2] = long_;
|
||||
integralTypeArray[3] = byte_;
|
||||
integralTypeArray[4] = char_;
|
||||
integralTypeArray[4] = dchar_;
|
||||
integralTypeArray[5] = short_;
|
||||
integralTypeArray[6] = ubyte_;
|
||||
integralTypeArray[7] = uint_;
|
||||
integralTypeArray[8] = ulong_;
|
||||
integralTypeArray[9] = ushort_;
|
||||
integralTypeArray[10] = wchar_;
|
||||
|
||||
foreach (s; integralTypeArray)
|
||||
{
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("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_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[21], CompletionKind.keyword);
|
||||
auto cent_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[15], CompletionKind.keyword);
|
||||
auto cfloat_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[22], CompletionKind.keyword);
|
||||
auto creal_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[23], CompletionKind.keyword);
|
||||
auto double_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[2], CompletionKind.keyword);
|
||||
auto float_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[4], CompletionKind.keyword);
|
||||
auto idouble_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[3], CompletionKind.keyword);
|
||||
auto ifloat_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[5], CompletionKind.keyword);
|
||||
auto ireal_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[18], CompletionKind.keyword);
|
||||
auto real_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[17], CompletionKind.keyword);
|
||||
auto ucent_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[16], CompletionKind.keyword);
|
||||
|
||||
DSymbol*[11] floatTypeArray;
|
||||
floatTypeArray[0] = cdouble_;
|
||||
floatTypeArray[1] = cent_;
|
||||
floatTypeArray[2] = cfloat_;
|
||||
floatTypeArray[3] = creal_;
|
||||
floatTypeArray[4] = double_;
|
||||
floatTypeArray[5] = float_;
|
||||
floatTypeArray[6] = idouble_;
|
||||
floatTypeArray[7] = ifloat_;
|
||||
floatTypeArray[8] = ireal_;
|
||||
floatTypeArray[9] = real_;
|
||||
floatTypeArray[10] = ucent_;
|
||||
|
||||
foreach (s; floatTypeArray)
|
||||
{
|
||||
s.parts.insert(alignof_);
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("dig"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("epsilon"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("infinity"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s));
|
||||
s.parts.insert(mangleof_);
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("mant_dig"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("max"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("max_10_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("max_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("min_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("min_10_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("min_normal"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!DSymbol(Mallocator.it, internString("nan"), CompletionKind.keyword, s));
|
||||
s.parts.insert(sizeof_);
|
||||
s.parts.insert(stringof_);
|
||||
}
|
||||
|
||||
aggregateSymbols.insert(allocate!DSymbol(Mallocator.it, internString("tupleof"), CompletionKind.keyword));
|
||||
aggregateSymbols.insert(mangleof_);
|
||||
aggregateSymbols.insert(alignof_);
|
||||
aggregateSymbols.insert(sizeof_);
|
||||
aggregateSymbols.insert(stringof_);
|
||||
aggregateSymbols.insert(init);
|
||||
|
||||
classSymbols.insert(allocate!DSymbol(Mallocator.it, internString("classInfo"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!DSymbol(Mallocator.it, internString("tupleof"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!DSymbol(Mallocator.it, internString("__vptr"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!DSymbol(Mallocator.it, internString("__monitor"), CompletionKind.variableName));
|
||||
classSymbols.insert(mangleof_);
|
||||
classSymbols.insert(alignof_);
|
||||
classSymbols.insert(sizeof_);
|
||||
classSymbols.insert(stringof_);
|
||||
classSymbols.insert(init);
|
||||
|
||||
ireal_.parts.insert(allocate!DSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(allocate!DSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(allocate!DSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, double_));
|
||||
ireal_.parts.insert(allocate!DSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(allocate!DSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(allocate!DSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, double_));
|
||||
|
||||
auto void_ = allocate!DSymbol(Mallocator.it, builtinTypeNames[14], CompletionKind.keyword);
|
||||
|
||||
builtinSymbols.insert(bool_);
|
||||
bool_.type = bool_;
|
||||
builtinSymbols.insert(int_);
|
||||
int_.type = int_;
|
||||
builtinSymbols.insert(long_);
|
||||
long_.type = long_;
|
||||
builtinSymbols.insert(byte_);
|
||||
byte_.type = byte_;
|
||||
builtinSymbols.insert(char_);
|
||||
char_.type = char_;
|
||||
builtinSymbols.insert(dchar_);
|
||||
dchar_.type = dchar_;
|
||||
builtinSymbols.insert(short_);
|
||||
short_.type = short_;
|
||||
builtinSymbols.insert(ubyte_);
|
||||
ubyte_.type = ubyte_;
|
||||
builtinSymbols.insert(uint_);
|
||||
uint_.type = uint_;
|
||||
builtinSymbols.insert(ulong_);
|
||||
ulong_.type = ulong_;
|
||||
builtinSymbols.insert(ushort_);
|
||||
ushort_.type = ushort_;
|
||||
builtinSymbols.insert(wchar_);
|
||||
wchar_.type = wchar_;
|
||||
builtinSymbols.insert(cdouble_);
|
||||
cdouble_.type = cdouble_;
|
||||
builtinSymbols.insert(cent_);
|
||||
cent_.type = cent_;
|
||||
builtinSymbols.insert(cfloat_);
|
||||
cfloat_.type = cfloat_;
|
||||
builtinSymbols.insert(creal_);
|
||||
creal_.type = creal_;
|
||||
builtinSymbols.insert(double_);
|
||||
double_.type = double_;
|
||||
builtinSymbols.insert(float_);
|
||||
float_.type = float_;
|
||||
builtinSymbols.insert(idouble_);
|
||||
idouble_.type = idouble_;
|
||||
builtinSymbols.insert(ifloat_);
|
||||
ifloat_.type = ifloat_;
|
||||
builtinSymbols.insert(ireal_);
|
||||
ireal_.type = ireal_;
|
||||
builtinSymbols.insert(real_);
|
||||
real_.type = real_;
|
||||
builtinSymbols.insert(ucent_);
|
||||
ucent_.type = ucent_;
|
||||
builtinSymbols.insert(void_);
|
||||
void_.type = void_;
|
||||
|
||||
|
||||
foreach (s; ["__DATE__", "__EOF__", "__TIME__", "__TIMESTAMP__", "__VENDOR__",
|
||||
"__VERSION__", "__FUNCTION__", "__PRETTY_FUNCTION__", "__MODULE__",
|
||||
"__FILE__", "__LINE__"])
|
||||
builtinSymbols.insert(allocate!DSymbol(Mallocator.it, internString(s), CompletionKind.keyword));
|
||||
}
|
|
@ -16,19 +16,20 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module conversion.astconverter;
|
||||
module dsymbol.conversion.astconverter;
|
||||
|
||||
import actypes;
|
||||
import conversion.first;
|
||||
import conversion.second;
|
||||
import conversion.third;
|
||||
import dsymbol.conversion.first;
|
||||
import dsymbol.conversion.second;
|
||||
import dsymbol.conversion.third;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.string_interning;
|
||||
import dsymbol.symbol;
|
||||
import memory.allocators;
|
||||
import std.allocator;
|
||||
import std.d.ast;
|
||||
import std.d.lexer;
|
||||
import std.d.parser;
|
||||
import std.typecons;
|
||||
import string_interning;
|
||||
|
||||
/**
|
||||
* Used by autocompletion.
|
|
@ -16,21 +16,25 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module conversion.first;
|
||||
module dsymbol.conversion.first;
|
||||
|
||||
import actypes;
|
||||
import std.d.formatter;
|
||||
import std.allocator;
|
||||
import containers.unrolledlist;
|
||||
import dsymbol.builtin.names;
|
||||
import dsymbol.builtin.symbols;
|
||||
import dsymbol.import_;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.semantic;
|
||||
import dsymbol.semantic;
|
||||
import dsymbol.string_interning;
|
||||
import dsymbol.symbol;
|
||||
import memory.allocators;
|
||||
import memory.appender;
|
||||
import messages;
|
||||
import semantic;
|
||||
import std.allocator;
|
||||
import std.d.ast;
|
||||
import std.d.formatter;
|
||||
import std.d.lexer;
|
||||
import std.typecons;
|
||||
import stupidlog;
|
||||
import containers.unrolledlist;
|
||||
import string_interning;
|
||||
|
||||
/**
|
||||
* First Pass handles the following:
|
||||
|
@ -325,7 +329,7 @@ final class FirstPass : ASTVisitor
|
|||
Scope* s = allocate!Scope(semanticAllocator, structBody.startLocation, structBody.endLocation);
|
||||
// Log.trace("Added scope ", s.startLocation, " ", s.endLocation);
|
||||
|
||||
ACSymbol* thisSymbol = allocate!ACSymbol(symbolAllocator,
|
||||
DSymbol* thisSymbol = allocate!DSymbol(symbolAllocator,
|
||||
THIS_SYMBOL_NAME, CompletionKind.variableName, currentSymbol.acSymbol);
|
||||
thisSymbol.location = s.startLocation;
|
||||
thisSymbol.symbolFile = symbolFile;
|
||||
|
@ -705,7 +709,7 @@ private:
|
|||
}
|
||||
body
|
||||
{
|
||||
ACSymbol* acSymbol = allocate!ACSymbol(symbolAllocator, name, kind);
|
||||
DSymbol* acSymbol = allocate!DSymbol(symbolAllocator, name, kind);
|
||||
acSymbol.location = location;
|
||||
acSymbol.symbolFile = symbolFile;
|
||||
symbolsAllocated++;
|
|
@ -16,15 +16,17 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module conversion.second;
|
||||
module dsymbol.conversion.second;
|
||||
|
||||
import conversion.first;
|
||||
import actypes;
|
||||
import semantic;
|
||||
import messages;
|
||||
import dsymbol.conversion.first;
|
||||
import dsymbol.semantic;
|
||||
import dsymbol.string_interning;
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.import_;
|
||||
import dsymbol.builtin.symbols;
|
||||
import dsymbol.builtin.names;
|
||||
import std.allocator;
|
||||
import stupidlog;
|
||||
import string_interning;
|
||||
|
||||
/**
|
||||
* Second pass handles the following:
|
||||
|
@ -79,7 +81,7 @@ private:
|
|||
/**
|
||||
* Assigns symbols to scopes based on their location.
|
||||
*/
|
||||
void assignToScopes(ACSymbol* currentSymbol)
|
||||
void assignToScopes(DSymbol* currentSymbol)
|
||||
{
|
||||
if (currentSymbol.kind != CompletionKind.moduleName)
|
||||
{
|
||||
|
@ -102,8 +104,8 @@ private:
|
|||
* Returns: A package symbol that can be used for auto-completing qualified
|
||||
* symbol names.
|
||||
*/
|
||||
ACSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope,
|
||||
ACSymbol* moduleSymbol)
|
||||
DSymbol* createImportSymbols(ImportInformation* info, Scope* currentScope,
|
||||
DSymbol* moduleSymbol)
|
||||
in
|
||||
{
|
||||
assert (info !is null);
|
||||
|
@ -116,14 +118,14 @@ private:
|
|||
immutable istring firstPart = info.importParts[].front;
|
||||
|
||||
// top-level package symbol
|
||||
ACSymbol* firstSymbol = void;
|
||||
ACSymbol*[] symbols = currentScope.getSymbolsByName(firstPart);
|
||||
DSymbol* firstSymbol = void;
|
||||
DSymbol*[] symbols = currentScope.getSymbolsByName(firstPart);
|
||||
if (symbols.length > 0)
|
||||
firstSymbol = symbols[0];
|
||||
else
|
||||
firstSymbol = allocate!ACSymbol(symbolAllocator, firstPart,
|
||||
firstSymbol = allocate!DSymbol(symbolAllocator, firstPart,
|
||||
CompletionKind.packageName);
|
||||
ACSymbol* currentSymbol = firstSymbol;
|
||||
DSymbol* currentSymbol = firstSymbol;
|
||||
size_t i = 0;
|
||||
foreach (importPart; info.importParts[])
|
||||
{
|
||||
|
@ -133,7 +135,7 @@ private:
|
|||
if (i + 2 >= info.importParts.length) // Skip the last item as it's the module name
|
||||
break;
|
||||
symbols = currentSymbol.getPartsByName(importPart);
|
||||
ACSymbol* s = null;
|
||||
DSymbol* s = null;
|
||||
foreach (sy; symbols)
|
||||
{
|
||||
if (sy.kind == CompletionKind.packageName)
|
||||
|
@ -143,7 +145,7 @@ private:
|
|||
}
|
||||
}
|
||||
if (s is null)
|
||||
s = allocate!ACSymbol(symbolAllocator, importPart, CompletionKind.packageName);
|
||||
s = allocate!DSymbol(symbolAllocator, importPart, CompletionKind.packageName);
|
||||
currentSymbol.parts.insert(s);
|
||||
currentSymbol = s;
|
||||
}
|
||||
|
@ -157,25 +159,25 @@ private:
|
|||
*/
|
||||
void resolveImports(Scope* currentScope)
|
||||
{
|
||||
import modulecache : ModuleCache;
|
||||
import dsymbol.modulecache : ModuleCache;
|
||||
foreach (importInfo; currentScope.importInformation[])
|
||||
{
|
||||
// Get symbol for the imported module
|
||||
immutable string moduleAbsPath = ModuleCache.resolveImportLoctation(
|
||||
importInfo.modulePath);
|
||||
ACSymbol* symbol = moduleAbsPath is null ? null
|
||||
DSymbol* symbol = moduleAbsPath is null ? null
|
||||
: ModuleCache.getModuleSymbol(moduleAbsPath);
|
||||
if (symbol is null)
|
||||
continue;
|
||||
|
||||
ACSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol);
|
||||
DSymbol* moduleSymbol = createImportSymbols(importInfo, currentScope, symbol);
|
||||
|
||||
// if this is a selective import
|
||||
if (importInfo.importedSymbols.length == 0)
|
||||
{
|
||||
// if this import is at module scope
|
||||
if (importInfo.isPublic && currentScope.parent is null)
|
||||
rootSymbol.acSymbol.parts.insert(allocate!ACSymbol(symbolAllocator,
|
||||
rootSymbol.acSymbol.parts.insert(allocate!DSymbol(symbolAllocator,
|
||||
IMPORT_SYMBOL_NAME, CompletionKind.importSymbol, symbol));
|
||||
else
|
||||
currentScope.symbols.insert(symbol.parts[]);
|
||||
|
@ -186,8 +188,8 @@ private:
|
|||
{
|
||||
// Handle selective and renamed imports
|
||||
|
||||
ACSymbol needle = ACSymbol(tup[1]);
|
||||
ACSymbol* sym;
|
||||
DSymbol needle = DSymbol(tup[1]);
|
||||
DSymbol* sym;
|
||||
auto r = symbol.parts.equalRange(&needle);
|
||||
if (r.empty) foreach (sy; symbol.parts[])
|
||||
{
|
||||
|
@ -204,7 +206,7 @@ private:
|
|||
continue;
|
||||
if (tup[0] !is null)
|
||||
{
|
||||
ACSymbol* s = allocate!ACSymbol(symbolAllocator, tup[0],
|
||||
DSymbol* s = allocate!DSymbol(symbolAllocator, tup[0],
|
||||
sym.kind, sym.type);
|
||||
s.parts.insert(sym.parts[]);
|
||||
s.callTip = sym.callTip;
|
|
@ -16,17 +16,19 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module conversion.third;
|
||||
module dsymbol.conversion.third;
|
||||
|
||||
import std.d.ast;
|
||||
import std.d.lexer;
|
||||
import conversion.second;
|
||||
import semantic;
|
||||
import actypes;
|
||||
import dsymbol.conversion.second;
|
||||
import dsymbol.semantic;
|
||||
import dsymbol.string_interning;
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.builtin.names;
|
||||
import dsymbol.builtin.symbols;
|
||||
import messages;
|
||||
import std.allocator;
|
||||
import string_interning;
|
||||
import stupidlog;
|
||||
import std.d.ast;
|
||||
import std.d.lexer;
|
||||
|
||||
/**
|
||||
* Third pass handles the following:
|
||||
|
@ -73,13 +75,13 @@ public:
|
|||
Scope* moduleScope;
|
||||
|
||||
/**
|
||||
* The Symbol allocator
|
||||
* The symbol allocator
|
||||
*/
|
||||
CAllocator symbolAllocator;
|
||||
|
||||
private:
|
||||
|
||||
bool shouldFollowtype(const ACSymbol* t, const SemanticSymbol* currentSymbol)
|
||||
bool shouldFollowtype(const DSymbol* t, const SemanticSymbol* currentSymbol)
|
||||
{
|
||||
if (t is null)
|
||||
return false;
|
||||
|
@ -107,7 +109,7 @@ private:
|
|||
case memberVariableName:
|
||||
case functionName:
|
||||
case aliasName:
|
||||
ACSymbol* t = resolveType(currentSymbol.initializer,
|
||||
DSymbol* t = resolveType(currentSymbol.initializer,
|
||||
currentSymbol.type, currentSymbol.acSymbol.location);
|
||||
while (shouldFollowtype(t, currentSymbol))
|
||||
t = t.type;
|
||||
|
@ -155,7 +157,7 @@ private:
|
|||
import std.algorithm : filter;
|
||||
outer: foreach (istring[] base; currentSymbol.baseClasses)
|
||||
{
|
||||
ACSymbol* baseClass;
|
||||
DSymbol* baseClass;
|
||||
if (base.length == 0)
|
||||
continue;
|
||||
auto symbolScope = moduleScope.getScopeByCursor(currentSymbol.acSymbol.location);
|
||||
|
@ -177,7 +179,7 @@ private:
|
|||
a => a.name.ptr != CONSTRUCTOR_SYMBOL_NAME.ptr));
|
||||
if (baseClass.kind == CompletionKind.className)
|
||||
{
|
||||
auto s = allocate!ACSymbol(symbolAllocator,
|
||||
auto s = allocate!DSymbol(symbolAllocator,
|
||||
SUPER_SYMBOL_NAME, CompletionKind.variableName, baseClass);
|
||||
symbolScope.symbols.insert(s);
|
||||
}
|
||||
|
@ -191,7 +193,7 @@ private:
|
|||
auto parts = currentSymbol.acSymbol.getPartsByName(aliasThis);
|
||||
if (parts.length == 0 || parts[0].type is null)
|
||||
continue;
|
||||
ACSymbol* s = allocate!ACSymbol(symbolAllocator, IMPORT_SYMBOL_NAME,
|
||||
DSymbol* s = allocate!DSymbol(symbolAllocator, IMPORT_SYMBOL_NAME,
|
||||
CompletionKind.importSymbol);
|
||||
s.type = parts[0].type;
|
||||
currentSymbol.acSymbol.parts.insert(s);
|
||||
|
@ -222,7 +224,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
ACSymbol* resolveInitializerType(I)(ref const I initializer, size_t location)
|
||||
DSymbol* resolveInitializerType(I)(ref const I initializer, size_t location)
|
||||
{
|
||||
if (initializer.empty)
|
||||
return null;
|
||||
|
@ -256,7 +258,7 @@ private:
|
|||
s = s.type;
|
||||
else
|
||||
{
|
||||
ACSymbol*[] f = s.getPartsByName(internString("front"));
|
||||
DSymbol*[] f = s.getPartsByName(internString("front"));
|
||||
if (f.length > 0)
|
||||
s = f[0].type;
|
||||
else
|
||||
|
@ -280,13 +282,13 @@ private:
|
|||
return s;
|
||||
}
|
||||
|
||||
ACSymbol* resolveType(I)(ref const I initializer, const Type t, size_t location)
|
||||
DSymbol* resolveType(I)(ref const I initializer, const Type t, size_t location)
|
||||
{
|
||||
if (t is null)
|
||||
return resolveInitializerType(initializer, location);
|
||||
if (t.type2 is null)
|
||||
return null;
|
||||
ACSymbol* s;
|
||||
DSymbol* s;
|
||||
if (t.type2.builtinType != tok!"")
|
||||
s = convertBuiltinType(t.type2);
|
||||
else if (t.type2.typeConstructor != tok!"")
|
||||
|
@ -333,13 +335,13 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
ACSymbol* processSuffix(ACSymbol* symbol, const TypeSuffix suffix, const Type t)
|
||||
DSymbol* processSuffix(DSymbol* symbol, const TypeSuffix suffix, const Type t)
|
||||
{
|
||||
if (suffix.star.type != tok!"")
|
||||
return symbol;
|
||||
if (suffix.array || suffix.type)
|
||||
{
|
||||
ACSymbol* s = allocate!ACSymbol(symbolAllocator, istring(null));
|
||||
DSymbol* s = allocate!DSymbol(symbolAllocator, istring(null));
|
||||
s.parts.insert(suffix.array ? arraySymbols[]
|
||||
: assocArraySymbols[]);
|
||||
s.type = symbol;
|
||||
|
@ -348,10 +350,10 @@ private:
|
|||
}
|
||||
if (suffix.parameters)
|
||||
{
|
||||
import conversion.first : formatNode;
|
||||
import dsymbol.conversion.first : formatNode;
|
||||
import memory.allocators : QuickAllocator;
|
||||
import memory.appender : Appender;
|
||||
ACSymbol* s = allocate!ACSymbol(symbolAllocator, istring(null));
|
||||
DSymbol* s = allocate!DSymbol(symbolAllocator, istring(null));
|
||||
s.type = symbol;
|
||||
s.qualifier = SymbolQualifier.func;
|
||||
QuickAllocator!1024 q;
|
||||
|
@ -364,10 +366,10 @@ private:
|
|||
return null;
|
||||
}
|
||||
|
||||
ACSymbol* convertBuiltinType(const Type2 type2)
|
||||
DSymbol* convertBuiltinType(const Type2 type2)
|
||||
{
|
||||
istring stringRepresentation = getBuiltinTypeName(type2.builtinType);
|
||||
ACSymbol s = ACSymbol(stringRepresentation);
|
||||
DSymbol s = DSymbol(stringRepresentation);
|
||||
assert(s.name.ptr == stringRepresentation.ptr);
|
||||
return builtinSymbols.equalRange(&s).front();
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module dsymbol.import_;
|
||||
|
||||
import containers.unrolledlist;
|
||||
import dsymbol.string_interning;
|
||||
import std.typecons;
|
||||
|
||||
/**
|
||||
* Import information
|
||||
*/
|
||||
struct ImportInformation
|
||||
{
|
||||
/// Import statement parts
|
||||
UnrolledList!istring importParts;
|
||||
/// module relative path
|
||||
istring modulePath;
|
||||
/// symbols to import from this module
|
||||
UnrolledList!(Tuple!(istring, istring), false) importedSymbols;
|
||||
/// true if the import is public
|
||||
bool isPublic;
|
||||
}
|
|
@ -16,8 +16,20 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module modulecache;
|
||||
module dsymbol.modulecache;
|
||||
|
||||
import containers.dynamicarray;
|
||||
import containers.hashset;
|
||||
import containers.ttree;
|
||||
import containers.unrolledlist;
|
||||
import dsymbol.conversion.astconverter;
|
||||
import dsymbol.conversion.first;
|
||||
import dsymbol.conversion.second;
|
||||
import dsymbol.conversion.third;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.semantic;
|
||||
import dsymbol.symbol;
|
||||
import memory.allocators;
|
||||
import std.algorithm;
|
||||
import std.allocator;
|
||||
import std.conv;
|
||||
|
@ -25,27 +37,16 @@ import std.d.ast;
|
|||
import std.datetime;
|
||||
import std.d.lexer;
|
||||
import std.d.parser;
|
||||
import std.experimental.logger;
|
||||
import std.file;
|
||||
import std.lexer;
|
||||
import std.path;
|
||||
|
||||
import actypes;
|
||||
import semantic;
|
||||
import memory.allocators;
|
||||
import containers.ttree;
|
||||
import containers.hashset;
|
||||
import containers.unrolledlist;
|
||||
import conversion.astconverter;
|
||||
import conversion.first;
|
||||
import conversion.second;
|
||||
import conversion.third;
|
||||
import containers.dynamicarray;
|
||||
import stupidlog;
|
||||
import messages;
|
||||
|
||||
private struct CacheEntry
|
||||
{
|
||||
ACSymbol* symbol;
|
||||
DSymbol* symbol;
|
||||
SysTime modificationTime;
|
||||
string path;
|
||||
|
||||
|
@ -81,7 +82,7 @@ bool existanceCheck(A)(A path)
|
|||
{
|
||||
if (path.exists())
|
||||
return true;
|
||||
Log.error("Cannot cache modules in ", path, " because it does not exist");
|
||||
warning("Cannot cache modules in ", path, " because it does not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ struct ModuleCache
|
|||
*/
|
||||
static void addImportPaths(string[] paths)
|
||||
{
|
||||
import string_interning : internString;
|
||||
import dsymbol.string_interning : internString;
|
||||
import std.array : array;
|
||||
auto newPaths = paths.filter!(a => existanceCheck(a) && !importPaths[].canFind(a)).map!(internString).array;
|
||||
importPaths.insert(newPaths);
|
||||
|
@ -124,7 +125,7 @@ struct ModuleCache
|
|||
/// TODO: Implement
|
||||
static void clear()
|
||||
{
|
||||
Log.info("ModuleCache.clear is not yet implemented.");
|
||||
info("ModuleCache.clear is not yet implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,9 +134,9 @@ struct ModuleCache
|
|||
* Returns:
|
||||
* The symbols defined in the given module
|
||||
*/
|
||||
static ACSymbol* getModuleSymbol(string location)
|
||||
static DSymbol* getModuleSymbol(string location)
|
||||
{
|
||||
import string_interning : internString;
|
||||
import dsymbol.string_interning : internString;
|
||||
import std.stdio : File;
|
||||
import std.typecons : scoped;
|
||||
|
||||
|
@ -155,7 +156,7 @@ struct ModuleCache
|
|||
|
||||
recursionGuard.insert(cachedLocation);
|
||||
|
||||
ACSymbol* symbol;
|
||||
DSymbol* symbol;
|
||||
File f = File(cachedLocation);
|
||||
immutable fileSize = cast(size_t) f.size;
|
||||
if (fileSize == 0)
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module dsymbol.scope_;
|
||||
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.import_;
|
||||
import dsymbol.builtin.names;
|
||||
import containers.ttree;
|
||||
import containers.unrolledlist;
|
||||
|
||||
/**
|
||||
* Contains symbols and supports lookup of symbols by cursor position.
|
||||
*/
|
||||
struct Scope
|
||||
{
|
||||
/**
|
||||
* Params:
|
||||
* begin = the beginning byte index
|
||||
* end = the ending byte index
|
||||
*/
|
||||
this (size_t begin, size_t end)
|
||||
{
|
||||
this.startLocation = begin;
|
||||
this.endLocation = end;
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
foreach (info; importInformation[])
|
||||
typeid(ImportInformation).destroy(info);
|
||||
foreach (child; children[])
|
||||
typeid(Scope).destroy(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* the innermost scope that contains the given cursor position
|
||||
*/
|
||||
Scope* getScopeByCursor(size_t cursorPosition) const
|
||||
{
|
||||
if (cursorPosition < startLocation) return null;
|
||||
if (cursorPosition > endLocation) return null;
|
||||
foreach (child; children[])
|
||||
{
|
||||
auto childScope = child.getScopeByCursor(cursorPosition);
|
||||
if (childScope !is null)
|
||||
return childScope;
|
||||
}
|
||||
return cast(typeof(return)) &this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* all symbols in the scope containing the cursor position, as well as
|
||||
* the symbols in parent scopes of that scope.
|
||||
*/
|
||||
DSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const
|
||||
{
|
||||
import std.array : array;
|
||||
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
return [];
|
||||
UnrolledList!(DSymbol*) symbols;
|
||||
Scope* sc = s;
|
||||
while (sc !is null)
|
||||
{
|
||||
foreach (item; sc.symbols[])
|
||||
{
|
||||
if (item.type !is null && (item.kind == CompletionKind.importSymbol
|
||||
|| item.kind == CompletionKind.withSymbol))
|
||||
{
|
||||
foreach (i; item.type.parts[])
|
||||
symbols.insert(i);
|
||||
}
|
||||
else
|
||||
symbols.insert(item);
|
||||
}
|
||||
sc = sc.parent;
|
||||
}
|
||||
return array(symbols[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol name to search for
|
||||
* Returns:
|
||||
* all symbols in this scope or parent scopes with the given name
|
||||
*/
|
||||
DSymbol*[] getSymbolsByName(istring name) const
|
||||
{
|
||||
import std.array : array, appender;
|
||||
|
||||
DSymbol s = DSymbol(name);
|
||||
auto er = symbols.equalRange(&s);
|
||||
if (!er.empty)
|
||||
return array(er);
|
||||
|
||||
// Check symbols from "with" statement
|
||||
DSymbol ir2 = DSymbol(WITH_SYMBOL_NAME);
|
||||
auto r2 = symbols.equalRange(&ir2);
|
||||
if (!r2.empty)
|
||||
{
|
||||
auto app = appender!(DSymbol*[])();
|
||||
foreach (e; r2)
|
||||
{
|
||||
if (e.type is null)
|
||||
continue;
|
||||
foreach (withSymbol; e.type.parts.equalRange(&s))
|
||||
app.put(withSymbol);
|
||||
}
|
||||
if (app.data.length > 0)
|
||||
return app.data;
|
||||
}
|
||||
|
||||
// Check imported symbols
|
||||
DSymbol ir = DSymbol(IMPORT_SYMBOL_NAME);
|
||||
auto r = symbols.equalRange(&ir);
|
||||
if (!r.empty)
|
||||
{
|
||||
auto app = appender!(DSymbol*[])();
|
||||
foreach (e; r)
|
||||
foreach (importedSymbol; e.type.parts.equalRange(&s))
|
||||
app.put(importedSymbol);
|
||||
if (app.data.length > 0)
|
||||
return app.data;
|
||||
}
|
||||
if (parent is null)
|
||||
return [];
|
||||
return parent.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol name to search for
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* all symbols with the given name in the scope containing the cursor
|
||||
* and its parent scopes
|
||||
*/
|
||||
DSymbol*[] getSymbolsByNameAndCursor(istring name, size_t cursorPosition) const
|
||||
{
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
return [];
|
||||
return s.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of symbols that are present at global scope
|
||||
*/
|
||||
DSymbol*[] getSymbolsAtGlobalScope(istring name) const
|
||||
{
|
||||
if (parent !is null)
|
||||
return parent.getSymbolsAtGlobalScope(name);
|
||||
return getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/// Imports contained in this scope
|
||||
UnrolledList!(ImportInformation*) importInformation;
|
||||
|
||||
/// The scope that contains this one
|
||||
Scope* parent;
|
||||
|
||||
/// Child scopes
|
||||
UnrolledList!(Scope*, false) 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
|
||||
TTree!(DSymbol*, true, "a < b", false) symbols;
|
||||
}
|
|
@ -16,18 +16,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module semantic;
|
||||
module dsymbol.semantic;
|
||||
|
||||
import messages;
|
||||
import actypes;
|
||||
import dsymbol.symbol;
|
||||
import std.d.ast;
|
||||
import std.d.lexer;
|
||||
import stupidlog;
|
||||
import containers.unrolledlist;
|
||||
import string_interning;
|
||||
|
||||
/**
|
||||
* Intermediate form between ACSymbol and the AST classes. Stores enough
|
||||
* Intermediate form between DSymbol and the AST classes. Stores enough
|
||||
* information to resolve things like base classes and alias this.
|
||||
*/
|
||||
struct SemanticSymbol
|
||||
|
@ -46,7 +43,7 @@ public:
|
|||
* symbolFile = the file name for this symbol
|
||||
* location = the location of this symbol
|
||||
*/
|
||||
this(ACSymbol* acSymbol, const Type type = null)
|
||||
this(DSymbol* acSymbol, const Type type = null)
|
||||
{
|
||||
this.acSymbol = acSymbol;
|
||||
this.type = type;
|
||||
|
@ -68,7 +65,7 @@ public:
|
|||
}
|
||||
|
||||
/// Autocompletion symbol
|
||||
ACSymbol* acSymbol;
|
||||
DSymbol* acSymbol;
|
||||
|
||||
/// Base classes
|
||||
UnrolledList!(istring[]) baseClasses;
|
||||
|
@ -107,6 +104,7 @@ Type argumentsType;
|
|||
|
||||
static this()
|
||||
{
|
||||
import dsymbol.string_interning : internString;
|
||||
import std.allocator : allocate, Mallocator;
|
||||
// _argptr has type void*
|
||||
argptrType = allocate!Type(Mallocator.it);
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module string_interning;
|
||||
module dsymbol.string_interning;
|
||||
|
||||
import std.d.lexer;
|
||||
|
||||
|
@ -38,6 +38,11 @@ alias istring = InternedString;
|
|||
//private size_t[string] dupCheck;
|
||||
private StringCache stringCache = void;
|
||||
|
||||
void checkStringCache()
|
||||
{
|
||||
stringCache.sanityCheck();
|
||||
}
|
||||
|
||||
private struct InternedString
|
||||
{
|
||||
void opAssign(T)(T other) if (is(Unqual!T == istring))
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module string_interning;
|
||||
|
||||
import std.d.lexer;
|
||||
|
||||
/**
|
||||
* Interns the given string and returns the interned version.
|
||||
*/
|
||||
istring internString(string s) nothrow @safe @nogc
|
||||
{
|
||||
return istring(stringCache.intern(s));
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
stringCache = StringCache(StringCache.defaultBucketCount);
|
||||
}
|
||||
|
||||
alias istring = InternedString;
|
||||
|
||||
//private size_t[string] dupCheck;
|
||||
private StringCache stringCache = void;
|
||||
|
||||
void checkStringCache()
|
||||
{
|
||||
stringCache.sanityCheck();
|
||||
}
|
||||
|
||||
private struct InternedString
|
||||
{
|
||||
void opAssign(T)(T other) if (is(Unqual!T == istring))
|
||||
{
|
||||
this.data = other.data;
|
||||
}
|
||||
string data;
|
||||
alias data this;
|
||||
private:
|
||||
import std.traits : Unqual;
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module dsymbol.symbol;
|
||||
|
||||
import std.algorithm;
|
||||
import std.array;
|
||||
import std.container;
|
||||
import std.typecons;
|
||||
import std.allocator;
|
||||
|
||||
import containers.ttree;
|
||||
import containers.unrolledlist;
|
||||
import containers.slist;
|
||||
import std.d.lexer;
|
||||
|
||||
import dsymbol.builtin.names;
|
||||
import dsymbol.string_interning;
|
||||
public import dsymbol.string_interning : istring;
|
||||
|
||||
import std.range : isOutputRange;
|
||||
|
||||
/**
|
||||
* Identifies the kind of the item in an identifier completion list
|
||||
*/
|
||||
enum CompletionKind : char
|
||||
{
|
||||
/// Invalid completion kind. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
dummy = '?',
|
||||
|
||||
/// Import symbol. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
importSymbol = '*',
|
||||
|
||||
/// With symbol. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
withSymbol = 'w',
|
||||
|
||||
/// class names
|
||||
className = 'c',
|
||||
|
||||
/// interface names
|
||||
interfaceName = 'i',
|
||||
|
||||
/// structure names
|
||||
structName = 's',
|
||||
|
||||
/// union name
|
||||
unionName = 'u',
|
||||
|
||||
/// variable name
|
||||
variableName = 'v',
|
||||
|
||||
/// member variable
|
||||
memberVariableName = 'm',
|
||||
|
||||
/// keyword, built-in version, scope statement
|
||||
keyword = 'k',
|
||||
|
||||
/// function or method
|
||||
functionName = 'f',
|
||||
|
||||
/// enum name
|
||||
enumName = 'g',
|
||||
|
||||
/// enum member
|
||||
enumMember = 'e',
|
||||
|
||||
/// package name
|
||||
packageName = 'P',
|
||||
|
||||
/// module name
|
||||
moduleName = 'M',
|
||||
|
||||
/// array
|
||||
array = 'a',
|
||||
|
||||
/// associative array
|
||||
assocArray = 'A',
|
||||
|
||||
/// alias name
|
||||
aliasName = 'l',
|
||||
|
||||
/// template name
|
||||
templateName = 't',
|
||||
|
||||
/// mixin template name
|
||||
mixinTemplateName = 'T'
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Any special information about a variable declaration symbol.
|
||||
*/
|
||||
enum SymbolQualifier : ubyte
|
||||
{
|
||||
/// _none
|
||||
none,
|
||||
/// the symbol is an array
|
||||
array,
|
||||
/// the symbol is a associative array
|
||||
assocArray,
|
||||
/// the symbol is a function or delegate pointer
|
||||
func
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocompletion symbol
|
||||
*/
|
||||
struct DSymbol
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Copying is disabled.
|
||||
*/
|
||||
@disable this();
|
||||
|
||||
/// ditto
|
||||
@disable this(this);
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
*/
|
||||
this(string name) nothrow @safe
|
||||
{
|
||||
this.name = name is null ? istring(null) : internString(name);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name) nothrow @safe
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
* kind = the symbol's completion kind
|
||||
*/
|
||||
this(string name, CompletionKind kind) nothrow @safe @nogc
|
||||
{
|
||||
this.name = name is null ? istring(name) : internString(name);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name, CompletionKind kind) nothrow @safe @nogc
|
||||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
* kind = the symbol's completion kind
|
||||
* resolvedType = the resolved type of the symbol
|
||||
*/
|
||||
this(string name, CompletionKind kind, DSymbol* type)
|
||||
{
|
||||
this.name = name is null ? istring(name) : internString(name);
|
||||
this.kind = kind;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name, CompletionKind kind, DSymbol* type)
|
||||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
int opCmp(ref const DSymbol other) const pure nothrow @safe
|
||||
{
|
||||
// Compare the pointers because the strings have been interned.
|
||||
// Identical strings MUST have the same address
|
||||
int r = name.ptr > other.name.ptr;
|
||||
if (name.ptr < other.name.ptr)
|
||||
r = -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool opEquals(ref const DSymbol other) const pure nothrow @safe
|
||||
{
|
||||
return other.name.ptr == this.name.ptr;
|
||||
}
|
||||
|
||||
size_t toHash() const pure nothrow @safe
|
||||
{
|
||||
return (cast(size_t) name.ptr) * 27_644_437;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parts whose name matches the given string.
|
||||
*/
|
||||
DSymbol*[] getPartsByName(istring name) const
|
||||
{
|
||||
import std.range : chain;
|
||||
DSymbol s = DSymbol(name);
|
||||
DSymbol p = DSymbol(IMPORT_SYMBOL_NAME);
|
||||
auto app = appender!(DSymbol*[])();
|
||||
foreach (part; parts.equalRange(&s))
|
||||
app.put(part);
|
||||
foreach (im; parts.equalRange(&p))
|
||||
app.put(im.type.getPartsByName(name));
|
||||
return app.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all parts and parts of parts with the given name to the given output
|
||||
* range.
|
||||
*/
|
||||
void getAllPartsNamed(OR)(string name, ref OR outputRange) const
|
||||
if (isOutputRange!(OR, DSymbol*))
|
||||
{
|
||||
foreach (part; parts[])
|
||||
{
|
||||
if (part.name == name)
|
||||
outputRange.put(part);
|
||||
part.getAllPartsNamed(name, outputRange);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DSymbol's name
|
||||
*/
|
||||
istring name;
|
||||
|
||||
/**
|
||||
* Symbols that compose this symbol, such as enum members, class variables,
|
||||
* methods, etc.
|
||||
*/
|
||||
TTree!(DSymbol*, true, "a < b", false) parts;
|
||||
|
||||
/**
|
||||
* Calltip to display if this is a function
|
||||
*/
|
||||
istring callTip;
|
||||
|
||||
/**
|
||||
* Module containing the symbol.
|
||||
*/
|
||||
istring symbolFile;
|
||||
|
||||
/**
|
||||
* Documentation for the symbol.
|
||||
*/
|
||||
istring doc;
|
||||
|
||||
/**
|
||||
* The symbol that represents the type.
|
||||
*/
|
||||
DSymbol* type;
|
||||
|
||||
/**
|
||||
* DSymbol location
|
||||
*/
|
||||
size_t location;
|
||||
|
||||
/**
|
||||
* The kind of symbol
|
||||
*/
|
||||
CompletionKind kind;
|
||||
|
||||
/**
|
||||
* DSymbol qualifier
|
||||
*/
|
||||
SymbolQualifier qualifier;
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit 32f6d638e38888e1bb11cf43e93fe2d11132a98f
|
||||
Subproject commit b490677106450153a6b270a37369a40a40b34689
|
26
makefile
26
makefile
|
@ -26,10 +26,9 @@ clean:
|
|||
rm -f *.o
|
||||
rm -rf $(OBJ_DIR)
|
||||
|
||||
CLIENT_SRC := src/client.d\
|
||||
src/messages.d\
|
||||
src/stupidlog.d\
|
||||
src/dcd_version.d\
|
||||
CLIENT_SRC := \
|
||||
$(shell find src/common -name "*.d")\
|
||||
$(shell find src/client -name "*.d")\
|
||||
msgpack-d/src/msgpack.d
|
||||
|
||||
DMD_CLIENT_FLAGS := -Imsgpack-d/src\
|
||||
|
@ -55,20 +54,10 @@ LDC_CLIENT_FLAGS := -Imsgpack-d/src\
|
|||
-oq\
|
||||
-of=bin/dcd-client
|
||||
|
||||
SERVER_SRC := src/actypes.d\
|
||||
src/conversion/astconverter.d\
|
||||
src/conversion/first.d\
|
||||
src/conversion/second.d\
|
||||
src/conversion/third.d\
|
||||
src/autocomplete.d\
|
||||
src/constants.d\
|
||||
src/messages.d\
|
||||
src/modulecache.d\
|
||||
src/semantic.d\
|
||||
src/server.d\
|
||||
src/stupidlog.d\
|
||||
src/string_interning.d\
|
||||
src/dcd_version.d\
|
||||
SERVER_SRC := \
|
||||
$(shell find src/common -name "*.d")\
|
||||
$(shell find src/server -name "*.d")\
|
||||
$(shell find dsymbol/src -name "*.d")\
|
||||
libdparse/src/std/d/ast.d\
|
||||
libdparse/src/std/d/entities.d\
|
||||
libdparse/src/std/d/lexer.d\
|
||||
|
@ -93,6 +82,7 @@ SERVER_OBJS = $(SERVER_SRC:%.d=$(OBJ_DIR)/%.o)
|
|||
DMD_SERVER_FLAGS := -Icontainers/src\
|
||||
-Imsgpack-d/src\
|
||||
-Ilibdparse/src\
|
||||
-Idsymbol/src\
|
||||
-J.\
|
||||
-wi\
|
||||
-O\
|
||||
|
|
766
src/actypes.d
766
src/actypes.d
|
@ -1,766 +0,0 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module actypes;
|
||||
|
||||
import std.algorithm;
|
||||
import std.array;
|
||||
import std.container;
|
||||
import std.typecons;
|
||||
import std.allocator;
|
||||
|
||||
import containers.ttree;
|
||||
import containers.unrolledlist;
|
||||
import containers.slist;
|
||||
import std.d.lexer;
|
||||
|
||||
import messages;
|
||||
import string_interning;
|
||||
public import string_interning : istring;
|
||||
|
||||
import std.range : isOutputRange;
|
||||
|
||||
/**
|
||||
* Any special information about a variable declaration symbol.
|
||||
*/
|
||||
enum SymbolQualifier : ubyte
|
||||
{
|
||||
/// _none
|
||||
none,
|
||||
/// the symbol is an array
|
||||
array,
|
||||
/// the symbol is a associative array
|
||||
assocArray,
|
||||
/// the symbol is a function or delegate pointer
|
||||
func
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocompletion symbol
|
||||
*/
|
||||
struct ACSymbol
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Copying is disabled.
|
||||
*/
|
||||
@disable this();
|
||||
|
||||
/// ditto
|
||||
@disable this(this);
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
*/
|
||||
this(string name) nothrow @safe
|
||||
{
|
||||
this.name = name is null ? istring(null) : internString(name);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name) nothrow @safe
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
* kind = the symbol's completion kind
|
||||
*/
|
||||
this(string name, CompletionKind kind) nothrow @safe @nogc
|
||||
{
|
||||
this.name = name is null ? istring(name) : internString(name);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name, CompletionKind kind) nothrow @safe @nogc
|
||||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol's name
|
||||
* kind = the symbol's completion kind
|
||||
* resolvedType = the resolved type of the symbol
|
||||
*/
|
||||
this(string name, CompletionKind kind, ACSymbol* type)
|
||||
{
|
||||
this.name = name is null ? istring(name) : internString(name);
|
||||
this.kind = kind;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(istring name, CompletionKind kind, ACSymbol* type)
|
||||
{
|
||||
this.name = name;
|
||||
this.kind = kind;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
int opCmp(ref const ACSymbol other) const pure nothrow @safe
|
||||
{
|
||||
// Compare the pointers because the strings have been interned.
|
||||
// Identical strings MUST have the same address
|
||||
int r = name.ptr > other.name.ptr;
|
||||
if (name.ptr < other.name.ptr)
|
||||
r = -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool opEquals(ref const ACSymbol other) const pure nothrow @safe
|
||||
{
|
||||
return other.name.ptr == this.name.ptr;
|
||||
}
|
||||
|
||||
size_t toHash() const pure nothrow @safe
|
||||
{
|
||||
return (cast(size_t) name.ptr) * 27_644_437;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parts whose name matches the given string.
|
||||
*/
|
||||
ACSymbol*[] getPartsByName(istring name) const
|
||||
{
|
||||
import std.range : chain;
|
||||
ACSymbol s = ACSymbol(name);
|
||||
ACSymbol p = ACSymbol(IMPORT_SYMBOL_NAME);
|
||||
auto app = appender!(ACSymbol*[])();
|
||||
foreach (part; parts.equalRange(&s))
|
||||
app.put(part);
|
||||
foreach (im; parts.equalRange(&p))
|
||||
app.put(im.type.getPartsByName(name));
|
||||
return app.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all parts and parts of parts with the given name to the given output
|
||||
* range.
|
||||
*/
|
||||
void getAllPartsNamed(OR)(string name, ref OR outputRange) const
|
||||
if (isOutputRange!(OR, ACSymbol*))
|
||||
{
|
||||
foreach (part; parts[])
|
||||
{
|
||||
if (part.name == name)
|
||||
outputRange.put(part);
|
||||
part.getAllPartsNamed(name, outputRange);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbol's name
|
||||
*/
|
||||
istring name;
|
||||
|
||||
/**
|
||||
* Symbols that compose this symbol, such as enum members, class variables,
|
||||
* methods, etc.
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) parts;
|
||||
|
||||
/**
|
||||
* Calltip to display if this is a function
|
||||
*/
|
||||
istring callTip;
|
||||
|
||||
/**
|
||||
* Module containing the symbol.
|
||||
*/
|
||||
istring symbolFile;
|
||||
|
||||
/**
|
||||
* Documentation for the symbol.
|
||||
*/
|
||||
istring doc;
|
||||
|
||||
/**
|
||||
* The symbol that represents the type.
|
||||
*/
|
||||
ACSymbol* type;
|
||||
|
||||
/**
|
||||
* Symbol location
|
||||
*/
|
||||
size_t location;
|
||||
|
||||
/**
|
||||
* The kind of symbol
|
||||
*/
|
||||
CompletionKind kind;
|
||||
|
||||
/**
|
||||
* Symbol qualifier
|
||||
*/
|
||||
SymbolQualifier qualifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains symbols and supports lookup of symbols by cursor position.
|
||||
*/
|
||||
struct Scope
|
||||
{
|
||||
/**
|
||||
* Params:
|
||||
* begin = the beginning byte index
|
||||
* end = the ending byte index
|
||||
*/
|
||||
this (size_t begin, size_t end)
|
||||
{
|
||||
this.startLocation = begin;
|
||||
this.endLocation = end;
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
foreach (info; importInformation[])
|
||||
typeid(ImportInformation).destroy(info);
|
||||
foreach (child; children[])
|
||||
typeid(Scope).destroy(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* the innermost scope that contains the given cursor position
|
||||
*/
|
||||
Scope* getScopeByCursor(size_t cursorPosition) const
|
||||
{
|
||||
if (cursorPosition < startLocation) return null;
|
||||
if (cursorPosition > endLocation) return null;
|
||||
foreach (child; children[])
|
||||
{
|
||||
auto childScope = child.getScopeByCursor(cursorPosition);
|
||||
if (childScope !is null)
|
||||
return childScope;
|
||||
}
|
||||
return cast(typeof(return)) &this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* all symbols in the scope containing the cursor position, as well as
|
||||
* the symbols in parent scopes of that scope.
|
||||
*/
|
||||
ACSymbol*[] getSymbolsInCursorScope(size_t cursorPosition) const
|
||||
{
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
return [];
|
||||
UnrolledList!(ACSymbol*) symbols;
|
||||
Scope* sc = s;
|
||||
while (sc !is null)
|
||||
{
|
||||
foreach (item; sc.symbols[])
|
||||
{
|
||||
if (item.type !is null && (item.kind == CompletionKind.importSymbol
|
||||
|| item.kind == CompletionKind.withSymbol))
|
||||
{
|
||||
foreach (i; item.type.parts[])
|
||||
symbols.insert(i);
|
||||
}
|
||||
else
|
||||
symbols.insert(item);
|
||||
}
|
||||
sc = sc.parent;
|
||||
}
|
||||
return array(symbols[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol name to search for
|
||||
* Returns:
|
||||
* all symbols in this scope or parent scopes with the given name
|
||||
*/
|
||||
ACSymbol*[] getSymbolsByName(istring name) const
|
||||
{
|
||||
ACSymbol s = ACSymbol(name);
|
||||
auto er = symbols.equalRange(&s);
|
||||
if (!er.empty)
|
||||
return array(er);
|
||||
|
||||
// Check symbols from "with" statement
|
||||
ACSymbol ir2 = ACSymbol(WITH_SYMBOL_NAME);
|
||||
auto r2 = symbols.equalRange(&ir2);
|
||||
if (!r2.empty)
|
||||
{
|
||||
auto app = appender!(ACSymbol*[])();
|
||||
foreach (e; r2)
|
||||
{
|
||||
if (e.type is null)
|
||||
continue;
|
||||
foreach (withSymbol; e.type.parts.equalRange(&s))
|
||||
app.put(withSymbol);
|
||||
}
|
||||
if (app.data.length > 0)
|
||||
return app.data;
|
||||
}
|
||||
|
||||
// Check imported symbols
|
||||
ACSymbol ir = ACSymbol(IMPORT_SYMBOL_NAME);
|
||||
auto r = symbols.equalRange(&ir);
|
||||
if (!r.empty)
|
||||
{
|
||||
auto app = appender!(ACSymbol*[])();
|
||||
foreach (e; r)
|
||||
foreach (importedSymbol; e.type.parts.equalRange(&s))
|
||||
app.put(importedSymbol);
|
||||
if (app.data.length > 0)
|
||||
return app.data;
|
||||
}
|
||||
if (parent is null)
|
||||
return [];
|
||||
return parent.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* name = the symbol name to search for
|
||||
* cursorPosition = the cursor position in bytes
|
||||
* Returns:
|
||||
* all symbols with the given name in the scope containing the cursor
|
||||
* and its parent scopes
|
||||
*/
|
||||
ACSymbol*[] getSymbolsByNameAndCursor(istring name, size_t cursorPosition) const
|
||||
{
|
||||
auto s = getScopeByCursor(cursorPosition);
|
||||
if (s is null)
|
||||
return [];
|
||||
return s.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of symbols that are present at global scope
|
||||
*/
|
||||
ACSymbol*[] getSymbolsAtGlobalScope(istring name) const
|
||||
{
|
||||
if (parent !is null)
|
||||
return parent.getSymbolsAtGlobalScope(name);
|
||||
return getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/// Imports contained in this scope
|
||||
UnrolledList!(ImportInformation*) importInformation;
|
||||
|
||||
/// The scope that contains this one
|
||||
Scope* parent;
|
||||
|
||||
/// Child scopes
|
||||
UnrolledList!(Scope*, false) 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
|
||||
TTree!(ACSymbol*, true, "a < b", false) symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import information
|
||||
*/
|
||||
struct ImportInformation
|
||||
{
|
||||
/// Import statement parts
|
||||
UnrolledList!istring importParts;
|
||||
/// module relative path
|
||||
istring modulePath;
|
||||
/// symbols to import from this module
|
||||
UnrolledList!(Tuple!(istring, istring), false) importedSymbols;
|
||||
/// true if the import is public
|
||||
bool isPublic;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Symbols for the built in types
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) builtinSymbols;
|
||||
|
||||
/**
|
||||
* Array properties
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) arraySymbols;
|
||||
|
||||
/**
|
||||
* Associative array properties
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) assocArraySymbols;
|
||||
|
||||
/**
|
||||
* Struct, enum, union, class, and interface properties
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) aggregateSymbols;
|
||||
|
||||
/**
|
||||
* Class properties
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) classSymbols;
|
||||
|
||||
private immutable(istring[24]) builtinTypeNames;
|
||||
|
||||
/// Constants for buit-in or dummy symbol names
|
||||
immutable istring IMPORT_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring WITH_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring CONSTRUCTOR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DESTRUCTOR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ARGPTR_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ARGUMENTS_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring THIS_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring SUPER_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring UNITTEST_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DOUBLE_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring FLOAT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IDOUBLE_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IFLOAT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring INT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring LONG_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring REAL_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring IREAL_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring UINT_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring ULONG_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring CHAR_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring DSTRING_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring STRING_LITERAL_SYMBOL_NAME;
|
||||
/// ditto
|
||||
immutable istring WSTRING_LITERAL_SYMBOL_NAME;
|
||||
|
||||
/**
|
||||
* Translates the IDs for built-in types into an interned string.
|
||||
*/
|
||||
istring getBuiltinTypeName(IdType id) nothrow pure @nogc @safe
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case tok!"int": return builtinTypeNames[0];
|
||||
case tok!"uint": return builtinTypeNames[1];
|
||||
case tok!"double": return builtinTypeNames[2];
|
||||
case tok!"idouble": return builtinTypeNames[3];
|
||||
case tok!"float": return builtinTypeNames[4];
|
||||
case tok!"ifloat": return builtinTypeNames[5];
|
||||
case tok!"short": return builtinTypeNames[6];
|
||||
case tok!"ushort": return builtinTypeNames[7];
|
||||
case tok!"long": return builtinTypeNames[8];
|
||||
case tok!"ulong": return builtinTypeNames[9];
|
||||
case tok!"char": return builtinTypeNames[10];
|
||||
case tok!"wchar": return builtinTypeNames[11];
|
||||
case tok!"dchar": return builtinTypeNames[12];
|
||||
case tok!"bool": return builtinTypeNames[13];
|
||||
case tok!"void": return builtinTypeNames[14];
|
||||
case tok!"cent": return builtinTypeNames[15];
|
||||
case tok!"ucent": return builtinTypeNames[16];
|
||||
case tok!"real": return builtinTypeNames[17];
|
||||
case tok!"ireal": return builtinTypeNames[18];
|
||||
case tok!"byte": return builtinTypeNames[19];
|
||||
case tok!"ubyte": return builtinTypeNames[20];
|
||||
case tok!"cdouble": return builtinTypeNames[21];
|
||||
case tok!"cfloat": return builtinTypeNames[22];
|
||||
case tok!"creal": return builtinTypeNames[23];
|
||||
default: assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes builtin types and the various properties of builtin types
|
||||
*/
|
||||
static this()
|
||||
{
|
||||
builtinTypeNames[0] = internString("int");
|
||||
builtinTypeNames[1] = internString("uint");
|
||||
builtinTypeNames[2] = internString("double");
|
||||
builtinTypeNames[3] = internString("idouble");
|
||||
builtinTypeNames[4] = internString("float");
|
||||
builtinTypeNames[5] = internString("ifloat");
|
||||
builtinTypeNames[6] = internString("short");
|
||||
builtinTypeNames[7] = internString("ushort");
|
||||
builtinTypeNames[8] = internString("long");
|
||||
builtinTypeNames[9] = internString("ulong");
|
||||
builtinTypeNames[10] = internString("char");
|
||||
builtinTypeNames[11] = internString("wchar");
|
||||
builtinTypeNames[12] = internString("dchar");
|
||||
builtinTypeNames[13] = internString("bool");
|
||||
builtinTypeNames[14] = internString("void");
|
||||
builtinTypeNames[15] = internString("cent");
|
||||
builtinTypeNames[16] = internString("ucent");
|
||||
builtinTypeNames[17] = internString("real");
|
||||
builtinTypeNames[18] = internString("ireal");
|
||||
builtinTypeNames[19] = internString("byte");
|
||||
builtinTypeNames[20] = internString("ubyte");
|
||||
builtinTypeNames[21] = internString("cdouble");
|
||||
builtinTypeNames[22] = internString("cfloat");
|
||||
builtinTypeNames[23] = internString("creal");
|
||||
|
||||
IMPORT_SYMBOL_NAME = internString("public");
|
||||
WITH_SYMBOL_NAME = internString("with");
|
||||
CONSTRUCTOR_SYMBOL_NAME = internString("*constructor*");
|
||||
DESTRUCTOR_SYMBOL_NAME = internString("~this");
|
||||
ARGPTR_SYMBOL_NAME = internString("_argptr");
|
||||
ARGUMENTS_SYMBOL_NAME = internString("_arguments");
|
||||
THIS_SYMBOL_NAME = internString("this");
|
||||
SUPER_SYMBOL_NAME = internString("super");
|
||||
UNITTEST_SYMBOL_NAME = internString("*unittest*");
|
||||
DOUBLE_LITERAL_SYMBOL_NAME = internString("*double");
|
||||
FLOAT_LITERAL_SYMBOL_NAME = internString("*float");
|
||||
IDOUBLE_LITERAL_SYMBOL_NAME = internString("*idouble");
|
||||
IFLOAT_LITERAL_SYMBOL_NAME = internString("*ifloat");
|
||||
INT_LITERAL_SYMBOL_NAME = internString("*int");
|
||||
LONG_LITERAL_SYMBOL_NAME = internString("*long");
|
||||
REAL_LITERAL_SYMBOL_NAME = internString("*real");
|
||||
IREAL_LITERAL_SYMBOL_NAME = internString("*ireal");
|
||||
UINT_LITERAL_SYMBOL_NAME = internString("*uint");
|
||||
ULONG_LITERAL_SYMBOL_NAME = internString("*ulong");
|
||||
CHAR_LITERAL_SYMBOL_NAME = internString("*char");
|
||||
DSTRING_LITERAL_SYMBOL_NAME = internString("*dstring");
|
||||
STRING_LITERAL_SYMBOL_NAME = internString("*string");
|
||||
WSTRING_LITERAL_SYMBOL_NAME = internString("*wstring");
|
||||
|
||||
auto bool_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[13], CompletionKind.keyword);
|
||||
auto int_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[0], CompletionKind.keyword);
|
||||
auto long_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[8], CompletionKind.keyword);
|
||||
auto byte_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[19], CompletionKind.keyword);
|
||||
auto char_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[10], CompletionKind.keyword);
|
||||
auto dchar_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[12], CompletionKind.keyword);
|
||||
auto short_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[6], CompletionKind.keyword);
|
||||
auto ubyte_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[20], CompletionKind.keyword);
|
||||
auto uint_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[1], CompletionKind.keyword);
|
||||
auto ulong_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[9], CompletionKind.keyword);
|
||||
auto ushort_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[7], CompletionKind.keyword);
|
||||
auto wchar_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[11], CompletionKind.keyword);
|
||||
|
||||
auto alignof_ = allocate!ACSymbol(Mallocator.it, internString("alignof"), CompletionKind.keyword);
|
||||
auto mangleof_ = allocate!ACSymbol(Mallocator.it, internString("mangleof"), CompletionKind.keyword);
|
||||
auto sizeof_ = allocate!ACSymbol(Mallocator.it, internString("sizeof"), CompletionKind.keyword);
|
||||
auto stringof_ = allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword);
|
||||
auto init = allocate!ACSymbol(Mallocator.it, internString("stringof"), CompletionKind.keyword);
|
||||
|
||||
arraySymbols.insert(alignof_);
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword));
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("idup"), CompletionKind.keyword));
|
||||
arraySymbols.insert(init);
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_));
|
||||
arraySymbols.insert(mangleof_);
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("ptr"), CompletionKind.keyword));
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("reverse"), CompletionKind.keyword));
|
||||
arraySymbols.insert(sizeof_);
|
||||
arraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("sort"), CompletionKind.keyword));
|
||||
arraySymbols.insert(stringof_);
|
||||
|
||||
assocArraySymbols.insert(alignof_);
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("byKey"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("byValue"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("dup"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("get"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("keys"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("length"), CompletionKind.keyword, ulong_));
|
||||
assocArraySymbols.insert(mangleof_);
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("rehash"), CompletionKind.keyword));
|
||||
assocArraySymbols.insert(sizeof_);
|
||||
assocArraySymbols.insert(stringof_);
|
||||
assocArraySymbols.insert(init);
|
||||
assocArraySymbols.insert(allocate!ACSymbol(Mallocator.it, internString("values"), CompletionKind.keyword));
|
||||
|
||||
ACSymbol*[11] integralTypeArray;
|
||||
integralTypeArray[0] = bool_;
|
||||
integralTypeArray[1] = int_;
|
||||
integralTypeArray[2] = long_;
|
||||
integralTypeArray[3] = byte_;
|
||||
integralTypeArray[4] = char_;
|
||||
integralTypeArray[4] = dchar_;
|
||||
integralTypeArray[5] = short_;
|
||||
integralTypeArray[6] = ubyte_;
|
||||
integralTypeArray[7] = uint_;
|
||||
integralTypeArray[8] = ulong_;
|
||||
integralTypeArray[9] = ushort_;
|
||||
integralTypeArray[10] = wchar_;
|
||||
|
||||
foreach (s; integralTypeArray)
|
||||
{
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("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_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[21], CompletionKind.keyword);
|
||||
auto cent_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[15], CompletionKind.keyword);
|
||||
auto cfloat_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[22], CompletionKind.keyword);
|
||||
auto creal_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[23], CompletionKind.keyword);
|
||||
auto double_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[2], CompletionKind.keyword);
|
||||
auto float_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[4], CompletionKind.keyword);
|
||||
auto idouble_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[3], CompletionKind.keyword);
|
||||
auto ifloat_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[5], CompletionKind.keyword);
|
||||
auto ireal_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[18], CompletionKind.keyword);
|
||||
auto real_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[17], CompletionKind.keyword);
|
||||
auto ucent_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[16], CompletionKind.keyword);
|
||||
|
||||
ACSymbol*[11] floatTypeArray;
|
||||
floatTypeArray[0] = cdouble_;
|
||||
floatTypeArray[1] = cent_;
|
||||
floatTypeArray[2] = cfloat_;
|
||||
floatTypeArray[3] = creal_;
|
||||
floatTypeArray[4] = double_;
|
||||
floatTypeArray[5] = float_;
|
||||
floatTypeArray[6] = idouble_;
|
||||
floatTypeArray[7] = ifloat_;
|
||||
floatTypeArray[8] = ireal_;
|
||||
floatTypeArray[9] = real_;
|
||||
floatTypeArray[10] = ucent_;
|
||||
|
||||
foreach (s; floatTypeArray)
|
||||
{
|
||||
s.parts.insert(alignof_);
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("dig"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("epsilon"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("infinity"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("init"), CompletionKind.keyword, s));
|
||||
s.parts.insert(mangleof_);
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("mant_dig"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max_10_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("max_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_10_exp"), CompletionKind.keyword, int_));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("min_normal"), CompletionKind.keyword, s));
|
||||
s.parts.insert(allocate!ACSymbol(Mallocator.it, internString("nan"), CompletionKind.keyword, s));
|
||||
s.parts.insert(sizeof_);
|
||||
s.parts.insert(stringof_);
|
||||
}
|
||||
|
||||
aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("tupleof"), CompletionKind.keyword));
|
||||
aggregateSymbols.insert(mangleof_);
|
||||
aggregateSymbols.insert(alignof_);
|
||||
aggregateSymbols.insert(sizeof_);
|
||||
aggregateSymbols.insert(stringof_);
|
||||
aggregateSymbols.insert(init);
|
||||
|
||||
classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("classInfo"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("tupleof"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("__vptr"), CompletionKind.variableName));
|
||||
classSymbols.insert(allocate!ACSymbol(Mallocator.it, internString("__monitor"), CompletionKind.variableName));
|
||||
classSymbols.insert(mangleof_);
|
||||
classSymbols.insert(alignof_);
|
||||
classSymbols.insert(sizeof_);
|
||||
classSymbols.insert(stringof_);
|
||||
classSymbols.insert(init);
|
||||
|
||||
ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("im"), CompletionKind.keyword, double_));
|
||||
ireal_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, real_));
|
||||
ifloat_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, float_));
|
||||
idouble_.parts.insert(allocate!ACSymbol(Mallocator.it, internString("re"), CompletionKind.keyword, double_));
|
||||
|
||||
auto void_ = allocate!ACSymbol(Mallocator.it, builtinTypeNames[14], CompletionKind.keyword);
|
||||
|
||||
builtinSymbols.insert(bool_);
|
||||
bool_.type = bool_;
|
||||
builtinSymbols.insert(int_);
|
||||
int_.type = int_;
|
||||
builtinSymbols.insert(long_);
|
||||
long_.type = long_;
|
||||
builtinSymbols.insert(byte_);
|
||||
byte_.type = byte_;
|
||||
builtinSymbols.insert(char_);
|
||||
char_.type = char_;
|
||||
builtinSymbols.insert(dchar_);
|
||||
dchar_.type = dchar_;
|
||||
builtinSymbols.insert(short_);
|
||||
short_.type = short_;
|
||||
builtinSymbols.insert(ubyte_);
|
||||
ubyte_.type = ubyte_;
|
||||
builtinSymbols.insert(uint_);
|
||||
uint_.type = uint_;
|
||||
builtinSymbols.insert(ulong_);
|
||||
ulong_.type = ulong_;
|
||||
builtinSymbols.insert(ushort_);
|
||||
ushort_.type = ushort_;
|
||||
builtinSymbols.insert(wchar_);
|
||||
wchar_.type = wchar_;
|
||||
builtinSymbols.insert(cdouble_);
|
||||
cdouble_.type = cdouble_;
|
||||
builtinSymbols.insert(cent_);
|
||||
cent_.type = cent_;
|
||||
builtinSymbols.insert(cfloat_);
|
||||
cfloat_.type = cfloat_;
|
||||
builtinSymbols.insert(creal_);
|
||||
creal_.type = creal_;
|
||||
builtinSymbols.insert(double_);
|
||||
double_.type = double_;
|
||||
builtinSymbols.insert(float_);
|
||||
float_.type = float_;
|
||||
builtinSymbols.insert(idouble_);
|
||||
idouble_.type = idouble_;
|
||||
builtinSymbols.insert(ifloat_);
|
||||
ifloat_.type = ifloat_;
|
||||
builtinSymbols.insert(ireal_);
|
||||
ireal_.type = ireal_;
|
||||
builtinSymbols.insert(real_);
|
||||
real_.type = real_;
|
||||
builtinSymbols.insert(ucent_);
|
||||
ucent_.type = ucent_;
|
||||
builtinSymbols.insert(void_);
|
||||
void_.type = void_;
|
||||
|
||||
|
||||
foreach (s; ["__DATE__", "__EOF__", "__TIME__", "__TIMESTAMP__", "__VENDOR__",
|
||||
"__VERSION__", "__FUNCTION__", "__PRETTY_FUNCTION__", "__MODULE__",
|
||||
"__FILE__", "__LINE__"])
|
||||
builtinSymbols.insert(allocate!ACSymbol(Mallocator.it, internString(s), CompletionKind.keyword));
|
||||
}
|
||||
|
|
@ -28,10 +28,10 @@ import std.path;
|
|||
import std.file;
|
||||
import std.conv;
|
||||
import std.string;
|
||||
import std.experimental.logger;
|
||||
|
||||
import msgpack;
|
||||
import messages;
|
||||
import stupidlog;
|
||||
import dcd_version;
|
||||
|
||||
int main(string[] args)
|
||||
|
@ -58,7 +58,7 @@ int main(string[] args)
|
|||
}
|
||||
catch (ConvException e)
|
||||
{
|
||||
Log.fatal(e.msg);
|
||||
fatal(e.msg);
|
||||
printHelp(args[0]);
|
||||
return 1;
|
||||
}
|
|
@ -18,75 +18,6 @@
|
|||
|
||||
module messages;
|
||||
|
||||
/**
|
||||
* Identifies the kind of the item in an identifier completion list
|
||||
*/
|
||||
enum CompletionKind : char
|
||||
{
|
||||
/// Invalid completion kind. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
dummy = '?',
|
||||
|
||||
/// Import symbol. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
importSymbol = '*',
|
||||
|
||||
/// With symbol. This is used internally and will never
|
||||
/// be returned in a completion response.
|
||||
withSymbol = 'w',
|
||||
|
||||
/// class names
|
||||
className = 'c',
|
||||
|
||||
/// interface names
|
||||
interfaceName = 'i',
|
||||
|
||||
/// structure names
|
||||
structName = 's',
|
||||
|
||||
/// union name
|
||||
unionName = 'u',
|
||||
|
||||
/// variable name
|
||||
variableName = 'v',
|
||||
|
||||
/// member variable
|
||||
memberVariableName = 'm',
|
||||
|
||||
/// keyword, built-in version, scope statement
|
||||
keyword = 'k',
|
||||
|
||||
/// function or method
|
||||
functionName = 'f',
|
||||
|
||||
/// enum name
|
||||
enumName = 'g',
|
||||
|
||||
/// enum member
|
||||
enumMember = 'e',
|
||||
|
||||
/// package name
|
||||
packageName = 'P',
|
||||
|
||||
/// module name
|
||||
moduleName = 'M',
|
||||
|
||||
/// array
|
||||
array = 'a',
|
||||
|
||||
/// associative array
|
||||
assocArray = 'A',
|
||||
|
||||
/// alias name
|
||||
aliasName = 'l',
|
||||
|
||||
/// template name
|
||||
templateName = 't',
|
||||
|
||||
/// mixin template name
|
||||
mixinTemplateName = 'T'
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of completion list being returned
|
||||
*/
|
|
@ -19,28 +19,34 @@
|
|||
module autocomplete;
|
||||
|
||||
import std.algorithm;
|
||||
import std.allocator;
|
||||
import std.array;
|
||||
import std.conv;
|
||||
import std.experimental.logger;
|
||||
import std.file;
|
||||
import std.path;
|
||||
import std.range;
|
||||
import std.stdio;
|
||||
import std.string;
|
||||
import std.typecons;
|
||||
import std.uni;
|
||||
|
||||
import std.d.ast;
|
||||
import std.d.lexer;
|
||||
import std.d.parser;
|
||||
import std.string;
|
||||
import std.typecons;
|
||||
import memory.allocators;
|
||||
import std.allocator;
|
||||
|
||||
import messages;
|
||||
import actypes;
|
||||
import dsymbol.conversion.astconverter;
|
||||
import dsymbol.modulecache;
|
||||
import dsymbol.string_interning;
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.scope_;
|
||||
import dsymbol.builtin.names;
|
||||
import dsymbol.builtin.symbols;
|
||||
|
||||
import memory.allocators;
|
||||
|
||||
import constants;
|
||||
import modulecache;
|
||||
import conversion.astconverter;
|
||||
import stupidlog;
|
||||
import string_interning;
|
||||
import messages;
|
||||
|
||||
/**
|
||||
* Gets documentation for the symbol at the cursor
|
||||
|
@ -51,14 +57,14 @@ import string_interning;
|
|||
*/
|
||||
public AutocompleteResponse getDoc(const AutocompleteRequest request)
|
||||
{
|
||||
// Log.trace("Getting doc comments");
|
||||
// trace("Getting doc comments");
|
||||
AutocompleteResponse response;
|
||||
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
|
||||
auto cache = StringCache(StringCache.defaultBucketCount);
|
||||
ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc,
|
||||
DSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc,
|
||||
allocator, &cache);
|
||||
if (symbols.length == 0)
|
||||
Log.error("Could not find symbol");
|
||||
warning("Could not find symbol");
|
||||
else foreach (symbol; symbols.filter!(a => !a.doc.empty))
|
||||
response.docComments ~= formatComment(symbol.doc);
|
||||
return response;
|
||||
|
@ -76,7 +82,7 @@ public AutocompleteResponse findDeclaration(const AutocompleteRequest request)
|
|||
AutocompleteResponse response;
|
||||
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
|
||||
auto cache = StringCache(StringCache.defaultBucketCount);
|
||||
ACSymbol*[] symbols = getSymbolsForCompletion(request,
|
||||
DSymbol*[] symbols = getSymbolsForCompletion(request,
|
||||
CompletionType.location, allocator, &cache);
|
||||
if (symbols.length > 0)
|
||||
{
|
||||
|
@ -84,7 +90,7 @@ public AutocompleteResponse findDeclaration(const AutocompleteRequest request)
|
|||
response.symbolFilePath = symbols[0].symbolFile.idup;
|
||||
}
|
||||
else
|
||||
Log.error("Could not find symbol declaration");
|
||||
warning("Could not find symbol declaration");
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -143,14 +149,14 @@ public AutocompleteResponse symbolSearch(const AutocompleteRequest request)
|
|||
|
||||
static struct SearchResults
|
||||
{
|
||||
void put(ACSymbol* symbol)
|
||||
void put(DSymbol* symbol)
|
||||
{
|
||||
tree.insert(SearchResult(symbol));
|
||||
}
|
||||
|
||||
static struct SearchResult
|
||||
{
|
||||
ACSymbol* symbol;
|
||||
DSymbol* symbol;
|
||||
|
||||
int opCmp(ref const SearchResult other) const pure nothrow
|
||||
{
|
||||
|
@ -322,7 +328,7 @@ auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition,
|
|||
* all symbols that should be considered for the autocomplete list based on
|
||||
* the request's source code, cursor position, and completion type.
|
||||
*/
|
||||
ACSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
|
||||
DSymbol*[] getSymbolsForCompletion(const AutocompleteRequest request,
|
||||
const CompletionType type, CAllocator allocator, StringCache* cache)
|
||||
{
|
||||
const(Token)[] tokenArray;
|
||||
|
@ -525,7 +531,7 @@ body
|
|||
string resolvedLocation = ModuleCache.resolveImportLoctation(path);
|
||||
if (resolvedLocation is null)
|
||||
{
|
||||
Log.error("Could not resolve location of ", path);
|
||||
warning("Could not resolve location of ", path);
|
||||
return response;
|
||||
}
|
||||
auto symbols = ModuleCache.getModuleSymbol(resolvedLocation);
|
||||
|
@ -533,9 +539,9 @@ body
|
|||
import containers.hashset : HashSet;
|
||||
HashSet!string h;
|
||||
|
||||
void addSymbolToResponses(ACSymbol* sy)
|
||||
void addSymbolToResponses(DSymbol* sy)
|
||||
{
|
||||
auto a = ACSymbol(sy.name);
|
||||
auto a = DSymbol(sy.name);
|
||||
if (!builtinSymbols.contains(&a) && sy.name !is null && !h.contains(sy.name)
|
||||
&& sy.name != CONSTRUCTOR_SYMBOL_NAME)
|
||||
{
|
||||
|
@ -610,17 +616,17 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response)
|
|||
}
|
||||
}
|
||||
if (!found)
|
||||
Log.error("Could not find ", moduleParts);
|
||||
warning("Could not find ", moduleParts);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||
DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||
T tokens, size_t cursorPosition, CompletionType completionType)
|
||||
{
|
||||
// Find the symbol corresponding to the beginning of the chain
|
||||
ACSymbol*[] symbols;
|
||||
DSymbol*[] symbols;
|
||||
if (tokens.length == 0)
|
||||
return [];
|
||||
if (tokens[0] == tok!"." && tokens.length > 1)
|
||||
|
@ -633,7 +639,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
Log.error("Could not find declaration of ", stringToken(tokens[0]),
|
||||
warning("Could not find declaration of ", stringToken(tokens[0]),
|
||||
" from position ", cursorPosition);
|
||||
return [];
|
||||
}
|
||||
|
@ -759,7 +765,7 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
skip();
|
||||
Parser p = new Parser();
|
||||
p.setTokens(tokens[h .. i].array());
|
||||
ACSymbol*[] overloads;
|
||||
DSymbol*[] overloads;
|
||||
if (p.isSliceExpression())
|
||||
overloads = symbols[0].getPartsByName(internString("opSlice"));
|
||||
else
|
||||
|
@ -805,7 +811,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
if (tokens.length == 0)
|
||||
return;
|
||||
|
||||
ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||
cursorPosition, completionType);
|
||||
|
||||
if (symbols.length == 0)
|
||||
|
@ -904,7 +910,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
}
|
||||
|
||||
string generateStructConstructorCalltip(const ACSymbol* symbol)
|
||||
string generateStructConstructorCalltip(const DSymbol* symbol)
|
||||
in
|
||||
{
|
||||
assert (symbol.kind == CompletionKind.structName);
|
|
@ -30,16 +30,18 @@ import std.datetime;
|
|||
import std.conv;
|
||||
import std.allocator;
|
||||
import std.exception : enforce;
|
||||
import std.experimental.logger;
|
||||
|
||||
import core.memory;
|
||||
|
||||
import msgpack;
|
||||
|
||||
import dsymbol.string_interning;
|
||||
|
||||
import messages;
|
||||
import autocomplete;
|
||||
import modulecache;
|
||||
import stupidlog;
|
||||
import actypes;
|
||||
import dsymbol.modulecache;
|
||||
import dsymbol.symbol;
|
||||
import core.memory;
|
||||
import dcd_version;
|
||||
|
||||
|
@ -53,12 +55,9 @@ version(OSX) version = useXDG;
|
|||
|
||||
int main(string[] args)
|
||||
{
|
||||
Log.info("Starting up...");
|
||||
info("Starting up...");
|
||||
StopWatch sw = StopWatch(AutoStart.yes);
|
||||
|
||||
Log.output = stdout;
|
||||
Log.level = LogLevel.trace;
|
||||
|
||||
ushort port = 9166;
|
||||
bool help;
|
||||
bool printVersion;
|
||||
|
@ -71,7 +70,7 @@ int main(string[] args)
|
|||
}
|
||||
catch (ConvException e)
|
||||
{
|
||||
Log.fatal(e.msg);
|
||||
fatal(e.msg);
|
||||
printHelp(args[0]);
|
||||
return 1;
|
||||
}
|
||||
|
@ -100,21 +99,21 @@ int main(string[] args)
|
|||
socket.listen(0);
|
||||
scope (exit)
|
||||
{
|
||||
Log.info("Shutting down sockets...");
|
||||
info("Shutting down sockets...");
|
||||
socket.shutdown(SocketShutdown.BOTH);
|
||||
socket.close();
|
||||
Log.info("Sockets shut down.");
|
||||
info("Sockets shut down.");
|
||||
}
|
||||
|
||||
ModuleCache.addImportPaths(importPaths);
|
||||
Log.info("Import directories: ", ModuleCache.getImportPaths());
|
||||
info("Import directories: ", ModuleCache.getImportPaths());
|
||||
|
||||
ubyte[] buffer = cast(ubyte[]) Mallocator.it.allocate(1024 * 1024 * 4); // 4 megabytes should be enough for anybody...
|
||||
scope(exit) Mallocator.it.deallocate(buffer);
|
||||
|
||||
sw.stop();
|
||||
Log.info(ModuleCache.symbolsAllocated, " symbols cached.");
|
||||
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds.");
|
||||
info(ModuleCache.symbolsAllocated, " symbols cached.");
|
||||
info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds.");
|
||||
import core.memory : GC;
|
||||
GC.minimize();
|
||||
|
||||
|
@ -165,7 +164,7 @@ int main(string[] args)
|
|||
|
||||
if (bytesReceived == Socket.ERROR)
|
||||
{
|
||||
Log.error("Socket recieve failed");
|
||||
warning("Socket recieve failed");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -173,12 +172,12 @@ int main(string[] args)
|
|||
msgpack.unpack(buffer[size_t.sizeof .. bytesReceived], request);
|
||||
if (request.kind & RequestKind.clearCache)
|
||||
{
|
||||
Log.info("Clearing cache.");
|
||||
info("Clearing cache.");
|
||||
ModuleCache.clear();
|
||||
}
|
||||
else if (request.kind & RequestKind.shutdown)
|
||||
{
|
||||
Log.info("Shutting down.");
|
||||
info("Shutting down.");
|
||||
break serverLoop;
|
||||
}
|
||||
else if (request.kind & RequestKind.query)
|
||||
|
@ -195,14 +194,14 @@ int main(string[] args)
|
|||
}
|
||||
if (request.kind & RequestKind.autocomplete)
|
||||
{
|
||||
Log.info("Getting completions");
|
||||
info("Getting completions");
|
||||
AutocompleteResponse response = complete(request);
|
||||
ubyte[] responseBytes = msgpack.pack(response);
|
||||
s.send(responseBytes);
|
||||
}
|
||||
else if (request.kind & RequestKind.doc)
|
||||
{
|
||||
Log.info("Getting doc comment");
|
||||
info("Getting doc comment");
|
||||
try
|
||||
{
|
||||
AutocompleteResponse response = getDoc(request);
|
||||
|
@ -211,7 +210,7 @@ int main(string[] args)
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.error("Could not get DDoc information", e.msg);
|
||||
warning("Could not get DDoc information", e.msg);
|
||||
}
|
||||
}
|
||||
else if (request.kind & RequestKind.symbolLocation)
|
||||
|
@ -224,7 +223,7 @@ int main(string[] args)
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.error("Could not get symbol location", e.msg);
|
||||
warning("Could not get symbol location", e.msg);
|
||||
}
|
||||
}
|
||||
else if (request.kind & RequestKind.search)
|
||||
|
@ -233,7 +232,7 @@ int main(string[] args)
|
|||
ubyte[] responseBytes = msgpack.pack(response);
|
||||
s.send(responseBytes);
|
||||
}
|
||||
Log.info("Request processed in ", requestWatch.peek().to!("msecs", float), " milliseconds");
|
||||
info("Request processed in ", requestWatch.peek().to!("msecs", float), " milliseconds");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -283,11 +282,11 @@ void warnAboutOldConfigLocation()
|
|||
version (linux) if ("~/.config/dcd".expandTilde().exists()
|
||||
&& "~/.config/dcd".expandTilde().isFile())
|
||||
{
|
||||
Log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
Log.error("!! Upgrade warning:");
|
||||
Log.error("!! '~/.config/dcd' should be moved to '$XDG_CONFIG_HOME/dcd/dcd.conf'");
|
||||
Log.error("!! or '$HOME/.config/dcd/dcd.conf'");
|
||||
Log.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
warning("!! Upgrade warning:");
|
||||
warning("!! '~/.config/dcd' should be moved to '$XDG_CONFIG_HOME/dcd/dcd.conf'");
|
||||
warning("!! or '$HOME/.config/dcd/dcd.conf'");
|
||||
warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +299,7 @@ string[] loadConfiguredImportDirs()
|
|||
immutable string configLocation = getConfigurationLocation();
|
||||
if (!configLocation.exists())
|
||||
return [];
|
||||
Log.info("Loading configuration from ", configLocation);
|
||||
info("Loading configuration from ", configLocation);
|
||||
File f = File(configLocation, "rt");
|
||||
return f.byLine(KeepTerminator.no)
|
||||
.filter!(a => a.length > 0 && existanceCheck(a))
|
103
src/stupidlog.d
103
src/stupidlog.d
|
@ -1,103 +0,0 @@
|
|||
/**
|
||||
* This file is part of DCD, a development tool for the D programming language.
|
||||
* Copyright (C) 2014 Brian Schott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module stupidlog;
|
||||
|
||||
import std.stdio;
|
||||
import core.vararg;
|
||||
|
||||
enum LogLevel : uint
|
||||
{
|
||||
fatal = 0,
|
||||
error,
|
||||
info,
|
||||
trace
|
||||
}
|
||||
|
||||
struct Log
|
||||
{
|
||||
static void trace(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.trace) return;
|
||||
version(Windows)
|
||||
{
|
||||
output.writeln("[trace] ", args);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;36mtrace\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[trace] ", args);
|
||||
}
|
||||
}
|
||||
|
||||
static void info(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.info) return;
|
||||
version (Windows)
|
||||
{
|
||||
output.writeln("[info ] ", args);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;32minfo\033[0m ] ", args);
|
||||
else
|
||||
output.writeln("[info ] ", args);
|
||||
}
|
||||
}
|
||||
|
||||
static void error(T...)(T args)
|
||||
{
|
||||
if (level < LogLevel.error) return;
|
||||
version(Windows)
|
||||
{
|
||||
output.writeln("[error] ", args);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;31merror\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[error] ", args);
|
||||
}
|
||||
}
|
||||
|
||||
static void fatal(T...)(T args)
|
||||
{
|
||||
version(Windows)
|
||||
{
|
||||
output.writeln("[fatal] ", args);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output is stdout)
|
||||
output.writeln("[\033[01;35mfatal\033[0m] ", args);
|
||||
else
|
||||
output.writeln("[fatal] ", args);
|
||||
}
|
||||
}
|
||||
|
||||
static LogLevel level;
|
||||
static File output;
|
||||
}
|
Loading…
Reference in New Issue