Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new request to get inlay hints #762

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,19 @@ Otherwise the client outputs _00000_ so that the length of the answer is guarant
45
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

Expand Down
4 changes: 3 additions & 1 deletion common/src/dcd/common/messages.d
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ enum RequestKind : ushort
localUse = 0b00000010_00000000,
/// Remove import directory from server
removeImport = 0b00000100_00000000,
/// Get inlay hints
inlayHints = 0b00001000_00000000,

/// These request kinds require source code and won't be executed if there
/// is no source sent
requiresSourceCode = autocomplete | doc | symbolLocation | search | localUse,
requiresSourceCode = autocomplete | doc | symbolLocation | search | localUse | inlayHints,
// dfmt on
}

Expand Down
18 changes: 17 additions & 1 deletion src/dcd/client/client.d
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int runClient(string[] args)
bool clearCache;
bool symbolLocation;
bool doc;
bool inlayHints;
bool query;
bool printVersion;
bool listImports;
Expand All @@ -85,7 +86,7 @@ int runClient(string[] args)
getopt(args, "cursorPos|c", &cursorPos, "I", &addedImportPaths,
"R", &removedImportPaths, "port|p", &port, "help|h", &help,
"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,
"version", &printVersion, "listImports", &listImports,
"tcp", &useTCP, "socketFile", &socketFile,
Expand Down Expand Up @@ -234,6 +235,8 @@ int runClient(string[] args)
request.kind |= RequestKind.search;
else if(localUse)
request.kind |= RequestKind.localUse;
else if (inlayHints)
request.kind |= RequestKind.inlayHints;
else
request.kind |= RequestKind.autocomplete;

Expand All @@ -255,6 +258,8 @@ int runClient(string[] args)
printSearchResponse(response);
else if (localUse)
printLocalUse(response);
else if (inlayHints)
printInlayHintsResponse(response);
else
printCompletionResponse(response, fullOutput);

Expand Down Expand Up @@ -384,6 +389,17 @@ void printLocationResponse(ref const AutocompleteResponse response)
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)
{
if (response.completions.length > 0)
Expand Down
107 changes: 107 additions & 0 deletions src/dcd/server/autocomplete/inlayhints.d
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions src/dcd/server/autocomplete/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ import dcd.server.autocomplete.complete;
import dcd.server.autocomplete.doc;
import dcd.server.autocomplete.localuse;
import dcd.server.autocomplete.symbols;
import dcd.server.autocomplete.inlayhints;
5 changes: 5 additions & 0 deletions src/dcd/server/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ int runServer(string[] args)
s.trySendResponse(symbolSearch(request, cache), "Could not perform symbol search");
else if (request.kind & RequestKind.localUse)
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)
s.trySendResponse(AutocompleteResponse.ack, "Could not send ack");
}
Expand Down
Loading