use of org.spoofax.interpreter.terms.IStrategoAppl in project spoofax by metaborg.
the class JSGLRCompletionService method findPlaceholderTerms.
private Collection<IStrategoTerm> findPlaceholderTerms(IStrategoTerm ast) {
final Collection<IStrategoTerm> placeholderTerms = Lists.newLinkedList();
final IStrategoTermVisitor visitor = new AStrategoTermVisitor() {
@Override
public boolean visit(IStrategoTerm term) {
if (term instanceof IStrategoAppl) {
IStrategoAppl appl = (IStrategoAppl) term;
if (appl.getConstructor().getName().contains("-Plhdr") && appl.getSubtermCount() > 0) {
placeholderTerms.add(appl);
return false;
}
}
return true;
}
};
StrategoTermVisitee.topdown(visitor, ast);
return placeholderTerms;
}
use of org.spoofax.interpreter.terms.IStrategoAppl in project spoofax by metaborg.
the class JSGLRCompletionService method placeholderCompletions.
public Collection<ICompletion> placeholderCompletions(IStrategoAppl placeholder, String languageName, ILanguageComponent component, FileObject location) throws MetaborgException {
Collection<ICompletion> completions = Lists.newLinkedList();
// call Stratego part of the framework to compute change
final HybridInterpreter runtime = strategoRuntimeService.runtime(component, location, false);
final ITermFactory termFactory = termFactoryService.get(component, null, false);
IStrategoTerm placeholderParent = ParentAttachment.getParent(placeholder);
if (placeholderParent == null) {
placeholderParent = placeholder;
}
IStrategoInt placeholderIdx = termFactory.makeInt(-1);
for (int i = 0; i < placeholderParent.getSubtermCount(); i++) {
if (placeholderParent.getSubterm(i) == placeholder) {
placeholderIdx = termFactory.makeInt(i);
}
}
final String sort = ImploderAttachment.getSort(placeholder);
final IStrategoTerm strategoInput = termFactory.makeTuple(termFactory.makeString(sort), placeholder, placeholderParent, placeholderIdx);
final IStrategoTerm proposalsPlaceholder = strategoCommon.invoke(runtime, strategoInput, "get-proposals-placeholder-" + languageName);
if (proposalsPlaceholder == null) {
logger.error("Getting proposals for {} failed", placeholder);
return completions;
}
for (IStrategoTerm proposalTerm : proposalsPlaceholder) {
if (!(proposalTerm instanceof IStrategoTuple)) {
logger.error("Unexpected proposal term {}, skipping", proposalTerm);
continue;
}
final IStrategoTuple tuple = (IStrategoTuple) proposalTerm;
if (tuple.getSubtermCount() != 4 || !(tuple.getSubterm(0) instanceof IStrategoString) || !(tuple.getSubterm(1) instanceof IStrategoString) || !(tuple.getSubterm(2) instanceof IStrategoString) || !(tuple.getSubterm(3) instanceof IStrategoAppl)) {
logger.error("Unexpected proposal term {}, skipping", proposalTerm);
continue;
}
final String name = Tools.asJavaString(tuple.getSubterm(0));
final String text = Tools.asJavaString(tuple.getSubterm(1));
final String additionalInfo = Tools.asJavaString(tuple.getSubterm(2));
final StrategoAppl change = (StrategoAppl) tuple.getSubterm(3);
if (change.getConstructor().getName().contains("REPLACE_TERM")) {
final ICompletion completion = createCompletionReplaceTerm(name, text, additionalInfo, change, false, "", "");
if (completion == null) {
logger.error("Unexpected proposal term {}, skipping", proposalTerm);
continue;
}
completions.add(completion);
}
}
return completions;
}
use of org.spoofax.interpreter.terms.IStrategoAppl in project spoofax by metaborg.
the class JSGLRCompletionService method createCompletionInsertionTermFixing.
private ICompletion createCompletionInsertionTermFixing(String name, String text, String additionalInfo, String prefix, String suffix, StrategoAppl change, String completionKind) {
final StrategoTerm newNode = (StrategoTerm) change.getSubterm(0);
if (change.getSubtermCount() != 1 || !(newNode instanceof IStrategoAppl)) {
return null;
}
final String sort = ImploderAttachment.getSort(newNode);
int insertionPoint, suffixPoint;
ITokens tokenizer = ImploderAttachment.getTokenizer(newNode);
final StrategoTerm topMostAmb = findTopMostAmbNode(newNode);
final ImploderAttachment topMostAmbIA = topMostAmb.getAttachment(ImploderAttachment.TYPE);
// get the last non-layout token before the topmost ambiguity
int tokenPosition = topMostAmbIA.getLeftToken().getIndex() - 1 > 0 ? topMostAmbIA.getLeftToken().getIndex() - 1 : 0;
while ((tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR) && tokenPosition > 0) tokenPosition--;
insertionPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset();
if (topMostAmbIA.getRightToken().getEndOffset() < topMostAmbIA.getRightToken().getStartOffset()) {
// keep all the characters after the last non-layout token if completion ends with a
// placeholder
tokenPosition = topMostAmbIA.getRightToken().getIndex();
while (tokenPosition > 0 && (tokenizer.getTokenAt(tokenPosition).getEndOffset() < tokenizer.getTokenAt(tokenPosition).getStartOffset() || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT)) tokenPosition--;
suffixPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset() + 1;
} else {
// skip all the (erroneous) characters that were in the text already
suffixPoint = topMostAmbIA.getRightToken().getEndOffset() + 1;
}
CompletionKind kind;
if (completionKind.equals("recovery")) {
kind = CompletionKind.recovery;
} else if (completionKind.equals("expansionEditing")) {
kind = CompletionKind.expansionEditing;
} else {
kind = CompletionKind.expansion;
}
return new Completion(name, sort, text, additionalInfo, insertionPoint + 1, suffixPoint, kind, prefix, suffix);
}
use of org.spoofax.interpreter.terms.IStrategoAppl in project spoofax by metaborg.
the class JSGLRCompletionService method createCompletionReplaceTerm.
private ICompletion createCompletionReplaceTerm(String name, String text, String additionalInfo, StrategoAppl change, boolean blankLineCompletion, String prefix, String suffix) {
final StrategoTerm oldNode = (StrategoTerm) change.getSubterm(0);
final StrategoTerm newNode = (StrategoTerm) change.getSubterm(1);
if (change.getSubtermCount() != 2 || !(newNode instanceof IStrategoAppl) || !(oldNode instanceof IStrategoAppl)) {
return null;
}
final String sort = ImploderAttachment.getSort(oldNode);
int insertionPoint, suffixPoint;
final ImploderAttachment oldNodeIA = oldNode.getAttachment(ImploderAttachment.TYPE);
ITokens tokenizer = ImploderAttachment.getTokenizer(oldNode);
// check if it's an empty node
if (oldNodeIA.getLeftToken().getStartOffset() > oldNodeIA.getRightToken().getEndOffset()) {
// get the last non-layout token before the new node
int tokenPosition = oldNodeIA.getLeftToken().getIndex() - 1 > 0 ? oldNodeIA.getLeftToken().getIndex() - 1 : 0;
while (tokenPosition > 0 && (tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR)) tokenPosition--;
insertionPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset();
// if completion does not spam multiple lines preserve everything starting at the first non-layout char
if (!additionalInfo.contains("\n")) {
tokenPosition = oldNodeIA.getLeftToken().getIndex() + 1 < tokenizer.getTokenCount() ? oldNodeIA.getLeftToken().getIndex() + 1 : tokenizer.getTokenCount() - 1;
while (tokenPosition < tokenizer.getTokenCount() && (tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR)) tokenPosition++;
suffixPoint = tokenizer.getTokenAt(tokenPosition).getStartOffset();
} else {
// if completion spams multiple lines keep the lines
suffixPoint = insertionPoint + 1;
}
// if completion is triggered in an empty line, consume that line
IToken checkToken;
boolean blankLine = false;
if (blankLineCompletion) {
for (; tokenPosition < tokenizer.getTokenCount(); tokenPosition++) {
checkToken = tokenizer.getTokenAt(tokenPosition);
if (tokenizer.toString(checkToken, checkToken).contains("\n")) {
suffixPoint = checkToken.getEndOffset();
if (!blankLine) {
blankLine = true;
} else {
break;
}
}
}
}
} else {
// if not, do a regular replacement
insertionPoint = oldNodeIA.getLeftToken().getStartOffset() - 1;
suffixPoint = oldNodeIA.getRightToken().getEndOffset() + 1;
}
CompletionKind kind;
if (prefix.equals("") && suffix.equals("")) {
kind = CompletionKind.expansion;
} else {
kind = CompletionKind.expansionEditing;
}
return new Completion(name, sort, text, additionalInfo, insertionPoint + 1, suffixPoint, kind, prefix, suffix);
}
use of org.spoofax.interpreter.terms.IStrategoAppl 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;
}
Aggregations