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

Allow semantic tokens to be provided by more than one provider #135602

Merged
merged 12 commits into from
Oct 25, 2021

Conversation

rchiodo
Copy link
Contributor

@rchiodo rchiodo commented Oct 21, 2021

This PR fixes #135580

Allow there to be more than one semantic token provider registered at the same time and pick the tokens from the provider that actually returns results.

This is necessary to get microsoft/vscode-jupyter#6799 working

Copy link
Member

@alexdima alexdima left a comment

Choose a reason for hiding this comment

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

These suggested changes introduce subtle problems in ModelSemanticColoring. In ModelSemanticColoring, there is a SemanticTokensProviderStyling instantiated for each DocumentSemanticTokensProvider. The SemanticTokensProviderStyling instance is able to decode semantic tokens according to the provider's legend.

So although the newly introduced CompositeDocumentSemanticTokensProvider is looping through multiple providers, the getLegend() call will only be made once for the single CompositeDocumentSemanticTokensProvider instance here. So there will be a situation where the legend of the first provider would be attempted to be used to decode the tokens of a different provider.

The other subtle problem is that semantic tokens supports incremental updating of semantic tokens, and for this purpose lastResultId is used. For simple semantic providers, which do not support incremental semantic tokens, lastResultId will always be null, so it doesn't matter if the lastResultId from one provider is passed as the lastResultId of another provider, but in case of two advanced document semantic tokens providers, we need to make sure to never mix the lastResultId from one tokens provider and pass it by accident as the lastResultId to a different tokens provider.

@aeschli aeschli assigned alexdima and unassigned aeschli Oct 22, 2021
@rchiodo rchiodo requested a review from alexdima October 22, 2021 17:19
@rchiodo
Copy link
Contributor Author

rchiodo commented Oct 22, 2021

@alexdima Thanks for the feedback.

I've changed the ModelSemanticColoring to ask for the legend after it gets results so it should use the correct legend now.

I've also added a weakmap that maps provider to their last result id to make sure it's allowed.

private disposables = new DisposableStore();
private didChangeEmitter = new Emitter<void>();
private lastUsedProvider: DocumentSemanticTokensProvider | undefined = undefined;
private static providerToLastResult = new WeakMap<DocumentSemanticTokensProvider, string>();
Copy link
Member

Choose a reason for hiding this comment

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

This static introduces another subtle bug in the case of having two files opened at the same time, even when having a single provider.

If file1.ts and file2.ts are shown side-by-side, and if file1.ts makes a request and has the resultId 1, and then file2.ts makes a request and has the resultId 2, then after typing in file1.ts the request will not use resultId 1 (which would be correct) because the last request to this provider returned the resultId 2 for file2.ts.

IMHO there is a problem with the lifecycle of CompositeDocumentSemanticTokensProvider here. Before, getDocumentSemanticTokens could be implemented stateless, but IMHO that is no longer the case now, as some state needs to be captured between semantic tokens requests (like e.g. what was the last selected provider).

I will try to refactor how ModelSemanticColoring interacts with the DocumentSemanticTokensProviderRegistry, but IMHO this can no longer be done with a stateless getDocumentSemanticTokens call. I am working directly on your branch, please hold off from pushing for now.

@alexdima
Copy link
Member

Thank you!

@alexdima alexdima merged commit af37dd9 into microsoft:main Oct 25, 2021
@alexdima alexdima added this to the October 2021 milestone Oct 25, 2021
@rchiodo
Copy link
Contributor Author

rchiodo commented Oct 25, 2021

Thanks @alexdima

@github-actions github-actions bot locked and limited conversation to collaborators Dec 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Semantic tokens allow for a single provider
3 participants