Merge pull request #413 from WebFreak001/skip-fix
Fix calltips often reporting wrong functions merged-on-behalf-of: Brian Schott <Hackerpilot@users.noreply.github.com>
This commit is contained in:
commit
26b46a0735
|
@ -59,12 +59,8 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
||||||
request.cursorPosition, stringCache, tokenArray);
|
request.cursorPosition, stringCache, tokenArray);
|
||||||
if (beforeTokens.length >= 2)
|
if (beforeTokens.length >= 2)
|
||||||
{
|
{
|
||||||
if (beforeTokens[$ - 1] == tok!"(" || beforeTokens[$ - 1] == tok!"[")
|
if (beforeTokens[$ - 1] == tok!"(" || beforeTokens[$ - 1] == tok!"["
|
||||||
{
|
|| beforeTokens[$ - 1] == tok!",")
|
||||||
return parenCompletion(beforeTokens, tokenArray, request.cursorPosition,
|
|
||||||
moduleCache);
|
|
||||||
}
|
|
||||||
else if (beforeTokens[$ - 1] == tok!",")
|
|
||||||
{
|
{
|
||||||
immutable size_t end = goBackToOpenParen(beforeTokens);
|
immutable size_t end = goBackToOpenParen(beforeTokens);
|
||||||
if (end != size_t.max)
|
if (end != size_t.max)
|
||||||
|
@ -80,7 +76,7 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
||||||
beforeTokens = beforeTokens[$-1 .. $];
|
beforeTokens = beforeTokens[$-1 .. $];
|
||||||
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition,
|
return dotCompletion(beforeTokens, tokenArray, request.cursorPosition,
|
||||||
moduleCache);
|
moduleCache);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return importCompletion(beforeTokens, kind, moduleCache);
|
return importCompletion(beforeTokens, kind, moduleCache);
|
||||||
}
|
}
|
||||||
|
@ -122,16 +118,14 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
significantTokenType = tok!"identifier";
|
significantTokenType = tok!"identifier";
|
||||||
beforeTokens = beforeTokens[0 .. $ - 1];
|
beforeTokens = beforeTokens[0 .. $ - 1];
|
||||||
}
|
}
|
||||||
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".")
|
else if (beforeTokens.length >= 2 && beforeTokens[$ - 1] == tok!".")
|
||||||
significantTokenType = beforeTokens[$ - 2].type;
|
significantTokenType = beforeTokens[$ - 2].type;
|
||||||
else
|
else
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
switch (significantTokenType)
|
switch (significantTokenType)
|
||||||
{
|
{
|
||||||
case tok!"stringLiteral":
|
mixin(STRING_LITERAL_CASES);
|
||||||
case tok!"wstringLiteral":
|
|
||||||
case tok!"dstringLiteral":
|
|
||||||
foreach (symbol; arraySymbols)
|
foreach (symbol; arraySymbols)
|
||||||
{
|
{
|
||||||
response.completionKinds ~= symbol.kind;
|
response.completionKinds ~= symbol.kind;
|
||||||
|
@ -139,34 +133,9 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
||||||
}
|
}
|
||||||
response.completionType = CompletionType.identifiers;
|
response.completionType = CompletionType.identifiers;
|
||||||
break;
|
break;
|
||||||
case tok!"int":
|
mixin(TYPE_IDENT_CASES);
|
||||||
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":
|
|
||||||
case tok!")":
|
case tok!")":
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
case tok!"this":
|
|
||||||
case tok!"super":
|
|
||||||
auto allocator = scoped!(ASTAllocator)();
|
auto allocator = scoped!(ASTAllocator)();
|
||||||
RollbackAllocator rba;
|
RollbackAllocator rba;
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
||||||
|
@ -227,7 +196,6 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
break;
|
break;
|
||||||
case tok!"characterLiteral":
|
case tok!"characterLiteral":
|
||||||
case tok!"doubleLiteral":
|
case tok!"doubleLiteral":
|
||||||
case tok!"dstringLiteral":
|
|
||||||
case tok!"floatLiteral":
|
case tok!"floatLiteral":
|
||||||
case tok!"identifier":
|
case tok!"identifier":
|
||||||
case tok!"idoubleLiteral":
|
case tok!"idoubleLiteral":
|
||||||
|
@ -236,14 +204,13 @@ AutocompleteResponse parenCompletion(T)(T beforeTokens,
|
||||||
case tok!"irealLiteral":
|
case tok!"irealLiteral":
|
||||||
case tok!"longLiteral":
|
case tok!"longLiteral":
|
||||||
case tok!"realLiteral":
|
case tok!"realLiteral":
|
||||||
case tok!"stringLiteral":
|
|
||||||
case tok!"uintLiteral":
|
case tok!"uintLiteral":
|
||||||
case tok!"ulongLiteral":
|
case tok!"ulongLiteral":
|
||||||
case tok!"wstringLiteral":
|
|
||||||
case tok!"this":
|
case tok!"this":
|
||||||
case tok!"super":
|
case tok!"super":
|
||||||
case tok!")":
|
case tok!")":
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
|
mixin(STRING_LITERAL_CASES);
|
||||||
auto allocator = scoped!(ASTAllocator)();
|
auto allocator = scoped!(ASTAllocator)();
|
||||||
RollbackAllocator rba;
|
RollbackAllocator rba;
|
||||||
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
||||||
|
|
|
@ -147,36 +147,15 @@ SymbolStuff getSymbolsForCompletion(const AutocompleteRequest request,
|
||||||
request.cursorPosition, type), pair.symbol, pair.scope_);
|
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)
|
bool isSliceExpression(T)(T tokens, size_t index)
|
||||||
{
|
{
|
||||||
while (index < tokens.length) switch (tokens[index].type)
|
while (index < tokens.length) switch (tokens[index].type)
|
||||||
{
|
{
|
||||||
case tok!"[":
|
case tok!"[":
|
||||||
skip!(tok!"[", tok!"]")(tokens, index);
|
tokens.skipParen(index, tok!"[", tok!"]");
|
||||||
break;
|
break;
|
||||||
case tok!"(":
|
case tok!"(":
|
||||||
skip!(tok!"(", tok!")")(tokens, index);
|
tokens.skipParen(index, tok!"(", tok!")");
|
||||||
break;
|
break;
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
case tok!"}":
|
case tok!"}":
|
||||||
|
@ -200,22 +179,6 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||||
//dumpTokens(tokens.release);
|
//dumpTokens(tokens.release);
|
||||||
//writeln(">>>");
|
//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
|
// Find the symbol corresponding to the beginning of the chain
|
||||||
DSymbol*[] symbols;
|
DSymbol*[] symbols;
|
||||||
if (tokens.length == 0)
|
if (tokens.length == 0)
|
||||||
|
@ -224,7 +187,8 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||||
// e.g. (a.b!c).d
|
// e.g. (a.b!c).d
|
||||||
if (tokens[0] == tok!"(")
|
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],
|
symbols = getSymbolsByTokenChain(completionScope, tokens[1 .. j],
|
||||||
cursorPosition, completionType);
|
cursorPosition, completionType);
|
||||||
tokens = tokens[j + 1 .. $];
|
tokens = tokens[j + 1 .. $];
|
||||||
|
@ -307,7 +271,7 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||||
{
|
{
|
||||||
void skip(IdType open, IdType close)
|
void skip(IdType open, IdType close)
|
||||||
{
|
{
|
||||||
i = skipEnd(tokens, i, open, close);
|
tokens.skipParen(i, open, close);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tokens[i].type)
|
switch (tokens[i].type)
|
||||||
|
@ -438,7 +402,7 @@ DSymbol*[] getSymbolsByTokenChain(T)(Scope* completionScope,
|
||||||
return symbols;
|
return symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum TYPE_IDENT_AND_LITERAL_CASES = q{
|
enum TYPE_IDENT_CASES = q{
|
||||||
case tok!"int":
|
case tok!"int":
|
||||||
case tok!"uint":
|
case tok!"uint":
|
||||||
case tok!"long":
|
case tok!"long":
|
||||||
|
@ -465,11 +429,16 @@ private enum TYPE_IDENT_AND_LITERAL_CASES = q{
|
||||||
case tok!"this":
|
case tok!"this":
|
||||||
case tok!"super":
|
case tok!"super":
|
||||||
case tok!"identifier":
|
case tok!"identifier":
|
||||||
|
};
|
||||||
|
|
||||||
|
enum STRING_LITERAL_CASES = q{
|
||||||
case tok!"stringLiteral":
|
case tok!"stringLiteral":
|
||||||
case tok!"wstringLiteral":
|
case tok!"wstringLiteral":
|
||||||
case tok!"dstringLiteral":
|
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:
|
skip:
|
||||||
mixin (EXPRESSION_LOOP_BREAK);
|
mixin (EXPRESSION_LOOP_BREAK);
|
||||||
immutable bookmark = i;
|
immutable bookmark = i;
|
||||||
int depth = 1;
|
i = beforeTokens.skipParenReverse(i, open, close);
|
||||||
do
|
|
||||||
{
|
|
||||||
if (depth == 0 || i == 0)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
i--;
|
|
||||||
if (beforeTokens[i].type == open)
|
|
||||||
depth++;
|
|
||||||
else if (beforeTokens[i].type == close)
|
|
||||||
depth--;
|
|
||||||
} while (true);
|
|
||||||
|
|
||||||
skipCount++;
|
skipCount++;
|
||||||
|
|
||||||
|
@ -622,7 +580,7 @@ bool isUdaExpression(T)(ref T tokens)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
ptrdiff_t skip;
|
ptrdiff_t skip;
|
||||||
ptrdiff_t i = tokens.length - 2;
|
auto i = cast(ptrdiff_t) tokens.length - 2;
|
||||||
|
|
||||||
if (i < 1)
|
if (i < 1)
|
||||||
return result;
|
return result;
|
||||||
|
@ -669,6 +627,10 @@ bool isUdaExpression(T)(ref T tokens)
|
||||||
return result;
|
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)
|
size_t goBackToOpenParen(T)(T beforeTokens)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
@ -677,8 +639,6 @@ in
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
size_t i = beforeTokens.length - 1;
|
size_t i = beforeTokens.length - 1;
|
||||||
IdType open;
|
|
||||||
IdType close;
|
|
||||||
while (true) switch (beforeTokens[i].type)
|
while (true) switch (beforeTokens[i].type)
|
||||||
{
|
{
|
||||||
case tok!",":
|
case tok!",":
|
||||||
|
@ -706,36 +666,75 @@ body
|
||||||
case tok!"[":
|
case tok!"[":
|
||||||
return i + 1;
|
return i + 1;
|
||||||
case tok!")":
|
case tok!")":
|
||||||
open = tok!")";
|
i = beforeTokens.skipParenReverseBefore(i, tok!")", tok!"(");
|
||||||
close = tok!"(";
|
break;
|
||||||
goto skip;
|
|
||||||
case tok!"}":
|
case tok!"}":
|
||||||
open = tok!"}";
|
i = beforeTokens.skipParenReverseBefore(i, tok!"}", tok!"{");
|
||||||
close = tok!"{";
|
break;
|
||||||
goto skip;
|
|
||||||
case tok!"]":
|
case tok!"]":
|
||||||
open = tok!"]";
|
i = beforeTokens.skipParenReverseBefore(i, tok!"]", 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);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return size_t.max;
|
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
|
||||||
|
*/
|
||||||
|
size_t skipParenReverse(T)(T beforeTokens, size_t i, IdType open, IdType close)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
return 0;
|
||||||
|
int depth = 1;
|
||||||
|
while (depth != 0 && i != 0)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
if (beforeTokens[i].type == open)
|
||||||
|
depth++;
|
||||||
|
else if (beforeTokens[i].type == close)
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t skipParenReverseBefore(T)(T beforeTokens, size_t i, IdType open, IdType close)
|
||||||
|
{
|
||||||
|
i = skipParenReverse(beforeTokens, i, open, close);
|
||||||
|
if (i != 0)
|
||||||
|
i--;
|
||||||
|
return 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;
|
||||||
|
i = skipParenReverse(t, i, tok!")", tok!"(");
|
||||||
|
assert(i == 2);
|
||||||
|
i = t.length - 1;
|
||||||
|
i = skipParenReverseBefore(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