PR changes round 1
This commit is contained in:
parent
0c22a2bf7e
commit
810b77fe06
|
@ -66,6 +66,9 @@ struct ScopeSymbolPair
|
||||||
{
|
{
|
||||||
typeid(DSymbol).destroy(symbol);
|
typeid(DSymbol).destroy(symbol);
|
||||||
typeid(Scope).destroy(scope_);
|
typeid(Scope).destroy(scope_);
|
||||||
|
foreach(ufcsSym; ufcsSymbols){
|
||||||
|
typeid(DSymbol).destroy(ufcsSym);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DSymbol* symbol;
|
DSymbol* symbol;
|
||||||
|
|
|
@ -14,16 +14,16 @@ import std.regex;
|
||||||
import containers.hashset : HashSet;
|
import containers.hashset : HashSet;
|
||||||
import std.experimental.logger;
|
import std.experimental.logger;
|
||||||
|
|
||||||
enum UFCSCompletionContext
|
enum CompletionContext
|
||||||
{
|
{
|
||||||
|
UnknownCompletion,
|
||||||
DotCompletion,
|
DotCompletion,
|
||||||
ParenCompletion,
|
ParenCompletion,
|
||||||
UnknownCompletion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TokenCursorResult
|
struct TokenCursorResult
|
||||||
{
|
{
|
||||||
UFCSCompletionContext completionContext = UFCSCompletionContext.UnknownCompletion;
|
CompletionContext completionContext;
|
||||||
istring functionName;
|
istring functionName;
|
||||||
istring symbolIdentifierName;
|
istring symbolIdentifierName;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
|
||||||
&& sortedBeforeTokens[$ - 2].type is tok!"identifier")
|
&& sortedBeforeTokens[$ - 2].type is tok!"identifier")
|
||||||
{
|
{
|
||||||
// Check if it's UFCS dot completion
|
// Check if it's UFCS dot completion
|
||||||
tokenCursorResult.completionContext = UFCSCompletionContext.DotCompletion;
|
tokenCursorResult.completionContext = CompletionContext.DotCompletion;
|
||||||
tokenCursorResult.symbolIdentifierName = istring(sortedBeforeTokens[$ - 2].text);
|
tokenCursorResult.symbolIdentifierName = istring(sortedBeforeTokens[$ - 2].text);
|
||||||
return tokenCursorResult;
|
return tokenCursorResult;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
|
||||||
&& slicedAtParen[$ - 2].type is tok!"identifier"
|
&& slicedAtParen[$ - 2].type is tok!"identifier"
|
||||||
&& slicedAtParen[$ - 1].type is tok!"(")
|
&& slicedAtParen[$ - 1].type is tok!"(")
|
||||||
{
|
{
|
||||||
tokenCursorResult.completionContext = UFCSCompletionContext.ParenCompletion;
|
tokenCursorResult.completionContext = CompletionContext.ParenCompletion;
|
||||||
tokenCursorResult.symbolIdentifierName = istring(slicedAtParen[$ - 4].text);
|
tokenCursorResult.symbolIdentifierName = istring(slicedAtParen[$ - 4].text);
|
||||||
tokenCursorResult.functionName = istring(slicedAtParen[$ - 2].text);
|
tokenCursorResult.functionName = istring(slicedAtParen[$ - 2].text);
|
||||||
return tokenCursorResult;
|
return tokenCursorResult;
|
||||||
|
@ -119,7 +119,6 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getUFCSSymbols(T, Y)(ref T localAppender, ref Y globalAppender, Scope* completionScope, size_t cursorPosition)
|
private void getUFCSSymbols(T, Y)(ref T localAppender, ref Y globalAppender, Scope* completionScope, size_t cursorPosition)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Scope* currentScope = completionScope.getScopeByCursor(cursorPosition);
|
Scope* currentScope = completionScope.getScopeByCursor(cursorPosition);
|
||||||
|
@ -134,13 +133,6 @@ private void getUFCSSymbols(T, Y)(ref T localAppender, ref Y globalAppender, Sco
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto filteredSymbols = cursorSymbols.filter!(s => s.kind == CompletionKind.functionName).array;
|
|
||||||
|
|
||||||
foreach (DSymbol* sym; filteredSymbols)
|
|
||||||
{
|
|
||||||
globalAppender.put(sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet!size_t visited;
|
HashSet!size_t visited;
|
||||||
|
|
||||||
while (currentScope !is null && currentScope.parent !is null)
|
while (currentScope !is null && currentScope.parent !is null)
|
||||||
|
@ -189,7 +181,7 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, ref const(Token)[] to
|
||||||
|
|
||||||
TokenCursorResult tokenCursorResult = getCursorToken(tokens, cursorPosition);
|
TokenCursorResult tokenCursorResult = getCursorToken(tokens, cursorPosition);
|
||||||
|
|
||||||
if (tokenCursorResult.completionContext is UFCSCompletionContext.UnknownCompletion)
|
if (tokenCursorResult.completionContext is CompletionContext.UnknownCompletion)
|
||||||
{
|
{
|
||||||
trace("Is not a valid UFCS completion");
|
trace("Is not a valid UFCS completion");
|
||||||
return [];
|
return [];
|
||||||
|
@ -206,7 +198,7 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, ref const(Token)[] to
|
||||||
|
|
||||||
if (cursorSymbol.isInvalidForUFCSCompletion)
|
if (cursorSymbol.isInvalidForUFCSCompletion)
|
||||||
{
|
{
|
||||||
trace("CursorSymbol is invalid");
|
trace("CursorSymbol is invalid for UFCS");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +215,7 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, ref const(Token)[] to
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenCursorResult.completionContext == UFCSCompletionContext.ParenCompletion)
|
if (tokenCursorResult.completionContext == CompletionContext.ParenCompletion)
|
||||||
{
|
{
|
||||||
return getUFCSSymbolsForParenCompletion(cursorSymbolType, completionScope, tokenCursorResult.functionName, cursorPosition);
|
return getUFCSSymbolsForParenCompletion(cursorSymbolType, completionScope, tokenCursorResult.functionName, cursorPosition);
|
||||||
}
|
}
|
||||||
|
@ -246,7 +238,7 @@ private DSymbol*[] getUFCSSymbolsForDotCompletion(DSymbol* symbolType, Scope* co
|
||||||
return localAppender.data ~ globalAppender.data;
|
return localAppender.data ~ globalAppender.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
DSymbol*[] getUFCSSymbolsForParenCompletion(DSymbol* symbolType, Scope* completionScope, istring searchWord, size_t cursorPosition)
|
private DSymbol*[] getUFCSSymbolsForParenCompletion(DSymbol* symbolType, Scope* completionScope, istring searchWord, size_t cursorPosition)
|
||||||
{
|
{
|
||||||
// local appender
|
// local appender
|
||||||
FilteredAppender!(a => a.isCallableWithArg(symbolType) && a.name.among(searchWord), DSymbol*[]) localAppender;
|
FilteredAppender!(a => a.isCallableWithArg(symbolType) && a.name.among(searchWord), DSymbol*[]) localAppender;
|
||||||
|
@ -259,10 +251,21 @@ DSymbol*[] getUFCSSymbolsForParenCompletion(DSymbol* symbolType, Scope* completi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool willImplicitBeUpcasted(string from, string to)
|
private bool willImplicitBeUpcasted(const(DSymbol)* from, const(DSymbol)* to)
|
||||||
{
|
{
|
||||||
|
if (from is null || to is null || to.functionParameters.empty || to.functionParameters.front.type is null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fromTypeName = from.name.data;
|
||||||
|
string toTypeName = to.functionParameters.front.type.name.data;
|
||||||
|
|
||||||
|
return typeWillBeUpcastedTo(fromTypeName, toTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool typeWillBeUpcastedTo(string from, string to) {
|
||||||
string* found = from in INTEGER_PROMOTIONS;
|
string* found = from in INTEGER_PROMOTIONS;
|
||||||
if (!found)
|
if (found is null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +273,7 @@ private bool willImplicitBeUpcasted(string from, string to)
|
||||||
return INTEGER_PROMOTIONS[from] == to;
|
return INTEGER_PROMOTIONS[from] == to;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool matchAliasThis(const(DSymbol)* beforeDotType, DSymbol* incomingSymbol, int recursionDepth)
|
private bool matchAliasThis(const(DSymbol)* beforeDotType, const(DSymbol)* incomingSymbol, int recursionDepth)
|
||||||
{
|
{
|
||||||
// For now we are only resolving the first alias this symbol
|
// For now we are only resolving the first alias this symbol
|
||||||
// when multiple alias this are supported, we can rethink another solution
|
// when multiple alias this are supported, we can rethink another solution
|
||||||
|
@ -285,6 +288,10 @@ private bool matchAliasThis(const(DSymbol)* beforeDotType, DSymbol* incomingSymb
|
||||||
return isCallableWithArg(incomingSymbol, beforeDotType.aliasThisSymbols.front.type, false, recursionDepth);
|
return isCallableWithArg(incomingSymbol, beforeDotType.aliasThisSymbols.front.type, false, recursionDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isNonConstrainedTemplate(const(DSymbol)* incomingSymbol){
|
||||||
|
return incomingSymbol.functionParameters.front.type !is null && incomingSymbol.functionParameters.front.type.kind is CompletionKind.typeTmpParam;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Params:
|
* Params:
|
||||||
* incomingSymbol = the function symbol to check if it is valid for UFCS with `beforeDotType`.
|
* incomingSymbol = the function symbol to check if it is valid for UFCS with `beforeDotType`.
|
||||||
|
@ -294,26 +301,22 @@ private bool matchAliasThis(const(DSymbol)* beforeDotType, DSymbol* incomingSymb
|
||||||
* `true` if `incomingSymbols`' first parameter matches `beforeDotType`
|
* `true` if `incomingSymbols`' first parameter matches `beforeDotType`
|
||||||
* `false` otherwise
|
* `false` otherwise
|
||||||
*/
|
*/
|
||||||
bool isCallableWithArg(DSymbol* incomingSymbol, const(DSymbol)* beforeDotType, bool isGlobalScope = false, int recursionDepth = 0)
|
bool isCallableWithArg(const(DSymbol)* incomingSymbol, const(DSymbol)* beforeDotType, bool isGlobalScope = false, int recursionDepth = 0)
|
||||||
{
|
{
|
||||||
if (!incomingSymbol || !beforeDotType
|
if (incomingSymbol is null
|
||||||
|| (isGlobalScope && incomingSymbol.protection == tok!"private") || recursionDepth > MAX_RECURSION_DEPTH)
|
|| beforeDotType is null
|
||||||
|
|| isGlobalScope && incomingSymbol.protection is tok!"private" // don't show private functions if we are in global scope
|
||||||
|
|| recursionDepth > MAX_RECURSION_DEPTH)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incomingSymbol.kind == CompletionKind.functionName && !incomingSymbol
|
if (incomingSymbol.kind is CompletionKind.functionName && !incomingSymbol.functionParameters.empty && incomingSymbol.functionParameters.front.type)
|
||||||
.functionParameters.empty)
|
|
||||||
{
|
{
|
||||||
if (beforeDotType is incomingSymbol.functionParameters.front.type
|
return beforeDotType is incomingSymbol.functionParameters.front.type
|
||||||
|| incomingSymbol.functionParameters.front.type.kind is CompletionKind.typeTmpParam // non constrained template
|
|| isNonConstrainedTemplate(incomingSymbol)
|
||||||
|| willImplicitBeUpcasted(beforeDotType.name, incomingSymbol
|
|| willImplicitBeUpcasted(beforeDotType, incomingSymbol)
|
||||||
.functionParameters.front.type.name)
|
|| matchAliasThis(beforeDotType, incomingSymbol, recursionDepth);
|
||||||
|| matchAliasThis(beforeDotType, incomingSymbol, recursionDepth))
|
|
||||||
{
|
|
||||||
incomingSymbol.kind = CompletionKind.ufcsName;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -355,6 +358,6 @@ struct FilteredAppender(alias predicate, T:
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
assert(!willImplicitBeUpcasted("A", "B"));
|
assert(!typeWillBeUpcastedTo("A", "B"));
|
||||||
assert(willImplicitBeUpcasted("bool", "int"));
|
assert(typeWillBeUpcastedTo("bool", "int"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
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, false, partial);
|
||||||
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, s.kind)).array;
|
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
|
||||||
break;
|
break;
|
||||||
// these tokens before a "." mean "Module Scope Operator"
|
// these tokens before a "." mean "Module Scope Operator"
|
||||||
case tok!":":
|
case tok!":":
|
||||||
|
@ -308,8 +308,11 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
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, beforeTokens[$ - 1] == tok!"[");
|
||||||
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, s.kind)).array;
|
if (!pair.ufcsSymbols.empty) {
|
||||||
response.completionType = CompletionType.calltips;
|
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.
|
||||||
|
response.completionType = CompletionType.calltips;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -562,11 +565,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
||||||
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
|
||||||
cursorPosition, completionType);
|
cursorPosition, completionType);
|
||||||
|
|
||||||
if (tokens.length > 2 && tokens[1] == tok!".")
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symbols.length == 0)
|
if (symbols.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
identifiers
|
identifiers
|
||||||
alignof k
|
alignof k
|
||||||
b v
|
b v
|
||||||
bar F
|
|
||||||
init k
|
init k
|
||||||
mangleof k
|
mangleof k
|
||||||
sizeof k
|
sizeof k
|
||||||
|
|
|
@ -2,7 +2,6 @@ identifiers
|
||||||
__monitor v
|
__monitor v
|
||||||
__vptr v
|
__vptr v
|
||||||
alignof k
|
alignof k
|
||||||
bar F
|
|
||||||
classinfo v
|
classinfo v
|
||||||
e v
|
e v
|
||||||
init k
|
init k
|
||||||
|
|
Loading…
Reference in New Issue