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 some clangd LSP extensions to the ClangdLanguageServer API #256

Merged
merged 1 commit into from
Feb 19, 2024

Conversation

travkin79
Copy link
Contributor

See discussion #253

Copy link
Member

@ruspl-afed ruspl-afed left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution @travkin79

Before moving on, the following issues need to be resolved:

  • copyright headers should be provided
  • commits should be squashed to one

Do you plan to add any test to demonstrate new API in action?

@travkin79
Copy link
Contributor Author

travkin79 commented Feb 19, 2024

Thanks for your feedback @ruspl-afed,

Before moving on, the following issues need to be resolved:

copyright headers should be provided
commits should be squashed to one

Done.

Do you plan to add any test to demonstrate new API in action?

I thought of some simple integration tests that use the LS using clangd (call the API and check the return value), but I don't know how to run clangd in a test environment. Maybe its better to use a LS mock, but then, I'm not sure what to test at all. :-)
Do you have any hints?

*
* @see {@link ClangdLanguageServer#getAst(AstParams)}
*/
public class AstNode {
Copy link
Contributor

Choose a reason for hiding this comment

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

I has a smell that cdt-lsp is providing these classes without using them. That's dead code in an exported package. @travkin79 could implement these classes in your custom plug-in where its used?

Copy link
Contributor

Choose a reason for hiding this comment

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

could implement these classes in your custom plug-in where its used?

Forget my comment, I think it s to be implemented here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These classes are part of the extended ClangdLanguageServer interface. Without them, the code will not compile and LSP4J will not be able to parse the LS response. Removing these classes would mean to remove the new methods from the ClangdLanguageServer interface, i.e. removing the new clangd LSP extensions.

Copy link
Contributor

@ghentschke ghentschke left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@ruspl-afed ruspl-afed left a comment

Choose a reason for hiding this comment

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

LGTM

@ruspl-afed
Copy link
Member

Done.

Thanks!

Do you have any hints?

Mock would be enough. The idea was to show how to use newly added API, not to test the real clangd response.

@ghentschke ghentschke merged commit 51ffc73 into eclipse-cdt:master Feb 19, 2024
3 checks passed
@ghentschke
Copy link
Contributor

@travkin79 Thank you!

@jonahgraham
Copy link
Member

@travkin79 I was wondering if you have any open source examples of using the clangd extensions in CDT LSP? Or, If you have used it internally, can you share a line or two of how you have used it? I am preparing my talk for EclipseCon next week and I want to highlight this change and how it is used in practice.

@travkin79
Copy link
Contributor Author

travkin79 commented Oct 15, 2024

Hi @jonahgraham,
It's great that you give a talk about CDT LSP, clangd, and their future. 👍 It would be great to see your slides some day or a video of your talk. 😄

I have no open source code that uses the new extensions from clangd, but I can give you some code excerpts using it. I must admit, we use only one of the two new LSP extensions.

I tried using the AST extension from LSP4E, CDT LSP, and clangd, but the responses from clangd were not convincing (not enough data or not as expected). Thus, we stopped using the AST API.

But we're actively using SymbolInfo API from LSP4E, CDT LSP, and clangd. We use it for retrieving some detailed documentation from an additional (code complementing) documentation model. We take a selected element in a CDT LSP editor, calculate a fully qualified name in order to create a URI, then resolve it in a documentation model and finally display the element's (enriched) documentation in a custom documentation view.

I'm not sure what code examples you're interested in, so here are some more lines that show you the new extension's usage:

import org.eclipse.xtext.naming.QualifiedName;

// ...

	public URI resolveDocumentation(IEditorInput editorInput, ITextSelection selection, IProgressMonitor monitor) {
		// ...
		if (editorInput instanceof IFileEditorInput) {
			IFileEditorInput input = (IFileEditorInput) editorInput;
			IDocument document = LSPEclipseUtils.getDocument(input.getFile());
			
			if (document != null) {
				// calculate qualified name first and check if we have a documentation
				List<SymbolDetails> symbolDetails = requestSymbolInfoFromLS(selection, document);
				for (SymbolDetails details: symbolDetails) {
					String name = details.getName();
					String containerName = details.getContainerName();
					String qualifiedName = containerName + name;
					
					String[] qualifiedNameSegments = qualifiedName.split("::");
						
					String memberName = null;
					// calculate member name if any
					// ...
						
					QualifiedName qualifiedElementName = QualifiedName.create(qualifiedNameSegments);
						
					URI uri = documentationModel.computeElementUri(qualifiedElementName, memberName, progress.split(50));
					if (uri != null) {
						return uri;
					}
				}
			}
		}
		// ...
	}

	private List<SymbolDetails> requestSymbolInfoFromLS(ITextSelection selection, IDocument document) {
		try {
			TextDocumentPositionParams params = LSPEclipseUtils.toTextDocumentPosistionParams(
					selection.getOffset(), document);
			return requestSymbolInfoFromLS(params, document);
		} catch (BadLocationException e) {
			//...log(e);
		}
		return Collections.emptyList();
	}
	
	private List<SymbolDetails> requestSymbolInfoFromLS(TextDocumentPositionParams params, IDocument document) {
		try {
			Optional<SymbolDetails[]> response = LanguageServers.forDocument(document)
				.computeFirst(server -> {
					if (server instanceof ClangdLanguageServer) {
						return ((ClangdLanguageServer) server).getSymbolInfo(params);
					}
					return null;
				}).get();
			if (response.isPresent()) {
				return Arrays.asList(response.get()).stream()
						.filter(detail -> detail != null)
						.collect(Collectors.toList());
			}
		} catch (ExecutionException e) {
			// ...log(e);
		} catch (InterruptedException e) {
			Thread.interrupted();
			// ...log(e);
		}
		return Collections.emptyList();
	}

Concerning CDT LSP challenges, there are a few, I'm interested in. You might consider the following GitHub issues / PRs / discussions interesting or noteworthy:

@jonahgraham
Copy link
Member

Thanks @travkin79 this is very useful and I will incorporate this into my talk. I will probably publish my talk slides on https://kichwacoders.com/blog/ after EclipseCon. I also expect the EF to publish the talks on Youtube in a EclipseCon 2024 playlist https://www.youtube.com/@EclipseFdn/playlists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants