Skip to content

Commit e05f700

Browse files
committed
Merge remote-tracking branch 'origin/migrate-dap' into feature/lsp-formatting
2 parents 94086da + 16a7eb3 commit e05f700

File tree

17 files changed

+613
-126
lines changed

17 files changed

+613
-126
lines changed

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

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,37 @@
3131
import java.util.concurrent.CompletableFuture;
3232
import java.util.concurrent.CopyOnWriteArrayList;
3333
import java.util.concurrent.ExecutorService;
34+
import java.util.stream.Collectors;
3435

3536
import com.google.gson.JsonPrimitive;
37+
38+
import org.apache.logging.log4j.LogManager;
39+
import org.apache.logging.log4j.Logger;
3640
import org.checkerframework.checker.nullness.qual.Nullable;
3741
import org.eclipse.lsp4j.ClientCapabilities;
42+
import org.eclipse.lsp4j.DeleteFilesParams;
3843
import org.eclipse.lsp4j.DidChangeConfigurationParams;
3944
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
4045
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
4146
import org.eclipse.lsp4j.ExecuteCommandParams;
47+
import org.eclipse.lsp4j.FileDelete;
48+
import org.eclipse.lsp4j.FileOperationFilter;
49+
import org.eclipse.lsp4j.FileOperationOptions;
50+
import org.eclipse.lsp4j.FileOperationPattern;
51+
import org.eclipse.lsp4j.FileOperationsServerCapabilities;
52+
import org.eclipse.lsp4j.RenameFilesParams;
4253
import org.eclipse.lsp4j.ServerCapabilities;
4354
import org.eclipse.lsp4j.WorkspaceFolder;
4455
import org.eclipse.lsp4j.WorkspaceFoldersOptions;
4556
import org.eclipse.lsp4j.WorkspaceServerCapabilities;
4657
import org.eclipse.lsp4j.services.LanguageClient;
4758
import org.eclipse.lsp4j.services.LanguageClientAware;
4859
import org.eclipse.lsp4j.services.WorkspaceService;
60+
import org.rascalmpl.vscode.lsp.util.locations.Locations;
4961

5062
public class BaseWorkspaceService implements WorkspaceService, LanguageClientAware {
63+
private static final Logger logger = LogManager.getLogger(BaseWorkspaceService.class);
64+
5165
public static final String RASCAL_LANGUAGE = "Rascal";
5266
public static final String RASCAL_META_COMMAND = "rascal-meta-command";
5367
public static final String RASCAL_COMMAND = "rascal-command";
@@ -57,10 +71,13 @@ public class BaseWorkspaceService implements WorkspaceService, LanguageClientAwa
5771
private final IBaseTextDocumentService documentService;
5872
private final CopyOnWriteArrayList<WorkspaceFolder> workspaceFolders = new CopyOnWriteArrayList<>();
5973

74+
private final List<FileOperationPattern> interestedInFiles;
75+
6076

61-
protected BaseWorkspaceService(ExecutorService exec, IBaseTextDocumentService documentService) {
77+
protected BaseWorkspaceService(ExecutorService exec, IBaseTextDocumentService documentService, List<FileOperationPattern> interestedInFiles) {
6278
this.documentService = documentService;
6379
this.ownExecuter = exec;
80+
this.interestedInFiles = interestedInFiles;
6481
}
6582

6683

@@ -72,13 +89,35 @@ public void initialize(ClientCapabilities clientCap, @Nullable List<WorkspaceFol
7289

7390
var clientWorkspaceCap = clientCap.getWorkspace();
7491

75-
if (clientWorkspaceCap != null && Boolean.TRUE.equals(clientWorkspaceCap.getWorkspaceFolders())) {
76-
var workspaceCap = new WorkspaceFoldersOptions();
77-
workspaceCap.setSupported(true);
78-
workspaceCap.setChangeNotifications(true);
79-
capabilities.setWorkspace(new WorkspaceServerCapabilities(workspaceCap));
92+
WorkspaceServerCapabilities workspaceCapabilities = new WorkspaceServerCapabilities();
93+
if (clientWorkspaceCap != null) {
94+
if (clientWorkspaceCap.getWorkspaceFolders()) {
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.stream()
103+
.map(FileOperationFilter::new)
104+
.collect(Collectors.toList())
105+
);
106+
boolean watchesSet = false;
107+
if (clientWorkspaceCap.getFileOperations().getDidRename()) {
108+
fileOperationCapabilities.setDidRename(whichFiles);
109+
watchesSet = true;
110+
}
111+
if (clientWorkspaceCap.getFileOperations().getDidDelete()) {
112+
fileOperationCapabilities.setDidDelete(whichFiles);
113+
watchesSet = true;
114+
}
115+
if (watchesSet) {
116+
workspaceCapabilities.setFileOperations(fileOperationCapabilities);
117+
}
80118
}
81119

120+
capabilities.setWorkspace(workspaceCapabilities);
82121
}
83122

84123
public List<WorkspaceFolder> workspaceFolders() {
@@ -112,6 +151,33 @@ public void didChangeWorkspaceFolders(DidChangeWorkspaceFoldersParams params) {
112151
}
113152
}
114153

154+
@Override
155+
public void didRenameFiles(RenameFilesParams params) {
156+
logger.debug("workspace/didRenameFiles: {}", params.getFiles());
157+
158+
ownExecuter.submit(() -> {
159+
documentService.didRenameFiles(params, workspaceFolders());
160+
});
161+
162+
ownExecuter.submit(() -> {
163+
// cleanup the old files (we do not get a `didDelete` event)
164+
var oldFiles = params.getFiles().stream()
165+
.map(f -> f.getOldUri())
166+
.map(FileDelete::new)
167+
.collect(Collectors.toList());
168+
documentService.didDeleteFiles(new DeleteFilesParams(oldFiles));
169+
});
170+
}
171+
172+
@Override
173+
public void didDeleteFiles(DeleteFilesParams params) {
174+
logger.debug("workspace/didDeleteFiles: {}", params.getFiles());
175+
176+
ownExecuter.submit(() -> {
177+
documentService.didDeleteFiles(params);
178+
});
179+
}
180+
115181
@Override
116182
public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
117183
if (params.getCommand().startsWith(RASCAL_META_COMMAND) || params.getCommand().startsWith(RASCAL_COMMAND)) {
@@ -120,7 +186,7 @@ public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
120186
return documentService.executeCommand(languageName, command).thenApply(v -> v);
121187
}
122188

123-
return CompletableFuture.supplyAsync(() -> params.getCommand() + " was ignored.");
189+
return CompletableFuture.supplyAsync(() -> params.getCommand() + " was ignored.", ownExecuter);
124190
}
125191

126192

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
package org.rascalmpl.vscode.lsp;
2828

2929
import java.time.Duration;
30-
import java.util.Set;
30+
import java.util.List;
3131
import java.util.concurrent.CompletableFuture;
3232

33+
import org.eclipse.lsp4j.DeleteFilesParams;
3334
import org.eclipse.lsp4j.RenameFilesParams;
3435
import org.eclipse.lsp4j.ServerCapabilities;
36+
import org.eclipse.lsp4j.WorkspaceFolder;
3537
import org.eclipse.lsp4j.services.LanguageClient;
3638
import org.eclipse.lsp4j.services.TextDocumentService;
3739
import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter;
@@ -56,6 +58,7 @@ public interface IBaseTextDocumentService extends TextDocumentService {
5658

5759
boolean isManagingFile(ISourceLocation file);
5860

59-
default void didRenameFiles(RenameFilesParams params, Set<ISourceLocation> workspaceFolders) {}
61+
void didRenameFiles(RenameFilesParams params, List<WorkspaceFolder> workspaceFolders);
62+
void didDeleteFiles(DeleteFilesParams params);
6063
void cancelProgress(String progressId);
6164
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import io.usethesource.vallang.IList;
4040
import io.usethesource.vallang.ISet;
4141
import io.usethesource.vallang.ISourceLocation;
42+
import io.usethesource.vallang.ITuple;
4243
import io.usethesource.vallang.IValue;
4344
import io.usethesource.vallang.type.Type;
4445
import io.usethesource.vallang.type.TypeFactory;
@@ -62,19 +63,25 @@ public interface ILanguageContributions {
6263
public InterruptibleFuture<IList> selectionRange(IList focus);
6364
public InterruptibleFuture<IList> formatting(ITree input, ISourceLocation loc, IConstructor formattingOptions);
6465

66+
public InterruptibleFuture<ISourceLocation> prepareRename(IList focus);
67+
public InterruptibleFuture<ITuple> rename(IList focus, String name);
68+
public InterruptibleFuture<ITuple> didRenameFiles(IList fileRenames);
69+
6570
public CompletableFuture<IList> parseCodeActions(String command);
6671

6772
public CompletableFuture<Boolean> hasAnalysis();
6873
public CompletableFuture<Boolean> hasBuild();
6974
public CompletableFuture<Boolean> hasDocumentSymbol();
7075
public CompletableFuture<Boolean> hasCodeLens();
7176
public CompletableFuture<Boolean> hasInlayHint();
77+
public CompletableFuture<Boolean> hasRename();
7278
public CompletableFuture<Boolean> hasExecution();
7379
public CompletableFuture<Boolean> hasHover();
7480
public CompletableFuture<Boolean> hasDefinition();
7581
public CompletableFuture<Boolean> hasReferences();
7682
public CompletableFuture<Boolean> hasImplementation();
7783
public CompletableFuture<Boolean> hasCodeAction();
84+
public CompletableFuture<Boolean> hasDidRenameFiles();
7885
public CompletableFuture<Boolean> hasSelectionRange();
7986
public CompletableFuture<Boolean> hasFormatting();
8087

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

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import io.usethesource.vallang.IList;
6060
import io.usethesource.vallang.ISet;
6161
import io.usethesource.vallang.ISourceLocation;
62+
import io.usethesource.vallang.ITuple;
6263
import io.usethesource.vallang.IValue;
6364
import io.usethesource.vallang.IValueFactory;
6465
import io.usethesource.vallang.exceptions.FactTypeUseException;
@@ -90,6 +91,9 @@ public class InterpretedLanguageContributions implements ILanguageContributions
9091
private final CompletableFuture<@Nullable IFunction> references;
9192
private final CompletableFuture<@Nullable IFunction> implementation;
9293
private final CompletableFuture<@Nullable IFunction> codeAction;
94+
private final CompletableFuture<@Nullable IFunction> prepareRename;
95+
private final CompletableFuture<@Nullable IFunction> rename;
96+
private final CompletableFuture<@Nullable IFunction> didRenameFiles;
9397
private final CompletableFuture<@Nullable IFunction> selectionRange;
9498
private final CompletableFuture<@Nullable IFunction> formatting;
9599

@@ -104,6 +108,8 @@ public class InterpretedLanguageContributions implements ILanguageContributions
104108
private final CompletableFuture<Boolean> hasReferences;
105109
private final CompletableFuture<Boolean> hasImplementation;
106110
private final CompletableFuture<Boolean> hasCodeAction;
111+
private final CompletableFuture<Boolean> hasRename;
112+
private final CompletableFuture<Boolean> hasDidRenameFiles;
107113
private final CompletableFuture<Boolean> hasSelectionRange;
108114
private final CompletableFuture<Boolean> hasFormatting;
109115

@@ -148,6 +154,9 @@ public InterpretedLanguageContributions(LanguageParameter lang, IBaseTextDocumen
148154
this.references = getFunctionFor(contributions, LanguageContributions.REFERENCES);
149155
this.implementation = getFunctionFor(contributions, LanguageContributions.IMPLEMENTATION);
150156
this.codeAction = getFunctionFor(contributions, LanguageContributions.CODE_ACTION);
157+
this.prepareRename = getKeywordParamFunctionFor(contributions, LanguageContributions.RENAME, LanguageContributions.PREPARE_RENAME_SERVICE);
158+
this.rename = getFunctionFor(contributions, LanguageContributions.RENAME);
159+
this.didRenameFiles = getFunctionFor(contributions, LanguageContributions.DID_RENAME_FILES);
151160
this.selectionRange = getFunctionFor(contributions, LanguageContributions.SELECTION_RANGE);
152161
this.formatting = getFunctionFor(contributions, LanguageContributions.FORMATTING);
153162

@@ -163,6 +172,8 @@ public InterpretedLanguageContributions(LanguageParameter lang, IBaseTextDocumen
163172
this.hasReferences = nonNull(this.references);
164173
this.hasImplementation = nonNull(this.implementation);
165174
this.hasCodeAction = nonNull(this.codeAction);
175+
this.hasRename = nonNull(this.rename);
176+
this.hasDidRenameFiles = nonNull(this.didRenameFiles);
166177
this.hasSelectionRange = nonNull(this.selectionRange);
167178
this.hasFormatting = nonNull(this.formatting);
168179

@@ -266,19 +277,29 @@ private CompletableFuture<IConstructor> parseCommand(String command) {
266277
});
267278
}
268279

269-
private static CompletableFuture<@Nullable IFunction> getFunctionFor(CompletableFuture<ISet> contributions, String cons) {
280+
private static CompletableFuture<@Nullable IConstructor> getContribution(CompletableFuture<ISet> contributions, String cons) {
270281
return contributions.thenApply(conts -> {
271282
for (IValue elem : conts) {
272283
IConstructor contrib = (IConstructor) elem;
273284
if (cons.equals(contrib.getConstructorType().getName())) {
274-
return (IFunction) contrib.get(0);
285+
return contrib;
275286
}
276287
}
277288
logger.debug("No {} defined", cons);
278289
return null;
279290
});
280291
}
281292

293+
private static CompletableFuture<@Nullable IFunction> getFunctionFor(CompletableFuture<ISet> contributions, String cons) {
294+
return getContribution(contributions, cons).thenApply(contribution -> (IFunction) contribution.get(0));
295+
}
296+
297+
private static CompletableFuture<@Nullable IFunction> getKeywordParamFunctionFor(CompletableFuture<ISet> contributions, String cons, String kwParam) {
298+
return getContribution(contributions, cons).thenApply(contribution ->
299+
(IFunction) contribution.asWithKeywordParameters().getParameter(kwParam)
300+
);
301+
}
302+
282303
@Override
283304
public String getName() {
284305
return name;
@@ -320,6 +341,24 @@ public InterruptibleFuture<IList> inlayHint(@Nullable ITree input) {
320341
return execFunction(LanguageContributions.INLAY_HINT, inlayHint, VF.list(), input);
321342
}
322343

344+
@Override
345+
public InterruptibleFuture<ISourceLocation> prepareRename(IList focus) {
346+
debug(LanguageContributions.PREPARE_RENAME_SERVICE, focus.isEmpty() ? "" : focus.get(0));
347+
return execFunction(LanguageContributions.PREPARE_RENAME_SERVICE, prepareRename, URIUtil.unknownLocation(), focus);
348+
}
349+
350+
@Override
351+
public InterruptibleFuture<ITuple> rename(IList focus, String newName) {
352+
debug(LanguageContributions.RENAME_SERVICE, newName, focus.isEmpty() ? "" : focus.get(0));
353+
return execFunction(LanguageContributions.RENAME_SERVICE, rename, VF.tuple(VF.list(), VF.list()), focus, VF.string(newName));
354+
}
355+
356+
@Override
357+
public InterruptibleFuture<ITuple> didRenameFiles(IList fileRenames) {
358+
debug(LanguageContributions.DID_RENAME_FILES, fileRenames);
359+
return execFunction(LanguageContributions.DID_RENAME_FILES, didRenameFiles, VF.tuple(VF.list(), VF.list()), fileRenames);
360+
}
361+
323362
@Override
324363
public InterruptibleFuture<ISet> hover(IList focus) {
325364
debug(LanguageContributions.HOVER, focus.length());
@@ -400,6 +439,16 @@ public CompletableFuture<Boolean> hasInlayHint() {
400439
return hasInlayHint;
401440
}
402441

442+
@Override
443+
public CompletableFuture<Boolean> hasRename() {
444+
return hasRename;
445+
}
446+
447+
@Override
448+
public CompletableFuture<Boolean> hasDidRenameFiles() {
449+
return hasDidRenameFiles;
450+
}
451+
403452
@Override
404453
public CompletableFuture<Boolean> hasCodeLens() {
405454
return hasCodeLens;

0 commit comments

Comments
 (0)