Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ede3d33
Added a type checker wrapper function to check complete Rascal projects
rodinaarssen Jul 9, 2026
7b5f9ff
Merge remote-tracking branch 'origin/main' into check-full-project
rodinaarssen Jul 9, 2026
baad8ee
Added rascal-lsp wiring for full project type checking
rodinaarssen Jul 9, 2026
781c5f3
Added commands to the Explorer view context menu to trigger a full pr…
rodinaarssen Jul 9, 2026
a29e4c2
Not using a function a file that no longer exists
rodinaarssen Jul 9, 2026
52fac1a
Fixed small regression issues
rodinaarssen Jul 10, 2026
744673d
Removed commented code
rodinaarssen Jul 10, 2026
f72c449
Fixed total amount of work
rodinaarssen Jul 10, 2026
f20fd4b
Added nullable annotation
rodinaarssen Jul 10, 2026
31759a8
Aligned compile/check function names
rodinaarssen Jul 10, 2026
5dce8bc
Removed unnecessary function argument
rodinaarssen Jul 10, 2026
fcf47b3
Removed default implementation for checkProject
rodinaarssen Jul 10, 2026
f779afe
ParametricTextDocumentService now throws an error on checkProject
rodinaarssen Jul 10, 2026
61d2333
Fixed type errors
rodinaarssen Jul 10, 2026
6b796e0
Removed information dialog
rodinaarssen Jul 10, 2026
4ecab5f
Unused imports
rodinaarssen Jul 10, 2026
bca5a88
Fixed more type errors
rodinaarssen Jul 14, 2026
c21b66e
Added UI test for project checking
rodinaarssen Jul 14, 2026
ecd3282
Merge remote-tracking branch 'origin/main' into check-full-project
rodinaarssen Jul 14, 2026
5392ce9
Fixed another type error
rodinaarssen Jul 14, 2026
42176ba
Fixed line number in UI test
rodinaarssen Jul 14, 2026
ed1acaf
Fixed test configuration to run all tests instead of only a single one
rodinaarssen Jul 14, 2026
2464118
Fixed expression
rodinaarssen Jul 14, 2026
1131a73
Trying to fix UI test
rodinaarssen Jul 15, 2026
6d70c23
Skip test on macOS
rodinaarssen Jul 15, 2026
10b54f1
Propagating InterruptibleFuture
rodinaarssen Jul 16, 2026
4d3477d
Changed lists into sets of messages
rodinaarssen Jul 16, 2026
536f6ad
Changed sets into lists of messages
rodinaarssen Jul 16, 2026
0ec8a33
Fixed type error
rodinaarssen Jul 16, 2026
fb5e1d0
Fixed type error
rodinaarssen Jul 16, 2026
d93c20b
Perform more filtering on type checker messages in the IDE
rodinaarssen Jul 16, 2026
975ca16
Changed set to list
rodinaarssen Jul 16, 2026
d0061ba
Changed final check in test
rodinaarssen Jul 17, 2026
ae01e70
Only run a single test in CI, temporarily
rodinaarssen Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.rascalmpl.util.NamedThreadPool;
import org.rascalmpl.vscode.lsp.log.LogRedirectConfiguration;
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
import org.rascalmpl.vscode.lsp.rascal.jsonrpc.CheckProjectRequest;
import org.rascalmpl.vscode.lsp.terminal.RemoteIDEServicesThread;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.PathConfigParameter;
import org.rascalmpl.vscode.lsp.util.Sets;
Expand Down Expand Up @@ -287,6 +288,11 @@ public CompletableFuture<Void> sendUnregisterLanguage(LanguageParameter lang) {
return CompletableFutureUtils.completedFuture(null, executor);
}

@Override
public CompletableFuture<Void> checkProject(CheckProjectRequest req) {
return CompletableFuture.runAsync(() -> lspDocumentService.checkProject(req), executor);
}

@Override
public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
logger.info("LSP connection started (connected to {} version {})", params.getClientInfo().getName(), params.getClientInfo().getVersion());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.rascalmpl.uri.remote.jsonrpc.ISourceLocationRequest;
import org.rascalmpl.uri.remote.jsonrpc.SourceLocationResponse;
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
import org.rascalmpl.vscode.lsp.rascal.jsonrpc.CheckProjectRequest;
import org.rascalmpl.vscode.lsp.uri.jsonrpc.messages.PathConfigParameter;

@JsonSegment("rascal")
Expand Down Expand Up @@ -64,10 +65,14 @@ default CompletableFuture<Two<String, URI[]>[]> supplyPathConfig(PathConfigParam
@JsonNotification
void setMinimumLogLevel(String level);


@JsonRequest("vfs/schemes")
CompletableFuture<String[]> fileSystemSchemes();

@JsonRequest("vfs/logical/resolve")
CompletableFuture<SourceLocationResponse> resolve(ISourceLocationRequest req);

@JsonRequest
default CompletableFuture<Void> checkProject(CheckProjectRequest req) {
throw new UnsupportedOperationException();
}
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.eclipse.lsp4j.ClientCapabilities;
import org.eclipse.lsp4j.CreateFilesParams;
import org.eclipse.lsp4j.DeleteFilesParams;
Expand All @@ -39,6 +40,7 @@
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
import org.rascalmpl.vscode.lsp.rascal.jsonrpc.CheckProjectRequest;

import io.usethesource.vallang.IValue;

Expand All @@ -52,6 +54,7 @@ public interface IBaseTextDocumentService extends TextDocumentService, ITextDocu
void initialized();
void registerLanguage(LanguageParameter lang);
void unregisterLanguage(LanguageParameter lang);
CompletableFuture<Void> checkProject(CheckProjectRequest req);
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated

CompletableFuture<IValue> executeCommand(String languageName, String command);
Collection<String> extensions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.uri.remote.jsonrpc.ISourceLocationRequest;

Check warning on line 125 in rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.rascalmpl.uri.remote.jsonrpc.ISourceLocationRequest'.

See more on https://sonarcloud.io/project/issues?id=usethesource_rascal-language-servers&issues=AZ9IO7j4eurDT4Cv55G6&open=AZ9IO7j4eurDT4Cv55G6&pullRequest=1153
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.parsetrees.ITree;
import org.rascalmpl.values.parsetrees.TreeAdapter;
Expand All @@ -148,6 +149,7 @@
import org.rascalmpl.vscode.lsp.rascal.conversion.Message;
import org.rascalmpl.vscode.lsp.rascal.conversion.SelectionRanges;
import org.rascalmpl.vscode.lsp.rascal.conversion.SemanticTokenizer;
import org.rascalmpl.vscode.lsp.rascal.jsonrpc.CheckProjectRequest;
import org.rascalmpl.vscode.lsp.uri.LSPOpenFileRedirector;
import org.rascalmpl.vscode.lsp.util.Maps;
import org.rascalmpl.vscode.lsp.util.Versioned;
Expand Down Expand Up @@ -1051,4 +1053,9 @@
contributions.values().forEach(plex ->
plex.cancelProgress(progressId));
}

public CompletableFuture<Void> checkProject(CheckProjectRequest req) {
// Do nothing
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated
return CompletableFuture.completedFuture(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Check warning on line 48 in rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalLanguageServices.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'java.util.stream.Stream'.

See more on https://sonarcloud.io/project/issues?id=usethesource_rascal-language-servers&issues=AZ9IO7nVeurDT4Cv55G7&open=AZ9IO7nVeurDT4Cv55G7&pullRequest=1153

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.PolyNull;

Check warning on line 53 in rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalLanguageServices.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.checkerframework.checker.nullness.qual.PolyNull'.

See more on https://sonarcloud.io/project/issues?id=usethesource_rascal-language-servers&issues=AZ9IO7nVeurDT4Cv55G8&open=AZ9IO7nVeurDT4Cv55G8&pullRequest=1153
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
Expand All @@ -70,12 +73,14 @@
import org.rascalmpl.vscode.lsp.BaseWorkspaceService;
import org.rascalmpl.vscode.lsp.IBaseLanguageClient;
import org.rascalmpl.vscode.lsp.RascalLSPMonitor;
import org.rascalmpl.vscode.lsp.rascal.conversion.Diagnostics;

Check warning on line 76 in rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/rascal/RascalLanguageServices.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'org.rascalmpl.vscode.lsp.rascal.conversion.Diagnostics'.

See more on https://sonarcloud.io/project/issues?id=usethesource_rascal-language-servers&issues=AZ9IO7nVeurDT4Cv55G9&open=AZ9IO7nVeurDT4Cv55G9&pullRequest=1153
import org.rascalmpl.vscode.lsp.util.EvaluatorUtil;
import org.rascalmpl.vscode.lsp.util.EvaluatorUtil.LSPContext;
import org.rascalmpl.vscode.lsp.util.RascalServices;
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
import org.rascalmpl.vscode.lsp.util.locations.Locations;

import io.usethesource.vallang.IBool;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IList;
import io.usethesource.vallang.IMap;
Expand Down Expand Up @@ -265,18 +270,30 @@
});
}

private ISet getWorkspaceFolders(BaseWorkspaceService workspaceService) {
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated
return workspaceService.workspaceFolders().stream().map(f -> Locations.toLoc(f.getUri())).collect(VF.setWriter());
}

public InterruptibleFuture<Map<ISourceLocation, ISet>> compileFile(ISourceLocation file, PathConfig pcfg,
Executor exec) {
logger.debug("Running Rascal check for: {} with {}", file, pcfg);
var workspaceFolders = workspaceService.workspaceFolders().stream().map(f -> Locations.toLoc(f.getUri())).collect(VF.setWriter());

var shortModuleName = URIUtil.getLocationName(URIUtil.removeExtension(file));
return runEvaluator("Rascal check (" + shortModuleName +")", compilerEvaluator,
e -> translateCheckResults((IMap) e.call("checkFile", file, workspaceFolders, makeParseTreeGetter(e), makePathConfigGetter(e))),
e -> translateCheckResults((IMap) e.call("checkFile", file, getWorkspaceFolders(workspaceService), makeParseTreeGetter(e), makePathConfigGetter(e))),
Map.of(file, VF.set()), exec, false, client);
}

public void checkProject(ISourceLocation projectRoot, IBool clean, Executor exec) {
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated
logger.debug("Check Rascal project: {}", projectRoot);

var shortName = URIUtil.getLocationName(projectRoot);
runEvaluator("Rascal check project (" + shortName +")", compilerEvaluator,
Comment thread
rodinaarssen marked this conversation as resolved.
Outdated
e -> translateCheckResults((IMap) e.call("checkProject", projectRoot, clean, getWorkspaceFolders(workspaceService), makeParseTreeGetter(e), makePathConfigGetter(e))),
Map.of(projectRoot, VF.set()), exec, false, client).thenAccept(r ->
rascalTextDocumentService.getFileFacts().reportTypeCheckerMessages(r));
}

private @Nullable ISourceLocation getFileLoc(ITree moduleTree) {
try {
if (TreeAdapter.isTop(moduleTree)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -55,7 +56,6 @@
import org.eclipse.lsp4j.CreateFilesParams;
import org.eclipse.lsp4j.DefinitionParams;
import org.eclipse.lsp4j.DeleteFilesParams;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
Expand Down Expand Up @@ -119,20 +119,21 @@
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;
import org.rascalmpl.vscode.lsp.rascal.RascalLanguageServices.CodeLensSuggestion;
import org.rascalmpl.vscode.lsp.rascal.conversion.CodeActions;
import org.rascalmpl.vscode.lsp.rascal.conversion.Diagnostics;
import org.rascalmpl.vscode.lsp.rascal.conversion.DocumentChanges;
import org.rascalmpl.vscode.lsp.rascal.conversion.DocumentSymbols;
import org.rascalmpl.vscode.lsp.rascal.conversion.FoldingRanges;
import org.rascalmpl.vscode.lsp.rascal.conversion.Message;
import org.rascalmpl.vscode.lsp.rascal.conversion.SelectionRanges;
import org.rascalmpl.vscode.lsp.rascal.conversion.SemanticTokenizer;
import org.rascalmpl.vscode.lsp.rascal.jsonrpc.CheckProjectRequest;
import org.rascalmpl.vscode.lsp.rascal.model.FileFacts;
import org.rascalmpl.vscode.lsp.rascal.model.SummaryBridge;
import org.rascalmpl.vscode.lsp.uri.LSPOpenFileRedirector;
import org.rascalmpl.vscode.lsp.util.Versioned;
import org.rascalmpl.vscode.lsp.util.concurrent.CompletableFutureUtils;
import org.rascalmpl.vscode.lsp.util.locations.Locations;
import org.rascalmpl.vscode.lsp.util.locations.impl.TreeSearch;

import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IList;
import io.usethesource.vallang.ISet;
Expand All @@ -158,7 +159,6 @@ public RascalTextDocumentService(ExecutorService exec) {
LSPOpenFileRedirector.getInstance().registerTextDocumentService(this);
}


private LanguageClient availableClient() {
if (client == null) {
throw new IllegalStateException("Client has not been connected yet");
Expand Down Expand Up @@ -259,7 +259,6 @@ private void triggerAnalyzer(TextDocumentState state, Duration delay) {
}
}


@Override
public void didClose(DidCloseTextDocumentParams params) {
logger.debug("Close: {}", params.getTextDocument());
Expand Down Expand Up @@ -658,4 +657,12 @@ public FileFacts getFileFacts() {
public void cancelProgress(String progressId) {
exec.submit(() -> availableRascalServices().cancelProgress(progressId));
}

@Override
public CompletableFuture<Void> checkProject(CheckProjectRequest req) {
return CompletableFuture.supplyAsync(() -> {
availableRascalServices().checkProject(req.getLocation(), req.getClean(), exec);
return null;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018-2025, 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.rascal.jsonrpc;

import java.util.Objects;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.rascalmpl.values.ValueFactoryFactory;

import io.usethesource.vallang.IBool;
import io.usethesource.vallang.ISourceLocation;

public class CheckProjectRequest {
private final ISourceLocation loc;
private final boolean clean;

public CheckProjectRequest(ISourceLocation loc, boolean clean) {
this.loc = loc;
this.clean = clean;
}

public ISourceLocation getLocation() {
return loc;
}

public IBool getClean() {
return ValueFactoryFactory.getValueFactory().bool(clean);
}

@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof CheckProjectRequest) {
var other = (CheckProjectRequest) obj;
return Objects.equals(loc, other.loc)
&& clean == other.clean;
}
return false;
}

@Override
public int hashCode() {
return Objects.hash(loc, clean);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.rascalmpl.vscode.lsp.util.locations.Locations;

import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISet;
import io.usethesource.vallang.ISourceLocation;

public class FileFacts implements DiagnosticsReporter {
Expand Down Expand Up @@ -113,6 +114,10 @@ public void reportParseErrors(ISourceLocation file, Versioned<List<Diagnostic>>
getFile(file).reportParseErrors(msgs);
}

public void reportTypeCheckerMessages(Map<ISourceLocation, ISet> messages) {
Diagnostics.translateMessages(messages, Set.of("rsc"), cm).forEach((f, msgs) -> getFile(f).reportTypeCheckerMessages(msgs));
}

private FileFact getFile(ISourceLocation l) {
l = l.top();
ISourceLocation resolved = Locations.toClientLocation(l);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;

import org.checkerframework.checker.nullness.qual.PolyNull;
import org.rascalmpl.vscode.lsp.util.concurrent.CompletableFutureUtils;

Expand Down
Loading
Loading