This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add semantic selection to ClangdLSPServer.
ClosedPublic

Authored by usaxena95 on Sep 18 2019, 10:18 AM.

Details

Summary

This adds semantic selection to the LSP Server.
Adds support for serialization of input request and the output reply.
Also adds regression tests for the feature.

Currently we do not support multi cursor.The LSP Server only accepts single position in the request as opposed to many position in the spec.

Spec:
https://github.com/microsoft/language-server-protocol/blob/dbaeumer/3.15/specification.md#textDocument_selectionRange

Event Timeline

usaxena95 created this revision.Sep 18 2019, 10:18 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 18 2019, 10:18 AM

A drive-by comment...

clang-tools-extra/clangd/ClangdLSPServer.cpp
1155

This should be return Reply(...), right?
Especially bad if positions is empty as we attempt to read the first element right away.

Fixed error message.

usaxena95 marked 2 inline comments as done.

Addressed comments.

usaxena95 added inline comments.Sep 18 2019, 11:16 AM
clang-tools-extra/clangd/ClangdLSPServer.cpp
1155

Aah. Yeah. Thanks.

I think we're missing the client/server capability implementation in this patch, we should include them.

clang-tools-extra/clangd/ClangdLSPServer.cpp
1151

maybe add an assert(!Params.positions.empty()). I think we should not run into this case.

clang-tools-extra/clangd/Protocol.h
1235

The data structures defined in Protocol are mirrored to LSP's. I think we should follow it for semantic selection as well (even though LSP use a wired structure, linked list).

so here, the structure should be like

struct SelectionRange {
    /**
     * The [range](#Range) of this selection range.
     */
    Range range;
    /**
     * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`.
     */
    llvm::Optional<SelectionRange> parent;
}

And we'd need to define a render function in ClangLSPServer to covert the vector<Range> to the LSP's SelectionRange.

1242

does this operator get used in this patch?

clang-tools-extra/clangd/test/selection-range.test
5

could we create a smaller test? just void func() {} is enough, I'd keep the lit test as small as possible (since this feature has been test in the unittest)

ilya-biryukov added inline comments.Sep 19 2019, 1:13 AM
clang-tools-extra/clangd/ClangdLSPServer.cpp
1151

But Params comes to clangd over LSP, right?
That means assert can fire in case of bad inputs over LSP to clangd.
Bad inputs over LSP should never crash clangd.

usaxena95 updated this revision to Diff 221499.Sep 24 2019, 3:34 AM
usaxena95 marked 7 inline comments as done.

Addressed comments:
Added client/server capabilities.
Made lit test smaller.

I am not sure adding client capability is useful here. I have not used the client capability for selectionRange anywhere and I think we can remove it.
WDYT ?

clang-tools-extra/clangd/ClangdLSPServer.cpp
1151

Yes this comes from the client and can be a bad input. We should just return error and not crash in such case.

clang-tools-extra/clangd/Protocol.h
1242

No. Removed it.

I am not sure adding client capability is useful here. I have not used the client capability for selectionRange anywhere and I think we can remove it.
WDYT ?

The SelectionRangeClientCapabilities determines what should the LSP server send the client, if it is true, clangd should send SelectionRangeRegistrationOptions. But looking at the current specification, it doesn't seem to add too much value. I think we can just simplify return a bool for now (as you did in this patch).

clang-tools-extra/clangd/ClangdLSPServer.cpp
142

nit: use for range.

1151

but the code still doesn't handle the empty case?

clang-tools-extra/clangd/Protocol.h
1244

I think we can simplify the code further, using llvm::Optional<SelectionRange> should be enough, the parent is null for the outer-most range.

usaxena95 updated this revision to Diff 221510.Sep 24 2019, 4:37 AM
usaxena95 marked 5 inline comments as done.

Addressed comments.

The SelectionRangeClientCapabilities determines what should the LSP server send the client, if it is true, clangd should send SelectionRangeRegistrationOptions.
But looking at the current specification, it doesn't seem to add too much value. I think we can just simplify return a bool for now (as you did in this patch).

Yeah. So should I remove the client capability since we do not use it and just return bool as now?

clang-tools-extra/clangd/ClangdLSPServer.cpp
1151

We do right ?
If the size != 1 then we just return an error.

clang-tools-extra/clangd/Protocol.h
1244

I don't think it is possible to do that since the type (SelectionRange) would be incomplete at that point. For example size of this class cannot be computed.

mostly good, a few nits.

clang-tools-extra/clangd/ClangdLSPServer.cpp
136

nit: remove the {}, in LLVM we prefer no {} for a single-statement body.

1151

yes, it is correct now. maybe I read the wrong snapshot before.

1168

does Reply({render(std::move(*Ranges))}); work?

clang-tools-extra/clangd/Protocol.h
422

I think we could drop this field now, it is not used, as we always return selectionRangeProvider:true.

1237

nit: please remove the markdown elements around the range in the comment.

1244

ah, good point, I see. We could just use std::unique_ptr<SelectionRange> parent;.

1247

Are these constructors needed?

usaxena95 updated this revision to Diff 221521.Sep 24 2019, 5:46 AM
usaxena95 marked 9 inline comments as done.

Addressed comments.

clang-tools-extra/clangd/ClangdLSPServer.cpp
1168

List initialization of vector of move only types is painful 😃
Even this does not work: Reply(std::vector<SelectionRange>{render(std::move(*Ranges))}); because I think it vector tries to copy construct it because of initializer_lists

clang-tools-extra/clangd/Protocol.h
1247

We don't need them if we use just unique_ptr. They were needed before in Optional<unique_ptr>. Somehow it was not able to deduce this is a trivially-constructible + move only class.

hokein accepted this revision.Sep 24 2019, 5:58 AM

thanks, looks good.

clang-tools-extra/clangd/Protocol.cpp
18

the header seems not used?

This revision is now accepted and ready to land.Sep 24 2019, 5:58 AM
usaxena95 updated this revision to Diff 221534.Sep 24 2019, 6:35 AM

Removed ununsed header.

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptSep 24 2019, 6:38 AM