Merge duplicate implementations of skip in server
+ some code duplication removal
This commit is contained in:
parent
843a7783c3
commit
fa81ad2d59
|
@ -59,12 +59,8 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
|||
request.cursorPosition, stringCache, tokenArray);
|
||||
if (beforeTokens.length >= 2)
|
||||
{
|
||||
if (beforeTokens[$ - 1] == tok!"(" || beforeTokens[$ - 1] == tok!"[")
|
||||
{
|
||||
return parenCompletion(beforeTokens, tokenArray, request.cursorPosition,
|
||||
moduleCache);
|
||||
}
|
||||
else if (beforeTokens[$ - 1] == tok!",")
|
||||
if (beforeTokens[$ - 1] == tok!"(" || beforeTokens[$ - 1] == tok!"["
|
||||
|| beforeTokens[$ - 1] == tok!",")
|
||||
{
|
||||
immutable size_t end = goBackToOpenParen(beforeTokens);
|
||||
if (end != size_t.max)
|
||||
|
@ -80,7 +76,7 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
|||
beforeTokens = beforeTokens[$-1 .. $];
|
||||
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition,
|
||||
moduleCache);
|
||||
}
|
||||
}
|
||||
else
|
||||
return importCompletion(beforeTokens, kind, moduleCache);
|
||||
}
|
||||
|
@ -122,16 +118,14 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
|||
significantTokenType = tok!"identifier";
|
||||
beforeTokens = beforeTokens[0 .. $ - 1];
|
||||
}
|
||||
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".")
|
||||
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".")
|
||||
significantTokenType = beforeTokens[$ - 2].type;
|
||||
else
|
||||
return response;
|
||||
|
||||
switch (significantTokenType)
|
||||
{
|
||||
case tok!"stringLiteral":
|
||||
case tok!"wstringLiteral":
|
||||
case tok!"dstringLiteral":
|
||||
mixin(STRING_LITERAL_CASES);
|
||||
foreach (symbol; arraySymbols)
|
||||
{
|
||||
response.completionKinds ~= symbol.kind;
|
||||
|
@ -139,34 +133,9 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
|||
}
|
||||
response.completionType = CompletionType.identifiers;
|
||||
break;
|
||||
case tok!"int":
|
||||
case tok!"uint":
|
||||
case tok!"long":
|
||||
case tok!"ulong":
|
||||
case tok!"char":
|
||||
case tok!"wchar":
|
||||
case tok!"dchar":
|
||||
case tok!"bool":
|
||||
case tok!"byte":
|
||||
case tok!"ubyte":
|
||||
case tok!"short":
|
||||
case tok!"ushort":
|
||||
case tok!"cent":
|
||||
case tok!"ucent":
|
||||
case tok!"float":
|
||||
case tok!"ifloat":
|
||||
case tok!"cfloat":
|
||||
case tok!"idouble":
|
||||
case tok!"cdouble":
|
||||
case tok!"double":
|
||||
case tok!"real":
|
||||
case tok!"ireal":
|
||||
case tok!"creal":
|
||||
case tok!"identifier":
|
||||
mixin(TYPE_IDENT_CASES);
|
||||
case tok!")":
|
||||
case tok!"]":
|
||||
case tok!"this":
|
||||
case tok!"super":
|
||||
auto allocator = scoped!(ASTAllocator)();
|
||||
RollbackAllocator rba;
|
||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
||||
|
@ -227,7 +196,6 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
|||
break;
|
||||
case tok!"characterLiteral":
|
||||
case tok!"doubleLiteral":
|
||||
case tok!"dstringLiteral":
|
||||
case tok!"floatLiteral":
|
||||
case tok!"identifier":
|
||||
case tok!"idoubleLiteral":
|
||||
|
@ -236,14 +204,13 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
|||
case tok!"irealLiteral":
|
||||
case tok!"longLiteral":
|
||||
case tok!"realLiteral":
|
||||
case tok!"stringLiteral":
|
||||
case tok!"uintLiteral":
|
||||
case tok!"ulongLiteral":
|
||||
case tok!"wstringLiteral":
|
||||
case tok!"this":
|
||||
case tok!"super":
|
||||
case tok!")":
|
||||
case tok!"]":
|
||||
mixin(STRING_LITERAL_CASES);
|
||||
auto allocator = scoped!(ASTAllocator)();
|
||||
RollbackAllocator rba;
|
||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
||||
|
|
|
@ -147,36 +147,15 @@ SymbolStuff getSymbolsForCompletion(const AutocompleteRequest request,
|
|||
request.cursorPosition, type), pair.symbol, pair.scope_);
|
||||
}
|
||||
|
||||
static void skip(alias O, alias C, T)(T t, ref size_t i)
|
||||
{
|
||||
int depth = 1;
|
||||
while (i < t.length) switch (t[i].type)
|
||||
{
|
||||
case O:
|
||||
i++;
|
||||
depth++;
|
||||
break;
|
||||
case C:
|
||||
i++;
|
||||
depth--;
|
||||
if (depth <= 0)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isSliceExpression(T)(T tokens, size_t index)
|
||||
{
|
||||
while (index < tokens.length) switch (tokens[index].type)
|
||||
{
|
||||
case tok!"[":
|
||||
skip!(tok!"[", tok!"]")(tokens, index);
|
||||
tokens.skipParen(index, tok!"[", tok!"]");
|
||||
break;
|
||||
case tok!"(":
|
||||
skip!(tok!"(", tok!")")(tokens, index);
|
||||
tokens.skipParen(index, tok!"(", tok!")");
|
||||
break;
|
||||
case tok!"]":
|
||||
case tok!"}":
|
||||
|
@ -200,22 +179,6 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
//dumpTokens(tokens.release);
|
||||
//writeln(">>>");
|
||||
|
||||
static size_t skipEnd(T tokenSlice, size_t i, IdType open, IdType close)
|
||||
{
|
||||
size_t j = i + 1;
|
||||
for (int depth = 1; depth > 0 && j < tokenSlice.length; j++)
|
||||
{
|
||||
if (tokenSlice[j].type == open)
|
||||
depth++;
|
||||
else if (tokenSlice[j].type == close)
|
||||
{
|
||||
depth--;
|
||||
if (depth == 0) break;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
// Find the symbol corresponding to the beginning of the chain
|
||||
DSymbol*[] symbols;
|
||||
if (tokens.length == 0)
|
||||
|
@ -224,7 +187,8 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
// e.g. (a.b!c).d
|
||||
if (tokens[0] == tok!"(")
|
||||
{
|
||||
immutable j = skipEnd(tokens, 0, tok!"(", tok!")");
|
||||
size_t j;
|
||||
tokens.skipParen(j, tok!"(", tok!")");
|
||||
symbols = getSymbolsByTokenChain(completionScope, tokens[1 .. j],
|
||||
cursorPosition, completionType);
|
||||
tokens = tokens[j + 1 .. $];
|
||||
|
@ -307,7 +271,7 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
{
|
||||
void skip(IdType open, IdType close)
|
||||
{
|
||||
i = skipEnd(tokens, i, open, close);
|
||||
tokens.skipParen(i, open, close);
|
||||
}
|
||||
|
||||
switch (tokens[i].type)
|
||||
|
@ -438,7 +402,7 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
|||
return symbols;
|
||||
}
|
||||
|
||||
private enum TYPE_IDENT_AND_LITERAL_CASES = q{
|
||||
enum TYPE_IDENT_CASES = q{
|
||||
case tok!"int":
|
||||
case tok!"uint":
|
||||
case tok!"long":
|
||||
|
@ -465,11 +429,16 @@ private enum TYPE_IDENT_AND_LITERAL_CASES = q{
|
|||
case tok!"this":
|
||||
case tok!"super":
|
||||
case tok!"identifier":
|
||||
};
|
||||
|
||||
enum STRING_LITERAL_CASES = q{
|
||||
case tok!"stringLiteral":
|
||||
case tok!"wstringLiteral":
|
||||
case tok!"dstringLiteral":
|
||||
};
|
||||
|
||||
enum TYPE_IDENT_AND_LITERAL_CASES = TYPE_IDENT_CASES ~ STRING_LITERAL_CASES;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -516,18 +485,7 @@ T getExpression(T)(T beforeTokens)
|
|||
skip:
|
||||
mixin (EXPRESSION_LOOP_BREAK);
|
||||
immutable bookmark = i;
|
||||
int depth = 1;
|
||||
do
|
||||
{
|
||||
if (depth == 0 || i == 0)
|
||||
break;
|
||||
else
|
||||
i--;
|
||||
if (beforeTokens[i].type == open)
|
||||
depth++;
|
||||
else if (beforeTokens[i].type == close)
|
||||
depth--;
|
||||
} while (true);
|
||||
beforeTokens.skipParenReverse(i, open, close);
|
||||
|
||||
skipCount++;
|
||||
|
||||
|
@ -622,11 +580,11 @@ bool isUdaExpression(T)(ref T tokens)
|
|||
{
|
||||
bool result;
|
||||
ptrdiff_t skip;
|
||||
ptrdiff_t i = tokens.length - 2;
|
||||
|
||||
auto i = cast(ptrdiff_t) tokens.length - 2;
|
||||
|
||||
if (i < 1)
|
||||
return result;
|
||||
|
||||
|
||||
// skips the UDA ctor
|
||||
if (tokens[i].type == tok!")")
|
||||
{
|
||||
|
@ -650,7 +608,7 @@ bool isUdaExpression(T)(ref T tokens)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (skip == 0)
|
||||
{
|
||||
// @UDA!SingleTemplateParameter
|
||||
|
@ -665,10 +623,14 @@ bool isUdaExpression(T)(ref T tokens)
|
|||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses a token slice in reverse to find the opening parentheses or square bracket
|
||||
* that begins the block the last token is in.
|
||||
*/
|
||||
size_t goBackToOpenParen(T)(T beforeTokens)
|
||||
in
|
||||
{
|
||||
|
@ -677,8 +639,6 @@ in
|
|||
body
|
||||
{
|
||||
size_t i = beforeTokens.length - 1;
|
||||
IdType open;
|
||||
IdType close;
|
||||
while (true) switch (beforeTokens[i].type)
|
||||
{
|
||||
case tok!",":
|
||||
|
@ -706,36 +666,69 @@ body
|
|||
case tok!"[":
|
||||
return i + 1;
|
||||
case tok!")":
|
||||
open = tok!")";
|
||||
close = tok!"(";
|
||||
goto skip;
|
||||
beforeTokens.skipParenReverse!true(i, tok!")", tok!"(");
|
||||
break;
|
||||
case tok!"}":
|
||||
open = tok!"}";
|
||||
close = tok!"{";
|
||||
goto skip;
|
||||
beforeTokens.skipParenReverse!true(i, tok!"}", tok!"{");
|
||||
break;
|
||||
case tok!"]":
|
||||
open = tok!"]";
|
||||
close = tok!"[";
|
||||
skip:
|
||||
if (i == 0)
|
||||
return size_t.max;
|
||||
else
|
||||
i--;
|
||||
int depth = 1;
|
||||
do
|
||||
{
|
||||
if (depth == 0 || i == 0)
|
||||
break;
|
||||
else
|
||||
i--;
|
||||
if (beforeTokens[i].type == open)
|
||||
depth++;
|
||||
else if (beforeTokens[i].type == close)
|
||||
depth--;
|
||||
} while (true);
|
||||
beforeTokens.skipParenReverse!true(i, tok!"]", tok!"[");
|
||||
break;
|
||||
default:
|
||||
return size_t.max;
|
||||
}
|
||||
return size_t.max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips blocks of parentheses until the starting block has been closed
|
||||
*/
|
||||
void skipParen(T)(T tokenSlice, ref size_t i, IdType open, IdType close)
|
||||
{
|
||||
if (i >= tokenSlice.length || tokenSlice.length <= 0)
|
||||
return;
|
||||
int depth = 1;
|
||||
while (depth != 0 && i + 1 != tokenSlice.length)
|
||||
{
|
||||
i++;
|
||||
if (tokenSlice[i].type == open)
|
||||
depth++;
|
||||
else if (tokenSlice[i].type == close)
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips blocks of parentheses in reverse until the starting block has been opened
|
||||
*/
|
||||
void skipParenReverse(bool before = false, T)(T beforeTokens, ref size_t i, IdType open, IdType close)
|
||||
{
|
||||
if (i == 0)
|
||||
return;
|
||||
int depth = 1;
|
||||
while (depth != 0 && i != 0)
|
||||
{
|
||||
i--;
|
||||
if (beforeTokens[i].type == open)
|
||||
depth++;
|
||||
else if (beforeTokens[i].type == close)
|
||||
depth--;
|
||||
}
|
||||
static if (before)
|
||||
if (i != 0)
|
||||
i--;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
Token[] t = [
|
||||
Token(tok!"identifier"), Token(tok!"identifier"), Token(tok!"("),
|
||||
Token(tok!"identifier"), Token(tok!"("), Token(tok!")"), Token(tok!",")
|
||||
];
|
||||
size_t i = t.length - 1;
|
||||
skipParenReverse!false(t, i, tok!")", tok!"(");
|
||||
assert(i == 2);
|
||||
i = t.length - 1;
|
||||
skipParenReverse!true(t, i, tok!")", tok!"(");
|
||||
assert(i == 1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
calltips
|
||||
void doStuff(int a, int b)
|
|
@ -0,0 +1,8 @@
|
|||
void doStuff(int a, int b) { return; }
|
||||
int getInt(int i, int[] b) { return i; }
|
||||
int b(int a) { return a; }
|
||||
void main(string[] args)
|
||||
{
|
||||
doStuff(getInt(1, [b(3)]),);
|
||||
auto x = 10, 20;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
set -e
|
||||
set -u
|
||||
|
||||
../../bin/dcd-client $1 file.d -c161 > actual1.txt
|
||||
diff actual1.txt expected1.txt
|
Loading…
Reference in New Issue