Skip to content

Commit 64f9ed6

Browse files
FlorianKroissrubenporras
authored andcommitted
fix: Make sure DefaultFormatRegionsProvider is the default IFormatRegionsProvider
+ Add `service.ranking=1` to the properties of DefaultFormatRegionsProvider, so that it is properly used as the default + Extract lookup for IFormatRegionsProvider into Utility class + Add test cases for lookup
1 parent 914633c commit 64f9ed6

File tree

5 files changed

+149
-29
lines changed

5 files changed

+149
-29
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* See git history
11+
*******************************************************************************/
12+
package org.eclipse.lsp4e.test.format;
13+
14+
import static org.junit.Assert.assertTrue;
15+
16+
import java.util.Dictionary;
17+
import java.util.Hashtable;
18+
19+
import org.eclipse.jdt.annotation.Nullable;
20+
import org.eclipse.jface.text.IDocument;
21+
import org.eclipse.jface.text.IRegion;
22+
import org.eclipse.lsp4e.format.DefaultFormatRegionsProvider;
23+
import org.eclipse.lsp4e.format.IFormatRegionsProvider;
24+
import org.eclipse.lsp4e.internal.FormatRegionsProviderUtil;
25+
import org.junit.Test;
26+
import org.osgi.framework.BundleContext;
27+
import org.osgi.framework.FrameworkUtil;
28+
import org.osgi.framework.ServiceRegistration;
29+
30+
public class FormatRegionsProviderUtilTest {
31+
32+
@Test
33+
public void lookupOnlyDefault() throws Exception {
34+
var provider = FormatRegionsProviderUtil.lookup("noFormatProviderForThisId"); //$NON-NLS-1$
35+
assertTrue(provider instanceof DefaultFormatRegionsProvider);
36+
}
37+
38+
@Test
39+
public void lookup() throws Exception {
40+
// Setup
41+
IFormatRegionsProvider instance = new IFormatRegionsProvider() {
42+
43+
@Override
44+
public IRegion @Nullable [] getFormattingRegions(IDocument document) {
45+
return null;
46+
}
47+
48+
};
49+
50+
BundleContext bundleContext = FrameworkUtil.getBundle(FormatRegionsProviderUtil.class).getBundleContext();
51+
final Dictionary<String, Object> props = new Hashtable<>();
52+
props.put("serverDefinitionId", "foo");
53+
ServiceRegistration<IFormatRegionsProvider> serviceRegistration = bundleContext
54+
.registerService(IFormatRegionsProvider.class, instance, props);
55+
56+
IFormatRegionsProvider provider;
57+
// There is no matching provider, so we expect the default.
58+
provider = FormatRegionsProviderUtil.lookup("notMatching");
59+
assertTrue(provider instanceof DefaultFormatRegionsProvider);
60+
61+
// There is a matching provider
62+
provider = FormatRegionsProviderUtil.lookup("foo"); //$NON-NLS-1$
63+
assertTrue(provider == instance);
64+
65+
// Cleanup
66+
serviceRegistration.unregister();
67+
}
68+
69+
}

org.eclipse.lsp4e/OSGI-INF/org.eclipse.lsp4e.format.DefaultFormatRegionsProvider.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.lsp4e.format.DefaultFormatRegionsProvider">
3+
<property name="service.ranking" value="1"/>
34
<service>
45
<provide interface="org.eclipse.lsp4e.format.IFormatRegionsProvider"/>
56
</service>

org.eclipse.lsp4e/src/org/eclipse/lsp4e/DocumentContentSynchronizer.java

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.eclipse.jface.text.MultiTextSelection;
4646
import org.eclipse.lsp4e.format.IFormatRegionsProvider;
4747
import org.eclipse.lsp4e.internal.DocumentUtil;
48+
import org.eclipse.lsp4e.internal.FormatRegionsProviderUtil;
4849
import org.eclipse.lsp4e.operations.format.LSPFormatter;
4950
import org.eclipse.lsp4e.ui.Messages;
5051
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
@@ -68,9 +69,6 @@
6869
import org.eclipse.lsp4j.jsonrpc.messages.Either;
6970
import org.eclipse.lsp4j.services.LanguageServer;
7071
import org.eclipse.osgi.util.NLS;
71-
import org.osgi.framework.FrameworkUtil;
72-
import org.osgi.framework.InvalidSyntaxException;
73-
import org.osgi.framework.ServiceReference;
7472

7573
final class DocumentContentSynchronizer implements IDocumentListener {
7674

@@ -304,34 +302,12 @@ private void formatDocument() {
304302
}
305303

306304
private synchronized IRegion @Nullable [] getFormatRegions() {
305+
if (formatRegionsProvider == null) {
306+
formatRegionsProvider = FormatRegionsProviderUtil.lookup(languageServerWrapper.serverDefinition.id);
307+
}
307308
if (formatRegionsProvider != null) {
308309
return formatRegionsProvider.getFormattingRegions(document);
309310
}
310-
var serverId = "(serverDefinitionId=" + languageServerWrapper.serverDefinition.id + ")"; //$NON-NLS-1$ //$NON-NLS-2$
311-
final var bundle = FrameworkUtil.getBundle(this.getClass());
312-
if (bundle != null) {
313-
var bundleContext = bundle.getBundleContext();
314-
if (bundleContext != null) {
315-
try {
316-
ServiceReference<?> reference = null;
317-
var serviceReferences = bundleContext.getAllServiceReferences(IFormatRegionsProvider.class.getName(), serverId);
318-
if (serviceReferences != null) {
319-
reference = serviceReferences[0];
320-
} else {
321-
//Use LSP4E default implementation:
322-
reference = bundleContext.getServiceReference(IFormatRegionsProvider.class.getName());
323-
}
324-
if (reference != null) {
325-
formatRegionsProvider = (IFormatRegionsProvider) bundleContext.getService(reference);
326-
if (formatRegionsProvider != null) {
327-
return formatRegionsProvider.getFormattingRegions(document);
328-
}
329-
}
330-
} catch (InvalidSyntaxException e) {
331-
LanguageServerPlugin.logError(e);
332-
}
333-
}
334-
}
335311
return null;
336312
}
337313

org.eclipse.lsp4e/src/org/eclipse/lsp4e/format/DefaultFormatRegionsProvider.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
import org.eclipse.jdt.annotation.Nullable;
1515
import org.eclipse.jface.text.IDocument;
1616
import org.eclipse.jface.text.IRegion;
17+
import org.osgi.framework.BundleContext;
1718
import org.osgi.service.component.annotations.Component;
1819

1920
/**
2021
* Default OSGi service implementation if no bundle provides a OSGi service for {@link IFormatRegionsProvider}.
2122
*
23+
* <p>
24+
* This implementation has a 'service.ranking' of 1 so it is chosen as the default when querying
25+
* {@link BundleContext#getServiceReference(String)} without specifying a serverDefinitionId.
2226
*/
23-
@Component
27+
@Component(property={"service.ranking=1"})
2428
public class DefaultFormatRegionsProvider implements IFormatRegionsProvider {
2529

2630
@Override
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* See git history
11+
*******************************************************************************/
12+
package org.eclipse.lsp4e.internal;
13+
14+
import org.eclipse.jdt.annotation.Nullable;
15+
import org.eclipse.lsp4e.LanguageServerPlugin;
16+
import org.eclipse.lsp4e.format.IFormatRegionsProvider;
17+
import org.osgi.framework.FrameworkUtil;
18+
import org.osgi.framework.InvalidSyntaxException;
19+
import org.osgi.framework.ServiceReference;
20+
21+
public class FormatRegionsProviderUtil {
22+
23+
private FormatRegionsProviderUtil() {
24+
// this class shouldn't be instantiated
25+
}
26+
27+
/**
28+
* Lookup the {@link IFormatRegionsProvider} for the given server definition id.
29+
*
30+
* @param serverDefinitionId
31+
* The id the of the language server
32+
* @return The found {@link IFormatRegionsProvider} or {@code null}.
33+
* @see IFormatRegionsProvider
34+
*/
35+
public static @Nullable IFormatRegionsProvider lookup(String serverDefinitionId) {
36+
final var bundle = FrameworkUtil.getBundle(FormatRegionsProviderUtil.class);
37+
if (bundle == null) {
38+
return null;
39+
}
40+
41+
var bundleContext = bundle.getBundleContext();
42+
if (bundleContext == null) {
43+
return null;
44+
}
45+
46+
final ServiceReference<?>[] serviceReferences;
47+
try {
48+
String filter = "(serverDefinitionId=" + serverDefinitionId + ")"; //$NON-NLS-1$ //$NON-NLS-2$
49+
serviceReferences = bundleContext.getAllServiceReferences(IFormatRegionsProvider.class.getName(), filter);
50+
} catch (InvalidSyntaxException e) {
51+
LanguageServerPlugin.logError(e);
52+
return null;
53+
}
54+
55+
final ServiceReference<?> reference;
56+
if (serviceReferences != null) {
57+
reference = serviceReferences[0];
58+
} else {
59+
// Fallback to default
60+
reference = bundleContext.getServiceReference(IFormatRegionsProvider.class.getName());
61+
}
62+
63+
if (reference == null) {
64+
return null;
65+
}
66+
67+
return (IFormatRegionsProvider) bundleContext.getService(reference);
68+
}
69+
70+
}

0 commit comments

Comments
 (0)