PR changes
This commit is contained in:
parent
9e4c70ce15
commit
218d047760
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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!"]":
|
||||
|
|
|
@ -31,6 +31,7 @@ import dparse.rollback_allocator;
|
|||
import dsymbol.conversion;
|
||||
import dsymbol.modulecache;
|
||||
import dsymbol.symbol;
|
||||
import dsymbol.utils;
|
||||
|
||||
import dcd.common.messages;
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -8,6 +8,5 @@ mangleof k
|
|||
ptr k
|
||||
sizeof k
|
||||
stringof k
|
||||
testUfcs F
|
||||
ufcsString F
|
||||
ufcsStringBar F
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
identifiers
|
||||
testUfcs F
|
||||
ufcsString F
|
||||
ufcsStringBar F
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,5 @@
|
|||
identifiers
|
||||
aliasStruct F
|
||||
alignof k
|
||||
fooHey f
|
||||
hasArgname F
|
||||
|
|
|
@ -8,7 +8,9 @@ void main()
|
|||
foo.
|
||||
}
|
||||
|
||||
void aliasStruct() {
|
||||
void aliasStruct(Foo f) {
|
||||
auto intAliased = IntAliased();
|
||||
intAliased.
|
||||
f.
|
||||
f.
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue