Made autocompletion work when the cursor isn't at a dot or lparen
This commit is contained in:
parent
357c65f62b
commit
70cdbe4428
20
actypes.d
20
actypes.d
|
|
@ -159,6 +159,24 @@ public:
|
||||||
this.end = end;
|
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
|
* Finds the scope containing the cursor position, then searches for a
|
||||||
* symbol with the given name.
|
* symbol with the given name.
|
||||||
|
|
@ -169,7 +187,7 @@ public:
|
||||||
if (s is null)
|
if (s is null)
|
||||||
{
|
{
|
||||||
writeln("Could not find scope");
|
writeln("Could not find scope");
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return s.findSymbolsInScope(name);
|
return s.findSymbolsInScope(name);
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,17 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
|
||||||
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);
|
||||||
|
string partial;
|
||||||
|
|
||||||
auto beforeTokens = sortedTokens.lowerBound(cast(size_t) request.cursorPosition);
|
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)
|
if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.lParen)
|
||||||
{
|
{
|
||||||
immutable(string)[] completions;
|
immutable(string)[] completions;
|
||||||
|
|
@ -92,6 +100,7 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
|
||||||
}
|
}
|
||||||
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.dot)
|
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == TokenType.dot)
|
||||||
{
|
{
|
||||||
|
dotCompletion:
|
||||||
switch (beforeTokens[$ - 2].type)
|
switch (beforeTokens[$ - 2].type)
|
||||||
{
|
{
|
||||||
case TokenType.stringLiteral:
|
case TokenType.stringLiteral:
|
||||||
|
|
@ -132,9 +141,10 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
|
||||||
case TokenType.rBracket:
|
case TokenType.rBracket:
|
||||||
case TokenType.this_:
|
case TokenType.this_:
|
||||||
auto visitor = processModule(tokenArray);
|
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,
|
response.setCompletions(visitor, expression, request.cursorPosition,
|
||||||
CompletionType.identifiers);
|
CompletionType.identifiers, partial);
|
||||||
break;
|
break;
|
||||||
case TokenType.lParen:
|
case TokenType.lParen:
|
||||||
case TokenType.lBrace:
|
case TokenType.lBrace:
|
||||||
|
|
@ -152,10 +162,10 @@ AutocompleteResponse complete(AutocompleteRequest request, string[] importPaths)
|
||||||
|
|
||||||
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, string partial = null)
|
||||||
{
|
{
|
||||||
// Autocomplete module imports instead of symbols
|
// 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)
|
if (completionType == CompletionType.identifiers)
|
||||||
setImportCompletions(tokens, response);
|
setImportCompletions(tokens, response);
|
||||||
|
|
@ -163,6 +173,26 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.scope_.resolveSymbolTypes();
|
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);
|
ACSymbol[] symbols = visitor.scope_.findSymbolsInCurrentScope(cursorPosition, tokens[0].value);
|
||||||
if (symbols.length == 0)
|
if (symbols.length == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -179,7 +209,6 @@ 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.length == 0)
|
if (symbols.length == 0)
|
||||||
{
|
{
|
||||||
//writeln("Could not figure it out");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,11 +262,11 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
break loop;
|
break loop;
|
||||||
break;
|
break;
|
||||||
case identifier:
|
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);
|
symbols = symbols[0].getPartsByName(tokens[i].value);
|
||||||
if (symbols.length == 0)
|
if (symbols.length == 0)
|
||||||
{
|
{
|
||||||
writeln("Couldn't find it.");
|
// writeln("Couldn't find it.");
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
if (symbols[0].kind == CompletionKind.variableName
|
if (symbols[0].kind == CompletionKind.variableName
|
||||||
|
|
@ -317,7 +346,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
}
|
}
|
||||||
if (completionType == CompletionType.identifiers)
|
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");
|
// writeln("Adding ", s.name, " to the completion list");
|
||||||
response.completionKinds ~= s.kind;
|
response.completionKinds ~= s.kind;
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,18 @@ local function showCompletionList(r)
|
||||||
completions[#completions + 1] = completion
|
completions[#completions + 1] = completion
|
||||||
end
|
end
|
||||||
table.sort(completions, function(a, b) return string.upper(a) < string.upper(b) 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
|
buffer.auto_c_choose_single = setting
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function showCurrentCallTip()
|
local function showCurrentCallTip()
|
||||||
local tip = calltips[currentCalltip]
|
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,
|
string.format("overload %d of %d\1\2\n%s", currentCalltip, #calltips,
|
||||||
calltips[currentCalltip]))
|
calltips[currentCalltip]))
|
||||||
end
|
end
|
||||||
|
|
@ -109,11 +113,13 @@ function M.autocomplete(ch)
|
||||||
local character = string.char(ch)
|
local character = string.char(ch)
|
||||||
if character == "." or character == "(" then
|
if character == "." or character == "(" then
|
||||||
local fileName = os.tmpname()
|
local fileName = os.tmpname()
|
||||||
local tmpFile = io.open(fileName, "w")
|
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " > " .. fileName
|
||||||
tmpFile:write(buffer:get_text())
|
local p = io.popen(command, "w")
|
||||||
local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " " .. fileName
|
p:write(buffer:get_text())
|
||||||
local p = io.popen(command, "r")
|
p:flush()
|
||||||
local r = p:read("*a")
|
p:close()
|
||||||
|
local tmpFile = io.open(fileName, "r")
|
||||||
|
local r = tmpFile:read("*a")
|
||||||
--print(r)
|
--print(r)
|
||||||
if r ~= "\n" then
|
if r ~= "\n" then
|
||||||
if r:match("^identifiers.*") then
|
if r:match("^identifiers.*") then
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue