PR changes round 1

This commit is contained in:
davu 2023-03-16 01:58:49 +01:00 committed by Jan Jurzitza
parent 0c22a2bf7e
commit 810b77fe06
5 changed files with 48 additions and 46 deletions

View File

@ -66,6 +66,9 @@ struct ScopeSymbolPair
{
typeid(DSymbol).destroy(symbol);
typeid(Scope).destroy(scope_);
foreach(ufcsSym; ufcsSymbols){
typeid(DSymbol).destroy(ufcsSym);
}
}
DSymbol* symbol;

View File

@ -14,16 +14,16 @@ import std.regex;
import containers.hashset : HashSet;
import std.experimental.logger;
enum UFCSCompletionContext
enum CompletionContext
{
UnknownCompletion,
DotCompletion,
ParenCompletion,
UnknownCompletion
}
struct TokenCursorResult
{
UFCSCompletionContext completionContext = UFCSCompletionContext.UnknownCompletion;
CompletionContext completionContext;
istring functionName;
istring symbolIdentifierName;
}
@ -86,7 +86,7 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
&& sortedBeforeTokens[$ - 2].type is tok!"identifier")
{
// Check if it's UFCS dot completion
tokenCursorResult.completionContext = UFCSCompletionContext.DotCompletion;
tokenCursorResult.completionContext = CompletionContext.DotCompletion;
tokenCursorResult.symbolIdentifierName = istring(sortedBeforeTokens[$ - 2].text);
return tokenCursorResult;
}
@ -107,7 +107,7 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
&& slicedAtParen[$ - 2].type is tok!"identifier"
&& slicedAtParen[$ - 1].type is tok!"(")
{
tokenCursorResult.completionContext = UFCSCompletionContext.ParenCompletion;
tokenCursorResult.completionContext = CompletionContext.ParenCompletion;
tokenCursorResult.symbolIdentifierName = istring(slicedAtParen[$ - 4].text);
tokenCursorResult.functionName = istring(slicedAtParen[$ - 2].text);
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)
{
Scope* currentScope = completionScope.getScopeByCursor(cursorPosition);
@ -134,13 +133,6 @@ private void getUFCSSymbols(T, Y)(ref T localAppender, ref Y globalAppender, Sco
return;
}
auto filteredSymbols = cursorSymbols.filter!(s => s.kind == CompletionKind.functionName).array;
foreach (DSymbol* sym; filteredSymbols)
{
globalAppender.put(sym);
}
HashSet!size_t visited;
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);
if (tokenCursorResult.completionContext is UFCSCompletionContext.UnknownCompletion)
if (tokenCursorResult.completionContext is CompletionContext.UnknownCompletion)
{
trace("Is not a valid UFCS completion");
return [];
@ -206,7 +198,7 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, ref const(Token)[] to
if (cursorSymbol.isInvalidForUFCSCompletion)
{
trace("CursorSymbol is invalid");
trace("CursorSymbol is invalid for UFCS");
return [];
}
@ -223,7 +215,7 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, ref const(Token)[] to
return [];
}
if (tokenCursorResult.completionContext == UFCSCompletionContext.ParenCompletion)
if (tokenCursorResult.completionContext == CompletionContext.ParenCompletion)
{
return getUFCSSymbolsForParenCompletion(cursorSymbolType, completionScope, tokenCursorResult.functionName, cursorPosition);
}
@ -246,7 +238,7 @@ private DSymbol*[] getUFCSSymbolsForDotCompletion(DSymbol* symbolType, Scope* co
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
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;
if (!found)
if (found is null)
{
return false;
}
@ -270,7 +273,7 @@ private bool willImplicitBeUpcasted(string from, string 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
// 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);
}
bool isNonConstrainedTemplate(const(DSymbol)* incomingSymbol){
return incomingSymbol.functionParameters.front.type !is null && incomingSymbol.functionParameters.front.type.kind is CompletionKind.typeTmpParam;
}
/**
* Params:
* 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`
* `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
|| (isGlobalScope && incomingSymbol.protection == tok!"private") || recursionDepth > MAX_RECURSION_DEPTH)
if (incomingSymbol is null
|| 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;
}
if (incomingSymbol.kind == CompletionKind.functionName && !incomingSymbol
.functionParameters.empty)
if (incomingSymbol.kind is CompletionKind.functionName && !incomingSymbol.functionParameters.empty && incomingSymbol.functionParameters.front.type)
{
if (beforeDotType is incomingSymbol.functionParameters.front.type
|| incomingSymbol.functionParameters.front.type.kind is CompletionKind.typeTmpParam // non constrained template
|| willImplicitBeUpcasted(beforeDotType.name, incomingSymbol
.functionParameters.front.type.name)
|| matchAliasThis(beforeDotType, incomingSymbol, recursionDepth))
{
incomingSymbol.kind = CompletionKind.ufcsName;
return true;
}
return beforeDotType is incomingSymbol.functionParameters.front.type
|| isNonConstrainedTemplate(incomingSymbol)
|| willImplicitBeUpcasted(beforeDotType, incomingSymbol)
|| matchAliasThis(beforeDotType, incomingSymbol, recursionDepth);
}
return false;
@ -355,6 +358,6 @@ struct FilteredAppender(alias predicate, T:
unittest
{
assert(!willImplicitBeUpcasted("A", "B"));
assert(willImplicitBeUpcasted("bool", "int"));
assert(!typeWillBeUpcastedTo("A", "B"));
assert(typeWillBeUpcastedTo("bool", "int"));
}

View File

@ -221,7 +221,7 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
scope(exit) pair.destroy();
response.setCompletions(pair.scope_, getExpression(beforeTokens),
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;
// these tokens before a "." mean "Module Scope Operator"
case tok!":":
@ -308,8 +308,11 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
auto expression = getExpression(beforeTokens[0 .. $ - 1]);
response.setCompletions(pair.scope_, expression,
cursorPosition, CompletionType.calltips, beforeTokens[$ - 1] == tok!"[");
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, s.kind)).array;
response.completionType = CompletionType.calltips;
if (!pair.ufcsSymbols.empty) {
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;
default:
break;
@ -562,11 +565,6 @@ void setCompletions(T)(ref AutocompleteResponse response,
DSymbol*[] symbols = getSymbolsByTokenChain(completionScope, tokens,
cursorPosition, completionType);
if (tokens.length > 2 && tokens[1] == tok!".")
{
}
if (symbols.length == 0)
return;

View File

@ -1,7 +1,6 @@
identifiers
alignof k
b v
bar F
init k
mangleof k
sizeof k

View File

@ -2,7 +2,6 @@ identifiers
__monitor v
__vptr v
alignof k
bar F
classinfo v
e v
init k