de.se_rwth.monticoreeditor.Resolving.java Source code

Java tutorial

Introduction

Here is the source code for de.se_rwth.monticoreeditor.Resolving.java

Source

/*******************************************************************************
 * MontiCore Language Workbench
 * Copyright (c) 2015, 2016, MontiCore, All rights reserved.
 *  
 * This project is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this project. If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package de.se_rwth.monticoreeditor;

import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

import org.eclipse.core.resources.IProject;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import de.monticore.ast.ASTNode;
import de.monticore.codegen.mc2cd.MCGrammarSymbolTableHelper;
import de.monticore.grammar.grammar._ast.ASTMCGrammar;
import de.monticore.grammar.grammar._ast.ASTNonTerminal;
import de.monticore.grammar.grammar._ast.ASTNonTerminalSeparator;
import de.monticore.symboltable.Symbol;
import de.monticore.utils.ASTNodes;
import de.se_rwth.langeditor.modelstates.ModelState;
import de.se_rwth.langeditor.util.ResourceLocator;

class Resolving {

    private Map<IProject, ModelStatesInProject> modelStatesInProjects = new HashMap<>();

    private Map<IProject, SymbolTableMaintainer> symbolTableMaintainers = new HashMap<>();

    void buildProject(IProject project, ImmutableSet<ModelState> modelStates, ImmutableList<Path> modelPath) {
        ModelStatesInProject astMapper = getModelStatesInProject(project);
        modelStates.forEach(astMapper::acceptModelState);
        SymbolTableMaintainer symbolTableMaintainer = getSymbolTableMaintainer(project, modelPath);
        modelStates.forEach(symbolTableMaintainer::acceptModelState);
    }

    void buildModel(ModelState modelState) {
        ModelStatesInProject modelStatesInProject = getModelStatesInProject(modelState.getProject());
        modelStatesInProject.acceptModelState(modelState);

        SymbolTableMaintainer maintainer = getSymbolTableMaintainer(modelState.getProject());
        maintainer.acceptModelState(modelState);
    }

    Optional<Supplier<Optional<ASTNode>>> createResolver(ASTNode astNode) {
        Optional<Supplier<Optional<ASTNode>>> resolveByNonTerminal = getEnclosingASTNode(astNode,
                ASTNonTerminal.class).map(nonTerminal -> createSupplier(nonTerminal, nonTerminal.getName()));
        if (resolveByNonTerminal.isPresent()) {
            return resolveByNonTerminal;
        }

        Optional<ASTNonTerminalSeparator> nonTerminalSep = getEnclosingASTNode(astNode,
                ASTNonTerminalSeparator.class);
        if (nonTerminalSep.isPresent()) {
            Optional<ASTMCGrammar> grammarNode = getEnclosingASTNode(nonTerminalSep.get(), ASTMCGrammar.class);
            if (grammarNode.isPresent()) {
                return Optional.of(createSupplier(grammarNode.get(), nonTerminalSep.get().getName()));
            }
        }

        return Optional.empty();
    }

    private Supplier<Optional<ASTNode>> createSupplier(ASTNode astNode, String name) {
        return () -> MCGrammarSymbolTableHelper.resolveRule(astNode, name).flatMap(Symbol::getAstNode);
    }

    private <T extends ASTNode> Optional<T> getEnclosingASTNode(ASTNode astNode, Class<T> type) {
        Optional<ImmutableMap<ASTNode, ASTNode>> optionalChildToParentMap = modelStatesInProjects.values().stream()
                .flatMap(modelStates -> modelStates.getASTMCGrammars().stream()).map(ASTNodes::childToParentMap)
                .filter(childToParentMap -> childToParentMap.keySet().contains(astNode)).findFirst();
        return optionalChildToParentMap.map(childToParentMap -> {
            ASTNode enclosingASTNode = astNode;
            while (enclosingASTNode != null && !type.isInstance(enclosingASTNode)) {
                enclosingASTNode = childToParentMap.get(enclosingASTNode);
            }
            return enclosingASTNode;
        }).map(type::cast);
    }

    private ModelStatesInProject getModelStatesInProject(IProject project) {
        if (!modelStatesInProjects.containsKey(project)) {
            ModelStatesInProject astMapper = new ModelStatesInProject();
            modelStatesInProjects.put(project, astMapper);
        }
        return modelStatesInProjects.get(project);
    }

    private SymbolTableMaintainer getSymbolTableMaintainer(IProject project) {
        if (!symbolTableMaintainers.containsKey(project)) {
            SymbolTableMaintainer symbolTableMaintainer = new SymbolTableMaintainer(
                    getModelStatesInProject(project), ResourceLocator.assembleModelPath(project));
            symbolTableMaintainers.put(project, symbolTableMaintainer);
        }
        return symbolTableMaintainers.get(project);
    }

    private SymbolTableMaintainer getSymbolTableMaintainer(IProject project, ImmutableList<Path> modelPath) {
        if (!symbolTableMaintainers.containsKey(project)) {
            SymbolTableMaintainer symbolTableMaintainer = new SymbolTableMaintainer(
                    getModelStatesInProject(project), modelPath);
            symbolTableMaintainers.put(project, symbolTableMaintainer);
        }
        return symbolTableMaintainers.get(project);
    }

}