Skip to content

Commit dcea8b7

Browse files
authored
Merge pull request #706 from usethesource/completions/parametric
Parametric completion
2 parents 71c0e9c + 45517b2 commit dcea8b7

File tree

26 files changed

+1592
-28
lines changed

26 files changed

+1592
-28
lines changed

rascal-lsp/src/main/checkerframework/jdk.astub

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,15 @@ public class URI {
4949
public URI(@Nullable String scheme, @Nullable String authority, @Nullable String path, @Nullable String query, @Nullable String fragment) throws URISyntaxException {}
5050
public URI(@Nullable String scheme, @Nullable String userInfo, @Nullable String host, int port, @Nullable String path, @Nullable String query, @Nullable String fragment) throws URISyntaxException {}
5151
}
52+
53+
54+
package java.util;
55+
56+
import org.checkerframework.checker.nullness.qual.*;
57+
58+
public interface Map<K, V> {
59+
// Mirror fixes in https://github.com/typetools/jdk/pull/227
60+
public @Nullable V compute(
61+
K key,
62+
BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) {}
63+
}

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/BaseLanguageServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
256256
logger.info("LSP connection started (connected to {} version {})", params.getClientInfo().getName(), params.getClientInfo().getVersion());
257257
logger.debug("LSP client capabilities: {}", params.getCapabilities());
258258
final InitializeResult initializeResult = new InitializeResult(new ServerCapabilities());
259-
lspDocumentService.initializeServerCapabilities(initializeResult.getCapabilities());
259+
lspDocumentService.initializeServerCapabilities(params.getCapabilities(), initializeResult.getCapabilities());
260260
lspWorkspaceService.initialize(params.getCapabilities(), params.getWorkspaceFolders(), initializeResult.getCapabilities());
261261
logger.debug("Initialized LSP connection with capabilities: {}", initializeResult);
262262
return initializeResult;

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/IBaseTextDocumentService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
import java.time.Duration;
3030
import java.util.List;
3131
import java.util.concurrent.CompletableFuture;
32-
3332
import org.checkerframework.checker.nullness.qual.Nullable;
33+
import org.eclipse.lsp4j.ClientCapabilities;
3434
import org.eclipse.lsp4j.CreateFilesParams;
3535
import org.eclipse.lsp4j.DeleteFilesParams;
3636
import org.eclipse.lsp4j.RenameFilesParams;
@@ -49,7 +49,7 @@ public interface IBaseTextDocumentService extends TextDocumentService {
4949
static final Duration NO_DEBOUNCE = Duration.ZERO;
5050
static final Duration NORMAL_DEBOUNCE = Duration.ofMillis(800);
5151

52-
void initializeServerCapabilities(ServerCapabilities result);
52+
void initializeServerCapabilities(ClientCapabilities clientCapabilities, ServerCapabilities result);
5353
void shutdown();
5454
void connect(LanguageClient client);
5555
void pair(BaseWorkspaceService workspaceService);

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ILanguageContributions.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
3535

3636
import io.usethesource.vallang.IConstructor;
37+
import io.usethesource.vallang.IInteger;
3738
import io.usethesource.vallang.IList;
3839
import io.usethesource.vallang.ISet;
3940
import io.usethesource.vallang.ISourceLocation;
@@ -65,7 +66,9 @@ public interface ILanguageContributions {
6566
public InterruptibleFuture<ISourceLocation> prepareRename(IList focus);
6667
public InterruptibleFuture<ITuple> rename(IList focus, String name);
6768
public InterruptibleFuture<ITuple> didRenameFiles(IList fileRenames);
69+
public InterruptibleFuture<IList> completion(IList focus, IInteger cursorOffset, IConstructor trigger);
6870

71+
public CompletableFuture<IList> completionTriggerCharacters();
6972
public CompletableFuture<IList> parseCodeActions(String command);
7073
public CompletableFuture<IConstructor> parseCallHierarchyData(String data);
7174

@@ -84,6 +87,7 @@ public interface ILanguageContributions {
8487
public CompletableFuture<Boolean> hasDidRenameFiles();
8588
public CompletableFuture<Boolean> hasSelectionRange();
8689
public CompletableFuture<Boolean> hasCallHierarchy();
90+
public CompletableFuture<Boolean> hasCompletion();
8791

8892
public CompletableFuture<Boolean> specialCaseHighlighting();
8993

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/InterpretedLanguageContributions.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131
import java.util.Objects;
3232
import java.util.concurrent.CompletableFuture;
3333
import java.util.concurrent.ExecutorService;
34-
3534
import org.apache.logging.log4j.LogManager;
3635
import org.apache.logging.log4j.Logger;
3736
import org.checkerframework.checker.nullness.qual.NonNull;
3837
import org.checkerframework.checker.nullness.qual.Nullable;
38+
import org.checkerframework.checker.nullness.qual.PolyNull;
3939
import org.rascalmpl.interpreter.Evaluator;
4040
import org.rascalmpl.interpreter.env.ModuleEnvironment;
4141
import org.rascalmpl.library.util.PathConfig;
@@ -57,6 +57,7 @@
5757

5858
import io.usethesource.vallang.IBool;
5959
import io.usethesource.vallang.IConstructor;
60+
import io.usethesource.vallang.IInteger;
6061
import io.usethesource.vallang.IList;
6162
import io.usethesource.vallang.ISet;
6263
import io.usethesource.vallang.ISourceLocation;
@@ -98,6 +99,8 @@ public class InterpretedLanguageContributions implements ILanguageContributions
9899
private final CompletableFuture<@Nullable IFunction> selectionRange;
99100
private final CompletableFuture<@Nullable IFunction> prepareCallHierarchy;
100101
private final CompletableFuture<@Nullable IFunction> callHierarchyService;
102+
private final CompletableFuture<@Nullable IFunction> completion;
103+
private final CompletableFuture<IList> completionTriggerCharacters;
101104

102105
private final CompletableFuture<Boolean> hasAnalysis;
103106
private final CompletableFuture<Boolean> hasBuild;
@@ -114,6 +117,7 @@ public class InterpretedLanguageContributions implements ILanguageContributions
114117
private final CompletableFuture<Boolean> hasDidRenameFiles;
115118
private final CompletableFuture<Boolean> hasSelectionRange;
116119
private final CompletableFuture<Boolean> hasCallHierarchy;
120+
private final CompletableFuture<Boolean> hasCompletion;
117121

118122
private final CompletableFuture<Boolean> specialCaseHighlighting;
119123

@@ -162,6 +166,8 @@ public InterpretedLanguageContributions(LanguageParameter lang, IBaseTextDocumen
162166
this.selectionRange = getFunctionFor(contributions, LanguageContributions.SELECTION_RANGE);
163167
this.prepareCallHierarchy = getFunctionFor(contributions, LanguageContributions.CALL_HIERARCHY, 0);
164168
this.callHierarchyService = getFunctionFor(contributions, LanguageContributions.CALL_HIERARCHY, 1);
169+
this.completion = getFunctionFor(contributions, LanguageContributions.COMPLETION);
170+
this.completionTriggerCharacters = getContributionParameter(contributions, LanguageContributions.COMPLETION, LanguageContributions.COMPLETION_TRIGGER_CHARACTERS, VF.list(), IList.class);
165171

166172
// assign boolean properties once instead of wasting futures all the time
167173
this.hasAnalysis = nonNull(this.analysis);
@@ -179,6 +185,7 @@ public InterpretedLanguageContributions(LanguageParameter lang, IBaseTextDocumen
179185
this.hasDidRenameFiles = nonNull(this.didRenameFiles);
180186
this.hasSelectionRange = nonNull(this.selectionRange);
181187
this.hasCallHierarchy = nonNull(this.prepareCallHierarchy);
188+
this.hasCompletion = nonNull(this.completion);
182189

183190
this.specialCaseHighlighting = getContributionParameter(contributions,
184191
LanguageContributions.PARSING,
@@ -237,8 +244,22 @@ private static boolean hasContribution(ISet contributions, String name) {
237244

238245
private static CompletableFuture<Boolean> getContributionParameter(
239246
CompletableFuture<ISet> contributions, String name, String parameter) {
247+
return getContributionParameter(contributions, name, parameter, VF.bool(false), IBool.class).thenApply(IBool::getValue);
248+
}
249+
250+
private static <T extends IValue> CompletableFuture<@PolyNull T> getContributionParameter(CompletableFuture<ISet> contributions, String name, String parameter, @PolyNull T defaultVal, Class<T> t) {
251+
return contributions.thenApply(c -> {
252+
var contrib = getContribution(c, name);
253+
if (contrib == null) {
254+
return defaultVal;
255+
}
240256

241-
return contributions.thenApply(c -> isTrue(getContribution(c, name), parameter));
257+
try {
258+
return t.cast(contrib.asWithKeywordParameters().getParameter(parameter));
259+
} catch (ClassCastException e) {
260+
return defaultVal;
261+
}
262+
});
242263
}
243264

244265
private static boolean isTrue(@Nullable IConstructor constructor, String parameter) {
@@ -442,7 +463,6 @@ public InterruptibleFuture<IList> selectionRange(IList focus) {
442463
return execFunction(LanguageContributions.SELECTION_RANGE, selectionRange, VF.list(), focus);
443464
}
444465

445-
@Override
446466
public InterruptibleFuture<IList> prepareCallHierarchy(IList focus) {
447467
debug(LanguageContributions.CALL_HIERARCHY, "prepare", focus.length());
448468
return execFunction(LanguageContributions.CALL_HIERARCHY, prepareCallHierarchy, VF.list(), focus);
@@ -454,6 +474,17 @@ public InterruptibleFuture<IList> incomingOutgoingCalls(IConstructor hierarchyIt
454474
return execFunction(LanguageContributions.CALL_HIERARCHY, callHierarchyService, VF.list(), hierarchyItem, direction);
455475
}
456476

477+
@Override
478+
public InterruptibleFuture<IList> completion(IList focus, IInteger cursorOffset, IConstructor trigger) {
479+
debug(LanguageContributions.COMPLETION, focus.length());
480+
return execFunction(LanguageContributions.COMPLETION, completion, VF.list(), focus, cursorOffset, trigger);
481+
}
482+
483+
@Override
484+
public CompletableFuture<IList> completionTriggerCharacters() {
485+
return completionTriggerCharacters;
486+
}
487+
457488
private void debug(String name, Object param) {
458489
logger.debug("{}({})", name, param);
459490
}
@@ -522,11 +553,15 @@ public CompletableFuture<Boolean> hasSelectionRange() {
522553
return hasSelectionRange;
523554
}
524555

525-
@Override
526556
public CompletableFuture<Boolean> hasCallHierarchy() {
527557
return hasCallHierarchy;
528558
}
529559

560+
@Override
561+
public CompletableFuture<Boolean> hasCompletion() {
562+
return hasCompletion;
563+
}
564+
530565
@Override
531566
public CompletableFuture<Boolean> hasAnalysis() {
532567
return hasAnalysis;

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/LanguageContributionsMultiplexer.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
3939

4040
import io.usethesource.vallang.IConstructor;
41+
import io.usethesource.vallang.IInteger;
4142
import io.usethesource.vallang.IList;
4243
import io.usethesource.vallang.ISet;
4344
import io.usethesource.vallang.ISourceLocation;
@@ -71,6 +72,7 @@ private static final <T> CompletableFuture<T> failedInitialization() {
7172
private volatile CompletableFuture<ILanguageContributions> didRenameFiles = failedInitialization();
7273
private volatile CompletableFuture<ILanguageContributions> selectionRange = failedInitialization();
7374
private volatile CompletableFuture<ILanguageContributions> callHierarchy = failedInitialization();
75+
private volatile CompletableFuture<ILanguageContributions> completion = failedInitialization();
7476

7577
private volatile CompletableFuture<Boolean> hasAnalysis = failedInitialization();
7678
private volatile CompletableFuture<Boolean> hasBuild = failedInitialization();
@@ -87,6 +89,7 @@ private static final <T> CompletableFuture<T> failedInitialization() {
8789
private volatile CompletableFuture<Boolean> hasDidRenameFiles = failedInitialization();
8890
private volatile CompletableFuture<Boolean> hasSelectionRange = failedInitialization();
8991
private volatile CompletableFuture<Boolean> hasCallHierarchy = failedInitialization();
92+
private volatile CompletableFuture<Boolean> hasCompletion = failedInitialization();
9093

9194
private volatile CompletableFuture<Boolean> specialCaseHighlighting = failedInitialization();
9295

@@ -164,6 +167,7 @@ private synchronized void calculateRouting() {
164167
didRenameFiles = findFirstOrDefault(ILanguageContributions::hasDidRenameFiles);
165168
selectionRange = findFirstOrDefault(ILanguageContributions::hasSelectionRange);
166169
callHierarchy = findFirstOrDefault(ILanguageContributions::hasCallHierarchy);
170+
completion = findFirstOrDefault(ILanguageContributions::hasCompletion);
167171

168172
hasAnalysis = anyTrue(ILanguageContributions::hasAnalysis);
169173
hasBuild = anyTrue(ILanguageContributions::hasBuild);
@@ -180,6 +184,7 @@ private synchronized void calculateRouting() {
180184
hasDidRenameFiles = anyTrue(ILanguageContributions::hasDidRenameFiles);
181185
hasSelectionRange = anyTrue(ILanguageContributions::hasSelectionRange);
182186
hasCallHierarchy = anyTrue(ILanguageContributions::hasCallHierarchy);
187+
hasCompletion = anyTrue(ILanguageContributions::hasCompletion);
183188

184189
// Always use the special-case highlighting status of *the first*
185190
// contribution (possibly using the default value in the Rascal ADT if
@@ -336,13 +341,18 @@ public InterruptibleFuture<IList> codeAction(IList focus) {
336341
}
337342

338343
@Override
339-
public CompletableFuture<Boolean> hasSelectionRange() {
340-
return hasSelectionRange;
344+
public InterruptibleFuture<IList> selectionRange(IList focus) {
345+
return flatten(selectionRange, c -> c.selectionRange(focus));
341346
}
342347

343348
@Override
344-
public InterruptibleFuture<IList> selectionRange(IList focus) {
345-
return flatten(selectionRange, c -> c.selectionRange(focus));
349+
public InterruptibleFuture<IList> completion(IList focus, IInteger cursorOffset, IConstructor trigger) {
350+
return flatten(completion, c -> c.completion(focus, cursorOffset, trigger));
351+
}
352+
353+
@Override
354+
public CompletableFuture<IList> completionTriggerCharacters() {
355+
return completion.thenCompose(ILanguageContributions::completionTriggerCharacters);
346356
}
347357

348358
@Override
@@ -410,6 +420,11 @@ public CompletableFuture<Boolean> hasInlayHint() {
410420
return hasInlayHint;
411421
}
412422

423+
@Override
424+
public CompletableFuture<Boolean> hasSelectionRange() {
425+
return hasSelectionRange;
426+
}
427+
413428
@Override
414429
public CompletableFuture<Boolean> hasRename() {
415430
return hasRename;
@@ -420,11 +435,15 @@ public CompletableFuture<Boolean> hasDidRenameFiles() {
420435
return hasDidRenameFiles;
421436
}
422437

423-
@Override
424438
public CompletableFuture<Boolean> hasCallHierarchy() {
425439
return hasCallHierarchy;
426440
}
427441

442+
@Override
443+
public CompletableFuture<Boolean> hasCompletion() {
444+
return hasCompletion;
445+
}
446+
428447
@Override
429448
public CompletableFuture<Boolean> specialCaseHighlighting() {
430449
return specialCaseHighlighting;

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/NoContributions.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
3636

3737
import io.usethesource.vallang.IConstructor;
38+
import io.usethesource.vallang.IInteger;
3839
import io.usethesource.vallang.IList;
3940
import io.usethesource.vallang.ISet;
4041
import io.usethesource.vallang.ISourceLocation;
@@ -168,6 +169,16 @@ public CompletableFuture<IConstructor> parseCallHierarchyData(String data) {
168169
throw new NoContributionException("parseCallHierarchyData");
169170
}
170171

172+
@Override
173+
public InterruptibleFuture<IList> completion(IList focus, IInteger cursorOffset, IConstructor trigger) {
174+
throw new NoContributionException("completion");
175+
}
176+
177+
@Override
178+
public CompletableFuture<IList> completionTriggerCharacters() {
179+
throw new NoContributionException("completionTriggerCharacters");
180+
}
181+
171182
@Override
172183
public CompletableFuture<Boolean> hasAnalysis() {
173184
return falsy;
@@ -243,6 +254,11 @@ public CompletableFuture<Boolean> hasCallHierarchy() {
243254
return falsy;
244255
}
245256

257+
@Override
258+
public CompletableFuture<Boolean> hasCompletion() {
259+
return falsy;
260+
}
261+
246262
@Override
247263
public CompletableFuture<Boolean> specialCaseHighlighting() {
248264
return falsy;

0 commit comments

Comments
 (0)