Skip to content

Commit f0930d1

Browse files
committed
Rascal LSP formatting API and example.
1 parent 54f5b6d commit f0930d1

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
5959
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
6060
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
61+
import org.eclipse.lsp4j.DocumentFormattingParams;
6162
import org.eclipse.lsp4j.DocumentSymbol;
6263
import org.eclipse.lsp4j.DocumentSymbolParams;
6364
import org.eclipse.lsp4j.ExecuteCommandOptions;
@@ -69,8 +70,8 @@
6970
import org.eclipse.lsp4j.InlayHint;
7071
import org.eclipse.lsp4j.InlayHintKind;
7172
import org.eclipse.lsp4j.InlayHintParams;
72-
import org.eclipse.lsp4j.LocationLink;
7373
import org.eclipse.lsp4j.Location;
74+
import org.eclipse.lsp4j.LocationLink;
7475
import org.eclipse.lsp4j.Position;
7576
import org.eclipse.lsp4j.ReferenceParams;
7677
import org.eclipse.lsp4j.SemanticTokens;
@@ -83,6 +84,7 @@
8384
import org.eclipse.lsp4j.TextDocumentIdentifier;
8485
import org.eclipse.lsp4j.TextDocumentItem;
8586
import org.eclipse.lsp4j.TextDocumentSyncKind;
87+
import org.eclipse.lsp4j.TextEdit;
8688
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
8789
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
8890
import org.eclipse.lsp4j.jsonrpc.messages.Either;
@@ -104,8 +106,8 @@
104106
import org.rascalmpl.vscode.lsp.uri.FallbackResolver;
105107
import org.rascalmpl.vscode.lsp.util.CodeActions;
106108
import org.rascalmpl.vscode.lsp.util.Diagnostics;
107-
import org.rascalmpl.vscode.lsp.util.FoldingRanges;
108109
import org.rascalmpl.vscode.lsp.util.DocumentSymbols;
110+
import org.rascalmpl.vscode.lsp.util.FoldingRanges;
109111
import org.rascalmpl.vscode.lsp.util.SemanticTokenizer;
110112
import org.rascalmpl.vscode.lsp.util.Versioned;
111113
import org.rascalmpl.vscode.lsp.util.concurrent.InterruptibleFuture;
@@ -511,6 +513,17 @@ public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActio
511513
return CodeActions.mergeAndConvertCodeActions(this, dedicatedLanguageName, contribs.getName(), quickfixes, codeActions);
512514
}
513515

516+
@Override
517+
public CompletableFuture<List<? extends TextEdit>> formatting(DocumentFormattingParams params) {
518+
logger.debug("formatting: {}", params);
519+
520+
// convert the `FormattingOptions` map to a `formattingOptions` constructor
521+
// call the `formatting` implementation of the relevant language contribution
522+
// with the resulting string and the input tree, compute a list of `TextEdit`s to return
523+
524+
return CompletableFuture.completedFuture(Collections.emptyList());
525+
}
526+
514527
private CompletableFuture<IList> computeCodeActions(final ILanguageContributions contribs, final int startLine, final int startColumn, ITree tree) {
515528
IList focus = TreeSearch.computeFocusList(tree, startLine, startColumn);
516529

rascal-lsp/src/main/rascal/library/demo/lang/pico/LanguageServer.rsc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import ParseTree;
3939
import util::ParseErrorRecovery;
4040
import util::Reflective;
4141
import lang::pico::\syntax::Main;
42+
import IO;
43+
import String;
4244

4345
private Tree (str _input, loc _origin) picoParser(bool allowRecovery) {
4446
return ParseTree::parser(#start[Program], allowRecovery=allowRecovery, filters=allowRecovery ? {createParseErrorFilter(false)} : {});
@@ -57,9 +59,37 @@ set[LanguageService] picoLanguageServer(bool allowRecovery) = {
5759
execution(picoExecutionService),
5860
inlayHint(picoInlayHintService),
5961
definition(picoDefinitionService),
60-
codeAction(picoCodeActionService)
62+
codeAction(picoCodeActionService),
63+
formatting(picoFormattingService)
6164
};
6265

66+
str picoFormattingService(Tree input, formattingOptions(int tabSize, bool insertSpaces, bool trimTrailingWhiteSpace, bool insertFinalNewLine, bool trimFinalNewLines)) {
67+
str formatted = "<input>";
68+
str linesep = "\n";
69+
70+
println("Warning; `tabSize` (<tabSize>) is ignored");
71+
if (insertSpaces) {
72+
println("Warning; `insertSpaces` is ignored");
73+
}
74+
75+
str trimLineTrailingWs(/^<nonWhiteSpace:.*\S>\s*$/) = nonWhiteSpace;
76+
default str trimLineTrailingWs(/^\s*$/) = "";
77+
78+
if (trimTrailingWhiteSpace) {
79+
formatted = intercalate(linesep, [trimLineTrailingWs(l) | l <- split(linesep, formatted)]);
80+
}
81+
82+
if (trimFinalNewLines, /^<textLines:.*[^\n]>\n+$/ := formatted) {
83+
formatted = textLines;
84+
}
85+
86+
if (insertFinalNewLine && /\n$/ !:= formatted) {
87+
formatted += "\n";
88+
}
89+
90+
return formatted;
91+
}
92+
6393
set[LanguageService] picoLanguageServer() = picoLanguageServer(false);
6494
set[LanguageService] picoLanguageServerWithRecovery() = picoLanguageServer(true);
6595

rascal-lsp/src/main/rascal/library/util/LanguageServer.rsc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,19 @@ data LanguageService
268268
| references (set[loc] (Focus _focus) referencesService)
269269
| implementation(set[loc] (Focus _focus) implementationService)
270270
| codeAction (list[CodeAction] (Focus _focus) codeActionService)
271+
| formatting (str (Tree _input, FormattingOptions _opts) formattingService)
271272
;
272273

274+
data FormattingOptions
275+
// If LSP adds more options, add them as keyword arguments for backward compatibility
276+
= formattingOptions(
277+
int tabSize
278+
, bool insertSpaces
279+
, bool trimTrailingWhiteSpace
280+
, bool insertFinalNewLine
281+
, bool trimFinalNewLines
282+
);
283+
273284
@deprecated{Backward compatible with ((parsing)).}
274285
@synopsis{Construct a `parsing` ((LanguageService))}
275286
LanguageService parser(Parser parser) = parsing(parser);

0 commit comments

Comments
 (0)