Skip to content

Commit 0b427eb

Browse files
committed
Introduce universal configuration provider
1 parent e2bb297 commit 0b427eb

12 files changed

+565
-5
lines changed

org.eclipse.lsp4e/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Bundle-ActivationPolicy: lazy
5050
Bundle-Activator: org.eclipse.lsp4e.LanguageServerPlugin
5151
Export-Package: org.eclipse.lsp4e;x-internal:=true,
5252
org.eclipse.lsp4e.command;x-internal:=true,
53+
org.eclipse.lsp4e.configuration,
5354
org.eclipse.lsp4e.format;x-internal:=true,
5455
org.eclipse.lsp4e.operations.codeactions;x-internal:=true,
5556
org.eclipse.lsp4e.operations.completion;x-internal:=true,

org.eclipse.lsp4e/plugin.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<?eclipse version="3.4"?>
33
<plugin>
44
<extension-point id="languageServer" name="Language Server" schema="schema/languageServer.exsd"/>
5+
<extension-point id="languageServerConfiguration" name="Language Server configuration providers" schema="schema/languageServerConfiguration.exsd"/>
56
<!-- Extension point will ideally be "org.eclipse.text...." because
67
the feature should be part of the generic text editor -->
78
<extension
@@ -754,4 +755,10 @@
754755
</and>
755756
</definition>
756757
</extension>
758+
<extension
759+
point="org.eclipse.core.runtime.preferences">
760+
<modifier
761+
class="org.eclipse.lsp4e.PreferenceModifyListener2">
762+
</modifier>
763+
</extension>
757764
</plugin>

org.eclipse.lsp4e/schema/languageServer.exsd

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ If set to a number bigger than zero, the server will run until the timeout is re
151151
</documentation>
152152
</annotation>
153153
</attribute>
154+
<attribute name="watchConfiguration" type="string">
155+
<annotation>
156+
<documentation>
157+
comma separated list of configuration prefix
158+
</documentation>
159+
</annotation>
160+
</attribute>
154161
</complexType>
155162
</element>
156163

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<!-- Schema file written by PDE -->
3+
<schema targetNamespace="org.eclipse.lsp4e" xmlns="http://www.w3.org/2001/XMLSchema">
4+
<annotation>
5+
<appinfo>
6+
<meta.schema plugin="org.eclipse.lsp4e" id="languageServerConfiguration" name="Language Server configuration providers"/>
7+
</appinfo>
8+
<documentation>
9+
This extension point allows to define configuration sources.
10+
</documentation>
11+
</annotation>
12+
13+
<element name="extension">
14+
<annotation>
15+
<appinfo>
16+
<meta.element />
17+
</appinfo>
18+
</annotation>
19+
<complexType>
20+
<sequence>
21+
<element ref="provider" minOccurs="0" maxOccurs="unbounded"/>
22+
<element ref="alias" minOccurs="0" maxOccurs="unbounded"/>
23+
</sequence>
24+
<attribute name="point" type="string" use="required">
25+
<annotation>
26+
<documentation>
27+
28+
</documentation>
29+
</annotation>
30+
</attribute>
31+
<attribute name="id" type="string">
32+
<annotation>
33+
<documentation>
34+
35+
</documentation>
36+
</annotation>
37+
</attribute>
38+
<attribute name="name" type="string">
39+
<annotation>
40+
<documentation>
41+
42+
</documentation>
43+
<appinfo>
44+
<meta.attribute translatable="true"/>
45+
</appinfo>
46+
</annotation>
47+
</attribute>
48+
</complexType>
49+
</element>
50+
51+
<element name="provider">
52+
<complexType>
53+
<attribute name="class" type="string" use="required">
54+
<annotation>
55+
<documentation>
56+
57+
</documentation>
58+
<appinfo>
59+
<meta.attribute kind="java" basedOn=":org.eclipse.lsp4e.configuration.IConfigurationProvider"/>
60+
</appinfo>
61+
</annotation>
62+
</attribute>
63+
</complexType>
64+
</element>
65+
66+
<element name="alias">
67+
<complexType>
68+
<attribute name="source" type="string" use="required">
69+
<annotation>
70+
<documentation>
71+
Original settings paths already support by another provider
72+
</documentation>
73+
</annotation>
74+
</attribute>
75+
<attribute name="target" type="string" use="required">
76+
<annotation>
77+
<documentation>
78+
New settings paths
79+
</documentation>
80+
</annotation>
81+
</attribute>
82+
</complexType>
83+
</element>
84+
85+
<annotation>
86+
<appinfo>
87+
<meta.section type="since"/>
88+
</appinfo>
89+
<documentation>
90+
[Enter the first release in which this extension point appears.]
91+
</documentation>
92+
</annotation>
93+
94+
<annotation>
95+
<appinfo>
96+
<meta.section type="examples"/>
97+
</appinfo>
98+
<documentation>
99+
[Enter extension point usage example here.]
100+
</documentation>
101+
</annotation>
102+
103+
<annotation>
104+
<appinfo>
105+
<meta.section type="apiinfo"/>
106+
</appinfo>
107+
<documentation>
108+
[Enter API information here.]
109+
</documentation>
110+
</annotation>
111+
112+
<annotation>
113+
<appinfo>
114+
<meta.section type="implementation"/>
115+
</appinfo>
116+
<documentation>
117+
[Enter information about supplied implementation of this extension point.]
118+
</documentation>
119+
</annotation>
120+
121+
122+
</schema>

org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageClientImpl.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
import org.eclipse.jdt.annotation.NonNull;
2727
import org.eclipse.jface.text.ITextViewer;
2828
import org.eclipse.jface.text.source.SourceViewer;
29+
import org.eclipse.lsp4e.configuration.ConfigurationRegistry;
2930
import org.eclipse.lsp4e.progress.LSPProgressManager;
3031
import org.eclipse.lsp4e.ui.Messages;
3132
import org.eclipse.lsp4e.ui.UI;
3233
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
3334
import org.eclipse.lsp4j.ApplyWorkspaceEditResponse;
35+
import org.eclipse.lsp4j.ConfigurationItem;
3436
import org.eclipse.lsp4j.ConfigurationParams;
3537
import org.eclipse.lsp4j.Location;
3638
import org.eclipse.lsp4j.MessageActionItem;
@@ -75,8 +77,12 @@ protected final LanguageServer getLanguageServer() {
7577
public CompletableFuture<List<Object>> configuration(ConfigurationParams configurationParams) {
7678
// override as needed
7779
List<Object> list = new ArrayList<>(configurationParams.getItems().size());
78-
for (int i = 0; i < configurationParams.getItems().size(); i++) {
79-
list.add(null);
80+
for (ConfigurationItem item: configurationParams.getItems()) {
81+
if (item.getScopeUri() == null) {
82+
list.add(ConfigurationRegistry.getInstance().resolve(item.getSection()));
83+
} else {
84+
list.add(null);
85+
}
8086
}
8187
return CompletableFuture.completedFuture(list);
8288
}

org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServerWrapper.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.eclipse.jdt.annotation.Nullable;
6767
import org.eclipse.jface.text.IDocument;
6868
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
69+
import org.eclipse.lsp4e.configuration.ConfigurationRegistry;
6970
import org.eclipse.lsp4e.internal.FileBufferListenerAdapter;
7071
import org.eclipse.lsp4e.internal.SupportedFeatures;
7172
import org.eclipse.lsp4e.server.StreamConnectionProvider;
@@ -74,6 +75,7 @@
7475
import org.eclipse.lsp4j.ClientCapabilities;
7576
import org.eclipse.lsp4j.ClientInfo;
7677
import org.eclipse.lsp4j.CodeActionOptions;
78+
import org.eclipse.lsp4j.DidChangeConfigurationParams;
7779
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
7880
import org.eclipse.lsp4j.DocumentFormattingOptions;
7981
import org.eclipse.lsp4j.DocumentRangeFormattingOptions;
@@ -161,6 +163,7 @@ public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) {
161163
private final Timer timer = new Timer("Stop Language Server Task Processor"); //$NON-NLS-1$
162164
private TimerTask stopTimerTask;
163165
private AtomicBoolean stopping = new AtomicBoolean(false);
166+
private String[] subscribedConfig;
164167

165168
private final ExecutorService dispatcher;
166169

@@ -189,6 +192,7 @@ private LanguageServerWrapper(@Nullable IProject project, @NonNull LanguageServe
189192
this.initialPath = initialPath;
190193
this.serverDefinition = serverDefinition;
191194
this.connectedDocuments = new HashMap<>();
195+
this.subscribedConfig = serverDefinition.subcribedConfigurations;
192196
String projectName = (project != null && project.getName() != null && !serverDefinition.isSingleton) ? ("@" + project.getName()) : ""; //$NON-NLS-1$//$NON-NLS-2$
193197
String dispatcherThreadNameFormat = "LS-" + serverDefinition.id + projectName + "#dispatcher"; //$NON-NLS-1$ //$NON-NLS-2$
194198
this.dispatcher = Executors
@@ -307,6 +311,10 @@ public synchronized void start() throws IOException {
307311
this.initiallySupportsWorkspaceFolders = supportsWorkspaceFolders(serverCapabilities);
308312
}).thenRun(() -> {
309313
this.languageServer.initialized(new InitializedParams());
314+
}).thenRun(() -> {
315+
if (this.subscribedConfig != null && this.subscribedConfig.length > 0) {
316+
sendConfiguration();
317+
}
310318
}).thenRun(() -> {
311319
final Map<URI, IDocument> toReconnect = filesToReconnect;
312320
initializeFuture.thenRunAsync(() -> {
@@ -718,6 +726,34 @@ public void sendNotification(@NonNull Consumer<LanguageServer> fn) {
718726
getInitializedServer().thenAcceptAsync(fn, this.dispatcher);
719727
}
720728

729+
public void configurationChanged(String[] paths) {
730+
if (this.subscribedConfig == null) {
731+
return;
732+
}
733+
if (subscribedConfig.length == 0) {
734+
sendNotification(ls -> ls.getWorkspaceService().didChangeConfiguration(new DidChangeConfigurationParams()));
735+
} else {
736+
for (String prefix : subscribedConfig) {
737+
for (String path : paths) {
738+
if (path.startsWith(prefix)) {
739+
sendConfiguration();
740+
return;
741+
}
742+
}
743+
}
744+
}
745+
}
746+
747+
private void sendConfiguration()
748+
{
749+
Map<String, Object> obj = new HashMap<>();
750+
for (String prefx : subscribedConfig) {
751+
obj.put(prefx, ConfigurationRegistry.getInstance().resolve(prefx));
752+
}
753+
754+
sendNotification(ls -> ls.getWorkspaceService().didChangeConfiguration(new DidChangeConfigurationParams(obj)));
755+
}
756+
721757
/**
722758
* Runs a request on the language server
723759
*
@@ -913,6 +949,16 @@ void registerCapability(RegistrationParams params) {
913949
serverCapabilities.setTypeHierarchyProvider(Boolean.TRUE);
914950
addRegistration(reg, () -> serverCapabilities.setTypeHierarchyProvider(typeHierarchyBeforeRegistration));
915951
break;
952+
953+
case "workspace/didChangeConfiguration": //$NON-NLS-1$
954+
synchronized(this) {
955+
this.subscribedConfig = new String[0];
956+
addRegistration(reg, () -> {
957+
subscribedConfig = null;
958+
});
959+
}
960+
961+
break;
916962
}});
917963
}
918964

org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServersRegistry.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,24 @@ public class LanguageServersRegistry {
8989
private static final String LABEL_ATTRIBUTE = "label"; //$NON-NLS-1$
9090
private static final String ENABLED_WHEN_ATTRIBUTE = "enabledWhen"; //$NON-NLS-1$
9191
private static final String ENABLED_WHEN_DESC = "description"; //$NON-NLS-1$
92+
private static final String WATCH_CONFIGURATION = "watchConfiguration"; //$NON-NLS-1$
93+
private static final String COMMA = ","; //$NON-NLS-1$
9294

9395
public abstract static class LanguageServerDefinition {
9496
public final @NonNull String id;
9597
public final @NonNull String label;
9698
public final boolean isSingleton;
9799
public final int lastDocumentDisconnectedTimeout;
98100
public final @NonNull Map<IContentType, String> languageIdMappings;
101+
public final String[] subcribedConfigurations;
99102

100-
LanguageServerDefinition(@NonNull String id, @NonNull String label, boolean isSingleton, int lastDocumentDisconnectedTimeout) {
103+
LanguageServerDefinition(@NonNull String id, @NonNull String label, boolean isSingleton, int lastDocumentDisconnectedTimeout, String[] subscribedConfigurations) {
101104
this.id = id;
102105
this.label = label;
103106
this.isSingleton = isSingleton;
104107
this.lastDocumentDisconnectedTimeout = lastDocumentDisconnectedTimeout;
105108
this.languageIdMappings = new ConcurrentHashMap<>();
109+
this.subcribedConfigurations = subscribedConfigurations;
106110
}
107111

108112
public void registerAssociation(@NonNull IContentType contentType, @NonNull String languageId) {
@@ -159,7 +163,7 @@ private static int getLastDocumentDisconnectedTimeout(IConfigurationElement elem
159163
}
160164

161165
public ExtensionLanguageServerDefinition(@NonNull IConfigurationElement element) {
162-
super(element.getAttribute(ID_ATTRIBUTE), element.getAttribute(LABEL_ATTRIBUTE), getIsSingleton(element), getLastDocumentDisconnectedTimeout(element));
166+
super(element.getAttribute(ID_ATTRIBUTE), element.getAttribute(LABEL_ATTRIBUTE), getIsSingleton(element), getLastDocumentDisconnectedTimeout(element), element.getAttribute(WATCH_CONFIGURATION) == null ? null : element.getAttribute(WATCH_CONFIGURATION).split(COMMA));
163167
this.extension = element;
164168
}
165169

@@ -232,7 +236,7 @@ static class LaunchConfigurationLanguageServerDefinition extends LanguageServerD
232236

233237
public LaunchConfigurationLanguageServerDefinition(ILaunchConfiguration launchConfiguration,
234238
Set<String> launchModes) {
235-
super(launchConfiguration.getName(), launchConfiguration.getName(), DEFAULT_SINGLETON, DEFAULT_LAST_DOCUMENTED_DISCONNECTED_TIEMOUT);
239+
super(launchConfiguration.getName(), launchConfiguration.getName(), DEFAULT_SINGLETON, DEFAULT_LAST_DOCUMENTED_DISCONNECTED_TIEMOUT, null);
236240
this.launchConfiguration = launchConfiguration;
237241
this.launchModes = launchModes;
238242
}

0 commit comments

Comments
 (0)