Handle array and map slicing and indexing properly

This commit is contained in:
Hackerpilot 2013-08-11 13:08:56 +00:00
parent cf65c47a85
commit 126e101e78
3 changed files with 213 additions and 199 deletions

View File

@ -223,7 +223,7 @@ public:
|| a.kind == CompletionKind.functionName || a.kind == CompletionKind.functionName
|| a.kind == CompletionKind.memberVariableName) && a.resolvedType is null)()) || a.kind == CompletionKind.memberVariableName) && 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)
continue; continue;

View File

@ -104,7 +104,7 @@ class AutocompleteVisitor : ASTVisitor
{ {
foreach (parameter; dec.parameters.parameters) foreach (parameter; dec.parameters.parameters)
{ {
writeln("Adding parameter ", parameter.name.value); // writeln("Adding parameter ", parameter.name.value);
ACSymbol paramSymbol = new ACSymbol; ACSymbol paramSymbol = new ACSymbol;
paramSymbol.name = parameter.name.value; paramSymbol.name = parameter.name.value;
paramSymbol.type = parameter.type; paramSymbol.type = parameter.type;
@ -114,7 +114,7 @@ class AutocompleteVisitor : ASTVisitor
} }
} }
writeln("Parameter symbols added"); // writeln("Parameter symbols added");
if (dec.returnType !is null) if (dec.returnType !is null)
{ {
symbol.calltip = format("%s %s%s", dec.returnType.toString(), symbol.calltip = format("%s %s%s", dec.returnType.toString(),
@ -129,7 +129,7 @@ class AutocompleteVisitor : ASTVisitor
if (functionBody !is null) if (functionBody !is null)
{ {
writeln("Processing function body"); // writeln("Processing function body");
auto s = scope_; auto s = scope_;
scope_ = new Scope(functionBody.startLocation, scope_ = new Scope(functionBody.startLocation,
functionBody.endLocation); functionBody.endLocation);

View File

@ -38,22 +38,22 @@ import constants;
AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths) AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
{ {
writeln("Got a completion request"); writeln("Got a completion request");
AutocompleteResponse response; AutocompleteResponse response;
LexerConfig config; LexerConfig config;
auto tokens = request.sourceCode.byToken(config); auto tokens = request.sourceCode.byToken(config);
auto tokenArray = tokens.array(); auto tokenArray = tokens.array();
auto sortedTokens = assumeSorted(tokenArray); auto sortedTokens = assumeSorted(tokenArray);
auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition); auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition);
if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.lParen) if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.lParen)
{ {
immutable(string)[] completions; immutable(string)[] completions;
switch (beforeTokens[$ - 2].type) switch (beforeTokens[$ - 2].type)
{ {
case TokenType.traits: case TokenType.traits:
completions = traits; completions = traits;
goto fillResponse; goto fillResponse;
case TokenType.scope_: case TokenType.scope_:
@ -68,91 +68,92 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
case TokenType.pragma_: case TokenType.pragma_:
completions = pragmas; completions = pragmas;
fillResponse: fillResponse:
response.completionType = CompletionType.identifiers; response.completionType = CompletionType.identifiers;
for (size_t i = 0; i < completions.length; i++) for (size_t i = 0; i < completions.length; i++)
{ {
response.completions ~= completions[i]; response.completions ~= completions[i];
response.completionKinds ~= CompletionKind.keyword; response.completionKinds ~= CompletionKind.keyword;
} }
break; break;
case TokenType.identifier: case TokenType.identifier:
case TokenType.rParen: case TokenType.rParen:
case TokenType.rBracket: case TokenType.rBracket:
auto visitor = processModule(tokenArray); auto visitor = processModule(tokenArray);
visitor.scope_.symbols ~= builtinSymbols; visitor.scope_.symbols ~= builtinSymbols;
auto expression = getExpression(beforeTokens[0 .. $ - 1]); auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(visitor, expression, request.cursorPosition, response.setCompletions(visitor, expression, request.cursorPosition,
CompletionType.calltips); CompletionType.calltips);
break; break;
default: default:
break; break;
} }
} }
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.dot) else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.dot)
{ {
switch (beforeTokens[$ - 2].type) switch (beforeTokens[$ - 2].type)
{ {
case TokenType.stringLiteral: case TokenType.stringLiteral:
case TokenType.wstringLiteral: case TokenType.wstringLiteral:
case TokenType.dstringLiteral: case TokenType.dstringLiteral:
foreach (symbol; arraySymbols) foreach (symbol; arraySymbols)
{ {
response.completionKinds ~= symbol.kind; response.completionKinds ~= symbol.kind;
response.completions ~= symbol.name; response.completions ~= symbol.name;
} }
response.completionType = CompletionType.identifiers; response.completionType = CompletionType.identifiers;
break; break;
case TokenType.int_: case TokenType.int_:
case TokenType.uint_: case TokenType.uint_:
case TokenType.long_: case TokenType.long_:
case TokenType.ulong_: case TokenType.ulong_:
case TokenType.char_: case TokenType.char_:
case TokenType.wchar_: case TokenType.wchar_:
case TokenType.dchar_: case TokenType.dchar_:
case TokenType.bool_: case TokenType.bool_:
case TokenType.byte_: case TokenType.byte_:
case TokenType.ubyte_: case TokenType.ubyte_:
case TokenType.short_: case TokenType.short_:
case TokenType.ushort_: case TokenType.ushort_:
case TokenType.cent_: case TokenType.cent_:
case TokenType.ucent_: case TokenType.ucent_:
case TokenType.float_: case TokenType.float_:
case TokenType.ifloat_: case TokenType.ifloat_:
case TokenType.cfloat_: case TokenType.cfloat_:
case TokenType.idouble_: case TokenType.idouble_:
case TokenType.cdouble_: case TokenType.cdouble_:
case TokenType.double_: case TokenType.double_:
case TokenType.real_: case TokenType.real_:
case TokenType.ireal_: case TokenType.ireal_:
case TokenType.creal_: case TokenType.creal_:
case TokenType.identifier: case TokenType.identifier:
case TokenType.rParen: case TokenType.rParen:
case TokenType.rBracket: case TokenType.rBracket:
case TokenType.this_: case TokenType.this_:
auto visitor = processModule(tokenArray); auto visitor = processModule(tokenArray);
visitor.scope_.symbols ~= builtinSymbols; visitor.scope_.symbols ~= builtinSymbols;
auto expression = getExpression(beforeTokens[0 .. $ - 1]); auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(visitor, expression, request.cursorPosition, response.setCompletions(visitor, expression, request.cursorPosition,
CompletionType.identifiers); CompletionType.identifiers);
break; break;
case TokenType.lParen: case TokenType.lParen:
case TokenType.lBrace: case TokenType.lBrace:
case TokenType.lBracket: case TokenType.lBracket:
case TokenType.semicolon: case TokenType.semicolon:
case TokenType.colon: case TokenType.colon:
// TODO: global scope // TODO: global scope
break; break;
default: default:
break; break;
} }
} }
return response; return response;
} }
void setCompletions(T)(ref AutocompleteResponse response, void setCompletions(T)(ref AutocompleteResponse response,
AutocompleteVisitor visitor, T tokens, size_t cursorPosition, AutocompleteVisitor visitor, T tokens, size_t cursorPosition,
CompletionType completionType) CompletionType completionType)
{ {
writeln("Getting completions for ", map!"a.value"(tokens)); writeln("Getting completions for ", map!"a.value"(tokens));
writeln("Resolving symbols for editor buffer"); writeln("Resolving symbols for editor buffer");
visitor.scope_.resolveSymbolTypes(); visitor.scope_.resolveSymbolTypes();
@ -176,73 +177,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
{ {
TokenType open; TokenType open;
TokenType close; TokenType close;
with (TokenType) switch (tokens[i].type)
{
case TokenType.int_:
case TokenType.uint_:
case TokenType.long_:
case TokenType.ulong_:
case TokenType.char_:
case TokenType.wchar_:
case TokenType.dchar_:
case TokenType.bool_:
case TokenType.byte_:
case TokenType.ubyte_:
case TokenType.short_:
case TokenType.ushort_:
case TokenType.cent_:
case TokenType.ucent_:
case TokenType.float_:
case TokenType.ifloat_:
case TokenType.cfloat_:
case TokenType.idouble_:
case TokenType.cdouble_:
case TokenType.double_:
case TokenType.real_:
case TokenType.ireal_:
case TokenType.creal_:
case this_:
symbol = symbol.getPartByName(getTokenValue(tokens[i].type));
if (symbol is null)
break loop;
break;
case identifier:
writeln("looking for ", tokens[i].value, " in ", symbol.name);
symbol = symbol.getPartByName(tokens[i].value);
if (symbol is null)
{
writeln("Couldn't find it.");
break loop;
}
if (symbol.kind == CompletionKind.variableName
|| symbol.kind == CompletionKind.memberVariableName
|| (symbol.kind == CompletionKind.functionName
&& (completionType == CompletionType.identifiers
|| i + 1 < tokens.length)))
{
symbol = symbol.resolvedType; void skip()
} {
break;
case lParen:
open = TokenType.lParen;
close = TokenType.rParen;
goto skip;
case lBracket:
open = TokenType.lBracket;
close = TokenType.rBracket;
// TODO: handle slicing
// TODO: handle opIndex
// TODO: handle opSlice
if (symbol.qualifier == SymbolQualifier.array
|| symbol.qualifier == SymbolQualifier.assocArray)
{
symbol = symbol.resolvedType;
goto skip;
}
else
return;
skip:
i++; i++;
for (int depth = 1; depth > 0 && i < tokens.length; i++) for (int depth = 1; depth > 0 && i < tokens.length; i++)
{ {
@ -254,6 +191,83 @@ void setCompletions(T)(ref AutocompleteResponse response,
if (depth == 0) break; if (depth == 0) break;
} }
} }
}
with (TokenType) switch (tokens[i].type)
{
case TokenType.int_:
case TokenType.uint_:
case TokenType.long_:
case TokenType.ulong_:
case TokenType.char_:
case TokenType.wchar_:
case TokenType.dchar_:
case TokenType.bool_:
case TokenType.byte_:
case TokenType.ubyte_:
case TokenType.short_:
case TokenType.ushort_:
case TokenType.cent_:
case TokenType.ucent_:
case TokenType.float_:
case TokenType.ifloat_:
case TokenType.cfloat_:
case TokenType.idouble_:
case TokenType.cdouble_:
case TokenType.double_:
case TokenType.real_:
case TokenType.ireal_:
case TokenType.creal_:
case this_:
symbol = symbol.getPartByName(getTokenValue(tokens[i].type));
if (symbol is null)
break loop;
break;
case identifier:
//writeln("looking for ", tokens[i].value, " in ", symbol.name);
symbol = symbol.getPartByName(tokens[i].value);
if (symbol is null)
{
//writeln("Couldn't find it.");
break loop;
}
if (symbol.kind == CompletionKind.variableName
|| symbol.kind == CompletionKind.memberVariableName
|| (symbol.kind == CompletionKind.functionName
&& (completionType == CompletionType.identifiers
|| i + 1 < tokens.length)))
{
symbol = symbol.resolvedType;
}
break;
case lParen:
open = TokenType.lParen;
close = TokenType.rParen;
skip();
break;
case lBracket:
open = TokenType.lBracket;
close = TokenType.rBracket;
// TODO: handle opIndex
// TODO: handle opSlice
if (symbol.qualifier == SymbolQualifier.array)
{
auto h = i;
skip();
Parser p;
p.setTokens(tokens[h .. i].array());
if (!p.isSliceExpression())
{
symbol = symbol.resolvedType;
}
}
else if (symbol.qualifier == SymbolQualifier.assocArray)
{
symbol = symbol.resolvedType;
skip();
}
else
return;
break; break;
case dot: case dot:
break; break;
@ -297,28 +311,28 @@ T getExpression(T)(T beforeTokens)
with (TokenType) switch (beforeTokens[i].type) with (TokenType) switch (beforeTokens[i].type)
{ {
case TokenType.int_: case TokenType.int_:
case TokenType.uint_: case TokenType.uint_:
case TokenType.long_: case TokenType.long_:
case TokenType.ulong_: case TokenType.ulong_:
case TokenType.char_: case TokenType.char_:
case TokenType.wchar_: case TokenType.wchar_:
case TokenType.dchar_: case TokenType.dchar_:
case TokenType.bool_: case TokenType.bool_:
case TokenType.byte_: case TokenType.byte_:
case TokenType.ubyte_: case TokenType.ubyte_:
case TokenType.short_: case TokenType.short_:
case TokenType.ushort_: case TokenType.ushort_:
case TokenType.cent_: case TokenType.cent_:
case TokenType.ucent_: case TokenType.ucent_:
case TokenType.float_: case TokenType.float_:
case TokenType.ifloat_: case TokenType.ifloat_:
case TokenType.cfloat_: case TokenType.cfloat_:
case TokenType.idouble_: case TokenType.idouble_:
case TokenType.cdouble_: case TokenType.cdouble_:
case TokenType.double_: case TokenType.double_:
case TokenType.real_: case TokenType.real_:
case TokenType.ireal_: case TokenType.ireal_:
case TokenType.creal_: case TokenType.creal_:
case this_: case this_:
case identifier: case identifier:
if (hasSpecialPrefix) if (hasSpecialPrefix)
@ -370,25 +384,25 @@ T getExpression(T)(T beforeTokens)
string createCamelCaseRegex(string input) string createCamelCaseRegex(string input)
{ {
dstring output; dstring output;
uint i; uint i;
foreach (dchar d; input) foreach (dchar d; input)
{ {
if (isLower(d)) if (isLower(d))
output ~= d; output ~= d;
else if (i > 0) else if (i > 0)
{ {
output ~= ".*"; output ~= ".*";
output ~= d; output ~= d;
} }
i++; i++;
} }
return to!string(output ~ ".*"); return to!string(output ~ ".*");
} }
unittest unittest
{ {
assert("ClNa".createCamelCaseRegex() == "Cl.*Na.*"); assert("ClNa".createCamelCaseRegex() == "Cl.*Na.*");
} }
/** /**
@ -399,13 +413,13 @@ static this()
auto bool_ = new ACSymbol("bool", CompletionKind.keyword); auto bool_ = new ACSymbol("bool", CompletionKind.keyword);
auto int_ = new ACSymbol("int", CompletionKind.keyword); auto int_ = new ACSymbol("int", CompletionKind.keyword);
auto long_ = new ACSymbol("long", CompletionKind.keyword); auto long_ = new ACSymbol("long", CompletionKind.keyword);
auto byte_ = new ACSymbol("byte", CompletionKind.keyword); auto byte_ = new ACSymbol("byte", CompletionKind.keyword);
auto dchar_ = new ACSymbol("dchar", CompletionKind.keyword); auto dchar_ = new ACSymbol("dchar", CompletionKind.keyword);
auto short_ = new ACSymbol("short", CompletionKind.keyword); auto short_ = new ACSymbol("short", CompletionKind.keyword);
auto ubyte_ = new ACSymbol("ubyte", CompletionKind.keyword); auto ubyte_ = new ACSymbol("ubyte", CompletionKind.keyword);
auto uint_ = new ACSymbol("uint", CompletionKind.keyword); auto uint_ = new ACSymbol("uint", CompletionKind.keyword);
auto ulong_ = new ACSymbol("ulong", CompletionKind.keyword); auto ulong_ = new ACSymbol("ulong", CompletionKind.keyword);
auto ushort_ = new ACSymbol("ushort", CompletionKind.keyword); auto ushort_ = new ACSymbol("ushort", CompletionKind.keyword);
auto wchar_ = new ACSymbol("wchar", CompletionKind.keyword); auto wchar_ = new ACSymbol("wchar", CompletionKind.keyword);
auto alignof_ = new ACSymbol("alignof", CompletionKind.keyword, ulong_); auto alignof_ = new ACSymbol("alignof", CompletionKind.keyword, ulong_);
@ -452,17 +466,17 @@ static this()
} }
auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword); auto cdouble_ = new ACSymbol("cdouble", CompletionKind.keyword);
auto cent_ = new ACSymbol("cent", CompletionKind.keyword); auto cent_ = new ACSymbol("cent", CompletionKind.keyword);
auto cfloat_ = new ACSymbol("cfloat", CompletionKind.keyword); auto cfloat_ = new ACSymbol("cfloat", CompletionKind.keyword);
auto char_ = new ACSymbol("char", CompletionKind.keyword); auto char_ = new ACSymbol("char", CompletionKind.keyword);
auto creal_ = new ACSymbol("creal", CompletionKind.keyword); auto creal_ = new ACSymbol("creal", CompletionKind.keyword);
auto double_ = new ACSymbol("double", CompletionKind.keyword); auto double_ = new ACSymbol("double", CompletionKind.keyword);
auto float_ = new ACSymbol("float", CompletionKind.keyword); auto float_ = new ACSymbol("float", CompletionKind.keyword);
auto idouble_ = new ACSymbol("idouble", CompletionKind.keyword); auto idouble_ = new ACSymbol("idouble", CompletionKind.keyword);
auto ifloat_ = new ACSymbol("ifloat", CompletionKind.keyword); auto ifloat_ = new ACSymbol("ifloat", CompletionKind.keyword);
auto ireal_ = new ACSymbol("ireal", CompletionKind.keyword); auto ireal_ = new ACSymbol("ireal", CompletionKind.keyword);
auto real_ = new ACSymbol("real", CompletionKind.keyword); auto real_ = new ACSymbol("real", CompletionKind.keyword);
auto ucent_ = new ACSymbol("ucent", CompletionKind.keyword); auto ucent_ = new ACSymbol("ucent", CompletionKind.keyword);
foreach (s; [cdouble_, cent_, cfloat_, char_, creal_, double_, float_, foreach (s; [cdouble_, cent_, cfloat_, char_, creal_, double_, float_,
idouble_, ifloat_, ireal_, real_, ucent_]) idouble_, ifloat_, ireal_, real_, ucent_])