use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.
the class JSGLRCompletionService method findCompletionTerm.
private Collection<IStrategoTerm> findCompletionTerm(StrategoTerm ast) {
final Collection<IStrategoTerm> completionTerms = Lists.newLinkedList();
final IStrategoTermVisitor visitor = new AStrategoTermVisitor() {
@Override
public boolean visit(IStrategoTerm term) {
ImploderAttachment ia = term.getAttachment(ImploderAttachment.TYPE);
if (ia.isNestedCompletion()) {
return false;
}
if (ia.isCompletion()) {
completionTerms.add(term);
return false;
}
return true;
}
};
StrategoTermVisitee.topdown(visitor, ast);
return completionTerms;
}
use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.
the class JSGLRCompletionService method completionCorrectPrograms.
public Collection<ICompletion> completionCorrectPrograms(int position, boolean blankLineCompletion, ISpoofaxParseUnit parseResult) throws MetaborgException {
Collection<ICompletion> completions = Sets.newHashSet();
final FileObject location = parseResult.source();
final ILanguageImpl language = parseResult.input().langImpl();
final String languageName = language.belongsTo().name();
for (ILanguageComponent component : language.components()) {
final HybridInterpreter runtime = strategoRuntimeService.runtime(component, location, false);
final ITermFactory termFactory = termFactoryService.get(component, null, false);
final Map<IStrategoTerm, Boolean> leftRecursiveTerms = new HashMap<IStrategoTerm, Boolean>();
final Map<IStrategoTerm, Boolean> rightRecursiveTerms = new HashMap<IStrategoTerm, Boolean>();
final Iterable<IStrategoTerm> terms = tracingTermsCompletions(position, parseResult.ast(), new SourceRegion(position), runtime, termFactory, languageName, leftRecursiveTerms, rightRecursiveTerms);
final IStrategoAppl placeholder = getPlaceholder(position, terms);
final Iterable<IStrategoList> lists = getLists(terms, leftRecursiveTerms, rightRecursiveTerms);
final Iterable<IStrategoTerm> optionals = getOptionals(terms, leftRecursiveTerms, rightRecursiveTerms);
final Iterable<IStrategoTerm> leftRecursive = getLeftRecursiveTerms(position, terms, leftRecursiveTerms);
final Iterable<IStrategoTerm> rightRecursive = getRightRecursiveTerms(position, terms, rightRecursiveTerms);
if (placeholder != null) {
completions.addAll(placeholderCompletions(placeholder, languageName, component, location));
} else {
if (Iterables.size(lists) != 0) {
completions.addAll(listsCompletions(position, blankLineCompletion, lists, languageName, component, location));
}
if (Iterables.size(optionals) != 0) {
completions.addAll(optionalCompletions(optionals, blankLineCompletion, languageName, component, location));
}
// TODO Improve recursive completions
// if(Iterables.size(leftRecursive) != 0 || Iterables.size(rightRecursive) != 0) {
// completions
// .addAll(recursiveCompletions(leftRecursive, rightRecursive, languageName, component, location));
// }
}
}
return completions;
}
use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.
the class JSGLRCompletionService method fromTokens.
// TODO: Do these strategies need to be specific for a language
@Nullable
protected ISourceLocation fromTokens(IStrategoTerm fragment, HybridInterpreter runtime, ITermFactory termFactory, int position, String languageName, Map<IStrategoTerm, Boolean> leftRecursiveTerms, Map<IStrategoTerm, Boolean> rightRecursiveTerms) {
final FileObject resource = SourceAttachment.getResource(fragment, resourceService);
final IToken left = ImploderAttachment.getLeftToken(fragment);
final IToken right = ImploderAttachment.getRightToken(fragment);
ITokens tokenizer = ImploderAttachment.getTokenizer(fragment);
IToken leftmostValid = left;
IToken rightmostValid = right;
boolean isList = (fragment instanceof IStrategoList) ? true : false;
boolean isOptional = false;
String sort = ImploderAttachment.getSort(fragment);
IStrategoTerm input = termFactory.makeString(sort);
boolean isLeftRecursive = false;
if (fragment instanceof IStrategoAppl && position > right.getEndOffset()) {
try {
isLeftRecursive = strategoCommon.invoke(runtime, input, "is-left-recursive") != null;
} catch (MetaborgException e) {
logger.error("Failed to check recursivity for term {} of sort {} - syntactic completion not activated for this language, please import the completion stratego library", fragment, sort);
}
}
boolean isRightRecursive = false;
if (fragment instanceof IStrategoAppl && position <= left.getStartOffset()) {
try {
isRightRecursive = strategoCommon.invoke(runtime, input, "is-right-recursive") != null;
} catch (MetaborgException e) {
logger.error("Failed to check recursivity for term {} of sort {} - syntactic completion not activated for this language, please import the completion stratego library", fragment, sort);
}
}
if (isLeftRecursive) {
leftRecursiveTerms.put(fragment, true);
}
if (isRightRecursive) {
rightRecursiveTerms.put(fragment, true);
}
if (left == null || right == null) {
return null;
}
if (!isList && left == right && left.getEndOffset() < left.getStartOffset()) {
isOptional = true;
}
// if it's a list or a node that is empty make the element includes the surrounding layout tokens
if (left.getStartOffset() > right.getEndOffset() || isList || isOptional || (isLeftRecursive && isRightRecursive)) {
for (int i = left.getIndex() - 1; i >= 0; i--) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
leftmostValid = tokenizer.getTokenAt(i);
} else {
break;
}
}
for (int i = right.getIndex() + 1; i < tokenizer.getTokenCount(); i++) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_EOF || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
rightmostValid = tokenizer.getTokenAt(i);
} else {
break;
}
}
// if it is left recursive include the layout only on the right
} else if (isLeftRecursive) {
for (int i = left.getIndex(); i < right.getIndex(); i++) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
leftmostValid = tokenizer.getTokenAt(i + 1);
} else {
break;
}
}
for (int i = right.getIndex() + 1; i < tokenizer.getTokenCount(); i++) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_EOF || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
rightmostValid = tokenizer.getTokenAt(i);
} else {
break;
}
}
// if it is right recursive include the layout only on the left
} else if (isRightRecursive) {
for (int i = left.getIndex() - 1; i >= 0; i--) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
leftmostValid = tokenizer.getTokenAt(i);
} else {
break;
}
}
for (int i = right.getIndex(); i > left.getIndex(); i--) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_EOF || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
rightmostValid = tokenizer.getTokenAt(i - 1);
} else {
break;
}
}
} else // if not make it stripes the surrounding layout tokens
{
for (int i = left.getIndex(); i < right.getIndex(); i++) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
leftmostValid = tokenizer.getTokenAt(i + 1);
} else {
break;
}
}
for (int i = right.getIndex(); i > left.getIndex(); i--) {
if (tokenizer.getTokenAt(i).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(i).getKind() == IToken.TK_EOF || tokenizer.getTokenAt(i).getKind() == IToken.TK_ERROR) {
rightmostValid = tokenizer.getTokenAt(i - 1);
} else {
break;
}
}
}
final ISourceRegion region = JSGLRSourceRegionFactory.fromTokensLayout(leftmostValid, rightmostValid, (isOptional || isList || isLeftRecursive || isRightRecursive));
return new SourceLocation(region, resource);
}
use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.
the class ActionFacetFromESV method menu.
private static Menu menu(IStrategoTerm menuTerm, TransformActionFlags flags, ImmutableList<String> nesting, Multimap<ITransformGoal, ITransformAction> actions) {
final String name = name(menuTerm.getSubterm(0));
final ImmutableList<String> newNesting = ImmutableList.<String>builder().addAll(nesting).add(name).build();
final TransformActionFlags extraFlags = flags(menuTerm.getSubterm(1));
final TransformActionFlags mergedFlags = TransformActionFlags.merge(flags, extraFlags);
final Iterable<IStrategoTerm> items = menuTerm.getSubterm(2);
final Menu menu = new Menu(name);
for (IStrategoTerm item : items) {
final String constructor = Tools.constructorName(item);
if (constructor == null) {
logger.error("Could not interpret menu item from term {}", item);
continue;
}
switch(constructor) {
case "Submenu":
final Menu submenu = menu(item, mergedFlags, newNesting, actions);
menu.add(submenu);
break;
case "Action":
final String actionName = name(item.getSubterm(0));
final String strategy = Tools.asJavaString(item.getSubterm(1).getSubterm(0));
final TransformActionFlags actionFlags = flags(item.getSubterm(2));
final TransformActionFlags mergedActionFlags = TransformActionFlags.merge(mergedFlags, actionFlags);
final ImmutableList<String> newActionNesting = ImmutableList.<String>builder().addAll(newNesting).add(actionName).build();
final NamedGoal goal = new NamedGoal(newActionNesting);
final TransformAction action = new TransformAction(actionName, goal, mergedActionFlags, strategy);
actions.put(goal, action);
actions.put(new EndNamedGoal(goal.names.get(goal.names.size() - 1)), action);
final MenuAction menuAction = new MenuAction(action);
menu.add(menuAction);
break;
case "Separator":
final Separator separator = new Separator();
menu.add(separator);
break;
default:
logger.warn("Unhandled menu item term {}", item);
break;
}
}
return menu;
}
use of org.spoofax.interpreter.terms.IStrategoTerm in project spoofax by metaborg.
the class JSGLRCompletionService method getPlaceholder.
@Nullable
private IStrategoAppl getPlaceholder(int position, final Iterable<IStrategoTerm> terms) {
for (IStrategoTerm term : terms) {
if (term instanceof IStrategoAppl) {
IToken left = ImploderAttachment.getLeftToken(term);
IToken right = ImploderAttachment.getRightToken(term);
final IStrategoAppl appl = (IStrategoAppl) term;
if (appl.getConstructor().getName().endsWith("-Plhdr") && position > left.getStartOffset() && position <= right.getEndOffset()) {
return appl;
}
}
}
return null;
}
Aggregations