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 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

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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 */

View File

@ -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',
}
/**