PR changes

This commit is contained in:
davu 2023-03-26 11:50:50 +02:00 committed by Jan Jurzitza
parent 9e4c70ce15
commit 218d047760
14 changed files with 125 additions and 141 deletions

View File

@ -30,11 +30,6 @@ struct TokenCursorResult
string partialIdentifier;
}
struct DeducedSymbolTypeResult{
const(DSymbol)* deducedSymbolType;
bool success = false;
}
// https://dlang.org/spec/type.html#implicit-conversions
enum string[string] INTEGER_PROMOTIONS = [
"bool": "int",
@ -49,20 +44,17 @@ enum string[string] INTEGER_PROMOTIONS = [
enum MAX_NUMBER_OF_MATCHING_RUNS = 50;
private DeducedSymbolTypeResult deduceSymbolTypeByToken(Scope* completionScope, scope ref const(Token) significantToken, size_t cursorPosition)
private const(DSymbol)* deduceSymbolTypeByToken(Scope* completionScope, scope ref const(Token) significantToken, size_t cursorPosition)
{
DeducedSymbolTypeResult result;
//Literal type deduction
if (significantToken.type is tok!"stringLiteral"){
result.deducedSymbolType = completionScope.getFirstSymbolByNameAndCursor(istring("string"), cursorPosition);
result.success = true;
return result;
return completionScope.getFirstSymbolByNameAndCursor(symbolNameToTypeName(STRING_LITERAL_SYMBOL_NAME), cursorPosition);
}
const(DSymbol)* symbol = completionScope.getFirstSymbolByNameAndCursor(istring(significantToken.text), cursorPosition);
if (symbol is null) {
return result;
return null;
}
const(DSymbol)* symbolType = symbol.type;
@ -82,9 +74,7 @@ private DeducedSymbolTypeResult deduceSymbolTypeByToken(Scope* completionScope,
}
result.deducedSymbolType = symbolType;
result.success = true;
return result;
return symbolType;
}
@ -120,8 +110,14 @@ private TokenCursorResult getCursorToken(const(Token)[] tokens, size_t cursorPos
&& (sortedBeforeTokens[$ - 2].type is tok!"identifier" || sortedBeforeTokens[$ - 2].type is tok!"stringLiteral"))
{
// Check if it's UFCS dot completion
tokenCursorResult.completionContext = CompletionContext.DotCompletion;
auto expressionTokens = getExpression(sortedBeforeTokens);
if(expressionTokens[0] !is sortedBeforeTokens[$ - 2]){
// If the expression is invalid as a dot token we return
return tokenCursorResult;
}
tokenCursorResult.significantToken = sortedBeforeTokens[$ - 2];
tokenCursorResult.completionContext = CompletionContext.DotCompletion;
return tokenCursorResult;
}
else if (!tokenCursorResult.partialIdentifier.length)
@ -212,14 +208,14 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, scope ref const(Token
return [];
}
DeducedSymbolTypeResult deducedSymbolTypeResult = deduceSymbolTypeByToken(completionScope, tokenCursorResult.significantToken, cursorPosition);
const(DSymbol)* deducedSymbolType = deduceSymbolTypeByToken(completionScope, tokenCursorResult.significantToken, cursorPosition);
if (deducedSymbolTypeResult.deducedSymbolType is null)
if (deducedSymbolType is null)
{
return [];
}
if (deducedSymbolTypeResult.deducedSymbolType.isInvalidForUFCSCompletion)
if (deducedSymbolType.isInvalidForUFCSCompletion)
{
trace("CursorSymbolType isn't valid for UFCS completion");
return [];
@ -227,11 +223,11 @@ DSymbol*[] getUFCSSymbolsForCursor(Scope* completionScope, scope ref const(Token
if (tokenCursorResult.completionContext == CompletionContext.ParenCompletion)
{
return getUFCSSymbolsForParenCompletion(deducedSymbolTypeResult.deducedSymbolType, completionScope, tokenCursorResult.functionName, cursorPosition);
return getUFCSSymbolsForParenCompletion(deducedSymbolType, completionScope, tokenCursorResult.functionName, cursorPosition);
}
else
{
return getUFCSSymbolsForDotCompletion(deducedSymbolTypeResult.deducedSymbolType, completionScope, cursorPosition, tokenCursorResult.partialIdentifier);
return getUFCSSymbolsForDotCompletion(deducedSymbolType, completionScope, cursorPosition, tokenCursorResult.partialIdentifier);
}
}

View File

@ -153,3 +153,91 @@ unittest
i = skipParenReverseBefore(t, i, tok!")", tok!"(");
assert(i == 1);
}
T getExpression(T)(T beforeTokens)
{
enum EXPRESSION_LOOP_BREAK = q{
if (i + 1 < beforeTokens.length) switch (beforeTokens[i + 1].type)
{
mixin (TYPE_IDENT_AND_LITERAL_CASES);
i++;
break expressionLoop;
default:
break;
}
};
if (beforeTokens.length == 0)
return beforeTokens[0 .. 0];
size_t i = beforeTokens.length - 1;
size_t sliceEnd = beforeTokens.length;
IdType open;
IdType close;
uint skipCount = 0;
expressionLoop: while (true)
{
switch (beforeTokens[i].type)
{
case tok!"import":
i++;
break expressionLoop;
mixin (TYPE_IDENT_AND_LITERAL_CASES);
mixin (EXPRESSION_LOOP_BREAK);
break;
case tok!".":
break;
case tok!")":
open = tok!")";
close = tok!"(";
goto skip;
case tok!"]":
open = tok!"]";
close = tok!"[";
skip:
mixin (EXPRESSION_LOOP_BREAK);
immutable bookmark = i;
i = beforeTokens.skipParenReverse(i, open, close);
skipCount++;
// check the current token after skipping parens to the left.
// if it's a loop keyword, pretend we never skipped the parens.
if (i > 0) switch (beforeTokens[i - 1].type)
{
case tok!"scope":
case tok!"if":
case tok!"while":
case tok!"for":
case tok!"foreach":
case tok!"foreach_reverse":
case tok!"do":
case tok!"cast":
case tok!"catch":
i = bookmark + 1;
break expressionLoop;
case tok!"!":
// only break if the bang is for a template instance
if (i - 2 >= 0 && beforeTokens[i - 2].type == tok!"identifier" && skipCount == 1)
{
sliceEnd = i - 1;
i -= 2;
break expressionLoop;
}
break;
default:
break;
}
break;
default:
i++;
break expressionLoop;
}
if (i == 0)
break;
else
i--;
}
return beforeTokens[i .. sliceEnd];
}

View File

@ -208,18 +208,9 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
switch (significantTokenType)
{
mixin(STRING_LITERAL_CASES);
{
foreach (symbol; arraySymbols){
foreach (symbol; arraySymbols)
response.completions ~= makeSymbolCompletionInfo(symbol, symbol.kind);
}
response.completionType = CompletionType.identifiers;
RollbackAllocator rba;
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, &rba, cursorPosition, moduleCache);
scope(exit) pair.destroy();
response.completions ~= pair.ufcsSymbols.map!(s => makeSymbolCompletionInfo(s, CompletionKind.ufcsName)).array;
break;
}
goto case;
mixin(TYPE_IDENT_CASES);
case tok!")":
case tok!"]":

View File

@ -31,6 +31,7 @@ import dparse.rollback_allocator;
import dsymbol.conversion;
import dsymbol.modulecache;
import dsymbol.symbol;
import dsymbol.utils;
import dcd.common.messages;

View File

@ -422,96 +422,6 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
return symbols;
}
/**
*
*/
T getExpression(T)(T beforeTokens)
{
enum EXPRESSION_LOOP_BREAK = q{
if (i + 1 < beforeTokens.length) switch (beforeTokens[i + 1].type)
{
mixin (TYPE_IDENT_AND_LITERAL_CASES);
i++;
break expressionLoop;
default:
break;
}
};
if (beforeTokens.length == 0)
return beforeTokens[0 .. 0];
size_t i = beforeTokens.length - 1;
size_t sliceEnd = beforeTokens.length;
IdType open;
IdType close;
uint skipCount = 0;
expressionLoop: while (true)
{
switch (beforeTokens[i].type)
{
case tok!"import":
i++;
break expressionLoop;
mixin (TYPE_IDENT_AND_LITERAL_CASES);
mixin (EXPRESSION_LOOP_BREAK);
break;
case tok!".":
break;
case tok!")":
open = tok!")";
close = tok!"(";
goto skip;
case tok!"]":
open = tok!"]";
close = tok!"[";
skip:
mixin (EXPRESSION_LOOP_BREAK);
immutable bookmark = i;
i = beforeTokens.skipParenReverse(i, open, close);
skipCount++;
// check the current token after skipping parens to the left.
// if it's a loop keyword, pretend we never skipped the parens.
if (i > 0) switch (beforeTokens[i - 1].type)
{
case tok!"scope":
case tok!"if":
case tok!"while":
case tok!"for":
case tok!"foreach":
case tok!"foreach_reverse":
case tok!"do":
case tok!"cast":
case tok!"catch":
i = bookmark + 1;
break expressionLoop;
case tok!"!":
// only break if the bang is for a template instance
if (i - 2 >= 0 && beforeTokens[i - 2].type == tok!"identifier" && skipCount == 1)
{
sliceEnd = i - 1;
i -= 2;
break expressionLoop;
}
break;
default:
break;
}
break;
default:
i++;
break expressionLoop;
}
if (i == 0)
break;
else
i--;
}
return beforeTokens[i .. sliceEnd];
}
/**
* Determines if an import is selective, whole-module, or neither.
*/

View File

@ -8,6 +8,5 @@ mangleof k
ptr k
sizeof k
stringof k
testUfcs F
ufcsString F
ufcsStringBar F

View File

@ -1,4 +0,0 @@
identifiers
testUfcs F
ufcsString F
ufcsStringBar F

View File

@ -1,6 +1,7 @@
struct Hello { void hi(){} }
void ufcsString(string input){}
void ufcsStringBar(string input){}
void testUfcs(string x){
void testUfcs(Hello x){
"foo".
x.
}

View File

@ -1,15 +1,8 @@
set -e
set -u
#TEST CASE 0
SOURCE_FILE_0=file.d
ACTUAL_FILE_NAME_0=actual_string_literal_test.txt
EXPECTED_FILE_NAME_0=expected_string_literal_test.txt
../../bin/dcd-client $1 -c127 file.d > actual_string_literal_test.txt
diff actual_string_literal_test.txt expected_string_literal_test.txt --strip-trailing-cr
../../bin/dcd-client $1 -c99 $SOURCE_FILE_0 > $ACTUAL_FILE_NAME_0
diff $ACTUAL_FILE_NAME_0 $EXPECTED_FILE_NAME_0 --strip-trailing-cr
ACTUAL_FILE_NAME_1=actual_string_test.txt
EXPECTED_FILE_NAME_1=expected_string_test.txt
../../bin/dcd-client $1 -c103 $SOURCE_FILE_0 > $ACTUAL_FILE_NAME_1
diff $ACTUAL_FILE_NAME_1 $EXPECTED_FILE_NAME_1 --strip-trailing-cr
../../bin/dcd-client $1 -c131 file.d > actual_string_test.txt
diff actual_string_test.txt expected_string_test.txt --strip-trailing-cr

View File

@ -1,4 +1,5 @@
identifiers
aliasStruct F
alignof k
fooHey f
hasArgname F

View File

@ -8,7 +8,9 @@ void main()
foo.
}
void aliasStruct() {
void aliasStruct(Foo f) {
auto intAliased = IntAliased();
intAliased.
f.
f.
}

View File

@ -4,5 +4,11 @@ set -u
../../bin/dcd-client $1 -c82 -I"$PWD"/fooutils file.d > actual_struct_test.txt
diff actual_struct_test.txt expected_struct_test.txt
../../bin/dcd-client $1 -c152 -I"$PWD"/fooutils file.d > actual_aliased_struct_test.txt
diff actual_aliased_struct_test.txt expected_aliased_struct_test.txt
../../bin/dcd-client $1 -c157 -I"$PWD"/fooutils file.d > actual_aliased_struct_test.txt
diff actual_aliased_struct_test.txt expected_aliased_struct_test.txt
../../bin/dcd-client $1 -c161 -I"$PWD"/fooutils file.d > actual_should_not_complete_test.txt
diff actual_should_not_complete_test.txt expected_should_not_complete_test.txt
../../bin/dcd-client $1 -c165 -I"$PWD"/fooutils file.d > actual_should_not_complete_test2.txt
diff actual_should_not_complete_test2.txt expected_should_not_complete_test2.txt