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 resource to be opened to evaluate method to provide info for tester #400

Merged
merged 1 commit into from
Feb 20, 2023

Conversation

ghentschke
Copy link
Contributor

fix for #393

try {
final var context = new EvaluationContext(parent.get(), new Object());
context.setAllowPluginActivation(true);
if (openResource != null) {
context.addVariable("openResource", openResource); //$NON-NLS-1$
Copy link
Contributor

Choose a reason for hiding this comment

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

LSP4E manipulates more than resources. The common item is the IDocument. Would it be possible to use it instead?

Copy link
Contributor Author

@ghentschke ghentschke Jan 25, 2023

Choose a reason for hiding this comment

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

The idea is, that the object behind the openResource variable could be any object like IFile, IDocument or IEditorInput and that the enabledWhen tester for contentTypeMapping in the org.eclipse.lsp4e.languageServer extension point should handle this. In my case a PropertyTester checks the object type and handles it appropriately (similar to HasLanguageServerPropertyTester.java)

I named the variable openResource because it should be the object that LPS4E wants to manipulate. Then I can check in my property tester if LSP4E should do that or not. (files in old C-Projects should not cause clangd language server to be started). Trials with editorInput or viewer variables in my test failed because i have to check the file to be opened not the actual.

Maybe the variable name could be better like openObject or object or manipulatedObject ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

LSP4E manipulates more than resources. The common item is the IDocument. Would it be possible to use it instead?

Using IDocument now in evaluation contest as default variable now

@ghentschke ghentschke force-pushed the fix-issue-393 branch 4 times, most recently from 7bde942 to 93c8767 Compare February 9, 2023 09:48
Copy link
Contributor

@mickaelistria mickaelistria left a comment

Choose a reason for hiding this comment

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

One important thing is that sometimes, document may not pre-exist. In such case, the operation needs to create the document and then dispose it later. See for example how LSSearchQuery achieves that.

Comment on lines 36 to 38
public boolean isEnabled() {
return isUserEnabled() && isExtensionEnabled();
return isEnabled(null);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we delete those?

Copy link
Contributor Author

@ghentschke ghentschke Feb 10, 2023

Choose a reason for hiding this comment

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

We could, then the caller has to use isEnabled(null) when there is no document available (e.g. in org.eclipse.lsp4e.ui.EnableDisableLSJob.run(IProgressMonitor):

	@Override
	protected IStatus run(IProgressMonitor monitor) {
		for (ContentTypeToLanguageServerDefinition changedDefinition : serverDefinitions) {
			LanguageServerDefinition serverDefinition = changedDefinition.getValue();
			if (serverDefinition != null) {
				if (!changedDefinition.isEnabled(null)) {
         ...

I would prefer to delete those methods without argument, because then the developer is urged to provide a IDocument when using this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One important thing is that sometimes, document may not pre-exist. In such case, the operation needs to create the document and then dispose it later. See for example how LSSearchQuery achieves that.

I'll check that

Comment on lines 55 to 57
public boolean isExtensionEnabled() {
return enablement != null ? enablement.evaluate() : true;
return isExtensionEnabled(null);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we delete those?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same as above

Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer to delete those methods without argument, because then the developer is urged to provide a IDocument when using this method.

OK.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mickaelistria: Updated change. The evaluate method gets an URI and creates a document if its not pre-existing. It will be disposed after the check. Removed isExtensionEnabled() and isEnabled() call without arguments. Had to modify the tests according to the removal.

@ghentschke ghentschke force-pushed the fix-issue-393 branch 2 times, most recently from 224a090 to 6aeb52b Compare February 13, 2023 10:00
@mickaelistria
Copy link
Contributor

Using the URI is a good approach. However I think we should avoid setting a default variable; and instead explicitly include it in the context. I am not certain that the URI is the right variable to make default and thus not setting the default variable allows to not make a mistake that will be hard to resolve.
For consistency, we should try to add same variables or at least use the same names for variables as in GenericContentTypeRelatedExtension .
What do you think?

@ghentschke
Copy link
Contributor Author

ghentschke commented Feb 15, 2023

For me it's okay to do not use the default variable and use additionalVariables instead. In this case the user has to explicitly use the with statement to access these variables in a PropertyTester. But I think this would be okay.

I would like to add the following variables: document, resource, uri Uri is most flexible, because the user can determine external files. This is very important when handling C/C++ header files. The LS shall not be enabled on all external files.

@ghentschke
Copy link
Contributor Author

ghentschke commented Feb 15, 2023

org.eclipse.lsp4e.enablement.EnablementTester.evaluate(URI) looks like this when adding document, resource, and uri as variables. uri ist most reliable because document and resource can be null for external files:

	public boolean evaluate(URI uri) {
		boolean temporaryLoadDocument = false;
		IResource resource = null;
		try {
			IDocument document = null;
			resource = LSPEclipseUtils.findResourceFor(uri);
			if (resource != null) {
				document = LSPEclipseUtils.getExistingDocument(resource);
				if (document == null) {
					document = LSPEclipseUtils.getDocument(resource);
					temporaryLoadDocument = true;
				}
			}
			if (document == null) {
				temporaryLoadDocument = false;
			}
			final var context = new EvaluationContext(parent.get(), new Object());
			context.addVariable("document", //$NON-NLS-1$
					document != null ? document : IEvaluationContext.UNDEFINED_VARIABLE);
			context.addVariable("resource", //$NON-NLS-1$
					resource != null ? resource : IEvaluationContext.UNDEFINED_VARIABLE);
			context.addVariable("uri", //$NON-NLS-1$
					uri != null ? uri : IEvaluationContext.UNDEFINED_VARIABLE);
			context.setAllowPluginActivation(true);
			return expression.evaluate(context).equals(EvaluationResult.TRUE);
		} catch (CoreException e) {
			LanguageServerPlugin.logError("Error occured during evaluation of enablement expression", e); //$NON-NLS-1$
		} finally {
			if (temporaryLoadDocument && resource != null) {
				try {
					FileBuffers.getTextFileBufferManager().disconnect(resource.getFullPath(), LocationKind.IFILE, new NullProgressMonitor());
				} catch (CoreException e) {
					LanguageServerPlugin.logError(e);
				}
			}
		}

@mickaelistria
Copy link
Contributor

Thanks for this useful addition!

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.

2 participants