Merge branch 'master' of https://github.com/Hackerpilot/DCD
This commit is contained in:
commit
fb46f25560
|
|
@ -3,12 +3,14 @@ The D Completion Daemon is an auto-complete program for the D programming langua
|
|||
|
||||

|
||||
|
||||
(The above is a screenshot of [Textadept](http://foicica.com/textadept/))
|
||||
|
||||
DCD consists of a client and a server. The client (dcd-client) is used by a text editor script or from the command line.
|
||||
The server (dcd-server) is responsible for caching imported files, calculating autocomplete information, and sending it
|
||||
back to the client.
|
||||
|
||||
#Status
|
||||
*This program is still in an alpha state.*
|
||||
This program is reasonably stable.
|
||||
|
||||
* Working:
|
||||
* Autocompletion of properties of built-in types such as int, float, double, etc.
|
||||
|
|
@ -21,17 +23,17 @@ back to the client.
|
|||
* Finding the declaration location of a symbol at the cursor
|
||||
* *import* statement completions
|
||||
* Display of documentation comments in function call tips
|
||||
* *alias this*
|
||||
* Not working:
|
||||
* Automatic starting of the server by the client
|
||||
* UFCS
|
||||
* Autocompletion of declarations with template arguments
|
||||
* *auto* declarations
|
||||
* *alias this*
|
||||
* Determining the type of an enum member when no base type is specified, but the first member has an initialaizer
|
||||
* That one feature that you *REALLY* needed
|
||||
|
||||
#Setup
|
||||
1. Install a recent D compiler. DCD is only tested with DMD 2.064.2
|
||||
1. Install a recent D compiler. DCD is tested with 2.065 and the 2.066 betas.
|
||||
1. Run ```git submodule update --init``` after cloning this repository to grab the MessagePack and Datapacked libraries and the parser from DScanner.
|
||||
1. run the ```build.sh``` script to build the client and server. (Or build.bat on Windows)
|
||||
1. Configure your text editor to call the dcd-client program. See the *editors* folder for directions on configuring your specific editor.
|
||||
|
|
|
|||
33
actypes.d
33
actypes.d
|
|
@ -107,7 +107,11 @@ public:
|
|||
ACSymbol*[] getPartsByName(string name)
|
||||
{
|
||||
ACSymbol s = ACSymbol(name);
|
||||
return array(parts.equalRange(&s));
|
||||
auto er = parts.equalRange(&s);
|
||||
if (er.empty)
|
||||
return array(aliasThisParts.equalRange(&s));
|
||||
else
|
||||
return array(er);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -121,6 +125,11 @@ public:
|
|||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) parts;
|
||||
|
||||
/**
|
||||
* Symbols included due to an alias this.
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) aliasThisParts;
|
||||
|
||||
/**
|
||||
* Calltip to display if this is a function
|
||||
*/
|
||||
|
|
@ -233,14 +242,9 @@ struct Scope
|
|||
{
|
||||
import std.range;
|
||||
ACSymbol s = ACSymbol(name);
|
||||
auto r = array(symbols.equalRange(&s));
|
||||
foreach (i; r)
|
||||
{
|
||||
import std.string;
|
||||
assert (i.name == name, format("%s %s %d", i.name, name, r.length));
|
||||
}
|
||||
if (r.length > 0)
|
||||
return cast(typeof(return)) r;
|
||||
auto er = symbols.equalRange(&s);
|
||||
if (!er.empty)
|
||||
return cast(typeof(return)) array(er);
|
||||
if (parent is null)
|
||||
return [];
|
||||
return parent.getSymbolsByName(name);
|
||||
|
|
@ -262,6 +266,13 @@ struct Scope
|
|||
return s.getSymbolsByName(name);
|
||||
}
|
||||
|
||||
ACSymbol*[] getSymbolsAtGlobalScope(string name)
|
||||
{
|
||||
if (parent !is null)
|
||||
return parent.getSymbolsAtGlobalScope(name);
|
||||
return getSymbolsByName(name);
|
||||
}
|
||||
|
||||
/// Imports contained in this scope
|
||||
UnrolledList!(ImportInformation*) importInformation;
|
||||
|
||||
|
|
@ -313,7 +324,7 @@ TTree!(ACSymbol*, true, "a < b", false) arraySymbols;
|
|||
TTree!(ACSymbol*, true, "a < b", false) assocArraySymbols;
|
||||
|
||||
/**
|
||||
* Enum, union, class, and interface properties
|
||||
* Struct, enum, union, class, and interface properties
|
||||
*/
|
||||
TTree!(ACSymbol*, true, "a < b", false) aggregateSymbols;
|
||||
|
||||
|
|
@ -506,7 +517,7 @@ static this()
|
|||
s.parts.insert(stringof_);
|
||||
}
|
||||
|
||||
aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.variableName));
|
||||
aggregateSymbols.insert(allocate!ACSymbol(Mallocator.it, "tupleof", CompletionKind.keyword));
|
||||
aggregateSymbols.insert(mangleof_);
|
||||
aggregateSymbols.insert(alignof_);
|
||||
aggregateSymbols.insert(sizeof_);
|
||||
|
|
|
|||
|
|
@ -185,7 +185,6 @@ AutocompleteResponse complete(const AutocompleteRequest request)
|
|||
case tok!"[":
|
||||
case tok!";":
|
||||
case tok!":":
|
||||
// TODO: global scope
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -299,8 +298,16 @@ ACSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
Log.trace("Getting symbols from token chain",
|
||||
tokens.map!stringToken);
|
||||
// Find the symbol corresponding to the beginning of the chain
|
||||
ACSymbol*[] symbols = completionScope.getSymbolsByNameAndCursor(
|
||||
stringToken(tokens[0]), cursorPosition);
|
||||
ACSymbol*[] symbols;
|
||||
if (tokens[0] == tok!"." && tokens.length > 1)
|
||||
{
|
||||
tokens = tokens[1 .. $];
|
||||
Log.info("Looking for ", stringToken(tokens[0]), " at global scope");
|
||||
symbols = completionScope.getSymbolsAtGlobalScope(stringToken(tokens[0]));
|
||||
}
|
||||
else
|
||||
symbols = completionScope.getSymbolsByNameAndCursor(stringToken(tokens[0]), cursorPosition);
|
||||
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
Log.error("Could not find declaration of ", stringToken(tokens[0]),
|
||||
|
|
@ -493,6 +500,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
|
||||
if (completionType == CompletionType.identifiers)
|
||||
{
|
||||
import containers.ttree;
|
||||
if (symbols[0].qualifier == SymbolQualifier.func
|
||||
|| symbols[0].kind == CompletionKind.functionName)
|
||||
{
|
||||
|
|
@ -501,7 +509,10 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
if (symbols.length == 0)
|
||||
return;
|
||||
}
|
||||
foreach (s; symbols[0].parts[].filter!(a => a.name !is null
|
||||
TTree!(ACSymbol*, true, "a < b", false) parts;
|
||||
parts.insert(symbols[0].parts[]);
|
||||
parts.insert(symbols[0].aliasThisParts[]);
|
||||
foreach (s; parts[].filter!(a => a.name !is null
|
||||
&& a.name.length > 0 && a.name[0] != '*'
|
||||
&& (partial is null ? true : a.name.toUpper().startsWith(partial.toUpper()))
|
||||
&& !response.completions.canFind(a.name)))
|
||||
|
|
@ -542,7 +553,15 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
{
|
||||
auto constructor = symbols[0].getPartsByName("*constructor*");
|
||||
if (constructor.length == 0)
|
||||
{
|
||||
// Build a call tip out of the struct fields
|
||||
if (symbols[0].kind == CompletionKind.structName)
|
||||
{
|
||||
response.completionType = CompletionType.calltips;
|
||||
response.completions = [generateStructConstructorCalltip(symbols[0])];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
symbols = constructor;
|
||||
|
|
@ -560,6 +579,34 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
}
|
||||
|
||||
string generateStructConstructorCalltip(const ACSymbol* symbol)
|
||||
in
|
||||
{
|
||||
assert (symbol.kind == CompletionKind.structName);
|
||||
}
|
||||
body
|
||||
{
|
||||
string generatedStructConstructorCalltip = "this(";
|
||||
size_t i = 0;
|
||||
immutable c = count(symbol.parts[].filter!(a => a.kind == CompletionKind.variableName));
|
||||
foreach (part; array(symbol.parts[]).sort!((a, b) => a.location < b.location))
|
||||
{
|
||||
if (part.kind != CompletionKind.variableName)
|
||||
continue;
|
||||
i++;
|
||||
if (part.type !is null)
|
||||
{
|
||||
generatedStructConstructorCalltip ~= part.type.name;
|
||||
generatedStructConstructorCalltip ~= " ";
|
||||
}
|
||||
generatedStructConstructorCalltip ~= part.name;
|
||||
if (i < c)
|
||||
generatedStructConstructorCalltip ~= ", ";
|
||||
}
|
||||
generatedStructConstructorCalltip ~= ")";
|
||||
return generatedStructConstructorCalltip;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
1
build.sh
1
build.sh
|
|
@ -37,6 +37,7 @@ dmd\
|
|||
containers/src/containers/unrolledlist.d\
|
||||
containers/src/containers/hashset.d\
|
||||
containers/src/containers/internal/hash.d\
|
||||
containers/src/containers/internal/node.d\
|
||||
containers/src/containers/slist.d\
|
||||
msgpack-d/src/msgpack.d\
|
||||
-Icontainers/src\
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2a72525f649850f452f21e7f362f70440f487a61
|
||||
Subproject commit 74b394404947f8c1ea9c6e769fdb413db049d27d
|
||||
|
|
@ -69,11 +69,6 @@ private:
|
|||
case className:
|
||||
case interfaceName:
|
||||
resolveInheritance(currentSymbol);
|
||||
goto case structName;
|
||||
case structName:
|
||||
case unionName:
|
||||
resolveAliasThis(currentSymbol);
|
||||
resolveMixinTemplates(currentSymbol);
|
||||
break;
|
||||
case variableName:
|
||||
case memberVariableName:
|
||||
|
|
@ -85,6 +80,8 @@ private:
|
|||
t = t.type;
|
||||
currentSymbol.acSymbol.type = t;
|
||||
break;
|
||||
case structName:
|
||||
case unionName:
|
||||
case enumName:
|
||||
case keyword:
|
||||
case enumMember:
|
||||
|
|
@ -97,10 +94,24 @@ private:
|
|||
case mixinTemplateName:
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (child; currentSymbol.children)
|
||||
{
|
||||
thirdPass(child);
|
||||
}
|
||||
|
||||
with (CompletionKind) switch (currentSymbol.acSymbol.kind)
|
||||
{
|
||||
case className:
|
||||
case interfaceName:
|
||||
case structName:
|
||||
case unionName:
|
||||
resolveAliasThis(currentSymbol);
|
||||
resolveMixinTemplates(currentSymbol);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void resolveInheritance(SemanticSymbol* currentSymbol)
|
||||
|
|
@ -129,10 +140,16 @@ private:
|
|||
|
||||
void resolveAliasThis(SemanticSymbol* currentSymbol)
|
||||
{
|
||||
// TODO:
|
||||
foreach (aliasThis; currentSymbol.aliasThis)
|
||||
{
|
||||
auto parts = currentSymbol.acSymbol.getPartsByName(aliasThis);
|
||||
if (parts.length == 0 || parts[0].type is null)
|
||||
continue;
|
||||
currentSymbol.acSymbol.aliasThisParts.insert(parts[0].type.parts[]);
|
||||
}
|
||||
}
|
||||
|
||||
void resolveMixinTemplates(SemanticSymbol* currentSymbol)
|
||||
void resolveMixinTemplates(SemanticSymbol*)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue