Search in sources :

Example 6 with ITokens

use of org.spoofax.jsglr.client.imploder.ITokens in project spoofax by metaborg.

the class JSGLRCompletionService method calculateSuffix.

private String calculateSuffix(int cursorPosition, IStrategoTerm proposalTerm) {
    String suffix = "";
    ITokens tokenizer = proposalTerm.getAttachment(ImploderAttachment.TYPE).getLeftToken().getTokenizer();
    IToken leftToken = proposalTerm.getAttachment(ImploderAttachment.TYPE).getLeftToken();
    IToken rightToken = proposalTerm.getAttachment(ImploderAttachment.TYPE).getRightToken();
    IToken current = rightToken;
    int startOffsetSuffix = Integer.MAX_VALUE;
    while (current.getStartOffset() >= cursorPosition && current != leftToken) {
        if (startOffsetSuffix > current.getStartOffset()) {
            suffix = current.toString() + suffix;
            startOffsetSuffix = current.getStartOffset();
        }
        current = tokenizer.getTokenAt(current.getIndex() - 1);
    }
    return suffix;
}
Also used : IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) ITokens(org.spoofax.jsglr.client.imploder.ITokens)

Example 7 with ITokens

use of org.spoofax.jsglr.client.imploder.ITokens 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);
}
Also used : SourceLocation(org.metaborg.core.source.SourceLocation) ISourceLocation(org.metaborg.core.source.ISourceLocation) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IToken(org.spoofax.jsglr.client.imploder.IToken) MetaborgException(org.metaborg.core.MetaborgException) ISourceRegion(org.metaborg.core.source.ISourceRegion) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) IStrategoList(org.spoofax.interpreter.terms.IStrategoList) FileObject(org.apache.commons.vfs2.FileObject) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) ITokens(org.spoofax.jsglr.client.imploder.ITokens) Nullable(javax.annotation.Nullable)

Example 8 with ITokens

use of org.spoofax.jsglr.client.imploder.ITokens in project spoofax by metaborg.

the class JSGLRCompletionService method createCompletionInsertBefore.

private ICompletion createCompletionInsertBefore(String name, String text, String additionalInfo, StrategoAppl change) {
    final StrategoTerm oldNode = (StrategoTerm) change.getSubterm(0);
    final StrategoTerm newNode = (StrategoTerm) change.getSubterm(1);
    // expect two terms and 1st should be an element of a list
    final StrategoTerm oldList = (StrategoTerm) ParentAttachment.getParent(oldNode);
    if (change.getSubtermCount() != 2 || !(oldNode instanceof IStrategoAppl) || !(newNode instanceof IStrategoList) || !(oldList instanceof IStrategoList)) {
        return null;
    }
    final String sort = ImploderAttachment.getSort(oldNode);
    int insertionPoint, suffixPoint;
    ITokens tokenizer = ImploderAttachment.getTokenizer(oldNode);
    IStrategoTerm[] subterms = oldList.getAllSubterms();
    int indexOfElement;
    for (indexOfElement = 0; indexOfElement < subterms.length; indexOfElement++) {
        if (subterms[indexOfElement] == oldNode)
            break;
    }
    // if inserted element is first (only two elements)
    if (indexOfElement == 0) {
        // insert after the first non-layout token before the leftmost token of the
        // completion node
        final ImploderAttachment oldNodeIA = oldNode.getAttachment(ImploderAttachment.TYPE);
        int tokenPosition = oldNodeIA.getLeftToken().getIndex() - 1 > 0 ? oldNodeIA.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();
    } 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(indexOfElement - 1);
        insertionPoint = elementBefore.getAttachment(ImploderAttachment.TYPE).getRightToken().getEndOffset();
    }
    // if completion is separated by a newline, preserve indentation of the subsequent node
    // else separation follows from the grammar
    String separator = "";
    for (int i = text.length() - 1; i >= 0; i--) {
        if (text.charAt(i) == additionalInfo.charAt(additionalInfo.length() - 1)) {
            break;
        }
        separator = text.charAt(i) + separator;
    }
    IToken checkToken = oldNode.getAttachment(ImploderAttachment.TYPE).getLeftToken();
    int checkTokenIdx = oldNode.getAttachment(ImploderAttachment.TYPE).getLeftToken().getIndex();
    suffixPoint = insertionPoint;
    if (separator.contains("\n")) {
        for (; checkTokenIdx >= 0; checkTokenIdx--) {
            checkToken = tokenizer.getTokenAt(checkTokenIdx);
            if (tokenizer.toString(checkToken, checkToken).contains("\n")) {
                break;
            }
            suffixPoint = checkToken.getStartOffset();
        }
    } else {
        suffixPoint = checkToken.getStartOffset();
    }
    return new Completion(name, sort, text, additionalInfo, insertionPoint + 1, suffixPoint, CompletionKind.expansion);
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) ICompletion(org.metaborg.core.completion.ICompletion) Completion(org.metaborg.core.completion.Completion) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) StrategoTerm(org.spoofax.terms.StrategoTerm) IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) IStrategoList(org.spoofax.interpreter.terms.IStrategoList) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) ImploderAttachment(org.spoofax.jsglr.client.imploder.ImploderAttachment) ListImploderAttachment(org.spoofax.jsglr.client.imploder.ListImploderAttachment) ITokens(org.spoofax.jsglr.client.imploder.ITokens)

Example 9 with ITokens

use of org.spoofax.jsglr.client.imploder.ITokens in project spoofax by metaborg.

the class JSGLRCompletionService method calculatePrefix.

private String calculatePrefix(int cursorPosition, IStrategoTerm proposalTerm) {
    String prefix = "";
    ITokens tokenizer = proposalTerm.getAttachment(ImploderAttachment.TYPE).getLeftToken().getTokenizer();
    IToken leftToken = proposalTerm.getAttachment(ImploderAttachment.TYPE).getLeftToken();
    IToken rightToken = proposalTerm.getAttachment(ImploderAttachment.TYPE).getRightToken();
    IToken current = leftToken;
    int endOffsetPrefix = Integer.MIN_VALUE;
    while (current.getEndOffset() < cursorPosition && current != rightToken) {
        if (endOffsetPrefix < current.getEndOffset()) {
            prefix += current.toString();
            endOffsetPrefix = current.getEndOffset();
        }
        current = tokenizer.getTokenAt(current.getIndex() + 1);
    }
    return prefix;
}
Also used : IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) ITokens(org.spoofax.jsglr.client.imploder.ITokens)

Example 10 with ITokens

use of org.spoofax.jsglr.client.imploder.ITokens in project spoofax by metaborg.

the class JSGLRCompletionService method createCompletionReplaceTermFixing.

private ICompletion createCompletionReplaceTermFixing(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);
    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 ((tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPosition).getKind() == IToken.TK_ERROR) && tokenPosition > 0) tokenPosition--;
        insertionPoint = tokenizer.getTokenAt(tokenPosition).getEndOffset();
    } else {
        // if not, do a regular replacement
        insertionPoint = oldNodeIA.getLeftToken().getStartOffset() - 1;
    }
    // insert after the first non-layout token
    int tokenPositionEnd = oldNodeIA.getRightToken().getIndex();
    while ((tokenizer.getTokenAt(tokenPositionEnd).getEndOffset() < tokenizer.getTokenAt(tokenPositionEnd).getStartOffset() || tokenizer.getTokenAt(tokenPositionEnd).getKind() == IToken.TK_LAYOUT || tokenizer.getTokenAt(tokenPositionEnd).getKind() == IToken.TK_ERROR) && tokenPositionEnd > 0) tokenPositionEnd--;
    suffixPoint = tokenizer.getTokenAt(tokenPositionEnd).getEndOffset() + 1;
    CompletionKind kind;
    if (completionKind.equals("recovery")) {
        kind = CompletionKind.recovery;
    } else {
        kind = CompletionKind.expansion;
    }
    return new Completion(name, sort, text, additionalInfo, insertionPoint + 1, suffixPoint, kind, prefix, suffix);
}
Also used : ICompletion(org.metaborg.core.completion.ICompletion) Completion(org.metaborg.core.completion.Completion) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) StrategoTerm(org.spoofax.terms.StrategoTerm) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) ImploderAttachment(org.spoofax.jsglr.client.imploder.ImploderAttachment) ListImploderAttachment(org.spoofax.jsglr.client.imploder.ListImploderAttachment) CompletionKind(org.metaborg.core.completion.CompletionKind) ITokens(org.spoofax.jsglr.client.imploder.ITokens)

Aggregations

ITokens (org.spoofax.jsglr.client.imploder.ITokens)14 IStrategoString (org.spoofax.interpreter.terms.IStrategoString)10 IStrategoTerm (org.spoofax.interpreter.terms.IStrategoTerm)9 IToken (org.spoofax.jsglr.client.imploder.IToken)9 ImploderAttachment (org.spoofax.jsglr.client.imploder.ImploderAttachment)8 Completion (org.metaborg.core.completion.Completion)7 ICompletion (org.metaborg.core.completion.ICompletion)7 IStrategoAppl (org.spoofax.interpreter.terms.IStrategoAppl)7 ListImploderAttachment (org.spoofax.jsglr.client.imploder.ListImploderAttachment)7 StrategoTerm (org.spoofax.terms.StrategoTerm)7 CompletionKind (org.metaborg.core.completion.CompletionKind)5 IStrategoList (org.spoofax.interpreter.terms.IStrategoList)5 ISourceRegion (org.metaborg.core.source.ISourceRegion)2 Nullable (javax.annotation.Nullable)1 FileObject (org.apache.commons.vfs2.FileObject)1 MetaborgException (org.metaborg.core.MetaborgException)1 ISourceLocation (org.metaborg.core.source.ISourceLocation)1 SourceLocation (org.metaborg.core.source.SourceLocation)1 ICategory (org.metaborg.core.style.ICategory)1 IRegionCategory (org.metaborg.core.style.IRegionCategory)1