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

Support Type Hierarchy #1231

Closed
wants to merge 8 commits into from

Conversation

CsCherrYY
Copy link

@CsCherrYY CsCherrYY commented Mar 29, 2021

There are three requests to support type hierarchy:

  • textDocument/prepareTypeHierarchy: Sent from the client to the server to get the type hierarchy item from the given text document position
  • typeHierarchy/supertypes and typeHierarchy/subtypes: Sent from the client to the server to resolve the given item's supertypes or subtypes

*
* @since 3.17.0
*/
typeHierarchyProvider?: boolean | TypeHierarchyOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a simple boolean necessary/sufficient here since each server capability can be defined under TypeHierarchyOptions?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we don't need boolean here in this version. We are considering whether to remove the capability inheritanceTreeSuppport to keep the type hierarchy general. I'll update this PR then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it was referring call hierarchy.

callHierarchyProvider?: boolean | CallHierarchyOptions | CallHierarchyRegistrationOptions;

which is equivalent to:

boolean // simplest 
OR
{
  workDoneProgress?: boolean;  // from WorkDoneProgressOptions
} 
OR
{
  workDoneProgress?: boolean;  // from WorkDoneProgressOptions
  id?: string;  // from StaticRegistrationOptions 
  documentSelector: DocumentSelector | null;  // from TextDocumentRegistrationOptions 
}

specifying whether server has capabitility to support work done progress / unregistration / customized scope of the feature.

Is a simple boolean necessary/sufficient here since each server capability can be defined under TypeHierarchyOptions?

@KamasamaK I think boolean is insufficient for advanced features mentioned above. For me, it's somehow necessary . Because on one hand, when I implement it in server side I might not care about any advanced feature, then I can simply return a true; on the other hand it's consistent with other capabilities like call hierarchy.

We are considering whether to remove the capability inheritanceTreeSuppport to keep the type hierarchy general.

@CsCherrYY I'm voting +1 for removing inheritanceTreeSuppport, otherwise for languages supporting multiple inheritance (e.g. C++), you may also need something like inheritanceGraphSuppport?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't care about implementing or can't implement advanced features, you can return false for their capabilities. For example, codeLensProvider only has a type of CodeLensOptions with one optional native capability, so that's already established for LSP. That is the reason I say it is probably unnecessary. But if the extra capability is going to be removed, that might change things.

Perhaps @dbaeumer can weigh in on the necessity of a simple boolean for new operations when *Options exists, and whether them having no or only optional native properties makes a difference in that determination.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing out CodeLensOptions. It looks:
{ resolveProvider: false } means server doesn't have a resolve provider.
{ resolveProvider: true } means server also support to resolve code lens.
So now I have a question, if server doesn't support code lens at all, what should it return? (if boolean is not allowed)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excluding codeLensProvider would indicate that the server does not support it.

A missing property should be interpreted as an absence of the capability. If a missing property normally defines sub properties, all missing sub properties should be interpreted as an absence of the corresponding capability.

_Response_:

* result: `TreeItem<TypeHierarchyItem> | null`
* error: code and message set in case an exception happens during the 'typeHierarchy/resolve' request
Copy link
Contributor

@KamasamaK KamasamaK Mar 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be 'typeHierarchy/inheritanceTree'? There is no 'typeHierarchy/resolve' request defined.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I'll fix it in the next commit.

```typescript
export interface TypeHierarchyOptions extends WorkDoneProgressOptions {
/**
* The server has support for supporting inheritance tree.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"support for supporting" -> "support for providing an"


_Response_:

* result: `TypeHierarchyItem[] | null` defined as follows:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we allow null here ? What's the client expected to do with a null? It's better to define this to either return an empty array, or an error. Alternatively explicitly define what the meaning of null is (as opposed to an empty array or an error return).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the textDocument/prepareTypeHierarchy request, if the element in the location of the params is not a valid type (that depends on the server implementation, whether to infer a valid type), it will return null to indicate that there is no result. For those types have no subtypes in typeHierarchy/subtypes, the server will return an empty array.

Thanks for the comment, I'll add a description in the next commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null is for consistency since lots of LSP requests that return and array can return null to indicate no elements


/**
* A data entry field that is preserved between a call hierarchy prepare and
* incoming calls or outgoing calls requests.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"and incoming calls or outgoing calls requests" - I'm not sure I understand what that's saying.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's copy/pasted from CallHierarchyItem.data and mistakenly unchanged.

```
_Response_:

* result: `TypeHierarchyItem[] | null`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, what's null for? we need to be explicit about what the valid responses are and what they mean, so that client and servers work together in harmony.

```
_Response_:

* result: `TypeHierarchyItem[] | null`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does null return mean?

```
_Response_:

* result: `TreeItem<TypeHierarchyItem> | null`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does null mean?


_Request_:

* method: 'typeHierarchy/subtypes'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious why there are so many messages here, nor why the prepare and resolve steps are required.

For clients (and presumably many servers), it would be simpler to return the whole tree in a single message. With this current API proposal there will be a lot of chatter for an ostensibly simple dataset. Could we perhaps incorporate the ability for the server to return the full type hierarchy in response to just a simple /typeHierarchy message as the first instance? Do we know that this is extremely expensive to calculate in many servers (enough to justify the complexity of this back-and-forth prepare/request/request/request API?

It's also unclear to me when a client should use subtypes and super types requests vs the inheritanceTree request - unless I'm missing something, they are implementing the same thing in a different way? What's the rationale for this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as you mentioned, calculating the full type hierarchy is extremely expensive for a given type with many subtypes. We currently have an implementation in Java language server, it may cost about 25 seconds to calculate the direct subtypes of java.io.Serializable (1877 subtypes in the example project in total). We want the user to know what server is doing - after prepare request, the client can get the base type itself so that it can be shown. So the user can see the based type with some progress icons at least, with partial result mechanism (if implemented), the client can show the results gradually.

For the second question, we have two common views for all languages, they are subtypes and supertypes. For single inheritance languages, since a given class could only have one superclass, usually they have another view to show all the classes in the inheritance tree. That can be performed in many supertypes requests and a subtypes request as well, so we're still in discussing whether to isolate this request.

@CsCherrYY
Copy link
Author

Thanks a lot for the comments from @KamasamaK @puremourning and @Eskibear , I have the following thinking and plan about updating this PR.

  • Address the wording issues and mistakes you have mentioned.
  • Remove typeHierarchy/inheritanceTree to make it general with both single inheritance languages and multiple inheritance languages, the support of inheritance tree could be implemented in clients.
  • Remove hasSupertypes and hasSubtypes to keep the interface simple. The clients would keep the status of each item.
  • As @puremourning said, it would be indeed simpler if we can return the full type hierarchy in one request, but performance issue is still crucial. Could we have a property naming like depth or level to indicate the resolve levels in the server? That allows the client to clear the resolve levels in one request. Since we're using partial result mechanism and the return type of typeHierarchy/supertypes or typeHierarchy/subtypes is an array, I have no promising idea to define a good data structure of the return array including more than one level of type hierarchy. Could we find a proper one?

Do you have any suggestions or comments?

@CsCherrYY
Copy link
Author

CsCherrYY commented Apr 20, 2021

Based on current typeHierarchy/supertypes and typeHierarchy/subtypes requests, it's still useful for single inheritance languages(C#, Java, etc.) to support inheritance tree view, so we have a draft to support inheritance tree view without changing current requests:

  • in TypeHierarchyOptions, inheritanceTreeSuppport can be used to indicate if the language server has support for inheritance tree.

    export interface TypeHierarchyOptions extends WorkDoneProgressOptions {
        /** 
         * The server supports for providing an inheritance tree.
         */
        inheritanceTreeSuppport?: boolean;
    }
    

    Client can offer an inheritance tree view if inheritanceTreeSuppport is true.

  • in TypeHierarchySupertypesParams, to distinguish between general typeHierarchy/supertypes requests and the typeHierarchy/supertypes requests during inheritance tree view initialization, classOnly is used to tell server if the request should only return class:

    export interface TypeHierarchySupertypesParams extends
        WorkDoneProgressParams, PartialResultParams {
        item: TypeHierarchyItem;
        /**
         * This request only asks for super class of the given type.
         */
        classOnly?: boolean;
    }
    
  • In inheritance tree view, client will send multiple typeHierarchy/supertypes requests with its classOnly set to true, the request will return super class of the given item. Based on this, client could get all ancestor classes of base type in the inheritance tree. Another typeHierarchy/subtypes request will be sent to get direct subtypes of base type in the initialization stage.

Does this make sense?

1. first a type hierarchy item is prepared for the given text document position.
1. for a type hierarchy item the supertype or subtype type hierarchy items are resolved.

In the first step, the `textDocument/prepareTypeHierarchy` request could have a unique, constant and optional `transactionId`. The following `typeHierarchy/supertypes` and `typeHierarchy/subtypes` requests in the second step could have the same `transactionId` in their params, which could be used to help indicate some cached data in the server.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not aware of any existing LSP API that uses this "prepare to get ID then pass ID back" method; this seems pretty specific to a particular LS implementation. The closest I'm aware of is completion (where it's arbitrary data), but that's because the user may not even visit a particular completion (so you want to defer that work to later in hopes it's never done). This new API appears to always call prepare, then one of the two other calls.

Why not just have the two calls and cache the information internally (say, per snapshot or similar?). This would match other similarly-expensive calls like go-to-references or go-to-implementations which are simple requests. If we were to add this to Pylance, we wouldn't need this transaction ID, as the info is there in the analysis (or will be lazily produced from the current state)

I can also see this pattern being problematic for LSIF (where you expect basically pure functions for read-only requests), but I guess the ID is optional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this "prepare to get ID then pass ID back" method

As far as I understand of this proposal, client is reponsible to generate this ID itself, and passes it to server in request textDocument/prepareTypeHierarchy. I assume the purpose of this "prepare" request is to get corresponding TypeHierarchyItem of the cursor position where you send the request, instead of getting ID.

As mentioned above in https://github.com/microsoft/language-server-protocol/pull/1231/files#r612267620 (though not explicitly described in spec) if it's not a valid type (e.g. triggered on some keywords), response of "prepare" request can be null, and client probably should not send further requests then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can sort of see the argument of needing to re-query at various points in the same hierarchy, but I can see troubles where because the client is defining this ID, it doesn't have enough information to determine when the result has actually changed (e.g., the server has changed the analysis and now this request cycle is invalid; like on an external file watcher change), and therefore requires something like how semantic tokenization has notifications for "the data has changed".

One thing that I think is similar to this right now is signature help retriggering; as the user moves the cursor, the previous signature info is passed back to the server, which can then use that to further edit the response, or, choose to ignore it and give the data fresh.

I guess I'll need to reread this with fresh eyes in the morning.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an alternative approach: the prepare request returns a TypeHierarchyItem so the data field of the item can be used to identify the type hierarchy. If the type hierarchy changes I would suggest that the server errors this on the next sub or super type request and lets the client decided what to do (e.g. refresh the hierarchy, close the hierarchy, ...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I find that to be a bit more understandable and close to completion resolution / signature help callbacks (assuming this new data field is something returned by the server at the prepare call, then passed back by the client, versus how this spec currently has the client come up with an ID).

Copy link
Author

@CsCherrYY CsCherrYY Apr 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an alternative approach: the prepare request returns a TypeHierarchyItem so the data field of the item can be used to identify the type hierarchy.

So under this approach, in my understanding, the server will be responsible for managing the "transaction" itself. It can save something to identify it in data field at the response of prepare call, as @jakebailey said. The client always keep it unchanged in the TypeHierarchyItem and send it back with the next sub or super type requests, is that right?

And if we apply this and remove transactionId in params, should we add some description explicitly to show that the data field could be used to carry the type hierarchy related information in the server? I think it may help the designers of language servers if the server can use this mechanism to improve the performance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CsCherrYY yes, that is the idea and consistent with other situations. For example the completion item has a data field as well which the clients needs to preserve and sent back on a resolve call so that the server can related the completion item to some previous request.

A comment in the data field that describes the use case of a transaction ID is for sure something we should do.

@CsCherrYY
Copy link
Author

I have updated the PR based on @dbaeumer 's comment and remove transactionId. Besides, the inheritanceTreeSuppport is added as a server capability in this commit as well, the draft is mentioned in #1231 (comment).

* type hierarchy in the server, helping improve the performance on
* resolving supertypes and subtypes.
*/
data?: unknown;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense for the prepare response to be an object (versus an array), and have a single data field? I guess I'm not sure to what extent the full call needs data versus each individual item (where if you really just wanted the same data, you'd have to dupe it on each of them).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, in clangd, what we put in the data field is a hash of the internal universal identifier of the symbol represented by the TypeHierarchyItem, so it being per-item makes sense.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we need a data field in each individual item would depend on server. If server could hold or cache the whole type hierarchy and use it to find a type in coming requests, one data field is OK, but if server wants to use data field to indicate the specific type, we'd better to keep a data field in each item. In protocol, I suggest keeping this field in each item to support these two usages both.

/**
* The server supports for providing an inheritance tree.
*/
inheritanceTreeSuppport?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in support

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not convinced that we should add inheritanceTreeSuppport in the first version since I don't see clients to support this rendering. IMO it makes things simply harder to understand. Or do I miss something?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My apologize for not mentioning the client behaviors about inheritanceTreeSupport in the protocol. I'd like to describe it in detail here:

When using inheritanceTreeSupport, the client has the same mechanism of handling response data as the other two requests. The only difference is how to set classOnly in TypeHierarchySupertypesParams.

  • If the server doesn't set inheritanceTreeSupport or it's false, the classOnly will always be undefined since the server doesn't support inheritance tree. Besides, Inheritance Tree button will hide in the client.
  • When the server set inheritanceTreeSupport to true, the client could show Inheritance Tree button.
    • If the active view is inheritance tree view, after prepare request, to get the most ancestor class of the given type, the client will send several typeHierarchy/supertypes requests with classOnly in their params set to true. The responses include all classes in the inheritance tree of the given item, so that the client can render this tree reversally. The remaining requests work normally.
    • If the active view is not inheritance tree view, classOnly will always be false and everything works normally.
  • In the server, if there is a typeHierarchy/supertypes request with its classOnly is true, the response should contain class only, otherwise it contains all types.

If there is no inheritanceTreeSupport in the protocol, since we'd like to support inheritance tree view for it's the most important type hierarchy view for Java users (might also for single inheritance language users), we have to independently implement the view in java extension instead. We might make it as a command and use workspace.executeCommand to trigger this view. In server, we'll have the similar logics to handle the supertype requests which return only class. Another concern is that if we can put the Inheritance Tree button properly. See the following screenshot:
type2
Currently we could put them together since we contribute ms-vscode.references-view, if the right two buttons are supported in LSP and implemented in client already, can we still find a way to put them together?

What do you think of this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was incorrect about what I said. I see the rendering but I am still not convinced for the modes in the API. Explaining this is simply too complicated. Why can a client not render that tree using the existing API by filtering interfaces. And what do we expect that happens if a client calls the API with classOnly for a item that represents a interface.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can a client not render that tree using the existing API by filtering interfaces.

A client can render that tree by filtering interfaces indeed. It's a good tradeoff to remove classOnly and put all the logics in client implementation to keep the protocol clear. If we remove classOnly and keep inheritanceTreeSupport in the first version, should we define the behaviors of client? If we remove inheritanceTreeSupport from the first version, my concern is whether we can still keep the inheritance tree view (from java extension) and the other two views button (from VSCode) together.

And what do we expect that happens if a client calls the API with classOnly for a item that represents a interface.

Currently we expect calling the API with classOnly for an interface will return an empty array since never a class can be the supertype of an interface.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not understanding why inheritanceTreeSupport can influence how a client can renderer a class hierarchy. Isn't this something that is under the sole control of the client and a server should never influence this?

Another problem I see with classOnly is that it is specific for a certain use case. It might cause problems with other languages. I could for example imagine a special view for language that have multiple class inheritance. Another view could be special for interface to see the implemented protocols.

If we think that that performance and payload size is a problem then we should add a filter property to the params which would allows to filter hierarchy items on the server side. IMO classOnly is simply to specific for a specific use case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About inheritanceTreeSupport

After reading through above comments, I think current naming is causing confusion. Let me help to clarify according to my understanding:

ServerCapabilities.inheritanceTreeSupport proposed by @CsCherrYY indicates whether "the language only supports single inheritance through class". E.g. it's true for Java because multiple inheritance is supported through interfaces. And it's false for C++. (@CsCherrYY correct me if I'm wrong)

"how a client can renderer a class hierarchy" mentioned by @dbaeumer should be related to a Client capability if needed. For example inheritanceTreeSupport, inheritanceGraphSupport (for multiple-inheritance languages?) etc. (@dbaeumer correct me if I'm wrong)

About classOnly

If we think that that performance and payload size is a problem then we should add a filter property to the params

Agree that classOnly is merely a specific filter property, is there any other filtering requirement (e.g. interfaceOnly), how would a generic filter property look like?
I'm testing this proposal on Java language server, so far I don't see any performance/payload size problems as we expand the hierarchy level by level, and I'm fine to filter items on either server/client side.

Here I only have a stupid question as I know little about client implementation details: No matter what the filtering property eventually is, if I want to support showing class view (e.g. using tree items in vscode's reference view) for Java, how does client know when to filter the items or not? Does it provide multiple entries (e.g."show supertypes", "show subtypes", "show class view", "show interface only") and send requests with different params corresponding to the entries?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filter properties would be properties that are available on a TypeHierarchyItem. I would say typically the kind property.

Regarding the UI: it could either be a different command or some sort of filter buttons in the UI.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's possible to keep the Class Hierarchy view available for the Java users, I'm very glad to remove inheritanceTreeSupport in the first version since it's indeed a little complicated. Here is another approach to support Class Hierarchy: The Java extension can contribute another button in reference-view and use a separated command to show class hierarchy. But there is still a concern about the UI implementation.

We want to make the separated class hierarchy button align with the two existing type hierarchy buttons (supertype hierarchy and subtype hierarchy). In the current reference-view implementation, the call hierarchy uses context value to control whether to show the button. Since the call hierarchy has only two views, it works well. But for type hierarchy, can we make the context value extendable to support possible other views? Then we can use other conditions like enablement to show if this button is disabled, like the current Java implementation.

@dbaeumer Could you give any suggestions?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: Another concern is about the default view. Currently the default type hierarchy view for java users is Class Hierarchy view, which is most frequently used by java developers. However, the implementation of type hierarchy in vscode-references-view would be based on the protocol, supporting subtype hierarchy view and supertype hierarchy view only. Could it be possible to change the default view of type hierarchy in another extension? e.g. Java extension.

Eskibear added a commit to Eskibear/vscode-languageserver-node that referenced this pull request May 17, 2021
Signed-off-by: Yan Zhang <yanzh@microsoft.com>
@Eskibear
Copy link
Member

I tried implementing current "prepare/supertypes/subtypes" proposal for Java on VS Code. Below is a demo based on type B1.

image

lsp-based-type-hierarchy_demo.mp4

@Eskibear
Copy link
Member

About performance and payload, I tested with interface java.io.Serializable which has ~1800 subtypes, it took 5-7s for the subtypes request. And it took ~60s to fetch subtypes of java.lang.Object, i.e. all types including anonymous ones.

lsp-based-type-hierarchy_serializable.mp4

Above was tested on Intel Core i7-10700. Server implementation depends on how powerful the CPU is, e.g. the Serializable case took ~20s for another machine with Intel Xeon E5-1620 v4 (less powerful).

Copy link
Contributor

@rcjsuen rcjsuen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For typeHierarchy/supertypes and typeHierarchy/subtypes, should the request parameters use something simpler than a TypeHierarchyItem. Is it necessary to include range and selectionRange when asking the server to fetch this information?

@CsCherrYY
Copy link
Author

For typeHierarchy/supertypes and typeHierarchy/subtypes, should the request parameters use something simpler than a TypeHierarchyItem. Is it necessary to include range and selectionRange when asking the server to fetch this information?

range and selectionRange could be used to specify the particular type in the server. In some cases, like resolving anonymous types in Java, we can't use only name, uri and detail to find the exact type. (Another way is to use data field to preserve some identifier, but data is not a required field)

@dbaeumer
Copy link
Member

dbaeumer commented Jun 3, 2021

@rcjsuen I was thinking the same but IMO this doesn't cause a lot of overhead and keeps the spec simpler. We don't need to define another type.

Regarding anonymous types: I think this are best identified using the data property on an item.

@CsCherrYY the performance is mainly influenced by the server producing the data. Not by sending them to the client. Right?

@CsCherrYY
Copy link
Author

@CsCherrYY the performance is mainly influenced by the server producing the data. Not by sending them to the client. Right?

Yes. The time for producing the data in the server takes up major time. I just tried @Eskibear 's implementation on my PC.

For java.io.Serializable (1877 subtypes), the total time to receive the response of java/subtypes is 23172ms, the time when producing the data in the server is 23082ms, which takes up about 99.6% of total time.

For java.util.List (37 subtypes), the total time to receive the response of java/subtypes is 2191ms, the time when producing the data in the server is 2176ms, which takes up about 99.3% of total time.

@dbaeumer
Copy link
Member

dbaeumer commented Jun 7, 2021

@CsCherrYY thanks for clarification.

@dbaeumer
Copy link
Member

@CsCherrYY as a next step we should add an implementation of the type hierarchy to the LSP client libraries for VS Code.

@CsCherrYY
Copy link
Author

@CsCherrYY as a next step we should add an implementation of the type hierarchy to the LSP client libraries for VS Code.

Sure. If we implement this protocol without inheritanceTreeSupport, there are still some concerns about the implementation, as I posted previously in #1231 (comment) and #1231 (comment):

  • For the UI: We would like to find a proper way to make the class hierarchy view button (will be contributed by Java extension) align with the supertype view button and subtype view button.
  • For the default view: We would like to make it possible to change the default view if the user is currently using Java extension.

@Eskibear is working on corresponding implementation for LSP client libraries already. I think we can focus on the implementation once we have resolved these concerns.

@dbaeumer
Copy link
Member

@CsCherrYY regarding #1231 (comment)

To my understanding this is a problem with the reference view. It has nothing to do with what we define in the protocol. Right?

If this is true then we need to discuss the button problem with the VS Code team and might need to think about a PR against https://github.com/Microsoft/vscode-references-view.

@CsCherrYY
Copy link
Author

CsCherrYY commented Jun 18, 2021

@CsCherrYY regarding #1231 (comment)

To my understanding this is a problem with the reference view. It has nothing to do with what we define in the protocol. Right?

If this is true then we need to discuss the button problem with the VS Code team and might need to think about a PR against https://github.com/Microsoft/vscode-references-view.

Yes, they are UI related problems and I'll create an issue to talk about this in the vscode repository.

@CsCherrYY
Copy link
Author

CsCherrYY commented Jun 18, 2021

@dbaeumer I have removed the part about inheritanceTreeSupport in 90090af and create microsoft/vscode#126666, we can discuss the UI problems there.

@isc-bsaviano
Copy link

What is the status of this PR? The TypeHierarchy API in VS Code is getting finalized for the upcoming release and the PR implementing this in vscode-languageserver-node was merged a while ago

@dbaeumer dbaeumer added this to the 3.17 milestone Sep 28, 2021
@dbaeumer
Copy link
Member

We will have a new propsed version of the libs beginning of October. Depending on the feedback there might be changes. When we have some confidence that all is good I will copy the MD part from the implementation to the spec. I would like to keep the PR open to not forget this.

@KamasamaK
Copy link
Contributor

Type Hierarchy has already been finalized for VS Code. Is anything still pending for this PR?

@dbaeumer
Copy link
Member

I wanted to wait with merging the spec to see if there is some feedback about the proposed implementation which is available since a while in the VS Code libs.

@KamasamaK
Copy link
Contributor

This was added to the spec in 7201ba1

@KamasamaK
Copy link
Contributor

@dbaeumer Since you already committed this feature yourself, this PR is no longer needed.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 7, 2022

Correct. Will close the PR

@dbaeumer dbaeumer closed this Apr 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants