| /* |
| * Copyright 2000-2014 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 com.intellij.ide.ui.search; |
| |
| import com.intellij.application.options.OptionsContainingConfigurable; |
| import com.intellij.ide.fileTemplates.FileTemplate; |
| import com.intellij.ide.fileTemplates.FileTemplateManager; |
| import com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable; |
| import com.intellij.ide.plugins.AvailablePluginsManagerMain; |
| import com.intellij.ide.plugins.PluginManagerConfigurable; |
| import com.intellij.openapi.actionSystem.ActionManager; |
| import com.intellij.openapi.actionSystem.AnAction; |
| import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.application.ApplicationStarterEx; |
| import com.intellij.openapi.application.ex.ApplicationEx; |
| import com.intellij.openapi.keymap.impl.ui.KeymapPanel; |
| import com.intellij.openapi.options.SearchableConfigurable; |
| import com.intellij.openapi.options.UnnamedConfigurable; |
| import com.intellij.openapi.options.ex.ConfigurableWrapper; |
| import com.intellij.openapi.project.ProjectManager; |
| import com.intellij.openapi.util.JDOMUtil; |
| import org.jdom.Document; |
| import org.jdom.Element; |
| import org.jetbrains.annotations.NonNls; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| /** |
| * Used by Installer's build buildSearchableOptions step. In order to run locally use TraverseUi configuration. |
| * Pass corresponding -Didea.platform.prefix=YOUR_IDE_PREFIX to vm options and choose main_YOUR_IDE module |
| */ |
| @SuppressWarnings({"CallToPrintStackTrace", "SynchronizeOnThis"}) |
| public class TraverseUIStarter extends ApplicationStarterEx { |
| @NonNls private static final String OPTIONS = "options"; |
| @NonNls private static final String CONFIGURABLE = "configurable"; |
| @NonNls private static final String ID = "id"; |
| @NonNls private static final String CONFIGURABLE_NAME = "configurable_name"; |
| @NonNls private static final String OPTION = "option"; |
| @NonNls private static final String NAME = "name"; |
| @NonNls private static final String PATH = "path"; |
| @NonNls private static final String HIT = "hit"; |
| |
| private String OUTPUT_PATH; |
| |
| @Override |
| public boolean isHeadless() { |
| return true; |
| } |
| |
| @Override |
| @NonNls |
| public String getCommandName() { |
| return "traverseUI"; |
| } |
| |
| @Override |
| public void premain(String[] args) { |
| OUTPUT_PATH = args[1]; |
| } |
| |
| @Override |
| public void main(String[] args){ |
| System.out.println("Starting searchable options index builder"); |
| try { |
| startup(); |
| } |
| catch (Throwable e) { |
| System.out.println("Searchable options index builder failed"); |
| e.printStackTrace(); |
| System.exit(-1); |
| } |
| } |
| |
| public void startup() throws IOException { |
| final HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options = |
| new HashMap<SearchableConfigurable, TreeSet<OptionDescription>>(); |
| SearchUtil.processProjectConfigurables(ProjectManager.getInstance().getDefaultProject(), options); |
| Element root = new Element(OPTIONS); |
| for (SearchableConfigurable configurable : options.keySet()) { |
| Element configurableElement = new Element(CONFIGURABLE); |
| final String id = configurable.getId(); |
| if (id == null) continue; |
| configurableElement.setAttribute(ID, id); |
| configurableElement.setAttribute(CONFIGURABLE_NAME, configurable.getDisplayName()); |
| final TreeSet<OptionDescription> sortedOptions = options.get(configurable); |
| writeOptions(configurableElement, sortedOptions); |
| if (configurable instanceof ConfigurableWrapper) { |
| final UnnamedConfigurable wrapped = ((ConfigurableWrapper)configurable).getConfigurable(); |
| if (wrapped instanceof SearchableConfigurable) { |
| configurable = (SearchableConfigurable)wrapped; |
| } |
| } |
| if (configurable instanceof KeymapPanel){ |
| processKeymap(configurableElement); |
| } else if (configurable instanceof OptionsContainingConfigurable){ |
| processOptionsContainingConfigurable((OptionsContainingConfigurable)configurable, configurableElement); |
| } else if (configurable instanceof PluginManagerConfigurable) { |
| final TreeSet<OptionDescription> descriptions = wordsToOptionDescriptors(Collections.singleton(AvailablePluginsManagerMain.MANAGE_REPOSITORIES)); |
| for (OptionDescription description : descriptions) { |
| append(null, AvailablePluginsManagerMain.MANAGE_REPOSITORIES, description.getOption(), configurableElement); |
| } |
| } else if (configurable instanceof AllFileTemplatesConfigurable) { |
| processFileTemplates(configurableElement); |
| } |
| root.addContent(configurableElement); |
| configurable.disposeUIResources(); |
| } |
| final File file = new File(OUTPUT_PATH); |
| if (!file.isFile()) { |
| file.getParentFile().mkdirs(); |
| file.createNewFile(); |
| } |
| JDOMUtil.writeDocument(new Document(root), OUTPUT_PATH, "\n"); |
| |
| System.out.println("Searchable options index builder completed"); |
| |
| ((ApplicationEx)ApplicationManager.getApplication()).exit(true, true); |
| } |
| |
| private static void processFileTemplates(Element configurableElement) { |
| final SearchableOptionsRegistrar optionsRegistrar = SearchableOptionsRegistrar.getInstance(); |
| TreeSet<OptionDescription> options = new TreeSet<OptionDescription>(); |
| |
| processTemplates(optionsRegistrar, options, FileTemplateManager.getInstance().getAllTemplates()); |
| processTemplates(optionsRegistrar, options, FileTemplateManager.getInstance().getAllPatterns()); |
| processTemplates(optionsRegistrar, options, FileTemplateManager.getInstance().getAllCodeTemplates()); |
| processTemplates(optionsRegistrar, options, FileTemplateManager.getInstance().getAllJ2eeTemplates()); |
| |
| writeOptions(configurableElement, options); |
| } |
| |
| private static void processTemplates(SearchableOptionsRegistrar optionsRegistrar, |
| TreeSet<OptionDescription> options, |
| FileTemplate[] templates) { |
| for (FileTemplate template : templates) { |
| collectOptions(optionsRegistrar, options, template.getName()); |
| //collectOptions(optionsRegistrar, options, template.getDescription()); |
| } |
| } |
| |
| private static void collectOptions(SearchableOptionsRegistrar optionsRegistrar, |
| TreeSet<OptionDescription> options, |
| String text) { |
| collectOptions(optionsRegistrar, options, text, null); |
| } |
| |
| private static void collectOptions(SearchableOptionsRegistrar optionsRegistrar, |
| TreeSet<OptionDescription> options, |
| String text, |
| String path) { |
| final Set<String> strings = optionsRegistrar.getProcessedWordsWithoutStemming(text); |
| for (String word : strings) { |
| options.add(new OptionDescription(word, text, path)); |
| } |
| } |
| |
| private static void processOptionsContainingConfigurable(final OptionsContainingConfigurable configurable, |
| final Element configurableElement) { |
| final Set<String> optionsPath = configurable.processListOptions(); |
| final TreeSet<OptionDescription> result = wordsToOptionDescriptors(optionsPath); |
| writeOptions(configurableElement, result); |
| } |
| |
| private static TreeSet<OptionDescription> wordsToOptionDescriptors(Set<String> optionsPath) { |
| SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance(); |
| final TreeSet<OptionDescription> result = new TreeSet<OptionDescription>(); |
| for (String opt : optionsPath) { |
| final Set<String> words = searchableOptionsRegistrar.getProcessedWordsWithoutStemming(opt); |
| for (String word : words) { |
| if (word != null){ |
| result.add(new OptionDescription(word, opt, null)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private static void processKeymap(final Element configurableElement){ |
| final ActionManager actionManager = ActionManager.getInstance(); |
| final String componentName = actionManager.getComponentName(); |
| final SearchableOptionsRegistrar searchableOptionsRegistrar = SearchableOptionsRegistrar.getInstance(); |
| final Set<String> ids = ((ActionManagerImpl)actionManager).getActionIds(); |
| final TreeSet<OptionDescription> options = new TreeSet<OptionDescription>(); |
| for (String id : ids) { |
| final AnAction anAction = actionManager.getAction(id); |
| final String text = anAction.getTemplatePresentation().getText(); |
| if (text != null) { |
| collectOptions(searchableOptionsRegistrar, options, text, componentName); |
| } |
| final String description = anAction.getTemplatePresentation().getDescription(); |
| if (description != null) { |
| collectOptions(searchableOptionsRegistrar, options, description, componentName); |
| } |
| } |
| writeOptions(configurableElement, options); |
| } |
| |
| private static void writeOptions(Element configurableElement, TreeSet<OptionDescription> options) { |
| for (OptionDescription opt : options) { |
| append(opt.getPath(), opt.getHit(), opt.getOption(), configurableElement); |
| } |
| } |
| |
| private static void append(String path, String hit, final String word, final Element configurableElement) { |
| Element optionElement = new Element(OPTION); |
| optionElement.setAttribute(NAME, word); |
| if (path != null) { |
| optionElement.setAttribute(PATH, path); |
| } |
| optionElement.setAttribute(HIT, hit); |
| configurableElement.addContent(optionElement); |
| } |
| } |