Search in sources :

Example 36 with IStrategoTerm

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;
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) AStrategoTermVisitor(org.spoofax.terms.visitor.AStrategoTermVisitor) IStrategoTermVisitor(org.spoofax.terms.visitor.IStrategoTermVisitor) ImploderAttachment(org.spoofax.jsglr.client.imploder.ImploderAttachment) ListImploderAttachment(org.spoofax.jsglr.client.imploder.ListImploderAttachment)

Example 37 with IStrategoTerm

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;
}
Also used : ICompletion(org.metaborg.core.completion.ICompletion) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) HashMap(java.util.HashMap) HybridInterpreter(org.strategoxt.HybridInterpreter) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) IStrategoList(org.spoofax.interpreter.terms.IStrategoList) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) SourceRegion(org.metaborg.core.source.SourceRegion) ISourceRegion(org.metaborg.core.source.ISourceRegion) ILanguageImpl(org.metaborg.core.language.ILanguageImpl) FileObject(org.apache.commons.vfs2.FileObject) ILanguageComponent(org.metaborg.core.language.ILanguageComponent) ITermFactory(org.spoofax.interpreter.terms.ITermFactory)

Example 38 with IStrategoTerm

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);
}
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 39 with IStrategoTerm

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;
}
Also used : MenuAction(org.metaborg.core.menu.MenuAction) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) NamedGoal(org.metaborg.core.action.NamedGoal) EndNamedGoal(org.metaborg.core.action.EndNamedGoal) TransformActionFlags(org.metaborg.core.action.TransformActionFlags) EndNamedGoal(org.metaborg.core.action.EndNamedGoal) ITransformAction(org.metaborg.core.action.ITransformAction) IMenu(org.metaborg.core.menu.IMenu) Menu(org.metaborg.core.menu.Menu) Separator(org.metaborg.core.menu.Separator)

Example 40 with IStrategoTerm

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;
}
Also used : IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) IToken(org.spoofax.jsglr.client.imploder.IToken) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) Nullable(javax.annotation.Nullable)

Aggregations

IStrategoTerm (org.spoofax.interpreter.terms.IStrategoTerm)82 IStrategoString (org.spoofax.interpreter.terms.IStrategoString)31 FileObject (org.apache.commons.vfs2.FileObject)27 IStrategoAppl (org.spoofax.interpreter.terms.IStrategoAppl)25 MetaborgException (org.metaborg.core.MetaborgException)19 ITermFactory (org.spoofax.interpreter.terms.ITermFactory)17 HybridInterpreter (org.strategoxt.HybridInterpreter)17 IStrategoList (org.spoofax.interpreter.terms.IStrategoList)16 ILanguageImpl (org.metaborg.core.language.ILanguageImpl)15 Nullable (javax.annotation.Nullable)14 ISourceRegion (org.metaborg.core.source.ISourceRegion)12 ICompletion (org.metaborg.core.completion.ICompletion)11 IStrategoTuple (org.spoofax.interpreter.terms.IStrategoTuple)10 IOException (java.io.IOException)9 IProject (org.metaborg.core.project.IProject)9 IMessage (org.metaborg.core.messages.IMessage)8 IToken (org.spoofax.jsglr.client.imploder.IToken)8 IContext (org.metaborg.core.context.IContext)7 ILanguageComponent (org.metaborg.core.language.ILanguageComponent)7 ListImploderAttachment (org.spoofax.jsglr.client.imploder.ListImploderAttachment)7