|
|
|
|
@ -68,11 +68,14 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
|
|
|
|
fakeIdent.type = tok!"identifier";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool dotId = beforeTokens.length >= 2 &&
|
|
|
|
|
beforeTokens[$-1] == tok!"identifier" && beforeTokens[$-2] == tok!".";
|
|
|
|
|
|
|
|
|
|
// detects if the completion request uses the current module `ModuleDeclaration`
|
|
|
|
|
// as access chain. In this case removes this access chain, and just keep the dot
|
|
|
|
|
// because within a module semantic is the same (`myModule.stuff` -> `.stuff`).
|
|
|
|
|
if (tokenArray.length >= 3 && tokenArray[0] == tok!"module" &&
|
|
|
|
|
beforeTokens[$-1] == tok!".")
|
|
|
|
|
if (tokenArray.length >= 3 && tokenArray[0] == tok!"module" && beforeTokens.length &&
|
|
|
|
|
(beforeTokens[$-1] == tok!"." || dotId))
|
|
|
|
|
{
|
|
|
|
|
const upper = tokenArray.countUntil!(a => a.type == tok!";");
|
|
|
|
|
bool isSame = true;
|
|
|
|
|
@ -80,11 +83,12 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
|
|
|
|
if (upper != -1 && beforeTokens.length >= upper * 2)
|
|
|
|
|
foreach (immutable i; 0 .. upper)
|
|
|
|
|
{
|
|
|
|
|
const j = beforeTokens.length - upper + i - 1;
|
|
|
|
|
const j = beforeTokens.length - upper + i - 1 - ubyte(dotId);
|
|
|
|
|
// verify that the chain is well located after an expr or a decl
|
|
|
|
|
if (i == 0)
|
|
|
|
|
{
|
|
|
|
|
if (beforeTokens[j].type.among(tok!"{", tok!"}", tok!";"))
|
|
|
|
|
if (beforeTokens[j].type.among(tok!"{", tok!"}", tok!";", tok!"[",
|
|
|
|
|
tok!"(", tok!",", tok!":"))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// compare the end of the "before tokens" (access chain)
|
|
|
|
|
@ -99,9 +103,15 @@ public AutocompleteResponse complete(const AutocompleteRequest request,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// replace the "before tokens" with a pattern making the remaining
|
|
|
|
|
// part of the completions think that it's a "Module Scope Operator".
|
|
|
|
|
// parts of the completion process think that it's a "Module Scope Operator".
|
|
|
|
|
if (isSame)
|
|
|
|
|
beforeTokens = assumeSorted([const Token(tok!"{"), const Token(tok!".")]);
|
|
|
|
|
{
|
|
|
|
|
if (dotId)
|
|
|
|
|
beforeTokens = assumeSorted([const Token(tok!"{"), const Token(tok!"."),
|
|
|
|
|
cast(const) beforeTokens[$-1]]);
|
|
|
|
|
else
|
|
|
|
|
beforeTokens = assumeSorted([const Token(tok!"{"), const Token(tok!".")]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (beforeTokens.length >= 2)
|
|
|
|
|
@ -200,21 +210,21 @@ AutocompleteResponse dotCompletion(T)(T beforeTokens, const(Token)[] tokenArray,
|
|
|
|
|
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
|
|
|
|
cursorPosition, CompletionType.identifiers, false, partial);
|
|
|
|
|
break;
|
|
|
|
|
// these tokens before a "." mean "Module Scope Operator"
|
|
|
|
|
case tok!":":
|
|
|
|
|
case tok!"(":
|
|
|
|
|
case tok!"[":
|
|
|
|
|
case tok!":":
|
|
|
|
|
break;
|
|
|
|
|
// these tokens before a "." means "Module Scope Operator"
|
|
|
|
|
case tok!"{":
|
|
|
|
|
case tok!";":
|
|
|
|
|
case tok!"}":
|
|
|
|
|
case tok!",":
|
|
|
|
|
auto allocator = scoped!(ASTAllocator)();
|
|
|
|
|
RollbackAllocator rba;
|
|
|
|
|
ScopeSymbolPair pair = generateAutocompleteTrees(tokenArray, allocator,
|
|
|
|
|
&rba, 1, moduleCache);
|
|
|
|
|
scope(exit) pair.destroy();
|
|
|
|
|
response.setCompletions(pair.scope_, getExpression(beforeTokens),
|
|
|
|
|
1, CompletionType.identifiers, false, "stdin");
|
|
|
|
|
1, CompletionType.identifiers, false, partial);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
@ -520,7 +530,9 @@ void setCompletions(T)(ref AutocompleteResponse response,
|
|
|
|
|
foreach (s; currentSymbols.filter!(a => isPublicCompletionKind(a.kind)
|
|
|
|
|
&& a.kind != CompletionKind.importSymbol
|
|
|
|
|
&& a.kind != CompletionKind.dummy
|
|
|
|
|
&& a.symbolFile == partial))
|
|
|
|
|
&& a.symbolFile == "stdin"
|
|
|
|
|
&& (partial !is null && toUpper(a.name.data).startsWith(toUpper(partial))
|
|
|
|
|
|| partial is null)))
|
|
|
|
|
{
|
|
|
|
|
response.completions ~= makeSymbolCompletionInfo(s, s.kind);
|
|
|
|
|
}
|
|
|
|
|
|