Skip to content

Commit

Permalink
Merge pull request #218 from usethesource/rascal-libraries-navigator
Browse files Browse the repository at this point in the history
Implemented rascal library navigator
  • Loading branch information
DavyLandman authored Nov 9, 2023
2 parents 8eb2439 + 98505ba commit 6564442
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
Expand All @@ -49,6 +51,7 @@
import org.eclipse.lsp4j.SetTraceParams;
import org.eclipse.lsp4j.WorkspaceFolder;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.jsonrpc.messages.Tuple.Two;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.eclipse.lsp4j.services.NotebookDocumentService;
Expand All @@ -65,6 +68,7 @@
import org.rascalmpl.vscode.lsp.uri.ProjectURIResolver;
import org.rascalmpl.vscode.lsp.uri.TargetURIResolver;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.impl.VSCodeVFSClient;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.PathConfigParameter;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.VFSRegister;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
Expand Down Expand Up @@ -196,18 +200,18 @@ private static void startLSP(Launcher<IBaseLanguageClient> server) {
}
private static class ActualLanguageServer implements IBaseLanguageServerExtensions, LanguageClientAware {
static final Logger logger = LogManager.getLogger(ActualLanguageServer.class);
private static final URIResolverRegistry reg = URIResolverRegistry.getInstance();
private final IBaseTextDocumentService lspDocumentService;
private final BaseWorkspaceService lspWorkspaceService;
private final Runnable onExit;
private IBaseLanguageClient client;
private IDEServicesConfiguration ideServicesConfiguration;

private ActualLanguageServer(Runnable onExit, IBaseTextDocumentService lspDocumentService) {
this.onExit = onExit;
this.lspDocumentService = lspDocumentService;
this.lspWorkspaceService = new BaseWorkspaceService(lspDocumentService);
URIResolverRegistry.getInstance().registerLogical(new ProjectURIResolver(this::resolveProjectLocation));
URIResolverRegistry.getInstance().registerLogical(new TargetURIResolver(this::resolveProjectLocation));
reg.registerLogical(new ProjectURIResolver(this::resolveProjectLocation));
reg.registerLogical(new TargetURIResolver(this::resolveProjectLocation));
}

private ISourceLocation resolveProjectLocation(ISourceLocation loc) {
Expand Down Expand Up @@ -246,29 +250,56 @@ private static String[] classLoaderFiles(IList source) {

@Override
public CompletableFuture<String[]> supplyProjectCompilationClasspath(URIParameter projectFolder) {
try {
if (projectFolder.getUri() == null) {
return CompletableFuture.completedFuture(
classLoaderFiles(PathConfig.getDefaultClassloadersList())
);
}
ISourceLocation path = URIUtil.createFromURI(projectFolder.getUri());
if (!URIResolverRegistry.getInstance().isDirectory(path)) {
path = URIUtil.getParentLocation(path);
return CompletableFuture.supplyAsync(() -> {
try {
if (projectFolder.getUri() == null) {
return classLoaderFiles(PathConfig.getDefaultClassloadersList());
}
PathConfig pcfg = findPathConfig(projectFolder.getLocation(), RascalConfigMode.COMPILER);
return classLoaderFiles(pcfg.getClassloaders());
}

ISourceLocation projectDir = ShellEvaluatorFactory.inferProjectRoot(new File(path.getPath()));
if (projectDir == null) {
throw new RuntimeException("Project of file |" + projectFolder.getUri() + "| is missing a `META-INF/RASCAL.MF` file!");
catch (IOException | URISyntaxException e) {
logger.catching(e);
throw new CompletionException(e);
}
PathConfig pcfg = PathConfig.fromSourceProjectRascalManifest(projectDir, RascalConfigMode.COMPILER);
});
}

return CompletableFuture.completedFuture(classLoaderFiles(pcfg.getClassloaders()));
private static PathConfig findPathConfig(ISourceLocation path, RascalConfigMode mode) throws IOException {
if (!reg.isDirectory(path)) {
path = URIUtil.getParentLocation(path);
}
catch (IOException | URISyntaxException e) {
logger.catching(e);
throw new RuntimeException(e);

ISourceLocation projectDir = ShellEvaluatorFactory.inferProjectRoot(new File(path.getPath()));
if (projectDir == null) {
throw new IOException("Project of file |" + path.toString() + "| is missing a `META-INF/RASCAL.MF` file!");
}
return PathConfig.fromSourceProjectRascalManifest(projectDir, mode);
}

private static URI[] toURIArray(IList src) {
return src.stream()
.map(ISourceLocation.class::cast)
.map(ISourceLocation::getURI)
.toArray(URI[]::new);
}

@Override
public CompletableFuture<Two<String, URI[]>[]> supplyPathConfig(PathConfigParameter projectFolder) {
return CompletableFuture.supplyAsync(() -> {
try {
var pcfg = PathConfig.fromSourceProjectMemberRascalManifest(projectFolder.getLocation(), projectFolder.getMode().mapConfigMode());
Two<String, URI[]>[] result = new Two[4];
result[0] = new Two<>("Sources", toURIArray(pcfg.getSrcs()));
result[1] = new Two<>("Libraries", toURIArray(pcfg.getLibs()));
result[2] = new Two<>("Java Compiler Path", toURIArray(pcfg.getJavaCompilerPath()));
result[3] = new Two<>("Classloaders", toURIArray(pcfg.getClassloaders()));
return result;
} catch (IOException | URISyntaxException e) {
logger.catching(e);
throw new CompletionException(e);
}
});
}

@Override
Expand Down Expand Up @@ -326,10 +357,10 @@ public void setTrace(SetTraceParams params) {

@Override
public void connect(LanguageClient client) {
this.client = (IBaseLanguageClient) client;
this.ideServicesConfiguration = IDEServicesThread.startIDEServices(this.client, lspDocumentService, lspWorkspaceService);
lspDocumentService.connect(this.client);
lspWorkspaceService.connect(this.client);
var actualClient = (IBaseLanguageClient) client;
this.ideServicesConfiguration = IDEServicesThread.startIDEServices(actualClient, lspDocumentService, lspWorkspaceService);
lspDocumentService.connect(actualClient);
lspWorkspaceService.connect(actualClient);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
*/
package org.rascalmpl.vscode.lsp;

import java.net.URI;
import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.jsonrpc.messages.Tuple.Two;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
import org.eclipse.lsp4j.services.LanguageServer;
import org.rascalmpl.vscode.lsp.terminal.ITerminalIDEServer.LanguageParameter;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.PathConfigParameter;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.VFSRegister;

public interface IBaseLanguageServerExtensions extends LanguageServer, IRascalFileSystemServices {
Expand All @@ -53,6 +56,11 @@ default CompletableFuture<String[]> supplyProjectCompilationClasspath(URIParamet
throw new UnsupportedOperationException();
}

@JsonRequest("rascal/supplyPathConfig")
default CompletableFuture<Two<String, URI[]>[]> supplyPathConfig(PathConfigParameter projectFolder) {
throw new UnsupportedOperationException();
}

@JsonNotification("rascal/vfs/register")
void registerVFS(VFSRegister registration);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.uri.jsonrpc.messages;

import org.rascalmpl.library.util.PathConfig.RascalConfigMode;

public enum PathConfigMode {
INTERPRETER(0),
COMPILER(1);

private final int value;

PathConfigMode(int value) {
this.value = value;
}
public int getValue() {
return value;
}

public RascalConfigMode mapConfigMode() {
switch (this) {
case INTERPRETER: return RascalConfigMode.INTERPETER;
case COMPILER: return RascalConfigMode.COMPILER;
default: throw new IllegalArgumentException("Missing case: " + this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.uri.jsonrpc.messages;

import java.net.URISyntaxException;
import org.rascalmpl.uri.URIUtil;
import io.usethesource.vallang.ISourceLocation;

public class PathConfigParameter {
private String uri;
private PathConfigMode mode;


public PathConfigParameter(String uri, PathConfigMode mode) {
this.uri = uri;
this.mode = mode;
}

public String getUri() {
return uri;
}

public ISourceLocation getLocation() throws URISyntaxException {
return URIUtil.createFromURI(uri);
}

public PathConfigMode getMode() {
return mode;
}

}
16 changes: 16 additions & 0 deletions rascal-vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@
"editor.semanticHighlighting.enabled": true
}
},
"views": {
"explorer": [
{
"id": "rascalmpl-configuration-view",
"name": "Rascal Configuration",
"icon": "./assets/images/rascal-logo.svg",
"visibility": "collapsed"
}
]
},
"viewsWelcome": [
{
"view": "rascalmpl-configuration-view",
"contents": "No Rascal Projects found in the workspace"
}
],
"breakpoints": [
{
"language": "rascalmpl"
Expand Down
2 changes: 2 additions & 0 deletions rascal-vscode-extension/src/RascalExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { RascalLanguageServer } from './lsp/RascalLanguageServer';
import { LanguageParameter, ParameterizedLanguageServer } from './lsp/ParameterizedLanguageServer';
import { RascalTerminalLinkProvider } from './RascalTerminalLinkProvider';
import { VSCodeUriResolverServer } from './fs/VSCodeURIResolver';
import { RascalLibraryProvider } from './ux/LibraryNavigator';
import { FileType } from 'vscode';

export class RascalExtension implements vscode.Disposable {
Expand All @@ -53,6 +54,7 @@ export class RascalExtension implements vscode.Disposable {
this.registerImportModule();
checkForJVMUpdate();

vscode.window.registerTreeDataProvider('rascalmpl-configuration-view', new RascalLibraryProvider(this.rascal.rascalClient));
vscode.window.registerTerminalLinkProvider(new RascalTerminalLinkProvider(this.rascal.rascalClient));
}

Expand Down
1 change: 0 additions & 1 deletion rascal-vscode-extension/src/auto-jvm/JavaLookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ const pexec = promisify(cp.exec);

export async function getJavaExecutable(): Promise<string> {
if (lookupCompleted) {
console.log("Returning: " + lookupCompleted);
return lookupCompleted;
}
for (const possibleCandidate of await getJavaCandidates()) {
Expand Down
Loading

0 comments on commit 6564442

Please sign in to comment.