diff --git a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.form b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.form index b6012a096c95..db191dde6fa3 100644 --- a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.form +++ b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.form @@ -1,6 +1,6 @@
- + @@ -16,7 +16,7 @@ - + @@ -34,6 +34,16 @@ + + + + + + + + + + diff --git a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java index 071f348a79a4..debdb7b9fdc6 100644 --- a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java @@ -15,6 +15,7 @@ */ package com.intellij.execution.jar; +import com.intellij.application.options.ModulesComboBox; import com.intellij.execution.ui.AlternativeJREPanel; import com.intellij.execution.ui.CommonJavaParametersPanel; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -34,6 +35,7 @@ import javax.swing.*; public class JarApplicationConfigurable extends SettingsEditor implements PanelWithAnchor { private CommonJavaParametersPanel myCommonProgramParameters; private LabeledComponent myJarPathComponent; + private LabeledComponent myModuleComponent; private JPanel myWholePanel; private AlternativeJREPanel myAlternativeJREPanel; @@ -43,6 +45,9 @@ public class JarApplicationConfigurable extends SettingsEditor"); + modulesComboBox.fillModules(project); } public void applyEditorTo(final JarApplicationConfiguration configuration) throws ConfigurationException { @@ -50,12 +55,14 @@ public class JarApplicationConfigurable extends SettingsEditor myEnvs = new LinkedHashMap(); + private JavaRunConfigurationModule myConfigurationModule; public JarApplicationConfiguration(Project project, ConfigurationFactory factory, String name) { super(project, factory, name); + myConfigurationModule = new JavaRunConfigurationModule(project, true); } @NotNull @@ -67,6 +70,15 @@ public class JarApplicationConfiguration extends RunConfigurationBase implements JavaRunConfigurationExtensionManager.getInstance().readExternal(this, element); XmlSerializer.deserializeInto(myBean, element); EnvironmentVariablesComponent.readExternal(element, getEnvs()); + myConfigurationModule.readExternal(element); + } + + public void setModule(Module module) { + myConfigurationModule.setModule(module); + } + + public Module getModule() { + return myConfigurationModule.getModule(); } @Override @@ -76,6 +88,9 @@ public class JarApplicationConfiguration extends RunConfigurationBase implements XmlSerializer.serializeInto(myBean, element, SERIALIZATION_FILTERS); EnvironmentVariablesComponent.writeExternal(element, getEnvs()); PathMacroManager.getInstance(getProject()).collapsePathsRecursively(element); + if (myConfigurationModule.getModule() != null) { + myConfigurationModule.writeExternal(element); + } } @Override @@ -89,6 +104,13 @@ public class JarApplicationConfiguration extends RunConfigurationBase implements JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this); } + @NotNull + @Override + public Module[] getModules() { + Module module = myConfigurationModule.getModule(); + return module != null ? new Module[] {module}: Module.EMPTY_ARRAY; + } + @Nullable @Override public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException { diff --git a/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java b/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java index 9a1dfad2955a..45519c91baeb 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java @@ -19,5 +19,5 @@ package com.intellij.execution.configurations; /** * @author spleaner */ -public interface ModuleRunProfile extends RunProfileWithCompileBeforeLaunchOption { +public interface ModuleRunProfile extends RunProfileWithCompileBeforeLaunchOption, SearchScopeProvidingRunProfile { } diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java index ea6b158e0bc2..e3f0c22a2132 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java @@ -28,8 +28,8 @@ public class SearchScopeProvider { @NotNull public static GlobalSearchScope createSearchScope(@NotNull Project project, @Nullable RunProfile runProfile) { Module[] modules = null; - if (runProfile instanceof ModuleRunProfile) { - modules = ((ModuleRunProfile)runProfile).getModules(); + if (runProfile instanceof SearchScopeProvidingRunProfile) { + modules = ((SearchScopeProvidingRunProfile)runProfile).getModules(); } if (modules == null || modules.length == 0) { return GlobalSearchScope.allScope(project); diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java new file mode 100644 index 000000000000..afdd273384e8 --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java @@ -0,0 +1,34 @@ +/* + * 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.execution.configurations; + +import com.intellij.openapi.module.Module; +import org.jetbrains.annotations.NotNull; + +/** + * Base interface for run configurations that can specify which part of the project should be used to search sources. This information + * will be used to provide more accurate navigation to sources from stack traces, debugger, etc + * + * @author nik + */ +public interface SearchScopeProvidingRunProfile extends RunProfile { + /** + * @return modules where to search sources for this configuration + */ + @NotNull + Module[] getModules(); +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/application/options/ModuleListCellRenderer.java b/platform/lang-impl/src/com/intellij/application/options/ModuleListCellRenderer.java index f544517bb5d4..6bc5f6505c92 100644 --- a/platform/lang-impl/src/com/intellij/application/options/ModuleListCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/application/options/ModuleListCellRenderer.java @@ -3,6 +3,7 @@ package com.intellij.application.options; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.ui.ListCellRendererWrapper; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -10,10 +11,20 @@ import javax.swing.*; * @author yole */ public class ModuleListCellRenderer extends ListCellRendererWrapper { + private final String myEmptySelectionText; + + public ModuleListCellRenderer() { + this("[none]"); + } + + public ModuleListCellRenderer(@NotNull String emptySelectionText) { + myEmptySelectionText = emptySelectionText; + } + @Override public void customize(JList list, Module module, int index, boolean selected, boolean hasFocus) { if (module == null) { - setText("[none]"); + setText(myEmptySelectionText); } else { setIcon(ModuleType.get(module).getIcon()); diff --git a/platform/lang-impl/src/com/intellij/application/options/ModulesComboBox.java b/platform/lang-impl/src/com/intellij/application/options/ModulesComboBox.java index 17434cb0c7ba..4c2ef3a3d16c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/ModulesComboBox.java +++ b/platform/lang-impl/src/com/intellij/application/options/ModulesComboBox.java @@ -36,6 +36,7 @@ import java.util.List; */ public class ModulesComboBox extends ComboBox { private final SortedComboBoxModel myModel; + private boolean myAllowEmptySelection; public ModulesComboBox() { this(new SortedComboBoxModel(ModulesAlphaComparator.INSTANCE)); @@ -58,8 +59,17 @@ public class ModulesComboBox extends ComboBox { setRenderer(new ModuleListCellRenderer()); } + public void allowEmptySelection(@NotNull String emptySelectionText) { + myAllowEmptySelection = true; + myModel.add(null); + setRenderer(new ModuleListCellRenderer(emptySelectionText)); + } + public void setModules(@NotNull Collection modules) { myModel.setAll(modules); + if (myAllowEmptySelection) { + myModel.add(null); + } } public void fillModules(@NotNull Project project) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java index 8a561e4003b4..61a5c71861c3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ModulesAlphaComparator.java @@ -29,8 +29,9 @@ public class ModulesAlphaComparator implements Comparator{ @Override public int compare(Module module1, Module module2) { - final String name1 = module1.getName(); - final String name2 = module2.getName(); - return name1.compareToIgnoreCase(name2); + if (module1 == null && module2 == null) return 0; + if (module1 == null && module2 != null) return -1; + if (module1 != null && module2 == null) return 1; + return module1.getName().compareToIgnoreCase(module2.getName()); } } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index c26cb10030c4..c2b7de8ba7ed 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -153,17 +153,26 @@ public class StringUtil extends StringUtilRt { int i = 0; while (i < text.length()) { - final int i1 = ignoreCase? indexOfIgnoreCase(text, oldS, i) : text.indexOf(oldS, i); - if (i1 < 0) { - if (i == 0) return text; + final int index = ignoreCase? indexOfIgnoreCase(text, oldS, i) : text.indexOf(oldS, i); + if (index < 0) { + if (i == 0) { + return text; + } + newText.append(text, i, text.length()); break; } else { - if (newText == null) newText = new StringBuilder(text.length() - i); - newText.append(text, i, i1); + if (newText == null) { + if (text.length() == oldS.length()) { + return newS; + } + newText = new StringBuilder(text.length() - i); + } + + newText.append(text, i, index); newText.append(newS); - i = i1 + oldS.length(); + i = index + oldS.length(); } } return newText != null ? newText.toString() : ""; @@ -1786,7 +1795,7 @@ public class StringUtil extends StringUtilRt { public static boolean contains(@NotNull CharSequence sequence, @NotNull CharSequence infix) { return indexOf(sequence, infix) >= 0; } - + @Contract(pure = true) public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix) { for (int i = 0; i < sequence.length() - infix.length(); i++) { @@ -2448,7 +2457,7 @@ public class StringUtil extends StringUtilRt { * \r
* * will return the following array: foo\r\n, \n, bar\n, \r\n, baz\r, \r - * + * */ @NotNull @Contract(pure = true) diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index d2f593d13ff1..93ebb038cae1 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -111,7 +111,7 @@ public class StringUtilTest extends TestCase { public void testFormatLinks() { assertEquals("http://a-b+c", StringUtil.formatLinks("http://a-b+c")); } - + public void testCopyHeapCharBuffer() { String s = "abcde"; CharBuffer buffer = CharBuffer.allocate(s.length()); @@ -124,7 +124,7 @@ public class StringUtilTest extends TestCase { assertNull(CharArrayUtil.fromSequenceWithoutCopying(buffer.subSequence(1, 5))); assertNull(CharArrayUtil.fromSequenceWithoutCopying(buffer.subSequence(1, 2))); } - + public void testTitleCase() { assertEquals("Couldn't Connect to Debugger", StringUtil.wordsToBeginFromUpperCase("Couldn't connect to debugger")); } @@ -198,7 +198,7 @@ public class StringUtilTest extends TestCase { assertEquals(Arrays.asList("aa"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("aa"))); assertEquals(Arrays.asList("\n", "\n", "aa\n", "\n", "bb\n", "cc\n", "\n"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\naa\n\nbb\ncc\n\n"))); - + assertEquals(Arrays.asList("\r", "\r\n", "\r"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("\r\r\n\r"))); assertEquals(Arrays.asList("\r\n", "\r", "\r\n"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("\r\n\r\r\n"))); @@ -224,4 +224,13 @@ public class StringUtilTest extends TestCase { } } } + + public void testReplaceReturnReplacementIfTextEqualsToReplacedText() { + String newS = "/tmp"; + assertSame(StringUtil.replace("$PROJECT_FILE$", "$PROJECT_FILE$".toLowerCase().toUpperCase() /* ensure new String instance */, newS), newS); + } + + public void testReplace() { + assertEquals(StringUtil.replace("$PROJECT_FILE$/filename", "$PROJECT_FILE$", "/tmp"), "/tmp/filename"); + } }