Skip to content

Commit e6ab901

Browse files
authored
Merge pull request #8514 from Achal1607/refactor-configuration
Refactored configuration management for LSP module
2 parents a29d0fc + 562e2e9 commit e6ab901

File tree

14 files changed

+1286
-114
lines changed

14 files changed

+1286
-114
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.modules.java.lsp.server.protocol;
20+
21+
import com.google.gson.JsonElement;
22+
import com.google.gson.JsonObject;
23+
import java.net.MalformedURLException;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import java.util.concurrent.CompletableFuture;
27+
import java.util.function.BiConsumer;
28+
import org.eclipse.lsp4j.ConfigurationItem;
29+
import org.eclipse.lsp4j.ConfigurationParams;
30+
import org.netbeans.api.project.FileOwnerQuery;
31+
import org.netbeans.api.project.Project;
32+
import org.netbeans.modules.java.lsp.server.Utils;
33+
import org.openide.filesystems.FileObject;
34+
import org.openide.filesystems.FileUtil;
35+
import org.openide.util.Lookup;
36+
37+
/**
38+
* Manages configuration settings for LSP clients
39+
*
40+
* @author atalati
41+
*/
42+
public class ClientConfigurationManager {
43+
44+
final ConfigValueCache cache = new ConfigValueCache();
45+
final NbCodeLanguageClient client;
46+
47+
public ClientConfigurationManager(NbCodeLanguageClient client) {
48+
this.client = client;
49+
}
50+
51+
public void registerConfigChangeListener(String section, BiConsumer<String, JsonElement> consumer) {
52+
cache.registerListener(section, consumer);
53+
}
54+
55+
public CompletableFuture<JsonElement> getConfigurationUsingAltPrefix(String config) {
56+
return lookupCacheAndGetConfig(List.of(config), null, true, true)
57+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
58+
}
59+
60+
public CompletableFuture<JsonElement> getConfigurationUsingAltPrefix(String config, String scope) {
61+
return lookupCacheAndGetConfig(List.of(config), scope, true, true)
62+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
63+
}
64+
65+
public CompletableFuture<JsonElement> getConfigurationUsingAltPrefixWithoutCaching(String config) {
66+
return lookupCacheAndGetConfig(List.of(config), null, false, false)
67+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
68+
}
69+
70+
public CompletableFuture<JsonElement> getConfigurationUsingAltPrefixWithoutCaching(String config, String scope) {
71+
return lookupCacheAndGetConfig(List.of(config), null, false, false)
72+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
73+
}
74+
75+
public CompletableFuture<List<JsonElement>> getConfigurationsUsingAltPrefix(List<String> configs) {
76+
return lookupCacheAndGetConfig(configs, null, true, true);
77+
}
78+
79+
public CompletableFuture<JsonElement> getConfiguration(String config) {
80+
return lookupCacheAndGetConfig(List.of(config), null, false, true)
81+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
82+
}
83+
84+
public CompletableFuture<JsonElement> getConfigurationWithoutCaching(String config) {
85+
return lookupCacheAndGetConfig(List.of(config), null, false, false)
86+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
87+
}
88+
89+
public CompletableFuture<JsonElement> getConfigurationWithoutCaching(String config, String scope) {
90+
return lookupCacheAndGetConfig(List.of(config), null, false, false)
91+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
92+
}
93+
94+
public CompletableFuture<JsonElement> getConfiguration(String config, String scope) {
95+
return lookupCacheAndGetConfig(List.of(config), scope, false, true)
96+
.thenApply(result -> result.isEmpty() ? null : result.get(0));
97+
}
98+
99+
public CompletableFuture<List<JsonElement>> getConfigurations(List<String> configs) {
100+
return lookupCacheAndGetConfig(configs, null, false, true);
101+
}
102+
103+
public CompletableFuture<List<JsonElement>> getConfigurations(List<String> configs, String scope) {
104+
return lookupCacheAndGetConfig(configs, scope, false, true);
105+
}
106+
107+
private CompletableFuture<List<JsonElement>> lookupCacheAndGetConfig(List<String> configs, String scope, boolean isAltPrefix, boolean isCachingRequired) {
108+
final String configPrefix = isAltPrefix ? client.getNbCodeCapabilities().getAltConfigurationPrefix() : client.getNbCodeCapabilities().getConfigurationPrefix();
109+
List<ConfigurationItem> itemsToRequest = new ArrayList<>();
110+
List<JsonElement> result = new ArrayList<>();
111+
String prjScope = getProjectFromFileScope(scope);
112+
113+
for (int i = 0; i < configs.size(); i++) {
114+
String config = configs.get(i);
115+
String prefixedConfig = configPrefix + config;
116+
JsonElement cachedValue = cache.getConfigValue(prefixedConfig, prjScope);
117+
if (cachedValue != null) {
118+
result.add(cachedValue);
119+
} else {
120+
ConfigurationItem item = new ConfigurationItem();
121+
if (scope != null) {
122+
item.setScopeUri(scope);
123+
}
124+
item.setSection(prefixedConfig);
125+
itemsToRequest.add(item);
126+
result.add(null);
127+
}
128+
}
129+
130+
if (itemsToRequest.isEmpty()) {
131+
return CompletableFuture.completedFuture(result);
132+
}
133+
134+
return client.configuration(new ConfigurationParams(itemsToRequest))
135+
.thenApply(clientConfigs -> {
136+
if (clientConfigs != null && clientConfigs.size() == result.size()) {
137+
int j = 0;
138+
for (int i = 0; i < result.size(); i++) {
139+
if (result.get(i) == null) {
140+
JsonElement value = (JsonElement) clientConfigs.get(j);
141+
result.set(i, value);
142+
String prefixedConfig = configPrefix + configs.get(i);
143+
if (isCachingRequired) {
144+
cache.cacheConfigValue(prefixedConfig, value, prjScope);
145+
}
146+
j++;
147+
}
148+
}
149+
} else {
150+
for (int i = 0; i < result.size(); i++) {
151+
if (result.get(i) == null) {
152+
result.set(i, new JsonObject());
153+
}
154+
}
155+
}
156+
return result;
157+
});
158+
}
159+
160+
public void handleConfigurationChange(JsonObject settings) {
161+
cache.updateCache(client, null, cache, settings);
162+
}
163+
164+
private String getProjectFromFileScope(String scope) {
165+
try {
166+
if (scope == null) {
167+
return null;
168+
}
169+
FileObject fo = Utils.fromUri(scope);
170+
if (fo == null) {
171+
return null;
172+
}
173+
Project prj = FileOwnerQuery.getOwner(fo);
174+
if (prj == null) {
175+
return findWorkspaceFolder(fo);
176+
}
177+
178+
return Utils.toUri(prj.getProjectDirectory());
179+
} catch (MalformedURLException ignored) {
180+
}
181+
return null;
182+
}
183+
184+
// Copied from abstract class SingleFileOptionsQueryImpl
185+
private String findWorkspaceFolder(FileObject file) {
186+
Workspace workspace = Lookup.getDefault().lookup(Workspace.class);
187+
if (workspace == null) {
188+
return null;
189+
}
190+
for (FileObject workspaceFolder : workspace.getClientWorkspaceFolders()) {
191+
if (FileUtil.isParentOf(workspaceFolder, file) || workspaceFolder == file) {
192+
return Utils.toUri(workspaceFolder);
193+
}
194+
}
195+
196+
//in case file is a source root, and the workspace folder is nested inside the root:
197+
for (FileObject workspaceFolder : workspace.getClientWorkspaceFolders()) {
198+
if (FileUtil.isParentOf(file, workspaceFolder)) {
199+
return Utils.toUri(workspaceFolder);
200+
}
201+
}
202+
203+
return null;
204+
}
205+
}

0 commit comments

Comments
 (0)