Merge 5bc2a5af37
into 09f4e7e932
This commit is contained in:
commit
77a97dccc6
13
README.md
13
README.md
|
@ -314,6 +314,19 @@ Otherwise the client outputs _00000_ so that the length of the answer is guarant
|
||||||
45
|
45
|
||||||
133
|
133
|
||||||
|
|
||||||
|
## Inlay Hints
|
||||||
|
|
||||||
|
Build a list of extra annoations for your IDE to display.
|
||||||
|
You must submit the content of the current file displayed in your editor.
|
||||||
|
|
||||||
|
dcd-client --inlayHints
|
||||||
|
|
||||||
|
This is a W.I.P., currently it only provide annoatations about aliases for your variables,
|
||||||
|
more is planned.
|
||||||
|
|
||||||
|
#### Example output
|
||||||
|
|
||||||
|
42 ->MyAlias->MyType
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,12 @@ enum RequestKind : ushort
|
||||||
localUse = 0b00000010_00000000,
|
localUse = 0b00000010_00000000,
|
||||||
/// Remove import directory from server
|
/// Remove import directory from server
|
||||||
removeImport = 0b00000100_00000000,
|
removeImport = 0b00000100_00000000,
|
||||||
|
/// Get inlay hints
|
||||||
|
inlayHints = 0b00001000_00000000,
|
||||||
|
|
||||||
/// These request kinds require source code and won't be executed if there
|
/// These request kinds require source code and won't be executed if there
|
||||||
/// is no source sent
|
/// is no source sent
|
||||||
requiresSourceCode = autocomplete | doc | symbolLocation | search | localUse,
|
requiresSourceCode = autocomplete | doc | symbolLocation | search | localUse | inlayHints,
|
||||||
// dfmt on
|
// dfmt on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ int runClient(string[] args)
|
||||||
bool clearCache;
|
bool clearCache;
|
||||||
bool symbolLocation;
|
bool symbolLocation;
|
||||||
bool doc;
|
bool doc;
|
||||||
|
bool inlayHints;
|
||||||
bool query;
|
bool query;
|
||||||
bool printVersion;
|
bool printVersion;
|
||||||
bool listImports;
|
bool listImports;
|
||||||
|
@ -85,7 +86,7 @@ int runClient(string[] args)
|
||||||
getopt(args, "cursorPos|c", &cursorPos, "I", &addedImportPaths,
|
getopt(args, "cursorPos|c", &cursorPos, "I", &addedImportPaths,
|
||||||
"R", &removedImportPaths, "port|p", &port, "help|h", &help,
|
"R", &removedImportPaths, "port|p", &port, "help|h", &help,
|
||||||
"shutdown", &shutdown, "clearCache", &clearCache,
|
"shutdown", &shutdown, "clearCache", &clearCache,
|
||||||
"symbolLocation|l", &symbolLocation, "doc|d", &doc,
|
"symbolLocation|l", &symbolLocation, "doc|d", &doc, "inlayHints", &inlayHints,
|
||||||
"query|status|q", &query, "search|s", &search,
|
"query|status|q", &query, "search|s", &search,
|
||||||
"version", &printVersion, "listImports", &listImports,
|
"version", &printVersion, "listImports", &listImports,
|
||||||
"tcp", &useTCP, "socketFile", &socketFile,
|
"tcp", &useTCP, "socketFile", &socketFile,
|
||||||
|
@ -234,6 +235,8 @@ int runClient(string[] args)
|
||||||
request.kind |= RequestKind.search;
|
request.kind |= RequestKind.search;
|
||||||
else if(localUse)
|
else if(localUse)
|
||||||
request.kind |= RequestKind.localUse;
|
request.kind |= RequestKind.localUse;
|
||||||
|
else if (inlayHints)
|
||||||
|
request.kind |= RequestKind.inlayHints;
|
||||||
else
|
else
|
||||||
request.kind |= RequestKind.autocomplete;
|
request.kind |= RequestKind.autocomplete;
|
||||||
|
|
||||||
|
@ -255,6 +258,8 @@ int runClient(string[] args)
|
||||||
printSearchResponse(response);
|
printSearchResponse(response);
|
||||||
else if (localUse)
|
else if (localUse)
|
||||||
printLocalUse(response);
|
printLocalUse(response);
|
||||||
|
else if (inlayHints)
|
||||||
|
printInlayHintsResponse(response);
|
||||||
else
|
else
|
||||||
printCompletionResponse(response, fullOutput);
|
printCompletionResponse(response, fullOutput);
|
||||||
|
|
||||||
|
@ -384,6 +389,17 @@ void printLocationResponse(ref const AutocompleteResponse response)
|
||||||
writeln(makeTabSeparated(response.symbolFilePath, response.symbolLocation.to!string));
|
writeln(makeTabSeparated(response.symbolFilePath, response.symbolLocation.to!string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printInlayHintsResponse(ref const AutocompleteResponse response)
|
||||||
|
{
|
||||||
|
auto app = appender!(string[])();
|
||||||
|
foreach (ref completion; response.completions)
|
||||||
|
{
|
||||||
|
app.put(makeTabSeparated(completion.symbolLocation.to!string, completion.identifier));
|
||||||
|
}
|
||||||
|
foreach (line; app.data)
|
||||||
|
writeln(line);
|
||||||
|
}
|
||||||
|
|
||||||
void printCompletionResponse(ref const AutocompleteResponse response, bool extended)
|
void printCompletionResponse(ref const AutocompleteResponse response, bool extended)
|
||||||
{
|
{
|
||||||
if (response.completions.length > 0)
|
if (response.completions.length > 0)
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* This file is part of DCD, a development tool for the D programming language.
|
||||||
|
* Copyright (C) 2014 Brian Schott
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module dcd.server.autocomplete.inlayhints;
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
import std.algorithm;
|
||||||
|
import std.array;
|
||||||
|
import std.experimental.allocator;
|
||||||
|
import std.experimental.logger;
|
||||||
|
import std.typecons;
|
||||||
|
|
||||||
|
import dcd.server.autocomplete.util;
|
||||||
|
|
||||||
|
import dparse.lexer;
|
||||||
|
import dparse.rollback_allocator;
|
||||||
|
|
||||||
|
import dsymbol.modulecache;
|
||||||
|
import dsymbol.symbol;
|
||||||
|
import dsymbol.scope_;
|
||||||
|
import dsymbol.conversion;
|
||||||
|
import dsymbol.string_interning;
|
||||||
|
|
||||||
|
import dcd.common.messages;
|
||||||
|
|
||||||
|
import containers.hashset;
|
||||||
|
|
||||||
|
public AutocompleteResponse getInlayHints(const AutocompleteRequest request,
|
||||||
|
ref ModuleCache moduleCache)
|
||||||
|
{
|
||||||
|
// trace("Getting inlay hints comments");
|
||||||
|
AutocompleteResponse response;
|
||||||
|
|
||||||
|
LexerConfig config;
|
||||||
|
config.fileName = "";
|
||||||
|
auto cache = StringCache(request.sourceCode.length.optimalBucketCount);
|
||||||
|
auto tokenArray = getTokensForParser(cast(ubyte[]) request.sourceCode, config, &cache);
|
||||||
|
RollbackAllocator rba;
|
||||||
|
auto pair = generateAutocompleteTrees(tokenArray, &rba, -1, moduleCache);
|
||||||
|
scope(exit) pair.destroy();
|
||||||
|
|
||||||
|
void check(DSymbol* it, ref HashSet!size_t visited)
|
||||||
|
{
|
||||||
|
if (visited.contains(cast(size_t) it))
|
||||||
|
return;
|
||||||
|
if (it.symbolFile != "stdin") return;
|
||||||
|
visited.insert(cast(size_t) it);
|
||||||
|
|
||||||
|
//writeln("sym: ", it.name," ", it.location, " kind: ", it.kind," qualifier: ", it.qualifier);
|
||||||
|
//if (auto type = it.type)
|
||||||
|
//{
|
||||||
|
// writeln(" ", type.name, " kind: ", type.kind, " qualifier", type.qualifier);
|
||||||
|
// if (auto ttype = type.type)
|
||||||
|
// writeln(" ", ttype.name, " kind: ", ttype.kind, " qualifier", ttype.qualifier);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
// struct Data {}
|
||||||
|
// alias Alias1 = Data;
|
||||||
|
// Alias1 var; becomes: Alias1 [-> Data] var;
|
||||||
|
if (it.kind == CompletionKind.variableName && it.type && it.type.kind == CompletionKind.aliasName)
|
||||||
|
{
|
||||||
|
AutocompleteResponse.Completion c;
|
||||||
|
c.symbolLocation = it.location - 1;
|
||||||
|
|
||||||
|
DSymbol* type = it.type;
|
||||||
|
|
||||||
|
while (type)
|
||||||
|
{
|
||||||
|
if (type.kind == CompletionKind.aliasName && type.type)
|
||||||
|
c.identifier ~= "->" ~ type.type.name;
|
||||||
|
if (type.type && type.type.kind != CompletionKind.aliasName) break;
|
||||||
|
type = type.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.completions ~= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(part; it.opSlice())
|
||||||
|
check(part, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet!size_t visited;
|
||||||
|
foreach (symbol; pair.scope_.symbols)
|
||||||
|
{
|
||||||
|
check(symbol, visited);
|
||||||
|
foreach(part; symbol.opSlice())
|
||||||
|
check(part, visited);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
|
@ -24,3 +24,4 @@ import dcd.server.autocomplete.complete;
|
||||||
import dcd.server.autocomplete.doc;
|
import dcd.server.autocomplete.doc;
|
||||||
import dcd.server.autocomplete.localuse;
|
import dcd.server.autocomplete.localuse;
|
||||||
import dcd.server.autocomplete.symbols;
|
import dcd.server.autocomplete.symbols;
|
||||||
|
import dcd.server.autocomplete.inlayhints;
|
||||||
|
|
|
@ -347,6 +347,11 @@ int runServer(string[] args)
|
||||||
s.trySendResponse(symbolSearch(request, cache), "Could not perform symbol search");
|
s.trySendResponse(symbolSearch(request, cache), "Could not perform symbol search");
|
||||||
else if (request.kind & RequestKind.localUse)
|
else if (request.kind & RequestKind.localUse)
|
||||||
s.trySendResponse(findLocalUse(request, cache), "Couldnot find local usage");
|
s.trySendResponse(findLocalUse(request, cache), "Couldnot find local usage");
|
||||||
|
else if (request.kind & RequestKind.inlayHints)
|
||||||
|
{
|
||||||
|
info("Getting inlay hints");
|
||||||
|
s.trySendResponse(getInlayHints(request, cache), "Could not get inlay hints");
|
||||||
|
}
|
||||||
else if (needResponse)
|
else if (needResponse)
|
||||||
s.trySendResponse(AutocompleteResponse.ack, "Could not send ack");
|
s.trySendResponse(AutocompleteResponse.ack, "Could not send ack");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue