module demo::lang::pico::LanguageServer
rascal-0.34.0
rascal-lsp-2.20.0
Usage
import demo::lang::pico::LanguageServer;
Source code
Dependencies
import util::LanguageServer;
import util::IDEServices;
import ParseTree;
import util::Reflective;
import lang::pico::\syntax::Main;
import IO;
function picoLanguageContributor
set[LanguageService] picoLanguageContributor() = {
parser(parser(#start[Program])),
outliner(picoOutliner),
lenses(picoLenses),
executor(picoCommands),
inlayHinter(picoHinter),
definer(lookupDef)
};
function picoLanguageContributorSlowSummary
set[LanguageService] picoLanguageContributorSlowSummary() = {
parser(parser(#start[Program])),
analyzer(picoAnalyzer, providesImplementations = false),
builder(picoBuilder)
};
function picoOutliner
list[DocumentSymbol] picoOutliner(start[Program] input)
= [symbol("<input.src>", DocumentSymbolKind::\file(), input.src, children=[
*[symbol("<var.id>", \variable(), var.src) | /IdType var := input]
])];
function picoAnalyzer
Summary picoAnalyzer(loc l, start[Program] input) = picoSummarizer(l, input, analyze());
function picoBuilder
Summary picoBuilder(loc l, start[Program] input) = picoSummarizer(l, input, build());
data PicoSummarizerMode
data PicoSummarizerMode
= analyze()
| build()
;
function picoSummarizer
Summary picoSummarizer(loc l, start[Program] input, PicoSummarizerMode mode) {
Summary s = summary(l);
rel[str, loc] defs = {<"<var.id>", var.src> | /IdType var := input};
rel[loc, str] uses = {<id.src, "<id>"> | /Id id := input};
rel[loc, str] docs = {<var.src, "*variable* <var>"> | /IdType var := input};
// Provide errors (cheap to compute) both in analyze mode and in build mode
s.messages += {<src, error("<id> is not defined", src)> | <src, id> <- uses, id notin defs<0>};
s.references += (uses o defs)<1,0>;
s.definitions += uses o defs;
s.documentation += (uses o defs) o docs;
// Provide warnings (expensive to compute) only in build mode
if (build() := mode) {
rel[loc, str] asgn = {<id.src, "<id>"> | /Statement stmt := input, (Statement) `<Id id> := <Expression _>` := stmt};
s.messages += {<src, warning("<id> is not assigned", src)> | <id, src> <- defs, id notin asgn<1>};
}
return s;
}
function lookupDef
set[loc] lookupDef(loc _, start[Program] input, Tree cursor) =
{ d.src | /IdType d := input, cursor := d.id};
data Command
data Command
= renameAtoB(start[Program] program)
;
function picoLenses
rel[loc,Command] picoLenses(start[Program] input) = {<input@\loc, renameAtoB(input, title="Rename variables a to b.")>};
function picoHinter
list[InlayHint] picoHinter(start[Program] input) {
typeLookup = ( "<name>" : "<tp>" | /(IdType)`<Id name> : <Type tp>` := input);
return [
hint(name.src, " : <typeLookup["<name>"]>", \type(), atEnd = true) | /(Expression)`<Id name>` := input, "<name>" in typeLookup
];
}
function getAtoBEdits
list[DocumentEdit] getAtoBEdits(start[Program] input)
= [changed(input@\loc.top, [replace(id@\loc, "b") | /id:(Id) `a` := input])];
function picoCommands
value picoCommands(renameAtoB(start[Program] input)) {
applyDocumentsEdits(getAtoBEdits(input));
return ("result": true);
}
function main
void main() {
registerLanguage(
language(
pathConfig(),
"Pico",
{"pico", "pico-new"},
"demo::lang::pico::LanguageServer",
"picoLanguageContributor"
)
);
registerLanguage(
language(
pathConfig(),
"Pico",
{"pico", "pico-new"},
"demo::lang::pico::LanguageServer",
"picoLanguageContributorSlowSummary"
)
);
}