Skip to content

Commit

Permalink
Merge pull request #531 from usethesource/fix/rename-refactoring/modu…
Browse files Browse the repository at this point in the history
…le-names

Improve handling of qualified names when renaming
  • Loading branch information
toinehartman authored Jan 8, 2025
2 parents 68d0002 + 15b4f52 commit 257f075
Show file tree
Hide file tree
Showing 21 changed files with 734 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import java.util.concurrent.ExecutorService;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -149,17 +152,23 @@ public void write(JsonWriter target, IValue value) throws IOException {
}

@SuppressWarnings({"java:S2189", "java:S106"})
public static void startLanguageServer(Supplier<IBaseTextDocumentService> service, int portNumber) {
public static void startLanguageServer(ExecutorService threadPool, Function<ExecutorService, IBaseTextDocumentService> docServiceProvider, BiFunction<ExecutorService, IBaseTextDocumentService, BaseWorkspaceService> workspaceServiceProvider, int portNumber) {
logger.info("Starting Rascal Language Server: {}", getVersion());

if (DEPLOY_MODE) {
startLSP(constructLSPClient(capturedIn, capturedOut, new ActualLanguageServer(() -> System.exit(0), service.get())));
var docService = docServiceProvider.apply(threadPool);
var wsService = workspaceServiceProvider.apply(threadPool, docService);
docService.pair(wsService);
startLSP(constructLSPClient(capturedIn, capturedOut, new ActualLanguageServer(() -> System.exit(0), docService, wsService)));
}
else {
try (ServerSocket serverSocket = new ServerSocket(portNumber, 0, InetAddress.getByName("127.0.0.1"))) {
logger.info("Rascal LSP server listens on port number: {}", portNumber);
while (true) {
startLSP(constructLSPClient(serverSocket.accept(), new ActualLanguageServer(() -> {}, service.get())));
var docService = docServiceProvider.apply(threadPool);
var wsService = workspaceServiceProvider.apply(threadPool, docService);
docService.pair(wsService);
startLSP(constructLSPClient(serverSocket.accept(), new ActualLanguageServer(() -> {}, docService, wsService)));
}
} catch (IOException e) {
logger.fatal("Failure to start TCP server", e);
Expand Down Expand Up @@ -206,10 +215,10 @@ private static class ActualLanguageServer implements IBaseLanguageServerExtensi
private final Runnable onExit;
private IDEServicesConfiguration ideServicesConfiguration;

private ActualLanguageServer(Runnable onExit, IBaseTextDocumentService lspDocumentService) {
private ActualLanguageServer(Runnable onExit, IBaseTextDocumentService lspDocumentService, BaseWorkspaceService lspWorkspaceService) {
this.onExit = onExit;
this.lspDocumentService = lspDocumentService;
this.lspWorkspaceService = new BaseWorkspaceService(lspDocumentService);
this.lspWorkspaceService = lspWorkspaceService;
reg.registerLogical(new ProjectURIResolver(this::resolveProjectLocation));
reg.registerLogical(new TargetURIResolver(this::resolveProjectLocation));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;

import com.google.gson.JsonPrimitive;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.eclipse.lsp4j.ClientCapabilities;
Expand All @@ -50,13 +52,15 @@ public class BaseWorkspaceService implements WorkspaceService, LanguageClientAwa
public static final String RASCAL_META_COMMAND = "rascal-meta-command";
public static final String RASCAL_COMMAND = "rascal-command";

private final ExecutorService ownExecuter;

private final IBaseTextDocumentService documentService;
private final CopyOnWriteArrayList<WorkspaceFolder> workspaceFolders = new CopyOnWriteArrayList<>();


BaseWorkspaceService(IBaseTextDocumentService documentService) {
protected BaseWorkspaceService(ExecutorService exec, IBaseTextDocumentService documentService) {
this.documentService = documentService;
documentService.pair(this);
this.ownExecuter = exec;
}


Expand Down Expand Up @@ -120,6 +124,9 @@ public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
}


protected final ExecutorService getExecuter() {
return ownExecuter;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
*/
package org.rascalmpl.vscode.lsp;

import java.util.Set;
import java.util.concurrent.CompletableFuture;

import org.eclipse.lsp4j.RenameFilesParams;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter;
import org.rascalmpl.vscode.lsp.util.locations.LineColumnOffsetMap;

import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;

Expand All @@ -45,4 +49,5 @@ public interface IBaseTextDocumentService extends TextDocumentService {
CompletableFuture<IValue> executeCommand(String languageName, String command);
LineColumnOffsetMap getColumnMap(ISourceLocation file);

default void didRenameFiles(RenameFilesParams params, Set<ISourceLocation> workspaceFolders) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
*/
package org.rascalmpl.vscode.lsp.parametric;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.rascalmpl.vscode.lsp.BaseLanguageServer;
import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter;

import com.google.gson.GsonBuilder;

public class ParametricLanguageServer extends BaseLanguageServer {
Expand All @@ -43,9 +43,10 @@ public static void main(String[] args) {
dedicatedLanguage = null;
}

startLanguageServer(() -> {
ExecutorService threadPool = Executors.newCachedThreadPool();
return new ParametricTextDocumentService(threadPool, dedicatedLanguage);
}, 9999);
startLanguageServer(Executors.newCachedThreadPool()
, threadPool -> new ParametricTextDocumentService(threadPool, dedicatedLanguage)
, ParametricWorkspaceService::new
, 9999
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public LineColumnOffsetMap getColumnMap(ISourceLocation file) {
return columns.get(file);
}

private String getContents(ISourceLocation file) {
public String getContents(ISourceLocation file) {
file = file.top();
TextDocumentState ideState = files.get(file);
if (ideState != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2023, NWO-I CWI and Swat.engineering
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.rascalmpl.vscode.lsp.parametric;

import java.util.concurrent.ExecutorService;

import org.rascalmpl.vscode.lsp.BaseWorkspaceService;
import org.rascalmpl.vscode.lsp.IBaseTextDocumentService;

public class ParametricWorkspaceService extends BaseWorkspaceService {
ParametricWorkspaceService(ExecutorService exec, IBaseTextDocumentService docService) {
super(exec, docService);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
*/
package org.rascalmpl.vscode.lsp.rascal;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.logging.log4j.LogManager;
Expand All @@ -36,10 +35,7 @@
public class RascalLanguageServer extends BaseLanguageServer {
public static void main(String[] args) {
try {
startLanguageServer(() -> {
ExecutorService threadPool = Executors.newCachedThreadPool();
return new RascalTextDocumentService(threadPool);
}, 8888);
startLanguageServer(Executors.newCachedThreadPool(), RascalTextDocumentService::new, RascalWorkspaceService::new, 8888);
}
catch (Throwable e) {
final Logger logger = LogManager.getLogger(RascalLanguageServer.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import java.io.IOException;
import java.io.StringReader;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -43,29 +44,30 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.FileRename;
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
import org.rascalmpl.exceptions.Throw;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.interpreter.env.ModuleEnvironment;
import org.rascalmpl.library.util.PathConfig;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.functions.IFunction;
import org.rascalmpl.values.parsetrees.ITree;
import org.rascalmpl.values.parsetrees.TreeAdapter;
import org.rascalmpl.vscode.lsp.BaseWorkspaceService;
import org.rascalmpl.vscode.lsp.IBaseLanguageClient;
import org.rascalmpl.vscode.lsp.RascalLSPMonitor;
import org.rascalmpl.vscode.lsp.TextDocumentState;
import org.rascalmpl.vscode.lsp.util.EvaluatorUtil;
import org.rascalmpl.vscode.lsp.util.RascalServices;
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
import org.rascalmpl.vscode.lsp.util.locations.ColumnMaps;
import org.rascalmpl.vscode.lsp.util.locations.Locations;

import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IList;
Expand Down Expand Up @@ -205,11 +207,7 @@ public InterruptibleFuture<IList> getDocumentSymbols(IConstructor module) {
}


public InterruptibleFuture<ITuple> getRename(ITree module, Position cursor, Set<ISourceLocation> workspaceFolders, Function<ISourceLocation, PathConfig> getPathConfig, String newName, ColumnMaps columns) {
var moduleLocation = TreeAdapter.getLocation(module);
Position pos = Locations.toRascalPosition(moduleLocation, cursor, columns);
var cursorTree = TreeAdapter.locateLexical(module, pos.getLine(), pos.getCharacter());

public InterruptibleFuture<ITuple> getRename(ITree cursorTree, Set<ISourceLocation> workspaceFolders, Function<ISourceLocation, PathConfig> getPathConfig, String newName) {
return runEvaluator("Rascal rename", semanticEvaluator, eval -> {
try {
IFunction rascalGetPathConfig = eval.getFunctionValueFactory().function(getPathConfigType, (t, u) -> addResources(getPathConfig.apply((ISourceLocation) t[0])));
Expand All @@ -235,6 +233,36 @@ public InterruptibleFuture<ITuple> getRename(ITree module, Position cursor, Set<
}, VF.tuple(VF.list(), VF.map()), exec, false, client);
}

private ISourceLocation sourceLocationFromUri(String uri) {
try {
return URIUtil.createFromURI(uri);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

public CompletableFuture<ITuple> getModuleRenames(List<FileRename> fileRenames, Set<ISourceLocation> workspaceFolders, Function<ISourceLocation, PathConfig> getPathConfig, Map<ISourceLocation, TextDocumentState> documents) {
var emptyResult = VF.tuple(VF.list(), VF.map());
if (fileRenames.isEmpty()) {
return CompletableFuture.completedFuture(emptyResult);
}

return CompletableFuture.supplyAsync(() -> fileRenames.stream()
.map(r -> VF.tuple(sourceLocationFromUri(r.getOldUri()), sourceLocationFromUri(r.getNewUri())))
.collect(VF.listWriter())
, exec)
.thenCompose(renames -> {
return runEvaluator("Rascal module rename", semanticEvaluator, eval -> {
IFunction rascalGetPathConfig = eval.getFunctionValueFactory().function(getPathConfigType, (t, u) -> addResources(getPathConfig.apply((ISourceLocation) t[0])));
try {
return (ITuple) eval.call("rascalRenameModule", renames, VF.set(workspaceFolders.toArray(ISourceLocation[]::new)), rascalGetPathConfig);
} catch (Throw e) {
throw new RuntimeException(e.getMessage());
}
}, emptyResult, exec, false, client).get();
});
}


public CompletableFuture<ITree> parseSourceFile(ISourceLocation loc, String input) {
return CompletableFuture.supplyAsync(() -> RascalServices.parseRascalModule(loc, input.toCharArray()), exec);
Expand Down
Loading

0 comments on commit 257f075

Please sign in to comment.