Skip to content

Commit

Permalink
Merge pull request #491 from usethesource/recovery/outline-and-code-l…
Browse files Browse the repository at this point in the history
…ense-fixes

Both outline and codelenses support can now handle error trees
  • Loading branch information
PieterOlivier authored Oct 25, 2024
2 parents b947d04 + 5d60fde commit 91d0e6b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
import org.rascalmpl.exceptions.Throw;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.library.util.ErrorRecovery;
import org.rascalmpl.library.util.PathConfig;
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.functions.IFunction;
Expand All @@ -76,6 +77,7 @@

public class RascalLanguageServices {
private static final IValueFactory VF = IRascalValueFactory.getInstance();
private static final ErrorRecovery RECOVERY = new ErrorRecovery(IRascalValueFactory.getInstance());

private static final Logger logger = LogManager.getLogger(RascalLanguageServices.class);

Expand Down Expand Up @@ -236,8 +238,13 @@ public List<CodeLensSuggestion> locateCodeLenses(ITree tree) {
List<CodeLensSuggestion> result = new ArrayList<>(2);
result.add(new CodeLensSuggestion(module, "Import in new Rascal terminal", "rascalmpl.importModule", moduleName));

for (IValue topLevel : TreeAdapter
.getListASTArgs(TreeAdapter.getArg(TreeAdapter.getArg(tree, "body"), "toplevels"))) {
ITree body = TreeAdapter.getArg(tree, "body");
ITree toplevels = TreeAdapter.getArg(body, "toplevels");
for (IValue topLevel : TreeAdapter.getListASTArgs(toplevels)) {
if (RECOVERY.hasErrors((ITree) topLevel)) {
continue;
}

ITree decl = TreeAdapter.getArg((ITree) topLevel, "declaration");
if ("function".equals(TreeAdapter.getConstructorName(decl))) {
ITree signature = TreeAdapter.getArg(TreeAdapter.getArg(decl, "functionDeclaration"), "signature");
Expand Down
72 changes: 47 additions & 25 deletions rascal-lsp/src/main/rascal/lang/rascal/lsp/Outline.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,58 @@ import String;
import ParseTree;
import lang::rascal::\syntax::Rascal;
import util::LanguageServer;
import util::ErrorRecovery;

list[DocumentSymbol] outlineRascalModule(start[Module] \mod) {
m= \mod.top;
children = [];

top-down-break visit (m) {
case (Declaration) `<Tags _> <Visibility _> <Type t> <{Variable ","}+ vars>;`:
children += [symbol(clean("<v.name>"), variable(), v@\loc, detail="variable <t> <v>") | v <- vars];

case (Declaration) `<Tags _> <Visibility _> anno <Type t> <Type ot>@<Name name>;`:
children += [symbol(clean("<name>"), field(), t@\loc, detail="anno <t> <ot>")];

case (Declaration) `<Tags _> <Visibility _> alias <UserType u> = <Type al>;`:
children += [symbol(clean("<u.name>"), struct(), u@\loc, detail="<u> = <al>")];
if (!(m has header) || hasErrors(m.header)) {
return [];
}

case (Declaration) `<Tags _> <Visibility _> tag <Kind k> <Name name> on <{Type ","}+ ts>;`:
children += [symbol(clean("<name>"), \key(), name@\loc, detail="tag <k> <name> on <ts>")];
children = [];

case (Declaration) `<Tags _> <Visibility _> data <UserType u> <CommonKeywordParameters kws>;`: {
kwlist = [symbol(".<k.name>", property(), k@\loc, detail="<k.\type>") | kws is present, KeywordFormal k <- kws.keywordFormalList];
children += [symbol("<u.name>", struct(), u@\loc, detail="data <u> <kws>", children=kwlist)];
top-down-break visit (m) {
case decl: (Declaration) `<Tags _> <Visibility _> <Type t> <{Variable ","}+ vars>;`:
if (!hasErrors(decl)) {
children += [symbol(clean("<v.name>"), variable(), v@\loc, detail="variable <t> <v>") | v <- vars];
}

case decl: (Declaration) `<Tags _> <Visibility _> anno <Type t> <Type ot>@<Name name>;`:
if (!hasErrors(decl)) {
children += [symbol(clean("<name>"), field(), t@\loc, detail="anno <t> <ot>")];
}

case decl: (Declaration) `<Tags _> <Visibility _> alias <UserType u> = <Type al>;`:
if (!hasErrors(decl)) {
children += [symbol(clean("<u.name>"), struct(), u@\loc, detail="<u> = <al>")];
}

case decl: (Declaration) `<Tags _> <Visibility _> tag <Kind k> <Name name> on <{Type ","}+ ts>;`:
if (!hasErrors(decl)) {
children += [symbol(clean("<name>"), \key(), name@\loc, detail="tag <k> <name> on <ts>")];
}

case decl: (Declaration) `<Tags _> <Visibility _> data <UserType u> <CommonKeywordParameters kws>;`: {
if (!hasErrors(decl)) {
kwlist = [symbol(".<k.name>", property(), k@\loc, detail="<k.\type>") | kws is present, KeywordFormal k <- kws.keywordFormalList];
children += [symbol("<u.name>", struct(), u@\loc, detail="data <u> <kws>", children=kwlist)];
}
}

case (Declaration) `<Tags _> <Visibility _> data <UserType u> <CommonKeywordParameters kws> = <{Variant "|"}+ variants>;` : {
kwlist = [symbol(".<k.name>", property(), k@\loc, detail="<k.\type>") | kws is present, KeywordFormal k <- kws.keywordFormalList];
variantlist = [symbol(clean("<v>"), \constructor(), v@\loc) | v <- variants];
case decl: (Declaration) `<Tags _> <Visibility _> data <UserType u> <CommonKeywordParameters kws> = <{Variant "|"}+ variants>;` : {
if (!hasErrors(decl)) {
kwlist = [symbol(".<k.name>", property(), k@\loc, detail="<k.\type>") | kws is present, KeywordFormal k <- kws.keywordFormalList];
variantlist = [symbol(clean("<v>"), \constructor(), v@\loc) | v <- variants];

children += [symbol("<u.name>", struct(), u@\loc, detail="data <u> <kws>", children=kwlist + variantlist)];
children += [symbol("<u.name>", struct(), u@\loc, detail="data <u> <kws>", children=kwlist + variantlist)];
}
}

case FunctionDeclaration func :
children += [symbol("<func.signature.name><func.signature.parameters>", \function(), (func.signature)@\loc, detail="<func.signature.\type>")];
if (!hasErrors(func)) {
children += [symbol("<func.signature.name><func.signature.parameters>", \function(), (func.signature)@\loc, detail="<func.signature.\type>")];
}

/*
case (Import) `extend <ImportedModule mm>;` :
Expand All @@ -76,11 +96,13 @@ list[DocumentSymbol] outlineRascalModule(start[Module] \mod) {
*/

case SyntaxDefinition def : {
rs = [symbol(clean("<prefix> <p.syms>"), \function(), p@\loc)
| /Prod p := def.production, p is labeled || p is unlabeled,
str prefix := (p is labeled ? "<p.name>: " : "")
];
children += [symbol(clean("<def.defined>"), \struct(), def@\loc, children=rs)];
if (!hasErrors(def)) {
rs = [symbol(clean("<prefix> <p.syms>"), \function(), p@\loc)
| /Prod p := def.production, !hasErrors(p) && (p is labeled || p is unlabeled),
str prefix := (p is labeled ? "<p.name>: " : "")
];
children += [symbol(clean("<def.defined>"), \struct(), def@\loc, children=rs)];
}
}
}
Expand Down

0 comments on commit 91d0e6b

Please sign in to comment.