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(DSymbol).destroy(symbol);
typeid(Scope).destroy(scope_); typeid(Scope).destroy(scope_);
foreach(ufcsSym; ufcsSymbols){
typeid(DSymbol).destroy(ufcsSym);
}
} }
DSymbol* symbol; DSymbol* symbol;

View File

@ -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"));
} }

View File

@ -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;

View File

@ -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

View File

@ -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