From f52cb6ad2ac0a8a8b5b61397be43cc7964e75e6d Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Sat, 8 Feb 2014 20:56:13 -0800 Subject: [PATCH] Added documentation. Removed duplicated code from autocompletion module --- .gitignore | 6 +- actypes.d | 87 +++++++-- astconverter.d | 10 +- autocomplete.d | 467 ++++++++++++++++++++++++++----------------------- client.d | 2 +- constants.d | 2 +- messages.d | 2 +- modulecache.d | 2 +- semantic.d | 14 +- server.d | 49 ++++-- stupidlog.d | 10 +- 11 files changed, 397 insertions(+), 254 deletions(-) diff --git a/.gitignore b/.gitignore index c994c34..686f415 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,10 @@ # *nix binaries dcd-client dcd-server -dcd-client.o -dcd-server.o +*.o # Perf reports perf.data + +# Valgrind reports +callgrind.* diff --git a/actypes.d b/actypes.d index a911411..c64752c 100644 --- a/actypes.d +++ b/actypes.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 @@ -28,6 +28,9 @@ import std.array; import std.typecons; import std.container; +/** + * Compares symbols by their name + */ bool comparitor(const(ACSymbol)* a, const(ACSymbol)* b) pure nothrow { return a.name < b.name; @@ -150,8 +153,16 @@ public: 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; @@ -159,6 +170,12 @@ struct Scope this.symbols = new RedBlackTree!(ACSymbol*, comparitor, true); } + /** + * 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; @@ -172,6 +189,13 @@ struct Scope 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); @@ -188,14 +212,18 @@ struct Scope return symbols.array(); } + /** + * Params: + * name = the symbol name to search for + * Returns: + * all symbols in this scope or parent scopes with the given name + */ ACSymbol*[] getSymbolsByName(string name) const { import std.range; ACSymbol s = ACSymbol(name); RedBlackTree!(ACSymbol*, comparitor, true) t = cast() symbols; auto r = t.equalRange(&s).array(); - version(assert) foreach (n; r) - assert (n.name == name, name); if (r.length > 0) return cast(typeof(return)) r; if (parent is null) @@ -203,6 +231,14 @@ struct Scope 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(string name, size_t cursorPosition) const { auto s = getScopeByCursor(cursorPosition); @@ -230,6 +266,9 @@ struct Scope RedBlackTree!(ACSymbol*, comparitor, true) symbols; } +/** + * Import information + */ struct ImportInformation { /// Import statement parts @@ -243,6 +282,41 @@ struct ImportInformation } +/** + * Symbols for the built in types + */ +RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols; + +/** + * Array properties + */ +RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols; + +/** + * Associative array properties + */ +RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols; + +/** + * Enum, union, class, and interface properties + */ +RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols; + +/** + * Class properties + */ +RedBlackTree!(ACSymbol*, comparitor, true) classSymbols; + +/** + * Type of the _argptr variable + */ +Type argptrType; + +/** + * Type of _arguments + */ +Type argumentsType; + /** * Initializes builtin types and the various properties of builtin types */ @@ -406,10 +480,3 @@ static this() classSymbols = clSym; } -RedBlackTree!(ACSymbol*, comparitor, true) builtinSymbols; -RedBlackTree!(ACSymbol*, comparitor, true) arraySymbols; -RedBlackTree!(ACSymbol*, comparitor, true) assocArraySymbols; -RedBlackTree!(ACSymbol*, comparitor, true) aggregateSymbols; -RedBlackTree!(ACSymbol*, comparitor, true) classSymbols; -Type argptrType; -Type argumentsType; diff --git a/astconverter.d b/astconverter.d index f82a10d..f8cff2a 100644 --- a/astconverter.d +++ b/astconverter.d @@ -1,9 +1,7 @@ -/******************************************************************************* - * Authors: Brian Schott - * Copyright: Brian Schott - * Date: Sep 21 2013 +/** + * This file is part of DCD, a development tool for the D programming language. + * Copyright (C) 2014 Brian Schott * - * License: * 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 @@ -16,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - ******************************************************************************/ + */ module astconverter; diff --git a/autocomplete.d b/autocomplete.d index 571cb8e..574bdc0 100644 --- a/autocomplete.d +++ b/autocomplete.d @@ -1,9 +1,7 @@ -/******************************************************************************* - * Authors: Brian Schott - * Copyright: Brian Schott - * Date: Jul 19 2013 +/** + * This file is part of DCD, a development tool for the D programming language. + * Copyright (C) 2014 Brian Schott * - * License: * 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 @@ -16,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - ******************************************************************************/ + */ module autocomplete; @@ -40,35 +38,18 @@ import modulecache; import astconverter; import stupidlog; +/** + * Gets documentation for the symbol at the cursor + * Params: + * request = the autocompletion request + * Returns: + * the autocompletion response + */ AutocompleteResponse getDoc(const AutocompleteRequest request) { Log.trace("Getting doc comments"); - AutocompleteResponse response; - LexerConfig config; - config.fileName = "stdin"; - StringCache* cache = new StringCache(StringCache.defaultBucketCount); - auto tokens = byToken(cast(ubyte[]) request.sourceCode, config, cache); - const(Token)[] tokenArray = void; - try { - tokenArray = tokens.array(); - } catch (Exception e) { - Log.error("Could not provide autocomplete due to lexing exception: ", e.msg); - return response; - } - auto sortedTokens = assumeSorted(tokenArray); - string partial; - - auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition); - - Log.trace("Token at cursor: ", beforeTokens[$ - 1].text); - - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin"); - auto expression = getExpression(beforeTokens); - - ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, expression, - request.cursorPosition, CompletionType.ddoc); - + ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.ddoc); if (symbols.length == 0) Log.error("Could not find symbol"); else foreach (symbol; symbols) @@ -86,76 +67,213 @@ AutocompleteResponse getDoc(const AutocompleteRequest request) /** * Finds the declaration of the symbol at the cursor position. + * Params: + * request = the autocompletion request + * Returns: + * the autocompletion response */ AutocompleteResponse findDeclaration(const AutocompleteRequest request) { Log.trace("Finding declaration"); AutocompleteResponse response; - LexerConfig config; - config.fileName = "stdin"; - StringCache* cache = new StringCache(StringCache.defaultBucketCount); - auto tokens = byToken(cast(ubyte[]) request.sourceCode, config, cache); - const(Token)[] tokenArray = void; - try { - tokenArray = tokens.array(); - } catch (Exception e) { - Log.error("Could not provide autocomplete due to lexing exception: ", e.msg); - return response; - } - auto sortedTokens = assumeSorted(tokenArray); - string partial; - - auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition); - - Log.trace("Token at cursor: ", beforeTokens[$ - 1].text); - - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin"); - auto expression = getExpression(beforeTokens); - - ACSymbol*[] symbols = getSymbolsByTokenChain(completionScope, expression, - request.cursorPosition, CompletionType.location); - + ACSymbol*[] symbols = getSymbolsForCompletion(request, CompletionType.location); if (symbols.length > 0) { response.symbolLocation = symbols[0].location; response.symbolFilePath = symbols[0].symbolFile; - Log.info(beforeTokens[$ - 1].text, " declared in ", + Log.info(symbols[0].name, " declared in ", response.symbolFilePath, " at ", response.symbolLocation); } else - { Log.error("Could not find symbol"); - } - return response; } -bool shouldSwapWithType(CompletionType completionType, CompletionKind kind, - size_t current, size_t max) pure nothrow @safe +/** + * Handles autocompletion + * Params: + * request = the autocompletion request + * Returns: + * the autocompletion response + */ +AutocompleteResponse complete(const AutocompleteRequest request) { - // Modules and packages never have types, so always return false - if (kind == CompletionKind.moduleName - || kind == CompletionKind.packageName - || kind == CompletionKind.className - || kind == CompletionKind.structName - || kind == CompletionKind.interfaceName - || kind == CompletionKind.enumName - || kind == CompletionKind.unionName) + Log.info("Got a completion request"); + + const(Token)[] tokenArray; + auto beforeTokens = getTokensBeforeCursor(request.sourceCode, + request.cursorPosition, tokenArray); + string partial; + IdType tokenType; + + if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!"(") + return parenCompletion(beforeTokens, tokenArray, request.cursorPosition); + + AutocompleteResponse response; + if (beforeTokens.length >= 1 && beforeTokens[$ - 1] == tok!"identifier") { - return false; + partial = beforeTokens[$ - 1].text; + tokenType = beforeTokens[$ - 1].type; + beforeTokens = beforeTokens[0 .. $ - 1]; } - // Swap out every part of a chain with its type except the last part - if (current < max) - return true; - // Only swap out types for these kinds - immutable bool isInteresting = - kind == CompletionKind.variableName - || kind == CompletionKind.memberVariableName - || kind == CompletionKind.enumMember - || kind == CompletionKind.functionName; - return completionType == CompletionType.identifiers && isInteresting; + else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".") + tokenType = beforeTokens[$ - 2].type; + else + return response; + + switch (tokenType) + { + case tok!"stringLiteral": + case tok!"wstringLiteral": + case tok!"dstringLiteral": + foreach (symbol; (cast() arraySymbols)[]) + { + response.completionKinds ~= symbol.kind; + response.completions ~= symbol.name; + } + response.completionType = CompletionType.identifiers; + break; + case tok!"int": + case tok!"uint": + case tok!"long": + case tok!"ulong": + case tok!"char": + case tok!"wchar": + case tok!"dchar": + case tok!"bool": + case tok!"byte": + case tok!"ubyte": + case tok!"short": + case tok!"ushort": + case tok!"cent": + case tok!"ucent": + case tok!"float": + case tok!"ifloat": + case tok!"cfloat": + case tok!"idouble": + case tok!"cdouble": + case tok!"double": + case tok!"real": + case tok!"ireal": + case tok!"creal": + case tok!"identifier": + case tok!")": + case tok!"]": + case tok!"this": + const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, + "stdin"); + auto expression = getExpression(beforeTokens); + response.setCompletions(completionScope, expression, + request.cursorPosition, CompletionType.identifiers, partial); + break; + case tok!"(": + case tok!"{": + case tok!"[": + case tok!";": + case tok!":": + // TODO: global scope + break; + default: + break; + } + return response; } +/** + * Params: + * sourceCode = the source code of the file being edited + * cursorPosition = the cursor position in bytes + * Returns: + * a sorted range of tokens before the cursor position + */ +auto getTokensBeforeCursor(const(ubyte[]) sourceCode, size_t cursorPosition, + out const(Token)[] tokenArray) +{ + LexerConfig config; + config.fileName = "stdin"; + StringCache* cache = new StringCache(StringCache.defaultBucketCount); + auto tokens = byToken(cast(ubyte[]) sourceCode, config, cache); + tokenArray = tokens.array(); + auto sortedTokens = assumeSorted(tokenArray); + return sortedTokens.lowerBound(cast(size_t) cursorPosition); +} + +/** + * Params: + * request = the autocompletion request + * type = type the autocompletion type + * Returns: + * 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, + const CompletionType type) +{ + const(Token)[] tokenArray; + auto beforeTokens = getTokensBeforeCursor(request.sourceCode, + request.cursorPosition, tokenArray); + const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, "stdin"); + auto expression = getExpression(beforeTokens); + return getSymbolsByTokenChain(completionScope, expression, + request.cursorPosition, type); +} + +/** + * Handles paren completion for function calls and some keywords + * Params: + * beforeTokens = the tokens before the cursor + * tokenArray = all tokens in the file + * cursorPosition = the cursor position in bytes + * Returns: + * the autocompletion response + */ +AutocompleteResponse parenCompletion(T)(T beforeTokens, + const(Token)[] tokenArray, size_t cursorPosition) +{ + AutocompleteResponse response; + immutable(string)[] completions; + switch (beforeTokens[$ - 2].type) + { + case tok!"__traits": + completions = traits; + goto fillResponse; + case tok!"scope": + completions = scopes; + goto fillResponse; + case tok!"version": + completions = versions; + goto fillResponse; + case tok!"extern": + completions = linkages; + goto fillResponse; + case tok!"pragma": + completions = pragmas; + fillResponse: + response.completionType = CompletionType.identifiers; + for (size_t i = 0; i < completions.length; i++) + { + response.completions ~= completions[i]; + response.completionKinds ~= CompletionKind.keyword; + } + break; + case tok!"identifier": + case tok!")": + case tok!"]": + const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, + "stdin"); + auto expression = getExpression(beforeTokens[0 .. $ - 1]); + response.setCompletions(completionScope, expression, + cursorPosition, CompletionType.calltips); + break; + default: + break; + } + return response; +} + +/** + * + */ ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope, T tokens, size_t cursorPosition, CompletionType completionType) { @@ -315,140 +433,9 @@ ACSymbol*[] getSymbolsByTokenChain(T)(const(Scope)* completionScope, return symbols; } -AutocompleteResponse complete(const AutocompleteRequest request) -{ - Log.info("Got a completion request"); - AutocompleteResponse response; - - LexerConfig config; - config.fileName = "stdin"; - StringCache* cache = new StringCache(StringCache.defaultBucketCount); - auto tokens = byToken(cast(ubyte[]) request.sourceCode, config, - cache); - const(Token)[] tokenArray = void; - try { - tokenArray = tokens.array(); - } catch (Exception e) { - Log.error("Could not provide autocomplete due to lexing exception: ", e.msg); - return response; - } - auto sortedTokens = assumeSorted(tokenArray); - string partial; - - auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition); - - IdType tokenType; - - if (beforeTokens.length >= 1 && beforeTokens[$ - 1] == tok!"identifier") - { - partial = beforeTokens[$ - 1].text; - tokenType = beforeTokens[$ - 1].type; - beforeTokens = beforeTokens[0 .. $ - 1]; - goto dotCompletion; - } - else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!"(") - { - immutable(string)[] completions; - switch (beforeTokens[$ - 2].type) - { - case tok!"__traits": - completions = traits; - goto fillResponse; - case tok!"scope": - completions = scopes; - goto fillResponse; - case tok!"version": - completions = versions; - goto fillResponse; - case tok!"extern": - completions = linkages; - goto fillResponse; - case tok!"pragma": - completions = pragmas; - fillResponse: - response.completionType = CompletionType.identifiers; - for (size_t i = 0; i < completions.length; i++) - { - response.completions ~= completions[i]; - response.completionKinds ~= CompletionKind.keyword; - } - break; - case tok!"identifier": - case tok!")": - case tok!"]": - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, - "stdin"); - auto expression = getExpression(beforeTokens[0 .. $ - 1]); - response.setCompletions(completionScope, expression, - request.cursorPosition, CompletionType.calltips); - break; - default: - break; - } - } - else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".") - { - tokenType = beforeTokens[$ - 2].type; -dotCompletion: - switch (tokenType) - { - case tok!"stringLiteral": - case tok!"wstringLiteral": - case tok!"dstringLiteral": - foreach (symbol; (cast() arraySymbols)[]) - { - response.completionKinds ~= symbol.kind; - response.completions ~= symbol.name; - } - response.completionType = CompletionType.identifiers; - break; - case tok!"int": - case tok!"uint": - case tok!"long": - case tok!"ulong": - case tok!"char": - case tok!"wchar": - case tok!"dchar": - case tok!"bool": - case tok!"byte": - case tok!"ubyte": - case tok!"short": - case tok!"ushort": - case tok!"cent": - case tok!"ucent": - case tok!"float": - case tok!"ifloat": - case tok!"cfloat": - case tok!"idouble": - case tok!"cdouble": - case tok!"double": - case tok!"real": - case tok!"ireal": - case tok!"creal": - case tok!"identifier": - case tok!")": - case tok!"]": - case tok!"this": - const(Scope)* completionScope = generateAutocompleteTrees(tokenArray, - "stdin"); - auto expression = getExpression(beforeTokens); - response.setCompletions(completionScope, expression, - request.cursorPosition, CompletionType.identifiers, partial); - break; - case tok!"(": - case tok!"{": - case tok!"[": - case tok!";": - case tok!":": - // TODO: global scope - break; - default: - break; - } - } - return response; -} - +/** + * + */ void setCompletions(T)(ref AutocompleteResponse response, const(Scope)* completionScope, T tokens, size_t cursorPosition, CompletionType completionType, string partial = null) @@ -538,6 +525,9 @@ void setCompletions(T)(ref AutocompleteResponse response, } } +/** + * + */ T getExpression(T)(T beforeTokens) { if (beforeTokens.length == 0) @@ -641,6 +631,12 @@ T getExpression(T)(T beforeTokens) return beforeTokens[i .. $]; } +/** + * Populates the response with completion information for an import statement + * Params: + * tokens = the tokens after the "import" keyword and before the cursor + * response = the response that should be populated + */ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response) { response.completionType = CompletionType.identifiers; @@ -650,7 +646,7 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response) string path = buildPath(moduleParts); foreach (importDirectory; ModuleCache.getImportPaths()) { - string p = format("%s%s%s", importDirectory, dirSeparator, path); + string p = buildPath(importDirectory, path); Log.trace("Checking for ", p); if (!exists(p)) continue; @@ -672,6 +668,47 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response) } } +/** + * Params: + * completionType = the completion type being requested + * kind = the kind of the current item in the completion chain + * current = the index of the current item in the symbol chain + * max = the number of items in the symbol chain + * Returns: + * true if the symbol should be swapped with its type field + */ +bool shouldSwapWithType(CompletionType completionType, CompletionKind kind, + size_t current, size_t max) pure nothrow @safe +{ + // Modules and packages never have types, so always return false + if (kind == CompletionKind.moduleName + || kind == CompletionKind.packageName + || kind == CompletionKind.className + || kind == CompletionKind.structName + || kind == CompletionKind.interfaceName + || kind == CompletionKind.enumName + || kind == CompletionKind.unionName) + { + return false; + } + // Swap out every part of a chain with its type except the last part + if (current < max) + return true; + // Only swap out types for these kinds + immutable bool isInteresting = + kind == CompletionKind.variableName + || kind == CompletionKind.memberVariableName + || kind == CompletionKind.enumMember + || kind == CompletionKind.functionName; + return completionType == CompletionType.identifiers && isInteresting; +} + +/** + * Params: + * comment = the comment to format + * Returns + * the comment with the comment characters removed + */ string formatComment(string comment) { import std.string; diff --git a/client.d b/client.d index 417e469..19ff945 100644 --- a/client.d +++ b/client.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 diff --git a/constants.d b/constants.d index d7b4f37..cb7c102 100644 --- a/constants.d +++ b/constants.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 diff --git a/messages.d b/messages.d index 2404e21..841b71d 100644 --- a/messages.d +++ b/messages.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 diff --git a/modulecache.d b/modulecache.d index 8068fbc..9913735 100644 --- a/modulecache.d +++ b/modulecache.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 diff --git a/semantic.d b/semantic.d index 0dfbab1..93c8a17 100644 --- a/semantic.d +++ b/semantic.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 @@ -34,6 +34,13 @@ public: @disable this(); + /** + * Params: + * name = the name + * kind = the completion kind + * symbolFile = the file name for this symbol + * location = the location of this symbol + */ this(string name, CompletionKind kind, string symbolFile, size_t location = size_t.max) { @@ -42,6 +49,9 @@ public: acSymbol.symbolFile = symbolFile; } + /** + * Adds a child to the children field and updates the acSymbol's parts field + */ void addChild(SemanticSymbol* child) { children ~= child; @@ -66,7 +76,9 @@ public: /// Protection level for this symobol IdType protection; + /// Parent symbol SemanticSymbol* parent; + /// Child symbols SemanticSymbol*[] children; } diff --git a/server.d b/server.d index 4bc8185..1e95c82 100644 --- a/server.d +++ b/server.d @@ -1,6 +1,6 @@ /** * This file is part of DCD, a development tool for the D programming language. - * Copyright (C) 2013 Brian Schott + * 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 @@ -151,19 +151,42 @@ int main(string[] args) Log.info("Shutting down."); break serverLoop; case RequestKind.autocomplete: - AutocompleteResponse response = complete(request); - ubyte[] responseBytes = msgpack.pack(response); - s.send(responseBytes); + try + { + AutocompleteResponse response = complete(request); + ubyte[] responseBytes = msgpack.pack(response); + s.send(responseBytes); + } + catch (Exception e) + { + Log.error("Could not handle autocomplete request due to an exception:", + e.msg); + } break; case RequestKind.doc: - AutocompleteResponse response = getDoc(request); - ubyte[] responseBytes = msgpack.pack(response); - s.send(responseBytes); + try + { + AutocompleteResponse response = getDoc(request); + ubyte[] responseBytes = msgpack.pack(response); + s.send(responseBytes); + } + catch (Exception e) + { + Log.error("Could not get DDoc information", e.msg); + } + break; case RequestKind.symbolLocation: - AutocompleteResponse response = findDeclaration(request); - ubyte[] responseBytes = msgpack.pack(response); - s.send(responseBytes); + try + { + AutocompleteResponse response = findDeclaration(request); + ubyte[] responseBytes = msgpack.pack(response); + s.send(responseBytes); + } + catch (Exception e) + { + Log.error("Could not get symbol location", e.msg); + } break; } Log.info("Request processed in ", requestWatch.peek().to!("msecs", float), " milliseconds"); @@ -171,6 +194,9 @@ int main(string[] args) return 0; } +/** + * Locates the configuration file + */ string getConfigurationLocation() { version (useXDG) @@ -208,6 +234,9 @@ void warnAboutOldConfigLocation() } } +/** + * Loads import directories from the configuration file + */ string[] loadConfiguredImportDirs() { warnAboutOldConfigLocation(); diff --git a/stupidlog.d b/stupidlog.d index 091b488..49de3f6 100644 --- a/stupidlog.d +++ b/stupidlog.d @@ -1,9 +1,7 @@ -/******************************************************************************* - * Authors: Brian Schott - * Copyright: Brian Schott - * Date: Oct 5 2013 +/** + * This file is part of DCD, a development tool for the D programming language. + * Copyright (C) 2014 Brian Schott * - * License: * 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 @@ -16,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - ******************************************************************************/ + */ module stupidlog;