package jetbrains.mps.ide.ui.finders; /*Generated by MPS */ import jetbrains.mps.ide.findusages.findalgorithm.finders.BaseFinder; import jetbrains.mps.ide.findusages.findalgorithm.finders.IFinder; import java.util.Set; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.ide.findusages.model.SearchResults; import jetbrains.mps.ide.findusages.model.SearchQuery; import org.jetbrains.mps.openapi.util.ProgressMonitor; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SModuleReference; import java.util.Collection; import jetbrains.mps.util.IterableUtil; import java.util.HashSet; import org.jetbrains.mps.openapi.util.SubProgressKind; import jetbrains.mps.project.Solution; import jetbrains.mps.smodel.Language; import jetbrains.mps.project.DevKit; import jetbrains.mps.smodel.Generator; import jetbrains.mps.ide.findusages.model.SearchResult; import org.jetbrains.mps.openapi.module.SDependency; import org.jetbrains.mps.openapi.module.SDependencyScope; import jetbrains.mps.smodel.SModelStereotype; import java.util.LinkedHashSet; import org.jetbrains.mps.openapi.model.SModelReference; import jetbrains.mps.smodel.SModelOperations; import jetbrains.mps.smodel.SModelInternal; /** * In fact, ModuleDependencyFinder, looks up given module as a dependency in other modules and their models. */ public class ModuleUsagesFinder extends BaseFinder implements IFinder { /*package*/ static final String USED_BY = "used by"; private static final String DEPENDENT_MODULES = "dependent modules"; private static final String RUNTIME_MODULES = "runtime modules"; private static final String EXTENDING_LANGUAGES = "extending languages"; private static final String EXTENDING_GENERATORS = "extending generators"; /** * valid during find() only */ private Set<SModel> myModels2Visit; public ModuleUsagesFinder() { } @Override public String getDescription() { return "Module Usages"; } @Override public SearchResults find(SearchQuery query, ProgressMonitor monitor) { SearchResults searchResults = new SearchResults(); Object value = query.getObjectHolder().getObject(); SModule searchedModule = null; SModuleReference searchedModuleRef = null; if (value instanceof SModule) { searchedModule = ((SModule) value); searchedModuleRef = searchedModule.getModuleReference(); } else if (value instanceof SModuleReference) { searchedModuleRef = (SModuleReference) value; searchedModule = query.getScope().resolve(searchedModuleRef); } if (searchedModuleRef == null) { return searchResults; } searchResults.getSearchedNodes().add(searchedModuleRef); Collection<SModule> modules = IterableUtil.asCollection(query.getScope().getModules()); myModels2Visit = new HashSet<SModel>(IterableUtil.asCollection(query.getScope().getModels())); monitor.start("", 2); ProgressMonitor subTask = monitor.subTask(1, SubProgressKind.REPLACING); subTask.start("Looking up uses in modules", modules.size()); for (SModule module : modules) { if (monitor.isCanceled()) { return searchResults; } if (module instanceof Solution) { collectUsagesInSolution(searchedModuleRef, (Solution) module, searchResults); } else if (module instanceof Language) { collectUsagesInLanguage(searchedModuleRef, (Language) module, searchResults); } else if (module instanceof DevKit) { collectUsagesInDevKit(searchedModuleRef, (DevKit) module, searchResults); } else if (module instanceof Generator) { collectUsagesInGenerator(searchedModuleRef, (Generator) module, searchResults); } subTask.advance(1); } subTask = monitor.subTask(1, SubProgressKind.REPLACING); if (searchedModule != null) { final DevKit searchedDevkit; int steps = myModels2Visit.size(); if (searchedModule instanceof DevKit) { searchedDevkit = (DevKit) searchedModule; steps *= 2; } else { searchedDevkit = null; } subTask.start("Looking up uses in models", steps); ModuleUsagesFinder.ModuleUseInModel f = new ModuleUsagesFinder.ModuleUseInModel(searchedModule, searchResults); for (SModel model : myModels2Visit) { f.collect(model); subTask.advance(1); } if (searchedDevkit != null) { ModuleUsagesFinder.DevKitUseInModel f2 = new ModuleUsagesFinder.DevKitUseInModel(searchedDevkit, searchResults); for (SModel model : myModels2Visit) { f2.collect(model); subTask.advance(1); } } } monitor.done(); myModels2Visit = null; return searchResults; } /*package*/ void collectUsagesInSolution(SModuleReference searchModuleRef, Solution solution, SearchResults searchResults) { if (getDeclaredDependenciesTargets(solution).contains(searchModuleRef)) { searchResults.add(new SearchResult<Solution>(solution, DEPENDENT_MODULES)); collectUsagesInModels(solution); } } /*package*/ void collectUsagesInLanguage(SModuleReference searchModuleRef, Language language, SearchResults searchResults) { boolean used = false; if (language.getExtendedLanguageRefs().contains(searchModuleRef)) { used = true; searchResults.add(new SearchResult<Language>(language, EXTENDING_LANGUAGES)); } if (getDeclaredDependenciesTargets(language).contains(searchModuleRef)) { used = true; searchResults.add(new SearchResult<Language>(language, DEPENDENT_MODULES)); } if (language.getRuntimeModulesReferences().contains(searchModuleRef)) { used = true; searchResults.add(new SearchResult<Language>(language, RUNTIME_MODULES)); } if (used) { collectUsagesInModels(language); } } /*package*/ void collectUsagesInGenerator(SModuleReference searchModuleRef, Generator generator, SearchResults searchResults) { boolean depExtends = false; boolean depDesign = false; boolean depRegular = false; for (SDependency dep : findDependencies(generator, searchModuleRef)) { if (dep.getScope() == SDependencyScope.EXTENDS) { depExtends = true; } else if (dep.getScope() == SDependencyScope.DESIGN) { depDesign = true; } else { depRegular = true; } } if (depExtends) { searchResults.add(new SearchResult<Generator>(generator, EXTENDING_GENERATORS)); } if (depDesign) { searchResults.add(new SearchResult<Generator>(generator, DEPENDENT_MODULES)); } if (depRegular) { searchResults.add(new SearchResult<Generator>(generator, DEPENDENT_MODULES)); } if (depExtends || depRegular || depDesign) { collectUsagesInModels(generator); } } /*package*/ void collectUsagesInDevKit(SModuleReference searchModuleRef, DevKit devKit, SearchResults searchResults) { if (getDeclaredDependenciesTargets(devKit).contains(searchModuleRef)) { searchResults.add(new SearchResult<DevKit>(devKit, DEPENDENT_MODULES)); } } /*package*/ static Set<SModuleReference> getDeclaredDependenciesTargets(SModule module) { Set<SModuleReference> result = new HashSet<SModuleReference>(); for (SDependency dep : module.getDeclaredDependencies()) { result.add(dep.getTargetModule()); } return result; } private void collectUsagesInModels(SModule owner) { for (SModel model : owner.getModels()) { if (!((SModelStereotype.isUserModel(model)))) { continue; } myModels2Visit.add(model); } } private static Set<SDependency> findDependencies(SModule from, SModuleReference to) { // FIXME nice candidate to move into SModule (along with findDependencies(SDependencyKind) LinkedHashSet<SDependency> rv = new LinkedHashSet<SDependency>(); for (SDependency dep : from.getDeclaredDependencies()) { if (dep.getTargetModule().equals(to)) { rv.add(dep); } } return rv; } /** * Models have imports, pointing to other models with SModelReference. * We need to find out whether these model references point to any model of a given module. * One approach is to get SModuleReference from SModelReference, another is to know all module's models * and match against their references. Former approach doesn't work as few model reference are capable of * telling their module reference. */ private static class ModuleUseInModel { private final SearchResults mySearchResults; private final Set<SModelReference> myModelsToFind; public ModuleUseInModel(SModule toFind, SearchResults toPopulate) { myModelsToFind = new HashSet<SModelReference>(); for (SModel m : toFind.getModels()) { myModelsToFind.add(m.getReference()); } mySearchResults = toPopulate; } public void collect(SModel model) { for (SModelReference i : SModelOperations.getImportedModelUIDs(model)) { if (myModelsToFind.contains(i)) { mySearchResults.add(new SearchResult<SModel>(model, ModuleUsagesFinder.USED_BY)); break; } } } } private static class DevKitUseInModel { private final SearchResults mySearchResults; private final SModuleReference myDevKitToFind; public DevKitUseInModel(DevKit toFind, SearchResults toPopulate) { myDevKitToFind = toFind.getModuleReference(); mySearchResults = toPopulate; } public void collect(SModel model) { if (model instanceof SModelInternal) { if (((SModelInternal) model).importedDevkits().contains(myDevKitToFind)) { mySearchResults.add(new SearchResult<SModel>(model, USED_BY)); } } } } }