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;