use of org.spoofax.jsglr.client.imploder.ImploderAttachment in project spoofax by metaborg.
the class JSGLRCompletionService method findTopMostCompletionNode.
private StrategoTerm findTopMostCompletionNode(StrategoTerm newNode) {
StrategoTerm parent = (StrategoTerm) ParentAttachment.getParent(newNode);
if (parent == null) {
return newNode;
}
ImploderAttachment ia = ImploderAttachment.get(parent);
if (ia.getSort() == null || ia.isNestedCompletion()) {
return newNode;
}
return findTopMostCompletionNode(parent);
}
use of org.spoofax.jsglr.client.imploder.ImploderAttachment in project spoofax by metaborg.
the class JSGLRCompletionService method createCompletionInsertBeforeFixing.
private ICompletion createCompletionInsertBeforeFixing(String name, String text, String additionalInfo, String prefix, String suffix, StrategoAppl change, String completionKind) {
// expect two terms and 1st should be an element of a list
final StrategoTerm oldNode = (StrategoTerm) change.getSubterm(0);
final StrategoTerm newNode = (StrategoTerm) change.getSubterm(1);
final StrategoTerm oldList = (StrategoTerm) ParentAttachment.getParent(oldNode);
if (change.getSubtermCount() != 2 || !(oldNode instanceof IStrategoAppl) || !(newNode instanceof IStrategoAppl) || !(oldList instanceof IStrategoList)) {
return null;
}
final String sort = ImploderAttachment.getSort(oldNode);
int insertionPoint, suffixPoint;
IStrategoTerm[] subterms = ((IStrategoList) oldList).getAllSubterms();
int indexOfCompletion;
for (indexOfCompletion = 0; indexOfCompletion < subterms.length; indexOfCompletion++) {
if (subterms[indexOfCompletion] == oldNode)
break;
}
// if inserted element is first (only two elements)
if (indexOfCompletion == 1) {
// insert after the first non-layout token before the leftmost token of the list
ITokens tokenizer = ImploderAttachment.getTokenizer(oldList);
// to avoid keeping duplicate tokens due to ambiguity
IStrategoTerm topMostAmbOldList = findTopMostAmbNode(oldList);
final ImploderAttachment oldListIA = topMostAmbOldList.getAttachment(ImploderAttachment.TYPE);
int tokenPosition = oldListIA.getLeftToken().getIndex() - 1 > 0 ? oldListIA.getLeftToken().getIndex() - 1 : 0;
while ((checkEmptyOffset(tokenizer.getTokenAt(tokenPosition)) || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR) && tokenPosition > 0) tokenPosition--;
insertionPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset();
} else {
// if inserted element is not first
// insert after at end offset of the rightmost token of the element before the completion
StrategoTerm elementBefore = (StrategoTerm) oldList.getSubterm(indexOfCompletion - 2);
insertionPoint = elementBefore.getAttachment(ImploderAttachment.TYPE).getRightToken().getEndOffset();
}
// suffix point should be the first token of the next element
suffixPoint = oldNode.getAttachment(ImploderAttachment.TYPE).getLeftToken().getStartOffset();
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.jsglr.client.imploder.ImploderAttachment in project spoofax by metaborg.
the class JSGLRCompletionService method findCompletionTermInsideNested.
private Collection<IStrategoTerm> findCompletionTermInsideNested(final 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() && !term.equals(ast)) {
return false;
}
if (ia.isCompletion()) {
completionTerms.add(term);
return false;
}
return true;
}
};
StrategoTermVisitee.topdown(visitor, ast);
return completionTerms;
}
use of org.spoofax.jsglr.client.imploder.ImploderAttachment in project spoofax by metaborg.
the class JSGLRCompletionService method createCompletionInsertAtEndFixing.
private ICompletion createCompletionInsertAtEndFixing(String name, String text, String additionalInfo, String prefix, String suffix, StrategoAppl change, String completionKind) {
final StrategoTerm oldNode = (StrategoTerm) change.getSubterm(0);
final StrategoTerm newNode = (StrategoTerm) change.getSubterm(1);
final StrategoTerm oldNodeTopMostAmb = findTopMostAmbNode(oldNode);
if (change.getSubtermCount() != 2 || !(oldNode instanceof IStrategoList) || !(newNode instanceof IStrategoAppl)) {
return null;
}
final String sort = ImploderAttachment.getElementSort(oldNode);
int insertionPoint, suffixPoint;
ITokens tokenizer = ImploderAttachment.getTokenizer(oldNodeTopMostAmb);
final ImploderAttachment oldNodeIA = oldNodeTopMostAmb.getAttachment(ImploderAttachment.TYPE);
// insert after the first non-layout token before the leftmost token of the completion node
if (((IStrategoList) oldNode).size() == 1) {
int tokenPosition = oldNodeIA.getLeftToken().getIndex() - 1 > 0 ? oldNodeIA.getLeftToken().getIndex() - 1 : 0;
while (tokenPosition > 0 && (checkEmptyOffset(tokenizer.getTokenAt(tokenPosition)) || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR)) tokenPosition--;
insertionPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset();
} else {
// if list is not empty
// insert after at end offset of the rightmost token of the element before the completion
StrategoTerm elementBefore = (StrategoTerm) oldNode.getSubterm(oldNode.getAllSubterms().length - 2);
insertionPoint = elementBefore.getAttachment(ImploderAttachment.TYPE).getRightToken().getEndOffset();
}
// keep all the characters after the last non-layout token
int tokenPosition = oldNodeIA.getRightToken().getIndex();
while (tokenizer.getTokenAt(tokenPosition).getEndOffset() < tokenizer.getTokenAt(tokenPosition).getStartOffset() || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT && tokenPosition > 0) tokenPosition--;
suffixPoint = tokenizer.getTokenAt(tokenPosition).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.jsglr.client.imploder.ImploderAttachment in project spoofax by metaborg.
the class CategorizerService method categorize.
@Override
public Iterable<IRegionCategory<IStrategoTerm>> categorize(ILanguageImpl language, ISpoofaxParseUnit parseResult) {
final List<IRegionCategory<IStrategoTerm>> regionCategories = Lists.newLinkedList();
if (!parseResult.valid()) {
return regionCategories;
}
final StylerFacet facet = language.facet(StylerFacet.class);
if (facet == null) {
logger.error("Cannot categorize input of {}, it does not have a styler facet", language);
// GTODO: throw exception instead
return regionCategories;
}
final ImploderAttachment rootImploderAttachment = ImploderAttachment.get(parseResult.ast());
if (rootImploderAttachment == null) {
logger.error("Cannot categorize input {} of {}, it does not have an imploder attachment", parseResult, language);
// GTODO: throw exception instead
return regionCategories;
}
final ITokens tokenizer = rootImploderAttachment.getLeftToken().getTokenizer();
if (tokenizer == null) {
logger.error("Cannot categorize input {} of {}, it does not have a tokenizer", parseResult, language);
// GTODO: throw exception instead
return regionCategories;
}
final int tokenCount = tokenizer.getTokenCount();
int offset = -1;
for (int i = 0; i < tokenCount; ++i) {
final IToken token = tokenizer.getTokenAt(i);
if (tokenizer.isAmbigous() && token.getStartOffset() < offset) {
// In case of ambiguities, tokens inside the ambiguity are duplicated, ignore.
continue;
}
if (token.getStartOffset() > token.getEndOffset()) {
// Indicates an invalid region. Empty lists have regions like this.
continue;
}
if (offset >= token.getStartOffset()) {
// Duplicate region, skip.
continue;
}
offset = token.getEndOffset();
final ICategory category = category(facet, token);
if (category != null) {
final ISourceRegion region = JSGLRSourceRegionFactory.fromToken(token);
final IStrategoTerm term = (IStrategoTerm) token.getAstNode();
regionCategories.add(new RegionCategory<>(region, category, term));
}
}
return regionCategories;
}
Aggregations