package jetbrains.mps.editor.runtime.impl; /*Generated by MPS */ import com.intellij.openapi.components.ApplicationComponent; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.util.Map; import jetbrains.mps.smodel.adapter.ids.SLanguageId; import java.util.List; import jetbrains.mps.openapi.editor.cells.KeyMap; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.smodel.language.LanguageRegistry; import jetbrains.mps.ide.MPSCoreComponents; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.language.SLanguage; import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; import org.jetbrains.mps.openapi.module.SModule; import java.util.Collections; import jetbrains.mps.smodel.language.LanguageRuntime; import org.jetbrains.annotations.NonNls; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.smodel.behaviour.BHReflection; import jetbrains.mps.core.aspects.behaviour.SMethodTrimmedId; import org.apache.log4j.Level; import com.intellij.openapi.application.ApplicationManager; import jetbrains.mps.smodel.language.LanguageRegistryListener; public class LanguagesKeymapManager implements ApplicationComponent { private static final Logger LOG = LogManager.getLogger(LanguagesKeymapManager.class); private final Map<SLanguageId, List<KeyMap>> myLanguagesToKeyMaps = MapSequence.fromMap(new HashMap<SLanguageId, List<KeyMap>>()); private final LanguagesKeymapManager.LanguageLoadListener myListener = new LanguagesKeymapManager.LanguageLoadListener(); private final LanguageRegistry myLanguageRegistry; public LanguagesKeymapManager(MPSCoreComponents coreComponents) { myLanguageRegistry = coreComponents.getPlatform().findComponent(LanguageRegistry.class); } public List<KeyMap> getKeyMapsForLanguage(@NotNull SLanguage l) { SLanguageId languageId = MetaIdHelper.getLanguage(l); if (!(MapSequence.fromMap(myLanguagesToKeyMaps).containsKey(languageId))) { // FIXME this is a hack, until we expose KeyMaps as part of editor aspect (or standalone aspect), we need name from CellKeyMapDeclaration node SModule sourceModule = l.getSourceModule(); if (sourceModule == null) { return Collections.<KeyMap>emptyList(); } LanguageRuntime languageRuntime = myLanguageRegistry.getLanguage(languageId); if (languageRuntime == null) { return Collections.<KeyMap>emptyList(); } MapSequence.fromMap(myLanguagesToKeyMaps).put(languageId, loadLanguageKeyMaps(languageRuntime, sourceModule)); } return MapSequence.fromMap(myLanguagesToKeyMaps).get(languageId); } @Override public void initComponent() { myLanguageRegistry.addRegistryListener(myListener); } @Override public void disposeComponent() { myLanguageRegistry.removeRegistryListener(myListener); } @NonNls @NotNull @Override public String getComponentName() { return "Language KeyMap Manager"; } private void clearCaches() { MapSequence.fromMap(myLanguagesToKeyMaps).clear(); } private List<KeyMap> loadLanguageKeyMaps(LanguageRuntime languageRuntime, SModule languageSource) { SModel editorModelDescriptor = SModuleOperations.getAspect(languageSource, "editor"); SModel editorModel = (editorModelDescriptor != null ? editorModelDescriptor : null); if (editorModel == null) { return Collections.<KeyMap>emptyList(); } List<SNode> declarations = SModelOperations.roots(editorModel, MetaAdapterFactory.getConcept(0x18bc659203a64e29L, 0xa83a7ff23bde13baL, 0xfbc216b31bL, "jetbrains.mps.lang.editor.structure.CellKeyMapDeclaration")); if (ListSequence.fromList(declarations).isEmpty()) { return Collections.<KeyMap>emptyList(); } List<KeyMap> keyMaps = ListSequence.fromList(new ArrayList<KeyMap>()); for (SNode keyMapDeclaration : ListSequence.fromList(declarations)) { try { Class<KeyMap> keyMapClass = (Class<KeyMap>) languageRuntime.getClass().getClassLoader().loadClass(((String) BHReflection.invoke(keyMapDeclaration, SMethodTrimmedId.create("getFqName", null, "hEwIO9y")))); KeyMap keyMap = keyMapClass.newInstance(); if (keyMap.isApplicableToEveryModel()) { ListSequence.fromList(keyMaps).addElement(keyMap); } } catch (ClassNotFoundException ex) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("Failed to instantiate keymap", ex); } } catch (InstantiationException e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Failed to instantiate keymap", e); } } catch (IllegalAccessException e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Failed to instantiate keymap", e); } } } return (ListSequence.fromList(keyMaps).isEmpty() ? Collections.<KeyMap>emptyList() : keyMaps); } /*package*/ void unregisterLanguageKeyMaps(LanguageRuntime lr) { MapSequence.fromMap(myLanguagesToKeyMaps).removeKey(lr.getId()); } public static LanguagesKeymapManager getInstance() { return ApplicationManager.getApplication().getComponent(LanguagesKeymapManager.class); } private class LanguageLoadListener implements LanguageRegistryListener { /*package*/ LanguageLoadListener() { } @Override public void afterLanguagesLoaded(Iterable<LanguageRuntime> iterable) { } @Override public void beforeLanguagesUnloaded(Iterable<LanguageRuntime> iterable) { for (LanguageRuntime lr : iterable) { unregisterLanguageKeyMaps(lr); } } } }