Skip to content

Commit 3963bb7

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix/rename-refactoring/ignored-modules
2 parents 96f93a0 + 873b94d commit 3963bb7

27 files changed

+746
-232
lines changed

rascal-lsp/src/main/checkerframework/lsp4j.astub

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,25 @@ public abstract class ResourceOperation {
8585
public @Nullable String getAnnotationId() {}
8686
public void setAnnotationId(final @Nullable String annotationId) { }
8787
}
88+
89+
90+
package org.eclipse.lsp4j;
91+
92+
import java.util.List;
93+
import org.checkerframework.checker.nullness.qual.*;
94+
95+
public class Diagnostic {
96+
public void setRelatedInformation(@Nullable final List<DiagnosticRelatedInformation> relatedInformation) { }
97+
}
98+
99+
100+
package org.eclipse.lsp4j;
101+
102+
import org.eclipse.lsp4j.*;
103+
import java.util.List;
104+
import org.checkerframework.checker.nullness.qual.*;
105+
106+
public class CallHierarchyItem {
107+
public void setDetail(@Nullable final String detail) { }
108+
public void setData(@Nullable final Object data) { }
109+
}

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/BaseWorkspaceService.java

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@
4545
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
4646
import org.eclipse.lsp4j.ExecuteCommandParams;
4747
import org.eclipse.lsp4j.FileDelete;
48-
import org.eclipse.lsp4j.FileOperationFilter;
49-
import org.eclipse.lsp4j.FileOperationOptions;
50-
import org.eclipse.lsp4j.FileOperationsServerCapabilities;
5148
import org.eclipse.lsp4j.RenameFilesParams;
5249
import org.eclipse.lsp4j.ServerCapabilities;
5350
import org.eclipse.lsp4j.WorkspaceFolder;
@@ -72,13 +69,11 @@ public abstract class BaseWorkspaceService implements WorkspaceService, Language
7269

7370
private final IBaseTextDocumentService documentService;
7471
private final CopyOnWriteArrayList<WorkspaceFolder> workspaceFolders = new CopyOnWriteArrayList<>();
75-
private final List<FileOperationFilter> interestedInFiles;
7672

7773

78-
protected BaseWorkspaceService(ExecutorService exec, IBaseTextDocumentService documentService, List<FileOperationFilter> interestedInFiles) {
74+
protected BaseWorkspaceService(ExecutorService exec, IBaseTextDocumentService documentService) {
7975
this.documentService = documentService;
8076
this.exec = exec;
81-
this.interestedInFiles = interestedInFiles;
8277
}
8378

8479
public void initialize(ClientCapabilities clientCap, @Nullable List<WorkspaceFolder> currentWorkspaceFolders, ServerCapabilities capabilities) {
@@ -89,32 +84,17 @@ public void initialize(ClientCapabilities clientCap, @Nullable List<WorkspaceFol
8984

9085
var clientWorkspaceCap = clientCap.getWorkspace();
9186

92-
WorkspaceServerCapabilities workspaceCapabilities = new WorkspaceServerCapabilities();
93-
if (clientWorkspaceCap != null) {
94-
if (clientWorkspaceCap.getWorkspaceFolders().booleanValue()) {
95-
var folderOptions = new WorkspaceFoldersOptions();
96-
folderOptions.setSupported(true);
97-
folderOptions.setChangeNotifications(true);
98-
workspaceCapabilities.setWorkspaceFolders(folderOptions);
99-
}
100-
101-
var fileOperationCapabilities = new FileOperationsServerCapabilities();
102-
var whichFiles = new FileOperationOptions(interestedInFiles);
103-
boolean watchesSet = false;
104-
if (clientWorkspaceCap.getFileOperations().getDidRename().booleanValue()) {
105-
fileOperationCapabilities.setDidRename(whichFiles);
106-
watchesSet = true;
107-
}
108-
if (clientWorkspaceCap.getFileOperations().getDidDelete().booleanValue()) {
109-
fileOperationCapabilities.setDidDelete(whichFiles);
110-
watchesSet = true;
111-
}
112-
if (watchesSet) {
113-
workspaceCapabilities.setFileOperations(fileOperationCapabilities);
114-
}
87+
if (capabilities.getWorkspace() == null) {
88+
capabilities.setWorkspace(new WorkspaceServerCapabilities());
11589
}
11690

117-
capabilities.setWorkspace(workspaceCapabilities);
91+
var workspaceCapabilities = capabilities.getWorkspace();
92+
if (clientWorkspaceCap != null && clientWorkspaceCap.getWorkspaceFolders().booleanValue()) {
93+
var folderOptions = new WorkspaceFoldersOptions();
94+
folderOptions.setSupported(true);
95+
folderOptions.setChangeNotifications(true);
96+
workspaceCapabilities.setWorkspaceFolders(folderOptions);
97+
}
11898
}
11999

120100
public List<WorkspaceFolder> workspaceFolders() {

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/InterpretedLanguageContributions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.rascalmpl.vscode.lsp.RascalLSPMonitor;
5252
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
5353
import org.rascalmpl.vscode.lsp.parametric.model.RascalADTs.LanguageContributions;
54+
import org.rascalmpl.vscode.lsp.rascal.conversion.KeywordParameter;
5455
import org.rascalmpl.vscode.lsp.util.EvaluatorUtil;
5556
import org.rascalmpl.vscode.lsp.util.EvaluatorUtil.LSPContext;
5657
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
@@ -266,8 +267,7 @@ private static boolean isTrue(@Nullable IConstructor constructor, String paramet
266267
if (constructor == null) {
267268
return false;
268269
}
269-
var val = constructor.asWithKeywordParameters().getParameter(parameter);
270-
return !(val instanceof IBool) || ((IBool)val).getValue();
270+
return KeywordParameter.get(parameter, constructor.asWithKeywordParameters(), true);
271271
}
272272

273273
private static ISet loadContributions(Evaluator eval, LanguageParameter lang) {

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.time.Duration;
3232
import java.util.ArrayList;
3333
import java.util.Arrays;
34+
import java.util.Collection;
3435
import java.util.Collections;
3536
import java.util.HashMap;
3637
import java.util.LinkedHashMap;
@@ -140,6 +141,8 @@
140141
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
141142
import org.rascalmpl.vscode.lsp.parametric.capabilities.CapabilityRegistration;
142143
import org.rascalmpl.vscode.lsp.parametric.capabilities.CompletionCapability;
144+
import org.rascalmpl.vscode.lsp.parametric.capabilities.FileOperationCapability;
145+
import org.rascalmpl.vscode.lsp.parametric.capabilities.ICapabilityParams;
143146
import org.rascalmpl.vscode.lsp.parametric.model.ParametricFileFacts;
144147
import org.rascalmpl.vscode.lsp.parametric.model.ParametricSummary;
145148
import org.rascalmpl.vscode.lsp.parametric.model.ParametricSummary.SummaryLookup;
@@ -150,16 +153,17 @@
150153
import org.rascalmpl.vscode.lsp.rascal.conversion.DocumentChanges;
151154
import org.rascalmpl.vscode.lsp.rascal.conversion.DocumentSymbols;
152155
import org.rascalmpl.vscode.lsp.rascal.conversion.FoldingRanges;
156+
import org.rascalmpl.vscode.lsp.rascal.conversion.KeywordParameter;
153157
import org.rascalmpl.vscode.lsp.rascal.conversion.SelectionRanges;
154158
import org.rascalmpl.vscode.lsp.rascal.conversion.SemanticTokenizer;
155159
import org.rascalmpl.vscode.lsp.uri.FallbackResolver;
160+
import org.rascalmpl.vscode.lsp.util.Maps;
156161
import org.rascalmpl.vscode.lsp.util.Versioned;
157162
import org.rascalmpl.vscode.lsp.util.concurrent.CompletableFutureUtils;
158163
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
159164
import org.rascalmpl.vscode.lsp.util.locations.Locations;
160165
import org.rascalmpl.vscode.lsp.util.locations.impl.TreeSearch;
161166

162-
import io.usethesource.vallang.IBool;
163167
import io.usethesource.vallang.IConstructor;
164168
import io.usethesource.vallang.IList;
165169
import io.usethesource.vallang.ISet;
@@ -258,7 +262,10 @@ private CapabilityRegistration availableCapabilities() {
258262
public void initializeServerCapabilities(ClientCapabilities clientCapabilities, final ServerCapabilities result) {
259263
// Since the initialize request is the very first request after connecting, we can initialize the capabilities here
260264
// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
261-
dynamicCapabilities = new CapabilityRegistration(availableClient(), exec, Set.of(new CompletionCapability()), clientCapabilities);
265+
dynamicCapabilities = new CapabilityRegistration(availableClient(), exec, clientCapabilities
266+
, new CompletionCapability()
267+
, /* new FileOperationCapability.DidCreateFiles(exec), */ new FileOperationCapability.DidRenameFiles(exec), new FileOperationCapability.DidDeleteFiles(exec)
268+
);
262269
dynamicCapabilities.registerStaticCapabilities(result);
263270

264271
result.setDefinitionProvider(true);
@@ -637,16 +644,16 @@ private InlayHint rowToInlayHint(IValue v) {
637644
var label = ((IString) t.get("label")).getValue();
638645
var kind = (IConstructor) t.get("kind");
639646
var tKW = t.asWithKeywordParameters();
640-
var toolTip = (IString)tKW.getParameter("toolTip");
641-
var atEnd = tKW.hasParameter("atEnd") && ((IBool)tKW.getParameter("atEnd")).getValue();
647+
var toolTip = KeywordParameter.get("toolTip", tKW, (String) null);
648+
var atEnd = KeywordParameter.get("atEnd", tKW, false);
642649

643650
// translate to lsp
644651
var result = new InlayHint(Locations.toPosition(loc, columns, atEnd), Either.forLeft(label.trim()));
645652
result.setKind(kind.getName().equals("type") ? InlayHintKind.Type : InlayHintKind.Parameter);
646653
result.setPaddingLeft(label.startsWith(" "));
647654
result.setPaddingRight(label.endsWith(" "));
648655
if (toolTip != null && toolTip.length() > 0) {
649-
result.setTooltip(toolTip.getValue());
656+
result.setTooltip(toolTip);
650657
}
651658
return result;
652659
}
@@ -994,18 +1001,18 @@ public synchronized void registerLanguage(LanguageParameter lang) {
9941001
multiplexer.addContributor(buildContributionKey(lang),
9951002
new InterpretedLanguageContributions(lang, this, availableWorkspaceService(), (IBaseLanguageClient)clientCopy, exec));
9961003

997-
// `CapabilityRegistration::update` should never be called asynchronously, since that might re-order incoming updates.
998-
// Since `registerLanguage` is called from a single-threaded pool, calling it here is safe.
999-
// Note: `CapabilityRegistration::update` returns a void future, which we do not have to wait on.
1000-
availableCapabilities().update(Collections.unmodifiableCollection(contributions.values()));
1001-
10021004
fact.reloadContributions();
10031005
fact.setClient(clientCopy);
10041006

10051007
for (var extension: lang.getExtensions()) {
10061008
this.registeredExtensions.put(extension, lang.getName());
10071009
}
10081010

1011+
// `CapabilityRegistration::update` should never be called asynchronously, since that might re-order incoming updates.
1012+
// Since `registerLanguage` is called from a single-threaded pool, calling it here is safe.
1013+
// Note: `CapabilityRegistration::update` returns a void future, which we do not have to wait on.
1014+
availableCapabilities().update(buildLanguageParams());
1015+
10091016
// If we opened any files with this extension before, now associate them with contributions
10101017
var extensions = Arrays.asList(lang.getExtensions());
10111018
for (var f : files.keySet()) {
@@ -1015,6 +1022,25 @@ public synchronized void registerLanguage(LanguageParameter lang) {
10151022
}
10161023
}
10171024

1025+
/**
1026+
* Works iff `contributions` and `registeredExtensions` are in sync.
1027+
* As long as this in only called from synchronized {@link registerLanguage}/{@link unregisterLanguage}, this should work fine.
1028+
*/
1029+
private Collection<ICapabilityParams> buildLanguageParams() {
1030+
var extensionsByLang = Maps.invert(registeredExtensions);
1031+
return contributions.entrySet().stream().map(e -> new ICapabilityParams() {
1032+
@Override
1033+
public ILanguageContributions contributions() {
1034+
return e.getValue();
1035+
}
1036+
1037+
@Override
1038+
public Set<String> fileExtensions() {
1039+
return extensionsByLang.getOrDefault(e.getKey(), Collections.emptySet());
1040+
}
1041+
}).collect(Collectors.toSet());
1042+
}
1043+
10181044
private void updateFileState(LanguageParameter lang, ISourceLocation f) {
10191045
f = f.top();
10201046
logger.trace("File of language {} - updating state: {}", lang.getName(), f);
@@ -1062,7 +1088,7 @@ public synchronized void unregisterLanguage(LanguageParameter lang) {
10621088
contributions.remove(lang.getName());
10631089
}
10641090

1065-
availableCapabilities().update(Collections.unmodifiableCollection(contributions.values()));
1091+
availableCapabilities().update(buildLanguageParams());
10661092
}
10671093

10681094
@Override

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricWorkspaceService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@
2626
*/
2727
package org.rascalmpl.vscode.lsp.parametric;
2828

29-
import java.util.List;
3029
import java.util.concurrent.ExecutorService;
31-
import org.eclipse.lsp4j.FileOperationFilter;
32-
import org.eclipse.lsp4j.FileOperationPattern;
3330
import org.rascalmpl.vscode.lsp.BaseWorkspaceService;
3431
import org.rascalmpl.vscode.lsp.IBaseTextDocumentService;
3532

3633
public class ParametricWorkspaceService extends BaseWorkspaceService {
3734
ParametricWorkspaceService(ExecutorService exec, IBaseTextDocumentService docService) {
38-
super(exec, docService, List.of(new FileOperationFilter(new FileOperationPattern("**/*"))));
35+
super(exec, docService);
3936
}
4037
}

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/AbstractDynamicCapability.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ protected final boolean preferStaticRegistration() {
9191
* @param contribs The {@link ILanguageContributions} that this capability reflects.
9292
* @return A future resolving to the options.
9393
*/
94-
protected abstract CompletableFuture<@Nullable O> options(ILanguageContributions contribs);
94+
protected abstract CompletableFuture<@Nullable O> options(ICapabilityParams language);
9595

9696
/**
9797
* Checks whether the given language contributions contain a contribution that provides this capability.
9898
* @param contribs The {@link ILanguageContributions} that this capability reflects.
9999
* @return A future resolving to `true` if there is such a contribution, or `false` otherwise.
100100
*/
101-
protected abstract CompletableFuture<Boolean> isProvidedBy(ILanguageContributions contribs);
101+
protected abstract CompletableFuture<Boolean> isProvidedBy(ICapabilityParams language);
102102

103103
/**
104104
* Merges two non-null option objects.

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/capabilities/CapabilityRegistration.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import org.eclipse.lsp4j.UnregistrationParams;
5454
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
5555
import org.eclipse.lsp4j.services.LanguageClient;
56-
import org.rascalmpl.vscode.lsp.parametric.ILanguageContributions;
5756
import org.rascalmpl.vscode.lsp.util.concurrent.CompletableFutureUtils;
5857

5958
/**
@@ -71,7 +70,7 @@ public class CapabilityRegistration {
7170
private final Set<AbstractDynamicCapability<?>> dynamicCapabilities;
7271
private final Set<AbstractDynamicCapability<?>> staticCapabilities;
7372

74-
private final AtomicReference<Collection<ILanguageContributions>> lastContributions = new AtomicReference<>(Collections.emptyList());
73+
private final AtomicReference<Collection<ICapabilityParams>> lastParams = new AtomicReference<>(Collections.emptyList());
7574
// Map of method names with current registration values
7675
private final Map<String, Registration> currentRegistrations = new ConcurrentHashMap<>();
7776

@@ -80,7 +79,7 @@ public class CapabilityRegistration {
8079
* @param supportedCapabilities The capabilities to register with the client.
8180
* @param clientCapabilities The capabilities of the client. Determine whether dynamic registration is supported at all.
8281
*/
83-
public CapabilityRegistration(LanguageClient client, Executor exec, Set<AbstractDynamicCapability<?>> supportedCapabilities, ClientCapabilities clientCapabilities) {
82+
public CapabilityRegistration(LanguageClient client, Executor exec, ClientCapabilities clientCapabilities, AbstractDynamicCapability<?>... supportedCapabilities) {
8483
this.client = client;
8584
this.exec = exec;
8685
this.noop = CompletableFutureUtils.completedFuture(null, exec);
@@ -113,11 +112,11 @@ public void registerStaticCapabilities(ServerCapabilities result) {
113112

114113
/**
115114
* Update capabilities for language contributions.
116-
* @param contribs The contributions to represent.
115+
* @param languages The contributions to represent.
117116
* @return A future that completes with a boolean that is false when any registration failed, and true otherwise.
118117
*/
119-
public CompletableFuture<Void> update(Collection<ILanguageContributions> contribs) {
120-
logger.debug("Updating {} dynamic capabilities from {} contributions", dynamicCapabilities.size(), contribs.size());
118+
public CompletableFuture<Void> update(Collection<ICapabilityParams> languages) {
119+
logger.debug("Updating {} dynamic capabilities for {} languages", dynamicCapabilities.size(), languages.size());
121120
// Copy the contributions so we know we are looking at a stable collection of elements.
122121

123122
/*
@@ -126,7 +125,7 @@ public CompletableFuture<Void> update(Collection<ILanguageContributions> contrib
126125
Therefore, we need to set this reference before delegating any work to futures, where we lose guaranteed execution order.
127126
Additionally, this function should be called from a thread pool with predictable execution order.
128127
*/
129-
lastContributions.set(List.copyOf(contribs));
128+
lastParams.set(List.copyOf(languages));
130129
return CompletableFutureUtils.reduce(dynamicCapabilities.stream().map(this::updateRegistration), exec)
131130
.thenAccept(_v -> logger.debug("Done updating dynamic capabilities"));
132131
}
@@ -157,16 +156,16 @@ public CompletableFuture<Void> update(Collection<ILanguageContributions> contrib
157156
* @return A future completing with `true` when successful, or `false` otherwise.
158157
*/
159158
private <T> CompletableFuture<Void> updateRegistration(AbstractDynamicCapability<T> cap) {
160-
var contribs = lastContributions.get();
159+
var params = lastParams.get();
161160
var method = cap.methodName();
162161

163-
return tryBuildRegistration(cap, contribs).thenCompose(registration -> {
162+
return tryBuildRegistration(cap, params).thenCompose(registration -> {
164163
// Synchronize on `currentRegistrations`, so we can reliable compute the required registration
165164
// and update the current registration without interference from other threads.
166165
synchronized (currentRegistrations) {
167166
// If someone else modified the contributions in the meantime, we need to restart.
168167
// Since we took a read-only copy of the contributions, instance comparison can be used everywhere
169-
if (lastContributions.get() != contribs) {
168+
if (lastParams.get() != params) {
170169
return updateRegistration(cap);
171170
}
172171

@@ -204,7 +203,7 @@ private <T> CompletableFuture<Void> updateRegistration(AbstractDynamicCapability
204203
}
205204

206205
// Ensure that the registration is eventually consistent.
207-
if (Objects.equals(currentRegistrations.get(method), registration) && lastContributions.get() == contribs) {
206+
if (Objects.equals(currentRegistrations.get(method), registration) && lastParams.get() == params) {
208207
// Our update persisted and the contributions did not change in the meantime. Success!
209208
return noop;
210209
}
@@ -282,13 +281,13 @@ private <T> void handleError(@Nullable Throwable t, AbstractDynamicCapability<T>
282281
logger.error("Unexpected error while (un)registering capability {}", cap.methodName(), t);
283282
}
284283

285-
private <T> CompletableFuture<@Nullable Registration> tryBuildRegistration(AbstractDynamicCapability<T> cap, Collection<ILanguageContributions> contribs) {
286-
if (contribs.isEmpty()) {
284+
private <T> CompletableFuture<@Nullable Registration> tryBuildRegistration(AbstractDynamicCapability<T> cap, Collection<ICapabilityParams> languages) {
285+
if (languages.isEmpty()) {
287286
return CompletableFutureUtils.completedFuture(null, exec);
288287
}
289288

290289
// Filter contributions by providing this capability
291-
return CompletableFutureUtils.filter(contribs, cap::isProvidedBy).<@Nullable Registration>thenCompose(cs -> {
290+
return CompletableFutureUtils.filter(languages, cap::isProvidedBy).<@Nullable Registration>thenCompose(cs -> {
292291
if (cs.isEmpty()) {
293292
return CompletableFutureUtils.completedFuture(null, exec);
294293
}

0 commit comments

Comments
 (0)