Made autocompletion work when the cursor isn't at a dot or lparen

This commit is contained in:
Hackerpilot 2013-08-18 02:15:43 +00:00
parent 357c65f62b
commit 70cdbe4428
3 changed files with 71 additions and 16 deletions

View File

@ -159,6 +159,24 @@ public:
this.end = end;
}
ACSymbol[] getSymbolsInCurrentScope(size_t cursorPosition)
{
Scope s = findCurrentScope(cursorPosition);
if (s is null)
return [];
else
return s.getSymbols();
}
ACSymbol[] getSymbols()
{
ACSymbol[] rVal;
rVal ~= symbols;
if (parent !is null)
rVal ~= parent.getSymbols();
return rVal;
}
/**
* Finds the scope containing the cursor position, then searches for a
* symbol with the given name.
@ -169,7 +187,7 @@ public:
if (s is null)
{
writeln("Could not find scope");
return null;
return [];
}
else
return s.findSymbolsInScope(name);

View File

@ -48,9 +48,17 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
auto tokens = request.sourceCode.byToken(config);
auto tokenArray = tokens.array();
auto sortedTokens = assumeSorted(tokenArray);
string partial;
auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition);
if (beforeTokens.length >= 1 && beforeTokens[$ - 1] == TokenType.identifier)
{
//writeln("partial completion");
partial = beforeTokens[$ - 1].value;
beforeTokens = beforeTokens[0 .. $ - 1];
goto dotCompletion;
}
if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.lParen)
{
immutable(string)[] completions;
@ -92,6 +100,7 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
}
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.dot)
{
dotCompletion:
switch (beforeTokens[$ - 2].type)
{
case TokenType.stringLiteral:
@ -132,9 +141,10 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
case TokenType.rBracket:
case TokenType.this_:
auto visitor = processModule(tokenArray);
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
auto expression = getExpression(partial == null ? beforeTokens[0 .. $ - 1]
: beforeTokens);
response.setCompletions(visitor, expression, request.cursorPosition,
CompletionType.identifiers);
CompletionType.identifiers, partial);
break;
case TokenType.lParen:
case TokenType.lBrace:
@ -152,10 +162,10 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
void setCompletions(T)(ref AutocompleteResponse response,
AutocompleteVisitor visitor, T tokens, size_t cursorPosition,
CompletionType completionType)
CompletionType completionType, string partial = null)
{
// Autocomplete module imports instead of symbols
if (tokens[0].type == TokenType.import_)
if (tokens.length > 0 && tokens[0].type == TokenType.import_)
{
if (completionType == CompletionType.identifiers)
setImportCompletions(tokens, response);
@ -163,6 +173,26 @@ void setCompletions(T)(ref AutocompleteResponse response,
}
visitor.scope_.resolveSymbolTypes();
// Handle the simple case where we get all symbols in scope and filter it
// based on the currently entered text.
if (partial !is null && tokens.length == 0)
{
// writeln("Showing all symbols in current scope that start with ", partial);
foreach (s; visitor.scope_.getSymbolsInCurrentScope(cursorPosition)
.filter!(a => a.name.startsWith(partial)))
{
response.completionKinds ~= s.kind;
response.completions ~= s.name;
}
response.completionType = CompletionType.identifiers;
return;
}
if (tokens.length == 0)
return;
// Find the symbol corresponding to the beginning of the chain
ACSymbol[] symbols = visitor.scope_.findSymbolsInCurrentScope(cursorPosition, tokens[0].value);
if (symbols.length == 0)
{
@ -179,7 +209,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
symbols = symbols[0].resolvedType is null ? [] : [symbols[0].resolvedType];
if (symbols.length == 0)
{
//writeln("Could not figure it out");
return;
}
}
@ -233,11 +262,11 @@ void setCompletions(T)(ref AutocompleteResponse response,
break loop;
break;
case identifier:
writeln("looking for ", tokens[i].value, " in ", symbols[0].name);
// writeln("looking for ", tokens[i].value, " in ", symbols[0].name);
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
@ -317,7 +346,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
}
if (completionType == CompletionType.identifiers)
{
foreach (s; symbols[0].parts.filter!(a => a.name !is null && a.name[0] != '*'))
foreach (s; symbols[0].parts.filter!(a => a.name !is null
&& a.name[0] != '*'
&& (partial is null ? true : a.name.startsWith(partial))))
{
// writeln("Adding ", s.name, " to the completion list");
response.completionKinds ~= s.kind;

View File

@ -57,14 +57,18 @@ local function showCompletionList(r)
completions[#completions + 1] = completion
end
table.sort(completions, function(a, b) return string.upper(a) < string.upper(b) end)
buffer:auto_c_show(0, table.concat(completions, " "))
local charactersEntered = buffer.current_pos - buffer:word_start_position(buffer.current_pos)
if buffer.char_at[buffer.current_pos - 1] == string.byte('.') then charactersEntered = 0 end
print(charactersEntered)
buffer:auto_c_show(charactersEntered, table.concat(completions, " "))
--buffer.auto_c_fill_ups = "(.["
buffer.auto_c_choose_single = setting
end
local function showCurrentCallTip()
local tip = calltips[currentCalltip]
buffer:call_tip_show(buffer.current_pos,
buffer:call_tip_show(buffer:word_start_position(buffer.current_pos),
string.format("overload %d of %d\1\2\n%s", currentCalltip, #calltips,
calltips[currentCalltip]))
end
@ -109,11 +113,13 @@ function M.autocomplete(ch)
local character = string.char(ch)
if character == "." or character == "(" then
local fileName = os.tmpname()
local tmpFile = io.open(fileName, "w")
tmpFile:write(buffer:get_text())
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName
local p = io.popen(command, "r")
local r = p:read("*a")
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " > " .. fileName
local p = io.popen(command, "w")
p:write(buffer:get_text())
p:flush()
p:close()
local tmpFile = io.open(fileName, "r")
local r = tmpFile:read("*a")
--print(r)
if r ~= "\n" then
if r:match("^identifiers.*") then