Support alias declarations
This commit is contained in:
parent
2bf29e877a
commit
f458362ae7
|
@ -15,16 +15,16 @@ back to the client.
|
|||
* Autocompletion of __traits, scope, and extern arguments
|
||||
* Autocompletion of enums
|
||||
* Autocompletion of class, struct, and interface instances.
|
||||
* Display of call tips for functions and constructors
|
||||
* Display of call tips for functions, constructors, and variables of function type
|
||||
* alias declarations
|
||||
* Not working:
|
||||
* Automatic starting of the server by the client
|
||||
* Windows support (I don't know that it won't work, but this program is not tested on Windows yet)
|
||||
* UFCS
|
||||
* Templated declarations
|
||||
* import statement completions
|
||||
* *import* statement completions
|
||||
* Fields inherited from super classes or implemented interfaces.
|
||||
* *auto* declarations
|
||||
* alias declarations
|
||||
* Determining the type of an enum member when no base type is specified, but the first member has an initialaizer
|
||||
* Public imports
|
||||
* That one feature that you *REALLY* needed
|
||||
|
|
29
actypes.d
29
actypes.d
|
@ -215,15 +215,20 @@ public:
|
|||
// don't have any indirection
|
||||
foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName
|
||||
|| a.kind == CompletionKind.functionName || a.kind == CompletionKind.memberVariableName
|
||||
|| a.kind == CompletionKind.enumMember) && a.resolvedType is null)())
|
||||
|| a.kind == CompletionKind.enumMember || a.kind == CompletionKind.aliasName)
|
||||
&& a.resolvedType is null)())
|
||||
{
|
||||
//writeln("Resolving type of symbol ", s.name);
|
||||
writeln("Resolving type of symbol ", s.name);
|
||||
Type type = s.type;
|
||||
if (type is null)
|
||||
{
|
||||
//writeln("Could not find it due to null type");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.type2.builtinType != TokenType.invalid)
|
||||
{
|
||||
//writeln("It was a built-in type");
|
||||
// This part is easy. Autocomplete properties of built-in types
|
||||
s.resolvedType = findSymbolsInScope(getTokenValue(type.type2.builtinType))[0];
|
||||
}
|
||||
|
@ -235,14 +240,30 @@ public:
|
|||
// TODO: Does not work with qualified names or template instances
|
||||
Symbol sym = type.type2.symbol;
|
||||
if (sym.identifierOrTemplateChain.identifiersOrTemplateInstances.length != 1)
|
||||
return;
|
||||
{
|
||||
writeln("Could not resolve type");
|
||||
continue;
|
||||
}
|
||||
ACSymbol[] resolvedType = findSymbolsInCurrentScope(s.location,
|
||||
sym.identifierOrTemplateChain.identifiersOrTemplateInstances[0].identifier.value);
|
||||
if (resolvedType.length > 0)
|
||||
if (resolvedType.length > 0 && (resolvedType[0].kind == CompletionKind.interfaceName
|
||||
|| resolvedType[0].kind == CompletionKind.className
|
||||
|| resolvedType[0].kind == CompletionKind.aliasName
|
||||
|| resolvedType[0].kind == CompletionKind.unionName
|
||||
|| resolvedType[0].kind == CompletionKind.structName))
|
||||
{
|
||||
writeln("Type resolved to ", resolvedType[0].name, " which has kind ",
|
||||
resolvedType[0].kind, " and call tip ", resolvedType[0].calltip);
|
||||
s.resolvedType = resolvedType[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln(type);
|
||||
}
|
||||
foreach (suffix; type.typeSuffixes)
|
||||
{
|
||||
//writeln("Handling type suffix");
|
||||
// Handle type suffixes for declarations, e.g.:
|
||||
// int[] a;
|
||||
// SomeClass[string] b;
|
||||
|
|
64
acvisitor.d
64
acvisitor.d
|
@ -256,11 +256,22 @@ class AutocompleteVisitor : ASTVisitor
|
|||
// writeln("VariableDeclaration visit");
|
||||
foreach (d; dec.declarators)
|
||||
{
|
||||
auto symbol = new ACSymbol;
|
||||
ACSymbol symbol = new ACSymbol;
|
||||
if (dec.type.typeSuffixes.length > 0
|
||||
&& dec.type.typeSuffixes[$-1].delegateOrFunction != TokenType.invalid)
|
||||
{
|
||||
TypeSuffix suffix = dec.type.typeSuffixes[$ - 1];
|
||||
dec.type.typeSuffixes = dec.type.typeSuffixes[0 .. $ - 1];
|
||||
symbol.calltip = "%s %s%s".format(dec.type,
|
||||
suffix.delegateOrFunction.value,
|
||||
suffix.parameters.toString());
|
||||
}
|
||||
symbol.kind = CompletionKind.variableName;
|
||||
|
||||
symbol.type = dec.type;
|
||||
symbol.name = d.name.value;
|
||||
symbol.location = d.name.startIndex;
|
||||
symbol.kind = CompletionKind.variableName;
|
||||
|
||||
if (parentSymbol is null)
|
||||
symbols ~= symbol;
|
||||
else
|
||||
|
@ -269,6 +280,55 @@ class AutocompleteVisitor : ASTVisitor
|
|||
}
|
||||
}
|
||||
|
||||
override void visit(AliasDeclaration dec)
|
||||
{
|
||||
if (dec.type is null) foreach (aliasPart; dec.initializers)
|
||||
{
|
||||
ACSymbol aliasSymbol = new ACSymbol;
|
||||
aliasSymbol.kind = CompletionKind.aliasName;
|
||||
aliasSymbol.location = aliasPart.name.startIndex;
|
||||
aliasSymbol.type = aliasPart.type;
|
||||
if (aliasPart.type.typeSuffixes.length > 0
|
||||
&& aliasPart.type.typeSuffixes[$-1].delegateOrFunction != TokenType.invalid)
|
||||
{
|
||||
TypeSuffix suffix = aliasPart.type.typeSuffixes[$ - 1];
|
||||
aliasPart.type.typeSuffixes = aliasPart.type.typeSuffixes[0 .. $ - 1];
|
||||
aliasSymbol.calltip = "%s %s%s".format(dec.type,
|
||||
suffix.delegateOrFunction.value,
|
||||
suffix.parameters.toString());
|
||||
}
|
||||
if (parentSymbol is null)
|
||||
symbols ~= aliasSymbol;
|
||||
else
|
||||
parentSymbol.parts ~= aliasSymbol;
|
||||
scope_.symbols ~= aliasSymbol;
|
||||
}
|
||||
else
|
||||
{
|
||||
// writeln("Visiting alias declaration ", dec.name.value);
|
||||
ACSymbol aliasSymbol = new ACSymbol;
|
||||
aliasSymbol.kind = CompletionKind.aliasName;
|
||||
aliasSymbol.name = dec.name.value;
|
||||
aliasSymbol.type = dec.type;
|
||||
if (dec.type.typeSuffixes.length > 0
|
||||
&& dec.type.typeSuffixes[$-1].delegateOrFunction != TokenType.invalid)
|
||||
{
|
||||
TypeSuffix suffix = dec.type.typeSuffixes[$ - 1];
|
||||
dec.type.typeSuffixes = dec.type.typeSuffixes[0 .. $ - 1];
|
||||
aliasSymbol.calltip = "%s %s%s".format(dec.type,
|
||||
suffix.delegateOrFunction.value,
|
||||
suffix.parameters.toString());
|
||||
}
|
||||
aliasSymbol.location = dec.name.startIndex;
|
||||
if (parentSymbol is null)
|
||||
symbols ~= aliasSymbol;
|
||||
else
|
||||
parentSymbol.parts ~= aliasSymbol;
|
||||
scope_.symbols ~= aliasSymbol;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override void visit(ImportDeclaration dec)
|
||||
{
|
||||
// TODO: handle public imports
|
||||
|
|
|
@ -163,12 +163,16 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
if (completionType == CompletionType.identifiers
|
||||
&& symbols[0].kind == CompletionKind.memberVariableName
|
||||
|| symbols[0].kind == CompletionKind.variableName
|
||||
|| symbols[0].kind == CompletionKind.aliasName
|
||||
|| symbols[0].kind == CompletionKind.enumMember)
|
||||
{
|
||||
symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType];
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
//writeln("Could not figure it out");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
loop: for (size_t i = 1; i < tokens.length; i++)
|
||||
{
|
||||
|
@ -223,7 +227,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
symbols = symbols[0].getPartsByName(tokens[i].value);
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
//writeln("Couldn't find it.");
|
||||
// writeln("Couldn't find it.");
|
||||
break loop;
|
||||
}
|
||||
if (symbols[0].kind == CompletionKind.variableName
|
||||
|
@ -233,7 +237,18 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
&& (completionType == CompletionType.identifiers
|
||||
|| i + 1 < tokens.length)))
|
||||
{
|
||||
symbols = symbols[0].resolvedType is null ? [] :[symbols[0].resolvedType];
|
||||
symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType];
|
||||
}
|
||||
if (symbols[0].kind == CompletionKind.aliasName
|
||||
&& (completionType == CompletionType.identifiers
|
||||
|| i + 1 < tokens.length))
|
||||
{
|
||||
symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType];
|
||||
}
|
||||
if (symbols.length == 0)
|
||||
{
|
||||
// writeln("Couldn't find it.");
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
case lParen:
|
||||
|
@ -303,7 +318,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|||
}
|
||||
else if (completionType == CompletionType.calltips)
|
||||
{
|
||||
if (symbols[0].kind != CompletionKind.functionName)
|
||||
//writeln("Showing call tips for ", symbols[0].name, " of type ", symbols[0].kind);
|
||||
if (symbols[0].kind != CompletionKind.functionName
|
||||
&& symbols[0].calltip is null)
|
||||
{
|
||||
auto call = symbols[0].getPartsByName("opCall");
|
||||
if (call.length == 0)
|
||||
|
@ -386,6 +403,7 @@ T getExpression(T)(T beforeTokens)
|
|||
open = rBracket;
|
||||
close = lBracket;
|
||||
skip:
|
||||
auto bookmark = i;
|
||||
int depth = 1;
|
||||
do
|
||||
{
|
||||
|
@ -398,6 +416,21 @@ T getExpression(T)(T beforeTokens)
|
|||
else if (beforeTokens[i].type == close)
|
||||
depth--;
|
||||
} while (true);
|
||||
// check the current token after skipping parens to the left.
|
||||
// if it's a loop keyword, pretend we never skipped the parens.
|
||||
if (i > 0) switch (beforeTokens[i - 1].type)
|
||||
{
|
||||
case TokenType.if_:
|
||||
case TokenType.while_:
|
||||
case TokenType.for_:
|
||||
case TokenType.foreach_:
|
||||
case TokenType.foreach_reverse_:
|
||||
case TokenType.do_:
|
||||
i = bookmark + 1;
|
||||
break expressionLoop;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (hasSpecialPrefix)
|
||||
|
|
3
client.d
3
client.d
|
@ -150,6 +150,8 @@ int main(string[] args)
|
|||
AutocompleteResponse response;
|
||||
msgpack.unpack(buffer[0..bytesReceived], response);
|
||||
|
||||
if (response.completions.length > 0)
|
||||
{
|
||||
writeln(response.completionType);
|
||||
if (response.completionType == CompletionType.identifiers)
|
||||
{
|
||||
|
@ -165,6 +167,7 @@ int main(string[] args)
|
|||
writeln(completion);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ function M.registerImages()
|
|||
buffer:register_image(8, M.STRUCT)
|
||||
buffer:register_image(9, M.INTERFACE)
|
||||
buffer:register_image(10, M.ENUM)
|
||||
buffer:register_image(11, M.ALIAS)
|
||||
end
|
||||
|
||||
local function showCompletionList(r)
|
||||
|
@ -50,6 +51,8 @@ local function showCompletionList(r)
|
|||
completion = completion .. "?4"
|
||||
elseif kind == "P" then
|
||||
completion = completion .. "?3"
|
||||
elseif kind == "l" then
|
||||
completion = completion .. "?11"
|
||||
end
|
||||
completions[#completions + 1] = completion
|
||||
end
|
||||
|
@ -111,6 +114,7 @@ function M.autocomplete(ch)
|
|||
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName
|
||||
local p = io.popen(command, "r")
|
||||
local r = p:read("*a")
|
||||
--print(r)
|
||||
if r ~= "\n" then
|
||||
if r:match("^identifiers.*") then
|
||||
showCompletionList(r)
|
||||
|
@ -122,6 +126,45 @@ function M.autocomplete(ch)
|
|||
end
|
||||
end
|
||||
|
||||
M.ALIAS =[[
|
||||
/* XPM */
|
||||
static char * alias_xpm[] = {
|
||||
"16 16 17 1",
|
||||
" c None",
|
||||
". c #547AA0",
|
||||
"+ c #547BA2",
|
||||
"@ c #547CA4",
|
||||
"# c #F0F0F0",
|
||||
"$ c #547DA6",
|
||||
"% c #F5F5F5",
|
||||
"& c #547EA8",
|
||||
"* c #FBFBFB",
|
||||
"= c #F7F7F7",
|
||||
"- c #F2F2F2",
|
||||
"; c #547BA3",
|
||||
"> c #ECECEC",
|
||||
", c #547AA1",
|
||||
"' c #E7E7E7",
|
||||
") c #54799F",
|
||||
"! c #54789D",
|
||||
" ",
|
||||
" ",
|
||||
" .......... ",
|
||||
" ++++++++++++ ",
|
||||
" @@@@@##@@@@@ ",
|
||||
" $$$$%%%%$$$$ ",
|
||||
" &&&&****&&&& ",
|
||||
" &&&==&&==&&& ",
|
||||
" $$$==$$==$$$ ",
|
||||
" @@@------@@@ ",
|
||||
" ;;>>>>>>>>;; ",
|
||||
" ,,'',,,,'',, ",
|
||||
" )))))))))))) ",
|
||||
" !!!!!!!!!! ",
|
||||
" ",
|
||||
" "};
|
||||
]]
|
||||
|
||||
-- union icon
|
||||
M.UNION = [[
|
||||
/* XPM */
|
||||
|
|
|
@ -56,14 +56,17 @@ enum CompletionKind : char
|
|||
/// package name
|
||||
packageName = 'P',
|
||||
|
||||
// module name
|
||||
/// module name
|
||||
moduleName = 'M',
|
||||
|
||||
// array
|
||||
/// array
|
||||
array = 'a',
|
||||
|
||||
// associative array
|
||||
/// associative array
|
||||
assocArray = 'A',
|
||||
|
||||
/// alias name
|
||||
aliasName = 'l',
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue