diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java index 96e6d015f026..9386cca37ec8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ThreadDumpAction.java @@ -27,8 +27,8 @@ import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerSession; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; -import com.intellij.debugger.ui.DebuggerSessionTab; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -70,7 +70,7 @@ public class ThreadDumpAction extends AnAction implements AnAction.TransparentUp public void run() { XDebugSession xSession = session.getXDebugSession(); if (xSession != null) { - DebuggerSessionTab.addThreadDump(project, threads, xSession.getUI(), session); + DebuggerUtilsEx.addThreadDump(project, threads, xSession.getUI(), session); } } }, ModalityState.NON_MODAL); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index c7e682f200a5..5bd576c109f6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -33,7 +33,14 @@ import com.intellij.debugger.requests.Requestor; import com.intellij.debugger.ui.CompletionEditor; import com.intellij.debugger.ui.breakpoints.Breakpoint; import com.intellij.debugger.ui.tree.DebuggerTreeNode; +import com.intellij.execution.filters.ExceptionFilters; +import com.intellij.execution.filters.TextConsoleBuilder; +import com.intellij.execution.filters.TextConsoleBuilderFactory; +import com.intellij.execution.ui.ConsoleView; +import com.intellij.execution.ui.RunnerLayoutUi; +import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; @@ -47,6 +54,9 @@ import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.ui.classFilter.ClassFilter; +import com.intellij.ui.content.Content; +import com.intellij.unscramble.ThreadDumpPanel; +import com.intellij.unscramble.ThreadState; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.xdebugger.XSourcePosition; @@ -399,6 +409,43 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { return null; } + private static int myThreadDumpsCount = 0; + private static int myCurrentThreadDumpId = 1; + + private static final String THREAD_DUMP_CONTENT_PREFIX = "Dump"; + + public static void addThreadDump(Project project, List threads, final RunnerLayoutUi ui, DebuggerSession session) { + final TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project); + consoleBuilder.filters(ExceptionFilters.getFilters(session.getSearchScope())); + final ConsoleView consoleView = consoleBuilder.getConsole(); + final DefaultActionGroup toolbarActions = new DefaultActionGroup(); + consoleView.allowHeavyFilters(); + final ThreadDumpPanel panel = new ThreadDumpPanel(project, consoleView, toolbarActions, threads); + + final String id = THREAD_DUMP_CONTENT_PREFIX + " #" + myCurrentThreadDumpId; + final Content content = ui.createContent(id, panel, id, null, null); + content.setCloseable(true); + content.setDescription("Thread Dump"); + ui.addContent(content); + ui.selectAndFocus(content, true, true); + myThreadDumpsCount++; + myCurrentThreadDumpId++; + Disposer.register(content, new Disposable() { + @Override + public void dispose() { + myThreadDumpsCount--; + if (myThreadDumpsCount == 0) { + myCurrentThreadDumpId = 1; + } + } + }); + Disposer.register(content, consoleView); + ui.selectAndFocus(content, true, false); + if (threads.size() > 0) { + panel.selectStackFrame(0); + } + } + public abstract DebuggerTreeNode getSelectedNode (DataContext context); public abstract EvaluatorBuilder getEvaluatorBuilder(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java index eaf49dc37b29..3c346146ef60 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -42,6 +42,7 @@ import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugProcessStarter; import com.intellij.xdebugger.XDebugSession; @@ -222,12 +223,9 @@ public class DebuggerPanelsManager implements ProjectComponent { } private static DebuggerSession getSession(Project project, RunContentDescriptor descriptor) { - for (XDebugSession session : XDebuggerManager.getInstance(project).getDebugSessions()) { - if (session.getRunContentDescriptor().equals(descriptor)) { - XDebugProcess process = session.getDebugProcess(); - if (process instanceof JavaDebugProcess) { - return ((JavaDebugProcess)process).getDebuggerSession(); - } + for (JavaDebugProcess process : XDebuggerManager.getInstance(project).getDebugProcesses(JavaDebugProcess.class)) { + if (Comparing.equal(process.getProcessHandler(), descriptor.getProcessHandler())) { + return process.getDebuggerSession(); } } return null; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java index 51a96197ba48..7842769a7479 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java @@ -36,12 +36,8 @@ import com.intellij.execution.ExecutionManager; import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.executors.DefaultDebugExecutor; -import com.intellij.execution.filters.ExceptionFilters; -import com.intellij.execution.filters.TextConsoleBuilder; -import com.intellij.execution.filters.TextConsoleBuilderFactory; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ExecutionConsoleEx; -import com.intellij.execution.ui.RunnerLayoutUi; import com.intellij.execution.ui.layout.PlaceInGrid; import com.intellij.icons.AllIcons; import com.intellij.idea.ActionsBundle; @@ -56,8 +52,6 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManagerAdapter; import com.intellij.ui.content.ContentManagerEvent; import com.intellij.ui.content.tabs.PinToolwindowTabAction; -import com.intellij.unscramble.ThreadDumpPanel; -import com.intellij.unscramble.ThreadState; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager; @@ -68,7 +62,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.TreePath; -import java.util.List; public class DebuggerSessionTab extends DebuggerSessionTabBase implements Disposable { private static final Logger LOG = Logger.getInstance(DebuggerSessionTab.class); @@ -84,7 +77,6 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos private final DebugUIEnvironment myDebugUIEnvironment; private final ThreadsPanel myThreadsPanel; - private static final String THREAD_DUMP_CONTENT_PREFIX = "Dump"; public DebuggerSessionTab(final Project project, final String sessionName, @NotNull final DebugUIEnvironment environment, @NotNull DebuggerSession debuggerSession) { @@ -447,51 +439,6 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos myUi.selectAndFocus(myUi.findContent(DebuggerContentInfo.FRAME_CONTENT), true, false); } - private static int myThreadDumpsCount = 0; - private static int myCurrentThreadDumpId = 1; - - public static void addThreadDump(Project project, List threads, final RunnerLayoutUi ui, DebuggerSession session) { - final TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project); - consoleBuilder.filters(ExceptionFilters.getFilters(session.getSearchScope())); - final ConsoleView consoleView = consoleBuilder.getConsole(); - final DefaultActionGroup toolbarActions = new DefaultActionGroup(); - consoleView.allowHeavyFilters(); - final ThreadDumpPanel panel = new ThreadDumpPanel(project, consoleView, toolbarActions, threads); - - final String id = createThreadDumpContentId(); - final Content content = ui.createContent(id, panel, id, null, null); - content.setCloseable(true); - content.setDescription("Thread Dump"); - ui.addContent(content); - ui.selectAndFocus(content, true, true); - myThreadDumpsCount += 1; - myCurrentThreadDumpId += 1; - //Disposer.register(this, new Disposable() { - // @Override - // public void dispose() { - // ui.removeContent(content, true); - // } - //}); - Disposer.register(content, new Disposable() { - @Override - public void dispose() { - myThreadDumpsCount -= 1; - if (myThreadDumpsCount == 0) { - myCurrentThreadDumpId = 1; - } - } - }); - Disposer.register(content, consoleView); - ui.selectAndFocus(content, true, false); - if (threads.size() > 0) { - panel.selectStackFrame(0); - } - } - - private static String createThreadDumpContentId() { - return THREAD_DUMP_CONTENT_PREFIX + " #" + myCurrentThreadDumpId; - } - private class MyDebuggerStateManager extends DebuggerStateManager { @Override public void fireStateChanged(DebuggerContextImpl newContext, int event) { diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index 45c38a57154f..85bdf9c1398a 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -165,7 +165,7 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.typed.symbol"),"'Symbol <'_GenericArgument+>", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.casts"),"( '_Type <'_GenericArgument+> ) '_Expr", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.type.var.substitutions.in.intanceof.with.generic.types"),"'_Expr instanceof '_Type <'Substitutions+> ", GENERICS_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.variables.of.generic.types"),"'_Type <'_GenericArgument+> 'Var = 'Init?;", GENERICS_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.variables.of.generic.types"),"'_Type <'_GenericArgument+> 'Var = '_Init?;", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.diamond.operators"), "new 'ClassName<>('_Argument*)", GENERICS_TYPE), // Add comments and metadata @@ -226,7 +226,7 @@ class JavaPredefinedConfigurations { " public void ejbRemove();\n" + "}", J2EE_TYPE), createSearchTemplateInfoSimple(SSRBundle.message("predefined.configuration.ejb.interface"),"interface 'EjbInterface extends EJBObject {\n" + - " 'Type+ 'Method+('ParamType* 'ParamName*);\n" + + " '_Type+ '_Method+('_ParamType* '_ParamName*);\n" + "}", J2EE_TYPE), createSearchTemplateInfoSimple(SSRBundle.message("predefined.configuration.servlets"),"public class 'Servlet extends '_ParentClass:*HttpServlet {\n" + " public void '_InitServletMethod?:init ();\n" + @@ -243,19 +243,19 @@ class JavaPredefinedConfigurations { // Misc types createSearchTemplateInfo(SSRBundle.message("predefined.configuration.serializable.classes.and.their.serialization.implementation"), - "class '_Class implements '_Serializable:*Serializable {\n" + - " static final long 'VersionField?:serialVersionUID = '_VersionFieldInit?;\n" + + "class 'Class implements '_Serializable:*Serializable {\n" + + " static final long '_VersionField?:serialVersionUID = '_VersionFieldInit?;\n" + " private static final ObjectStreamField[] '_persistentFields?:serialPersistentFields = '_persistentFieldInitial?; \n" + - " private void 'SerializationWriteHandler?:writeObject (ObjectOutputStream '_stream) throws IOException;\n" + - " private void 'SerializationReadHandler?:readObject (ObjectInputStream '_stream2) throws IOException, ClassNotFoundException;\n" + - " Object 'SpecialSerializationReadHandler?:readResolve () throws ObjectStreamException;\n" + - " Object 'SpecialSerializationWriteHandler?:writeReplace () throws ObjectStreamException;\n" + + " private void '_SerializationWriteHandler?:writeObject (ObjectOutputStream '_stream) throws IOException;\n" + + " private void '_SerializationReadHandler?:readObject (ObjectInputStream '_stream2) throws IOException, ClassNotFoundException;\n" + + " Object '_SpecialSerializationReadHandler?:readResolve () throws ObjectStreamException;\n" + + " Object '_SpecialSerializationWriteHandler?:writeReplace () throws ObjectStreamException;\n" + "}",MISC_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.cloneable.implementations"), "class '_Class implements '_Interface:*Cloneable {\n" + " Object 'CloningMethod:*clone ();\n" + "}",MISC_TYPE), - createSearchTemplateInfoSimple(SSRBundle.message("predefined.configuration.]junit.test.cases"),"public class 'TestCase extends 'TestCaseClazz:*TestCase {\n" + + createSearchTemplateInfoSimple(SSRBundle.message("predefined.configuration.]junit.test.cases"),"public class 'TestCase extends '_TestCaseClazz:*TestCase {\n" + " public void '_testMethod+:test.* ();\n" + "}", MISC_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.singletons"),"class 'Class {\n" + @@ -285,7 +285,7 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.symbol"),"'Symbol",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.fields.variables.read"),"'Symbol:[read]",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.fields_variables.with.given.name.pattern.updated"),"'Symbol:[regex( name ) && write]",INTERESTING_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.usage.of.derived.type.in.cast"),"('CastType:*Base ) 'Expr",INTERESTING_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.usage.of.derived.type.in.cast"),"('CastType:*[regex( Base )]) '_Expr",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.boxing.in.declarations"),"'_Type:Object|Integer|Boolean|Long|Character|Short|Byte 'Var = '_Value:[exprtype( int|boolean|long|char|short|byte )]",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.unboxing.in.declarations"),"'_Type:int|boolean|long|char|short|byte 'Var = '_Value:[exprtype( Integer|Boolean|Long|Character|Short|Byte )]",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.boxing.in.method.calls"),"'_Instance?.'Call('_BeforeParam*,'_Param:[ exprtype( int|boolean|long|char|short|byte ) && formal( Object|Integer|Boolean|Long|Character|Short|Byte )],'_AfterParam*)",INTERESTING_TYPE), diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/TypeConversionDescriptor.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/TypeConversionDescriptor.java index d116c3ce30fe..0861f1ec9e5c 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/TypeConversionDescriptor.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/TypeConversionDescriptor.java @@ -1,6 +1,7 @@ package com.intellij.refactoring.typeMigration; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiExpression; @@ -65,7 +66,9 @@ public class TypeConversionDescriptor extends TypeConversionDescriptorBase { if (getExpression() != null) expression = getExpression(); final Project project = expression.getProject(); final ReplaceOptions options = new ReplaceOptions(); - options.setMatchOptions(new MatchOptions()); + final MatchOptions matchOptions = new MatchOptions(); + matchOptions.setFileType(StdFileTypes.JAVA); + options.setMatchOptions(matchOptions); final Replacer replacer = new Replacer(project, null); try { final String replacement = replacer.testReplace(expression.getText(), getStringToReplace(), getReplaceByString(), options); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java index f1daae220d85..91f363684185 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java @@ -40,12 +40,23 @@ public abstract class AbstractExternalProjectSettingsControl outdatedPlugins = myUpdateSettings.getOutdatedPlugins(); if (newer) { - if (!myUpdateSettings.myOutdatedPlugins.contains(idString)) { - myUpdateSettings.myOutdatedPlugins.add(idString); + if (!outdatedPlugins.contains(idString)) { + outdatedPlugins.add(idString); } } else { - myUpdateSettings.myOutdatedPlugins.remove(idString); + outdatedPlugins.remove(idString); } } } @@ -108,7 +110,7 @@ public class InstalledPluginsState { boolean existing = PluginManager.isPluginInstalled(id); synchronized (myLock) { - myUpdateSettings.myOutdatedPlugins.remove(id.getIdString()); + myUpdateSettings.getOutdatedPlugins().remove(id.getIdString()); if (existing) { myUpdatedPlugins.put(id, descriptor); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java index 7e0c6dd10d91..2c9e18f1347c 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -67,13 +67,13 @@ public class PluginHostsConfigurable extends BaseConfigurable { public void apply() throws ConfigurationException { UpdateSettings settings = UpdateSettings.getInstance(); - settings.myPluginHosts.clear(); - settings.myPluginHosts.addAll(myUpdatesSettingsPanel.getPluginsHosts()); + settings.getStoredPluginHosts().clear(); + settings.getStoredPluginHosts().addAll(myUpdatesSettingsPanel.getPluginsHosts()); } @Override public void reset() { - myUpdatesSettingsPanel.setPluginHosts(UpdateSettings.getInstance().myPluginHosts); + myUpdatesSettingsPanel.setPluginHosts(UpdateSettings.getInstance().getStoredPluginHosts()); } @Override @@ -82,7 +82,7 @@ public class PluginHostsConfigurable extends BaseConfigurable { return false; } //noinspection EqualsBetweenInconvertibleTypes - return !UpdateSettings.getInstance().myPluginHosts.equals(myUpdatesSettingsPanel.getPluginsHosts()); + return !UpdateSettings.getInstance().getStoredPluginHosts().equals(myUpdatesSettingsPanel.getPluginsHosts()); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java index 4a0da5a97736..ba7cf5900e0f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsEditor.java @@ -29,6 +29,7 @@ import com.intellij.openapi.ui.OnePixelDivider; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.OnePixelSplitter; import com.intellij.ui.components.panels.VerticalLayout; import com.intellij.ui.treeStructure.SimpleNode; @@ -40,9 +41,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.KeyEvent; +import java.awt.event.*; import java.util.LinkedHashMap; import java.util.Map; @@ -235,7 +234,9 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { mySpotlightPainter = new SpotlightPainter(myEditor, this) { void updateNow() { Configurable configurable = myFilter.myContext.getCurrentConfigurable(); - update(myFilter, configurable, myEditor.getContent(configurable)); + if (myTreeView.myTree.hasFocus() || mySearch.getTextEditor().hasFocus()) { + update(myFilter, configurable, myEditor.getContent(configurable)); + } } }; add(BorderLayout.CENTER, mySplitter); @@ -250,6 +251,29 @@ final class SettingsEditor extends AbstractEditor implements DataProvider { myFilter.update(filter, false, true); myTreeView.select(configurable); Disposer.register(this, myTreeView); + installSpotlightRemover(); + } + + private void installSpotlightRemover() { + final FocusAdapter spotlightRemover = new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + final Component comp = e.getOppositeComponent(); + if (comp == mySearch.getTextEditor() || comp == myTreeView.myTree) { + return; + } + mySpotlightPainter.update(null, null, null); + } + + @Override + public void focusGained(FocusEvent e) { + if (!StringUtil.isEmpty(mySearch.getText())) { + mySpotlightPainter.updateNow(); + } + } + }; + myTreeView.myTree.addFocusListener(spotlightRemover); + mySearch.getTextEditor().addFocusListener(spotlightRemover); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index bed4e4e11fe4..939eace5d54d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -631,7 +631,7 @@ public final class UpdateChecker { private static boolean ourHasFailedPlugins = false; public static void checkForUpdate(IdeaLoggingEvent event) { - if (!ourHasFailedPlugins && UpdateSettings.getInstance().CHECK_NEEDED) { + if (!ourHasFailedPlugins && UpdateSettings.getInstance().isCheckNeeded()) { final Throwable throwable = event.getThrowable(); final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(IdeErrorsDialog.findPluginId(throwable)); if (pluginDescriptor != null && !pluginDescriptor.isBundled()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java index f4436da4a5ee..86858309aeeb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java @@ -25,6 +25,7 @@ import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Alarm; import com.intellij.util.net.NetUtils; @@ -54,12 +55,13 @@ public class UpdateCheckerComponent implements ApplicationComponent { public UpdateCheckerComponent(@NotNull Application app, @NotNull UpdateSettings settings) { mySettings = settings; - if (mySettings.SECURE_CONNECTION && !NetUtils.isSniEnabled()) { + if (mySettings.isSecureConnection() && !NetUtils.isSniEnabled()) { app.invokeLater(new Runnable() { @Override public void run() { String title = IdeBundle.message("update.notifications.title"); - String message = IdeBundle.message("update.sni.disabled.notification"); + boolean tooOld = !SystemInfo.isJavaVersionAtLeast("1.7"); + String message = IdeBundle.message(tooOld ? "update.sni.not.available.notification" : "update.sni.disabled.notification"); UpdateChecker.NOTIFICATIONS.createNotification(title, message, NotificationType.ERROR, null).notify(null); } }, ModalityState.NON_MODAL); @@ -74,7 +76,7 @@ public class UpdateCheckerComponent implements ApplicationComponent { } private void scheduleOnStartCheck(@NotNull Application app) { - if (!mySettings.CHECK_NEEDED || mySettings.SECURE_CONNECTION && !NetUtils.isSniEnabled()) { + if (!mySettings.isCheckNeeded() || mySettings.isSecureConnection() && !NetUtils.isSniEnabled()) { return; } @@ -82,9 +84,9 @@ public class UpdateCheckerComponent implements ApplicationComponent { @Override public void appFrameCreated(String[] commandLineArgs, @NotNull Ref willOpenProject) { String currentBuild = ApplicationInfo.getInstance().getBuild().asString(); - long timeToNextCheck = mySettings.LAST_TIME_CHECKED + CHECK_INTERVAL - System.currentTimeMillis(); + long timeToNextCheck = mySettings.getLastTimeChecked() + CHECK_INTERVAL - System.currentTimeMillis(); - if (StringUtil.compareVersionNumbers(mySettings.LAST_BUILD_CHECKED, currentBuild) < 0 || timeToNextCheck <= 0) { + if (StringUtil.compareVersionNumbers(mySettings.getLasBuildChecked(), currentBuild) < 0 || timeToNextCheck <= 0) { myCheckRunnable.run(); } else { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java index 14d63c9d6bd5..0d6d45a99aa8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java @@ -18,15 +18,13 @@ package com.intellij.openapi.updateSettings.impl; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.components.*; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.DefaultJDOMExternalizer; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMExternalizableStringList; -import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.net.NetUtils; -import org.jdom.Element; +import com.intellij.util.xmlb.annotations.CollectionBean; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -38,94 +36,128 @@ import java.util.List; @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) } ) -public class UpdateSettings implements PersistentStateComponent, UserUpdateSettings { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.UpdateSettings"); - - public JDOMExternalizableStringList myPluginHosts = new JDOMExternalizableStringList(); - public JDOMExternalizableStringList myKnownUpdateChannels = new JDOMExternalizableStringList(); - public JDOMExternalizableStringList myIgnoredBuildNumbers = new JDOMExternalizableStringList(); - public JDOMExternalizableStringList myOutdatedPlugins = new JDOMExternalizableStringList(); - - public boolean CHECK_NEEDED = true; - public long LAST_TIME_CHECKED = 0; - public String LAST_BUILD_CHECKED = ""; - public String UPDATE_CHANNEL_TYPE = ChannelStatus.RELEASE_CODE; - public boolean SECURE_CONNECTION = false; - - public static UpdateSettings getInstance() { - return ServiceManager.getService(UpdateSettings.class); - } +public class UpdateSettings implements PersistentStateComponent, UserUpdateSettings { + private State myState = new State(); public UpdateSettings() { updateDefaultChannel(); } + public static UpdateSettings getInstance() { + return ServiceManager.getService(UpdateSettings.class); + } + + static class State { + @CollectionBean + public final List pluginHosts = new SmartList(); + @CollectionBean + public final List knownUpdateChannels = new SmartList(); + @CollectionBean + public final List ignoredBuildNumbers = new SmartList(); + @CollectionBean + public final List outdatedPlugins = new SmartList(); + + public boolean CHECK_NEEDED = true; + public long LAST_TIME_CHECKED = 0; + + public String LAST_BUILD_CHECKED; + public String UPDATE_CHANNEL_TYPE = ChannelStatus.RELEASE_CODE; + public boolean SECURE_CONNECTION = false; + } + + @Nullable + public String getLasBuildChecked() { + return myState.LAST_BUILD_CHECKED; + } + + @NotNull + public List getStoredPluginHosts() { + return myState.pluginHosts; + } + + public boolean isCheckNeeded() { + return myState.CHECK_NEEDED; + } + + public void setCheckNeeded(boolean value) { + myState.CHECK_NEEDED = value; + } + + public boolean isSecureConnection() { + return myState.SECURE_CONNECTION; + } + + public void setSecureConnection(boolean value) { + myState.SECURE_CONNECTION = value; + } + + @NotNull + public String getUpdateChannelType() { + return myState.UPDATE_CHANNEL_TYPE; + } + + public long getLastTimeChecked() { + return myState.LAST_TIME_CHECKED; + } + + public void setUpdateChannelType(@NotNull String value) { + myState.UPDATE_CHANNEL_TYPE = value; + } + + @NotNull + public List getOutdatedPlugins() { + return myState.outdatedPlugins; + } + private void updateDefaultChannel() { if (ApplicationInfoImpl.getShadowInstance().isEAP()) { - UPDATE_CHANNEL_TYPE = ChannelStatus.EAP_CODE; + myState.UPDATE_CHANNEL_TYPE = ChannelStatus.EAP_CODE; } } - @SuppressWarnings("deprecation") @Override - public Element getState() { - Element element = new Element("state"); - try { - DefaultJDOMExternalizer.writeExternal(this, element); - } - catch (WriteExternalException e) { - LOG.info(e); - } - return element; + public State getState() { + return myState; } - @SuppressWarnings("deprecation") @Override - public void loadState(Element state) { - try { - DefaultJDOMExternalizer.readExternal(this, state); - } - catch (InvalidDataException e) { - LOG.info(e); - } + public void loadState(State state) { + myState = state; + myState.LAST_BUILD_CHECKED = StringUtil.nullize(myState.LAST_BUILD_CHECKED); updateDefaultChannel(); } @NotNull @Override public List getKnownChannelsIds() { - List ids = new ArrayList(); - for (String channel : myKnownUpdateChannels) { - ids.add(channel); - } - return ids; + return new ArrayList(myState.knownUpdateChannels); } @Override public void setKnownChannelIds(@NotNull List ids) { - myKnownUpdateChannels.clear(); + myState.knownUpdateChannels.clear(); for (String id : ids) { - myKnownUpdateChannels.add(id); + myState.knownUpdateChannels.add(id); } } public void forgetChannelId(String id) { - myKnownUpdateChannels.remove(id); + myState.knownUpdateChannels.remove(id); } @Override public List getIgnoredBuildNumbers() { - return myIgnoredBuildNumbers; + return myState.ignoredBuildNumbers; } @NotNull @Override public ChannelStatus getSelectedChannelStatus() { - return ChannelStatus.fromCode(UPDATE_CHANNEL_TYPE); + return ChannelStatus.fromCode(myState.UPDATE_CHANNEL_TYPE); } public List getPluginHosts() { - List hosts = new ArrayList(myPluginHosts); + List hosts = new ArrayList(myState.pluginHosts); String pluginHosts = System.getProperty("idea.plugin.hosts"); if (pluginHosts != null) { ContainerUtil.addAll(hosts, pluginHosts.split(";")); @@ -134,15 +166,15 @@ public class UpdateSettings implements PersistentStateComponent, UserUp } public void forceCheckForUpdateAfterRestart() { - LAST_TIME_CHECKED = 0; + myState.LAST_TIME_CHECKED = 0; } public void saveLastCheckedInfo() { - LAST_TIME_CHECKED = System.currentTimeMillis(); - LAST_BUILD_CHECKED = ApplicationInfo.getInstance().getBuild().asString(); + myState.LAST_TIME_CHECKED = System.currentTimeMillis(); + myState.LAST_BUILD_CHECKED = ApplicationInfo.getInstance().getBuild().asString(); } public boolean canUseSecureConnection() { - return SECURE_CONNECTION && NetUtils.isSniEnabled(); + return myState.SECURE_CONNECTION && NetUtils.isSniEnabled(); } -} +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java index 9da0dbd415ea..8932a6b0425a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java @@ -25,6 +25,7 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.util.net.NetUtils; import com.intellij.util.text.DateFormatUtil; @@ -64,6 +65,7 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear return "preferences.updates"; } + @Override @NotNull public String getId() { return getHelpTopic(); @@ -79,9 +81,9 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear public void apply() throws ConfigurationException { UpdateSettings settings = UpdateSettings.getInstance(); - boolean wasEnabled = settings.CHECK_NEEDED; - settings.CHECK_NEEDED = myUpdatesSettingsPanel.myCheckForUpdates.isSelected(); - if (wasEnabled != settings.CHECK_NEEDED) { + boolean wasEnabled = settings.isCheckNeeded(); + settings.setCheckNeeded(myUpdatesSettingsPanel.myCheckForUpdates.isSelected()); + if (wasEnabled != settings.isCheckNeeded()) { UpdateCheckerComponent checker = ApplicationManager.getApplication().getComponent(UpdateCheckerComponent.class); if (checker != null) { if (wasEnabled) { @@ -93,27 +95,33 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear } } - settings.UPDATE_CHANNEL_TYPE = myUpdatesSettingsPanel.getSelectedChannelType().getCode(); - settings.SECURE_CONNECTION = myUpdatesSettingsPanel.myUseSecureConnection.isSelected(); + settings.setUpdateChannelType(myUpdatesSettingsPanel.getSelectedChannelType().getCode()); + settings.setSecureConnection(myUpdatesSettingsPanel.myUseSecureConnection.isSelected()); } @Override public void reset() { UpdateSettings settings = UpdateSettings.getInstance(); - myUpdatesSettingsPanel.myCheckForUpdates.setSelected(settings.CHECK_NEEDED); - myUpdatesSettingsPanel.myUseSecureConnection.setSelected(settings.SECURE_CONNECTION); + myUpdatesSettingsPanel.myCheckForUpdates.setSelected(settings.isCheckNeeded()); + myUpdatesSettingsPanel.myUseSecureConnection.setSelected(settings.isSecureConnection()); myUpdatesSettingsPanel.updateLastCheckedLabel(); - myUpdatesSettingsPanel.setSelectedChannelType(ChannelStatus.fromCode(settings.UPDATE_CHANNEL_TYPE)); + myUpdatesSettingsPanel.setSelectedChannelType(ChannelStatus.fromCode(settings.getUpdateChannelType())); } @Override public boolean isModified() { - if (myUpdatesSettingsPanel == null) return false; + if (myUpdatesSettingsPanel == null) { + return false; + } + UpdateSettings settings = UpdateSettings.getInstance(); - if (settings.CHECK_NEEDED != myUpdatesSettingsPanel.myCheckForUpdates.isSelected()) return true; - if (settings.SECURE_CONNECTION != myUpdatesSettingsPanel.myUseSecureConnection.isSelected()) return true; + if (settings.isCheckNeeded() != myUpdatesSettingsPanel.myCheckForUpdates.isSelected() || + settings.isSecureConnection() != myUpdatesSettingsPanel.myUseSecureConnection.isSelected()) { + return true; + } + Object channel = myUpdatesSettingsPanel.myUpdateChannels.getSelectedItem(); - return channel != null && !channel.equals(ChannelStatus.fromCode(settings.UPDATE_CHANNEL_TYPE)); + return channel != null && !channel.equals(ChannelStatus.fromCode(settings.getUpdateChannelType())); } @Override @@ -148,12 +156,13 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear myBuildNumber.setText(appInfo.getBuild().asString()); myCheckNow.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(myCheckNow)); UpdateSettings settings = new UpdateSettings(); settings.loadState(UpdateSettings.getInstance().getState()); - settings.UPDATE_CHANNEL_TYPE = getSelectedChannelType().getCode(); - settings.SECURE_CONNECTION = myUseSecureConnection.isSelected(); + settings.setUpdateChannelType(getSelectedChannelType().getCode()); + settings.setSecureConnection(myUseSecureConnection.isSelected()); UpdateChecker.updateAndShowResult(project, settings); updateLastCheckedLabel(); } @@ -163,16 +172,18 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear UpdateSettings settings = UpdateSettings.getInstance(); //noinspection unchecked - myUpdateChannels.setModel(new CollectionComboBoxModel(ChannelStatus.all(), ChannelStatus.fromCode(settings.UPDATE_CHANNEL_TYPE))); + myUpdateChannels.setModel(new CollectionComboBoxModel(ChannelStatus.all(), ChannelStatus.fromCode(settings.getUpdateChannelType()))); if (!NetUtils.isSniEnabled()) { myUseSecureConnection.setEnabled(false); - myUseSecureConnection.setToolTipText(IdeBundle.message("update.sni.disabled.notification")); + boolean tooOld = !SystemInfo.isJavaVersionAtLeast("1.7"); + String message = IdeBundle.message(tooOld ? "update.sni.not.available.notification" : "update.sni.disabled.notification"); + myUseSecureConnection.setToolTipText(message); } } private void updateLastCheckedLabel() { - long time = UpdateSettings.getInstance().LAST_TIME_CHECKED; + long time = UpdateSettings.getInstance().getLastTimeChecked(); myLastCheckedDate.setText(time == 0 ? IdeBundle.message("updates.last.check.never") : DateFormatUtil.formatPrettyDateTime(time)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java index 742fc08eb103..21eede8dc417 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -220,7 +220,9 @@ public class PluginsAdvertiser implements StartupActivity { @Override public void runActivity(@NotNull final Project project) { - if (!UpdateSettings.getInstance().CHECK_NEEDED) return; + if (!UpdateSettings.getInstance().isCheckNeeded()) { + return; + } final UnknownFeaturesCollector collectorSuggester = UnknownFeaturesCollector.getInstance(project); final Set unknownFeatures = collectorSuggester.getUnknownFeatures(); final KnownExtensions extensions = loadExtensions(); diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index b010f2373daa..806c0c72e97f 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -944,6 +944,7 @@ update.downloading.patch.error=Failed to download patch file:\n{0} update.plugins.update.action=&Update update.restart.plugins.update.action=&Update and Restart update.shutdown.plugins.update.action=&Update and Shutdown +update.sni.not.available.notification=Secure update is not supported on Java 6. Sorry. update.sni.disabled.notification=Secure update is impossible with SNI disabled hierarchy.method.next.occurence.name=Go to next method diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java index be33189ee486..be4759d676a7 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java @@ -32,6 +32,7 @@ public class StructuralSearchUtil { @Contract("null -> false") public static boolean isIdentifier(PsiElement element) { + if (element == null) return false; final StructuralSearchProfile profile = getProfileByPsiElement(element); return profile != null && profile.isIdentifier(element); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index 1597f2f2d87b..02efb3e95750 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -682,11 +682,9 @@ public class MatcherImpl { assert targetNode != null : "Could not match down up when no target node"; - System.out.println("elementToStartMatching = " + elementToStartMatching.getText()); match(elementToStartMatching); matchContext.getSink().matchingFinished(); - final List matches = sink.getMatches(); - return matches; + return sink.getMatches(); } private class MatchOneVirtualFile extends MatchOneFile { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java index 0d684503a14d..0ac16b386a19 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java @@ -42,6 +42,7 @@ class StringToConstraintsTransformer { StringBuilder miscBuffer = null; int anonymousTypedVarsCount = 0; + boolean targetFound = false; for(int index=0;index < pattern.length();++index) { char ch = pattern.charAt(index); @@ -187,6 +188,10 @@ class StringToConstraintsTransformer { constraint.setMaxCount(maxOccurs); constraint.setGreedy(greedy); constraint.setPartOfSearchResults(!anonymous); + if (targetFound && !anonymous) { + throw new MalformedPatternException("Pattern may have only one target"); + } + targetFound = !anonymous; } if (index < length && pattern.charAt(index) == ':') { @@ -248,7 +253,19 @@ class StringToConstraintsTransformer { // eat complete condition miscBuffer.setLength(0); - for(++index; index < length && ((ch = pattern.charAt(index))!=']' || pattern.charAt(index-1)=='\\'); ++index) { + for(++index; index < length && ((ch = pattern.charAt(index)) != ']' || pattern.charAt(index-1) == '\\'); ++index) { + if (ch == '"') { + miscBuffer.append(ch); + for (++index; index < length && (ch = pattern.charAt(index)) != '"'; ++index) { + if (ch == '\\') { + ++index; + if (index >= length) break; + ch = pattern.charAt(index); + } + miscBuffer.append(ch); + } + if (ch != '"') throw new MalformedPatternException(SSRBundle.message("error.expected.end.quote")); + } miscBuffer.append(ch); } if (ch != ']') throw new MalformedPatternException(SSRBundle.message("error.expected.condition.or.bracket")); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 9a137efee3a1..2e408cab6f29 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -26,10 +26,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; -import com.intellij.structuralsearch.MatchVariableConstraint; -import com.intellij.structuralsearch.NamedScriptableDefinition; -import com.intellij.structuralsearch.ReplacementVariableDefinition; -import com.intellij.structuralsearch.SSRBundle; +import com.intellij.structuralsearch.*; import com.intellij.structuralsearch.impl.matcher.CompiledPattern; import com.intellij.structuralsearch.impl.matcher.predicates.ScriptSupport; import com.intellij.structuralsearch.plugin.replace.ReplaceOptions; @@ -111,7 +108,6 @@ class EditVarConstraintsDialog extends DialogWrapper { regexprForExprType.getDocument().addDocumentListener(new MyDocumentListener(exprTypeWithinHierarchy, notExprType)); formalArgType.getDocument().addDocumentListener(new MyDocumentListener(formalArgTypeWithinHierarchy, invertFormalArgType)); - partOfSearchResults.setEnabled(!replaceContext); // todo: this doesn't do anything containedInConstraints.setVisible(false); withinCombo.getComboBox().setEditable(true); @@ -297,7 +293,16 @@ class EditVarConstraintsDialog extends DialogWrapper { varInfo.setWithinHierarchy(applyWithinTypeHierarchy.isSelected()); varInfo.setInvertRegExp(notRegexp.isSelected()); - varInfo.setPartOfSearchResults(partOfSearchResults.isEnabled() && partOfSearchResults.isSelected()); + final boolean target = partOfSearchResults.isSelected(); + if (target) { + final MatchOptions matchOptions = configuration.getMatchOptions(); + for (String name : matchOptions.getVariableConstraintNames()) { + if (!name.equals(varName)) { + matchOptions.getVariableConstraint(name).setPartOfSearchResults(false); + } + } + } + varInfo.setPartOfSearchResults(target); varInfo.setInvertExprType(notExprType.isSelected()); varInfo.setNameOfExprType(regexprForExprType.getDocument().getText()); @@ -357,7 +362,8 @@ class EditVarConstraintsDialog extends DialogWrapper { setSearchConstraintsVisible(true); } - MatchVariableConstraint varInfo = configuration.getMatchOptions().getVariableConstraint(varName); + final MatchOptions matchOptions = configuration.getMatchOptions(); + final MatchVariableConstraint varInfo = matchOptions.getVariableConstraint(varName); if (varInfo == null) { notRead.setSelected(false); @@ -371,7 +377,7 @@ class EditVarConstraintsDialog extends DialogWrapper { maxoccurs.setText("1"); maxoccursUnlimited.setSelected(false); applyWithinTypeHierarchy.setSelected(false); - partOfSearchResults.setSelected(false); + partOfSearchResults.setSelected(isTarget(varName, matchOptions)); regexprForExprType.getDocument().setText(""); notExprType.setSelected(false); @@ -406,7 +412,7 @@ class EditVarConstraintsDialog extends DialogWrapper { maxoccurs.setText(Integer.toString(varInfo.getMaxCount())); } - partOfSearchResults.setSelected( partOfSearchResults.isEnabled() && varInfo.isPartOfSearchResults() ); + partOfSearchResults.setSelected(isTarget(varName, matchOptions)); exprTypeWithinHierarchy.setSelected(varInfo.isExprTypeWithinHierarchy()); regexprForExprType.getDocument().setText(varInfo.getNameOfExprType()); @@ -427,10 +433,29 @@ class EditVarConstraintsDialog extends DialogWrapper { containedInConstraints.setVisible(contextVar); textConstraintsPanel.setVisible(!contextVar); expressionConstraints.setVisible(!contextVar); - partOfSearchResults.setVisible(!contextVar); + partOfSearchResults.setEnabled(!contextVar); occurencePanel.setVisible(!contextVar); } + private static boolean isTarget(String varName, MatchOptions matchOptions) { + if (Configuration.CONTEXT_VAR_NAME.equals(varName)) { + // Complete Match is default target + for (String name : matchOptions.getVariableConstraintNames()) { + if (!name.equals(Configuration.CONTEXT_VAR_NAME)) { + if (matchOptions.getVariableConstraint(name).isPartOfSearchResults()) { + return false; + } + } + } + return true; + } + final MatchVariableConstraint constraint = matchOptions.getVariableConstraint(varName); + if (constraint == null) { + return false; + } + return constraint.isPartOfSearchResults(); + } + private void setSearchConstraintsVisible(boolean b) { textConstraintsPanel.setVisible(b); occurencePanel.setVisible(b); diff --git a/platform/structuralsearch/source/messages/SSRBundle.properties b/platform/structuralsearch/source/messages/SSRBundle.properties index 372e456c9f8a..a59ca1d7610d 100644 --- a/platform/structuralsearch/source/messages/SSRBundle.properties +++ b/platform/structuralsearch/source/messages/SSRBundle.properties @@ -210,10 +210,11 @@ error.two.different.type.constraints=Two different type constraints error.incorrect.regexp.constraint=Incorrect reg exp constraint:{0} for {1} error.expected.character=Character expected after single quote error.overflow=Value overflow -error.expected.brace1="Digit, '}' or ',' expected" -error.expected.brace2="Digit or '}' expected" +error.expected.brace1=Digit, '}' or ',' expected +error.expected.brace2=Digit or '}' expected error.expected.condition=Condition expected after ''{0}'' error.expected.condition.or.bracket=Condition or ']' expected +error.expected.end.quote='"' expected invalid.modifier.type=Invalid modifier type {0} SSRInspection.replace.with=Replace with ''{0}'' diff --git a/platform/structuralsearch/testData/java/ReformatAndShortenClassRefPerformance_pattern.java b/platform/structuralsearch/testData/java/ReformatAndShortenClassRefPerformance_pattern.java index 1200d6f9624f..4dd5df59b3c2 100644 --- a/platform/structuralsearch/testData/java/ReformatAndShortenClassRefPerformance_pattern.java +++ b/platform/structuralsearch/testData/java/ReformatAndShortenClassRefPerformance_pattern.java @@ -1 +1 @@ -assertTrue(StrictMath.abs('v1 - 'v2) < 't); \ No newline at end of file +assertTrue(StrictMath.abs('_v1 - '_v2) < '_t); \ No newline at end of file diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index a8d846767a86..6a656a736654 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -22,8 +22,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { public void testReplaceInLiterals() { String s1 = "String ID_SPEED = \"Speed\";"; - String s2 = "String 'name = \"'string\";"; - String s2_2 = "String 'name = \"'string:[regex( .* )]\";"; + String s2 = "String 'name = \"'_string\";"; + String s2_2 = "String 'name = \"'_string:[regex( .* )]\";"; String s3 = "VSegAttribute $name$ = new VSegAttribute(\"$string$\");"; String expectedResult = "VSegAttribute ID_SPEED = new VSegAttribute(\"Speed\");"; @@ -58,7 +58,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s7 = "IconLoader.getIcon(\"/ant/property.png\");\n" + "IconLoader.getIcon(\"/ant/another/property.png\");\n"; - String s8 = "IconLoader.getIcon(\"/'module/'name:[regex( \\w+ )].png\");"; + String s8 = "IconLoader.getIcon(\"/'_module/'_name:[regex( \\w+ )].png\");"; String s9 = "Icons.$module$.$name$;"; String expectedResult3 = "Icons.ant.property;\n" + "IconLoader.getIcon(\"/ant/another/property.png\");\n"; @@ -101,7 +101,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " JOptionPane.showMessageDialog(null, \"MESSAGE\");\n" + " }\n" + "}"; - String s2 = "JOptionPane.'showDialog(null, 'msg);"; + String s2 = "JOptionPane.'showDialog(null, '_msg);"; String s3 = "//FIXME provide a parent frame\n" + "JOptionPane.$showDialog$(null, $msg$);"; @@ -125,7 +125,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s4 = "myButton.setText(\"Ok\");"; - String s5 = "'Instance.'MethodCall:[regex( setText )]('Parameter*:[regex( \"Ok\" )]);"; + String s5 = "'_Instance.'_MethodCall:[regex( setText )]('_Parameter*:[regex( \"Ok\" )]);"; String s6 = "$Instance$.$MethodCall$(\"OK\");"; String expectedResult2 = "myButton.setText(\"OK\");"; @@ -155,9 +155,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " matches = testMatcher.findMatches(s7,s8, options);\n" + " if (matches.size()!=2) return false;"; - String str2=" lastTest = 'Descr;\n" + - " matches = testMatcher.findMatches('In,'Pattern, options);\n" + - " if (matches.size()!='Number) return false;"; + String str2=" lastTest = '_Descr;\n" + + " matches = testMatcher.findMatches('_In,'_Pattern, options);\n" + + " if (matches.size()!='_Number) return false;"; String str3 = "assertEquals($Descr$,testMatcher.findMatches($In$,$Pattern$, options).size(),$Number$);"; String expectedResult1 = "// searching for several constructions\n" + " lastTest = \"several constructions match\";\n" + @@ -191,7 +191,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals("Empty replacement",expectedResult2,actualResult); - String str5 = "testMatcher.findMatches('In,'Pattern, options).size()"; + String str5 = "testMatcher.findMatches('_In,'_Pattern, options).size()"; String str6 = "findMatchesCount($In$,$Pattern$)"; String expectedResult3="// searching for several constructions\n" + " lastTest = \"several constructions match\";\n" + @@ -220,9 +220,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " if (asyncMode) {\n" + " myTreeModel.nodesWereInserted(parentNode,new int[] {i} );\n" + " }"; - String str11 = " 'parentNode.insert('newNode, 'i);\n" + + String str11 = " '_parentNode.insert('_newNode, '_i);\n" + " if (asyncMode) {\n" + - " myTreeModel.nodesWereInserted('parentNode,new int[] {'i} );\n" + + " myTreeModel.nodesWereInserted('_parentNode,new int[] {'_i} );\n" + " }"; String str12 = "addChild($parentNode$,$newNode$, $i$);"; String expectedResult5 = " addChild(parentNode,compositeNode, i);"; @@ -231,7 +231,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals( "Array initializer replacement", expectedResult5,actualResult); String str13 = " aaa(5,6,3,4,1,2);"; - String str14 = "aaa('t{2,2},3,4,'q{2,2});"; + String str14 = "aaa('_t{2,2},3,4,'_q{2,2});"; String str15 = "aaa($q$,3,4,$t$);"; String expectedResult6 = " aaa(1,2,3,4,5,6);"; @@ -239,7 +239,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals("Parameter multiple match",expectedResult6,actualResult); String str16 = " int c = a();"; - String str17 = "'t:a ('q*,'p*)"; + String str17 = "'_t:a ('_q*,'_p*)"; String str18 = "$t$($q$,1,$p$)"; String expectedResult7 = " int c = a(1);"; @@ -255,7 +255,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals("One substition replacement",expectedResult8,actualResult); String str22 = " instance.setAAA(anotherInstance.getBBB());"; - String str23 = " 'i.'m:set(.+) ('a.'m2:get(.+) ());"; + String str23 = " '_i.'_m:set(.+) ('_a.'_m2:get(.+) ());"; String str24 = " $a$.set$m2_1$( $i$.get$m_1$() );"; String expectedResult9 = " anotherInstance.setBBB( instance.getAAA() );"; @@ -291,7 +291,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String str28 = "UTElementNode elementNode = new UTElementNode(myProject, processedElement, psiFile,\n" + " processedElement.getTextOffset(), true,\n" + " !myUsageViewDescriptor.toMarkInvalidOrReadonlyUsages(), null);"; - String str29 = "new UTElementNode('param, 'directory, 'null, '0, 'true, !'descr.toMarkInvalidOrReadonlyUsages(),\n" + + String str29 = "new UTElementNode('_param, '_directory, '_null, '_0, '_true, !'_descr.toMarkInvalidOrReadonlyUsages(),\n" + " 'referencesWord)"; String str30 = "new UTElementNode($param$, $directory$, $null$, $0$, $true$, true,\n" + " $referencesWord$)"; @@ -314,7 +314,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s34 = "ParamChecker.isTrue(1==1, \"!!!\");"; - String s35 = "ParamChecker.isTrue('expr, 'msg)"; + String s35 = "ParamChecker.isTrue('_expr, '_msg)"; String s36 = "assert $expr$ : $msg$"; String expectedResult13 = "assert 1==1 : \"!!!\";"; @@ -346,7 +346,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s40 = "ParamChecker.instanceOf(queryKey, GroupBySqlTypePolicy.GroupKey.class);"; - String s41 = "ParamChecker.instanceOf('obj, 'class.class);"; + String s41 = "ParamChecker.instanceOf('_obj, '_class.class);"; String s42 = "assert $obj$ instanceof $class$ : \"$obj$ is an instance of \" + $obj$.getClass() + \"; expected \" + $class$.class;"; String expectedResult15 = "assert queryKey instanceof GroupBySqlTypePolicy.GroupKey : \"queryKey is an instance of \" + queryKey.getClass() + \"; expected \" + GroupBySqlTypePolicy.GroupKey.class;"; @@ -361,7 +361,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " static final String TAG_BEAN_VALUE = \"\";\n" + "}\n" + "XmlTag beanTag = rootTag.findSubTag(Wpd.TAG_BEAN_VALUE);"; - String s44 = "'Instance?.findSubTag( 'Parameter:[exprtype( *String ) ])"; + String s44 = "'_Instance?.findSubTag( '_Parameter:[exprtype( *String ) ])"; String s45 = "jetbrains.fabrique.util.XmlApiUtil.findSubTag($Instance$, $Parameter$)"; String expectedResult16 = "class Wpd {\n" + " static final String TAG_BEAN_VALUE = \"\";\n" + @@ -398,7 +398,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s49 = "class A {}\n" + "class B extends A {}\n" + "A a = new B();"; - String s50 = "A 'b = new 'B:*A ();"; + String s50 = "A '_b = new '_B:*A ();"; String s51 = "A $b$ = new $B$(\"$b$\");"; String expectedResult18 = "class A {}\n" + "class B extends A {}\n" + @@ -430,8 +430,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "} catch(Exception ex) {\n" + " aaa5();\n" + "}\n"; - String s53 = "try { 'a; } finally {\n" + - " 'b;" + + String s53 = "try { '_a; } finally {\n" + + " '_b;" + "}"; String s54 = "$a$;"; String expectedResult19 = "aaa();\n" + @@ -501,7 +501,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s64 = "int x = 42;\n" + "int y = 42; // Stuff"; - String s65 = "'Type 'Variable = 'Value; // 'Comment"; + String s65 = "'_Type '_Variable = '_Value; // '_Comment"; String s66 = "/**\n" + " *$Comment$\n" + " */\n" + @@ -521,7 +521,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s61 = "try { 1=1; } catch(Exception e) { 1=1; } catch(Throwable t) { 2=2; }"; - String s62 = "try { 'a; } catch(Exception e) { 'b; }"; + String s62 = "try { '_a; } catch(Exception e) { '_b; }"; String s63 = "try { $a$; } catch(Exception1 e) { $b$; } catch(Exception2 e) { $b$; }"; String expectedResult22 = "try { 1=1; } catch(Exception1 e) { 1=1; } catch(Exception2 e) { 1=1; } catch (Throwable t) { 2=2; }"; @@ -697,10 +697,10 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "}"; String s8 = "new Runnable() {\n" + " public void run() {\n" + - " 'l ();\n" + + " '_l ();\n" + " }\n" + - " private void 'l () {\n" + - " 'st{2,2};\n" + + " private void '_l () {\n" + + " '_st{2,2};\n" + " }\n" + "};"; String s9 = "new My() {\n" + @@ -980,7 +980,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { options.setToReformatAccordingToStyle(true); String s1 = "class A { public void b() {} }"; - String s2 = "class 'a { 'Other* }"; + String s2 = "class 'a { '_Other* }"; String s3 = "class $a$New { Logger LOG; $Other$ }"; String expectedResult = " class ANew {\n" + " Logger LOG;\n\n" + @@ -996,7 +996,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s4 = "class A { class C {} public void b() {} int f; }"; - String s5 = "class 'a { 'Other* }"; + String s5 = "class 'a { '_Other* }"; String s6 = "class $a$ { Logger LOG; $Other$ }"; String expectedResult2 = " class A {\n" + " Logger LOG;\n\n" + @@ -1015,7 +1015,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { ); String s7 = "class A extends B { int c; void b() {} { a = 1; } }"; - String s8 = "class 'A extends B { 'Other* }"; + String s8 = "class 'A extends B { '_Other* }"; String s9 = "class $A$ extends B2 { $Other$ }"; String expectedResult3 = " class A extends B2 {\n" + " int c;\n\n" + @@ -1036,7 +1036,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " public void b() {}\n" + " int f;\n" + "}"; - String s11 = "class 'a { 'Other* }"; + String s11 = "class 'a { '_Other* }"; String s12 = "public class $a$ {\n" + " $Other$\n" + "}"; @@ -1068,9 +1068,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "}\n" + "}"; String s14 = "class 'Class extends Thread {\n" + - " 'Class('ParameterType* 'ParameterName*) {\n" + - "\t super (CustomThreadGroup.getThreadGroup(), 'superarg* );\n" + - " 'Statement*;\n" + + " 'Class('_ParameterType* '_ParameterName*) {\n" + + "\t super (CustomThreadGroup.getThreadGroup(), '_superarg* );\n" + + " '_Statement*;\n" + " }\n" + "}"; String s15 = "class $Class$ extends CustomThread {\n" + @@ -1100,8 +1100,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s16 = "public class A {}\n" + "final class B {}"; - String s17 = "class 'A { 'Other* }"; - String s17_2 = "class 'A { private Log log = LogFactory.createLog(); 'Other* }"; + String s17 = "class 'A { '_Other* }"; + String s17_2 = "class 'A { private Log log = LogFactory.createLog(); '_Other* }"; String s18 = "class $A$ { private Log log = LogFactory.createLog(); $Other$ }"; String s18_2 = "class $A$ { $Other$ }"; @@ -1116,7 +1116,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals("Removing field",expectedResult7,actualResult); String s19 = "public class A extends Object implements Cloneable {}\n"; - String s20 = "class 'A { 'Other* }"; + String s20 = "class 'A { '_Other* }"; String s21 = "class $A$ { private Log log = LogFactory.createLog(); $Other$ }"; actualResult = replacer.testReplace(s19,s20,s21,options); @@ -1124,7 +1124,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { assertEquals("Extends / implements list for class",expectedResult8,actualResult); String s22 = "public class A { int Afield; }\n"; - String s23 = "class 'A { 'Other* }"; + String s23 = "class 'A { '_Other* }"; String s24 = "class $A$ { private Log log = LogFactory.createLog(); $Other$ }"; actualResult = replacer.testReplace(s22,s23,s24,options); @@ -1152,8 +1152,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s28 = "aaa"; String s29 = "class 'Class {\n" + - " 'Class('ParameterType 'ParameterName) {\n" + - " 'Class('ParameterName);\n" + + " 'Class('_ParameterType '_ParameterName) {\n" + + " 'Class('_ParameterName);\n" + " }\n" + "}"; String s30 = "class $Class$ {\n" + @@ -1177,7 +1177,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " int c; // comment2\n" + "}"; - String s32 = "'Type 'Variable = 'Value?; //'Comment"; + String s32 = "'_Type 'Variable = '_Value?; //'_Comment"; String s33 = "/**$Comment$*/\n" + "$Type$ $Variable$ = $Value$;"; @@ -1212,7 +1212,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "}"; String s35 = "public interface 'MessageInterface {\n" + - " public static final String 'X = 'VALUE;\n" + + " public static final String '_X = '_VALUE;\n" + " 'blah*" + "}"; String s36 = "public interface $MessageInterface$ {\n" + @@ -1266,7 +1266,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " private int c = 2;\n" + "}"; - String s2 = "@Modifier(\"PackageLocal\") 'Type 'Instance = 'Init?;"; + String s2 = "@Modifier(\"PackageLocal\") '_Type '_Instance = '_Init?;"; String s3 = "public $Type$ $Instance$ = $Init$;"; String expectedResult = "class A {\n" + @@ -1348,7 +1348,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " /**\n" + " * zzz\n" + " */\n" + - " void f('t 'p){'s+;}\n" + + " void f('_t '_p){'_s+;}\n" + "}"; String s3 = "class $c$ {\n" + " /**\n" + @@ -1408,13 +1408,13 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "}"; String s2 = "/**\n" + "* Created by IntelliJ IDEA.\n" + - "* User: 'USER\n" + - "* Date: 'DATE\n" + - "* Time: 'TIME\n" + + "* User: '_USER\n" + + "* Date: '_DATE\n" + + "* Time: '_TIME\n" + "* To change this template use File | Settings | File Templates.\n" + "*/\n" + "class 'c {\n" + - " 'other*\n" + + " '_other*\n" + "}"; String s3 = "/**\n" + "* by: $USER$\n" + @@ -1469,11 +1469,11 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { public void testClassReplacement9() throws IOException { String s1 = loadFile("before1.java"); - String s2 = "class 'A extends 'TestCaseCass:[regex( .*TestCase ) ] {\n" + - " 'OtherStatement*;\n" + - " public void 'testMethod*:[regex( test.* )] () {\n" + + String s2 = "class 'A extends '_TestCaseCass:[regex( .*TestCase ) ] {\n" + + " '_OtherStatement*;\n" + + " public void '_testMethod*:[regex( test.* )] () {\n" + " }\n" + - " 'OtherStatement2*;\n" + + " '_OtherStatement2*;\n" + "}"; String s3 = "class $A$ extends $TestCaseCass$ {\n" + " $OtherStatement$;\n" + @@ -1560,7 +1560,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String actualResult; String s43 = "public @Deprecated class Foo implements Comparable {\n int x;\n void m(){}\n }"; - String s44 = "class 'Class implements 'Interface { 'Content* }"; + String s44 = "class 'Class implements '_Interface { '_Content* }"; String s45 = "@MyAnnotation\n" + "class $Class$ implements $Interface$ {$Content$}"; String expectedResult16 = "@MyAnnotation public @Deprecated\n" + @@ -1579,7 +1579,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String actualResult; String s43 = "public @Deprecated class Foo implements Comparable {\n int x;\n void m(){}\n }"; - String s44 = "class 'Class implements 'Interface {}"; + String s44 = "class 'Class implements '_Interface {}"; String s45 = "@MyAnnotation\n" + "class $Class$ implements $Interface$ {}"; String expectedResult16 = "@MyAnnotation public @Deprecated\n" + @@ -1794,7 +1794,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " catch (final Exception e)\n" + " { continue; }\n" + "}"; - String toFind = "try { 'TryStatement*; } catch(Exception 'ExceptionDcl) { 'CatchStatement*; }"; + String toFind = "try { '_TryStatement*; } catch(Exception '_ExceptionDcl) { '_CatchStatement*; }"; String replacement = "try { $TryStatement$; }\n" + "catch(Throwable $ExceptionDcl$) { $CatchStatement$; }"; String expectedResult = "for (int i = 0; i < MIMEHelper.MIME_MAP.length; i++)\n" + "{\n" + @@ -1841,7 +1841,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " Math.sin(0.5);\n" + " Math.max(1, 2);\n" + "}}"; - final String what = "Math.'m('a*)"; + final String what = "Math.'m('_a*)"; final String by = "Math.$m$($a$)"; options.setToUseStaticImport(true); @@ -1961,7 +1961,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " } catch (PersistenceException e) {\n" + " // good\n" + " }"; - String s2 = "try { 'TryStatement; } catch('ExceptionType 'ExceptionDcl) { /* 'CommentContent */ }"; + String s2 = "try { '_TryStatement; } catch('_ExceptionType '_ExceptionDcl) { /* '_CommentContent */ }"; String replacement = "try { $TryStatement$; } catch($ExceptionType$ $ExceptionDcl$) { _logger.warning(\"$CommentContent$\", $ExceptionDcl$); }"; String expected = "try { em.persist(p); } catch(PersistenceException e) { _logger.warning(\" good\", e); }"; @@ -2077,9 +2077,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "a = 2;\n" + "int b = a;\n" + "b2 = 3;"; - String s2 = "int 'a = 'i;\n" + - "'st*;\n" + - "'a = 'c;"; + String s2 = "int '_a = '_i;\n" + + "'_st*;\n" + + "'_a = '_c;"; String s3 = "$st$;\n" + "$c$ = $i$;"; @@ -2092,9 +2092,9 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { actualResult ); - String s2_2 = "int 'a = 'i;\n" + - "'st*;\n" + - "int 'c = 'a;"; + String s2_2 = "int '_a = '_i;\n" + + "'_st*;\n" + + "int '_c = '_a;"; String s3_2 = "$st$;\n" + "int $c$ = $i$;"; String expected_2 = "a = 2;\nint b = 1;\nb2 = 3;"; @@ -2123,7 +2123,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { public void testReplaceMultipleFieldsInSingleDeclaration() { String source = "abstract class MyClass implements java.util.List {\n private String a, b;\n}"; - String search = "class 'Name implements java.util.List {\n 'ClassContent*\n}"; + String search = "class 'Name implements java.util.List {\n '_ClassContent*\n}"; String replace = "class $Name$ {\n $ClassContent$\n}"; String expectedResult = "abstract class MyClass {\n private String a,b;\n}"; @@ -2139,7 +2139,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String source = "import java.io.Externalizable;\n" + "import java.io.Serializable;\n" + "abstract class MyClass implements Serializable, java.util.List, Externalizable {}"; - String search = "class 'TestCase implements java.util.List, 'others* {\n 'MyClassContent\n}"; + String search = "class 'TestCase implements java.util.List, '_others* {\n '_MyClassContent\n}"; String replace = "class $TestCase$ implements $others$ {\n $MyClassContent$\n}"; String expectedResult = "import java.io.Externalizable;\n" + "import java.io.Serializable;\n" + @@ -2158,7 +2158,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " public void foo() {\n" + " }\n" + "}"; - String search = "class 'Class {\n 'Content*\n}"; + String search = "class 'Class {\n '_Content*\n}"; String replace = "class $Class$ {\n" + " void x() {}\n" + " $Content$\n" + diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index ef53d82b13ed..fbc3533e6887 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -826,7 +826,7 @@ public class StructuralSearchTest extends StructuralSearchTestCase { String s10031 = "try { a(); } catch(Exception ex) {} catch(Error error) { 1=1; }\n" + "try { a(); } catch(Exception ex) {}"; - String s10032 = "try { a(); } catch('_Type+ 'Arg+) { 'Statements*; }\n"; + String s10032 = "try { a(); } catch('_Type+ 'Arg+) { '_Statements*; }\n"; assertEquals( "finally matching", 2, @@ -2440,12 +2440,12 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "@Foo(value2=baz4) int a3;\n" + "}"; String s12 = "@Foo(value=baz) int 'a;)"; - String s12_2 = "@Foo(value='baz:baz2 ) int 'a;)"; - String s12_3 = "@Foo('value:value2 = baz3 ) int 'a;)"; - String s12_4 = "@Foo('value:value2 = 'baz3:baz3 ) int 'a;)"; - String s12_5 = "@Foo('value:value2 = 'baz3:baz ) int 'a;)"; - String s12_6 = "@Foo('value:value2 = 'baz3 ) int 'a;)"; - String s12_7 = "@Foo('value:value2 = ) int 'a;"; + String s12_2 = "@Foo(value='baz:baz2 ) int '_a;)"; + String s12_3 = "@Foo('value:value2 = baz3 ) int '_a;)"; + String s12_4 = "@Foo('value:value2 = '_baz3:baz3 ) int '_a;)"; + String s12_5 = "@Foo('value:value2 = '_baz3:baz ) int '_a;)"; + String s12_6 = "@Foo('value:value2 = '_baz3 ) int '_a;)"; + String s12_7 = "@Foo('value:value2 = ) int '_a;"; assertEquals("Find anno parameter value",1,findMatchesCount(s11,s12)); assertEquals("Find anno parameter value",2,findMatchesCount(s11,s12_2)); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java index dc1cbc5802f2..5cb376225ed3 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java @@ -4,6 +4,7 @@ import com.intellij.structuralsearch.MalformedPatternException; import com.intellij.structuralsearch.MatchOptions; import com.intellij.structuralsearch.MatchVariableConstraint; import com.intellij.structuralsearch.UnsupportedPatternException; +import com.intellij.structuralsearch.plugin.ui.Configuration; import org.junit.Before; import org.junit.Test; @@ -121,6 +122,14 @@ public class StringToConstraintsTransformerTest { assertEquals("$a$::$b$", myOptions.getSearchPattern()); } + @Test + public void testScriptEscaping() { + test("'_type 'a:[within( \"if ('_a:[regex( .*e.* )\\]) { '_st*; }\" )] = '_b;"); + assertEquals("$type$ $a$ = $b$;", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint = myOptions.getVariableConstraint(Configuration.CONTEXT_VAR_NAME); + assertEquals("\"if ('_a:[regex( .*e.* )]) { '_st*; }\"", constraint.getWithinConstraint()); + } + private void test(String pattern) { myOptions.setSearchPattern(pattern); StringToConstraintsTransformer.transformOldPattern(myOptions); diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 4cb8e83f374c..9f63e177e0a6 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -815,7 +815,7 @@ public class ContainerUtil extends ContainerUtilRt { @Nullable @Contract(pure=true) - public static T find(@NotNull Iterable iterable, final T equalTo) { + public static T find(@NotNull Iterable iterable, @NotNull final T equalTo) { return find(iterable, new Condition() { @Override public boolean value(final T object) { diff --git a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java index dd20dc36b0ca..76f20c182bc4 100644 --- a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,7 +31,7 @@ import java.util.Map; abstract class AbstractCollectionBinding extends Binding implements MultiNodeBinding { private Map myElementBindings; - private final Class myElementType; + private final Class myElementType; private final String myTagName; private final AbstractCollection myAnnotation; @@ -247,7 +247,7 @@ abstract class AbstractCollectionBinding extends Binding implements MultiNodeBin return myAnnotation == null || myAnnotation.surroundWithTag() ? getCollectionTagName(target) : null; } - protected String getCollectionTagName(final Object target) { + protected String getCollectionTagName(Object target) { return myTagName; } } diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index 3995cafbc9f1..f6f7a9b7b5eb 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -301,14 +301,17 @@ class BeanBinding extends Binding { do { for (Field field : currentClass.getDeclaredFields()) { int modifiers = field.getModifiers(); + //noinspection deprecation if (!Modifier.isStatic(modifiers) && (field.getAnnotation(OptionTag.class) != null || field.getAnnotation(Tag.class) != null || field.getAnnotation(Attribute.class) != null || field.getAnnotation(Property.class) != null || field.getAnnotation(Text.class) != null || + field.getAnnotation(CollectionBean.class) != null || (Modifier.isPublic(modifiers) && - !Modifier.isFinal(modifiers) && + // we don't want to allow final fields of all types, but only supported + (!Modifier.isFinal(modifiers) || Collection.class.isAssignableFrom(field.getType())) && !Modifier.isTransient(modifiers) && field.getAnnotation(Transient.class) == null))) { accessors.add(new FieldAccessor(field)); @@ -361,7 +364,7 @@ class BeanBinding extends Binding { return new TextBinding(accessor); } - if (binding instanceof JDOMExternalizableStringListBinding) { + if (binding instanceof CompactCollectionBinding) { return new AccessorBindingWrapper(accessor, binding); } diff --git a/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java index 622616bdb7fe..dda4a196eedc 100644 --- a/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,16 +22,13 @@ import java.lang.reflect.Type; import java.util.*; class CollectionBinding extends AbstractCollectionBinding { - public CollectionBinding(ParameterizedType type, final Accessor accessor) { + public CollectionBinding(ParameterizedType type, Accessor accessor) { super(getComponentClass(type), Constants.COLLECTION, accessor); } - private static Class getComponentClass(ParameterizedType type) { + private static Class getComponentClass(@NotNull ParameterizedType type) { Type arg = type.getActualTypeArguments()[0]; - if (arg instanceof ParameterizedType) { - return (Class)((ParameterizedType)arg).getRawType(); - } - return (Class)arg; + return arg instanceof ParameterizedType ? (Class)((ParameterizedType)arg).getRawType() : (Class)arg; } @Override @@ -58,7 +55,7 @@ class CollectionBinding extends AbstractCollectionBinding { } @Override - protected String getCollectionTagName(final Object target) { + protected String getCollectionTagName(Object target) { if (target instanceof Set) { return Constants.SET; } diff --git a/platform/util/src/com/intellij/util/xmlb/CompactCollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/CompactCollectionBinding.java new file mode 100644 index 000000000000..a1686a75b16b --- /dev/null +++ b/platform/util/src/com/intellij/util/xmlb/CompactCollectionBinding.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2015 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.util.xmlb; + +import com.intellij.util.containers.ContainerUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @see com.intellij.util.xmlb.annotations.CollectionBean + */ +class CompactCollectionBinding extends Binding { + private final String name; + + protected CompactCollectionBinding(@NotNull Accessor accessor) { + super(accessor); + + name = myAccessor.getName(); + } + + @Nullable + @Override + public Object serialize(Object o, @Nullable Object context, SerializationFilter filter) { + Element result = new Element(name); + @SuppressWarnings("unchecked") + List list = (List)o; + if (list == null || list.isEmpty()) { + return result; + } + + for (String item : list) { + result.addContent(new Element("item").setAttribute("value", item)); + } + return result; + } + + @Nullable + @Override + public Object deserialize(Object context, @NotNull Object node) { + @SuppressWarnings("unchecked") + List list = (List)context; + list.clear(); + Element element = (Element)node; + if (element.getName().equals(name)) { + for (Element item : element.getChildren("item")) { + ContainerUtil.addIfNotNull(list, item.getAttributeValue("value")); + } + } + else { + // JDOMExternalizableStringList format + Element value = element.getChild("value"); + if (value != null) { + value = value.getChild("list"); + } + if (value != null) { + for (Element item : value.getChildren("item")) { + //noinspection SpellCheckingInspection + ContainerUtil.addIfNotNull(list, item.getAttributeValue("itemvalue")); + } + } + } + return list; + } + + @Override + public boolean isBoundTo(Object node) { + if (node instanceof Element) { + Element element = (Element)node; + String elementName = element.getName(); + if (isNameEqual(elementName)) { + return true; + } + else if (elementName.equals(Constants.OPTION)) { + // JDOMExternalizableStringList format + return isNameEqual(element.getAttributeValue(Constants.NAME)); + } + } + return false; + } + + private boolean isNameEqual(@Nullable String value) { + if (value == null) { + return false; + } + else if (value.equals(name)) { + return true; + } + else if (value.length() == (name.length() + 2) && value.startsWith("my")) { + return Character.isUpperCase(value.charAt(2)) && value.regionMatches(true, 2, name, 0, name.length()); + } + else { + return false; + } + } + + @Override + public Class getBoundNodeType() { + return Element.class; + } +} diff --git a/platform/util/src/com/intellij/util/xmlb/JDOMExternalizableStringListBinding.java b/platform/util/src/com/intellij/util/xmlb/JDOMExternalizableStringListBinding.java deleted file mode 100644 index 346c616f59f1..000000000000 --- a/platform/util/src/com/intellij/util/xmlb/JDOMExternalizableStringListBinding.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.util.xmlb; - -import com.intellij.openapi.util.JDOMExternalizableStringList; -import com.intellij.util.containers.ContainerUtil; -import org.jdom.Element; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@SuppressWarnings("deprecation") -class JDOMExternalizableStringListBinding extends Binding { - private final String myName; - - protected JDOMExternalizableStringListBinding(@NotNull Accessor accessor) { - super(accessor); - - myName = myAccessor.getName(); - } - - @Nullable - @Override - public Object serialize(Object o, @Nullable Object context, SerializationFilter filter) { - Element result = new Element(myName); - JDOMExternalizableStringList list = (JDOMExternalizableStringList)o; - if (list == null || list.isEmpty()) { - return result; - } - - for (String item : list) { - result.addContent(new Element("item").setAttribute("value", item)); - } - return result; - } - - @Nullable - @Override - public Object deserialize(Object context, @NotNull Object node) { - JDOMExternalizableStringList list = (JDOMExternalizableStringList)context; - list.clear(); - for (Element item : ((Element)node).getChildren("item")) { - ContainerUtil.addIfNotNull(list, item.getAttributeValue("value")); - } - return list; - } - - @Override - public boolean isBoundTo(Object node) { - return node instanceof Element && ((Element)node).getName().equals(myName); - } - - @Override - public Class getBoundNodeType() { - return Element.class; - } -} diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index f67982f670d4..11a7ef5ef885 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,12 +18,12 @@ package com.intellij.util.xmlb; import com.intellij.openapi.util.JDOMExternalizableStringList; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.xmlb.annotations.CollectionBean; import org.jdom.*; import org.jdom.filter.Filter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.annotation.Annotation; import java.lang.ref.SoftReference; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -119,7 +119,8 @@ class XmlSerializerImpl { map.put(key, binding); try { binding.init(); - } catch (XmlSerializationException e) { + } + catch (XmlSerializationException e) { map.remove(key); throw e; } @@ -156,6 +157,12 @@ class XmlSerializerImpl { return new PrimitiveValueBinding(aClass, accessor); } if (Collection.class.isAssignableFrom(aClass) && originalType instanceof ParameterizedType) { + if (accessor != null) { + CollectionBean listBean = accessor.getAnnotation(CollectionBean.class); + if (listBean != null) { + return new CompactCollectionBinding(accessor); + } + } return new CollectionBinding((ParameterizedType)originalType, accessor); } if (accessor != null) { @@ -167,7 +174,7 @@ class XmlSerializerImpl { } //noinspection deprecation if (JDOMExternalizableStringList.class == aClass) { - return new JDOMExternalizableStringListBinding(accessor); + return new CompactCollectionBinding(accessor); } } if (Date.class.isAssignableFrom(aClass)) { @@ -179,21 +186,6 @@ class XmlSerializerImpl { return new BeanBinding(aClass, accessor); } - @Nullable - @Deprecated - @SuppressWarnings({"unchecked", "unused"}) - /** - * @deprecated to remove in IDEA 15 - */ - static T findAnnotation(Annotation[] annotations, Class aClass) { - if (annotations == null) return null; - - for (Annotation annotation : annotations) { - if (aClass.isAssignableFrom(annotation.getClass())) return (T)annotation; - } - return null; - } - @Nullable @SuppressWarnings({"unchecked"}) static T convert(Object value, Class type) { diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/AbstractCollection.java b/platform/util/src/com/intellij/util/xmlb/annotations/AbstractCollection.java index 9a08e253f0e3..fc7cd5c59180 100644 --- a/platform/util/src/com/intellij/util/xmlb/annotations/AbstractCollection.java +++ b/platform/util/src/com/intellij/util/xmlb/annotations/AbstractCollection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb.annotations; import com.intellij.util.xmlb.Constants; diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/CollectionBean.java b/platform/util/src/com/intellij/util/xmlb/annotations/CollectionBean.java new file mode 100644 index 000000000000..da60e05b4ef4 --- /dev/null +++ b/platform/util/src/com/intellij/util/xmlb/annotations/CollectionBean.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2015 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.util.xmlb.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +/** + * Can read serialized JDOMExternalizableStringList, but in any case will be written in this bean format. + * It is useful for application-level config, but for project-level consider to use ConverterProvider. + * + * Currently, only string element type supported. + */ +public @interface CollectionBean { +} diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index d318dc2f8cd4..f5e341b403a9 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.JDOMExternalizableStringList; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.SmartList; import com.intellij.util.xmlb.annotations.*; import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -1259,6 +1260,12 @@ public class XmlSerializerTest extends TestCase { public JDOMExternalizableStringList list = new JDOMExternalizableStringList(); } + @Tag("b") + static class Bean4 { + @CollectionBean + public final List list = new SmartList(); + } + @SuppressWarnings("deprecation") public void testJDOMExternalizableStringList() throws IOException, JDOMException { Bean3 bean = new Bean3(); @@ -1274,6 +1281,39 @@ public class XmlSerializerTest extends TestCase { "", bean, new SkipDefaultsSerializationFilter()); } + public void testCollectionBean() throws IOException, JDOMException { + Bean4 bean = new Bean4(); + bean.list.add("one"); + bean.list.add("two"); + bean.list.add("three"); + doSerializerTest("\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "", bean, new SkipDefaultsSerializationFilter()); + } + + public void testCollectionBeanReadJDOMExternalizableStringList() throws IOException, JDOMException { + @SuppressWarnings("deprecation") + JDOMExternalizableStringList list = new JDOMExternalizableStringList(); + list.add("one"); + list.add("two"); + list.add("three"); + + Element value = new Element("value"); + list.writeExternal(value); + Bean4 o = XmlSerializer.deserialize(new Element("state").addContent(new Element("option").setAttribute("name", "myList").addContent(value)), Bean4.class); + assertSerializer(o, "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "", "Deserialization failure", new SkipDefaultsSerializationFilter()); + } + private static void checkSmartSerialization(@NotNull Bean2 bean, @NotNull String serialized) throws IOException, JDOMException { SmartSerializer serializer = new SmartSerializer(); serializer.readExternal(bean, JDOMUtil.loadDocument(serialized).getRootElement()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java index 52481d46aae0..f115c3c36f3f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java @@ -25,7 +25,6 @@ import com.intellij.diff.util.WaitingBackgroundableTaskExecutor; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; @@ -34,6 +33,7 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.actions.diff.ChangeDiffRequestProducer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.*; @@ -119,12 +119,6 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor { } if (change.getBeforeRevision() instanceof FakeRevision || change.getAfterRevision() instanceof FakeRevision) { - ChangeListManager.getInstance(myProject).invokeAfterUpdate(new Runnable() { - @Override - public void run() { - refresh(); // TODO: this could cause diff init in 'hide' state - } - }, InvokeAfterUpdateMode.SILENT, "", ModalityState.current()); return new LoadingDiffRequest(ChangeDiffRequestProducer.getRequestTitle(change)); } @@ -193,9 +187,17 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor { return; } - if (selectedChanges.contains(myCurrentChange)) return; - myCurrentChange = selectedChanges.get(0); - updateRequest(); + Change selectedChange = myCurrentChange != null ? ContainerUtil.find(selectedChanges, myCurrentChange) : null; + if (selectedChange == null) { + myCurrentChange = selectedChanges.get(0); + updateRequest(); + return; + } + + if (myCurrentChange.getBeforeRevision() instanceof FakeRevision || myCurrentChange.getAfterRevision() instanceof FakeRevision) { + myCurrentChange = selectedChange; + updateRequest(); + } } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java index a24618215fde..f629904d14cc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AppUIUtil; import com.intellij.util.SmartList; +import com.intellij.util.containers.IntIntHashMap; import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -102,7 +103,7 @@ public abstract class XFetchValueActionBase extends AnAction { protected class ValueCollector { private final List values = new SmartList(); - private final List indents = new SmartList(); + private final IntIntHashMap indents = new IntIntHashMap(); private final XDebuggerTree myTree; private volatile boolean processed; @@ -111,18 +112,18 @@ public abstract class XFetchValueActionBase extends AnAction { } public void add(@NotNull String value) { - add(value, 0); + values.add(value); } public void add(@NotNull String value, int indent) { values.add(value); - indents.add(indent); + indents.put(values.size() - 1, indent); } public void finish(Project project) { if (processed && !values.contains(null) && !project.isDisposed()) { int minIndent = Integer.MAX_VALUE; - for (Integer indent : indents) { + for (int indent : indents.getValues()) { minIndent = Math.min(minIndent, indent); } StringBuilder sb = new StringBuilder(); @@ -130,8 +131,10 @@ public abstract class XFetchValueActionBase extends AnAction { if (i > 0) { sb.append("\n"); } - Integer indent = indents.get(i); - StringUtil.repeatSymbol(sb, ' ', indent - minIndent); + int indent = indents.get(i); + if (indent > 0) { + StringUtil.repeatSymbol(sb, ' ', indent - minIndent); + } sb.append(values.get(i)); } handleInCollector(project, sb.toString(), myTree); diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index 73c35b7aa75f..26407888482e 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -46,6 +46,7 @@ + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java index 55257bd4eec4..37a7442e3eb4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java @@ -15,50 +15,14 @@ */ package org.jetbrains.plugins.gradle.service.settings; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.externalSystem.model.settings.LocationSettingType; import com.intellij.openapi.externalSystem.service.settings.AbstractExternalProjectSettingsControl; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; -import com.intellij.openapi.externalSystem.service.ui.ExternalSystemJdkComboBox; -import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; import com.intellij.openapi.externalSystem.util.PaintAwarePanel; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.MessageType; -import com.intellij.openapi.ui.TextComponentAccessor; -import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.components.JBLabel; -import com.intellij.ui.components.JBRadioButton; -import com.intellij.util.Alarm; -import com.intellij.util.Consumer; -import com.intellij.util.ObjectUtils; -import com.intellij.util.ui.UIUtil; -import org.gradle.util.GradleVersion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.service.GradleInstallationManager; -import org.jetbrains.plugins.gradle.settings.DistributionType; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; -import org.jetbrains.plugins.gradle.util.GradleBundle; -import org.jetbrains.plugins.gradle.util.GradleConstants; -import org.jetbrains.plugins.gradle.util.GradleUtil; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.util.concurrent.TimeUnit; - -import static com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_PROJECT_JDK; /** * @author Denis Zhdanov @@ -66,354 +30,49 @@ import static com.intellij.openapi.externalSystem.service.execution.ExternalSyst */ public class GradleProjectSettingsControl extends AbstractExternalProjectSettingsControl { - private static final long BALLOON_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(1); - - @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - - @NotNull private LocationSettingType myGradleHomeSettingType = LocationSettingType.UNKNOWN; - - @NotNull private final GradleInstallationManager myInstallationManager; - - @SuppressWarnings("FieldCanBeLocal") // Used implicitly by reflection at disposeUIResources() and showUi() - private JLabel myGradleHomeLabel; - @SuppressWarnings("FieldCanBeLocal") // Used implicitly by reflection at disposeUIResources() and showUi() - private JLabel myGradleJdkLabel; - private ExternalSystemJdkComboBox myGradleJdkComboBox; - private TextFieldWithBrowseButton myGradleHomePathField; - private JBRadioButton myUseWrapperButton; - private JBRadioButton myUseWrapperWithVerificationButton; - private JBLabel myUseWrapperVerificationLabel; - private JBRadioButton myUseLocalDistributionButton; - private JBRadioButton myUseBundledDistributionButton; - - private boolean myShowBalloonIfNecessary; + private final GradleProjectSettingsControlBuilder myBuilder; public GradleProjectSettingsControl(@NotNull GradleProjectSettings initialSettings) { - super(initialSettings); - myInstallationManager = ServiceManager.getService(GradleInstallationManager.class); + this(GradleSettingsControlProvider.get().getProjectSettingsControlBuilder(initialSettings)); + } + + public GradleProjectSettingsControl(@NotNull GradleProjectSettingsControlBuilder builder) { + super(null, builder.getInitialSettings(), builder.getExternalSystemSettingsControlCustomizer()); + myBuilder = builder; } @Override protected void fillExtraControls(@NotNull PaintAwarePanel content, int indentLevel) { - content.setPaintCallback(new Consumer() { - @Override - public void consume(Graphics graphics) { - showBalloonIfNecessary(); - } - }); - - content.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (!"ancestor".equals(evt.getPropertyName())) { - return; - } - - // Configure the balloon to show on initial configurable drawing. - myShowBalloonIfNecessary = evt.getNewValue() != null && evt.getOldValue() == null; - - if (evt.getNewValue() == null && evt.getOldValue() != null) { - // Cancel delayed balloons when the configurable is hidden. - myAlarm.cancelAllRequests(); - } - } - }); - - myGradleHomeLabel = new JBLabel(GradleBundle.message("gradle.settings.text.home.path")); - initGradleHome(); - myGradleJdkLabel = new JBLabel(GradleBundle.message("gradle.settings.text.jvm.path")); - myGradleJdkComboBox = new ExternalSystemJdkComboBox().withoutJre(); - - initControls(); - content.add(myUseWrapperButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); - content.add(myUseWrapperWithVerificationButton, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); - content.add(myUseWrapperVerificationLabel, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); - //content.add(Box.createGlue(), ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); - // Hide bundled distribution option for a while - // content.add(myUseBundledDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); - content.add(myUseLocalDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); - - content.add(myGradleHomeLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); - content.add(myGradleHomePathField, ExternalSystemUiUtil.getFillLineConstraints(0)); - - content.add(myGradleJdkLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); - content.add(myGradleJdkComboBox, ExternalSystemUiUtil.getFillLineConstraints(0)); - } - - private void initControls() { - ActionListener listener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - boolean localDistributionEnabled = myUseLocalDistributionButton.isSelected(); - myGradleHomePathField.setEnabled(localDistributionEnabled); - if (localDistributionEnabled) { - if(myGradleHomePathField.getText().isEmpty()){ - deduceGradleHomeIfPossible(); - } else { - if(myInstallationManager.isGradleSdkHome(myGradleHomePathField.getText())){ - myGradleHomeSettingType = LocationSettingType.EXPLICIT_CORRECT; - } else { - myGradleHomeSettingType = LocationSettingType.EXPLICIT_INCORRECT; - myShowBalloonIfNecessary = true; - } - } - showBalloonIfNecessary(); - } - else { - myAlarm.cancelAllRequests(); - } - } - }; - - myUseWrapperButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.default_wrapper.configured")); - myUseWrapperButton.addActionListener(listener); - myUseWrapperWithVerificationButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.customizable_wrapper")); - myUseWrapperWithVerificationButton.addActionListener(listener); - myUseWrapperVerificationLabel = new JBLabel(GradleBundle.message("gradle.settings.text.wrapper.customization.compatibility")); - myUseWrapperVerificationLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.MINI)); - myUseWrapperVerificationLabel.setIcon(UIUtil.getBalloonInformationIcon()); - - myUseLocalDistributionButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.local.distribution")); - myUseLocalDistributionButton.addActionListener(listener); - - myUseBundledDistributionButton = new JBRadioButton( - GradleBundle.message("gradle.settings.text.use.bundled.distribution", GradleVersion.current().getVersion())); - myUseBundledDistributionButton.addActionListener(listener); - myUseBundledDistributionButton.setEnabled(false); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(myUseWrapperButton); - buttonGroup.add(myUseWrapperWithVerificationButton); - buttonGroup.add(myUseBundledDistributionButton); - buttonGroup.add(myUseLocalDistributionButton); - } - - private void initGradleHome() { - myGradleHomePathField = new TextFieldWithBrowseButton(); - - FileChooserDescriptor fileChooserDescriptor = GradleUtil.getGradleHomeFileChooserDescriptor(); - - myGradleHomePathField.addBrowseFolderListener( - "", - GradleBundle.message("gradle.settings.text.home.path"), - null, - fileChooserDescriptor, - TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT, - false - ); - myGradleHomePathField.getTextField().getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); - } - - @Override - public void removeUpdate(DocumentEvent e) { - myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); - } - - @Override - public void changedUpdate(DocumentEvent e) { - } - }); + myBuilder.createAndFillControls(content, indentLevel); } @Override public boolean validate(@NotNull GradleProjectSettings settings) throws ConfigurationException { - String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); - if (myUseLocalDistributionButton.isSelected()) { - if (StringUtil.isEmpty(gradleHomePath)) { - myGradleHomeSettingType = LocationSettingType.UNKNOWN; - throw new ConfigurationException(GradleBundle.message("gradle.home.setting.type.explicit.empty", gradleHomePath)); - } - else if (!myInstallationManager.isGradleSdkHome(new File(gradleHomePath))) { - myGradleHomeSettingType = LocationSettingType.EXPLICIT_INCORRECT; - new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); - throw new ConfigurationException(GradleBundle.message("gradle.home.setting.type.explicit.incorrect", gradleHomePath)); - } - } - return true; + return myBuilder.validate(settings); } @Override protected void applyExtraSettings(@NotNull GradleProjectSettings settings) { - String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); - if (StringUtil.isEmpty(gradleHomePath)) { - settings.setGradleHome(null); - } - else { - settings.setGradleHome(gradleHomePath); - GradleUtil.storeLastUsedGradleHome(gradleHomePath); - } - - final String gradleJvm = FileUtil.toCanonicalPath(myGradleJdkComboBox.getSelectedValue()); - settings.setGradleJvm(StringUtil.isEmpty(gradleJvm) ? null : gradleJvm); - - if (myUseLocalDistributionButton.isSelected()) { - settings.setDistributionType(DistributionType.LOCAL); - } else if(myUseWrapperButton.isSelected()) { - settings.setDistributionType(DistributionType.DEFAULT_WRAPPED); - } else if(myUseWrapperWithVerificationButton.isSelected() || myUseBundledDistributionButton.isSelected()) { - settings.setDistributionType(DistributionType.WRAPPED); - } + myBuilder.apply(settings); } @Override protected void updateInitialExtraSettings() { - String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); - getInitialSettings().setGradleHome(StringUtil.isEmpty(gradleHomePath) ? null : gradleHomePath); - final String gradleJvm = FileUtil.toCanonicalPath(myGradleJdkComboBox.getSelectedValue()); - getInitialSettings().setGradleJvm(StringUtil.isEmpty(gradleJvm) ? null : gradleJvm); - if (myUseLocalDistributionButton.isSelected()) { - getInitialSettings().setDistributionType(DistributionType.LOCAL); - } else if(myUseWrapperButton.isSelected()) { - getInitialSettings().setDistributionType(DistributionType.DEFAULT_WRAPPED); - } else if(myUseWrapperWithVerificationButton.isSelected() || myUseBundledDistributionButton.isSelected()) { - getInitialSettings().setDistributionType(DistributionType.WRAPPED); - } + myBuilder.apply(getInitialSettings()); } @Override protected boolean isExtraSettingModified() { - DistributionType distributionType = getInitialSettings().getDistributionType(); - if (myUseBundledDistributionButton.isSelected() && distributionType != DistributionType.BUNDLED) { - return true; - } - - if (myUseWrapperButton.isSelected() && distributionType != DistributionType.DEFAULT_WRAPPED) { - return true; - } - - if (myUseWrapperWithVerificationButton.isSelected() && distributionType != DistributionType.WRAPPED) { - return true; - } - - if (myUseLocalDistributionButton.isSelected() && distributionType != DistributionType.LOCAL) { - return true; - } - - if (!StringUtil.equals(myGradleJdkComboBox.getSelectedValue(), getInitialSettings().getGradleJvm())) { - return true; - } - - String gradleHome = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); - if (StringUtil.isEmpty(gradleHome)) { - return !StringUtil.isEmpty(getInitialSettings().getGradleHome()); - } - else { - return !gradleHome.equals(getInitialSettings().getGradleHome()); - } + return myBuilder.isModified(getInitialSettings()); } @Override protected void resetExtraSettings(boolean isDefaultModuleCreation) { - String gradleHome = getInitialSettings().getGradleHome(); - myGradleHomePathField.setText(gradleHome == null ? "" : gradleHome); - myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); - - resetGradleJdkComboBox(getProject()); - - updateWrapperControls(getInitialSettings().getExternalProjectPath(), isDefaultModuleCreation); - if (!myUseLocalDistributionButton.isSelected()) { - myGradleHomePathField.setEnabled(false); - return; - } - - if (StringUtil.isEmpty(gradleHome)) { - myGradleHomeSettingType = LocationSettingType.UNKNOWN; - deduceGradleHomeIfPossible(); - } - else { - myGradleHomeSettingType = myInstallationManager.isGradleSdkHome(new File(gradleHome)) ? - LocationSettingType.EXPLICIT_CORRECT : - LocationSettingType.EXPLICIT_INCORRECT; - myAlarm.cancelAllRequests(); - if (myGradleHomeSettingType == LocationSettingType.EXPLICIT_INCORRECT && - getInitialSettings().getDistributionType() == DistributionType.LOCAL) { - new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); - } - } + myBuilder.reset(getProject(), getInitialSettings(), isDefaultModuleCreation); } - public void updateWrapperControls(@Nullable String linkedProjectPath, boolean isDefaultModuleCreation) { - if(StringUtil.isEmpty(linkedProjectPath) && !isDefaultModuleCreation) { - myUseLocalDistributionButton.setSelected(true); - myGradleHomePathField.setEnabled(true); - return; - } - - final boolean isGradleDefaultWrapperFilesExist = GradleUtil.isGradleDefaultWrapperFilesExist(linkedProjectPath); - if (isGradleDefaultWrapperFilesExist || isDefaultModuleCreation) { - myUseWrapperButton.setEnabled(true); - myUseWrapperButton.setSelected(true); - myGradleHomePathField.setEnabled(false); - myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.default_wrapper.configured")); - } else { - myUseWrapperButton.setEnabled(false); - myUseLocalDistributionButton.setSelected(true); - myGradleHomePathField.setEnabled(true); - myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.default_wrapper.not_configured")); - } - - if(getInitialSettings().getDistributionType() == null) { - return; - } - - switch (getInitialSettings().getDistributionType()) { - case LOCAL: - myGradleHomePathField.setEnabled(true); - myUseLocalDistributionButton.setSelected(true); - break; - case DEFAULT_WRAPPED: - myGradleHomePathField.setEnabled(false); - myUseWrapperButton.setSelected(true); - myUseWrapperButton.setEnabled(true); - break; - case WRAPPED: - myGradleHomePathField.setEnabled(false); - myUseWrapperWithVerificationButton.setSelected(true); - break; - case BUNDLED: - myGradleHomePathField.setEnabled(false); - myUseBundledDistributionButton.setSelected(true); - break; - } - } - - /** - * Updates GUI of the gradle configurable in order to show deduced path to gradle (if possible). - */ - private void deduceGradleHomeIfPossible() { - File gradleHome = myInstallationManager.getAutodetectedGradleHome(); - if (gradleHome == null) { - new DelayedBalloonInfo(MessageType.WARNING, LocationSettingType.UNKNOWN, BALLOON_DELAY_MILLIS).run(); - return; - } - myGradleHomeSettingType = LocationSettingType.DEDUCED; - new DelayedBalloonInfo(MessageType.INFO, LocationSettingType.DEDUCED, BALLOON_DELAY_MILLIS).run(); - myGradleHomePathField.setText(gradleHome.getPath()); - myGradleHomePathField.getTextField().setForeground(LocationSettingType.DEDUCED.getColor()); - } - - void showBalloonIfNecessary() { - if (!myShowBalloonIfNecessary || !myGradleHomePathField.isEnabled()) { - return; - } - myShowBalloonIfNecessary = false; - MessageType messageType = null; - switch (myGradleHomeSettingType) { - case DEDUCED: - messageType = MessageType.INFO; - break; - case EXPLICIT_INCORRECT: - case UNKNOWN: - messageType = MessageType.ERROR; - break; - default: - } - if (messageType != null) { - new DelayedBalloonInfo(messageType, myGradleHomeSettingType, BALLOON_DELAY_MILLIS).run(); - } + public void update(@Nullable String linkedProjectPath, boolean isDefaultModuleCreation) { + myBuilder.update(linkedProjectPath, getInitialSettings(), isDefaultModuleCreation); } /** @@ -421,47 +80,12 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting */ public void setCurrentProject(@Nullable Project project) { super.setCurrentProject(project); - resetGradleJdkComboBox(project); + myBuilder.reset(getProject(), getInitialSettings(), false); } - private void resetGradleJdkComboBox(@Nullable final Project project) { - final String gradleJvm = getInitialSettings().getGradleJvm(); - myGradleJdkComboBox.setProject(project); - - final String sdkItem = ObjectUtils.nullizeByCondition(gradleJvm, new Condition() { - @Override - public boolean value(String s) { - return (project == null && StringUtil.equals(USE_PROJECT_JDK, s)) || StringUtil.isEmpty(s); - } - }); - - myGradleJdkComboBox.refreshData(sdkItem); - } - - private class DelayedBalloonInfo implements Runnable { - private final MessageType myMessageType; - private final String myText; - private final long myTriggerTime; - - DelayedBalloonInfo(@NotNull MessageType messageType, @NotNull LocationSettingType settingType, long delayMillis) { - myMessageType = messageType; - myText = settingType.getDescription(GradleConstants.SYSTEM_ID); - myTriggerTime = System.currentTimeMillis() + delayMillis; - } - - @Override - public void run() { - long diff = myTriggerTime - System.currentTimeMillis(); - if (diff > 0) { - myAlarm.cancelAllRequests(); - myAlarm.addRequest(this, diff); - return; - } - if (myGradleHomePathField == null || !myGradleHomePathField.isShowing()) { - // Don't schedule the balloon if the configurable is hidden. - return; - } - ExternalSystemUiUtil.showBalloon(myGradleHomePathField, myMessageType, myText); - } + @Override + public void disposeUIResources() { + super.disposeUIResources(); + myBuilder.disposeUIResources(); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java new file mode 100644 index 000000000000..cde018bbb636 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.settings; + +import com.intellij.openapi.externalSystem.service.settings.ExternalSystemSettingsControlCustomizer; +import com.intellij.openapi.externalSystem.util.PaintAwarePanel; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; + +/** + * @author Vladislav.Soroka + * @since 2/24/2015 + */ +public interface GradleProjectSettingsControlBuilder { + + GradleProjectSettings getInitialSettings(); + + IdeaGradleProjectSettingsControlBuilder addGradleHomeComponents(PaintAwarePanel content, int indentLevel); + + IdeaGradleProjectSettingsControlBuilder addGradleJdkComponents(PaintAwarePanel content, int indentLevel); + + IdeaGradleProjectSettingsControlBuilder addGradleChooserComponents(PaintAwarePanel content, int indentLevel); + + void disposeUIResources(); + + boolean validate(GradleProjectSettings settings) throws ConfigurationException; + + void apply(GradleProjectSettings settings); + + boolean isModified(GradleProjectSettings settings); + + void reset(Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation); + + void createAndFillControls(PaintAwarePanel content, int indentLevel); + + void update(String linkedProjectPath, GradleProjectSettings settings, boolean isDefaultModuleCreation); + + @Nullable + ExternalSystemSettingsControlCustomizer getExternalSystemSettingsControlCustomizer(); +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSettingsControlProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSettingsControlProvider.java new file mode 100644 index 000000000000..ce9cc90479ff --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSettingsControlProvider.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.settings; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ObjectUtils; +import com.intellij.util.PlatformUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; + +/** + * @author Vladislav.Soroka + * @since 2/24/2015 + */ +public abstract class GradleSettingsControlProvider { + + private static final ExtensionPointName EP_NAME = + ExtensionPointName.create("org.jetbrains.plugins.gradle.settingsControlProvider"); + + public abstract String getPlatformPrefix(); + + public abstract GradleProjectSettingsControlBuilder getProjectSettingsControlBuilder(@NotNull GradleProjectSettings initialSettings); + + @NotNull + public static GradleSettingsControlProvider get() { + GradleSettingsControlProvider result = null; + if (!PlatformUtils.isIntelliJ()) { + final String platformPrefix = PlatformUtils.getPlatformPrefix(); + for (GradleSettingsControlProvider provider : EP_NAME.getExtensions()) { + if (StringUtil.equals(platformPrefix, provider.getPlatformPrefix())) { + assert result == null : "Multiple GradleSettingsControlProvider extensions found"; + result = provider; + } + } + } + return ObjectUtils.notNull(result, new GradleSettingsControlProvider() { + @Override + public String getPlatformPrefix() { + return null; + } + + @Override + public GradleProjectSettingsControlBuilder getProjectSettingsControlBuilder(@NotNull GradleProjectSettings initialSettings) { + return new IdeaGradleProjectSettingsControlBuilder(initialSettings) + // Hide bundled distribution option for a while + .dropUseBundledDistributionButton(); + } + }); + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java new file mode 100644 index 000000000000..891ba0fd7f97 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java @@ -0,0 +1,604 @@ +/* + * Copyright 2000-2015 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 org.jetbrains.plugins.gradle.service.settings; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.externalSystem.model.settings.LocationSettingType; +import com.intellij.openapi.externalSystem.service.settings.ExternalSystemSettingsControlCustomizer; +import com.intellij.openapi.externalSystem.service.ui.ExternalSystemJdkComboBox; +import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; +import com.intellij.openapi.externalSystem.util.PaintAwarePanel; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.TextComponentAccessor; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBRadioButton; +import com.intellij.util.Alarm; +import com.intellij.util.Consumer; +import com.intellij.util.ObjectUtils; +import com.intellij.util.ui.UIUtil; +import org.gradle.util.GradleVersion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.service.GradleInstallationManager; +import org.jetbrains.plugins.gradle.settings.DistributionType; +import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; +import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.gradle.util.GradleUtil; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.concurrent.TimeUnit; + +import static com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_PROJECT_JDK; + +/** + * @author Vladislav.Soroka + * @since 2/24/2015 + */ +public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSettingsControlBuilder { + + private static final long BALLOON_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(1); + @NotNull + private final GradleInstallationManager myInstallationManager; + @NotNull + private final GradleProjectSettings myInitialSettings; + @NotNull + private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + @NotNull + private LocationSettingType myGradleHomeSettingType = LocationSettingType.UNKNOWN; + private boolean myShowBalloonIfNecessary; + private ActionListener myActionListener; + + + private boolean dropUseAutoImportBox; + private boolean dropCreateEmptyContentRootDirectoriesBox; + + @SuppressWarnings("FieldCanBeLocal") // Used implicitly by reflection at disposeUIResources() and showUi() + @Nullable + private JLabel myGradleHomeLabel; + @Nullable + private TextFieldWithBrowseButton myGradleHomePathField; + private boolean dropGradleHomePathComponents; + + @SuppressWarnings("FieldCanBeLocal") // Used implicitly by reflection at disposeUIResources() and showUi() + @Nullable + private JLabel myGradleJdkLabel; + @Nullable + private ExternalSystemJdkComboBox myGradleJdkComboBox; + private boolean dropGradleJdkComponents; + + @Nullable + private JBRadioButton myUseWrapperButton; + private boolean dropUseWrapperButton; + + @Nullable + private JBRadioButton myUseWrapperWithVerificationButton; + @SuppressWarnings("FieldCanBeLocal") // Used implicitly by reflection at disposeUIResources() and showUi() + @Nullable + private JBLabel myUseWrapperVerificationLabel; + private boolean dropCustomizableWrapperButton; + + @Nullable + private JBRadioButton myUseLocalDistributionButton; + private boolean dropUseLocalDistributionButton; + + @Nullable + private JBRadioButton myUseBundledDistributionButton; + private boolean dropUseBundledDistributionButton; + + public IdeaGradleProjectSettingsControlBuilder(@NotNull GradleProjectSettings initialSettings) { + myInstallationManager = ServiceManager.getService(GradleInstallationManager.class); + myInitialSettings = initialSettings; + + myActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (myGradleHomePathField == null) return; + + boolean localDistributionEnabled = myUseLocalDistributionButton != null && myUseLocalDistributionButton.isSelected(); + myGradleHomePathField.setEnabled(localDistributionEnabled); + if (localDistributionEnabled) { + if (myGradleHomePathField.getText().isEmpty()) { + deduceGradleHomeIfPossible(); + } + else { + if (myInstallationManager.isGradleSdkHome(myGradleHomePathField.getText())) { + myGradleHomeSettingType = LocationSettingType.EXPLICIT_CORRECT; + } + else { + myGradleHomeSettingType = LocationSettingType.EXPLICIT_INCORRECT; + myShowBalloonIfNecessary = true; + } + } + showBalloonIfNecessary(); + } + else { + myAlarm.cancelAllRequests(); + } + } + }; + } + + public IdeaGradleProjectSettingsControlBuilder dropGradleJdkComponents() { + dropGradleJdkComponents = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropUseWrapperButton() { + dropUseWrapperButton = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropGradleHomePathComponents() { + dropGradleHomePathComponents = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropCustomizableWrapperButton() { + dropCustomizableWrapperButton = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropUseLocalDistributionButton() { + dropUseLocalDistributionButton = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropUseBundledDistributionButton() { + dropUseBundledDistributionButton = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropUseAutoImportBox() { + dropUseAutoImportBox = true; + return this; + } + + public IdeaGradleProjectSettingsControlBuilder dropCreateEmptyContentRootDirectoriesBox() { + dropCreateEmptyContentRootDirectoriesBox = true; + return this; + } + + @NotNull + public GradleProjectSettings getInitialSettings() { + return myInitialSettings; + } + + @Override + public ExternalSystemSettingsControlCustomizer getExternalSystemSettingsControlCustomizer() { + return new ExternalSystemSettingsControlCustomizer(dropUseAutoImportBox, dropCreateEmptyContentRootDirectoriesBox); + } + + @Override + public void createAndFillControls(PaintAwarePanel content, int indentLevel) { + content.setPaintCallback(new Consumer() { + @Override + public void consume(Graphics graphics) { + showBalloonIfNecessary(); + } + }); + + content.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!"ancestor".equals(evt.getPropertyName())) { + return; + } + + // Configure the balloon to show on initial configurable drawing. + myShowBalloonIfNecessary = evt.getNewValue() != null && evt.getOldValue() == null; + + if (evt.getNewValue() == null && evt.getOldValue() != null) { + // Cancel delayed balloons when the configurable is hidden. + myAlarm.cancelAllRequests(); + } + } + }); + + addGradleChooserComponents(content, indentLevel); + addGradleHomeComponents(content, indentLevel); + addGradleJdkComponents(content, indentLevel); + } + + @Override + public void disposeUIResources() { + ExternalSystemUiUtil.disposeUi(this); + } + + /** + * Updates GUI of the gradle configurable in order to show deduced path to gradle (if possible). + */ + private void deduceGradleHomeIfPossible() { + if (myGradleHomePathField == null) return; + + File gradleHome = myInstallationManager.getAutodetectedGradleHome(); + if (gradleHome == null) { + new DelayedBalloonInfo(MessageType.WARNING, LocationSettingType.UNKNOWN, BALLOON_DELAY_MILLIS).run(); + return; + } + myGradleHomeSettingType = LocationSettingType.DEDUCED; + new DelayedBalloonInfo(MessageType.INFO, LocationSettingType.DEDUCED, BALLOON_DELAY_MILLIS).run(); + myGradleHomePathField.setText(gradleHome.getPath()); + myGradleHomePathField.getTextField().setForeground(LocationSettingType.DEDUCED.getColor()); + } + + @Override + public IdeaGradleProjectSettingsControlBuilder addGradleJdkComponents(PaintAwarePanel content, int indentLevel) { + if(!dropGradleJdkComponents) { + myGradleJdkLabel = new JBLabel(GradleBundle.message("gradle.settings.text.jvm.path")); + myGradleJdkComboBox = new ExternalSystemJdkComboBox().withoutJre(); + + content.add(myGradleJdkLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); + content.add(myGradleJdkComboBox, ExternalSystemUiUtil.getFillLineConstraints(0)); + } + return this; + } + + @Override + public IdeaGradleProjectSettingsControlBuilder addGradleChooserComponents(PaintAwarePanel content, int indentLevel) { + ButtonGroup buttonGroup = new ButtonGroup(); + + if(!dropUseWrapperButton) { + myUseWrapperButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.default_wrapper.configured")); + myUseWrapperButton.addActionListener(myActionListener); + buttonGroup.add(myUseWrapperButton); + content.add(myUseWrapperButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + } + + if(!dropCustomizableWrapperButton) { + myUseWrapperWithVerificationButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.customizable_wrapper")); + myUseWrapperWithVerificationButton.addActionListener(myActionListener); + myUseWrapperVerificationLabel = new JBLabel(GradleBundle.message("gradle.settings.text.wrapper.customization.compatibility")); + myUseWrapperVerificationLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.MINI)); + myUseWrapperVerificationLabel.setIcon(UIUtil.getBalloonInformationIcon()); + buttonGroup.add(myUseWrapperWithVerificationButton); + content.add(myUseWrapperWithVerificationButton, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); + content.add(myUseWrapperVerificationLabel, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + } + + if(!dropUseLocalDistributionButton) { + myUseLocalDistributionButton = new JBRadioButton(GradleBundle.message("gradle.settings.text.use.local.distribution")); + myUseLocalDistributionButton.addActionListener(myActionListener); + buttonGroup.add(myUseLocalDistributionButton); + content.add(myUseLocalDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + } + + if(!dropUseBundledDistributionButton) { + myUseBundledDistributionButton = new JBRadioButton( + GradleBundle.message("gradle.settings.text.use.bundled.distribution", GradleVersion.current().getVersion())); + myUseBundledDistributionButton.addActionListener(myActionListener); + buttonGroup.add(myUseBundledDistributionButton); + //content.add(Box.createGlue(), ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + content.add(myUseBundledDistributionButton, ExternalSystemUiUtil.getFillLineConstraints(indentLevel)); + } + + return this; + } + + @Override + public boolean validate(GradleProjectSettings settings) throws ConfigurationException { + if (myGradleHomePathField == null) return true; + + String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); + if (myUseLocalDistributionButton != null && myUseLocalDistributionButton.isSelected()) { + if (StringUtil.isEmpty(gradleHomePath)) { + myGradleHomeSettingType = LocationSettingType.UNKNOWN; + throw new ConfigurationException(GradleBundle.message("gradle.home.setting.type.explicit.empty", gradleHomePath)); + } + else if (!myInstallationManager.isGradleSdkHome(new File(gradleHomePath))) { + myGradleHomeSettingType = LocationSettingType.EXPLICIT_INCORRECT; + new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); + throw new ConfigurationException(GradleBundle.message("gradle.home.setting.type.explicit.incorrect", gradleHomePath)); + } + } + return true; + } + + @Override + public void apply(GradleProjectSettings settings) { + if (myGradleHomePathField != null) { + String gradleHomePath = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); + if (StringUtil.isEmpty(gradleHomePath)) { + settings.setGradleHome(null); + } + else { + settings.setGradleHome(gradleHomePath); + GradleUtil.storeLastUsedGradleHome(gradleHomePath); + } + } + + if (myGradleJdkComboBox != null) { + final String gradleJvm = FileUtil.toCanonicalPath(myGradleJdkComboBox.getSelectedValue()); + settings.setGradleJvm(StringUtil.isEmpty(gradleJvm) ? null : gradleJvm); + } + + if (myUseLocalDistributionButton != null && myUseLocalDistributionButton.isSelected()) { + settings.setDistributionType(DistributionType.LOCAL); + } + else if (myUseWrapperButton != null && myUseWrapperButton.isSelected()) { + settings.setDistributionType(DistributionType.DEFAULT_WRAPPED); + } + else if ((myUseWrapperWithVerificationButton != null && myUseWrapperWithVerificationButton.isSelected()) || + (myUseBundledDistributionButton != null && myUseBundledDistributionButton.isSelected())) { + settings.setDistributionType(DistributionType.WRAPPED); + } + } + + @Override + public boolean isModified(GradleProjectSettings settings) { + DistributionType distributionType = settings.getDistributionType(); + if (myUseBundledDistributionButton != null && + myUseBundledDistributionButton.isSelected() && + distributionType != DistributionType.BUNDLED) { + return true; + } + + if (myUseWrapperButton != null && myUseWrapperButton.isSelected() && distributionType != DistributionType.DEFAULT_WRAPPED) { + return true; + } + + if (myUseWrapperWithVerificationButton != null && + myUseWrapperWithVerificationButton.isSelected() && + distributionType != DistributionType.WRAPPED) { + return true; + } + + if (myUseLocalDistributionButton != null && myUseLocalDistributionButton.isSelected() && distributionType != DistributionType.LOCAL) { + return true; + } + + if (myGradleJdkComboBox != null && !StringUtil.equals(myGradleJdkComboBox.getSelectedValue(), settings.getGradleJvm())) { + return true; + } + + if (myGradleHomePathField == null) return false; + String gradleHome = FileUtil.toCanonicalPath(myGradleHomePathField.getText()); + if (StringUtil.isEmpty(gradleHome)) { + return !StringUtil.isEmpty(settings.getGradleHome()); + } + else { + return !gradleHome.equals(settings.getGradleHome()); + } + } + + @Override + public void reset(Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation) { + String gradleHome = settings.getGradleHome(); + if (myGradleHomePathField != null) { + myGradleHomePathField.setText(gradleHome == null ? "" : gradleHome); + myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); + } + + resetGradleJdkComboBox(project, settings); + resetWrapperControls(settings.getExternalProjectPath(), settings, isDefaultModuleCreation); + + if (myUseLocalDistributionButton != null && !myUseLocalDistributionButton.isSelected()) { + myGradleHomePathField.setEnabled(false); + return; + } + + if (StringUtil.isEmpty(gradleHome)) { + myGradleHomeSettingType = LocationSettingType.UNKNOWN; + deduceGradleHomeIfPossible(); + } + else { + myGradleHomeSettingType = myInstallationManager.isGradleSdkHome(new File(gradleHome)) ? + LocationSettingType.EXPLICIT_CORRECT : + LocationSettingType.EXPLICIT_INCORRECT; + myAlarm.cancelAllRequests(); + if (myGradleHomeSettingType == LocationSettingType.EXPLICIT_INCORRECT && + settings.getDistributionType() == DistributionType.LOCAL) { + new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); + } + } + } + + @Override + public void update(String linkedProjectPath, GradleProjectSettings settings, boolean isDefaultModuleCreation) { + resetWrapperControls(linkedProjectPath, settings, isDefaultModuleCreation); + } + + @Override + public IdeaGradleProjectSettingsControlBuilder addGradleHomeComponents(PaintAwarePanel content, int indentLevel) { + if(dropGradleHomePathComponents) return this; + + myGradleHomeLabel = new JBLabel(GradleBundle.message("gradle.settings.text.home.path")); + myGradleHomePathField = new TextFieldWithBrowseButton(); + + myGradleHomePathField.addBrowseFolderListener( + "", + GradleBundle.message("gradle.settings.text.home.path"), + null, + GradleUtil.getGradleHomeFileChooserDescriptor(), + TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT, + false + ); + myGradleHomePathField.getTextField().getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + myGradleHomePathField.getTextField().setForeground(LocationSettingType.EXPLICIT_CORRECT.getColor()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + } + }); + + content.add(myGradleHomeLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel)); + content.add(myGradleHomePathField, ExternalSystemUiUtil.getFillLineConstraints(0)); + + return this; + } + + private void resetGradleJdkComboBox(@Nullable final Project project, GradleProjectSettings settings) { + if (myGradleJdkComboBox == null) return; + + final String gradleJvm = settings.getGradleJvm(); + myGradleJdkComboBox.setProject(project); + + final String sdkItem = ObjectUtils.nullizeByCondition(gradleJvm, new Condition() { + @Override + public boolean value(String s) { + return (project == null && StringUtil.equals(USE_PROJECT_JDK, s)) || StringUtil.isEmpty(s); + } + }); + + myGradleJdkComboBox.refreshData(sdkItem); + } + + private void resetWrapperControls(String linkedProjectPath, @NotNull GradleProjectSettings settings, boolean isDefaultModuleCreation) { + if (StringUtil.isEmpty(linkedProjectPath) && !isDefaultModuleCreation) { + if (myUseLocalDistributionButton != null) { + myUseLocalDistributionButton.setSelected(true); + } + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(true); + } + return; + } + + final boolean isGradleDefaultWrapperFilesExist = GradleUtil.isGradleDefaultWrapperFilesExist(linkedProjectPath); + if (myUseWrapperButton != null && (isGradleDefaultWrapperFilesExist || isDefaultModuleCreation)) { + myUseWrapperButton.setEnabled(true); + myUseWrapperButton.setSelected(true); + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(false); + } + myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.default_wrapper.configured")); + } + else { + if (myUseWrapperButton != null) { + myUseWrapperButton.setEnabled(false); + myUseWrapperButton.setText(GradleBundle.message("gradle.settings.text.use.default_wrapper.not_configured")); + } + if (myUseLocalDistributionButton != null) { + myUseLocalDistributionButton.setSelected(true); + } + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(true); + } + } + + if (settings.getDistributionType() == null) { + return; + } + + switch (settings.getDistributionType()) { + case LOCAL: + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(true); + } + if (myUseLocalDistributionButton != null) { + myUseLocalDistributionButton.setSelected(true); + } + break; + case DEFAULT_WRAPPED: + if (isGradleDefaultWrapperFilesExist) { + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(false); + } + if (myUseWrapperButton != null) { + myUseWrapperButton.setSelected(true); + myUseWrapperButton.setEnabled(true); + } + } + break; + case WRAPPED: + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(false); + } + if (myUseWrapperWithVerificationButton != null) { + myUseWrapperWithVerificationButton.setSelected(true); + } + break; + case BUNDLED: + if (myGradleHomePathField != null) { + myGradleHomePathField.setEnabled(false); + } + if (myUseBundledDistributionButton != null) { + myUseBundledDistributionButton.setSelected(true); + } + break; + } + } + + void showBalloonIfNecessary() { + if (!myShowBalloonIfNecessary || (myGradleHomePathField != null && !myGradleHomePathField.isEnabled())) { + return; + } + myShowBalloonIfNecessary = false; + MessageType messageType = null; + switch (myGradleHomeSettingType) { + case DEDUCED: + messageType = MessageType.INFO; + break; + case EXPLICIT_INCORRECT: + case UNKNOWN: + messageType = MessageType.ERROR; + break; + default: + } + if (messageType != null) { + new DelayedBalloonInfo(messageType, myGradleHomeSettingType, BALLOON_DELAY_MILLIS).run(); + } + } + + private class DelayedBalloonInfo implements Runnable { + private final MessageType myMessageType; + private final String myText; + private final long myTriggerTime; + + DelayedBalloonInfo(@NotNull MessageType messageType, @NotNull LocationSettingType settingType, long delayMillis) { + myMessageType = messageType; + myText = settingType.getDescription(GradleConstants.SYSTEM_ID); + myTriggerTime = System.currentTimeMillis() + delayMillis; + } + + @Override + public void run() { + long diff = myTriggerTime - System.currentTimeMillis(); + if (diff > 0) { + myAlarm.cancelAllRequests(); + myAlarm.addRequest(this, diff); + return; + } + if (myGradleHomePathField == null || !myGradleHomePathField.isShowing()) { + // Don't schedule the balloon if the configurable is hidden. + return; + } + ExternalSystemUiUtil.showBalloon(myGradleHomePathField, myMessageType, myText); + } + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java index 605cd3667fe3..7bfad346e353 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java @@ -52,9 +52,7 @@ public class ImportFromGradleControl @NotNull @Override protected ExternalSystemSettingsControl createProjectSettingsControl(@NotNull GradleProjectSettings settings) { - GradleProjectSettingsControl settingsControl = new GradleProjectSettingsControl(settings); - settingsControl.hideUseAutoImportBox(); - return settingsControl; + return new GradleProjectSettingsControl(settings); } @Nullable @@ -65,7 +63,7 @@ public class ImportFromGradleControl @Override protected void onLinkedProjectPathChange(@NotNull String path) { - ((GradleProjectSettingsControl)getProjectSettingsControl()).updateWrapperControls(path, false); + ((GradleProjectSettingsControl)getProjectSettingsControl()).update(path, false); } @Override diff --git a/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java b/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java index 3f30d60aa406..100330608c73 100644 --- a/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java +++ b/python/src/com/jetbrains/python/console/parsing/PyConsoleParser.java @@ -55,7 +55,6 @@ public class PyConsoleParser extends PyParser{ StatementParsing stmt_parser = context.getStatementParser(); builder.setTokenTypeRemapper(stmt_parser); // must be done before touching the caching lexer with eof() call. - builder.setDebugMode(true); while (!builder.eof()) { stmt_parser.parseStatement(context.emptyParsingScope()); } diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index 6cbae17aca64..780ac5997985 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -37,7 +37,10 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.remote.RemoteProcessHandlerBase; @@ -52,7 +55,6 @@ import com.intellij.xdebugger.frame.XValueChildrenList; import com.intellij.xdebugger.impl.XSourcePositionImpl; import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; import com.jetbrains.python.PythonFileType; -import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.console.PythonDebugLanguageConsoleView; import com.jetbrains.python.console.pydev.PydevCompletionVariant; import com.jetbrains.python.debugger.pydev.*; @@ -801,7 +803,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr @Nullable - public XSourcePosition getCurrentFrameSourcePosition() { + private XSourcePosition getCurrentFrameSourcePosition() { try { PyStackFrame frame = currentFrame(); @@ -862,21 +864,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr return null; } - VirtualFile virtualFile = currentPosition.getFile(); - - final Document document = FileDocumentManager.getInstance().getDocument(virtualFile); - if (document == null) { - return null; - } - final FileViewProvider viewProvider = PsiManager.getInstance(getProject()).findViewProvider(virtualFile); - if (viewProvider == null) { - return null; - } - final PsiFile file = viewProvider.getPsi(PythonLanguage.getInstance()); - if (file == null) { - return null; - } - return file; + return PsiManager.getInstance(getProject()).findFile(currentPosition.getFile()); } diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java index db53fe6bebae..4a8235042137 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java @@ -18,12 +18,15 @@ package com.jetbrains.python.refactoring.classes.membersManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.listeners.RefactoringEventData; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.util.Function; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -98,4 +101,27 @@ public abstract class PyMembersRefactoringBaseProcessor extends BaseRefactoringP MembersManager.moveAllMembers(myMembersToMove, myFrom, destinations.toArray(new PyClass[destinations.size()])); PyClassRefactoringUtil.optimizeImports(myFrom.getContainingFile()); // To remove unneeded imports } + + @Nullable + @Override + protected RefactoringEventData getBeforeData() { + RefactoringEventData data = new RefactoringEventData(); + data.addElement(myFrom); + data.addMembers(myMembersToMove.toArray(new PyMemberInfo[myMembersToMove.size()]), new Function() { + @Override + public PsiElement fun(PyMemberInfo info) { + return info.getMember(); + } + }); + return data; + } + + + @Nullable + @Override + protected RefactoringEventData getAfterData(UsageInfo[] usages) { + final RefactoringEventData data = new RefactoringEventData(); + data.addElements(myTo); + return data; + } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java index 3b569e5d57e2..5fdb4e6f37c4 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java @@ -57,4 +57,10 @@ class PyPullUpProcessor extends PyMembersRefactoringBaseProcessor { public String getCommentReferencesText(final int usagesCount, final int filesCount) { return getCodeReferencesText(usagesCount, filesCount); } + + @Nullable + @Override + protected String getRefactoringId() { + return "refactoring.python.pull.up"; + } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java index f3919d39ce59..4f03783f3ccc 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java @@ -75,4 +75,10 @@ public class PyPushDownProcessor extends PyMembersRefactoringBaseProcessor { protected String getCommandName() { return PyPushDownHandler.REFACTORING_NAME; } + + @Nullable + @Override + protected String getRefactoringId() { + return "refactoring.python.push.down"; + } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java index 100cc9400918..f08a52c3a63f 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java @@ -74,6 +74,7 @@ public class XmlEmmetParser extends EmmetParser { put("object", "param"); put("map", "area"); }}; + private boolean isHtml; public XmlEmmetParser(List tokens, CustomTemplateCallback callback, @@ -84,6 +85,7 @@ public class XmlEmmetParser extends EmmetParser { if (surroundWithTemplate && parentTag != null && context.getNode().getElementType() == XmlTokenType.XML_START_TAG_START) { parentTag = PsiTreeUtil.getParentOfType(parentTag, XmlTag.class); } + isHtml = generator.isHtml(callback); if (parentTag != null) { hasTagContext = true; tagLevel.push(parentTag.getName()); @@ -210,7 +212,7 @@ public class XmlEmmetParser extends EmmetParser { @Nullable private String getDefaultTemplateKey() { - return ZenCodingUtil.isHtml(myCallback) ? suggestTagName() : null; + return isHtml ? suggestTagName() : null; } @Nullable diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java index 0434ea054e07..346c1528fee9 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.template.emmet.generators; import com.intellij.application.options.emmet.EmmetOptions; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; +import com.intellij.codeInsight.template.emmet.ZenCodingUtil; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.diagnostic.AttachmentFactory; @@ -124,4 +125,9 @@ public abstract class XmlZenCodingGenerator extends ZenCodingGenerator { public void disableEmmet() { EmmetOptions.getInstance().setEmmetEnabled(false); } + + @Override + public boolean isHtml(@NotNull CustomTemplateCallback callback) { + return ZenCodingUtil.isHtml(callback); + } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java index e333a0f1bc29..025bae895a02 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java @@ -148,6 +148,10 @@ public abstract class ZenCodingGenerator { return false; } + public boolean isHtml(@NotNull CustomTemplateCallback callback) { + return false; + } + public void disableEmmet() { } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java index f83263a72b91..be969593947e 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java @@ -49,6 +49,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; import com.intellij.util.LocalTimeCounter; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; @@ -276,6 +277,8 @@ public class GenerationNode extends UserDataHolderBase { /*assert generator == null || generator instanceof XmlZenCodingGenerator : "The generator cannot process TemplateToken because it doesn't inherit XmlZenCodingGenerator";*/ + ZenCodingGenerator zenCodingGenerator = ObjectUtils.notNull(generator, XmlZenCodingGeneratorImpl.INSTANCE); + Map attributes = token.getAttributes(); TemplateImpl template = token.getTemplate(); assert template != null; @@ -307,7 +310,7 @@ public class GenerationNode extends UserDataHolderBase { } } XmlTag tag1 = hasChildren ? expandEmptyTagIfNecessary(tag) : tag; - setAttributeValues(tag1, attributes, callback); + setAttributeValues(tag1, attributes, callback, zenCodingGenerator.isHtml(callback)); XmlFile physicalFile = (XmlFile)fileFactory.createFileFromText(HTMLLanguage.INSTANCE, tag1.getContainingFile().getText()); VirtualFile vFile = physicalFile.getVirtualFile(); if (vFile != null) { @@ -315,7 +318,6 @@ public class GenerationNode extends UserDataHolderBase { } token.setFile(physicalFile); } - ZenCodingGenerator zenCodingGenerator = generator != null ? generator : XmlZenCodingGeneratorImpl.INSTANCE; template = zenCodingGenerator.generateTemplate(token, hasChildren, callback.getContext()); removeVariablesWhichHasNoSegment(template); return template; @@ -445,7 +447,10 @@ public class GenerationNode extends UserDataHolderBase { return predefinedValues; } - private void setAttributeValues(@NotNull XmlTag tag, @NotNull final Map attributes, CustomTemplateCallback callback) { + private void setAttributeValues(@NotNull XmlTag tag, + @NotNull final Map attributes, + @NotNull CustomTemplateCallback callback, + boolean isHtml) { // default and implied attributes final String defaultAttributeValue = attributes.get(XmlEmmetParser.DEFAULT_ATTRIBUTE_NAME); if (defaultAttributeValue != null) { @@ -495,7 +500,7 @@ public class GenerationNode extends UserDataHolderBase { myContainsSurroundedTextMarker = true; } - if (isBooleanAttribute(attributeValue, xmlAttribute, callback)) { + if (isHtml && isBooleanAttribute(attributeValue, xmlAttribute, callback)) { if (HtmlUtil.isShortNotationOfBooleanAttributePreferred()) { if (xmlAttributeValueElement != null) { final PsiElement prevSibling = xmlAttributeValueElement.getPrevSibling(); @@ -536,7 +541,7 @@ public class GenerationNode extends UserDataHolderBase { if (XmlEmmetParser.BOOLEAN_ATTRIBUTE_VALUE.equals(attributeValue)) { return true; } - if (ZenCodingUtil.isHtml(callback) && StringUtil.isEmpty(attributeValue)) { + if (StringUtil.isEmpty(attributeValue)) { final XmlAttributeDescriptor descriptor = xmlAttribute.getDescriptor(); return descriptor != null && HtmlUtil.isBooleanAttribute(descriptor, callback.getContext()); }