adding bang completion for template func, struct, class
This commit is contained in:
parent
0e85f165a9
commit
371a36e9d5
|
@ -45,6 +45,10 @@ TTree!(DSymbol*, SymbolsAllocator, true, "a < b") enumSymbols;
|
||||||
*/
|
*/
|
||||||
TTree!(DSymbol*, SymbolsAllocator, true, "a < b") pointerSymbols;
|
TTree!(DSymbol*, SymbolsAllocator, true, "a < b") pointerSymbols;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templated properties
|
||||||
|
*/
|
||||||
|
TTree!(DSymbol*, SymbolsAllocator, true, "a < b") templatedSymbols;
|
||||||
/**
|
/**
|
||||||
* Variadic template parameters properties
|
* Variadic template parameters properties
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1041,6 +1041,7 @@ private:
|
||||||
continue;
|
continue;
|
||||||
SemanticSymbol* templateParameter = allocateSemanticSymbol(name,
|
SemanticSymbol* templateParameter = allocateSemanticSymbol(name,
|
||||||
kind, symbolFile, index);
|
kind, symbolFile, index);
|
||||||
|
symbol.acSymbol.qualifier = SymbolQualifier.templated;
|
||||||
if (type !is null)
|
if (type !is null)
|
||||||
addTypeToLookups(templateParameter.typeLookups, type);
|
addTypeToLookups(templateParameter.typeLookups, type);
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,7 @@ do
|
||||||
case SymbolQualifier.array: lastSuffix.addChildren(arraySymbols[], false); break;
|
case SymbolQualifier.array: lastSuffix.addChildren(arraySymbols[], false); break;
|
||||||
case SymbolQualifier.assocArray: lastSuffix.addChildren(assocArraySymbols[], false); break;
|
case SymbolQualifier.assocArray: lastSuffix.addChildren(assocArraySymbols[], false); break;
|
||||||
case SymbolQualifier.pointer: lastSuffix.addChildren(pointerSymbols[], false); break;
|
case SymbolQualifier.pointer: lastSuffix.addChildren(pointerSymbols[], false); break;
|
||||||
|
case SymbolQualifier.templated: lastSuffix.addChildren(templatedSymbols[], false); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suffix is null)
|
if (suffix is null)
|
||||||
|
|
|
@ -133,6 +133,8 @@ enum SymbolQualifier : ubyte
|
||||||
selectiveImport,
|
selectiveImport,
|
||||||
/// The symbol is a pointer
|
/// The symbol is a pointer
|
||||||
pointer,
|
pointer,
|
||||||
|
/// The symbol is templated
|
||||||
|
templated,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,6 +47,11 @@ import dsymbol.utils;
|
||||||
import dcd.common.constants;
|
import dcd.common.constants;
|
||||||
import dcd.common.messages;
|
import dcd.common.messages;
|
||||||
|
|
||||||
|
enum CompletionToken {
|
||||||
|
none,
|
||||||
|
bracket, bang
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles autocompletion
|
* Handles autocompletion
|
||||||
* Params:
|
* Params:
|
||||||
|
@ -134,10 +139,14 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
||||||
|| beforeTokens[$ - 1] == tok!",")
|
|| beforeTokens[$ - 1] == tok!",")
|
||||||
{
|
{
|
||||||
immutable size_t end = goBackToOpenParen(beforeTokens);
|
immutable size_t end = goBackToOpenParen(beforeTokens);
|
||||||
if (end != size_t.max)
|
if (end != size_t.max) {
|
||||||
return parenCompletion(beforeTokens[0 .. end], tokenArray,
|
return callTipCompletion(beforeTokens[0 .. end], tokenArray,
|
||||||
request.cursorPosition, moduleCache);
|
request.cursorPosition, moduleCache);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (beforeTokens[$ - 1] == tok!"!"){ // Bang completion
|
||||||
|
return callTipCompletion(beforeTokens, tokenArray, request.cursorPosition, moduleCache);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImportKind kind = determineImportKind(beforeTokens);
|
ImportKind kind = determineImportKind(beforeTokens);
|
||||||
|
@ -218,7 +227,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, &rba, cursorPosition, moduleCache);
|
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, &rba, cursorPosition, moduleCache);
|
||||||
scope(exit) pair.destroy();
|
scope(exit) pair.destroy();
|
||||||
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
||||||
cursorPosition, CompletionType.identifiers, false, partial);
|
cursorPosition, CompletionType.identifiers, CompletionToken.none, partial);
|
||||||
if (!pair.ufcsSymbols.empty) {
|
if (!pair.ufcsSymbols.empty) {
|
||||||
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
|
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
|
||||||
// Setting CompletionType in case of none symbols are found via setCompletions, but we have UFCS symbols.
|
// Setting CompletionType in case of none symbols are found via setCompletions, but we have UFCS symbols.
|
||||||
|
@ -237,7 +246,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, &rba, 1, moduleCache);
|
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, &rba, 1, moduleCache);
|
||||||
scope(exit) pair.destroy();
|
scope(exit) pair.destroy();
|
||||||
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
||||||
1, CompletionType.identifiers, false, partial);
|
1, CompletionType.identifiers, CompletionToken.none, partial);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -246,7 +255,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles paren completion for function calls and some keywords
|
* Handles calltip completion for function calls and some keywords
|
||||||
* Params:
|
* Params:
|
||||||
* beforeTokens = the tokens before the cursor
|
* beforeTokens = the tokens before the cursor
|
||||||
* tokenArray = all tokens in the file
|
* tokenArray = all tokens in the file
|
||||||
|
@ -254,7 +263,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
* Returns:
|
* Returns:
|
||||||
* the autocompletion response
|
* the autocompletion response
|
||||||
*/
|
*/
|
||||||
AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
AutocompleteResponse callTipCompletion(T)(T beforeTokens,
|
||||||
const(Token)[] tokenArray, size_t cursorPosition, ref ModuleCache moduleCache)
|
const(Token)[] tokenArray, size_t cursorPosition, ref ModuleCache moduleCache)
|
||||||
{
|
{
|
||||||
AutocompleteResponse response;
|
AutocompleteResponse response;
|
||||||
|
@ -309,7 +318,7 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
scope(exit) pair.destroy();
|
scope(exit) pair.destroy();
|
||||||
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
|
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
|
||||||
response.setCompletions(pair.scope_, expression,
|
response.setCompletions(pair.scope_, expression,
|
||||||
cursorPosition, CompletionType.calltips, beforeTokens[$ - 1] == tok!"[");
|
cursorPosition, CompletionType.calltips, getCompletionToken(beforeTokens));
|
||||||
if (!pair.ufcsSymbols.empty) {
|
if (!pair.ufcsSymbols.empty) {
|
||||||
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
|
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
|
||||||
// Setting CompletionType in case of none symbols are found via setCompletions, but we have UFCS symbols.
|
// Setting CompletionType in case of none symbols are found via setCompletions, but we have UFCS symbols.
|
||||||
|
@ -322,6 +331,18 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompletionToken getCompletionToken(T)(T beforeTokens) {
|
||||||
|
if(beforeTokens[$ - 1] == tok!"["){
|
||||||
|
return CompletionToken.bracket;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(beforeTokens[$ - 1] == tok!"!"){
|
||||||
|
return CompletionToken.bang;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletionToken.none;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides autocomplete for selective imports, e.g.:
|
* Provides autocomplete for selective imports, e.g.:
|
||||||
* ---
|
* ---
|
||||||
|
@ -505,7 +526,7 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response,
|
||||||
*/
|
*/
|
||||||
void setCompletions(T)(ref AutocompleteResponse response,
|
void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
Scope* completionScope, T tokens, size_t cursorPosition,
|
Scope* completionScope, T tokens, size_t cursorPosition,
|
||||||
CompletionType completionType, bool isBracket = false, string partial = null)
|
CompletionType completionType, CompletionToken completionToken = CompletionToken.none, string partial = null)
|
||||||
{
|
{
|
||||||
static void addSymToResponse(const(DSymbol)* s, ref AutocompleteResponse r, string p,
|
static void addSymToResponse(const(DSymbol)* s, ref AutocompleteResponse r, string p,
|
||||||
Scope* completionScope, size_t[] circularGuard = [])
|
Scope* completionScope, size_t[] circularGuard = [])
|
||||||
|
@ -567,6 +588,11 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||||
cursorPosition, completionType);
|
cursorPosition, completionType);
|
||||||
|
|
||||||
|
// If bang completion we check if symbol is also templated
|
||||||
|
if (completionToken == CompletionToken.bang && symbols.length >= 1 && symbols[0].qualifier != SymbolQualifier.templated){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (symbols.length == 0)
|
if (symbols.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -607,7 +633,7 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
symbols = [dumb];
|
symbols = [dumb];
|
||||||
goto setCallTips;
|
goto setCallTips;
|
||||||
}
|
}
|
||||||
if (isBracket)
|
if (completionToken == CompletionToken.bracket)
|
||||||
{
|
{
|
||||||
auto index = dumb.getPartsByName(internString("opIndex"));
|
auto index = dumb.getPartsByName(internString("opIndex"));
|
||||||
if (index.length > 0)
|
if (index.length > 0)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
calltips
|
||||||
|
this(T data)
|
|
@ -0,0 +1,2 @@
|
||||||
|
calltips
|
||||||
|
this(T foo, X bar)
|
|
@ -0,0 +1,2 @@
|
||||||
|
calltips
|
||||||
|
void doSomething(T)(T someElement)
|
|
@ -0,0 +1,23 @@
|
||||||
|
struct Wrapper(T) {
|
||||||
|
T data;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Something(T, X){
|
||||||
|
this(T foo, X bar){}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doSomething(T)(T someElement){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void instantiateTemp1() {
|
||||||
|
Wrapper!
|
||||||
|
}
|
||||||
|
|
||||||
|
void instantiateTemp2() {
|
||||||
|
Something!
|
||||||
|
}
|
||||||
|
|
||||||
|
void instantiateTemp3() {
|
||||||
|
doSomething!
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file.d -c155 > actual.txt
|
||||||
|
diff actual.txt expected.txt --strip-trailing-cr
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file.d -c196 > actual2.txt
|
||||||
|
diff actual2.txt expected2.txt --strip-trailing-cr
|
||||||
|
|
||||||
|
../../bin/dcd-client $1 file.d -c239 > actual3.txt
|
||||||
|
diff actual3.txt expected3.txt --strip-trailing-cr
|
Loading…
Reference in New Issue