/******************************************************************************* * 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); } }