/* * Copyright 2003-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.idea.core.project; import com.intellij.facet.impl.ui.FacetEditorContextBase; import com.intellij.facet.ui.FacetEditorContext; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.idea.core.library.ModuleLibrariesUtil; import jetbrains.mps.project.AbstractModule; import jetbrains.mps.project.dependency.GlobalModuleDependenciesManager; import jetbrains.mps.project.dependency.GlobalModuleDependenciesManager.Deptype; import jetbrains.mps.project.dependency.UsedModulesCollector; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SModuleReference; import jetbrains.mps.smodel.BootstrapLanguages; import jetbrains.mps.smodel.Language; import jetbrains.mps.smodel.ModuleRepositoryFacade; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * User: shatalin * Date: 6/8/12 */ public abstract class ModuleRuntimeLibrariesImporter { private static final Logger LOG = Logger.getInstance(ModuleRuntimeLibrariesImporter.class); private Project myProject; private final Collection<? extends SModuleReference> myAddedModules; private final ModifiableRootModel myModifiableRootModel; private final LibrariesContainer myLibrariesContainer; public ModuleRuntimeLibrariesImporter(FacetEditorContext context, Collection<? extends SModuleReference> addedModules) { this(addedModules, context.getModifiableRootModel(), ((FacetEditorContextBase) context).getContainer()); myProject = context.getProject(); } public ModuleRuntimeLibrariesImporter(Module ideaModule, Collection<? extends SModuleReference> addedModules, ModifiableRootModel modifiableModel) { this(addedModules, modifiableModel, LibrariesContainerFactory.createContainer(ideaModule)); myProject = ideaModule.getProject(); } private ModuleRuntimeLibrariesImporter(Collection<? extends SModuleReference> addedModules, ModifiableRootModel modifiableModel, LibrariesContainer container) { myAddedModules = addedModules; myModifiableRootModel = modifiableModel; myLibrariesContainer = container; } public static void importForUsedLanguages(FacetEditorContext context, Collection<? extends SModuleReference> addedModules) { new UsedLanguagesImporter(context, addedModules).addMissingLibraries(); } public static void importForUsedLanguages(Module ideaModule, Collection<SModuleReference> addedModules, ModifiableRootModel modifiableModel) { new UsedLanguagesImporter(ideaModule, addedModules, modifiableModel).addMissingLibraries(); } public static void importForUsedModules(Module ideaModule, Collection<SModuleReference> addedModules, ModifiableRootModel modifiableModel) { new UsedModulesImporter(ideaModule, addedModules, modifiableModel).addMissingLibraries(); } public void addMissingLibraries() { Set<SModuleReference> alreadyImported = ModuleLibrariesUtil.getModules(ProjectHelper.getProjectRepository(myProject), myModifiableRootModel.getOrderEntries()); Collection<Library> projectLibs2Add = new HashSet<Library>(); for (SModule usedModule : collectRuntimeModules(myAddedModules)) { if (BootstrapLanguages.jdkRef().equals(usedModule.getModuleReference())) { continue; } if (alreadyImported.contains(usedModule.getModuleReference())) { continue; } // todo how to deal with sdk stubs? Library library = null; if (usedModule instanceof StubSolutionIdea) { library = StubSolutionIdea.findLibrary((StubSolutionIdea) usedModule); } else { library = ModuleLibrariesUtil.getOrCreateAutoLibrary((AbstractModule) usedModule, getProject(), myLibrariesContainer); } if (library != null) { projectLibs2Add.add(library); } } for (Library projectLibrary : projectLibs2Add) { myModifiableRootModel.addLibraryEntry(projectLibrary); } } private Project getProject() { return myLibrariesContainer.getProject(); } protected abstract Set<SModule> collectRuntimeModules(Collection<? extends SModuleReference> moduleReferences); private static class UsedLanguagesImporter extends ModuleRuntimeLibrariesImporter { public UsedLanguagesImporter(FacetEditorContext context, Collection<? extends SModuleReference> addedModules) { super(context, addedModules); } public UsedLanguagesImporter(Module ideaModule, Collection<SModuleReference> addedModules, ModifiableRootModel modifiableModel) { super(ideaModule, addedModules, modifiableModel); } @Override protected Set<SModule> collectRuntimeModules(Collection<? extends SModuleReference> moduleReferences) { Set<SModule> runtimeDependencies = new HashSet<SModule>(); UsedModulesCollector usedModulesCollector = new UsedModulesCollector(); for (SModuleReference moduleReference : moduleReferences) { Language language = ModuleRepositoryFacade.getInstance().getModule(moduleReference, Language.class); LOG.assertTrue(language != null, "Can not find language by reference " + moduleReference); collectRuntimeModules(runtimeDependencies, language, usedModulesCollector); } return runtimeDependencies; } private void collectRuntimeModules(Set<SModule> runtimeDependencies, Language language, UsedModulesCollector usedModulesCollector) { for (SModuleReference runtimeModuleReference : language.getRuntimeModulesReferences()) { SModule runtimeModule = ModuleRepositoryFacade.getInstance().getModule(runtimeModuleReference); if (runtimeModule != null) { collectRuntimeDependencies(runtimeModule, runtimeDependencies, usedModulesCollector); } } } private void collectRuntimeDependencies(SModule module, Set<SModule> result, UsedModulesCollector usedModulesCollector) { // todo: extract some other methods in GlobalModuleDependenciesManager. Like getDependencies(Iterable<> addedModules, Iterable<> addedUsedModules, Deptype) if (result.contains(module)) { return; } result.add(module); for (SModule usedModule : usedModulesCollector.directlyUsedModules(module, Deptype.EXECUTE.reexportAll, Deptype.EXECUTE.runtimes)) { collectRuntimeDependencies(usedModule, result, usedModulesCollector); } } } private static class UsedModulesImporter extends ModuleRuntimeLibrariesImporter { public UsedModulesImporter(Module ideaModule, Collection<? extends SModuleReference> addedModules, ModifiableRootModel modifiableModel) { super(ideaModule, addedModules, modifiableModel); } @Override protected Set<SModule> collectRuntimeModules(Collection<? extends SModuleReference> moduleReferences) { Set<SModule> runtimeDependencies = new HashSet<SModule>(); for (SModuleReference moduleReference : moduleReferences) { SModule module = ModuleRepositoryFacade.getInstance().getModule(moduleReference); collectRuntimeModules(runtimeDependencies, module); } return runtimeDependencies; } private void collectRuntimeModules(Set<SModule> runtimeDependencies, SModule module) { runtimeDependencies.add(module); runtimeDependencies.addAll(new GlobalModuleDependenciesManager(Collections.singleton(module)).getModules(Deptype.COMPILE)); } } }