Skip to content

Commit a97730a

Browse files
committed
Add extension setting for max completion items
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
1 parent 58908d6 commit a97730a

File tree

7 files changed

+117
-69
lines changed

7 files changed

+117
-69
lines changed

modules/language-server/src/main/java/nextflow/lsp/NextflowLanguageServer.java

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525
import java.util.Optional;
2626
import java.util.concurrent.CompletableFuture;
2727

28-
import com.google.gson.JsonElement;
29-
import com.google.gson.JsonObject;
30-
import com.google.gson.JsonPrimitive;
3128
import nextflow.lsp.file.PathUtils;
29+
import nextflow.lsp.util.JsonUtils;
3230
import nextflow.lsp.util.Logger;
3331
import nextflow.lsp.services.LanguageServerConfiguration;
3432
import nextflow.lsp.services.LanguageService;
@@ -318,7 +316,7 @@ public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completio
318316
var service = getLanguageService(uri);
319317
if( service == null )
320318
return Either.forLeft(Collections.emptyList());
321-
return service.completion(params, configuration.extendedCompletion());
319+
return service.completion(params, configuration.maxCompletionItems(), configuration.extendedCompletion());
322320
});
323321
}
324322

@@ -442,17 +440,18 @@ public void didChangeConfiguration(DidChangeConfigurationParams params) {
442440

443441
var shouldInitialize = false;
444442

445-
var debug = getJsonBoolean(params.getSettings(), "nextflow.debug");
443+
var debug = JsonUtils.getBoolean(params.getSettings(), "nextflow.debug");
446444
if( debug != null )
447445
Logger.setDebugEnabled(debug);
448446

449-
var excludePatterns = getJsonStringArray(params.getSettings(), "nextflow.files.exclude");
447+
var excludePatterns = JsonUtils.getStringArray(params.getSettings(), "nextflow.files.exclude");
450448
if( !DefaultGroovyMethods.equals(configuration.excludePatterns(), excludePatterns) )
451449
shouldInitialize = true;
452-
var extendedCompletion = getJsonBoolean(params.getSettings(), "nextflow.completion.extended");
453-
var harshilAlignment = getJsonBoolean(params.getSettings(), "nextflow.formatting.harshilAlignment");
454-
var maheshForm = getJsonBoolean(params.getSettings(), "nextflow.formatting.maheshForm");
455-
var paranoidWarnings = getJsonBoolean(params.getSettings(), "nextflow.paranoidWarnings");
450+
var extendedCompletion = JsonUtils.getBoolean(params.getSettings(), "nextflow.completion.extended");
451+
var harshilAlignment = JsonUtils.getBoolean(params.getSettings(), "nextflow.formatting.harshilAlignment");
452+
var maheshForm = JsonUtils.getBoolean(params.getSettings(), "nextflow.formatting.maheshForm");
453+
var maxCompletionItems = JsonUtils.getInteger(params.getSettings(), "nextflow.completion.maxItems");
454+
var paranoidWarnings = JsonUtils.getBoolean(params.getSettings(), "nextflow.paranoidWarnings");
456455
if( paranoidWarnings != null && configuration.paranoidWarnings() != paranoidWarnings )
457456
shouldInitialize = true;
458457

@@ -461,6 +460,7 @@ public void didChangeConfiguration(DidChangeConfigurationParams params) {
461460
extendedCompletion != null ? extendedCompletion : configuration.extendedCompletion(),
462461
harshilAlignment != null ? harshilAlignment : configuration.harshilAlignment(),
463462
maheshForm != null ? maheshForm : configuration.maheshForm(),
463+
maxCompletionItems != null ? maxCompletionItems : configuration.maxCompletionItems(),
464464
paranoidWarnings != null ? paranoidWarnings : configuration.paranoidWarnings()
465465
);
466466

@@ -558,7 +558,7 @@ public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
558558
var arguments = params.getArguments();
559559
if( !"nextflow.server.previewDag".equals(command) || arguments.size() != 2 )
560560
return null;
561-
var uri = getJsonString(arguments.get(0));
561+
var uri = JsonUtils.getString(arguments.get(0));
562562
log.debug(String.format("textDocument/executeCommand %s %s", command, arguments.toString()));
563563
var service = getLanguageService(uri);
564564
if( service == null )
@@ -567,10 +567,6 @@ public CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
567567
});
568568
}
569569

570-
private String getJsonString(Object json) {
571-
return json instanceof JsonPrimitive jp ? jp.getAsString() : null;
572-
}
573-
574570
@Override
575571
public CompletableFuture<Either<List<? extends SymbolInformation>, List<? extends WorkspaceSymbol>>> symbol(WorkspaceSymbolParams params) {
576572
return CompletableFutures.computeAsync((cancelChecker) -> {
@@ -633,49 +629,4 @@ private LanguageService getLanguageService0(String uri, Map<String, LanguageServ
633629
return service;
634630
}
635631

636-
private List<String> getJsonStringArray(Object json, String path) {
637-
var value = getJsonElement(json, path);
638-
if( value == null || !value.isJsonArray() )
639-
return null;
640-
var result = new ArrayList<String>();
641-
for( var el : value.getAsJsonArray() ) {
642-
try {
643-
result.add(el.getAsJsonPrimitive().getAsString());
644-
}
645-
catch( AssertionError e ) {
646-
continue;
647-
}
648-
}
649-
return result;
650-
}
651-
652-
private Boolean getJsonBoolean(Object json, String path) {
653-
var value = getJsonElement(json, path);
654-
if( value == null || !value.isJsonPrimitive() )
655-
return null;
656-
var result = value.getAsJsonPrimitive();
657-
if( !result.isBoolean() )
658-
return null;
659-
return result.getAsBoolean();
660-
}
661-
662-
private JsonElement getJsonElement(Object json, String path) {
663-
if( !(json instanceof JsonObject) )
664-
return null;
665-
666-
JsonObject object = (JsonObject) json;
667-
var names = path.split("\\.");
668-
for( int i = 0; i < names.length - 1; i++ ) {
669-
var scope = names[i];
670-
if( !object.has(scope) || !object.get(scope).isJsonObject() )
671-
return null;
672-
object = object.get(scope).getAsJsonObject();
673-
}
674-
675-
var property = names[names.length - 1];
676-
if( !object.has(property) )
677-
return null;
678-
return object.get(property);
679-
}
680-
681632
}

modules/language-server/src/main/java/nextflow/lsp/services/LanguageServerConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public record LanguageServerConfiguration(
2323
boolean extendedCompletion,
2424
boolean harshilAlignment,
2525
boolean maheshForm,
26+
int maxCompletionItems,
2627
boolean paranoidWarnings
2728
) {
2829

@@ -32,6 +33,7 @@ public static LanguageServerConfiguration defaults() {
3233
false,
3334
false,
3435
false,
36+
100,
3537
false
3638
);
3739
}

modules/language-server/src/main/java/nextflow/lsp/services/LanguageService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public LanguageService() {
111111
protected abstract ASTNodeCache getAstCache();
112112
protected CallHierarchyProvider getCallHierarchyProvider() { return null; }
113113
protected CodeLensProvider getCodeLensProvider() { return null; }
114-
protected CompletionProvider getCompletionProvider(boolean extendedCompletion) { return null; }
114+
protected CompletionProvider getCompletionProvider(int maxCompletionItems, boolean extendedCompletion) { return null; }
115115
protected DefinitionProvider getDefinitionProvider() { return null; }
116116
protected FormattingProvider getFormattingProvider() { return null; }
117117
protected HoverProvider getHoverProvider() { return null; }
@@ -226,8 +226,8 @@ public List<CodeLens> codeLens(CodeLensParams params) {
226226
return provider.codeLens(params.getTextDocument());
227227
}
228228

229-
public Either<List<CompletionItem>, CompletionList> completion(CompletionParams params, boolean extendedCompletion) {
230-
var provider = getCompletionProvider(extendedCompletion);
229+
public Either<List<CompletionItem>, CompletionList> completion(CompletionParams params, int maxCompletionItems, boolean extendedCompletion) {
230+
var provider = getCompletionProvider(maxCompletionItems, extendedCompletion);
231231
if( provider == null )
232232
return Either.forLeft(Collections.emptyList());
233233

modules/language-server/src/main/java/nextflow/lsp/services/config/ConfigService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ protected ASTNodeCache getAstCache() {
4343
}
4444

4545
@Override
46-
protected CompletionProvider getCompletionProvider(boolean extendedCompletion) {
46+
protected CompletionProvider getCompletionProvider(int maxCompletionItems, boolean extendedCompletion) {
4747
return new ConfigCompletionProvider(astCache);
4848
}
4949

modules/language-server/src/main/java/nextflow/lsp/services/script/ScriptCompletionProvider.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@ public class ScriptCompletionProvider implements CompletionProvider {
8989

9090
private ScriptAstCache ast;
9191
private boolean extendedCompletion;
92+
private int maxCompletionItems;
9293
private URI uri;
93-
private int maxItemCount = 100;
9494
private boolean isIncomplete = false;
9595

96-
public ScriptCompletionProvider(ScriptAstCache ast, boolean extendedCompletion) {
96+
public ScriptCompletionProvider(ScriptAstCache ast, int maxCompletionItems, boolean extendedCompletion) {
9797
this.ast = ast;
9898
this.extendedCompletion = extendedCompletion;
99+
this.maxCompletionItems = maxCompletionItems;
99100
}
100101

101102
@Override
@@ -478,7 +479,7 @@ private static CompletionItemKind astNodeToCompletionItemKind(ASTNode node) {
478479
}
479480

480481
private boolean addItem(CompletionItem item, List<CompletionItem> items) {
481-
if( items.size() >= maxItemCount ) {
482+
if( items.size() >= maxCompletionItems ) {
482483
isIncomplete = true;
483484
return false;
484485
}

modules/language-server/src/main/java/nextflow/lsp/services/script/ScriptService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ protected CodeLensProvider getCodeLensProvider() {
7171
}
7272

7373
@Override
74-
protected CompletionProvider getCompletionProvider(boolean extendedCompletion) {
75-
return new ScriptCompletionProvider(astCache, extendedCompletion);
74+
protected CompletionProvider getCompletionProvider(int maxCompletionItems, boolean extendedCompletion) {
75+
return new ScriptCompletionProvider(astCache, maxCompletionItems, extendedCompletion);
7676
}
7777

7878
@Override
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2024-2025, Seqera Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package nextflow.lsp.util;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
import com.google.gson.JsonElement;
22+
import com.google.gson.JsonObject;
23+
import com.google.gson.JsonPrimitive;
24+
25+
/**
26+
*
27+
* @author Ben Sherman <bentshermann@gmail.com>
28+
*/
29+
public class JsonUtils {
30+
31+
public static List<String> getStringArray(Object json, String path) {
32+
var value = getObjectPath(json, path);
33+
if( value == null || !value.isJsonArray() )
34+
return null;
35+
var result = new ArrayList<String>();
36+
for( var el : value.getAsJsonArray() ) {
37+
try {
38+
result.add(el.getAsString());
39+
}
40+
catch( ClassCastException e ) {
41+
continue;
42+
}
43+
}
44+
return result;
45+
}
46+
47+
public static Boolean getBoolean(Object json, String path) {
48+
var value = getObjectPath(json, path);
49+
if( value == null )
50+
return null;
51+
try {
52+
return value.getAsBoolean();
53+
}
54+
catch( ClassCastException e ) {
55+
return null;
56+
}
57+
}
58+
59+
public static Integer getInteger(Object json, String path) {
60+
var value = getObjectPath(json, path);
61+
if( value == null )
62+
return null;
63+
try {
64+
return value.getAsInt();
65+
}
66+
catch( ClassCastException e ) {
67+
return null;
68+
}
69+
}
70+
71+
public static String getString(Object json) {
72+
return json instanceof JsonPrimitive jp ? jp.getAsString() : null;
73+
}
74+
75+
private static JsonElement getObjectPath(Object json, String path) {
76+
if( !(json instanceof JsonObject) )
77+
return null;
78+
79+
JsonObject object = (JsonObject) json;
80+
var names = path.split("\\.");
81+
for( int i = 0; i < names.length - 1; i++ ) {
82+
var scope = names[i];
83+
if( !object.has(scope) || !object.get(scope).isJsonObject() )
84+
return null;
85+
object = object.get(scope).getAsJsonObject();
86+
}
87+
88+
var property = names[names.length - 1];
89+
if( !object.has(property) )
90+
return null;
91+
return object.get(property);
92+
}
93+
94+
}

0 commit comments

Comments
 (0)