diff --git a/actypes.d b/actypes.d index f788250..435e892 100644 --- a/actypes.d +++ b/actypes.d @@ -98,6 +98,23 @@ public: return this.opCmp(other.name); } + /** + * Gets all parts whose name matches the given string. + */ + const(ACSymbol)*[] getPartsByName(string name) const + { + return cast(typeof(return)) parts.filter!(a => a.name == name).array; + } + + size_t estimateMemory(size_t runningTotal) const + { + runningTotal = runningTotal + name.length + callTip.length + + ACSymbol.sizeof; + foreach (part; parts) + runningTotal = part.estimateMemory(runningTotal); + return runningTotal; + } + /** * Symbols that compose this symbol, such as enum members, class variables, * methods, etc. @@ -109,15 +126,25 @@ public: */ string name; + /** + * Calltip to display if this is a function + */ + string callTip; + + /** + * Module containing the symbol. + */ + string symbolFile; + /** * The symbol that represents the type. */ const(ACSymbol)* type; /** - * Calltip to display if this is a function + * Symbol location */ - string callTip; + size_t location; /** * The kind of symbol @@ -128,24 +155,6 @@ public: * Symbol qualifier */ SymbolQualifier qualifier; - - /** - * Symbol location - */ - size_t location; - - /** - * Module containing the symbol. - */ - string symbolFile; - - /** - * Gets all parts whose name matches the given string. - */ - const(ACSymbol)*[] getPartsByName(string name) const - { - return cast(typeof(return)) parts.filter!(a => a.name == name).array; - } } struct Scope @@ -318,6 +327,28 @@ static this() builtinSymbols = [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_, ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_, float_, idouble_, ifloat_, ireal_, real_, ucent_, void_]; + + // _argptr has type void* + argptrType = new Type; + argptrType.type2 = new Type2; + argptrType.type2.builtinType = TokenType.void_; + TypeSuffix argptrTypeSuffix = new TypeSuffix; + argptrTypeSuffix.star = true; + argptrType.typeSuffixes ~= argptrTypeSuffix; + + // _arguments has type TypeInfo[] + argumentsType = new Type; + argumentsType = new Type; + argumentsType.type2 = new Type2; + argumentsType.type2.symbol = new Symbol; + argumentsType.type2.symbol.identifierOrTemplateChain = new IdentifierOrTemplateChain; + IdentifierOrTemplateInstance i = new IdentifierOrTemplateInstance; + i.identifier.value = "TypeInfo"; + i.identifier.type = TokenType.identifier; + argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances ~= i; + TypeSuffix argumentsTypeSuffix = new TypeSuffix; + argumentsTypeSuffix.array = true; + argumentsType.typeSuffixes ~= argptrTypeSuffix; } const(ACSymbol)*[] builtinSymbols; @@ -325,3 +356,5 @@ const(ACSymbol)*[] arraySymbols; const(ACSymbol)*[] assocArraySymbols; const(ACSymbol)*[] classSymbols; const(ACSymbol)*[] structSymbols; +Type argptrType; +Type argumentsType; diff --git a/astconverter.d b/astconverter.d index feff926..dfec652 100644 --- a/astconverter.d +++ b/astconverter.d @@ -62,6 +62,19 @@ final class FirstPass : ASTVisitor void run() { visit(mod); + mod = null; + } + + override void visit(Unittest u) + { + // Create a dummy symbol because we don't want unit test symbols leaking + // into the symbol they're declared in. + SemanticSymbol* s = new SemanticSymbol("*unittest*", + CompletionKind.dummy, null, 0); + s.parent = currentSymbol; + currentSymbol = s; + u.accept(this); + currentSymbol = s.parent; } override void visit(Constructor con) @@ -388,6 +401,20 @@ private: symbol.addChild(parameter); parameter.parent = symbol; } + if (parameters.hasVarargs) + { + SemanticSymbol* argptr = new SemanticSymbol("_argptr", + CompletionKind.variableName, null, 0); + argptr.type = argptrType; + argptr.parent = symbol; + symbol.addChild(argptr); + + SemanticSymbol* arguments = new SemanticSymbol("_arguments", + CompletionKind.variableName, null, 0); + arguments.type = argumentsType; + arguments.parent = symbol; + symbol.addChild(arguments); + } } symbol.acSymbol.callTip = formatCallTip(returnType, functionName, parameters); @@ -695,22 +722,29 @@ const(ACSymbol)*[] convertAstToSymbols(Module m, string symbolFile) { FirstPass first = new FirstPass(m, symbolFile); first.run(); + SecondPass second = SecondPass(first.rootSymbol, first.moduleScope); second.run(); + ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope); third.run(); + return cast(typeof(return)) third.rootSymbol.acSymbol.parts; } const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile) { Module m = parseModule(tokens, null); + FirstPass first = new FirstPass(m, symbolFile); first.run(); + SecondPass second = SecondPass(first.rootSymbol, first.currentScope); second.run(); + ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope); third.run(); + return cast(typeof(return)) third.moduleScope; } @@ -731,7 +765,7 @@ string[] iotcToStringArray(const IdentifierOrTemplateChain iotc) private static string convertChainToImportPath(IdentifierChain chain) { - return to!string(chain.identifiers.map!(a => a.value.dup).join(dirSeparator).array) ~ ".d"; + return to!string(chain.identifiers.map!(a => a.value).join(dirSeparator).array) ~ ".d"; } version(unittest) Module parseTestCode(string code) diff --git a/build.sh b/build.sh index 1c0d5f6..a047116 100755 --- a/build.sh +++ b/build.sh @@ -2,6 +2,10 @@ dmd -wi client.d\ messages.d\ msgpack-d/src/msgpack.d\ -Imsgpack-d/src\ + -release\ + -inline\ + -noboundscheck\ + -O\ -ofdcd-client dmd \ diff --git a/modulecache.d b/modulecache.d index aa4ca88..280033d 100644 --- a/modulecache.d +++ b/modulecache.d @@ -60,6 +60,18 @@ struct ModuleCache cache = cache.init; } + static void estimateMemory() + { + size_t estimate = 0; + foreach (c; cache) + { + foreach (symbol; c.symbols) + estimate = symbol.estimateMemory(estimate); + } + double megabytes = estimate / (1024.0F * 1024.0F); + Log.info("Memory use estimated at ", megabytes, " megabytes"); + } + /** * Adds the given path to the list of directories checked for imports */ @@ -78,7 +90,6 @@ struct ModuleCache { foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth)) { - Log.info("Loading and caching completions for ", fileName); getSymbolsInModule(fileName); } } @@ -92,7 +103,7 @@ struct ModuleCache */ static const(ACSymbol)*[] getSymbolsInModule(string moduleName) { -// Log.info("Getting symbols for module ", moduleName); + string location = resolveImportLoctation(moduleName); if (location is null) return []; @@ -104,6 +115,8 @@ struct ModuleCache return []; } + Log.info("Getting symbols for module ", moduleName); + recursionGuard[location] = true; const(ACSymbol)*[] symbols; @@ -131,9 +144,6 @@ struct ModuleCache CacheEntry c = CacheEntry(symbols, modification); cache[location] = c; recursionGuard[location] = false; - import core.memory; - GC.collect(); - GC.minimize(); return symbols; } diff --git a/semantic.d b/semantic.d index 85c1d2d..b9796e5 100644 --- a/semantic.d +++ b/semantic.d @@ -42,11 +42,6 @@ public: acSymbol.symbolFile = symbolFile; } - ~this() - { - Log.trace(acSymbol.name, " destructor"); - } - void addChild(SemanticSymbol* child) { children ~= child; diff --git a/server.d b/server.d index 0e9853f..d6c0402 100644 --- a/server.d +++ b/server.d @@ -98,6 +98,7 @@ int main(string[] args) sw.stop(); Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds"); + ModuleCache.estimateMemory(); while (true) { @@ -114,8 +115,6 @@ int main(string[] args) continue; } - // TODO: Only process connections from localhost - scope (exit) { s.shutdown(SocketShutdown.BOTH);