Pull symbol resolution code out into dsymbol folder

This commit is contained in:
Hackerpilot 2015-05-21 17:55:20 -07:00
parent 4cc67f0ea2
commit ae83e447a4
24 changed files with 1134 additions and 1107 deletions

View File

@ -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```

View File

@ -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");
}

View File

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

View File

@ -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.

View File

@ -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++;

View File

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

View File

@ -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();
}

View File

@ -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;
}

View File

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

View File

@ -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;
}

View File

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

View File

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

View File

@ -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;
}

View File

@ -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

View File

@ -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\

View File

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

View File

@ -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;
}

View File

@ -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
*/

View File

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

View File

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

View File

@ -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;
}