Search in sources :

Example 6 with IToken

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

the class JSGLRCompletionService method getLeftRecursiveTerms.

private Iterable<IStrategoTerm> getLeftRecursiveTerms(int position, Iterable<IStrategoTerm> terms, Map<IStrategoTerm, Boolean> leftRecursiveTerms) {
    Collection<IStrategoTerm> leftRecursive = Lists.newLinkedList();
    for (IStrategoTerm term : terms) {
        boolean isLeftRecursive = leftRecursiveTerms.containsKey(term);
        IToken left = ImploderAttachment.getLeftToken(term);
        IToken right = ImploderAttachment.getRightToken(term);
        if (isLeftRecursive && position > right.getEndOffset()) {
            leftRecursive.add(term);
        } else if (term instanceof IStrategoList || left.getStartOffset() > right.getEndOffset()) {
            continue;
        } else {
            break;
        }
    }
    return leftRecursive;
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoList(org.spoofax.interpreter.terms.IStrategoList)

Example 7 with IToken

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

the class JSGLRCompletionService method getOptionals.

@Nullable
private Iterable<IStrategoTerm> getOptionals(final Iterable<IStrategoTerm> terms, Map<IStrategoTerm, Boolean> leftRecursiveTerms, Map<IStrategoTerm, Boolean> rightRecursiveTerms) {
    Collection<IStrategoTerm> optionals = Lists.newLinkedList();
    for (IStrategoTerm term : terms) {
        IToken left = ImploderAttachment.getLeftToken(term);
        IToken right = ImploderAttachment.getRightToken(term);
        if (!(term instanceof IStrategoList) && left.getStartOffset() > right.getEndOffset()) {
            optionals.add(term);
        } else if (term instanceof IStrategoList) {
            continue;
        // if term is not nullable, nor a list nor left or right recursive stop the search
        } else {
            boolean isLeftRecursive = leftRecursiveTerms.containsKey(term);
            boolean isRightRecursive = rightRecursiveTerms.containsKey(term);
            if (!isLeftRecursive && !isRightRecursive) {
                break;
            }
        }
    }
    return optionals;
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoList(org.spoofax.interpreter.terms.IStrategoList) Nullable(javax.annotation.Nullable)

Example 8 with IToken

use of org.spoofax.jsglr.client.imploder.IToken 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);
}
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) IToken(org.spoofax.jsglr.client.imploder.IToken) 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)

Example 9 with IToken

use of org.spoofax.jsglr.client.imploder.IToken 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 10 with IToken

use of org.spoofax.jsglr.client.imploder.IToken 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)

Aggregations

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