Support alias declarations

This commit is contained in:
Hackerpilot 2013-08-14 21:30:41 +00:00
parent 2bf29e877a
commit f458362ae7
7 changed files with 230 additions and 67 deletions

View File

@ -15,16 +15,16 @@ back to the client.
* Autocompletion of __traits, scope, and extern arguments * Autocompletion of __traits, scope, and extern arguments
* Autocompletion of enums * Autocompletion of enums
* Autocompletion of class, struct, and interface instances. * 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: * Not working:
* Automatic starting of the server by the client * 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) * Windows support (I don't know that it won't work, but this program is not tested on Windows yet)
* UFCS * UFCS
* Templated declarations * Templated declarations
* import statement completions * *import* statement completions
* Fields inherited from super classes or implemented interfaces. * Fields inherited from super classes or implemented interfaces.
* *auto* declarations * *auto* declarations
* alias declarations
* Determining the type of an enum member when no base type is specified, but the first member has an initialaizer * Determining the type of an enum member when no base type is specified, but the first member has an initialaizer
* Public imports * Public imports
* That one feature that you *REALLY* needed * That one feature that you *REALLY* needed

View File

@ -215,15 +215,20 @@ public:
// don't have any indirection // don't have any indirection
foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName foreach (ref s; symbols.filter!(a => (a.kind == CompletionKind.variableName
|| a.kind == CompletionKind.functionName || a.kind == CompletionKind.memberVariableName || 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; Type type = s.type;
if (type is null) if (type is null)
{
//writeln("Could not find it due to null type");
continue; continue;
}
if (type.type2.builtinType != TokenType.invalid) if (type.type2.builtinType != TokenType.invalid)
{ {
//writeln("It was a built-in type");
// This part is easy. Autocomplete properties of built-in types // This part is easy. Autocomplete properties of built-in types
s.resolvedType = findSymbolsInScope(getTokenValue(type.type2.builtinType))[0]; s.resolvedType = findSymbolsInScope(getTokenValue(type.type2.builtinType))[0];
} }
@ -235,14 +240,30 @@ public:
// TODO: Does not work with qualified names or template instances // TODO: Does not work with qualified names or template instances
Symbol sym = type.type2.symbol; Symbol sym = type.type2.symbol;
if (sym.identifierOrTemplateChain.identifiersOrTemplateInstances.length != 1) if (sym.identifierOrTemplateChain.identifiersOrTemplateInstances.length != 1)
return; {
writeln("Could not resolve type");
continue;
}
ACSymbol[] resolvedType = findSymbolsInCurrentScope(s.location, ACSymbol[] resolvedType = findSymbolsInCurrentScope(s.location,
sym.identifierOrTemplateChain.identifiersOrTemplateInstances[0].identifier.value); 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]; s.resolvedType = resolvedType[0];
} }
}
else
{
writeln(type);
}
foreach (suffix; type.typeSuffixes) foreach (suffix; type.typeSuffixes)
{ {
//writeln("Handling type suffix");
// Handle type suffixes for declarations, e.g.: // Handle type suffixes for declarations, e.g.:
// int[] a; // int[] a;
// SomeClass[string] b; // SomeClass[string] b;

View File

@ -256,11 +256,22 @@ class AutocompleteVisitor : ASTVisitor
// writeln("VariableDeclaration visit"); // writeln("VariableDeclaration visit");
foreach (d; dec.declarators) 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.type = dec.type;
symbol.name = d.name.value; symbol.name = d.name.value;
symbol.location = d.name.startIndex; symbol.location = d.name.startIndex;
symbol.kind = CompletionKind.variableName;
if (parentSymbol is null) if (parentSymbol is null)
symbols ~= symbol; symbols ~= symbol;
else 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) override void visit(ImportDeclaration dec)
{ {
// TODO: handle public imports // TODO: handle public imports

View File

@ -163,12 +163,16 @@ void setCompletions(T)(ref AutocompleteResponse response,
if (completionType == CompletionType.identifiers if (completionType == CompletionType.identifiers
&& symbols[0].kind == CompletionKind.memberVariableName && symbols[0].kind == CompletionKind.memberVariableName
|| symbols[0].kind == CompletionKind.variableName || symbols[0].kind == CompletionKind.variableName
|| symbols[0].kind == CompletionKind.aliasName
|| symbols[0].kind == CompletionKind.enumMember) || symbols[0].kind == CompletionKind.enumMember)
{ {
symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType]; symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType];
if (symbols.length == 0) if (symbols.length == 0)
{
//writeln("Could not figure it out");
return; return;
} }
}
loop: for (size_t i = 1; i < tokens.length; i++) loop: for (size_t i = 1; i < tokens.length; i++)
{ {
@ -235,6 +239,17 @@ void setCompletions(T)(ref AutocompleteResponse response,
{ {
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; break;
case lParen: case lParen:
open = TokenType.lParen; open = TokenType.lParen;
@ -303,7 +318,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
} }
else if (completionType == CompletionType.calltips) 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"); auto call = symbols[0].getPartsByName("opCall");
if (call.length == 0) if (call.length == 0)
@ -386,6 +403,7 @@ T getExpression(T)(T beforeTokens)
open = rBracket; open = rBracket;
close = lBracket; close = lBracket;
skip: skip:
auto bookmark = i;
int depth = 1; int depth = 1;
do do
{ {
@ -398,6 +416,21 @@ T getExpression(T)(T beforeTokens)
else if (beforeTokens[i].type == close) else if (beforeTokens[i].type == close)
depth--; depth--;
} while (true); } 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; break;
default: default:
if (hasSpecialPrefix) if (hasSpecialPrefix)

View File

@ -150,6 +150,8 @@ int main(string[] args)
AutocompleteResponse response; AutocompleteResponse response;
msgpack.unpack(buffer[0..bytesReceived], response); msgpack.unpack(buffer[0..bytesReceived], response);
if (response.completions.length > 0)
{
writeln(response.completionType); writeln(response.completionType);
if (response.completionType == CompletionType.identifiers) if (response.completionType == CompletionType.identifiers)
{ {
@ -165,6 +167,7 @@ int main(string[] args)
writeln(completion); writeln(completion);
} }
} }
}
return 0; return 0;
} }

View File

@ -16,6 +16,7 @@ function M.registerImages()
buffer:register_image(8, M.STRUCT) buffer:register_image(8, M.STRUCT)
buffer:register_image(9, M.INTERFACE) buffer:register_image(9, M.INTERFACE)
buffer:register_image(10, M.ENUM) buffer:register_image(10, M.ENUM)
buffer:register_image(11, M.ALIAS)
end end
local function showCompletionList(r) local function showCompletionList(r)
@ -50,6 +51,8 @@ local function showCompletionList(r)
completion = completion .. "?4" completion = completion .. "?4"
elseif kind == "P" then elseif kind == "P" then
completion = completion .. "?3" completion = completion .. "?3"
elseif kind == "l" then
completion = completion .. "?11"
end end
completions[#completions + 1] = completion completions[#completions + 1] = completion
end end
@ -111,6 +114,7 @@ function M.autocomplete(ch)
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName
local p = io.popen(command, "r") local p = io.popen(command, "r")
local r = p:read("*a") local r = p:read("*a")
--print(r)
if r ~= "\n" then if r ~= "\n" then
if r:match("^identifiers.*") then if r:match("^identifiers.*") then
showCompletionList(r) showCompletionList(r)
@ -122,6 +126,45 @@ function M.autocomplete(ch)
end end
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 -- union icon
M.UNION = [[ M.UNION = [[
/* XPM */ /* XPM */

View File

@ -56,14 +56,17 @@ enum CompletionKind : char
/// package name /// package name
packageName = 'P', packageName = 'P',
// module name /// module name
moduleName = 'M', moduleName = 'M',
// array /// array
array = 'a', array = 'a',
// associative array /// associative array
assocArray = 'A', assocArray = 'A',
/// alias name
aliasName = 'l',
} }
/** /**