diff --git a/src/main/java/nextflow/lsp/ast/ASTNodeCache.java b/src/main/java/nextflow/lsp/ast/ASTNodeCache.java index bfd44341..d0652a43 100644 --- a/src/main/java/nextflow/lsp/ast/ASTNodeCache.java +++ b/src/main/java/nextflow/lsp/ast/ASTNodeCache.java @@ -25,6 +25,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import nextflow.lsp.compiler.LanguageServerCompiler; @@ -86,8 +88,9 @@ public void clear() { * * @param uris * @param fileCache + * @param progress optional callback to report progress as (current, total) */ - public Set update(Set uris, FileCache fileCache) { + public Set update(Set uris, FileCache fileCache, BiConsumer progress) { // invalidate cache for each source file for( var uri : uris ) { var nodes = nodesByURI.remove(uri); @@ -101,12 +104,17 @@ public Set update(Set uris, FileCache fileCache) { } // parse source files + var counter = new AtomicInteger(0); + var total = uris.size(); var sources = uris.parallelStream() .map(uri -> compiler.createSourceUnit(uri, fileCache)) .filter(sourceUnit -> sourceUnit != null) .map(sourceUnit -> { compiler.addSource(sourceUnit); compiler.compile(sourceUnit); + if( progress != null ) { + progress.accept(counter.incrementAndGet(), total); + } return sourceUnit; }) .sequential() diff --git a/src/main/java/nextflow/lsp/services/LanguageService.java b/src/main/java/nextflow/lsp/services/LanguageService.java index c21250e7..d2fc7dc2 100644 --- a/src/main/java/nextflow/lsp/services/LanguageService.java +++ b/src/main/java/nextflow/lsp/services/LanguageService.java @@ -38,6 +38,7 @@ import nextflow.lsp.util.DebouncingExecutor; import nextflow.lsp.util.LanguageServerUtils; import nextflow.lsp.util.Logger; +import nextflow.lsp.util.ProgressNotification; import nextflow.lsp.util.Positions; import nextflow.script.control.ParanoidWarning; import nextflow.script.control.RelatedInformationAware; @@ -363,14 +364,34 @@ private void update0() { log.debug(builder.toString()); } + // Create progress notification for multi-file updates + ProgressNotification progress = null; + if( uris.size() > 1 && client != null ) { + var token = "indexing-" + (rootUri != null ? rootUri.hashCode() : "default"); + progress = new ProgressNotification(client, token); + progress.create(); + progress.begin(String.format("Indexing %d files...", uris.size())); + } + try { - var changedUris = astCache.update(uris, fileCache); + final var progressNotification = progress; + var changedUris = astCache.update(uris, fileCache, + progressNotification != null + ? (current, total) -> progressNotification.update( + String.format("Indexing: %d / %d files", current, total), + current * 100 / total) + : null); publishDiagnostics(changedUris); } catch( Throwable e ) { System.err.println(e); e.printStackTrace(); } + finally { + if( progress != null ) { + progress.end(); + } + } } /** diff --git a/src/test/groovy/nextflow/lsp/TestLanguageClient.groovy b/src/test/groovy/nextflow/lsp/TestLanguageClient.groovy index 8383057d..49a736df 100644 --- a/src/test/groovy/nextflow/lsp/TestLanguageClient.groovy +++ b/src/test/groovy/nextflow/lsp/TestLanguageClient.groovy @@ -20,8 +20,10 @@ import java.util.concurrent.CompletableFuture import org.eclipse.lsp4j.MessageActionItem import org.eclipse.lsp4j.MessageParams +import org.eclipse.lsp4j.ProgressParams import org.eclipse.lsp4j.PublishDiagnosticsParams import org.eclipse.lsp4j.ShowMessageRequestParams +import org.eclipse.lsp4j.WorkDoneProgressCreateParams import org.eclipse.lsp4j.services.LanguageClient /** @@ -51,4 +53,14 @@ class TestLanguageClient implements LanguageClient { public void logMessage(MessageParams message) { System.err.println(message.getMessage()) } + + @Override + public CompletableFuture createProgress(WorkDoneProgressCreateParams params) { + return CompletableFuture.completedFuture(null) + } + + @Override + public void notifyProgress(ProgressParams params) { + // No-op for tests + } }