From 83ca8ea315110c98b39ed4a4435f505af7e78b25 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 11 Nov 2017 13:35:06 +0100 Subject: [PATCH 01/81] EnvironmentUtil: read batch environment --- .../com/intellij/execution/util/ExecUtil.java | 31 ++++--- .../src/com/intellij/util/ReadEnv.java | 25 ++++++ .../intellij/execution/CommandLineUtil.java | 34 ++++---- .../com/intellij/util/EnvironmentUtil.java | 83 +++++++++++++++---- .../intellij/util/EnvironmentUtilTest.java | 47 +++++++---- .../python/run/PyVirtualEnvReader.kt | 40 +-------- 6 files changed, 159 insertions(+), 101 deletions(-) create mode 100644 platform/util-rt/src/com/intellij/util/ReadEnv.java diff --git a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java index 8cf6ab30512a..84775ffbda6a 100644 --- a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java +++ b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java @@ -1,20 +1,19 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 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.util; +import com.intellij.execution.CommandLineUtil; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.CapturingProcessHandler; @@ -93,7 +92,7 @@ public class ExecUtil { @NotNull public static String getWindowsShellName() { - return SystemInfo.isWin2kOrNewer ? "cmd.exe" : "command.com"; + return CommandLineUtil.getWinShellName(); } @NotNull diff --git a/platform/util-rt/src/com/intellij/util/ReadEnv.java b/platform/util-rt/src/com/intellij/util/ReadEnv.java new file mode 100644 index 000000000000..e6d9e9e70c77 --- /dev/null +++ b/platform/util-rt/src/com/intellij/util/ReadEnv.java @@ -0,0 +1,25 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.util; + +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Map; + +public class ReadEnv { + public static void main(String[] args) throws Exception { + if (args.length != 1) throw new Exception("Exactly one argument expected"); + + Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(args[0]), "UTF-8")); + try { + for (Map.Entry each : System.getenv().entrySet()) { + if (each.getKey().startsWith("=")) continue; + out.write(each.getKey() + "=" + each.getValue() + "\0"); + } + } + finally { + out.close(); + } + } +} diff --git a/platform/util/src/com/intellij/execution/CommandLineUtil.java b/platform/util/src/com/intellij/execution/CommandLineUtil.java index 91942b726eeb..e16225f918cd 100644 --- a/platform/util/src/com/intellij/execution/CommandLineUtil.java +++ b/platform/util/src/com/intellij/execution/CommandLineUtil.java @@ -1,21 +1,20 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 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; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Contract; @@ -421,6 +420,11 @@ public class CommandLineUtil { return numTrailingBackslashes / 2; } + + @NotNull + public static String getWinShellName() { + return SystemInfo.isWin2kOrNewer ? "cmd.exe" : "command.com"; + } private static boolean isWinShell(String command) { return "cmd".equalsIgnoreCase(command) || "cmd.exe".equalsIgnoreCase(command); diff --git a/platform/util/src/com/intellij/util/EnvironmentUtil.java b/platform/util/src/com/intellij/util/EnvironmentUtil.java index 4872757931ae..0d26db738424 100644 --- a/platform/util/src/com/intellij/util/EnvironmentUtil.java +++ b/platform/util/src/com/intellij/util/EnvironmentUtil.java @@ -1,25 +1,25 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 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; +import com.intellij.execution.CommandLineUtil; import com.intellij.execution.process.UnixProcessManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -34,7 +34,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import java.io.*; +import java.io.File; +import java.io.InputStream; import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.Callable; @@ -186,6 +187,43 @@ public class EnvironmentUtil { FileUtil.delete(envFile); } } + + @NotNull + public Map readBatEnv(@NotNull File batchFile, List args) throws Exception { + return readBatOutputAndEnv(batchFile, args).second; + } + + @NotNull + protected Pair> readBatOutputAndEnv(@NotNull File batchFile, List args) throws Exception { + File envFile = FileUtil.createTempFile("intellij-cmd-env.", ".tmp", false); + try { + List cl = new ArrayList(); + cl.add(CommandLineUtil.getWinShellName()); + cl.add("/c"); + cl.add("call"); + cl.add(batchFile.getPath()); + cl.addAll(args); + cl.add("&&"); + cl.addAll(gerReadEnvCommand()); + cl.add(envFile.getPath()); + cl.addAll(Arrays.asList("||", "exit", "/B", "%ERRORLEVEL%")); + + return runProcessAndReadOutputAndEnvs(cl, + batchFile.getParentFile(), + null, + envFile, "\0"); + } + finally { + FileUtil.delete(envFile); + } + } + + @NotNull + private static List gerReadEnvCommand() { + return Arrays.asList(System.getProperty("java.home") + "/bin/java", + "-cp", PathManager.getJarPathForClass(ReadEnv.class), + ReadEnv.class.getCanonicalName()); + } @NotNull protected Map dumpProcessEnvToFile(@NotNull List command, @NotNull File envFile, String lineSeparator) @@ -213,6 +251,15 @@ public class EnvironmentUtil { @Nullable Map envs, @NotNull File envFile, String lineSeparator) throws Exception { + return runProcessAndReadOutputAndEnvs(command, workingDir, envs, envFile, lineSeparator).second; + } + + @NotNull + protected static Pair> runProcessAndReadOutputAndEnvs(@NotNull List command, + @Nullable File workingDir, + @Nullable Map envs, + @NotNull File envFile, + String lineSeparator) throws Exception { ProcessBuilder builder = new ProcessBuilder(command).redirectErrorStream(true); if (envs != null) { // we might need default environment for the process to launch correctly @@ -230,7 +277,7 @@ public class EnvironmentUtil { if (rv != 0 || lines.isEmpty()) { throw new Exception("rv:" + rv + " text:" + lines.length() + " out:" + StringUtil.trimEnd(gobbler.getText(), '\n')); } - return parseEnv(lines, lineSeparator); + return Pair.create(gobbler.getText(), parseEnv(lines, lineSeparator)); } @NotNull @@ -397,7 +444,7 @@ public class EnvironmentUtil { } } - private static class StreamGobbler extends BaseOutputReader { + public static class StreamGobbler extends BaseOutputReader { private static final Options OPTIONS = new Options() { @Override public SleepingPolicy policy() { diff --git a/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java index 4d51cb94a75f..17afc9565792 100644 --- a/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java @@ -1,23 +1,12 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; import org.junit.Test; +import java.io.File; +import java.util.Arrays; import java.util.Map; import static org.junit.Assert.*; @@ -63,4 +52,32 @@ public class EnvironmentUtilTest { Map env = EnvironmentUtil.testLoader(); assertTrue(env.size() >= System.getenv().size() / 2); } + + @Test(timeout = 30000) + public void loadingBatEnv() throws Exception { + assumeTrue(SystemInfo.isWindows); + + File file = FileUtil.createTempFile("test", ".bat", true); + FileUtil.writeToFile(file, "set FOO_TEST_1=123\r\nset FOO_TEST_2=%1"); + + Map result = new EnvironmentUtil.ShellEnvReader().readBatEnv(file, Arrays.asList("arg_value")); + assertEquals("123", result.get("FOO_TEST_1")); + assertEquals("arg_value", result.get("FOO_TEST_2")); + } + + @Test(timeout = 30000) + public void loadingBatEnv_ErrorHandling() throws Exception { + assumeTrue(SystemInfo.isWindows); + + File file = FileUtil.createTempFile("test", ".bat", true); + FileUtil.writeToFile(file, "echo some error\r\nexit /B 1"); + + try { + new EnvironmentUtil.ShellEnvReader().readBatEnv(file, Arrays.asList()); + fail("error should be reported"); + } + catch (Exception e) { + assertTrue(e.getMessage(), e.getMessage().contains("some error")); + } + } } \ No newline at end of file diff --git a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt index 29402cbca2b0..1b955eec3de5 100644 --- a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt +++ b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt @@ -1,25 +1,10 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.run import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.SystemInfo -import com.intellij.openapi.util.io.FileUtil import com.intellij.util.EnvironmentUtil -import com.intellij.util.LineSeparator +import com.intellij.util.containers.ContainerUtil import com.jetbrains.python.sdk.PythonSdkType import java.io.File @@ -58,7 +43,7 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE } else { if (activate != null) { - return readVirtualEnvOnWindows(activate); + return readBatEnv(File(activate.first), ContainerUtil.createMaybeSingletonList(activate.second)) } else { LOG.error("Can't find activate script for $virtualEnvSdkPath") @@ -72,25 +57,6 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE return runProcessAndReadEnvs(command, null, EnvironmentUtil.getEnvironmentMap(), envFile, lineSeparator) } - private fun readVirtualEnvOnWindows(activate: Pair): MutableMap { - val activateFile = FileUtil.createTempFile("pycharm-virualenv-activate.", ".bat", false) - val envFile = FileUtil.createTempFile("pycharm-virualenv-envs.", ".tmp", false) - try { - FileUtil.copy(File(activate.first), activateFile); - FileUtil.appendToFile(activateFile, "\n\nset >" + envFile.absoluteFile) - - val command = if (activate.second != null) listOf(activateFile.path, activate.second!!) - else listOf(activateFile.path) - - return runProcessAndReadEnvs(command, envFile, LineSeparator.CRLF.separatorString) - } - finally { - FileUtil.delete(activateFile) - FileUtil.delete(envFile) - } - - } - override fun getShellProcessCommand(): MutableList { val shellPath = shell From 41f10b574fe07f29bcae84cbe23a63d2b0852c12 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 11 Nov 2017 13:45:22 +0100 Subject: [PATCH 02/81] CPP-819 Support MSVC toolchain with CMake via NMake generator: enable by default --- platform/util/resources/misc/registry.properties | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 2973df4a300d..98b6bebbf61e 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1059,9 +1059,6 @@ cidr.indexer.thread.count.description=Number of CPU cores which will be used to how many cores should NOT be involved, e.g. "0" equals to "use every available CPU core", "-1" means "use every core but one". cidr.max.intellisense.file.length=500000 cidr.max.intellisense.file.length.description=Maximum length of C-based language file (in characters) IDE should provide code assistance for. -clion.enable.msvc=false -clion.enable.msvc.description=Experimental MSVC compiler support.\n\ - Please submit feedback and issues in https://youtrack.jetbrains.com/issue/CPP-819 ide.window.shadow.painter=false ide.window.shadow.painter.restartRequired=true From 9dbc7881fbc95a02d3d74fe8debd80bec1246156 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 13 Nov 2017 18:35:59 +0100 Subject: [PATCH 03/81] OC-12825 Project view: "Xcode order" in AppCode instead of "Manual order": API moved --- .../impl/AbstractProjectViewPane.java | 26 +++++----------- .../ide/projectView/impl/ProjectViewImpl.java | 30 ++++++------------- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java index 9240f2c3a1af..7a27af4cdcab 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java @@ -1,22 +1,9 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.projectView.impl; import com.intellij.ide.DataManager; +import com.intellij.ide.IdeBundle; import com.intellij.ide.PsiCopyPasteManager; import com.intellij.ide.SelectInTarget; import com.intellij.ide.dnd.*; @@ -72,11 +59,8 @@ import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.image.BufferedImage; import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import java.util.*; import java.util.List; -import java.util.Map; public abstract class AbstractProjectViewPane implements DataProvider, Disposable, BusyObject { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.projectViewPane"); @@ -159,6 +143,10 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl public boolean supportsManualOrder() { return false; } + + protected String getManualOrderOptionText() { + return IdeBundle.message("action.manual.order"); + } /** * @return all supported sub views IDs. diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 68de580e2ef9..aa5ae81448ec 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.projectView.impl; @@ -1922,10 +1908,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo pane.installComparator(); } - protected String getManualOrderOptionText() { - return IdeBundle.message("action.manual.order"); - } - @Override public boolean isSortByType(String paneId) { return getPaneOptionValue(mySortByType, paneId, ourSortByTypeDefaults); @@ -1940,7 +1922,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo private class ManualOrderAction extends ToggleAction implements DumbAware { private ManualOrderAction() { - super(getManualOrderOptionText(), getManualOrderOptionText(), AllIcons.ObjectBrowser.Sorted); + super(IdeBundle.message("action.manual.order"), null, AllIcons.ObjectBrowser.Sorted); } @Override @@ -1958,7 +1940,13 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo super.update(e); final Presentation presentation = e.getPresentation(); AbstractProjectViewPane pane = getCurrentProjectViewPane(); - presentation.setEnabledAndVisible(pane != null && pane.supportsManualOrder()); + if (pane == null) { + presentation.setEnabledAndVisible(false); + } + else { + presentation.setEnabledAndVisible(pane.supportsManualOrder()); + presentation.setText(pane.getManualOrderOptionText()); + } } } From 21ab6f13019cc2afe518d1c1d80faa180992ae60 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 14 Nov 2017 17:40:55 +0100 Subject: [PATCH 04/81] CPP-11226 Rework CLion Project view + OC-16310 Rework AppCode Project & Files views --- .../impl/ProjectViewSelectInPaneTarget.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInPaneTarget.java diff --git a/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInPaneTarget.java b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInPaneTarget.java new file mode 100644 index 000000000000..ca3956f5c1c4 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInPaneTarget.java @@ -0,0 +1,38 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ide.impl; + +import com.intellij.ide.projectView.impl.AbstractProjectViewPane; +import com.intellij.openapi.project.PossiblyDumbAware; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +public class ProjectViewSelectInPaneTarget extends ProjectViewSelectInTarget implements PossiblyDumbAware { + private final AbstractProjectViewPane myPane; + private final boolean myDumbAware; + + public ProjectViewSelectInPaneTarget(@NotNull Project project, @NotNull AbstractProjectViewPane pane, boolean dumbAware) { + super(project); + myPane = pane; + myDumbAware = dumbAware; + } + + @Override + public String toString() { + return myPane.getTitle(); + } + + @Override + public String getMinorViewId() { + return myPane.getId(); + } + + @Override + public float getWeight() { + return myPane.getWeight(); + } + + @Override + public boolean isDumbAware() { + return myDumbAware; + } +} From a97813509a48ae62be738477f54b8b65c7b52f46 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 15 Nov 2017 16:40:29 +0100 Subject: [PATCH 05/81] CPP-10844 Visual Studio is not found when path to VS or user home contains non ascii characters: clean-up --- platform/util-rt/src/com/intellij/util/ReadEnv.java | 10 +++++++++- .../src/com/intellij/execution/CommandLineUtil.java | 3 +-- .../util/src/com/intellij/util/EnvironmentUtil.java | 10 +++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/platform/util-rt/src/com/intellij/util/ReadEnv.java b/platform/util-rt/src/com/intellij/util/ReadEnv.java index e6d9e9e70c77..391bd5eafb97 100644 --- a/platform/util-rt/src/com/intellij/util/ReadEnv.java +++ b/platform/util-rt/src/com/intellij/util/ReadEnv.java @@ -14,8 +14,16 @@ public class ReadEnv { Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(args[0]), "UTF-8")); try { for (Map.Entry each : System.getenv().entrySet()) { + // on Windows Java getenv() includes variables that start from '='. + // These variables are not available available in normal command environment. + + // https://stackoverflow.com/questions/30102750/java-system-getenv-environment-names-starting-with if (each.getKey().startsWith("=")) continue; - out.write(each.getKey() + "=" + each.getValue() + "\0"); + + out.write(each.getKey()); + out.write("="); + out.write(each.getValue()); + out.write("\0"); } } finally { diff --git a/platform/util/src/com/intellij/execution/CommandLineUtil.java b/platform/util/src/com/intellij/execution/CommandLineUtil.java index e16225f918cd..1513665ca7c9 100644 --- a/platform/util/src/com/intellij/execution/CommandLineUtil.java +++ b/platform/util/src/com/intellij/execution/CommandLineUtil.java @@ -14,7 +14,6 @@ package com.intellij.execution; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Contract; @@ -423,7 +422,7 @@ public class CommandLineUtil { @NotNull public static String getWinShellName() { - return SystemInfo.isWin2kOrNewer ? "cmd.exe" : "command.com"; + return "cmd.exe"; } private static boolean isWinShell(String command) { diff --git a/platform/util/src/com/intellij/util/EnvironmentUtil.java b/platform/util/src/com/intellij/util/EnvironmentUtil.java index 0d26db738424..9dc239230a22 100644 --- a/platform/util/src/com/intellij/util/EnvironmentUtil.java +++ b/platform/util/src/com/intellij/util/EnvironmentUtil.java @@ -204,7 +204,7 @@ public class EnvironmentUtil { cl.add(batchFile.getPath()); cl.addAll(args); cl.add("&&"); - cl.addAll(gerReadEnvCommand()); + cl.addAll(getReadEnvCommand()); cl.add(envFile.getPath()); cl.addAll(Arrays.asList("||", "exit", "/B", "%ERRORLEVEL%")); @@ -219,8 +219,8 @@ public class EnvironmentUtil { } @NotNull - private static List gerReadEnvCommand() { - return Arrays.asList(System.getProperty("java.home") + "/bin/java", + private static List getReadEnvCommand() { + return Arrays.asList(FileUtil.toSystemDependentName(System.getProperty("java.home") + "/bin/java"), "-cp", PathManager.getJarPathForClass(ReadEnv.class), ReadEnv.class.getCanonicalName()); } @@ -234,7 +234,7 @@ public class EnvironmentUtil { @NotNull protected static Map runProcessAndReadEnvs(@NotNull List command, @NotNull File envFile, String lineSeparator) throws Exception { - return runProcessAndReadEnvs(command, null, envFile, lineSeparator); + return runProcessAndReadEnvs(command, null, null, envFile, lineSeparator); } @NotNull @@ -444,7 +444,7 @@ public class EnvironmentUtil { } } - public static class StreamGobbler extends BaseOutputReader { + private static class StreamGobbler extends BaseOutputReader { private static final Options OPTIONS = new Options() { @Override public SleepingPolicy policy() { From d681db417908444ec862f7e4b0f8878ee0a914a6 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 15 Nov 2017 22:53:10 +0100 Subject: [PATCH 06/81] CPP-10844 Visual Studio is not found when path to VS or user home contains non ascii characters: EnvironmentUtil API cleanup --- .../com/intellij/util/EnvironmentUtil.java | 60 +++++-------------- .../sdk/PyVirtualEnvTerminalCustomizer.kt | 18 +----- .../python/run/PyVirtualEnvReader.kt | 10 +--- .../jetbrains/python/sdk/PythonSdkType.java | 18 +----- 4 files changed, 22 insertions(+), 84 deletions(-) diff --git a/platform/util/src/com/intellij/util/EnvironmentUtil.java b/platform/util/src/com/intellij/util/EnvironmentUtil.java index 9dc239230a22..55e9a9bd2977 100644 --- a/platform/util/src/com/intellij/util/EnvironmentUtil.java +++ b/platform/util/src/com/intellij/util/EnvironmentUtil.java @@ -162,8 +162,11 @@ public class EnvironmentUtil { public static class ShellEnvReader { - public Map readShellEnv() throws Exception { + return readShellEnv(null); + } + + protected Map readShellEnv(@Nullable Map additionalEnvironment) throws Exception { File reader = PathManager.findBinFileWithException("printenv.py"); File envFile = FileUtil.createTempFile("intellij-shell-env.", ".tmp", false); @@ -181,7 +184,7 @@ public class EnvironmentUtil { LOG.info("loading shell env: " + StringUtil.join(command, " ")); - return dumpProcessEnvToFile(command, envFile, "\0"); + return runProcessAndReadOutputAndEnvs(command, null, additionalEnvironment, envFile).second; } finally { FileUtil.delete(envFile); @@ -208,10 +211,7 @@ public class EnvironmentUtil { cl.add(envFile.getPath()); cl.addAll(Arrays.asList("||", "exit", "/B", "%ERRORLEVEL%")); - return runProcessAndReadOutputAndEnvs(cl, - batchFile.getParentFile(), - null, - envFile, "\0"); + return runProcessAndReadOutputAndEnvs(cl, batchFile.getParentFile(), null, envFile); } finally { FileUtil.delete(envFile); @@ -225,45 +225,15 @@ public class EnvironmentUtil { ReadEnv.class.getCanonicalName()); } - @NotNull - protected Map dumpProcessEnvToFile(@NotNull List command, @NotNull File envFile, String lineSeparator) - throws Exception { - return runProcessAndReadEnvs(command, envFile, lineSeparator); - } - - @NotNull - protected static Map runProcessAndReadEnvs(@NotNull List command, @NotNull File envFile, String lineSeparator) - throws Exception { - return runProcessAndReadEnvs(command, null, null, envFile, lineSeparator); - } - - @NotNull - protected static Map runProcessAndReadEnvs(@NotNull List command, - @Nullable File workingDir, - @NotNull File envFile, - String lineSeparator) throws Exception { - return runProcessAndReadEnvs(command, workingDir, null, envFile, lineSeparator); - } - - @NotNull - protected static Map runProcessAndReadEnvs(@NotNull List command, - @Nullable File workingDir, - @Nullable Map envs, - @NotNull File envFile, - String lineSeparator) throws Exception { - return runProcessAndReadOutputAndEnvs(command, workingDir, envs, envFile, lineSeparator).second; - } - @NotNull protected static Pair> runProcessAndReadOutputAndEnvs(@NotNull List command, @Nullable File workingDir, - @Nullable Map envs, - @NotNull File envFile, - String lineSeparator) throws Exception { + @Nullable Map scriptEnvironment, + @NotNull File envFile) throws Exception { ProcessBuilder builder = new ProcessBuilder(command).redirectErrorStream(true); - if (envs != null) { + if (scriptEnvironment != null) { // we might need default environment for the process to launch correctly - builder.environment().putAll(envs); + builder.environment().putAll(scriptEnvironment); } if (workingDir != null) builder.directory(workingDir); builder.environment().put(DISABLE_OMZ_AUTO_UPDATE, "true"); @@ -277,7 +247,7 @@ public class EnvironmentUtil { if (rv != 0 || lines.isEmpty()) { throw new Exception("rv:" + rv + " text:" + lines.length() + " out:" + StringUtil.trimEnd(gobbler.getText(), '\n')); } - return Pair.create(gobbler.getText(), parseEnv(lines, lineSeparator)); + return Pair.create(gobbler.getText(), parseEnv(lines)); } @NotNull @@ -297,18 +267,18 @@ public class EnvironmentUtil { } @Nullable - protected String getShell() throws Exception { + protected String getShell() { return System.getenv("SHELL"); } } @NotNull - private static Map parseEnv(String text, String lineSeparator) throws Exception { + private static Map parseEnv(String text) throws Exception { Set toIgnore = new HashSet(Arrays.asList("_", "PWD", "SHLVL", DISABLE_OMZ_AUTO_UPDATE, INTELLIJ_ENVIRONMENT_READER)); Map env = System.getenv(); Map newEnv = new HashMap(); - String[] lines = text.split(lineSeparator); + String[] lines = text.split("\0"); for (String line : lines) { int pos = line.indexOf('='); if (pos <= 0) { @@ -437,7 +407,7 @@ public class EnvironmentUtil { @TestOnly static Map testParser(@NotNull String lines) { try { - return parseEnv(lines, "\0"); + return parseEnv(lines); } catch (Exception e) { throw new RuntimeException(e); diff --git a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt index c24baa6d1eec..56db5220da6e 100644 --- a/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt +++ b/python/python-terminal/src/com/jetbrains/python/sdk/PyVirtualEnvTerminalCustomizer.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.sdk import com.intellij.openapi.components.PersistentStateComponent @@ -69,7 +55,7 @@ class PyVirtualEnvTerminalCustomizer : LocalTerminalCustomizer() { reader.activate?.let { // we add only envs that are setup by the activate script, because adding other variables from the different shell // can break the actual shell - envs.putAll(reader.readShellEnv().mapKeys { k -> k.key.toUpperCase() }.filterKeys { k -> + envs.putAll(reader.readPythonEnv().mapKeys { k -> k.key.toUpperCase() }.filterKeys { k -> k in PyVirtualEnvReader.virtualEnvVars }) } diff --git a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt index 1b7b6753b53f..3e402cb7c2cd 100644 --- a/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt +++ b/python/src/com/jetbrains/python/run/PyVirtualEnvReader.kt @@ -37,10 +37,11 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE } } - override fun readShellEnv(): MutableMap { + fun readPythonEnv(): MutableMap { try { if (SystemInfo.isUnix) { - return super.readShellEnv() + // pass shell environment for correct virtualenv environment setup (virtualenv expects to be executed from the terminal) + return super.readShellEnv(EnvironmentUtil.getEnvironmentMap()) } else { if (activate != null) { @@ -57,11 +58,6 @@ class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellE return mutableMapOf() } - override fun dumpProcessEnvToFile(command: MutableList, envFile: File, lineSeparator: String?): MutableMap { - // pass shell environment for correct virtualenv environment setup (virtualenv expects to be executed from the terminal) - return runProcessAndReadEnvs(command, null, EnvironmentUtil.getEnvironmentMap(), envFile, lineSeparator) - } - override fun getShellProcessCommand(): MutableList { val shellPath = shell diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 8d48be50e085..1404e5c88efb 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.sdk; import com.google.common.collect.ImmutableMap; @@ -949,7 +935,7 @@ public final class PythonSdkType extends SdkType { PyVirtualEnvReader reader = new PyVirtualEnvReader(sdkHome); if (reader.getActivate() != null) { try { - env.putAll(reader.readShellEnv().entrySet().stream() + env.putAll(reader.readPythonEnv().entrySet().stream() .filter((entry) -> PyVirtualEnvReader.Companion.getVirtualEnvVars().contains(entry.getKey()) ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); } From 4854d1f1b88727d5f553f789376f7f461b5c8925 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 16 Nov 2017 17:06:07 +0100 Subject: [PATCH 07/81] FileColorsModel supports predefined colors for custom scopes: reference: CPP-4034 Replace semi-transparent color for non-build files with a dedicated scope for build files OC-2001 File Color: scope for files which are not in project and not in libraries --- .../com/intellij/ui/tabs/FileColorsModel.java | 97 ++++++++----------- 1 file changed, 39 insertions(+), 58 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsModel.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsModel.java index 8f8401a476c1..6f253e8c88cd 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsModel.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorsModel.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui.tabs; @@ -29,7 +15,6 @@ import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; import com.intellij.psi.search.scope.packageSet.PackageSet; import com.intellij.psi.search.scope.packageSet.PackageSetBase; import com.intellij.ui.ColorUtil; -import com.intellij.util.PlatformUtils; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jdom.Element; @@ -49,65 +34,61 @@ import java.util.Map; public class FileColorsModel implements Cloneable { public static final String FILE_COLOR = "fileColor"; - private final List myApplicationLevelConfigurations; - private final List myProjectLevelConfigurations; - private static final Map predefinedScopeNameToPropertyKey; - private static final Map predefinedScopeNameToColor; - - static { - predefinedScopeNameToPropertyKey = new THashMap<>(); - predefinedScopeNameToPropertyKey.put(NonProjectFilesScope.NAME, "file.colors.enable.non.project"); - // These IDEs have TestScope registered (via PackagesScopesProvider or TestScopeProvider) - if (PlatformUtils.isIntelliJ() || PlatformUtils.isRubyMine() || PlatformUtils.isPhpStorm() || PlatformUtils.isWebStorm() || PlatformUtils.isGoIde()) { - predefinedScopeNameToPropertyKey.put(TestsScope.NAME, "file.colors.enable.tests"); - } - - predefinedScopeNameToColor = new THashMap<>(); - } + private final List myApplicationLevelConfigurations = new ArrayList<>(); + private final List myProjectLevelConfigurations = new ArrayList<>(); + private final Map myPredefinedScopeNameToPropertyKey = new THashMap<>(); + private final Map myPredefinedScopeNameToColor = new THashMap<>(); @NotNull private final Project myProject; FileColorsModel(@NotNull final Project project) { myProject = project; - myApplicationLevelConfigurations = new ArrayList<>(); - myProjectLevelConfigurations = new ArrayList<>(); - - if (predefinedScopeNameToColor.size() < predefinedScopeNameToPropertyKey.size()) { - DefaultScopesProvider defaultScopesProvider = DefaultScopesProvider.getInstance(project); - for (String scopeName : predefinedScopeNameToPropertyKey.keySet()) { - final NamedScope scope = defaultScopesProvider.findCustomScope(scopeName); - assert scope != null : "There is no custom scope with name " + scopeName; - final Color color = ColorUtil.getColor(scope.getClass()); - assert color != null : scope.getClass().getName() + " is not annotated with @Colored"; - final String colorName = FileColorManagerImpl.getColorName(color); - predefinedScopeNameToColor.put(scopeName, colorName == null ? ColorUtil.toHex(color) : colorName); - } - } - initGlobalScopes(); + initPredefinedAndGlobalScopes(); } private FileColorsModel(@NotNull Project project, @NotNull List applicationLevel, @NotNull List projectLevel) { myProject = project; - myApplicationLevelConfigurations = new ArrayList<>(); - myProjectLevelConfigurations = new ArrayList<>(); myApplicationLevelConfigurations.addAll(applicationLevel); myProjectLevelConfigurations.addAll(projectLevel); - initGlobalScopes(); + initPredefinedAndGlobalScopes(); } - private void initGlobalScopes() { + private void initPredefinedAndGlobalScopes() { + for (NamedScope scope : DefaultScopesProvider.getInstance(myProject).getAllCustomScopes()) { + String scopeName = scope.getName(); + + final Color color = ColorUtil.getColor(scope.getClass()); + if (color == null) continue; + String colorName = FileColorManagerImpl.getColorName(color); + + myPredefinedScopeNameToColor.put(scopeName, colorName == null ? ColorUtil.toHex(color) : colorName); + + String propertyKey; + if (NonProjectFilesScope.NAME.equals(scopeName)) { + propertyKey = "file.colors.enable.non.project"; + } + else if (TestsScope.NAME.equals(scopeName)) { + propertyKey = "file.colors.enable.tests"; + } + else { + propertyKey = "file.colors.enable.custom." + scopeName; + } + + myPredefinedScopeNameToPropertyKey.put(scopeName, propertyKey); + } + PropertiesComponent propertyComponent = PropertiesComponent.getInstance(); - for (String scopeName : predefinedScopeNameToPropertyKey.keySet()) { + for (String scopeName : myPredefinedScopeNameToPropertyKey.keySet()) { if (findConfiguration(scopeName, false) == null) { - String color = propertyComponent.getValue(predefinedScopeNameToPropertyKey.get(scopeName)); + String color = propertyComponent.getValue(myPredefinedScopeNameToPropertyKey.get(scopeName)); if (color == null) { // backward compatibility, previously it was saved incorrectly as scope name instead of specified property key color = propertyComponent.getValue(scopeName); if (color == null) { - color = predefinedScopeNameToColor.get(scopeName); + color = myPredefinedScopeNameToColor.get(scopeName); } } @@ -124,13 +105,13 @@ public class FileColorsModel implements Cloneable { List configurations = isProjectLevel ? myProjectLevelConfigurations : myApplicationLevelConfigurations; for (FileColorConfiguration configuration : configurations) { String scopeName = configuration.getScopeName(); - String propertyKey = isProjectLevel ? null : predefinedScopeNameToPropertyKey.get(scopeName); + String propertyKey = isProjectLevel ? null : myPredefinedScopeNameToPropertyKey.get(scopeName); if (propertyKey == null) { configuration.save(e); } else { PropertiesComponent propertyComponent = PropertiesComponent.getInstance(); - propertyComponent.setValue(propertyKey, configuration.getColorName(), predefinedScopeNameToColor.get(scopeName)); + propertyComponent.setValue(propertyKey, configuration.getColorName(), myPredefinedScopeNameToColor.get(scopeName)); // previously it was saved incorrectly as scope name instead of specified property key PropertiesComponent.getInstance().setValue(scopeName, null); } @@ -142,7 +123,7 @@ public class FileColorsModel implements Cloneable { configurations.clear(); - Map predefinedScopeNameToPropertyKey = new THashMap<>(FileColorsModel.predefinedScopeNameToPropertyKey); + Map predefinedScopeNameToPropertyKey = new THashMap<>(myPredefinedScopeNameToPropertyKey); for (Element child : e.getChildren(FILE_COLOR)) { FileColorConfiguration configuration = FileColorConfiguration.load(child); if (configuration != null) { @@ -163,7 +144,7 @@ public class FileColorsModel implements Cloneable { // so, default value if (colorName == null) { - colorName = predefinedScopeNameToColor.get(scopeName); + colorName = myPredefinedScopeNameToColor.get(scopeName); } } // empty means that value deleted @@ -282,7 +263,7 @@ public class FileColorsModel implements Cloneable { } else { myApplicationLevelConfigurations.clear(); - Map predefinedScopeNameToPropertyKey = new THashMap<>(FileColorsModel.predefinedScopeNameToPropertyKey); + Map predefinedScopeNameToPropertyKey = new THashMap<>(myPredefinedScopeNameToPropertyKey); PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(); for (FileColorConfiguration configuration : configurations) { myApplicationLevelConfigurations.add(configuration); From 1e226a58d65d9027ac7b5c22eb189ea1c828c0cb Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 12:39:03 +0300 Subject: [PATCH 08/81] changed notification level to warning --- .../src/com/intellij/debugger/engine/DebugProcessEvents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index 16d5c4b016b0..2d36cc14cbc9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -558,7 +558,7 @@ public class DebugProcessEvents extends DebugProcessImpl { if (event != null && myNotificationsCoolDown.compareAndSet(false, true)) { AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> myNotificationsCoolDown.set(false), 1, TimeUnit.SECONDS); XDebuggerManagerImpl.NOTIFICATION_GROUP - .createNotification(DebuggerBundle.message("message.breakpoint.skipped", event.location()), MessageType.INFO) + .createNotification(DebuggerBundle.message("message.breakpoint.skipped", event.location()), MessageType.WARNING) .notify(getProject()); } } From ec5e010a2e7128528b0657ac6b3e605fab1bbcc8 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 16 Nov 2017 19:40:40 +0300 Subject: [PATCH 09/81] ModuleDeleteProvider cleanup: don't create unnecessary ModifiableRootModel --- .../roots/ui/configuration/ModulesConfigurator.java | 2 +- .../configuration/actions/ModuleDeleteProvider.java | 13 +++---------- .../plugins/groovy/mvc/MvcModuleStructureUtil.java | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index 8d97e808fa73..f48f1cd14025 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -473,7 +473,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change ContainerUtil.addIfNotNull(modifiableRootModels, modifiableRootModel); } - ModuleDeleteProvider.removeModule(moduleToRemove, null, modifiableRootModels, myModuleModel); + ModuleDeleteProvider.removeModule(moduleToRemove, modifiableRootModels, myModuleModel); Disposer.dispose(editor); } processModuleCountChanged(); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java index 9aabb14c1f5a..ed2f2f74a343 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java @@ -41,7 +41,6 @@ import com.intellij.util.ArrayUtilRt; import com.intellij.util.PathUtilRt; import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Collection; @@ -91,14 +90,13 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { final ModifiableModuleModel modifiableModuleModel = moduleManager.getModifiableModel(); final Map otherModuleRootModels = new HashMap<>(); for (final Module module : modules) { - final ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel(); for (final Module otherModule : currentModules) { if (otherModule == module || ArrayUtilRt.find(modules, otherModule) != -1) continue; if (!otherModuleRootModels.containsKey(otherModule)) { otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel()); } } - removeModule(module, modifiableModel, otherModuleRootModels.values(), modifiableModuleModel); + removeModule(module, otherModuleRootModels.values(), modifiableModuleModel); } final ModifiableRootModel[] modifiableRootModels = otherModuleRootModels.values().toArray(new ModifiableRootModel[otherModuleRootModels.size()]); ModifiableModelCommitter.multiCommit(modifiableRootModels, modifiableModuleModel); @@ -120,9 +118,8 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { } public static void removeModule(@NotNull final Module moduleToRemove, - @Nullable ModifiableRootModel modifiableRootModelToRemove, - @NotNull Collection otherModuleRootModels, - @NotNull final ModifiableModuleModel moduleModel) { + @NotNull Collection otherModuleRootModels, + @NotNull final ModifiableModuleModel moduleModel) { // remove all dependencies on the module that is about to be removed for (final ModifiableRootModel modifiableRootModel : otherModuleRootModels) { final OrderEntry[] orderEntries = modifiableRootModel.getOrderEntries(); @@ -135,10 +132,6 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { } } } - // destroyProcess editor - if (modifiableRootModelToRemove != null) { - modifiableRootModelToRemove.dispose(); - } // destroyProcess module moduleModel.disposeModule(moduleToRemove); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java index 1fe2389befdc..dde2b905353c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java @@ -531,7 +531,7 @@ public class MvcModuleStructureUtil { final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel(); - ModuleDeleteProvider.removeModule(toRemove, null, usingModels, moduleModel); + ModuleDeleteProvider.removeModule(toRemove, usingModels, moduleModel); ModifiableModelCommitter.multiCommit(usingModels, moduleModel); } From d2847285f8773efc3a6ba06636da1b0b221b0d83 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 17 Nov 2017 11:45:08 +0300 Subject: [PATCH 10/81] ModuleDeleteProvider: simplification and optimization, test added Previous version may take cubic time of number of modules. --- .../actions/ModuleDeleteProviderTest.java | 68 +++++++++++++++++++ .../actions/ModuleDeleteProvider.java | 39 ++++++----- 2 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java new file mode 100644 index 000000000000..381fedbf915e --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java @@ -0,0 +1,68 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.roots.ui.configuration.actions; + +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.TestDialog; +import com.intellij.testFramework.MapDataContext; +import com.intellij.testFramework.PlatformTestCase; + +/** + * @author nik + */ +public class ModuleDeleteProviderTest extends PlatformTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + Messages.setTestDialog(TestDialog.OK); + } + + public void testSimple() { + Module a = createModule("a"); + assertNotNull(ModuleManager.getInstance(myProject).findModuleByName("a")); + deleteModules(a); + assertNull(ModuleManager.getInstance(myProject).findModuleByName("a")); + } + + public void testDeleteDependency() { + Module a = createModule("a"); + Module b = createModule("b"); + ModuleRootModificationUtil.addDependency(a, b); + assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b"); + deleteModules(b); + assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames()); + } + + public void testDeleteTwoModules() { + Module a = createModule("a"); + Module b = createModule("b"); + ModuleRootModificationUtil.addDependency(a, b); + ModuleRootModificationUtil.addDependency(myModule, a); + ModuleRootModificationUtil.addDependency(myModule, b); + assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b"); + deleteModules(a, b); + assertNull(ModuleManager.getInstance(myProject).findModuleByName("a")); + assertNull(ModuleManager.getInstance(myProject).findModuleByName("b")); + assertEmpty(ModuleRootManager.getInstance(myModule).getDependencyModuleNames()); + } + + private void deleteModules(Module... modules) { + ModuleDeleteProvider provider = new ModuleDeleteProvider(); + MapDataContext dataContext = new MapDataContext(); + dataContext.put(CommonDataKeys.PROJECT, myProject); + dataContext.put(LangDataKeys.MODULE_CONTEXT_ARRAY, modules); + assertTrue(provider.canDeleteElement(dataContext)); + provider.deleteElement(dataContext); + } + + @Override + public void tearDown() throws Exception { + Messages.setTestDialog(TestDialog.DEFAULT); + super.tearDown(); + } +} diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java index ed2f2f74a343..c2d732cc70f5 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java @@ -37,15 +37,12 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; import com.intellij.project.ProjectKt; import com.intellij.projectImport.ProjectAttachProcessor; -import com.intellij.util.ArrayUtilRt; import com.intellij.util.PathUtilRt; import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { @Override @@ -89,14 +86,15 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { final Module[] currentModules = moduleManager.getModules(); final ModifiableModuleModel modifiableModuleModel = moduleManager.getModifiableModel(); final Map otherModuleRootModels = new HashMap<>(); - for (final Module module : modules) { - for (final Module otherModule : currentModules) { - if (otherModule == module || ArrayUtilRt.find(modules, otherModule) != -1) continue; - if (!otherModuleRootModels.containsKey(otherModule)) { - otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel()); - } + Set moduleNamesToDelete = Arrays.stream(modules).map(Module::getName).collect(Collectors.toSet()); + for (final Module otherModule : currentModules) { + if (!moduleNamesToDelete.contains(otherModule.getName())) { + otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel()); } - removeModule(module, otherModuleRootModels.values(), modifiableModuleModel); + } + removeDependenciesOnModules(moduleNamesToDelete, otherModuleRootModels.values()); + for (final Module module : modules) { + modifiableModuleModel.disposeModule(module); } final ModifiableRootModel[] modifiableRootModels = otherModuleRootModels.values().toArray(new ModifiableRootModel[otherModuleRootModels.size()]); ModifiableModelCommitter.multiCommit(modifiableRootModels, modifiableModuleModel); @@ -120,19 +118,20 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { public static void removeModule(@NotNull final Module moduleToRemove, @NotNull Collection otherModuleRootModels, @NotNull final ModifiableModuleModel moduleModel) { - // remove all dependencies on the module that is about to be removed + removeDependenciesOnModules(Collections.singleton(moduleToRemove.getName()), otherModuleRootModels); + moduleModel.disposeModule(moduleToRemove); + } + + private static void removeDependenciesOnModules(@NotNull Set moduleNamesToRemove, + @NotNull Collection otherModuleRootModels) { for (final ModifiableRootModel modifiableRootModel : otherModuleRootModels) { final OrderEntry[] orderEntries = modifiableRootModel.getOrderEntries(); for (final OrderEntry orderEntry : orderEntries) { - if (orderEntry instanceof ModuleOrderEntry && orderEntry.isValid()) { - final Module orderEntryModule = ((ModuleOrderEntry)orderEntry).getModule(); - if (orderEntryModule != null && orderEntryModule.equals(moduleToRemove)) { - modifiableRootModel.removeOrderEntry(orderEntry); - } + if (orderEntry instanceof ModuleOrderEntry && orderEntry.isValid() && + moduleNamesToRemove.contains(((ModuleOrderEntry)orderEntry).getModuleName())) { + modifiableRootModel.removeOrderEntry(orderEntry); } } } - // destroyProcess module - moduleModel.disposeModule(moduleToRemove); } } From c1dbfea842655d1db2afa2c1162d2aeb131a3138 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 17 Nov 2017 12:46:07 +0300 Subject: [PATCH 11/81] project view: support deleting unloaded modules Previously when a user press 'Delete' on a content root from an unloaded module in 'Project View', IDE will suggest to delete a directory. It may be unexpected and even lead to data loss if the user don't read the message carefully (IDEA-182200). Now it'll suggest to remove the unloaded module from the project. --- .../actions/ModuleDeleteProviderTest.java | 81 ++++++++++++++++--- .../intellij/ide/projectView/ProjectView.java | 8 ++ .../ide/projectView/impl/ProjectViewImpl.java | 32 +++++++- .../actions/ModuleDeleteProvider.java | 47 +++++++---- .../openapi/module/ModuleManager.java | 4 + .../openapi/module/EmptyModuleManager.kt | 3 + .../module/impl/ModuleManagerImpl.java | 9 +++ 7 files changed, 157 insertions(+), 27 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java index 381fedbf915e..4dccc099bd23 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProviderTest.java @@ -1,10 +1,12 @@ // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.roots.ui.configuration.actions; +import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.UnloadedModuleDescription; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.ui.Messages; @@ -12,6 +14,10 @@ import com.intellij.openapi.ui.TestDialog; import com.intellij.testFramework.MapDataContext; import com.intellij.testFramework.PlatformTestCase; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * @author nik */ @@ -23,10 +29,10 @@ public class ModuleDeleteProviderTest extends PlatformTestCase { } public void testSimple() { - Module a = createModule("a"); - assertNotNull(ModuleManager.getInstance(myProject).findModuleByName("a")); - deleteModules(a); - assertNull(ModuleManager.getInstance(myProject).findModuleByName("a")); + createModule("a"); + assertNotNull(getModuleManager().findModuleByName("a")); + deleteModules("a"); + assertNull(getModuleManager().findModuleByName("a")); } public void testDeleteDependency() { @@ -34,7 +40,7 @@ public class ModuleDeleteProviderTest extends PlatformTestCase { Module b = createModule("b"); ModuleRootModificationUtil.addDependency(a, b); assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b"); - deleteModules(b); + deleteModules("b"); assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames()); } @@ -45,17 +51,72 @@ public class ModuleDeleteProviderTest extends PlatformTestCase { ModuleRootModificationUtil.addDependency(myModule, a); ModuleRootModificationUtil.addDependency(myModule, b); assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b"); - deleteModules(a, b); - assertNull(ModuleManager.getInstance(myProject).findModuleByName("a")); - assertNull(ModuleManager.getInstance(myProject).findModuleByName("b")); + deleteModules("a", "b"); + assertNull(getModuleManager().findModuleByName("a")); + assertNull(getModuleManager().findModuleByName("b")); assertEmpty(ModuleRootManager.getInstance(myModule).getDependencyModuleNames()); } - private void deleteModules(Module... modules) { + public void testUnloaded() { + createModule("a"); + getModuleManager().setUnloadedModules(Arrays.asList("a")); + assertNotNull(getModuleManager().getUnloadedModuleDescription("a")); + deleteModules("a"); + assertNull(getModuleManager().getUnloadedModuleDescription("a")); + } + + public void testDeleteDependencyOnUnloadedModule() { + Module a = createModule("a"); + Module b = createModule("b"); + ModuleRootModificationUtil.addDependency(a, b); + getModuleManager().setUnloadedModules(Arrays.asList("b")); + assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b"); + deleteModules("b"); + assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames()); + } + + public void testLoadedAndUnloadedModule() { + Module a = createModule("a"); + Module b = createModule("b"); + ModuleRootModificationUtil.addDependency(a, b); + ModuleRootModificationUtil.addDependency(myModule, a); + ModuleRootModificationUtil.addDependency(myModule, b); + getModuleManager().setUnloadedModules(Arrays.asList("a")); + assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b"); + deleteModules("a", "b"); + assertNull(getModuleManager().findModuleByName("a")); + assertNull(getModuleManager().findModuleByName("b")); + assertEmpty(getModuleManager().getUnloadedModuleDescriptions()); + assertEmpty(ModuleRootManager.getInstance(myModule).getDependencyModuleNames()); + } + + private ModuleManager getModuleManager() { + return ModuleManager.getInstance(myProject); + } + + private void deleteModules(String... names) { ModuleDeleteProvider provider = new ModuleDeleteProvider(); MapDataContext dataContext = new MapDataContext(); dataContext.put(CommonDataKeys.PROJECT, myProject); - dataContext.put(LangDataKeys.MODULE_CONTEXT_ARRAY, modules); + List modules = new ArrayList<>(); + List unloaded = new ArrayList<>(); + for (String name : names) { + UnloadedModuleDescription description = getModuleManager().getUnloadedModuleDescription(name); + if (description != null) { + unloaded.add(description); + } + else { + Module module = getModuleManager().findModuleByName(name); + assertNotNull("Module " + name + " not found", module); + modules.add(module); + } + } + if (!modules.isEmpty()) { + dataContext.put(LangDataKeys.MODULE_CONTEXT_ARRAY, modules.toArray(Module.EMPTY_ARRAY)); + } + if (!unloaded.isEmpty()) { + dataContext.put(ProjectView.UNLOADED_MODULES_CONTEXT_KEY, unloaded); + } assertTrue(provider.canDeleteElement(dataContext)); provider.deleteElement(dataContext); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java index 80a69dac46c6..17230cdda58c 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java @@ -18,7 +18,9 @@ package com.intellij.ide.projectView; import com.intellij.ide.SelectInTarget; import com.intellij.ide.projectView.impl.AbstractProjectViewPane; +import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.UnloadedModuleDescription; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.vfs.VirtualFile; @@ -27,8 +29,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.List; public abstract class ProjectView { + /** + * Use this key to get unloaded modules which content roots are selected in Project View + */ + public static final DataKey> UNLOADED_MODULES_CONTEXT_KEY = DataKey.create("context.unloaded.modules.list"); + public static ProjectView getInstance(Project project) { return ServiceManager.getService(project, ProjectView.class); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 68de580e2ef9..14b84f572dd4 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -51,7 +51,9 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.module.UnloadedModuleDescription; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; @@ -87,6 +89,7 @@ import com.intellij.ui.tree.TreeVisitor; import com.intellij.util.ArrayUtil; import com.intellij.util.IJSwingUtilities; import com.intellij.util.PlatformIcons; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import com.intellij.util.messages.MessageBusConnection; @@ -1104,7 +1107,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo } if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { final Module[] modules = getSelectedModules(); - if (modules != null) { + if (modules != null || !getSelectedUnloadedModules().isEmpty()) { return myDeleteModuleProvider; } final LibraryOrderEntry orderEntry = getSelectedLibrary(); @@ -1152,6 +1155,9 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo if (LangDataKeys.MODULE_CONTEXT_ARRAY.is(dataId)) { return getSelectedModules(); } + if (UNLOADED_MODULES_CONTEXT_KEY.is(dataId)) { + return Collections.unmodifiableList(getSelectedUnloadedModules()); + } if (ModuleGroup.ARRAY_DATA_KEY.is(dataId)) { final List selectedElements = getSelectedElements(ModuleGroup.class); return selectedElements.isEmpty() ? null : selectedElements.toArray(new ModuleGroup[selectedElements.size()]); @@ -1260,6 +1266,21 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo return result.toArray(new Module[result.size()]); } } + + private List getSelectedUnloadedModules() { + final AbstractProjectViewPane viewPane = getCurrentProjectViewPane(); + if (viewPane == null) return Collections.emptyList(); + List result = new SmartList<>(); + for (Object element : viewPane.getSelectedElements()) { + if (element instanceof PsiDirectory) { + ContainerUtil.addIfNotNull(result, getUnloadedModuleByContentRoot(((PsiDirectory)element).getVirtualFile())); + } + else if (element instanceof VirtualFile) { + ContainerUtil.addIfNotNull(result, getUnloadedModuleByContentRoot((VirtualFile)element)); + } + } + return result; + } } /** Project view has the same node for module and its single content root @@ -1280,6 +1301,15 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo return null; } + @Nullable + private UnloadedModuleDescription getUnloadedModuleByContentRoot(@NotNull VirtualFile file) { + String moduleName = ProjectRootsUtil.findUnloadedModuleByContentRoot(file, myProject); + if (moduleName != null) { + return ModuleManager.getInstance(myProject).getUnloadedModuleDescription(moduleName); + } + return null; + } + @NotNull private List getSelectedElements(@NotNull Class klass) { List result = new ArrayList<>(); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java index c2d732cc70f5..0f69824e17de 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java @@ -18,14 +18,14 @@ package com.intellij.openapi.roots.ui.configuration.actions; import com.intellij.ide.DeleteProvider; import com.intellij.ide.TitledHandler; +import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.module.ModifiableModuleModel; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.*; +import com.intellij.openapi.module.impl.LoadedModuleDescriptionImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.ModifiableRootModel; @@ -39,6 +39,7 @@ import com.intellij.project.ProjectKt; import com.intellij.projectImport.ProjectAttachProcessor; import com.intellij.util.PathUtilRt; import com.intellij.util.PlatformUtils; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -48,7 +49,8 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { @Override public boolean canDeleteElement(@NotNull DataContext dataContext) { final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext); - return modules != null && !containsPrimaryModule(modules); + List unloadedModules = ProjectView.UNLOADED_MODULES_CONTEXT_KEY.getData(dataContext); + return modules != null && !containsPrimaryModule(modules) || unloadedModules != null && !unloadedModules.isEmpty(); } private static boolean containsPrimaryModule(Module[] modules) { @@ -73,12 +75,21 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { @Override public void deleteElement(@NotNull DataContext dataContext) { - final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext); - assert modules != null; final Project project = CommonDataKeys.PROJECT.getData(dataContext); assert project != null; - String names = StringUtil.join(Arrays.asList(modules), module -> "\'" + module.getName() + "\'", ", "); - int ret = Messages.showOkCancelDialog(getConfirmationText(modules, names), getActionTitle(), Messages.getQuestionIcon()); + + List moduleDescriptions = new ArrayList<>(); + final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext); + if (modules != null) { + moduleDescriptions.addAll(ContainerUtil.map(modules, LoadedModuleDescriptionImpl::new)); + } + List unloadedModules = ProjectView.UNLOADED_MODULES_CONTEXT_KEY.getData(dataContext); + if (unloadedModules != null) { + moduleDescriptions.addAll(unloadedModules); + } + + String names = StringUtil.join(moduleDescriptions, description -> "\'" + description.getName() + "\'", ", "); + int ret = Messages.showOkCancelDialog(getConfirmationText(names, moduleDescriptions.size()), getActionTitle(), Messages.getQuestionIcon()); if (ret != Messages.OK) return; CommandProcessor.getInstance().executeCommand(project, () -> { final Runnable action = () -> { @@ -86,28 +97,33 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { final Module[] currentModules = moduleManager.getModules(); final ModifiableModuleModel modifiableModuleModel = moduleManager.getModifiableModel(); final Map otherModuleRootModels = new HashMap<>(); - Set moduleNamesToDelete = Arrays.stream(modules).map(Module::getName).collect(Collectors.toSet()); + Set moduleNamesToDelete = moduleDescriptions.stream().map(ModuleDescription::getName).collect(Collectors.toSet()); for (final Module otherModule : currentModules) { if (!moduleNamesToDelete.contains(otherModule.getName())) { otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel()); } } removeDependenciesOnModules(moduleNamesToDelete, otherModuleRootModels.values()); - for (final Module module : modules) { - modifiableModuleModel.disposeModule(module); + if (modules != null) { + for (final Module module : modules) { + modifiableModuleModel.disposeModule(module); + } } final ModifiableRootModel[] modifiableRootModels = otherModuleRootModels.values().toArray(new ModifiableRootModel[otherModuleRootModels.size()]); ModifiableModelCommitter.multiCommit(modifiableRootModels, modifiableModuleModel); + if (unloadedModules != null) { + moduleManager.removeUnloadedModules(unloadedModules); + } }; ApplicationManager.getApplication().runWriteAction(action); }, ProjectBundle.message("module.remove.command"), null); } - private static String getConfirmationText(Module[] modules, String names) { + private static String getConfirmationText(String names, int numberOfModules) { if (ProjectAttachProcessor.canAttachToProject()) { - return ProjectBundle.message("project.remove.confirmation.prompt", names, modules.length); + return ProjectBundle.message("project.remove.confirmation.prompt", names, numberOfModules); } - return ProjectBundle.message("module.remove.confirmation.prompt", names, modules.length); + return ProjectBundle.message("module.remove.confirmation.prompt", names, numberOfModules); } @Override @@ -127,8 +143,7 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { for (final ModifiableRootModel modifiableRootModel : otherModuleRootModels) { final OrderEntry[] orderEntries = modifiableRootModel.getOrderEntries(); for (final OrderEntry orderEntry : orderEntries) { - if (orderEntry instanceof ModuleOrderEntry && orderEntry.isValid() && - moduleNamesToRemove.contains(((ModuleOrderEntry)orderEntry).getModuleName())) { + if (orderEntry instanceof ModuleOrderEntry && moduleNamesToRemove.contains(((ModuleOrderEntry)orderEntry).getModuleName())) { modifiableRootModel.removeOrderEntry(orderEntry); } } diff --git a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java index 8b51b206c968..8a8028d91252 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java +++ b/platform/projectModel-api/src/com/intellij/openapi/module/ModuleManager.java @@ -194,4 +194,8 @@ public abstract class ModuleManager extends SimpleModificationTracker { */ @ApiStatus.Experimental public abstract void setUnloadedModules(@NotNull List unloadedModuleNames); + + @ApiStatus.Experimental + public void removeUnloadedModules(@NotNull Collection unloadedModules) { + } } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/EmptyModuleManager.kt b/platform/projectModel-impl/src/com/intellij/openapi/module/EmptyModuleManager.kt index a2e67b6bfc73..7b41113790a3 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/module/EmptyModuleManager.kt +++ b/platform/projectModel-impl/src/com/intellij/openapi/module/EmptyModuleManager.kt @@ -57,4 +57,7 @@ class EmptyModuleManager(project: Project, messageBus: MessageBus) : ModuleManag override fun getUnloadedModuleDescriptions() = emptyList() override fun getUnloadedModuleDescription(moduleName: String) = null + + override fun removeUnloadedModules(unloadedModules: MutableCollection) { + } } \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java index 03f40655d69a..56f073da061d 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java @@ -1068,6 +1068,15 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Disposa myModulePathsToLoad.clear(); } + @Override + public void removeUnloadedModules(@NotNull Collection unloadedModules) { + ApplicationManager.getApplication().assertWriteAccessAllowed(); + for (UnloadedModuleDescription module : unloadedModules) { + myUnloadedModules.remove(module.getName()); + } + setUnloadedModuleNames(new ArrayList<>(myUnloadedModules.keySet())); + } + protected void setUnloadedModuleNames(@NotNull List unloadedModuleNames) { UnloadedModulesListStorage.getInstance(myProject).setUnloadedModuleNames(unloadedModuleNames); } From bf7edbabdd07c1e46dcc6ca5076fb3e3e69bf54d Mon Sep 17 00:00:00 2001 From: "Irina.Chernushina" Date: Fri, 17 Nov 2017 11:29:42 +0100 Subject: [PATCH 12/81] vue.js: completion for binding attributes (v-bind, :) - suggest bindings for default html attributes - suggest bindings for vue component properties - resolve was implemented earlier the problem described in WEB-29659 Vue.js plugin does not support "props" in custom components --- .../intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java index 1acfdc353b08..790e14d4e0bd 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java @@ -90,7 +90,7 @@ public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware, XmlNSTy } @Nullable - private static XmlElementDescriptor guessTagForCommonAttributes(@Nullable final XmlTag context) { + public static XmlElementDescriptor guessTagForCommonAttributes(@Nullable final XmlTag context) { if (context == null) return null; final XmlNSDescriptor nsDescriptor = context.getNSDescriptor(context.getNamespace(), false); if (nsDescriptor instanceof HtmlNSDescriptorImpl) { From 98bd65868326159009016228cdd404a2e4817644 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 17 Nov 2017 13:49:17 +0300 Subject: [PATCH 13/81] Build window: close listeners memory leak fixed --- .../build/BuildContentManagerImpl.java | 35 ++++++++++++++++--- .../intellij/build/MultipleBuildsView.java | 6 ++-- .../ExternalSystemProcessHandler.java | 3 ++ .../util/ExternalSystemUtil.java | 6 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/build/BuildContentManagerImpl.java b/java/compiler/impl/src/com/intellij/build/BuildContentManagerImpl.java index 18eb9156ff98..49494e78e03e 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildContentManagerImpl.java +++ b/java/compiler/impl/src/com/intellij/build/BuildContentManagerImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.project.VetoableProjectManagerListener; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; @@ -75,6 +76,8 @@ public class BuildContentManagerImpl implements BuildContentManager { public static final String Run = "Run"; public static final String Debug = "Debug"; private static final String[] ourPresetOrder = {Build, Sync, Run, Debug}; + private static final Key> CONTENT_CLOSE_LISTENERS = Key.create("CONTENT_CLOSE_LISTENERS"); + private Project myProject; private ToolWindow myToolWindow; private final List myPostponedRunnables = new ArrayList<>(); @@ -263,9 +266,16 @@ public class BuildContentManagerImpl implements BuildContentManager { return content; } - public void startBuildNotified(@NotNull Content content, @Nullable BuildProcessHandler processHandler) { + public void startBuildNotified(@NotNull BuildDescriptor buildDescriptor, + @NotNull Content content, + @Nullable BuildProcessHandler processHandler) { if (processHandler != null) { - new CloseListener(content, processHandler); + Map closeListenerMap = content.getUserData(CONTENT_CLOSE_LISTENERS); + if (closeListenerMap == null) { + closeListenerMap = ContainerUtil.newHashMap(); + content.putUserData(CONTENT_CLOSE_LISTENERS, closeListenerMap); + } + closeListenerMap.put(buildDescriptor.getId(), new CloseListener(content, processHandler)); } runWhenInitialized(() -> { Pair pair = liveContentsMap.computeIfAbsent(content, c -> Pair.pair(c.getIcon(), new AtomicInteger(0))); @@ -280,7 +290,17 @@ public class BuildContentManagerImpl implements BuildContentManager { }); } - public void finishBuildNotified(@NotNull Content content) { + public void finishBuildNotified(@NotNull BuildDescriptor buildDescriptor, @NotNull Content content) { + Map closeListenerMap = content.getUserData(CONTENT_CLOSE_LISTENERS); + if (closeListenerMap != null) { + CloseListener closeListener = closeListenerMap.remove(buildDescriptor.getId()); + if (closeListener != null) { + Disposer.dispose(closeListener); + if (closeListenerMap.isEmpty()) { + content.putUserData(CONTENT_CLOSE_LISTENERS, null); + } + } + } runWhenInitialized(() -> { Pair pair = liveContentsMap.get(content); if (pair != null && pair.second.decrementAndGet() == 0) { @@ -308,8 +328,10 @@ public class BuildContentManagerImpl implements BuildContentManager { } private class CloseListener extends ContentManagerAdapter implements VetoableProjectManagerListener, Disposable { + @Nullable private Content myContent; - private final BuildProcessHandler myProcessHandler; + @Nullable + private BuildProcessHandler myProcessHandler; private CloseListener(@NotNull final Content content, @NotNull BuildProcessHandler processHandler) { myContent = content; @@ -339,8 +361,11 @@ public class BuildContentManagerImpl implements BuildContentManager { contentManager.removeContentManagerListener(this); } ProjectManager.getInstance().removeProjectManagerListener(myProject, this); - content.release(); myContent = null; + if (myProcessHandler instanceof Disposable) { + Disposer.dispose((Disposable)myProcessHandler); + } + myProcessHandler = null; } @Override diff --git a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java index 3fdd00025494..7390bd13e274 100644 --- a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java +++ b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java @@ -201,7 +201,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { boolean focusContent = contentDescriptor.isAutoFocusContent(); myBuildContentManager.setSelectedContent( myContent, focusContent, focusContent, activateToolWindow, contentDescriptor.getActivationCallback()); - Disposer.register(this, contentDescriptor); + Disposer.register(view, contentDescriptor); } else { myBuildContentManager.setSelectedContent(myContent, true, true, true, null); @@ -233,7 +233,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { } myViewManager.onBuildStart(buildInfo); myProgressWatcher.addBuild(buildInfo); - ((BuildContentManagerImpl)myBuildContentManager).startBuildNotified(buildInfo.content, startBuildEvent.getProcessHandler()); + ((BuildContentManagerImpl)myBuildContentManager).startBuildNotified(buildInfo, buildInfo.content, startBuildEvent.getProcessHandler()); } else { if (event instanceof FinishBuildEvent) { @@ -241,7 +241,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { buildInfo.message = event.getMessage(); buildInfo.result = ((FinishBuildEvent)event).getResult(); myProgressWatcher.stopBuild(buildInfo); - ((BuildContentManagerImpl)myBuildContentManager).finishBuildNotified(buildInfo.content); + ((BuildContentManagerImpl)myBuildContentManager).finishBuildNotified(buildInfo, buildInfo.content); myViewManager.onBuildFinish(buildInfo); } else { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemProcessHandler.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemProcessHandler.java index 4b9a65d0251c..8afa13aa2658 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemProcessHandler.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemProcessHandler.java @@ -105,6 +105,9 @@ public class ExternalSystemProcessHandler extends BuildProcessHandler implements } protected void closeInput() { + if (myTask instanceof UserDataHolder) { + ((UserDataHolder)myTask).putUserData(ExternalSystemRunConfiguration.RUN_INPUT_KEY, null); + } StreamUtil.closeStream(myProcessInput); myProcessInput = null; } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index 731d8c23015b..dda28b6ebd9e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -390,9 +390,10 @@ public class ExternalSystemUtil { else { projectName = projectFile.getName(); } + final ExternalSystemResolveProjectTask myTask = + new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, vmOptions, arguments, isPreviewMode); + final TaskUnderProgress refreshProjectStructureTask = new TaskUnderProgress() { - private final ExternalSystemResolveProjectTask myTask - = new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, vmOptions, arguments, isPreviewMode); @SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"}) @Override @@ -442,7 +443,6 @@ public class ExternalSystemUtil { consoleManager.attachExecutionConsole(project, myTask, null, processHandler); if (consoleView != null) { Disposer.register(project, consoleView); - Disposer.register(consoleView, processHandler); } else { Disposer.register(project, processHandler); } From aef4672d167bde44870970e96828e3cb3b4f6b88 Mon Sep 17 00:00:00 2001 From: Yaroslav Pankratyev Date: Fri, 17 Nov 2017 14:09:54 +0700 Subject: [PATCH 14/81] IDEA-166677 Only plugin descriptor files for XInclude completion --- ...ginDescriptorXIncludeReferenceContributor.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/devkit/src/references/PluginDescriptorXIncludeReferenceContributor.java b/plugins/devkit/src/references/PluginDescriptorXIncludeReferenceContributor.java index 62f2d4bffb5e..db1fb306b98f 100644 --- a/plugins/devkit/src/references/PluginDescriptorXIncludeReferenceContributor.java +++ b/plugins/devkit/src/references/PluginDescriptorXIncludeReferenceContributor.java @@ -1,18 +1,17 @@ // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.devkit.references; +import com.intellij.openapi.util.Condition; import com.intellij.patterns.PatternCondition; import com.intellij.patterns.XmlAttributeValuePattern; import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceContributor; -import com.intellij.psi.PsiReferenceRegistrar; +import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; import com.intellij.psi.impl.source.resolve.reference.impl.providers.XmlBaseReferenceProvider; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.devkit.util.DescriptorUtil; import org.jetbrains.idea.devkit.util.PsiUtil; /** @@ -45,8 +44,12 @@ public class PluginDescriptorXIncludeReferenceContributor extends PsiReferenceCo @NotNull @Override public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { - // No customizations for PluginDescriptorXIncludeFileReferenceHelper to be used - return FileReferenceSet.createSet(element, false, false, false).getAllReferences(); + return new FileReferenceSet(element) { + @Override + protected Condition getReferenceCompletionFilter() { + return item -> DescriptorUtil.isPluginXml(item.getContainingFile()); + } + }.getAllReferences(); } } } From f76b212efc4176934d43058e62e75106475361cd Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 17 Nov 2017 13:55:45 +0300 Subject: [PATCH 15/81] cleanup --- .../externalSystem/util/ExternalSystemUtil.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index dda28b6ebd9e..914156e7ccc4 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -275,7 +275,7 @@ public class ExternalSystemUtil { final ExternalProjectRefreshCallback callback; if (spec.getCallback() == null) { - callback = new MyMultiExternalProjectRefreshCallback(spec.getProject(), projectDataManager, spec.getExternalSystemId()); + callback = new MyMultiExternalProjectRefreshCallback(spec.getProject(), projectDataManager); } else { callback = spec.getCallback(); @@ -405,7 +405,7 @@ public class ExternalSystemUtil { @Override public void cancel() { super.cancel(); - cancellImport(); + cancelImport(); } }); } @@ -431,7 +431,7 @@ public class ExternalSystemUtil { final ExternalSystemProcessHandler processHandler = new ExternalSystemProcessHandler(myTask, projectName + " import") { @Override protected void destroyProcessImpl() { - cancellImport(); + cancelImport(); closeInput(); } }; @@ -556,7 +556,7 @@ public class ExternalSystemUtil { } } - public void cancellImport() { + private void cancelImport() { myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions()); } }; @@ -1064,14 +1064,10 @@ public class ExternalSystemUtil { private final Set myExternalModulePaths; private final Project myProject; private final ProjectDataManager myProjectDataManager; - private final ProjectSystemId myExternalSystemId; - public MyMultiExternalProjectRefreshCallback(Project project, - ProjectDataManager projectDataManager, - ProjectSystemId externalSystemId) { + public MyMultiExternalProjectRefreshCallback(Project project, ProjectDataManager projectDataManager) { myProject = project; myProjectDataManager = projectDataManager; - myExternalSystemId = externalSystemId; myExternalModulePaths = ContainerUtilRt.newHashSet(); } From f81d8542f9309895b9fcfa8adc2dd43d58499a0a Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 17 Nov 2017 13:52:00 +0300 Subject: [PATCH 16/81] IDEA-181068 diff: "Jump to Source" calculates the column incorrectly for TAB indentation OpenFileDescriptor accepts line/col pair in terms of LogicalPosition, so a single "\t" occupies multiple offsets (defined by codestyle). --- .../src/com/intellij/diff/contents/DocumentContentImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/contents/DocumentContentImpl.java b/platform/diff-impl/src/com/intellij/diff/contents/DocumentContentImpl.java index 077ea0b638b5..d36bdcd09a6f 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/DocumentContentImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/DocumentContentImpl.java @@ -139,7 +139,9 @@ public class DocumentContentImpl extends DiffContentBase implements DocumentCont public void navigate(boolean requestFocus) { Document targetDocument = FileDocumentManager.getInstance().getDocument(myTargetFile); LineCol targetPosition = translatePosition(myDocument, targetDocument, myPosition); - OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, myTargetFile, targetPosition.line, targetPosition.column); + OpenFileDescriptor descriptor = targetDocument != null + ? new OpenFileDescriptor(myProject, myTargetFile, targetPosition.toOffset(targetDocument)) + : new OpenFileDescriptor(myProject, myTargetFile, targetPosition.line, targetPosition.column); if (descriptor.canNavigate()) descriptor.navigate(true); } From e539115444cbef5a384041247315779c5d1a778c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 17 Nov 2017 14:53:00 +0300 Subject: [PATCH 17/81] IDEA-182318 VFS Exceptions after switch branches. --- .../openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 60a81512e772..01ff1c6afd02 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -573,9 +573,12 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { for (int id : myData.myChildrenIds) { existingNames.add(VfsData.getNameByFileId(id)); } - FSRecords.NameId[] persistentIds = FSRecords.listAll(getId()); - for (FSRecords.NameId nameId : persistentIds) { - existingNames.add(nameId.name); + int id = getId(); + if (id >= 0) { + FSRecords.NameId[] persistentIds = FSRecords.listAll(id); + for (FSRecords.NameId nameId : persistentIds) { + existingNames.add(nameId.name); + } } validateAgainst(childrenToCreate, existingNames); From 14888462ba5e4765e64bf936c769941fa3a9ea47 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 15:07:34 +0300 Subject: [PATCH 18/81] IDEA-42430 Debugger: UI: Watches view: clicking outside the watch editor should apply change --- .../impl/ui/tree/TreeInplaceEditor.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java index 1cf8615c519e..fb39b171553e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xdebugger.impl.ui.tree; import com.intellij.codeInsight.lookup.LookupManager; @@ -271,7 +257,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener { } if (id != MouseEvent.MOUSE_RELEASED) { // do not cancel on release outside of the component - cancelEditing(); + doOKAction(); } } From 830d56b6b08b46238448e40237fdaa3c13db6409 Mon Sep 17 00:00:00 2001 From: Nikita Skvortsov Date: Fri, 17 Nov 2017 15:08:57 +0300 Subject: [PATCH 19/81] External system: clear reference to imported project from the task --- .../internal/ExternalSystemResolveProjectTask.java | 7 +------ .../externalSystem/util/ExternalSystemUtil.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java index d6447c1e4619..6b5398f2b320 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemResolveProjectTask.java @@ -118,11 +118,6 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask return resolver.cancelTask(getId()); } - @Nullable - public DataNode getExternalProject() { - return myExternalProject.get(); - } - @Override @NotNull protected String wrapProgressText(@NotNull String text) { @@ -134,7 +129,7 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask super.setState(state); if (state.isStopped()) { InternalExternalProjectInfo projectInfo = - new InternalExternalProjectInfo(getExternalSystemId(), getExternalProjectPath(), getExternalProject()); + new InternalExternalProjectInfo(getExternalSystemId(), getExternalProjectPath(), myExternalProject.getAndSet(null)); final long currentTimeMillis = System.currentTimeMillis(); projectInfo.setLastImportTimestamp(currentTimeMillis); projectInfo.setLastSuccessfulImportTimestamp(state == ExternalSystemTaskState.FAILED ? -1 : currentTimeMillis); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index 914156e7ccc4..99bd646b0784 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -529,11 +529,15 @@ public class ExternalSystemUtil { final Throwable error = myTask.getError(); if (error == null) { if (callback != null) { - DataNode externalProject = myTask.getExternalProject(); - if (externalProject != null && importSpec.shouldCreateDirectoriesForEmptyContentRoots()) { - externalProject.putUserData(ContentRootDataService.CREATE_EMPTY_DIRECTORIES, Boolean.TRUE); + final ExternalProjectInfo externalProjectData = ProjectDataManagerImpl.getInstance() + .getExternalProjectData(project, externalSystemId, externalProjectPath); + if (externalProjectData != null) { + DataNode externalProject = externalProjectData.getExternalProjectStructure(); + if (externalProject != null && importSpec.shouldCreateDirectoriesForEmptyContentRoots()) { + externalProject.putUserData(ContentRootDataService.CREATE_EMPTY_DIRECTORIES, Boolean.TRUE); + } + callback.onSuccess(externalProject); } - callback.onSuccess(externalProject); } if (!isPreviewMode) { externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.AFTER_SYNC); From 5ecc366f5cd336a330cbd862b55021273bd56b53 Mon Sep 17 00:00:00 2001 From: Ivan Semenov Date: Fri, 17 Nov 2017 15:09:46 +0300 Subject: [PATCH 20/81] Fix GitSubmoduleTest on windows --- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index bc6c52e96c34..4d17acbdf2cd 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -18,6 +18,7 @@ package git4idea.update import com.intellij.dvcs.DvcsUtil.getPushSupport import com.intellij.dvcs.DvcsUtil.getShortRepositoryName import com.intellij.openapi.progress.EmptyProgressIndicator +import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil.getRelativePath import com.intellij.openapi.vcs.Executor.cd import com.intellij.openapi.vcs.update.UpdatedFiles @@ -144,7 +145,7 @@ class GitSubmoduleTest : GitPlatformTest() { private fun addSubmodule(superProject: File, submoduleUrl: File, relativePath: String? = null) { cd(superProject) - git("submodule add ${submoduleUrl.path} ${relativePath ?: ""}") + git("submodule add ${FileUtil.toSystemIndependentName(submoduleUrl.path)} ${relativePath ?: ""}") git("commit -m 'Added submodule lib'") git("push origin master") } @@ -199,7 +200,7 @@ class GitSubmoduleTest : GitPlatformTest() { private fun assertSubmodulesInfo(repo: GitRepository, expectedSubmodules: List) { val expectedInfos = expectedSubmodules.map { val url = it.remotes.first().firstUrl!! - GitSubmoduleInfo(getRelativePath(virtualToIoFile(repo.root), virtualToIoFile(it.root))!!, url) + GitSubmoduleInfo(FileUtil.toSystemIndependentName(getRelativePath(virtualToIoFile(repo.root), virtualToIoFile(it.root))!!), url) } assertSameElements("Submodules were read incorrectly for ${getShortRepositoryName(repo)}", repo.submodules, expectedInfos) } From 36ff79c50a22cb2600326323f19799e68bcf47f7 Mon Sep 17 00:00:00 2001 From: anstarovoyt Date: Fri, 17 Nov 2017 15:14:45 +0300 Subject: [PATCH 21/81] platform: fix quick navigate popup actions on MacOS IDEA-182334 action "ShowQuickDocAtPinnedWindowFromTooltip" doesn't work on mac --- .../codeInsight/navigation/CtrlMouseHandler.java | 9 ++++++++- .../intellij/openapi/actionSystem/impl/ActionButton.java | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 6933bfef1306..f867c5ea679d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -1045,7 +1045,14 @@ public class CtrlMouseHandler extends AbstractProjectComponent { for (AbstractDocumentationTooltipAction action : ourTooltipActions) { Icon icon = action.getTemplatePresentation().getIcon(); Dimension minSize = new Dimension(icon.getIconWidth(), icon.getIconHeight()); - myButtons.add(new ActionButton(action, presentationFactory.getPresentation(action), IdeTooltipManager.IDE_TOOLTIP_PLACE, minSize)); + ActionButton actionButton = + new ActionButton(action, presentationFactory.getPresentation(action), IdeTooltipManager.IDE_TOOLTIP_PLACE, minSize) { + @Override + protected boolean checkSkipPressForEvent(@NotNull MouseEvent e) { + return e.getButton() != MouseEvent.BUTTON1; + } + }; + myButtons.add(actionButton); action.setDocInfo(documentationAnchor, elementUnderMouse); } Collections.reverse(myButtons); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java index dc05cf0e68d3..8424eac3cfaf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionButton.java @@ -30,8 +30,8 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ui.*; -import com.intellij.util.ui.accessibility.ScreenReader; import com.intellij.util.ui.accessibility.AccessibleContextUtil; +import com.intellij.util.ui.accessibility.ScreenReader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -337,7 +337,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A protected void processMouseEvent(MouseEvent e) { super.processMouseEvent(e); if (e.isConsumed()) return; - boolean skipPress = e.isMetaDown() || e.getButton() != MouseEvent.BUTTON1; + boolean skipPress = checkSkipPressForEvent(e); switch (e.getID()) { case MouseEvent.MOUSE_PRESSED: if (skipPress || !isButtonEnabled()) return; @@ -372,6 +372,10 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A } } + protected boolean checkSkipPressForEvent(@NotNull MouseEvent e) { + return e.isMetaDown() || e.getButton() != MouseEvent.BUTTON1; + } + private int getPopState(boolean isPushed) { if (isPushed || myRollover && myMouseDown && isButtonEnabled()) { return PUSHED; From 1efde7806c6cb2cf506bc78e76077122ac0a890f Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 17 Nov 2017 15:16:30 +0300 Subject: [PATCH 22/81] run configurations: restore API compatibility --- .../impl/RunConfigurationBeforeRunProvider.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java index 8d8323823af7..53a08c1ed692 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java @@ -162,7 +162,15 @@ extends BeforeRunTaskProvider Date: Thu, 16 Nov 2017 14:44:44 +0300 Subject: [PATCH 23/81] PY-26967 Don't show some actions if snap is used (IDEA-CR-26953) Actions are 'Create Desktop Entry' and 'Create Command-line Launcher' idea-snap.properties is removed --- .../build/impl/LinuxDistributionBuilder.groovy | 4 ---- .../resources/linux/snap/idea-snap.properties | 6 ------ .../ide/actions/CreateDesktopEntryAction.java | 2 +- .../ide/actions/CreateLauncherScriptAction.java | 2 +- .../ide/customize/CustomizeDesktopEntryStep.java | 1 + .../openapi/updateSettings/impl/UpdateSettings.java | 3 ++- .../src/com/intellij/openapi/util/SystemInfo.java | 12 ++++++++++++ 7 files changed, 17 insertions(+), 13 deletions(-) delete mode 100644 platform/build-scripts/resources/linux/snap/idea-snap.properties diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.groovy index c575419504f4..5dbadc32fe8c 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.groovy @@ -222,10 +222,6 @@ class LinuxDistributionBuilder extends OsSpecificDistributionBuilder { } } - buildContext.ant.concat(destfile: "${unixDistPath}/bin/idea.properties", append: true) { - filelist(dir: "${buildContext.paths.communityHome}/platform/build-scripts/resources/linux/snap", files: "idea-snap.properties") - } - buildContext.ant.delete(quiet: true) { fileset(dir: "${unixDistPath}/bin") { include(name: "fsnotifier") diff --git a/platform/build-scripts/resources/linux/snap/idea-snap.properties b/platform/build-scripts/resources/linux/snap/idea-snap.properties deleted file mode 100644 index 2afae5831d38..000000000000 --- a/platform/build-scripts/resources/linux/snap/idea-snap.properties +++ /dev/null @@ -1,6 +0,0 @@ - -#----------------------------------------------------------------------- -# Snap-specific properties -#----------------------------------------------------------------------- -idea.skip.desktop.entry.step=true -ide.no.platform.update=Snap diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java index 36eef3cbf1e1..320d6d44734b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java @@ -76,7 +76,7 @@ public class CreateDesktopEntryAction extends DumbAwareAction { }; public static boolean isAvailable() { - return SystemInfo.isUnix && SystemInfo.hasXdgOpen(); + return SystemInfo.isUnix && !SystemInfo.isSnap() && SystemInfo.hasXdgOpen(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index f82b02a3b5d1..fe6f09eca668 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -51,7 +51,7 @@ public class CreateLauncherScriptAction extends DumbAwareAction { private static final String CONTENTS = "/Contents"; public static boolean isAvailable() { - return SystemInfo.isUnix; + return SystemInfo.isUnix && !SystemInfo.isSnap(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java index 7e61b5893ae4..e721a9ab3199 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java @@ -20,6 +20,7 @@ import com.intellij.idea.ActionsBundle; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ExceptionUtil; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; 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 29e34ff3a776..e90e15905f02 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,6 +18,7 @@ package com.intellij.openapi.updateSettings.impl; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.components.*; import com.intellij.openapi.updateSettings.UpdateStrategyCustomization; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; @@ -65,7 +66,7 @@ public class UpdateSettings implements PersistentStateComponent ourIsSnap = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return PathManager.getHomePath().startsWith("/snap/"); + } + }; + public static boolean isSnap() { + return isLinux && ourIsSnap.getValue(); + } + public static final boolean isMacSystemMenu = isMac && "true".equals(System.getProperty("apple.laf.useScreenMenuBar")); public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; From 6029d2de347304d359ac58c5620310640af1fcce Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Fri, 17 Nov 2017 15:17:12 +0300 Subject: [PATCH 24/81] IDEA-182280 Invoke queueUpdate() for node's element --- .../src/com/intellij/ide/util/treeView/AbstractTreeUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 85e6cbc2f50d..bf57059bc5ce 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -1790,7 +1790,7 @@ public class AbstractTreeUi { @Override public void perform() { if (!pass.isExpired()) { - queueUpdate(node); + queueUpdate(getElementFor(node)); } } }); From a76dab0ccb7be252dec84e32d7bbb4e51992dd0c Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 10 Oct 2017 17:30:39 +0300 Subject: [PATCH 25/81] Ability to enable/disable semantic highlighting independently (PY-26445) --- .../python/highlighting/PyRainbowVisitor.kt | 25 +++----- .../python/highlighting/PythonColorsPage.java | 61 +++++++++++-------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/python/src/com/jetbrains/python/highlighting/PyRainbowVisitor.kt b/python/src/com/jetbrains/python/highlighting/PyRainbowVisitor.kt index a65651449e27..c5d56e419d10 100644 --- a/python/src/com/jetbrains/python/highlighting/PyRainbowVisitor.kt +++ b/python/src/com/jetbrains/python/highlighting/PyRainbowVisitor.kt @@ -1,21 +1,8 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.highlighting import com.intellij.codeInsight.daemon.RainbowVisitor +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -30,6 +17,10 @@ class PyRainbowVisitor : RainbowVisitor() { companion object { private val IGNORED_NAMES = setOf(PyNames.NONE, PyNames.TRUE, PyNames.FALSE) + private val DEFAULT_HIGHLIGHTING_KEY = DefaultLanguageHighlighterColors.LOCAL_VARIABLE + + @JvmStatic + val HIGHLIGHTING_KEYS = setOf(PyHighlighter.PY_PARAMETER, DEFAULT_HIGHLIGHTING_KEY) } override fun suitableForFile(file: PsiFile) = file is PyFile @@ -132,8 +123,8 @@ class PyRainbowVisitor : RainbowVisitor() { } } - private fun addInfo(context: PsiElement, rainbowElement: PsiElement, name: String, colorKey: TextAttributesKey? = null) { - addInfo(getInfo(context, rainbowElement, name, colorKey)) + private fun addInfo(context: PsiElement, rainbowElement: PsiElement, name: String, key: TextAttributesKey? = DEFAULT_HIGHLIGHTING_KEY) { + addInfo(getInfo(context, rainbowElement, name, key)) } private fun getLeastCommonScope(elements: Collection): ScopeOwner? { diff --git a/python/src/com/jetbrains/python/highlighting/PythonColorsPage.java b/python/src/com/jetbrains/python/highlighting/PythonColorsPage.java index 2c40f3ac96db..4aa6da82e7e3 100644 --- a/python/src/com/jetbrains/python/highlighting/PythonColorsPage.java +++ b/python/src/com/jetbrains/python/highlighting/PythonColorsPage.java @@ -1,34 +1,25 @@ -/* - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.highlighting; import com.google.common.collect.ImmutableMap; import com.intellij.application.options.colors.InspectionColorSettingsPage; +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.lang.Language; +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; import com.intellij.openapi.options.colors.AttributesDescriptor; import com.intellij.openapi.options.colors.ColorDescriptor; -import com.intellij.openapi.options.colors.ColorSettingsPage; +import com.intellij.openapi.options.colors.RainbowColorSettingsPage; import com.intellij.psi.codeStyle.DisplayPriority; import com.intellij.psi.codeStyle.DisplayPrioritySortable; import com.intellij.util.PlatformUtils; import com.jetbrains.python.PythonFileType; +import com.jetbrains.python.PythonLanguage; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Map; @@ -36,7 +27,7 @@ import java.util.Map; /** * @author yole */ -public class PythonColorsPage implements ColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable { +public class PythonColorsPage implements RainbowColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable { private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] { new AttributesDescriptor("Keyword", PyHighlighter.PY_KEYWORD), new AttributesDescriptor("String (bytes)", PyHighlighter.PY_BYTE_STRING), @@ -82,27 +73,34 @@ public class PythonColorsPage implements ColorSettingsPage, InspectionColorSetti .put("call", PyHighlighter.PY_FUNCTION_CALL) .put("mcall", PyHighlighter.PY_METHOD_CALL) .put("annotation", PyHighlighter.PY_ANNOTATION) + .put("localVar", DefaultLanguageHighlighterColors.LOCAL_VARIABLE) + .putAll(RainbowHighlighter.createRainbowHLM()) .build(); + @Override @NotNull public String getDisplayName() { return "Python"; } + @Override public Icon getIcon() { return PythonFileType.INSTANCE.getIcon(); } + @Override @NotNull public AttributesDescriptor[] getAttributeDescriptors() { return ATTRS; } + @Override @NotNull public ColorDescriptor[] getColorDescriptors() { return ColorDescriptor.EMPTY_ARRAY; } + @Override @NotNull public SyntaxHighlighter getHighlighter() { final SyntaxHighlighter highlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(PythonFileType.INSTANCE, null, null); @@ -110,31 +108,35 @@ public class PythonColorsPage implements ColorSettingsPage, InspectionColorSetti return highlighter; } + @Override @NotNull public String getDemoText() { return - "@decorator(param=1)\n" + + "@decorator(param=1)\n" + "def f(x):\n" + " \"\"\" Syntax Highlighting Demo\n" + - " @param x Parameter\"\"\"\n" + - " s = (\"Test\", 2+3, {'a': 'b'}, x) # Comment\n" + - " f(s[0].lower())\n"+ + " @param x Parameter\n" + + RainbowHighlighter.generatePaletteExample("\n ") + "\n" + + " \"\"\"\n" + + " s = (\"Test\", 2+3, {'a': 'b'}, x) # Comment\n" + + " f(s[0].lower())\n"+ "\n"+ "class Foo:\n"+ " tags: List[str]\n" + " def __init__(self: Foo):\n" + - " byte_string: str = 'newline:\\n also newline:\\x0a'\n" + - " text_string = u\"Cyrillic \u042f is \\u042f. Oops: \\u042g\"\n"+ + " byte_string: str = 'newline:\\n also newline:\\x0a'\n" + + " text_string = u\"Cyrillic \u042f is \\u042f. Oops: \\u042g\"\n"+ " self.makeSense(whatever=1)\n" + " \n" + " def makeSense(self, whatever):\n"+ " self.sense = whatever\n"+ "\n"+ - "x = len('abc')\n"+ + "x = len('abc')\n"+ "print(f.__doc__)" ; } + @Override public Map getAdditionalHighlightingTagToDescriptorMap() { return ourTagToDescriptorMap; } @@ -143,4 +145,15 @@ public class PythonColorsPage implements ColorSettingsPage, InspectionColorSetti public DisplayPriority getPriority() { return PlatformUtils.isPyCharm() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS; } + + @Override + public boolean isRainbowType(TextAttributesKey type) { + return PyRainbowVisitor.getHIGHLIGHTING_KEYS().contains(type); + } + + @Nullable + @Override + public Language getLanguage() { + return PythonLanguage.INSTANCE; + } } From 288239a2e04b4fddff970681f5e8e5dc576f224a Mon Sep 17 00:00:00 2001 From: Alexander Doroshko Date: Fri, 17 Nov 2017 15:26:06 +0300 Subject: [PATCH 26/81] DEXP-196880 IllegalArgumentException: Argument for @NotNull parameter 'project' of com/jetbrains/plugins/remotesdk/console/RemoteCredentialsDialogRunner.run must not be null --- .../lang-impl/src/com/intellij/tools/ToolEditorDialog.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java b/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java index 3cae95375efc..d7ebd8f3115a 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolEditorDialog.java @@ -80,6 +80,11 @@ public class ToolEditorDialog extends DialogWrapper { private JBCheckBox myShowConsoleOnStdErrCheckbox; private RawCommandLineEditor myOutputFilterField; + @Nullable + public Project getProject() { + return myProject; + } + @Override @NotNull protected JPanel createCenterPanel() { From 221cc05632eb6774207352df4611aecf626fd21d Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 16 Nov 2017 15:11:29 +0100 Subject: [PATCH 27/81] =?UTF-8?q?PathMacroFilter=20=E2=80=94=20add=20NotNu?= =?UTF-8?q?ll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JavaRunConfigurationPathMacroFilter.java | 19 +++------------- .../openapi/application/PathMacroFilter.java | 18 ++------------- .../RunConfigurationPathMacroFilter.java | 18 ++------------- .../application/PathMappingsMacroFilter.java | 19 +++------------- .../StructuralSearchPathMacroFilter.java | 19 +++------------- .../intellij/run/PathMacrosCollectorTest.java | 19 +++------------- .../components/CompositePathMacroFilter.java | 22 +++++-------------- .../openapi/vcs/VcsPathMacroFilter.java | 19 +++------------- 8 files changed, 24 insertions(+), 129 deletions(-) diff --git a/java/java-impl/src/com/intellij/execution/configuration/JavaRunConfigurationPathMacroFilter.java b/java/java-impl/src/com/intellij/execution/configuration/JavaRunConfigurationPathMacroFilter.java index ffaf6f5376b5..f6208dbccd2d 100644 --- a/java/java-impl/src/com/intellij/execution/configuration/JavaRunConfigurationPathMacroFilter.java +++ b/java/java-impl/src/com/intellij/execution/configuration/JavaRunConfigurationPathMacroFilter.java @@ -1,30 +1,17 @@ -/* - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution.configuration; import com.intellij.openapi.application.PathMacroFilter; import org.jdom.Attribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** * @author peter */ public class JavaRunConfigurationPathMacroFilter extends PathMacroFilter { @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { final Element parent = attribute.getParent(); if (parent.getName().equals("option")) { diff --git a/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java b/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java index f6beb95d4239..7d463bee9dc6 100644 --- a/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java +++ b/jps/model-serialization/src/com/intellij/openapi/application/PathMacroFilter.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.application; import org.jdom.Attribute; @@ -34,7 +20,7 @@ public abstract class PathMacroFilter { return false; } - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { return false; } diff --git a/platform/lang-impl/src/com/intellij/execution/configuration/RunConfigurationPathMacroFilter.java b/platform/lang-impl/src/com/intellij/execution/configuration/RunConfigurationPathMacroFilter.java index 19399e0156c3..1a640094b3cb 100644 --- a/platform/lang-impl/src/com/intellij/execution/configuration/RunConfigurationPathMacroFilter.java +++ b/platform/lang-impl/src/com/intellij/execution/configuration/RunConfigurationPathMacroFilter.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution.configuration; import com.intellij.openapi.application.PathMacroFilter; @@ -26,7 +12,7 @@ import org.jetbrains.annotations.NotNull; class RunConfigurationPathMacroFilter extends PathMacroFilter { @Override public boolean skipPathMacros(@NotNull Attribute attribute) { - return attribute.getParent().getName().equals("configuration") && attribute.getName().equals("name"); + return attribute.getName().equals("name") && attribute.getParent().getName().equals("configuration"); } @Override diff --git a/platform/lang-impl/src/com/intellij/openapi/application/PathMappingsMacroFilter.java b/platform/lang-impl/src/com/intellij/openapi/application/PathMappingsMacroFilter.java index 6cebf1782001..ad4f555c4f22 100644 --- a/platform/lang-impl/src/com/intellij/openapi/application/PathMappingsMacroFilter.java +++ b/platform/lang-impl/src/com/intellij/openapi/application/PathMappingsMacroFilter.java @@ -1,22 +1,9 @@ -/* - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.application; import org.jdom.Attribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** * Filter remote path in {@link com.intellij.util.PathMappingSettings.PathMapping} @@ -25,7 +12,7 @@ import org.jdom.Element; */ public class PathMappingsMacroFilter extends PathMacroFilter { @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { final Element parent = attribute.getParent(); if ("mapping".equals(parent.getName()) && "remote-root".equals(attribute.getName())) { return true; diff --git a/platform/lang-impl/src/com/intellij/openapi/application/StructuralSearchPathMacroFilter.java b/platform/lang-impl/src/com/intellij/openapi/application/StructuralSearchPathMacroFilter.java index b42ba1701b31..23d6b0fe53f7 100644 --- a/platform/lang-impl/src/com/intellij/openapi/application/StructuralSearchPathMacroFilter.java +++ b/platform/lang-impl/src/com/intellij/openapi/application/StructuralSearchPathMacroFilter.java @@ -1,21 +1,8 @@ -/* - * Copyright 2000-2012 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.application; import org.jdom.Attribute; +import org.jetbrains.annotations.NotNull; /** * Since SSR inspections can be stored in inspection profiles and loaded by users who don't have the SSR plugin installed, unfortunately @@ -25,7 +12,7 @@ import org.jdom.Attribute; */ public class StructuralSearchPathMacroFilter extends PathMacroFilter { @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { final String parentName = attribute.getParent().getName(); if ("replaceConfiguration".equals(parentName) || "searchConfiguration".equals(parentName)) { return true; diff --git a/platform/platform-tests/testSrc/com/intellij/run/PathMacrosCollectorTest.java b/platform/platform-tests/testSrc/com/intellij/run/PathMacrosCollectorTest.java index 92a689e7a731..9bebe47437ba 100644 --- a/platform/platform-tests/testSrc/com/intellij/run/PathMacrosCollectorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/run/PathMacrosCollectorTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2012 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.run; import com.intellij.application.options.PathMacrosCollector; @@ -23,6 +9,7 @@ import junit.framework.TestCase; import org.jdom.Attribute; import org.jdom.Element; import org.jdom.Text; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -78,7 +65,7 @@ public class PathMacrosCollectorTest extends TestCase { final Set filtered = PathMacrosCollector.getMacroNames(root, new PathMacroFilter() { @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { return "ignore".equals(attribute.getName()); } }, new PathMacrosImpl()); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/CompositePathMacroFilter.java b/platform/projectModel-impl/src/com/intellij/openapi/components/CompositePathMacroFilter.java index 93bd2a16f317..32a68da8ee2f 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/CompositePathMacroFilter.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/CompositePathMacroFilter.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components; import com.intellij.openapi.application.PathMacroFilter; @@ -50,9 +36,11 @@ public class CompositePathMacroFilter extends PathMacroFilter { } @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { for (PathMacroFilter filter : myFilters) { - if (filter.skipPathMacros(attribute)) return true; + if (filter.skipPathMacros(attribute)) { + return true; + } } return false; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/VcsPathMacroFilter.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/VcsPathMacroFilter.java index 04f52d7d6ee8..cfe26ff4f52e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/VcsPathMacroFilter.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/VcsPathMacroFilter.java @@ -1,30 +1,17 @@ -/* - * Copyright 2000-2012 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.vcs; import com.intellij.openapi.application.PathMacroFilter; import org.jdom.Attribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** * @author yole */ public class VcsPathMacroFilter extends PathMacroFilter { @Override - public boolean skipPathMacros(Attribute attribute) { + public boolean skipPathMacros(@NotNull Attribute attribute) { final Element parent = attribute.getParent(); final String parentName = parent.getName(); if ("MESSAGE".equals(parentName) && "value".equals(attribute.getName())) { From 2673736cb6eab04aa8f0260f77e75d3e26717d1c Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 17 Nov 2017 13:14:42 +0100 Subject: [PATCH 28/81] simplify code (kotlin) --- .../configuration-store-impl/src/StateMap.kt | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/platform/configuration-store-impl/src/StateMap.kt b/platform/configuration-store-impl/src/StateMap.kt index 170c9045fb03..43d06f92c48f 100644 --- a/platform/configuration-store-impl/src/StateMap.kt +++ b/platform/configuration-store-impl/src/StateMap.kt @@ -130,16 +130,7 @@ class StateMap private constructor(private val names: Array, private val fun hasState(key: String) = get(key) is Element fun hasStates(): Boolean { - if (isEmpty()) { - return false - } - - for (i in names.indices) { - if (states.get(i) is Element) { - return true - } - } - return false + return !isEmpty() && names.indices.any { states.get(it) is Element } } fun compare(key: String, newStates: StateMap, diffs: MutableSet) { @@ -241,16 +232,5 @@ private fun arrayEquals(a: ByteArray, a2: ByteArray, size: Int = a.size): Boolea if (a === a2) { return true } - - if (a2.size != size) { - return false - } - - for (i in 0 until size) { - if (a[i] != a2[i]) { - return false - } - } - - return true + return a2.size == size && (0 until size).none { a[it] != a2[it] } } \ No newline at end of file From e71d3798cba9c51925fb084dbf5f1f00db55dfcb Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 17 Nov 2017 13:23:31 +0100 Subject: [PATCH 29/81] external storage: do not store bytecode taget level in the project files --- .../compiler/CompilerConfigurationImpl.java | 49 ++++------- .../ExternalCompilerConfigurationStorage.kt | 85 +++++++++++++++++++ .../model/serialization/JpsLoaderBase.java | 23 ++--- .../model/serialization/JpsProjectLoader.java | 6 ++ .../src/ModuleStoreImpl.kt | 2 +- .../src/ProjectStoreImpl.kt | 2 +- .../src/StateStorageManagerImpl.kt | 9 +- .../ExternalSystemStorage.kt | 7 +- .../ExternalSystemStreamProviderFactory.kt | 17 ++-- .../intellij/openapi/components/State.java | 21 ++--- .../StreamProviderFactory.kt | 23 +---- .../module/impl/ExternalModuleListStorage.kt | 2 +- resources/src/componentSets/Compiler.xml | 4 + 13 files changed, 152 insertions(+), 98 deletions(-) create mode 100644 java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index 592b07186e2c..1a958c85ad78 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.impl.ExternalModuleListStorage; import com.intellij.openapi.project.ModuleListener; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; @@ -60,6 +61,8 @@ import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfig import java.io.File; import java.util.*; +import static com.intellij.compiler.ExternalCompilerConfigurationStorageKt.*; +import static com.intellij.util.JdomKt.element; import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.normalizeWildcards; import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.optimize; import static org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer.DEFAULT_WILDCARD_PATTERNS; @@ -153,7 +156,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements @Override public Element getState() { - Element state = new Element("state"); XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() { @Override @@ -207,30 +209,17 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements state.addContent(annotationProcessingSettings); } - if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) { - final Element bytecodeTarget = addChild(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL); + List moduleNames = getFilteredModuleNameList(myProject, myModuleBytecodeTarget, false); + if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !moduleNames.isEmpty()) { + final Element bytecodeTarget = element(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL); if (!StringUtil.isEmpty(myBytecodeTargetLevel)) { bytecodeTarget.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, myBytecodeTargetLevel); } - if (!myModuleBytecodeTarget.isEmpty()) { - final List moduleNames = new ArrayList<>(myModuleBytecodeTarget.keySet()); - Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER); - for (String name : moduleNames) { - final Element moduleElement = addChild(bytecodeTarget, JpsJavaCompilerConfigurationSerializer.MODULE); - moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name); - final String value = myModuleBytecodeTarget.get(name); - moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, value != null ? value : ""); - } - } + writeBytecodeTarget(moduleNames, myModuleBytecodeTarget, bytecodeTarget); } return state; } - @Override - public void loadState(Element state) { - readExternal(state); - } - @Override public int getBuildProcessHeapSize(final int javacPreferredHeapSize) { final int heapSize = myState.BUILD_PROCESS_HEAP_SIZE; @@ -702,8 +691,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements return true; } - - public void readExternal(@NotNull Element parentNode) { + @Override + public void loadState(@NotNull Element parentNode) { myState = XmlSerializer.deserialize(parentNode, State.class); if (!myProject.isDefault()) { for (Element option : parentNode.getChildren("option")) { @@ -785,20 +774,16 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements myBytecodeTargetLevel = null; myModuleBytecodeTarget.clear(); - final Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL); + + Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL); if (bytecodeTargetElement != null) { myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE); - for (Element elem : bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) { - final String name = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME); - if (name == null) { - continue; - } - final String target = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE); - if (target == null) { - continue; - } - myModuleBytecodeTarget.put(name, target); - } + readByteTargetLevel(parentNode); + } + + Map externalState = myProject.getComponent(ExternalCompilerConfigurationStorage.class).getLoadedState(); + if (externalState != null) { + myModuleBytecodeTarget.putAll(externalState); } } diff --git a/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt b/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt new file mode 100644 index 000000000000..14f7feab2f0c --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt @@ -0,0 +1,85 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.compiler + +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.module.impl.ModuleManagerImpl +import com.intellij.openapi.project.Project +import com.intellij.openapi.project.isExternalStorageEnabled +import com.intellij.openapi.roots.ExternalProjectSystemRegistry +import com.intellij.openapi.roots.ProjectModelElement +import com.intellij.openapi.roots.ProjectModelExternalSource +import com.intellij.util.element +import gnu.trove.THashMap +import org.jdom.Element +import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer +import java.util.* + +@State(name = "ExternalCompilerConfigurationStorage", storages = arrayOf(Storage("compiler.xml")), externalStorageOnly = true) +internal class ExternalCompilerConfigurationStorage(private val project: Project) : PersistentStateComponent, ProjectModelElement { + var loadedState: Map? = null + private set + + override fun getState(): Element { + val e = Element("state") + if (!project.isExternalStorageEnabled) { + return e + } + + val map = (CompilerConfigurationImpl.getInstance(project) as CompilerConfigurationImpl).modulesBytecodeTargetMap + val moduleNames = getFilteredModuleNameList(project, map, true) + if (moduleNames.isNotEmpty()) { + writeBytecodeTarget(moduleNames, map, e.element(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL)) + } + return e + } + + override fun loadState(state: Element) { + loadedState = readByteTargetLevel(state) + } + + override fun getExternalSource(): ProjectModelExternalSource? { + val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance() + for (module in ModuleManagerImpl.getInstanceImpl(project).modules) { + externalProjectSystemRegistry.getExternalSource(module)?.let { + return it + } + } + return null + } +} + +internal fun getFilteredModuleNameList(project: Project, map: Map, isExternal: Boolean): List { + if (!project.isExternalStorageEnabled) { + return map.keys.toList() + } + + val moduleManager = ModuleManagerImpl.getInstanceImpl(project) + val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance() + return map.keys.filter { + // if no module and !isExternal - return true because CompilerConfigurationImpl saves module name as is without module existence check and this logic is preserved + val module = moduleManager.findModuleByName(it) ?: return@filter !isExternal + (externalProjectSystemRegistry.getExternalSource(module) != null) == isExternal + } +} + +internal fun writeBytecodeTarget(moduleNames: List, map: Map, element: Element) { + Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER) + for (name in moduleNames) { + val moduleElement = element.element(JpsJavaCompilerConfigurationSerializer.MODULE) + moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name) + moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, map.get(name) ?: "") + } +} + +internal fun readByteTargetLevel(parentNode: Element): Map { + val result = THashMap() + val bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL) ?: return result + for (element in bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) { + val name = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME) ?: continue + val target = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE) ?: continue + result.put(name, target) + } + return result +} \ No newline at end of file diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java index 2211f06e6872..ebe2263a932c 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.jps.model.serialization; import com.intellij.openapi.diagnostic.Logger; @@ -57,7 +43,7 @@ public abstract class JpsLoaderBase { String fileName = serializer.getConfigFileName(); Path configFile = fileName == null ? defaultConfigFile : dir.resolve(fileName); Runnable timingLog = TimingLog.startActivity("loading: " + configFile.getFileName() + ":" + serializer.getComponentName()); - Element componentTag = JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName()); + Element componentTag = loadComponentData(serializer, configFile); if (componentTag != null) { serializer.loadExtension(element, componentTag); } @@ -67,6 +53,11 @@ public abstract class JpsLoaderBase { timingLog.run(); } + @Nullable + private Element loadComponentData(@NotNull JpsElementExtensionSerializerBase serializer, Path configFile) { + return JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName()); + } + /** * Returns null if file doesn't exist */ diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java index c975881354e5..73ae4db6bab1 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsProjectLoader.java @@ -110,6 +110,12 @@ public class JpsProjectLoader extends JpsLoaderBase { return dir.getParent().getFileName().toString(); } + @Nullable + @Override + protected Element loadRootElement(@NotNull Path file) { + return super.loadRootElement(file); + } + private void loadFromDirectory(@NotNull Path dir) { myProject.setName(getDirectoryBaseProjectName(dir)); Path defaultConfigFile = dir.resolve("misc.xml"); diff --git a/platform/configuration-store-impl/src/ModuleStoreImpl.kt b/platform/configuration-store-impl/src/ModuleStoreImpl.kt index 37ef72ee11d6..3ddcd88e3ef3 100644 --- a/platform/configuration-store-impl/src/ModuleStoreImpl.kt +++ b/platform/configuration-store-impl/src/ModuleStoreImpl.kt @@ -36,7 +36,7 @@ private open class ModuleStoreImpl(module: Module, private val pathMacroManager: override fun getStorageSpecs(component: PersistentStateComponent, stateSpec: State, operation: StateStorageOperation): List { val result = super.getStorageSpecs(component, stateSpec, operation) return StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny { - LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, result, operation) } + LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, stateSpec, result, operation) } } ?: result } } diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 8cbb8b9eb5f6..0aafad519394 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -201,7 +201,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo else { result!!.sortWith(deprecatedComparator) StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny { - LOG.runAndLogException { it.customizeStorageSpecs(component, project, result!!, operation) } + LOG.runAndLogException { it.customizeStorageSpecs(component, project, stateSpec, result!!, operation) } }?.let { // yes, DEPRECATED_PROJECT_FILE_STORAGE_ANNOTATION is not added in this case return it diff --git a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt index 98a1a70e7bab..3cc27b26aab7 100644 --- a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt +++ b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt @@ -174,7 +174,14 @@ open class StateStorageManagerImpl(private val rootTagName: String, key = normalizedCollapsedPath } else { - key = storageClass.name!! + val storageClassName = storageClass.name!! + // we cannot change this ancient logic for now, so, detect this case manually + if (storageClassName === "com.intellij.openapi.externalSystem.configurationStore.ExternalProjectStorage") { + key = "$normalizedCollapsedPath@ExternalProjectStorage" + } + else { + key = storageClassName + } } val storage = storageLock.read { storages.get(key) } ?: return storageLock.write { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt index 890e4102a600..24e40a1a3f52 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt @@ -33,12 +33,7 @@ internal open class ExternalProjectStorage(fileSpec: String, project: Project, s override fun createSaveSession(states: StateMap) = object : XmlElementStorageSaveSession(states, this) { override fun saveLocally(element: Element?) { - if (element == null) { - manager.fileStorage.remove(fileSpec) - } - else { - manager.fileStorage.write(fileSpec, element) - } + manager.fileStorage.write(fileSpec, element) } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStreamProviderFactory.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStreamProviderFactory.kt index c9f391121733..a455b5a6debe 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStreamProviderFactory.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStreamProviderFactory.kt @@ -63,7 +63,7 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project) }) } - override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, storages: List, operation: StateStorageOperation): List? { + override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, stateSpec: State, storages: List, operation: StateStorageOperation): List? { val project = componentManager as? Project ?: (componentManager as Module).project // we store isExternalStorageEnabled option in the project workspace file, so, for such components external storage is always disabled and not applicable if ((storages.size == 1 && storages.first().value == StoragePathMacros.WORKSPACE_FILE) || !project.isExternalStorageEnabled) { @@ -94,14 +94,21 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project) // so, we just add our storage as first and default storages in the end as fallback // on write default storages also returned, because default FileBasedStorage will remove data if component has external source - - val result = ArrayList(storages.size + 1) + val annotation: FileStorageAnnotation if (componentManager is Project) { - result.add(FileStorageAnnotation(storages.get(0).value, false, ExternalProjectStorage::class.java)) + val fileSpec = storages.get(0).value + annotation = FileStorageAnnotation(fileSpec, false, ExternalProjectStorage::class.java) } else { - result.add(EXTERNAL_MODULE_STORAGE_ANNOTATION) + annotation = EXTERNAL_MODULE_STORAGE_ANNOTATION } + + if (stateSpec.externalStorageOnly) { + return listOf(annotation) + } + + val result = ArrayList(storages.size + 1) + result.add(annotation) result.addAll(storages) return result } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/State.java b/platform/projectModel-api/src/com/intellij/openapi/components/State.java index 1e59be363c5f..456a17d2edd2 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/State.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/State.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components; import com.intellij.openapi.util.Getter; @@ -60,6 +46,11 @@ public @interface State { Class presentableName() default NameGetter.class; + /** + * Is this component intended to store data only in the external storage. + */ + boolean externalStorageOnly() default false; + abstract class NameGetter implements Getter { } } diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/StreamProviderFactory.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/StreamProviderFactory.kt index 86675c12dbdd..226bf230936b 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/StreamProviderFactory.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/StreamProviderFactory.kt @@ -1,24 +1,7 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.configurationStore -import com.intellij.openapi.components.ComponentManager -import com.intellij.openapi.components.PersistentStateComponent -import com.intellij.openapi.components.StateStorageOperation -import com.intellij.openapi.components.Storage +import com.intellij.openapi.components.* import com.intellij.openapi.extensions.ExtensionPointName /** @@ -38,5 +21,5 @@ interface StreamProviderFactory { * `storages` are preprocessed by component store - not raw from state spec. * @return null if not applicable */ - fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, storages: List, operation: StateStorageOperation): List? = null + fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, stateSpec: State, storages: List, operation: StateStorageOperation): List? = null } \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ExternalModuleListStorage.kt b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ExternalModuleListStorage.kt index 2509f15e7528..285fcc567962 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ExternalModuleListStorage.kt +++ b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ExternalModuleListStorage.kt @@ -12,7 +12,7 @@ import com.intellij.openapi.roots.ProjectModelElement import com.intellij.openapi.roots.ProjectModelExternalSource import org.jdom.Element -@State(name = "ExternalModuleListStorage", storages = arrayOf(Storage("modules.xml"))) +@State(name = "ExternalModuleListStorage", storages = arrayOf(Storage("modules.xml")), externalStorageOnly = true) internal class ExternalModuleListStorage(private val project: Project) : PersistentStateComponent, ProjectModelElement { var loadedState: Set? = null private set diff --git a/resources/src/componentSets/Compiler.xml b/resources/src/componentSets/Compiler.xml index 4350344eb250..0bb2c4f67d0d 100644 --- a/resources/src/componentSets/Compiler.xml +++ b/resources/src/componentSets/Compiler.xml @@ -13,6 +13,10 @@ com.intellij.packaging.artifacts.ArtifactManager com.intellij.packaging.impl.artifacts.ArtifactManagerImpl + + com.intellij.compiler.ExternalCompilerConfigurationStorage + + com.intellij.compiler.CompilerConfiguration com.intellij.compiler.CompilerConfigurationImpl From 9d7fa672d4418bbb80afbf33fa8971f57ebd662e Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 15:24:08 +0300 Subject: [PATCH 30/81] show initial null value --- .../debugger/engine/JavaValueModifier.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java index 4046ea343b03..b0b149916c77 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerBundle; @@ -51,7 +37,7 @@ public abstract class JavaValueModifier extends XValueModifier { @Override public void calculateInitialValueEditorText(final XInitialValueCallback callback) { final Value value = myJavaValue.getDescriptor().getValue(); - if (value instanceof PrimitiveValue) { + if (value == null || value instanceof PrimitiveValue) { String valueString = myJavaValue.getValueString(); int pos = valueString.lastIndexOf('('); //skip hex presentation if any if (pos > 1) { From 7fa96faf725f9ee605444bacb794c21906a3e699 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Fri, 17 Nov 2017 15:22:21 +0300 Subject: [PATCH 31/81] Java: Fixed comparing potential matches when detecting duplicates of the extracted method (IDEA-182275) --- .../util/duplicates/DuplicatesFinder.java | 2 +- .../WriteDifferentFieldsDuplicate.java | 17 +++++++++++++++ .../WriteDifferentFieldsDuplicate_after.java | 21 +++++++++++++++++++ .../java/refactoring/ExtractMethodTest.java | 4 ++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate_after.java diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index f89565ccd385..1cbd6aef81c5 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -564,7 +564,7 @@ public class DuplicatesFinder { PsiElement child2 = children2[i]; if (!matchPattern(child1, child2, candidates, match)) { matchedExtractablePart = matchExtractableExpression(child1, child2, candidates, match, true); - return matchedExtractablePart != null && matchedExtractablePart; + if (matchedExtractablePart == null || !matchedExtractablePart) return false; } } diff --git a/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate.java b/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate.java new file mode 100644 index 000000000000..5f9077a97e74 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate.java @@ -0,0 +1,17 @@ +class WriteDifferentFieldsDuplicate { + Runnable x; + Runnable y; + + private void foo() { + + if (x != null) { + x.run(); + x = null; + } + + if (y != null) { + y.run(); + y = null; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate_after.java b/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate_after.java new file mode 100644 index 000000000000..7132e803b47a --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/WriteDifferentFieldsDuplicate_after.java @@ -0,0 +1,21 @@ +class WriteDifferentFieldsDuplicate { + Runnable x; + Runnable y; + + private void foo() { + + newMethod(); + + if (y != null) { + y.run(); + y = null; + } + } + + private void newMethod() { + if (x != null) { + x.run(); + x = null; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodTest.java index 425f6317ffb0..817e8b7dbf01 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodTest.java @@ -1177,6 +1177,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testWriteDifferentFieldsDuplicate() throws Exception { + doDuplicatesTest(); + } + private void doTestDisabledParam() throws PrepareFailedException { final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); settings.ELSE_ON_NEW_LINE = true; From 75346398f1d45c381d861f2aee14751e4cd350c4 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 17 Nov 2017 16:06:30 +0300 Subject: [PATCH 32/81] Fix thread leaks in Python Console (PY-26465) --- .../jetbrains/python/console/PydevConsoleCommunication.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java index 1c109ccd105c..05cc114e47ee 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java @@ -178,12 +178,12 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl */ public synchronized void close() { sendCloseMessageToScript(); + PyDebugValueExecutionService.getInstance(myProject).sessionStopped(this); if (myWebServer != null) { myWebServer.shutdown(); myWebServer = null; } - PyDebugValueExecutionService.getInstance(myProject).sessionStopped(this); } /** @@ -195,6 +195,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl @NotNull public synchronized Future closeAsync() { sendCloseMessageToScript(); + PyDebugValueExecutionService.getInstance(myProject).sessionStopped(this); if (myWebServer != null) { Future shutdownFuture = myWebServer.shutdownAsync(); From fa337db48c04cc2d77e951cb50631dbb2f0f4f2b Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 17 Nov 2017 16:25:17 +0300 Subject: [PATCH 33/81] Gradle: use the same settings for buildSrc project import --- .../gradle/service/project/GradleProjectResolver.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index ee5ad2982bbf..354688f4fefb 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -151,6 +151,12 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver Date: Fri, 17 Nov 2017 16:28:40 +0300 Subject: [PATCH 34/81] IDEA-182289 'Replace All' interprets find/replace contents as HTML --- .../intellij/find/impl/FindPopupPanel.java | 7 ++---- .../ReplaceInProjectManager.java | 23 +++++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java index 7d3350ee4c67..41c9901d25a5 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java @@ -425,14 +425,11 @@ public class FindPopupPanel extends JBPanel implements FindUI { myReplaceAllButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (myResultsPreviewTable.getRowCount() < 2 || MessageDialogBuilder.yesNo(FindBundle.message( - "find.replace.all.confirmation.title"), FindBundle.message( - "find.replace.all.confirmation", + if (myResultsPreviewTable.getRowCount() < 2 || ReplaceInProjectManager.getInstance(myProject).showReplaceAllConfirmDialog( myMessageState[0], getStringToFind(), myMessageState[1], - getStringToReplace())) - .yesText(Messages.OK_BUTTON).noText(Messages.CANCEL_BUTTON).show() == Messages.YES) { + getStringToReplace())) { doOK(false); } } diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java index f851a226b39d..132a99998d43 100644 --- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java +++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java @@ -36,6 +36,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Factory; @@ -357,6 +358,14 @@ public class ReplaceInProjectManager { return true; } + public boolean showReplaceAllConfirmDialog(String usagesCount, String stringToFind, String filesCount, String stringToReplace) { + return Messages.YES == MessageDialogBuilder.yesNo( + FindBundle.message("find.replace.all.confirmation.title"), + FindBundle.message("find.replace.all.confirmation", usagesCount, StringUtil.escapeXml(stringToFind), filesCount, StringUtil.escapeXml(stringToReplace))) + .yesText(Messages.OK_BUTTON) + .noText(Messages.CANCEL_BUTTON).show(); + } + private void addReplaceActions(final ReplaceContext replaceContext) { final AbstractAction replaceAction = new AbstractAction(FindBundle.message("find.replace.all.action")) { @Override @@ -369,15 +378,11 @@ public class ReplaceInProjectManager { files.add(((UsageInfo2UsageAdapter)usage).getFile()); } } - if (files.size() < 2 || - JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(replaceContext.getUsageView().getComponent(), - FindBundle.message("find.replace.all.confirmation", - usages.size(), - replaceContext.getFindModel().getStringToFind(), - files.size(), - replaceContext.getFindModel().getStringToReplace()), - FindBundle.message("find.replace.all.confirmation.title"), - JOptionPane.OK_CANCEL_OPTION)) { + if (files.size() < 2 || showReplaceAllConfirmDialog( + "" + usages.size(), + replaceContext.getFindModel().getStringToFind(), + "" + files.size(), + replaceContext.getFindModel().getStringToReplace())) { replaceUsagesUnderCommand(replaceContext, usages); } } From 7aa22991083524d2b1221f2e05ae059939c784e5 Mon Sep 17 00:00:00 2001 From: Leonid Bushuev Date: Fri, 17 Nov 2017 16:32:14 +0300 Subject: [PATCH 35/81] Rename method PlatformTestUtil.disposeApplicationAndStopNonDaemonThreads() to disposeApplicationAndCheckForProjectLeaks(). --- platform/testFramework/src/_LastInSuiteTest.java | 4 ++-- .../src/com/intellij/testFramework/PlatformTestUtil.java | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/testFramework/src/_LastInSuiteTest.java b/platform/testFramework/src/_LastInSuiteTest.java index a8bcc62057fd..0264fba0d9e5 100644 --- a/platform/testFramework/src/_LastInSuiteTest.java +++ b/platform/testFramework/src/_LastInSuiteTest.java @@ -27,7 +27,7 @@ import junit.framework.TestCase; import java.util.concurrent.TimeUnit; import static com.intellij.testFramework.PlatformTestUtil.captureMemorySnapshot; -import static com.intellij.testFramework.PlatformTestUtil.disposeApplicationAndStopNonDaemonThreads; +import static com.intellij.testFramework.PlatformTestUtil.disposeApplicationAndCheckForProjectLeaks; /** * This must be the last test. @@ -60,7 +60,7 @@ public class _LastInSuiteTest extends TestCase { return; } - disposeApplicationAndStopNonDaemonThreads(); + disposeApplicationAndCheckForProjectLeaks(); try { Disposer.assertIsEmpty(true); diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java index 283070291809..23b6c94811c8 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java @@ -1090,7 +1090,11 @@ public class PlatformTestUtil { ourProjectCleanups.clear(); } - public static void disposeApplicationAndStopNonDaemonThreads() { + /** + * Disposes the application (it also stops some application-related threads) + * and checks for project leaks. + */ + public static void disposeApplicationAndCheckForProjectLeaks() { EdtTestUtil.runInEdtAndWait(() -> { try { LightPlatformTestCase.initApplication(); // in case nobody cared to init. LightPlatformTestCase.disposeApplication() would not work otherwise. From ad54d2af4d13aab7d2463e4da645d0712a61daa8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 17 Nov 2017 14:39:32 +0100 Subject: [PATCH 36/81] [platform] moves graph algorithms into core API ... to make it accessible from projectModel-* modules --- .../intellij/util/graph/GraphAlgorithms.java | 16 +------------- .../core/CoreApplicationEnvironment.java | 22 +++++-------------- .../intellij/util/graph/impl/CycleFinder.java | 16 +------------- .../util/graph/impl/GraphAlgorithmsImpl.java | 16 +------------- .../intellij/util/graph/impl/GraphEdge.java | 16 +------------- .../util/graph/impl/KShortestPathsFinder.java | 16 +------------- .../util/graph/impl/ShortestPathFinder.java | 16 +------------- 7 files changed, 11 insertions(+), 107 deletions(-) rename platform/{platform-api => core-api}/src/com/intellij/util/graph/GraphAlgorithms.java (74%) rename platform/{platform-impl => core-impl}/src/com/intellij/util/graph/impl/CycleFinder.java (77%) rename platform/{platform-impl => core-impl}/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java (86%) rename platform/{platform-impl => core-impl}/src/com/intellij/util/graph/impl/GraphEdge.java (59%) rename platform/{platform-impl => core-impl}/src/com/intellij/util/graph/impl/KShortestPathsFinder.java (94%) rename platform/{platform-impl => core-impl}/src/com/intellij/util/graph/impl/ShortestPathFinder.java (66%) diff --git a/platform/platform-api/src/com/intellij/util/graph/GraphAlgorithms.java b/platform/core-api/src/com/intellij/util/graph/GraphAlgorithms.java similarity index 74% rename from platform/platform-api/src/com/intellij/util/graph/GraphAlgorithms.java rename to platform/core-api/src/com/intellij/util/graph/GraphAlgorithms.java index 40b3064dc9db..6f9192fdfd46 100644 --- a/platform/platform-api/src/com/intellij/util/graph/GraphAlgorithms.java +++ b/platform/core-api/src/com/intellij/util/graph/GraphAlgorithms.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2011 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph; import com.intellij.openapi.components.ServiceManager; diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index 52f0935f19d1..b3c6b9adfdcc 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.core; import com.intellij.codeInsight.folding.CodeFoldingSettings; @@ -66,6 +52,8 @@ import com.intellij.psi.stubs.CoreStubTreeLoader; import com.intellij.psi.stubs.StubTreeLoader; import com.intellij.util.Consumer; import com.intellij.util.Processor; +import com.intellij.util.graph.GraphAlgorithms; +import com.intellij.util.graph.impl.GraphAlgorithmsImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.MutablePicoContainer; @@ -126,12 +114,12 @@ public class CoreApplicationEnvironment { registerApplicationService(StubTreeLoader.class, new CoreStubTreeLoader()); registerApplicationService(PsiReferenceService.class, new PsiReferenceServiceImpl()); registerApplicationService(MetaDataRegistrar.class, new MetaRegistry()); - registerApplicationService(ProgressManager.class, createProgressIndicatorProvider()); - registerApplicationService(JobLauncher.class, createJobLauncher()); registerApplicationService(CodeFoldingSettings.class, new CodeFoldingSettings()); registerApplicationService(CommandProcessor.class, new CoreCommandProcessor()); + registerApplicationService(GraphAlgorithms.class, new GraphAlgorithmsImpl()); + myApplication.registerService(ApplicationInfo.class, ApplicationInfoImpl.class); } diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/CycleFinder.java b/platform/core-impl/src/com/intellij/util/graph/impl/CycleFinder.java similarity index 77% rename from platform/platform-impl/src/com/intellij/util/graph/impl/CycleFinder.java rename to platform/core-impl/src/com/intellij/util/graph/impl/CycleFinder.java index 8f71253c23ec..d9f0bcb10939 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/CycleFinder.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/CycleFinder.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph.impl; import com.intellij.util.containers.ContainerUtil; diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java b/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java similarity index 86% rename from platform/platform-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java rename to platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java index 18d9e3565997..397b905ab023 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph.impl; import com.intellij.openapi.progress.ProgressIndicator; diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/GraphEdge.java b/platform/core-impl/src/com/intellij/util/graph/impl/GraphEdge.java similarity index 59% rename from platform/platform-impl/src/com/intellij/util/graph/impl/GraphEdge.java rename to platform/core-impl/src/com/intellij/util/graph/impl/GraphEdge.java index d7f977f0a810..5b3354bb126f 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/GraphEdge.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/GraphEdge.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2011 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph.impl; import org.jetbrains.annotations.NotNull; diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java b/platform/core-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java similarity index 94% rename from platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java rename to platform/core-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java index d7527c991944..384f412bc024 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2011 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph.impl; import com.intellij.openapi.diagnostic.Logger; diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java b/platform/core-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java similarity index 66% rename from platform/platform-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java rename to platform/core-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java index 1546ecd6f717..322b1e9e8479 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/ShortestPathFinder.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2011 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.graph.impl; import com.intellij.util.graph.Graph; From da128973887a25fb8a77d14a42640acc3b20ca73 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 16:41:28 +0300 Subject: [PATCH 37/81] IDEA-49244 Exceptions during watches evaluation are printed to console --- .../ui/impl/watch/EvaluationDescriptor.java | 21 ++++---------- .../ui/impl/watch/ValueDescriptorImpl.java | 29 +++++++------------ 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java index 14a504add554..9ada361e9aca 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.impl.watch; import com.intellij.debugger.DebuggerBundle; @@ -128,6 +114,11 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl { } } + @Override + protected boolean isPrintExceptionToConsole() { + return false; + } + @Nullable public Modifier getModifier() { return myModifier; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java index 3c582fc7e35b..a0eb4113d3e1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.impl.watch; import com.intellij.Patches; @@ -221,7 +207,8 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements catch (EvaluateException e) { myValueException = e; setFailed(e); - myValue = getTargetExceptionWithStackTraceFilled(evaluationContext, e); + myValue = getTargetExceptionWithStackTraceFilled(evaluationContext, e, + isPrintExceptionToConsole() || ApplicationManager.getApplication().isUnitTestMode()); myIsExpandable = false; } finally { @@ -231,8 +218,14 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements myIsNew = false; } + protected boolean isPrintExceptionToConsole() { + return true; + } + @Nullable - private static ObjectReference getTargetExceptionWithStackTraceFilled(final EvaluationContextImpl evaluationContext, EvaluateException ex){ + private static ObjectReference getTargetExceptionWithStackTraceFilled(EvaluationContextImpl evaluationContext, + EvaluateException ex, + boolean printToConsole) { final ObjectReference exceptionObj = ex.getExceptionFromTargetVM(); if (exceptionObj != null && evaluationContext != null) { try { @@ -243,7 +236,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements Value trace = process.invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList()); // print to console as well - if (trace instanceof ArrayReference) { + if (printToConsole && trace instanceof ArrayReference) { ArrayReference traceArray = (ArrayReference)trace; process.printToConsole(DebuggerUtils.getValueAsString(evaluationContext, exceptionObj) + "\n"); for (Value stackElement : traceArray.getValues()) { From bec235470aa400c9b318b8762634b4ff516f8ad2 Mon Sep 17 00:00:00 2001 From: Nikita Skvortsov Date: Wed, 15 Nov 2017 18:34:56 +0300 Subject: [PATCH 38/81] external build system: optimize dependencies import --- .../manage/ExternalSystemKeymapExtension.java | 9 ++- .../project/manage/LibraryDataService.java | 56 +++++++++++-------- .../BaseGradleProjectResolverExtension.java | 30 +++++----- .../project/GradleProjectResolverUtil.java | 1 + 4 files changed, 58 insertions(+), 38 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemKeymapExtension.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemKeymapExtension.java index 6ff668a87567..db8a40bf120e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemKeymapExtension.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalSystemKeymapExtension.java @@ -221,8 +221,13 @@ public class ExternalSystemKeymapExtension implements KeymapExtension { public static void clearActions(Project project, Collection> taskData) { ActionManager actionManager = ActionManager.getInstance(); if (actionManager != null) { - for (DataNode each : taskData) { - for (String eachAction : actionManager.getActionIds(getActionPrefix(project, each.getData().getLinkedExternalProjectPath()))) { + Set externalProjectPaths = ContainerUtil.newHashSet(); + for (DataNode node : taskData) { + externalProjectPaths.add(node.getData().getLinkedExternalProjectPath()); + } + + for (String externalProjectPath : externalProjectPaths) { + for (String eachAction : actionManager.getActionIds(getActionPrefix(project, externalProjectPath))) { AnAction action = actionManager.getAction(eachAction); if (!(action instanceof ExternalSystemRunConfigurationAction)) { actionManager.unregisterAction(eachAction); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java index 50d9e4a9ad7d..e66dc30f5f28 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java @@ -23,7 +23,6 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.RootPolicy; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -145,7 +144,6 @@ public class LibraryDataService extends AbstractProjectDataService> toImport, @@ -157,15 +155,45 @@ public class LibraryDataService extends AbstractProjectDataService orphanIdeLibraries = ContainerUtil.newSmartList(); final LibraryTable.ModifiableModel librariesModel = modelsProvider.getModifiableProjectLibrariesModel(); + final Map namesToLibs = ContainerUtil.newHashMap(); + final Set potentialOrphans = ContainerUtil.newHashSet(); + RootPolicy excludeUsedLibraries = new RootPolicy() { + @Override + public Void visitLibraryOrderEntry(@NotNull LibraryOrderEntry ideDependency, Void value) { + if (ideDependency.isModuleLevel()) { + return null; + } + Library lib = ideDependency.getLibrary(); + if (lib == null) { + lib = namesToLibs.get(ideDependency.getLibraryName()); + } + if (lib != null) { + potentialOrphans.remove(lib); + } + return null; + } + }; + for (Library library : librariesModel.getLibraries()) { if (!ExternalSystemApiUtil.isExternalSystemLibrary(library, projectData.getOwner())) continue; - if (isOrphanProjectLibrary(library, modelsProvider) && !modelsProvider.isSubstituted(library.getName())) { - orphanIdeLibraries.add(library); + namesToLibs.put(library.getName(), library); + potentialOrphans.add(library); + } + + for (Module module : modelsProvider.getModules()) { + for (OrderEntry entry : modelsProvider.getOrderEntries(module)) { + entry.accept(excludeUsedLibraries, null); + } + } + + for (Library lib : potentialOrphans) { + if (!modelsProvider.isSubstituted(lib.getName())) { + orphanIdeLibraries.add(lib); } } @@ -220,22 +248,4 @@ public class LibraryDataService extends AbstractProjectDataService visitor = new RootPolicy() { - @Override - public Boolean visitLibraryOrderEntry(@NotNull LibraryOrderEntry ideDependency, Boolean value) { - return !ideDependency.isModuleLevel() && - (library == ideDependency.getLibrary() || - (ideDependency.getLibrary() == null && StringUtil.equals(library.getName(), ideDependency.getLibraryName()))); - } - }; - for (Module module : modelsProvider.getModules()) { - for (OrderEntry entry : modelsProvider.getOrderEntries(module)) { - if (entry.accept(visitor, false)) return false; - } - } - return true; - } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java index 25a454c65816..cb0baebb1955 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java @@ -34,7 +34,10 @@ import com.intellij.openapi.externalSystem.service.notification.NotificationData import com.intellij.openapi.externalSystem.service.notification.NotificationSource; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.Order; -import com.intellij.openapi.module.*; +import com.intellij.openapi.module.EmptyModuleType; +import com.intellij.openapi.module.JavaModuleType; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.util.Pair; @@ -52,7 +55,6 @@ import com.intellij.util.text.CharArrayUtil; import groovy.lang.GroovyObject; import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; import org.gradle.internal.impldep.com.google.common.collect.Multimap; -import org.gradle.internal.impldep.com.google.common.io.InputSupplier; import org.gradle.tooling.ProjectConnection; import org.gradle.tooling.model.DomainObjectSet; import org.gradle.tooling.model.GradleModuleVersion; @@ -521,6 +523,12 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver if (dependencies == null) return; List orphanModules = ContainerUtil.newArrayList(); + Map modulesIndex = ContainerUtil.newHashMap(); + + for (DataNode dataNode : ExternalSystemApiUtil.getChildren(ideProject, ProjectKeys.MODULE)) { + modulesIndex.put(dataNode.getData().getExternalName(), dataNode.getData()); + } + for (int i = 0; i < dependencies.size(); i++) { IdeaDependency dependency = dependencies.get(i); if (dependency == null) { @@ -529,7 +537,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver DependencyScope scope = parseScope(dependency.getScope()); if (dependency instanceof IdeaModuleDependency) { - ModuleDependencyData d = buildDependency(resolverCtx, ideModule, (IdeaModuleDependency)dependency, ideProject); + ModuleDependencyData d = buildDependency(resolverCtx, ideModule, (IdeaModuleDependency)dependency, modulesIndex); d.setExported(dependency.getExported()); if (scope != null) { d.setScope(scope); @@ -870,7 +878,7 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver private static ModuleDependencyData buildDependency(@NotNull ProjectResolverContext resolverContext, @NotNull DataNode ownerModule, @NotNull IdeaModuleDependency dependency, - @NotNull DataNode ideProject) + @NotNull Map registeredModulesIndex) throws IllegalStateException { IdeaModule module = dependency.getDependencyModule(); if (module == null) { @@ -904,18 +912,14 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver )); } - Set registeredModuleNames = ContainerUtilRt.newHashSet(); - Collection> modulesDataNode = ExternalSystemApiUtil.getChildren(ideProject, ProjectKeys.MODULE); - for (DataNode moduleDataNode : modulesDataNode) { - String name = moduleDataNode.getData().getExternalName(); - registeredModuleNames.add(name); - if (name.equals(moduleName)) { - return new ModuleDependencyData(ownerModule.getData(), moduleDataNode.getData()); - } + ModuleData moduleData = registeredModulesIndex.get(moduleName); + if (moduleData != null) { + return new ModuleDependencyData(ownerModule.getData(), moduleData); } + throw new IllegalStateException(String.format( "Can't parse gradle module dependency '%s'. Reason: no module with such name (%s) is found. Registered modules: %s", - dependency, moduleName, registeredModuleNames + dependency, moduleName, registeredModulesIndex.keySet() )); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java index a80869db3628..ec5804559f4f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverUtil.java @@ -292,6 +292,7 @@ public class GradleProjectResolverUtil { @Nullable final File libFile, @NotNull final LibraryData library, @NotNull final ProjectResolverContext resolverCtx) { + if (libFile == null || !libFile.getName().startsWith("gradle-")) return; final BuildScriptClasspathModel buildScriptClasspathModel = resolverCtx.getExtraProject(gradleModule, BuildScriptClasspathModel.class); if (buildScriptClasspathModel == null) return; From e00c6b91bbebd849790815171f17a009e9658fb3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 17 Nov 2017 15:04:01 +0100 Subject: [PATCH 39/81] [ui] quotes paths for "Show in Explorer" action (IDEA-182339) --- .../ide/actions/ShowFilePathAction.java | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java index e6ccccc56b94..9b890d48a20b 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.actions; import com.intellij.execution.ExecutionException; @@ -283,9 +269,9 @@ public class ShowFilePathAction extends AnAction { String toSelect = _toSelect != null ? FileUtil.toSystemDependentName(FileUtil.toCanonicalPath(_toSelect.getPath())) : null; if (SystemInfo.isWindows) { - String cmd = toSelect != null ? "explorer /select," + toSelect : "explorer /root," + dir; + String cmd = toSelect != null ? "explorer /select,\"" + toSelect + '"' : "explorer /root,\"" + dir + '"'; LOG.debug(cmd); - Process process = Runtime.getRuntime().exec(cmd); // no quoting/escaping is needed + Process process = Runtime.getRuntime().exec(cmd); // no advanced quoting/escaping is needed new CapturingProcessHandler(process, null, cmd).runProcess().checkSuccess(LOG); } else if (SystemInfo.isMac) { From 1c28a25a42e425207f8f456b32251b44c51a07dc Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 17 Nov 2017 17:06:48 +0300 Subject: [PATCH 40/81] do not update an internal state before an exception may be thrown --- .../intellij/ui/tree/StructureTreeModel.java | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/tree/StructureTreeModel.java b/platform/platform-impl/src/com/intellij/ui/tree/StructureTreeModel.java index b6a990871620..74edbe5e6437 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/StructureTreeModel.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/StructureTreeModel.java @@ -205,11 +205,12 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable, Object element = structure.getRootElement(); if (!isValid(element)) return null; - Node node = root.get(); - boolean leaf = structure.isAlwaysLeaf(element); - if (node == null || leaf == node.getAllowsChildren() || !element.equals(node.getElement())) node = new Node(leaf); - node.update(structure.createDescriptor(element, null)); - return node; + Node newNode = new Node(structure, element, null); // an exception may be thrown while getting a root + Node oldNode = root.get(); + if (oldNode != null && oldNode.canReuse(newNode, element)) { + return oldNode; // reuse old node with possible children + } + return newNode; } private List getValidChildren(@NotNull Node node) { @@ -225,32 +226,37 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable, Object[] elements = structure.getChildElements(parent); if (elements == null || elements.length == 0) return null; + List list = new ArrayList<>(elements.length); + for (Object element : elements) { + if (isValid(element)) { + list.add(new Node(structure, element, descriptor)); // an exception may be thrown while getting children + } + } + Comparator comparator = this.comparator; + if (comparator != null) list.sort(comparator); // an exception may be thrown while sorting children + HashMap map = new HashMap<>(); node.getChildren().forEach(child -> { Object element = child.getElement(); if (element != null) map.put(element, child); }); - List list = new ArrayList<>(elements.length); - for (Object element : elements) { - if (isValid(element)) { - Node child = map.get(element); - boolean leaf = structure.isAlwaysLeaf(element); - if (child == null || leaf == child.getAllowsChildren()) child = new Node(leaf); - child.update(structure.createDescriptor(element, descriptor)); - list.add(child); + for (int i = 0; i < list.size(); i++) { + Node newNode = list.get(i); + Node oldNode = map.get(newNode.getElement()); + if (oldNode != null && oldNode.canReuse(newNode, null)) { + list.set(i, oldNode); // reuse old node with possible children } } - Comparator comparator = this.comparator; - if (comparator != null) list.sort(comparator); return list; } private static final class Node extends DefaultMutableTreeNode { private final Reference> children = new Reference<>(); - private Node(boolean leaf) { - super(null, !leaf); - if (leaf) children.set(null); + private Node(@NotNull AbstractTreeStructure structure, Object element, NodeDescriptor parent) { + super(structure.createDescriptor(element, parent), !structure.isAlwaysLeaf(element)); + if (!getAllowsChildren()) children.set(null); // validate children for leaf node + update(); // an exception may be thrown while updating } private void dispose() { @@ -259,9 +265,11 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable, if (list != null) list.forEach(Node::dispose); } - private void update(@NotNull NodeDescriptor descriptor) { - descriptor.update(); - super.userObject = descriptor; + private boolean canReuse(@NotNull Node node, Object element) { + if (super.allowsChildren != node.allowsChildren) return false; + if (element != null && !element.equals(getElement())) return false; + super.userObject = node.userObject; // replace old descriptor + return true; } private boolean update() { From ca84f62d964bfdce81d66f2ae560b47d75cebb01 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 17:37:34 +0300 Subject: [PATCH 41/81] IDEA-155080 Introduce better UI for single/multi-line editors - fixed expander bg color and use combobox in evaluator dialog --- .../ui/XLightBreakpointPropertiesPanel.java | 2 +- .../evaluate/ExpressionInputComponent.java | 92 ++----------------- .../impl/ui/XDebuggerEditorBase.java | 38 ++++---- .../impl/ui/XDebuggerExpressionComboBox.java | 18 +--- 4 files changed, 26 insertions(+), 124 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index 7e6aaf943b8c..e50481143208 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -127,7 +127,7 @@ public class XLightBreakpointPropertiesPanel implements XSuspendPolicyPanel.Dele if (debuggerEditorsProvider != null) { myConditionEnabledCheckbox = new JBCheckBox(XDebuggerBundle.message("xbreakpoints.condition.checkbox")); myConditionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, CONDITION_HISTORY_ID, - myBreakpoint.getSourcePosition(), true, true); + myBreakpoint.getSourcePosition(), true, false); myLanguageChooserPanel.add(myConditionComboBox.getLanguageChooser(), BorderLayout.CENTER); myConditionExpressionPanel.add(myConditionComboBox.getComponent(), BorderLayout.CENTER); myConditionEnabledCheckbox.addActionListener(e -> onCheckboxChanged()); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/ExpressionInputComponent.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/ExpressionInputComponent.java index 1ae06c2ea7e9..422634bf7897 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/ExpressionInputComponent.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/ExpressionInputComponent.java @@ -1,35 +1,11 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xdebugger.impl.evaluate; -import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.icons.AllIcons; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.editor.ex.util.EditorUtil; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.FixedSizeButton; -import com.intellij.openapi.ui.popup.PopupStep; -import com.intellij.openapi.ui.popup.util.BaseListPopupStep; -import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.components.JBLabel; -import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.components.BorderLayoutPanel; @@ -37,23 +13,19 @@ import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; -import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; -import com.intellij.xdebugger.impl.ui.XDebuggerExpressionEditor; +import com.intellij.xdebugger.impl.ui.XDebuggerExpressionComboBox; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; /** * @author nik */ public class ExpressionInputComponent extends EvaluationInputComponent { - private final XDebuggerExpressionEditor myExpressionEditor; + private final XDebuggerEditorBase myExpressionEditor; private final ExpressionInputForm myMainForm = new ExpressionInputForm(); public ExpressionInputComponent(final @NotNull Project project, @@ -65,25 +37,13 @@ public class ExpressionInputComponent extends EvaluationInputComponent { boolean showHelp) { super(XDebuggerBundle.message("xdebugger.dialog.title.evaluate.expression")); BorderLayoutPanel expressionPanel = JBUI.Panels.simplePanel(); - //myMainPanel.add(new JLabel(XDebuggerBundle.message("xdebugger.evaluate.label.expression")), BorderLayout.WEST); - myExpressionEditor = new XDebuggerExpressionEditor(project, editorsProvider, historyId, sourcePosition, - expression != null ? expression : XExpressionImpl.EMPTY_EXPRESSION, false, true, true) { + myExpressionEditor = new XDebuggerExpressionComboBox(project, editorsProvider, historyId, sourcePosition, true, false) { @Override - protected JComponent decorate(JComponent component, boolean multiline, boolean showEditor) { - return component; + protected void prepareEditor(Editor editor) { } }; + myExpressionEditor.setExpression(expression); expressionPanel.addToCenter(myExpressionEditor.getComponent()); - JButton historyButton = new FixedSizeButton(myExpressionEditor.getComponent()); - historyButton.setIcon(AllIcons.General.MessageHistory); - historyButton.setToolTipText(XDebuggerBundle.message("xdebugger.evaluate.history.hint")); - historyButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - showHistory(); - } - }); - expressionPanel.addToRight(myExpressionEditor.addExpand(historyButton)); final JBLabel help = new JBLabel(XDebuggerBundle.message("xdebugger.evaluate.addtowatches.hint", KeymapUtil.getKeystrokeText(XDebuggerEvaluationDialog.ADD_WATCH_KEYSTROKE)), SwingConstants.RIGHT); @@ -95,44 +55,6 @@ public class ExpressionInputComponent extends EvaluationInputComponent { myMainForm.addExpressionComponent(expressionPanel); myMainForm.addLanguageComponent(myExpressionEditor.getLanguageChooser()); - - new AnAction("XEvaluateDialog.ShowHistory") { - @Override - public void actionPerformed(AnActionEvent e) { - showHistory(); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(LookupManager.getActiveLookup(myExpressionEditor.getEditor()) == null); - } - }.registerCustomShortcutSet(CustomShortcutSet.fromString("DOWN"), myMainForm.getMainPanel(), parentDisposable); - } - - private void showHistory() { - List expressions = myExpressionEditor.getRecentExpressions(); - if (!expressions.isEmpty()) { - ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep(null, expressions) { - @Override - public PopupStep onChosen(XExpression selectedValue, boolean finalChoice) { - myExpressionEditor.setExpression(selectedValue); - myExpressionEditor.requestFocusInEditor(); - return FINAL_CHOICE; - } - }) { - @Override - protected ListCellRenderer getListElementRenderer() { - return new ColoredListCellRenderer() { - @Override - protected void customizeCellRenderer(@NotNull JList list, XExpression value, int index, boolean selected, boolean hasFocus) { - append(value.getExpression()); - } - }; - } - }; - popup.getList().setFont(EditorUtil.getEditorFont()); - popup.showUnderneathOf(myExpressionEditor.getEditorComponent()); - } } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java index 7e0a22875b50..8c5e1ed92531 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xdebugger.impl.ui; import com.intellij.icons.AllIcons; @@ -185,7 +171,7 @@ public abstract class XDebuggerEditorBase implements Expandable { panel.add(factoryPanel, BorderLayout.WEST); if (!multiline && showEditor) { - component = addExpand(component); + component = addExpand(component, false); } panel.addToCenter(component); @@ -207,12 +193,20 @@ public abstract class XDebuggerEditorBase implements Expandable { return panel; } - public JComponent addExpand(JComponent component) { - BorderLayoutPanel panel = new BorderLayoutPanel() { - @Override public Color getBackground() { - return component.getBackground(); - } - }; + protected JComponent addExpand(JComponent component, boolean inheritBackground) { + BorderLayoutPanel panel; + if (inheritBackground) { + panel = new BorderLayoutPanel() { + @Override + public Color getBackground() { + return component.getBackground(); + } + }; + } + else { + panel = JBUI.Panels.simplePanel(); + panel.setOpaque(false); + } panel.addToCenter(component); panel.addToRight(myExpandButton); return panel; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java index 8053ebe38b47..869a6be6ab28 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xdebugger.impl.ui; import com.intellij.openapi.editor.Document; @@ -212,7 +198,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { comp = addChooser(comp); } if (showMultiline) { - comp = addExpand(comp); + comp = addExpand(comp, true); } myPanel = comp; } From 557534e9c1f809280379d4f4eb074134ef103317 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 17 Nov 2017 17:39:47 +0300 Subject: [PATCH 42/81] IDEA-181128 Wrap on typing works wrong with parameter hints --- .../formatter/java/JavaWrapOnTypingTest.java | 46 ++++++++++++------- .../editorActions/AutoHardWrapHandler.java | 26 +++-------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaWrapOnTypingTest.java b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaWrapOnTypingTest.java index be9bc0d632ce..d87e590227b9 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaWrapOnTypingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaWrapOnTypingTest.java @@ -1,26 +1,10 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.java.psi.formatter.java; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; public class JavaWrapOnTypingTest extends LightCodeInsightFixtureTestCase { - - public void testWrapInsideTags() { myFixture.configureByText(JavaFileType.INSTANCE, "public class Hw {\n" + @@ -51,4 +35,32 @@ public class JavaWrapOnTypingTest extends LightCodeInsightFixtureTestCase { " }\n" + "}\n"); } + + public void testWrapAtLineWithParameterHints() { + myFixture.configureByText(JavaFileType.INSTANCE, + "public class C {\n" + + " void m(int a, int b) {}\n" + + " void other() { m(1, 2); }\n" + + "}"); + myFixture.doHighlighting(); + myFixture.checkResultWithInlays("public class C {\n" + + " void m(int a, int b) {}\n" + + " void other() { m(1, 2); }\n" + + "}"); + + myFixture.getEditor().getSettings().setWrapWhenTypingReachesRightMargin(true); + myFixture.getEditor().getSettings().setRightMargin(30); + + myFixture.type(" "); + myFixture.checkResultWithInlays("public class C {\n" + + " void m(int a, int b) {}\n" + + " void other() { m(1, 2 ); }\n" + + "}"); + myFixture.type(" "); + myFixture.checkResultWithInlays("public class C {\n" + + " void m(int a, int b) {}\n" + + " void other() { m(1, 2 \n" + + " ); }\n" + + "}"); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java index bfb0665a8254..b77feee795d2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2011 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.editorActions; import com.intellij.codeInsight.template.TemplateManager; @@ -118,8 +104,8 @@ public class AutoHardWrapHandler { return; } - VisualPosition visEndLinePosition = editor.offsetToVisualPosition(endOffset); - if (margin >= visEndLinePosition.column) { + LogicalPosition logEndLinePosition = editor.offsetToLogicalPosition(endOffset); + if (margin >= logEndLinePosition.column) { if (change != null) { change.modificationStamp = document.getModificationStamp(); } @@ -159,9 +145,9 @@ public class AutoHardWrapHandler { change.update(editor); // Is assumed to be max possible number of characters inserted on the visual line with caret. - int maxPreferredOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition( - new VisualPosition(caretModel.getVisualPosition().line, margin - FormatConstants.getReservedLineWrapWidthInColumns(editor)) - )); + int maxPreferredOffset = editor.logicalPositionToOffset( + new LogicalPosition(caretModel.getLogicalPosition().line, margin - FormatConstants.getReservedLineWrapWidthInColumns(editor)) + ); int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true, false); if (wrapOffset < 0) { From 4e8ad76be22f8621f02467ae56c44711006bbdf1 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 17 Nov 2017 15:45:38 +0100 Subject: [PATCH 43/81] honor jre global proxy settings (IDEA-181489) --- .../aether/ArtifactRepositoryManager.java | 2 +- .../idea/maven/aether/JreProxySelector.java | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/JreProxySelector.java diff --git a/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/ArtifactRepositoryManager.java b/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/ArtifactRepositoryManager.java index a6252cf8cc90..629538627bb5 100644 --- a/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/ArtifactRepositoryManager.java +++ b/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/ArtifactRepositoryManager.java @@ -115,11 +115,11 @@ public class ArtifactRepositoryManager { // setup session here session.setLocalRepositoryManager(ourSystem.newLocalRepositoryManager(session, new LocalRepository(localRepositoryPath))); + session.setProxySelector(new org.jetbrains.idea.maven.aether.JreProxySelector()); session.setReadOnly(); mySession = session; } - public void addRemoteRepository(final String id, final String url) { myRemoteRepositories.add(createRemoteRepository(id, url)); } diff --git a/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/JreProxySelector.java b/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/JreProxySelector.java new file mode 100644 index 000000000000..fd6e107ba296 --- /dev/null +++ b/aether-dependency-resolver/src/org/jetbrains/idea/maven/aether/JreProxySelector.java @@ -0,0 +1,127 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.idea.maven.aether; + +import org.eclipse.aether.repository.*; +import org.eclipse.aether.repository.Proxy; +import org.eclipse.aether.repository.ProxySelector; + +import java.net.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * This is a modified copy of the corresponding Aether class that adds support for https proxy types + */ +final class JreProxySelector implements ProxySelector { + + JreProxySelector() { + } + + public Proxy getProxy(RemoteRepository repository) { + try { + final java.net.ProxySelector systemSelector = java.net.ProxySelector.getDefault(); + if (systemSelector == null) { + return null; + } + final URI uri = new URI(repository.getUrl()).parseServerAuthority(); + final List selected = systemSelector.select(uri); + if (selected == null || selected.isEmpty()) { + return null; + } + for (java.net.Proxy proxy : selected) { + if (proxy.type() == java.net.Proxy.Type.HTTP && isValid(proxy.address())) { + final String proxyType = chooseProxyType(uri.getScheme()); + if (proxyType != null) { + final InetSocketAddress addr = (InetSocketAddress)proxy.address(); + return new Proxy(proxyType, addr.getHostName(), addr.getPort(), JreProxyAuthentication.INSTANCE); + } + } + } + } + catch (Throwable e) { + // URL invalid or not accepted by selector or no selector at all, simply use no proxy + } + return null; + } + + private static String chooseProxyType(final String protocol) { + if (Proxy.TYPE_HTTP.equals(protocol)) { + return Proxy.TYPE_HTTP; + } + if (Proxy.TYPE_HTTPS.equals(protocol)) { + return Proxy.TYPE_HTTPS; + } + return null; + } + + private static boolean isValid(SocketAddress address) { + if (address instanceof InetSocketAddress) { + /* + * NOTE: On some platforms with java.net.useSystemProxies=true, unconfigured proxies show up as proxy + * objects with empty host and port 0. + */ + final InetSocketAddress addr = (InetSocketAddress)address; + return addr.getPort() > 0 && addr.getHostName() != null && !addr.getHostName().isEmpty(); + } + return false; + } + + private static final class JreProxyAuthentication implements Authentication { + + public static final Authentication INSTANCE = new JreProxyAuthentication(); + + public void fill(AuthenticationContext context, String key, Map data) { + Proxy proxy = context.getProxy(); + if (proxy == null) { + return; + } + if (!AuthenticationContext.USERNAME.equals(key) && !AuthenticationContext.PASSWORD.equals(key)) { + return; + } + + try { + URL url; + String protocol = "http"; + try { + url = new URL(context.getRepository().getUrl()); + protocol = url.getProtocol(); + } + catch (Exception e) { + url = null; + } + + PasswordAuthentication auth = Authenticator.requestPasswordAuthentication( + proxy.getHost(), null, proxy.getPort(), protocol, "Credentials for proxy " + proxy, null, url, Authenticator.RequestorType.PROXY + ); + if (auth != null) { + context.put(AuthenticationContext.USERNAME, auth.getUserName()); + context.put(AuthenticationContext.PASSWORD, auth.getPassword()); + } + else { + context.put(AuthenticationContext.USERNAME, System.getProperty(protocol + ".proxyUser")); + context.put(AuthenticationContext.PASSWORD, System.getProperty(protocol + ".proxyPassword")); + } + } + catch (SecurityException e) { + // oh well, let's hope the proxy can do without auth + } + } + + public void digest(AuthenticationDigest digest) { + // we don't know anything about the JRE's current authenticator, assume the worst (i.e. interactive) + digest.update(UUID.randomUUID().toString()); + } + + @Override + public boolean equals(Object obj) { + return this == obj || (obj != null && getClass().equals(obj.getClass())); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + } +} + From ddbd4c464daa8d285eab716d12fe6d66981fb834 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Fri, 17 Nov 2017 18:17:01 +0300 Subject: [PATCH 44/81] Fix deprecated Code style API usages in Tests/JavaDoc --- .../java/JavaSpacePropertyProcessor.java | 2 +- .../java/psi/formatter/java/IndentTest.java | 6 +++--- .../psi/formatter/java/JavaFormatterTest.kt | 17 +++++++++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 20464e3aa8c6..0dddfea1eda8 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -521,7 +521,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { /** * Initializes {@link #myResult} property with {@link Spacing} which {@code 'min line feeds'} property is defined - * from {@link CodeStyleSettings#BLANK_LINES_AROUND_CLASS} value. + * from {@link CommonCodeStyleSettings#BLANK_LINES_AROUND_CLASS} value. */ private void setAroundClassSpacing() { myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, mySettings.BLANK_LINES_AROUND_CLASS + 1, diff --git a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/IndentTest.java b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/IndentTest.java index 200eefe9b6e3..6dea46692e18 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/IndentTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/IndentTest.java @@ -106,7 +106,7 @@ public class IndentTest extends LightIdeaTestCase { public void testParenthesizedContinuation() throws Exception { defaultSettings(); - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings settings = getJavaSettings(); settings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION = true; doTest("ParenthesizedContinuation.java", "ParenthesizedContinuation_after.java"); @@ -115,7 +115,7 @@ public class IndentTest extends LightIdeaTestCase { public void testParenthesizedContinuation2() throws Exception { defaultSettings(); - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings settings = getJavaSettings(); settings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION = true; doTest("ParenthesizedContinuation2.java", "ParenthesizedContinuation2_after.java"); @@ -159,7 +159,7 @@ public class IndentTest extends LightIdeaTestCase { } private void defaultSettings() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings settings = getJavaSettings(); settings.ALIGN_MULTILINE_PARAMETERS = true; settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = false; diff --git a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterTest.kt b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterTest.kt index f97e72aa6942..5c9c65919f71 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterTest.kt @@ -1953,16 +1953,17 @@ class JavaFormatterTest : AbstractJavaFormatterTest() { } fun testWrapParamsOnEveryItem() { - val codeStyleSettings = CodeStyleSettingsManager.getSettings(LightPlatformTestCase.getProject()) + val codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject()) - val oldMargin = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE).RIGHT_MARGIN - val oldKeep = codeStyleSettings.KEEP_LINE_BREAKS - val oldWrap = codeStyleSettings.METHOD_PARAMETERS_WRAP + val javaSettings = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE) + val oldMargin = javaSettings.RIGHT_MARGIN + val oldKeep = javaSettings.KEEP_LINE_BREAKS + val oldWrap = javaSettings.METHOD_PARAMETERS_WRAP try { codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, 80) - codeStyleSettings.KEEP_LINE_BREAKS = false - codeStyleSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM + javaSettings.KEEP_LINE_BREAKS = false + javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM doClassTest( "public void foo(String p1,\n" + @@ -1986,8 +1987,8 @@ class JavaFormatterTest : AbstractJavaFormatterTest() { } finally { codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, oldMargin) - codeStyleSettings.KEEP_LINE_BREAKS = oldKeep - codeStyleSettings.METHOD_PARAMETERS_WRAP = oldWrap + javaSettings.KEEP_LINE_BREAKS = oldKeep + javaSettings.METHOD_PARAMETERS_WRAP = oldWrap } } From 0d358e7cc176a7ae72fba5c8f5fd748a52718314 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Nov 2017 17:04:51 +0100 Subject: [PATCH 45/81] more debugging for flaky JobUtilTest --- platform/testFramework/src/_FirstInSuiteTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/testFramework/src/_FirstInSuiteTest.java b/platform/testFramework/src/_FirstInSuiteTest.java index b647ec1ec25c..042bab53e35d 100644 --- a/platform/testFramework/src/_FirstInSuiteTest.java +++ b/platform/testFramework/src/_FirstInSuiteTest.java @@ -64,6 +64,7 @@ public class _FirstInSuiteTest extends TestCase { // some tests do not initialize Application but want to use parallel streams IdeaForkJoinWorkerThreadFactory.setupForkJoinCommonPool(); System.out.println("ForkJoinPool.commonPool: " + ForkJoinPool.commonPool()); + System.out.println("cpu cores: " + Runtime.getRuntime().availableProcessors()); suiteStarted = System.nanoTime(); From 9881d0ad7f35f71c7046c7291b9bb0f1e4d38500 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 19:15:17 +0300 Subject: [PATCH 46/81] IDEA-48873 Add easy access to exception stacktrace for exception objects --- .../ui/impl/watch/FieldDescriptorImpl.java | 39 +++++++++++-------- .../ui/impl/watch/ValueDescriptorImpl.java | 32 ++++++++------- .../util/resources/misc/registry.properties | 2 + 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java index 2ea8ad3c79b0..637a9748174b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.impl.watch; import com.intellij.debugger.DebuggerBundle; @@ -31,7 +17,9 @@ import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.ui.tree.FieldDescriptor; import com.intellij.debugger.ui.tree.NodeDescriptor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.CommonClassNames; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; @@ -95,13 +83,32 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { DebuggerManagerThreadImpl.assertIsManagerThread(); try { - return (myObject != null) ? myObject.getValue(myField) : myField.declaringType().getValue(myField); + if (myObject != null) { + populateExceptionStackTraceIfNeeded(evaluationContext); + return myObject.getValue(myField); + } + else { + return myField.declaringType().getValue(myField); + } } catch (ObjectCollectedException ignored) { throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED; } } + private void populateExceptionStackTraceIfNeeded(EvaluationContextImpl evaluationContext) { + if ("stackTrace".equals(getName()) && + Registry.is("debugger.populate.exception.stack") && + DebuggerUtils.instanceOf(myObject.type(), CommonClassNames.JAVA_LANG_THROWABLE)) { + try { + invokeExceptionGetStackTrace(myObject, evaluationContext); + } + catch (Throwable e) { + LOG.info(e); // catch all exceptions to ensure the method returns gracefully + } + } + } + public boolean isStatic() { return myIsStatic; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java index a0eb4113d3e1..19cdc1641949 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java @@ -223,25 +223,31 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements } @Nullable - private static ObjectReference getTargetExceptionWithStackTraceFilled(EvaluationContextImpl evaluationContext, + protected static Value invokeExceptionGetStackTrace(ObjectReference exceptionObj, EvaluationContextImpl evaluationContext) + throws EvaluateException { + Method method = ((ClassType)exceptionObj.referenceType()).concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;"); + if (method != null) { + return evaluationContext.getDebugProcess().invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList()); + } + return null; + } + + @Nullable + private static ObjectReference getTargetExceptionWithStackTraceFilled(@Nullable EvaluationContextImpl evaluationContext, EvaluateException ex, boolean printToConsole) { final ObjectReference exceptionObj = ex.getExceptionFromTargetVM(); if (exceptionObj != null && evaluationContext != null) { try { - ClassType refType = (ClassType)exceptionObj.referenceType(); - Method method = refType.concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;"); - if (method != null) { - final DebugProcessImpl process = evaluationContext.getDebugProcess(); - Value trace = process.invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList()); + Value trace = invokeExceptionGetStackTrace(exceptionObj, evaluationContext); - // print to console as well - if (printToConsole && trace instanceof ArrayReference) { - ArrayReference traceArray = (ArrayReference)trace; - process.printToConsole(DebuggerUtils.getValueAsString(evaluationContext, exceptionObj) + "\n"); - for (Value stackElement : traceArray.getValues()) { - process.printToConsole("\tat " + DebuggerUtils.getValueAsString(evaluationContext, stackElement) + "\n"); - } + // print to console as well + if (printToConsole && trace instanceof ArrayReference) { + DebugProcessImpl process = evaluationContext.getDebugProcess(); + ArrayReference traceArray = (ArrayReference)trace; + process.printToConsole(DebuggerUtils.getValueAsString(evaluationContext, exceptionObj) + "\n"); + for (Value stackElement : traceArray.getValues()) { + process.printToConsole("\tat " + DebuggerUtils.getValueAsString(evaluationContext, stackElement) + "\n"); } } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 44f21f1ed344..6cce75fe4edf 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -368,6 +368,8 @@ debugger.keep.step.requests=false debugger.enable.memory.view=true debugger.enable.overhead.monitor=true debugger.tree.states.depth=100 +debugger.populate.exception.stack=true +debugger.populate.exception.stack.description=Automatically fill exception's stacktrace by calling getStackTrace analyze.exceptions.on.the.fly=false analyze.exceptions.on.the.fly.description=Automatically analyze clipboard on frame activation,\ From 5a01186d94d1faccc240bb9a66b6e67a0f671f6e Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Fri, 17 Nov 2017 19:22:38 +0300 Subject: [PATCH 47/81] Fix Code style API usages in Tests/JavaDoc --- .../psi/formatter/java/AbstractJavaBlock.java | 2 +- .../java/codeInsight/JoinLinesTest.java | 149 +++++++++--------- .../autodetect/DetectIndentAndTypeTest.java | 4 +- 3 files changed, 79 insertions(+), 76 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index f9ff0993035b..279c21623c58 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -811,7 +811,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo * * @param child variable declaration child node which alignment is to be defined * @return alignment to use for the given node - * @see CodeStyleSettings#ALIGN_GROUP_FIELD_DECLARATIONS + * @see CommonCodeStyleSettings#ALIGN_GROUP_FIELD_DECLARATIONS */ private boolean shouldAlignFieldInColumns(@NotNull ASTNode child) { // The whole idea of variable declarations alignment is that complete declaration blocks which children are to be aligned hold diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java index 1fc884aa30c8..a6e2a1b72c51 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java @@ -21,8 +21,6 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; -import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.testFramework.LightCodeInsightTestCase; @@ -43,81 +41,81 @@ public class JoinLinesTest extends LightCodeInsightTestCase { public void testLiteralSCR4989() { doTest(); } public void testSCR3493() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR3493a() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR3493b() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR3493c() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR3493d() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR3493e() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; } } public void testSCR5959() { @@ -138,49 +136,54 @@ public class JoinLinesTest extends LightCodeInsightTestCase { public void testDeclarationWithInitializer() {doTest(); } public void testUnwrapCodeBlock1() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; int old = settings.IF_BRACE_FORCE; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; - settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; + settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; - settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = old; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; + settings.IF_BRACE_FORCE = old; } } public void testUnwrapCodeBlock2() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - boolean use_tab_character = settings.useTabCharacter(null); - boolean smart_tabs = settings.isSmartTabs(null); + CommonCodeStyleSettings settings = getJavaSettings(); + boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER; + boolean smart_tabs = settings.getIndentOptions().SMART_TABS; int old = settings.IF_BRACE_FORCE; try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; - settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; + settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS; doTest(); } finally { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs; - settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = old; + settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character; + settings.getIndentOptions().SMART_TABS = smart_tabs; + settings.IF_BRACE_FORCE = old; } } + @NotNull + protected CommonCodeStyleSettings getJavaSettings() { + return CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE); + } + public void testAssignmentExpression() { doTest(); } public void testReformatInsertsNewlines() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings settings = getJavaSettings(); final Element root = new Element("fake"); settings.writeExternal(root); try { - settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true; - settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true; + settings.getIndentOptions().USE_TAB_CHARACTER = true; + settings.getIndentOptions().SMART_TABS = true; settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS; settings.METHOD_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; doTest(); @@ -190,7 +193,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase { } public void testForceBrace() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + CommonCodeStyleSettings settings = getJavaSettings(); int old = settings.IF_BRACE_FORCE; try { settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS; @@ -201,8 +204,8 @@ public class JoinLinesTest extends LightCodeInsightTestCase { } public void testWrongWrapping() { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - settings.setDefaultRightMargin(80); + CommonCodeStyleSettings settings = getJavaSettings(); + settings.RIGHT_MARGIN = 80; settings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; doTest(); @@ -210,9 +213,9 @@ public class JoinLinesTest extends LightCodeInsightTestCase { public void testSubsequentJoiningAndUnexpectedTextRemoval() { // Inspired by IDEA-65342 - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); - settings.setDefaultRightMargin(50); - settings.getCommonSettings(JavaLanguage.INSTANCE).CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; + CommonCodeStyleSettings settings = getJavaSettings(); + settings.RIGHT_MARGIN = 50; + settings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; doTest(2); } @@ -223,7 +226,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase { } public void testJoiningMethodCallWhenItDoesntFit() { - CommonCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE); + CommonCodeStyleSettings settings = getJavaSettings(); settings.METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; settings.RIGHT_MARGIN = 20; doTest(); @@ -232,7 +235,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase { public void testMultipleBlockComments() { doTest(); } public void testPreserveSpaceIfOnNewLineOptionEnabled() { - CommonCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE); + CommonCodeStyleSettings settings = getJavaSettings(); settings.CATCH_ON_NEW_LINE = true; doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/autodetect/DetectIndentAndTypeTest.java b/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/autodetect/DetectIndentAndTypeTest.java index 38db528ea8f9..5861c6ea43b6 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/autodetect/DetectIndentAndTypeTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/codeStyle/autodetect/DetectIndentAndTypeTest.java @@ -83,7 +83,7 @@ public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTest public void testContinuationTab_AsTabSize() { CommonCodeStyleSettings common = mySettings.getCommonSettings(JavaLanguage.INSTANCE); - mySettings.ALIGN_MULTILINE_BINARY_OPERATION = false; + common.ALIGN_MULTILINE_BINARY_OPERATION = false; CommonCodeStyleSettings.IndentOptions indentOptions = common.getIndentOptions(); assert indentOptions != null; @@ -106,7 +106,7 @@ public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTest public void testContinuationTabs_AsDoubleTabSize() { CommonCodeStyleSettings common = mySettings.getCommonSettings(JavaLanguage.INSTANCE); - mySettings.ALIGN_MULTILINE_BINARY_OPERATION = false; + common.ALIGN_MULTILINE_BINARY_OPERATION = false; CommonCodeStyleSettings.IndentOptions indentOptions = common.getIndentOptions(); assert indentOptions != null; From 2604f77beadc96b6c2887a6da29163ceb145dd5f Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Fri, 17 Nov 2017 20:24:59 +0300 Subject: [PATCH 48/81] EA-108253 - IAE: DebugProcessImpl.createVirtualMachineInt --- .../debugger/engine/DebugProcessImpl.java | 20 ++++++++------ .../execution/remote/RemoteConfigurable.form | 2 +- .../execution/remote/RemoteConfigurable.java | 26 +++++++------------ 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 6000a4b9eda2..00a973e4a306 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -474,17 +474,21 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb if (timeoutArg != null) { timeoutArg.setValue("0"); // wait forever } - String listeningAddress = connector.startListening(myArguments); - String port = StringUtil.substringAfter(listeningAddress, ":"); - if (port != null) { - listeningAddress = port; - } - myConnection.setAddress(listeningAddress); - - myDebugProcessDispatcher.getMulticaster().connectorIsReady(); try { + String listeningAddress = connector.startListening(myArguments); + String port = StringUtil.substringAfter(listeningAddress, ":"); + if (port != null) { + listeningAddress = port; + } + myConnection.setAddress(listeningAddress); + + myDebugProcessDispatcher.getMulticaster().connectorIsReady(); + return connector.accept(myArguments); } + catch (IllegalArgumentException e) { + throw new CantRunException(e.getLocalizedMessage()); + } finally { if(myArguments != null) { try { diff --git a/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.form b/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.form index 4d422a7538c7..e2f091d39508 100644 --- a/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.form +++ b/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.form @@ -51,7 +51,7 @@ - + diff --git a/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.java b/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.java index b364546d6af5..fa0407cc14df 100644 --- a/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/remote/RemoteConfigurable.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. /* * Class RemoteConfigurable @@ -31,6 +17,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.components.fields.IntegerField; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -47,7 +34,7 @@ public class RemoteConfigurable extends SettingsEditor { private JRadioButton myRbAttach; private JTextField myAddressField; private JTextField myHostField; - private JTextField myPortField; + private IntegerField myPortField; private JPanel myShmemPanel; private JPanel mySocketPanel; private ConfigurationArgumentsHelpArea myHelpArea; @@ -147,6 +134,9 @@ public class RemoteConfigurable extends SettingsEditor { configuration.SHMEM_ADDRESS = null; } configuration.USE_SOCKET_TRANSPORT = myRbSocket.isSelected(); + if (configuration.USE_SOCKET_TRANSPORT) { + myPortField.validateContent(); + } configuration.SERVER_MODE = myRbListen.isSelected(); myModuleSelector.applyTo(configuration); } @@ -199,5 +189,7 @@ public class RemoteConfigurable extends SettingsEditor { myJDK13HelpArea.updateText("-Xnoagent -Djava.compiler=NONE " + cmdLine); } - + private void createUIComponents() { + myPortField = new IntegerField("Port", 0, 0xFFFF); + } } \ No newline at end of file From 0d3a7d82f8d171690067e3777434f1d365b58e95 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Fri, 17 Nov 2017 20:44:01 +0300 Subject: [PATCH 49/81] Win installer: update silent mode and some bug fix. IDEA-146215 SILENT Install should use admin parameters IDEA-144263 PyCharm Educational Edition silent installation IDEA-159117 Silent Install Switch Doesn't Work IDEA-169935 Silent install (/S) on Windows always installs as current user only IDEA-154213 Win10 Installer issue, obsolete shortcuts left under programs list IDEA-156081 Create icon for running idea on 64-bit JVM from start menu on windows 8/10 IDEA-157045 Support silent installation for local system user IDEA-160684 Intellij IDEA Setup Windows EXE does not allow idea64.exe to be configured (on 64bit platforms) IDEA-162504 The windows executable is missing the build number in file details IDEA-170344 Missing start menu icon in search menu on Windows 10 IDEA-170921 Can't uninstall IntelliJ IDEA Community Edition IDEA-171703 PyCharm Silent install (/S) creates neither start menu nor uninstall entries IDEA-117135 Silent installer doesn't write to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall DBE-5416 uninstalling DG on Windows 7 leaves behind 16 bogus Registry entries (invalid firewall rules) DBE-2723 Installer "uninstall" doesn't remove windows uninstall entry --- build/conf/nsis/customInstallActions.nsi | 5 + build/conf/nsis/idea.nsi | 565 +++++++++++------- build/conf/nsis/registry.nsi | 2 - .../build/customInstallActions.nsi | 76 +++ 4 files changed, 428 insertions(+), 220 deletions(-) diff --git a/build/conf/nsis/customInstallActions.nsi b/build/conf/nsis/customInstallActions.nsi index 56277ba6e209..213a2c824d45 100644 --- a/build/conf/nsis/customInstallActions.nsi +++ b/build/conf/nsis/customInstallActions.nsi @@ -1,9 +1,14 @@ !define INSTALL_OPTION_ELEMENTS 5 +!define CUSTOM_SILENT_CONFIG 0 Function customPreInstallActions DetailPrint "There are no custom pre-install actions." FunctionEnd +Function customSilentConfigReader + DetailPrint "There are no custom silent install actions." +FunctionEnd + Function customInstallActions DetailPrint "There are no custom install actions." FunctionEnd diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi index 082c0ad63ed7..819be149fb22 100644 --- a/build/conf/nsis/idea.nsi +++ b/build/conf/nsis/idea.nsi @@ -25,11 +25,26 @@ SetCompressor lzma ; http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista RequestExecutionLevel user +;------------------------------------------------------------------------------ +; Variables +;------------------------------------------------------------------------------ +Var STARTMENU_FOLDER +Var config_path +Var system_path +Var productLauncher +Var baseRegKey +Var downloadJreX86 +Var productDir +Var control_fields +Var max_fields +Var silentMode + ;------------------------------------------------------------------------------ ; include "Modern User Interface" ;------------------------------------------------------------------------------ !include "MUI2.nsh" !include "FileFunc.nsh" +!include "TextFunc.nsh" !include UAC.nsh !include "InstallOptions.nsh" !include StrFunc.nsh @@ -53,19 +68,6 @@ ReserveFile "DeleteSettings.ini" !define MUI_HEADERIMAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_HEADER_FILE}" !define MUI_WELCOMEFINISHPAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_LOGO_FILE}" -;------------------------------------------------------------------------------ -; Variables -;------------------------------------------------------------------------------ - Var STARTMENU_FOLDER - Var config_path - Var system_path - Var productLauncher - Var baseRegKey - Var downloadJreX86 - Var productDir - Var control_fields - Var max_fields - ;------------------------------------------------------------------------------ ; on GUI initialization installer checks whether IDEA is already installed ;------------------------------------------------------------------------------ @@ -117,92 +119,95 @@ ReserveFile "DeleteSettings.ini" complete: FunctionEnd + Function ${un}SplitStr -Exch $0 ; str -Push $1 ; inQ -Push $3 ; idx -Push $4 ; tmp -StrCpy $1 0 -StrCpy $3 0 + Exch $0 ; str + Push $1 ; inQ + Push $3 ; idx + Push $4 ; tmp + StrCpy $1 0 + StrCpy $3 0 loop: - StrCpy $4 $0 1 $3 - ${If} $4 == '"' - ${If} $1 <> 0 - StrCpy $0 $0 "" 1 - IntOp $3 $3 - 1 - ${EndIf} - IntOp $1 $1 ! + StrCpy $4 $0 1 $3 + ${If} $4 == '"' + ${If} $1 <> 0 + StrCpy $0 $0 "" 1 + IntOp $3 $3 - 1 ${EndIf} - ${If} $4 == '' ; The end? - StrCpy $1 0 - StrCpy $4 ',' - ${EndIf} - ${If} $4 == ',' + IntOp $1 $1 ! + ${EndIf} + ${If} $4 == '' ; The end? + StrCpy $1 0 + StrCpy $4 ',' + ${EndIf} + ${If} $4 == ',' ${AndIf} $1 = 0 - StrCpy $4 $0 $3 - StrCpy $1 $4 "" -1 - ${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|} - killspace: - IntOp $3 $3 + 1 - StrCpy $0 $0 "" $3 - StrCpy $1 $0 1 - StrCpy $3 0 - StrCmp $1 ',' killspace - Push $0 ; Remaining - Exch 4 - Pop $0 - StrCmp $4 "" 0 moreleft - Pop $4 - Pop $3 - Pop $1 - Return - moreleft: - Exch $4 - Exch 2 - Pop $1 + StrCpy $4 $0 $3 + StrCpy $1 $4 "" -1 + ${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|} + killspace: + IntOp $3 $3 + 1 + StrCpy $0 $0 "" $3 + StrCpy $1 $0 1 + StrCpy $3 0 + StrCmp $1 ',' killspace + Push $0 ; Remaining + Exch 4 + Pop $0 + StrCmp $4 "" 0 moreleft + Pop $4 Pop $3 + Pop $1 Return - ${EndIf} - IntOp $3 $3 + 1 - Goto loop + moreleft: + Exch $4 + Exch 2 + Pop $1 + Pop $3 + Return + ${EndIf} + IntOp $3 $3 + 1 + Goto loop FunctionEnd + !macroend !insertmacro INST_UNINST_SWITCH "" !insertmacro INST_UNINST_SWITCH "un." + Function InstDirState - !define InstDirState `!insertmacro InstDirStateCall` + !define InstDirState `!insertmacro InstDirStateCall` - !macro InstDirStateCall _PATH _RESULT - Push `${_PATH}` - Call InstDirState - Pop ${_RESULT} - !macroend + !macro InstDirStateCall _PATH _RESULT + Push `${_PATH}` + Call InstDirState + Pop ${_RESULT} + !macroend - Exch $0 - Push $1 - ClearErrors + Exch $0 + Push $1 + ClearErrors - FindFirst $1 $0 '$0\*.*' - IfErrors 0 +3 - StrCpy $0 -1 - goto end - StrCmp $0 '.' 0 +4 - FindNext $1 $0 - StrCmp $0 '..' 0 +2 - FindNext $1 $0 - FindClose $1 - IfErrors 0 +3 - StrCpy $0 0 - goto end - StrCpy $0 1 - - end: - Pop $1 - Exch $0 + FindFirst $1 $0 '$0\*.*' + IfErrors 0 +3 + StrCpy $0 -1 + goto end + StrCmp $0 '.' 0 +4 + FindNext $1 $0 + StrCmp $0 '..' 0 +2 + FindNext $1 $0 + FindClose $1 + IfErrors 0 +3 + StrCpy $0 0 + goto end + StrCpy $0 1 +end: + Pop $1 + Exch $0 FunctionEnd + Function SplitFirstStrPart Exch $R0 Exch @@ -212,24 +217,24 @@ Function SplitFirstStrPart StrCpy $R3 $R1 StrLen $R1 $R0 IntOp $R1 $R1 + 1 - loop: - IntOp $R1 $R1 - 1 - StrCpy $R2 $R0 1 -$R1 - StrCmp $R1 0 exit0 - StrCmp $R2 $R3 exit1 loop - exit0: +loop: + IntOp $R1 $R1 - 1 + StrCpy $R2 $R0 1 -$R1 + StrCmp $R1 0 exit0 + StrCmp $R2 $R3 exit1 loop +exit0: StrCpy $R1 "" Goto exit2 - exit1: - IntOp $R1 $R1 - 1 - StrCmp $R1 0 0 +3 +exit1: + IntOp $R1 $R1 - 1 + StrCmp $R1 0 0 +3 StrCpy $R2 "" Goto +2 - StrCpy $R2 $R0 "" -$R1 - IntOp $R1 $R1 + 1 - StrCpy $R0 $R0 -$R1 - StrCpy $R1 $R2 - exit2: + StrCpy $R2 $R0 "" -$R1 + IntOp $R1 $R1 + 1 + StrCpy $R0 $R0 -$R1 + StrCpy $R1 $R2 +exit2: Pop $R3 Pop $R2 Exch $R1 ;rest @@ -237,29 +242,31 @@ Function SplitFirstStrPart Exch $R0 ;first FunctionEnd + Function VersionSplit - !define VersionSplit `!insertmacro VersionSplitCall` + !define VersionSplit `!insertmacro VersionSplitCall` - !macro VersionSplitCall _FULL _PRODUCT _BRANCH _BUILD - Push `${_FULL}` - Call VersionSplit - Pop ${_PRODUCT} - Pop ${_BRANCH} - Pop ${_BUILD} - !macroend + !macro VersionSplitCall _FULL _PRODUCT _BRANCH _BUILD + Push `${_FULL}` + Call VersionSplit + Pop ${_PRODUCT} + Pop ${_BRANCH} + Pop ${_BUILD} + !macroend - Pop $R0 - Push "-" - Push $R0 - Call SplitFirstStrPart - Pop $R0 - Pop $R1 - Push "." - Push $R1 - Call SplitFirstStrPart - Push $R0 + Pop $R0 + Push "-" + Push $R0 + Call SplitFirstStrPart + Pop $R0 + Pop $R1 + Push "." + Push $R1 + Call SplitFirstStrPart + Push $R0 FunctionEnd + Function OnDirectoryPageLeave ;check ; - if there are no files into $INSTDIR (recursively) @@ -281,18 +288,18 @@ Function instDirEmpty ClearErrors FindFirst $1 $2 "$9\*.*" IfErrors done 0 -nextElemement: +next_elemement: ;is the element a folder? - StrCmp $2 "." getNextElement - StrCmp $2 ".." getNextElement - IfFileExists "$9\$2\*.*" 0 nextFile + StrCmp $2 "." get_next_element + StrCmp $2 ".." get_next_element + IfFileExists "$9\$2\*.*" 0 next_file Push $9 StrCpy "$9" "$9\$2" Call instDirEmpty StrCmp $9 "not empty" done 0 Pop $9 - Goto getNextElement -nextFile: + Goto get_next_element +next_file: ;is it the file property? ${If} $2 != "idea.properties" ${AndIf} $2 != "${PRODUCT_EXE_FILE}.vmoptions" @@ -301,9 +308,9 @@ nextFile: StrCpy $9 "not empty" Goto done ${EndIf} -getNextElement: +get_next_element: FindNext $1 $2 - IfErrors 0 nextElemement + IfErrors 0 next_elemement done: FindClose $1 Pop $2 @@ -311,19 +318,6 @@ done: Pop $0 FunctionEnd -Function searchJava64 - StrCpy $0 "HKLM" - StrCpy $1 "Software\JavaSoft\Java Development Kit\${JAVA_REQUIREMENT}" - StrCpy $2 "JavaHome" - SetRegView 64 - call OMReadRegStr - SetRegView 32 - StrCpy $3 "$3\bin\java.exe" - IfFileExists $3 done no_java_64 -no_java_64: - StrCpy $3 "" -done: -FunctionEnd Function ConfirmDesktopShortcut !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)" @@ -344,7 +338,7 @@ Function ConfirmDesktopShortcut ${EndIf} ; if jre x86 for the build is available then add checkbox to Installation Options dialog - StrCmp "${LINK_TO_JRE}" "null" customPreActions 0 + StrCmp "${LINK_TO_JRE}" "null" custom_pre_actions 0 inetc::head /SILENT /TOSTACK ${LINK_TO_JRE} "" /END Pop $0 ${If} $0 == "OK" @@ -358,7 +352,7 @@ Function ConfirmDesktopShortcut !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "State" $downloadJreX86 !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Text" "Download and install JRE x86 by JetBrains" ${EndIf} -customPreActions: +custom_pre_actions: Call customPreInstallActions SetRegView 32 StrCmp "${ASSOCIATION}" "NoAssociation" skip_association @@ -378,6 +372,7 @@ done: !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini" FunctionEnd + Function downloadJre !insertmacro INSTALLOPTIONS_READ $R0 "Desktop.ini" "Field 4" "State" ${If} $R0 == 1 @@ -385,10 +380,10 @@ Function downloadJre Pop $0 ${If} $0 == "OK" untgz::extract "-d" "$INSTDIR\jre32" "$TEMP\jre.tar.gz" - StrCmp $R0 "success" removeTempJre + StrCmp $R0 "success" remove_temp_jre DetailPrint "Failed to extract jre.tar.gz" MessageBox MB_OK|MB_ICONEXCLAMATION|MB_DEFBUTTON1 "Failed to extract $TEMP\jre.tar.gz" -removeTempJre: +remove_temp_jre: IfFileExists "$TEMP\jre.tar.gz" 0 done Delete "$TEMP\jre.tar.gz" ${Else} @@ -398,13 +393,11 @@ removeTempJre: done: FunctionEnd - ;------------------------------------------------------------------------------ ; configuration ;------------------------------------------------------------------------------ !insertmacro MUI_PAGE_WELCOME - Page custom uninstallOldVersionDialog !ifdef LICENSE_FILE @@ -458,51 +451,112 @@ LicenseLangString myLicenseData ${LANG_ENGLISH} "${LICENSE_FILE}.txt" LicenseLangString myLicenseData ${LANG_JAPANESE} "${LICENSE_FILE}.txt" !endif + Function .onInit SetRegView 32 + !insertmacro INSTALLOPTIONS_EXTRACT "Desktop.ini" + IfSilent silent_mode uac_elevate +silent_mode: + IntCmp ${CUSTOM_SILENT_CONFIG} 0 silent_config silent_config custom_silent_config +silent_config: + Call silentConfigReader + Goto set_reg_key +custom_silent_config: + Call customSilentConfigReader +set_reg_key: StrCpy $baseRegKey "HKCU" - IfSilent UAC_Done -UAC_Elevate: - !insertmacro UAC_RunElevated - StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user? - continue install under user - StrCmp 0 $0 0 UAC_Err ; Error? - StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper? - Quit -UAC_Err: - Abort -UAC_ElevationAborted: - StrCpy $INSTDIR "$APPDATA\${MANUFACTURER}\${PRODUCT_WITH_VER}" - goto UAC_Done -UAC_Success: - StrCmp 1 $3 UAC_Admin ;Admin? - StrCmp 3 $1 0 UAC_ElevationAborted ;Try again? - goto UAC_Elevate -UAC_Admin: - ${If} ${RunningX64} - StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${PRODUCT_WITH_VER}" - ${Else} - StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}" - ${EndIf} - SetShellVarContext all - StrCpy $baseRegKey "HKLM" -UAC_Done: + StrCmp $silentMode "admin" uac_elevate done +uac_elevate: + !insertmacro UAC_RunElevated + StrCmp 1223 $0 uac_elevation_aborted ; UAC dialog aborted by user? - continue install under user + StrCmp 0 $0 0 uac_err ; Error? + StrCmp 1 $1 0 uac_success ;Are we the real deal or just the wrapper? + Quit +uac_err: + Abort +uac_elevation_aborted: + IfSilent done set_install_dir +set_install_dir: + StrCpy $INSTDIR "$APPDATA\${MANUFACTURER}\${PRODUCT_WITH_VER}" + goto done +uac_success: + StrCmp 1 $3 uac_admin ;Admin? + StrCmp 3 $1 0 uac_elevation_aborted ;Try again? + goto uac_elevate +uac_admin: + IfSilent uac_all_users set_install_dir_admin_mode +set_install_dir_admin_mode: + ${If} ${RunningX64} + StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${PRODUCT_WITH_VER}" + ${Else} + StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}" + ${EndIf} +uac_all_users: + SetShellVarContext all + StrCpy $baseRegKey "HKLM" +done: ; !insertmacro MUI_LANGDLL_DISPLAY FunctionEnd + +Function silentConfigReader + ${GetParameters} $R0 + ClearErrors + + ${GetOptions} $R0 /CONFIG= $R1 + IfErrors no_silent_config + + ${ConfigRead} "$R1" "mode=" $R0 + StrCpy $silentMode "user" + IfErrors launcher_32 + StrCpy $silentMode $R0 + +launcher_32: + ClearErrors + ${ConfigRead} "$R1" "launcher32=" $R3 + IfErrors launcher_64 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "State" $R3 + +launcher_64: + ClearErrors + ${ConfigRead} "$R1" "launcher64=" $R3 + IfErrors download_jre32 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "State" $R3 + +download_jre32: + ClearErrors + ${ConfigRead} "$R1" "jre32=" $R3 + IfErrors associations + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "State" $R3 + +associations: + ClearErrors + StrCmp "${ASSOCIATION}" "NoAssociation" done + !insertmacro INSTALLOPTIONS_READ $R0 "Desktop.ini" "Settings" "NumFields" + push "${ASSOCIATION}" +loop: + call SplitStr + Pop $0 + StrCmp $0 "" update_settings + ClearErrors + ${ConfigRead} "$R1" "$0=" $R3 + IfErrors update_settings + IntOp $R0 $R0 + 1 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "State" $R3 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" + goto loop + +update_settings: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" +no_silent_config: +done: +FunctionEnd + Function checkVersion StrCpy $2 "" StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" -; ${If} $0 == "HKLM" -; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" -; Push $0 -; call winVersion -; ${If} $0 == "1" -; StrCpy $1 "Software\Wow6432Node\${MANUFACTURER}\${PRODUCT_REG_VER}" -; ${Else} -; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" -; ${EndIf} -; Pop $0 -; ${EndIf} Call OMReadRegStr IfFileExists $3\bin\${PRODUCT_EXE_FILE} check_version Goto Done @@ -533,7 +587,7 @@ FunctionEnd Function uninstallOldVersion - ; uninstallation mode + ;uninstallation mode !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 2" "State" ${If} $9 == "1" ExecWait '"$3\bin\Uninstall.exe" /S' @@ -544,7 +598,7 @@ Function uninstallOldVersion goto complete uninstall: ;previous installation has been removed - ;customer decided to keep properties? + ;customer has decided to keep properties? IfFileExists $3\bin\idea.properties saveProperties fullRemove saveProperties: Delete "$3\bin\Uninstall.exe" @@ -563,12 +617,12 @@ StrCpy $6 "" loop: IntOp $7 $7 + 1 ${If} $8 >= $7 - !insertmacro INSTALLOPTIONS_READ $6 "UninstallOldVersions.ini" "Field $7" "Text" - ${If} $6 == $3 - ;found the same value in list of installations - StrCpy $6 "duplicated" - Goto finish - ${EndIf} + !insertmacro INSTALLOPTIONS_READ $6 "UninstallOldVersions.ini" "Field $7" "Text" + ${If} $6 == $3 + ;found the same value in list of installations + StrCpy $6 "duplicated" + Goto finish + ${EndIf} Goto loop ${EndIf} finish: @@ -609,6 +663,7 @@ ${If} $0 == "HKLM" StrCpy $4 0 Goto get_installation_info ${EndIf} + complete: !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Settings" "NumFields" "$8" ${If} $8 > $control_fields @@ -710,7 +765,6 @@ continue_enum_versions_hkcu: Goto enum_versions_hkcu end_enum_versions_hkcu: - StrCpy $0 "0" # registry key index enum_versions_hklm: @@ -725,15 +779,14 @@ continue_enum_versions_hklm: Goto enum_versions_hklm end_enum_versions_hklm: - StrCmp $INSTDIR "" 0 skip_default_instdir ${If} ${RunningX64} StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}" ${Else} StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}" ${EndIf} -skip_default_instdir: +skip_default_instdir: Pop $5 Pop $4 Pop $3 @@ -763,22 +816,60 @@ createRegistration: FunctionEnd Function ProductAssociation + push $0 + push $1 + push $2 + push $3 + StrCpy $2 "" + StrCmp $baseRegKey "HKLM" admin user +admin: + StrCpy $0 HKCR + StrCpy $R5 ${PRODUCT_PATHS_SELECTOR} + goto back_up +user: + StrCpy $0 HKCU + StrCpy $R4 "Software\Classes\$R4" + StrCpy $R5 "Software\Classes\${PRODUCT_PATHS_SELECTOR}" +back_up: ; back up old value of an association - ReadRegStr $1 HKCR $R4 "" - StrCmp $1 "" skip_backup - StrCmp $1 ${PRODUCT_PATHS_SELECTOR} skip_backup - WriteRegStr HKCR $R4 "backup_val" $1 + StrCpy $1 $R4 +call OMReadRegStr + StrCmp $3 "" skip_backup + StrCmp $3 ${PRODUCT_PATHS_SELECTOR} skip_backup + StrCpy $2 "backup_val" + Call OMWriteRegStr skip_backup: - WriteRegStr HKCR $R4 "" "${PRODUCT_PATHS_SELECTOR}" - ReadRegStr $0 HKCR ${PRODUCT_PATHS_SELECTOR} "" - StrCmp $0 "" 0 command_exists - WriteRegStr HKCR ${PRODUCT_PATHS_SELECTOR} "" "${PRODUCT_FULL_NAME}" - WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell" "" "open" - WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\DefaultIcon" "" "$productLauncher,0" + StrCpy $2 "" + StrCpy $3 ${PRODUCT_PATHS_SELECTOR} + Call OMWriteRegStr + StrCpy $1 ${PRODUCT_PATHS_SELECTOR} + StrCpy $2 "" + Call OMReadRegStr + StrCmp $3 "" 0 command_exists + StrCpy $2 "" + StrCpy $3 "${PRODUCT_FULL_NAME}" + Call OMWriteRegStr + StrCpy $1 "$R5\shell" + StrCpy $2 "" + StrCpy $3 "open" + Call OMWriteRegStr + StrCpy $1 "$R5\DefaultIcon" + StrCpy $2 "" + StrCpy $3 "$productLauncher,0" + Call OMWriteRegStr command_exists: - WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\DefaultIcon" "" " $productLauncher,0" - WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell\open\command" "" \ - '"$productLauncher" "%1"' + StrCpy $1 "$R5\DefaultIcon" + StrCpy $2 "" + StrCpy $3 " $productLauncher,0" + Call OMWriteRegStr + StrCpy $1 "$R5\shell\open\command" + StrCpy $2 "" + StrCpy $3 '"$productLauncher" "%1"' + Call OMWriteRegStr + pop $3 + pop $2 + pop $1 + pop $0 FunctionEnd ;------------------------------------------------------------------------------ @@ -786,20 +877,22 @@ FunctionEnd ;------------------------------------------------------------------------------ Section "IDEA Files" CopyIdeaFiles CreateDirectory $INSTDIR + Call customInstallActions + SetRegView 32 -; set up a launcher for associations + ;define launcher in accordingly to OS version ${If} ${RunningX64} StrCpy $productLauncher "$INSTDIR\bin\${PRODUCT_EXE_FILE_64}" ${Else} StrCpy $productLauncher "$INSTDIR\bin\${PRODUCT_EXE_FILE}" ${EndIf} + DetailPrint "productLauncher: $productLauncher" StrCmp "${LINK_TO_JRE}" "null" shortcuts 0 -; download and install JRE x86 + ;download and install JRE x86 Call downloadJre shortcuts: -; create shortcuts !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 2" "State" StrCmp $R2 1 "" exe_64 CreateShortCut "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ @@ -823,11 +916,7 @@ get_user_choice: next_association: IntOp $R2 $R2 + 1 IntCmp $R1 $R2 get_user_choice done get_user_choice - done: - Call customInstallActions - SetRegView 32 - ; registration application to be presented in Open With list call ProductRegistration !insertmacro MUI_STARTMENU_WRITE_BEGIN Application @@ -867,10 +956,9 @@ done: !undef Index skip_ipr: - ; readonly section SectionIn RO -!include "idea_win.nsh" + !include "idea_win.nsh" SetOutPath $INSTDIR\bin File "${PRODUCT_PROPERTIES_FILE}" @@ -1012,16 +1100,44 @@ UAC_Done: FunctionEnd -Function un.ReturnBackupRegValue +Function un.RestoreBackupRegValue ;replace Default str with the backup value (if there is the one) and then delete backup ; $1 - key (for example ".java") ; $2 - name (for example "backup_val") Push $0 - ReadRegStr $0 HKCR $1 $2 - StrCmp $0 "" "noBackup" - WriteRegStr HKCR $1 "" $0 - DeleteRegValue HKCR $1 $2 -noBackup: + Push $3 + + StrCmp $baseRegKey "HKLM" admin user +admin: + StrCpy $0 HKCR + goto read_backup_value +user: + StrCpy $0 HKCU + StrCpy $1 "Software\Classes\$1" + +read_backup_value: + call un.OMReadRegStr + StrCmp $3 "" no_backup restore_backup + +no_backup: + ;clean default value if it contains current product info + StrCpy $2 "" + call un.OMReadRegStr + StrCmp $4 $3 0 done + call un.OMDeleteRegValue + goto done + +restore_backup: + StrCmp $3 $4 remove_backup 0 + push $2 + StrCpy $2 "" + call un.OMWriteRegStr + pop $2 +remove_backup: + call un.OMDeleteRegValue + +done: + Pop $3 Pop $0 FunctionEnd @@ -1225,7 +1341,7 @@ skip_delete_settings: StrCmp $R9 "" registry StrCpy $5 "Software\${MANUFACTURER}" shortcuts: - ;the user has the admin rights + ;user has the admin rights IfFileExists "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" keep_current_user SetShellVarContext all keep_current_user: @@ -1244,13 +1360,17 @@ registry: StrCmp "${ASSOCIATION}" "NoAssociation" finish_uninstall push "${ASSOCIATION}" loop: + StrCpy $2 "backup_val" + StrCpy $4 "${PRODUCT_PATHS_SELECTOR}" call un.SplitStr Pop $0 StrCmp $0 "" finish_uninstall + + ;restore backup association(s) StrCpy $1 $0 - StrCpy $2 "backup_val" - Call un.ReturnBackupRegValue + Call un.RestoreBackupRegValue goto loop + finish_uninstall: StrCpy $0 $baseRegKey StrCpy $1 "$5\${PRODUCT_REG_VER}" @@ -1275,8 +1395,16 @@ finish: StrCpy $0 "HKCR" StrCpy $1 "Applications\${PRODUCT_EXE_FILE}" Call un.OMDeleteRegKey + StrCmp $baseRegKey "HKLM" admin user +admin: StrCpy $0 "HKCR" StrCpy $1 "${PRODUCT_PATHS_SELECTOR}" + goto delete_association +user: + StrCpy $0 "HKCU" + StrCpy $1 "Software\Classes\${PRODUCT_PATHS_SELECTOR}" +delete_association: + ; remove product information which was used for association(s) Call un.OMDeleteRegKey StrCpy $0 "${MUI_LANGDLL_REGISTRY_ROOT}" @@ -1287,6 +1415,7 @@ finish: StrCpy $1 "IntelliJIdeaProjectFile\DefaultIcon" StrCpy $2 "" call un.OMReadRegStr + StrCmp $3 "$productDir\${PRODUCT_EXE_FILE},0" remove_IntelliJIdeaProjectFile done remove_IntelliJIdeaProjectFile: StrCpy $1 "IntelliJIdeaProjectFile" diff --git a/build/conf/nsis/registry.nsi b/build/conf/nsis/registry.nsi index 99a47ce2715d..baff6702852a 100644 --- a/build/conf/nsis/registry.nsi +++ b/build/conf/nsis/registry.nsi @@ -81,8 +81,6 @@ Function ${un}OMReadRegStr hkcr: ReadRegStr $3 HKCR $1 $2 done: - IfErrors 0 +2 - DetailPrint "ERROR: $0, $1, $2" FunctionEnd ; ----------------------------------------------------------------------------- diff --git a/python/educational-python/build/customInstallActions.nsi b/python/educational-python/build/customInstallActions.nsi index 15a3f1c144a8..10ab4ec280ab 100644 --- a/python/educational-python/build/customInstallActions.nsi +++ b/python/educational-python/build/customInstallActions.nsi @@ -1,6 +1,7 @@ !include "TextFunc.nsh" !define INSTALL_OPTION_ELEMENTS 8 !define PYTHON_VERSIONS 4 +!define CUSTOM_SILENT_CONFIG 1 ${StrTok} @@ -41,6 +42,81 @@ checkPython3: done: FunctionEnd + +Function customSilentConfigReader + Call customPreInstallActions + + ${GetParameters} $R0 + ClearErrors + + ${GetOptions} $R0 /CONFIG= $R1 + IfErrors no_silent_config + + ${ConfigRead} "$R1" "mode=" $R0 + StrCpy $silentMode "user" + IfErrors run_in_user_mode + StrCpy $silentMode $R0 + +run_in_user_mode: + + ClearErrors + ${ConfigRead} "$R1" "launcher32=" $R3 + IfErrors launcher_64 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "State" $R3 + +launcher_64: + ClearErrors + ${ConfigRead} "$R1" "launcher64=" $R3 + IfErrors download_jre32 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "State" $R3 + +download_jre32: + ClearErrors + ${ConfigRead} "$R1" "jre32=" $R3 + IfErrors download_python2 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "State" $R3 + +download_python2: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 6" "State" 0 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 7" "State" 0 + ClearErrors + ${ConfigRead} "$R1" "python2=" $R3 + IfErrors download_python3 + StrCmp $R3 "1" 0 download_python3 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 6" "State" $R3 + +download_python3: + ClearErrors + ${ConfigRead} "$R1" "python3=" $R3 + IfErrors associations + StrCmp $R3 "1" 0 associations + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 7" "State" $R3 + +associations: + StrCmp "${ASSOCIATION}" "NoAssociation" done + !insertmacro INSTALLOPTIONS_READ $R0 "Desktop.ini" "Settings" "NumFields" + push "${ASSOCIATION}" +loop: + call SplitStr + Pop $0 + StrCmp $0 "" update_settings + ClearErrors + ${ConfigRead} "$R1" "$0=" $R3 + IfErrors update_settings + IntOp $R0 $R0 + 1 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "State" $R3 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" + goto loop + +update_settings: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" +no_silent_config: +done: +FunctionEnd + + Function customInstallActions ${LineSum} "$TEMP\python.txt" $R0 IfErrors cantOpenFile From a3923474f2e4ccf6a3a055b253501f24e3d9a840 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 17 Nov 2017 19:00:09 +0100 Subject: [PATCH 50/81] [java] quick fixes for using or exporting unused services (IDEA-179646) --- .../impl/analysis/ModuleHighlightUtil.java | 29 +++++++++------- .../impl/quickfix/AddModuleDirectiveFix.kt | 12 ++++++- .../src/messages/QuickFixBundle.properties | 1 + .../com/intellij/psi/PsiUsesStatement.java | 17 ++-------- .../impl/compiled/ClsUsesStatementImpl.java | 21 ++++-------- .../psi/impl/source/PsiUsesStatementImpl.java | 34 ++++++++----------- .../daemon/ModuleHighlightingTest.kt | 3 ++ .../daemon/quickFix/AddModuleDirectiveTest.kt | 28 ++++++++++++++- 8 files changed, 82 insertions(+), 63 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index baa17ba5854b..f9a3cf893f1c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -226,20 +226,25 @@ public class ModuleHighlightUtil { static List checkUnusedServices(@NotNull PsiJavaModule module, @NotNull PsiFile file) { List results = ContainerUtil.newSmartList(); - Set exports = JBIterable.from(module.getExports()).map(st -> refText(st.getPackageReference())).filter(Objects::nonNull).toSet(); - Set uses = JBIterable.from(module.getUses()).map(st -> qName(st.getClassReference())).filter(Objects::nonNull).toSet(); - Module host = findModuleForFile(file); if (host != null) { - for (PsiProvidesStatement statement : module.getProvides()) { - PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); - if (ref != null) { - PsiElement target = ref.resolve(); - if (target instanceof PsiClass && findModuleForFile(target.getContainingFile()) == host) { - String className = qName(ref), packageName = StringUtil.getPackageName(className); - if (!exports.contains(packageName) && !uses.contains(className)) { - String message = JavaErrorMessages.message("module.service.unused"); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(ref)).descriptionAndTooltip(message).create()); + List provides = JBIterable.from(module.getProvides()).toList(); + if (!provides.isEmpty()) { + Set exports = JBIterable.from(module.getExports()).map(PsiPackageAccessibilityStatement::getPackageName).filter(Objects::nonNull).toSet(); + Set uses = JBIterable.from(module.getUses()).map(PsiUsesStatement::getClassName).filter(Objects::nonNull).toSet(); + for (PsiProvidesStatement statement : provides) { + PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); + if (ref != null) { + PsiElement target = ref.resolve(); + if (target instanceof PsiClass && findModuleForFile(target.getContainingFile()) == host) { + String className = qName(ref), packageName = StringUtil.getPackageName(className); + if (!exports.contains(packageName) && !uses.contains(className)) { + String message = JavaErrorMessages.message("module.service.unused"); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(ref)).descriptionAndTooltip(message).create(); + QuickFixAction.registerQuickFixAction(info, new AddExportsDirectiveFix(module, packageName, "")); + QuickFixAction.registerQuickFixAction(info, new AddUsesDirectiveFix(module, className)); + results.add(info); + } } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt index 5cfb1b98b5c8..1fe5eccfe9b1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt @@ -40,11 +40,21 @@ class AddExportsDirectiveFix(module: PsiJavaModule, if (existing == null) { PsiUtil.addModuleStatement(module, PsiKeyword.EXPORTS + ' ' + packageName) } - else { + else if (!targetName.isEmpty()) { val targets = existing.moduleReferences.map { it.referenceText } if (!targets.isEmpty() && targetName !in targets) { existing.add(PsiElementFactory.SERVICE.getInstance(project).createModuleReferenceFromText(targetName)) } } } +} + +class AddUsesDirectiveFix(module: PsiJavaModule, private val svcName: String) : AddModuleDirectiveFix(module) { + override fun getText() = QuickFixBundle.message("module.info.add.uses.name", svcName) + + override fun invoke(project: Project, file: PsiFile, editor: Editor?, module: PsiJavaModule) { + if (module.uses.find { svcName == it.className } == null) { + PsiUtil.addModuleStatement(module, PsiKeyword.USES + ' ' + svcName) + } + } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/messages/QuickFixBundle.properties b/java/java-analysis-impl/src/messages/QuickFixBundle.properties index 2dc6a985ffc9..84644bb302ee 100644 --- a/java/java-analysis-impl/src/messages/QuickFixBundle.properties +++ b/java/java-analysis-impl/src/messages/QuickFixBundle.properties @@ -308,6 +308,7 @@ extract.side.effects.family.name=Delete statement extracting side effects module.info.add.directive.family.name=Add a directive to module-info.java module.info.add.requires.name=Add ''requires {0}'' directive to module-info.java module.info.add.exports.name=Add ''exports {0}'' directive to module-info.java +module.info.add.uses.name=Add ''uses {0}'' directive to module-info.java collection.to.array.text=Apply conversion ''.toArray({0})'' collection.to.array.family.name=Apply conversion '.toArray()' diff --git a/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java index 8e2567a70dc4..3ff0b9f86e1b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi; import org.jetbrains.annotations.Nullable; @@ -26,4 +12,5 @@ public interface PsiUsesStatement extends PsiStatement { PsiUsesStatement[] EMPTY_ARRAY = new PsiUsesStatement[0]; @Nullable PsiJavaCodeReferenceElement getClassReference(); + @Nullable String getClassName(); } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java index 87b7c324dcf0..7c91af3fafb7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.compiled; import com.intellij.openapi.util.text.StringUtil; @@ -37,6 +23,11 @@ public class ClsUsesStatementImpl extends ClsRepositoryPsiElementpkg.m2.C2; }", arrayOf("AddExportsDirectiveFix")) fixes("pkg/main/C.java", "package pkg.main;\nimport pkg.m2.C2;", arrayOf("AddExportsDirectiveFix")) + + addFile("pkg/main/S.java", "package pkg.main;\npublic class S { }") + fixes("module M { provides pkg.main.S with pkg.main.S; }", arrayOf("AddExportsDirectiveFix", "AddUsesDirectiveFix")) } fun testPackageAccessibility() = doTestPackageAccessibility(moduleFileInTests = false, checkFileInTests = false) diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddModuleDirectiveTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddModuleDirectiveTest.kt index 72932ddb526c..723326f754e5 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddModuleDirectiveTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddModuleDirectiveTest.kt @@ -3,6 +3,7 @@ package com.intellij.java.codeInsight.daemon.quickFix import com.intellij.codeInsight.daemon.impl.quickfix.AddExportsDirectiveFix import com.intellij.codeInsight.daemon.impl.quickfix.AddRequiresDirectiveFix +import com.intellij.codeInsight.daemon.impl.quickfix.AddUsesDirectiveFix import com.intellij.codeInsight.intention.IntentionAction import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase import com.intellij.openapi.command.WriteCommandAction @@ -57,6 +58,11 @@ class AddModuleDirectiveTest : LightJava9ModulesCodeInsightFixtureTestCase() { "module M { exports pkg.m to M1, M2; }", "module M { exports pkg.m to M1, M2; }") + fun testNoExportsToUnnamed() = doExportsTest( + "module M { exports pkg.m to M1; }", + "module M { exports pkg.m to M1; }", + target = "") + fun testExportsExtendsOther() = doExportsTest( "module M {\n" + " exports pkg.m to M1;\n" + @@ -73,8 +79,28 @@ class AddModuleDirectiveTest : LightJava9ModulesCodeInsightFixtureTestCase() { " exports pkg.m to M1, M2\n" + "}") + fun testNewUses() = doUsesTest( + "module M { }", + "module M {\n" + + " uses pkg.m.C;\n" + + "}") + + fun testUsesAfterOther() = doUsesTest( + "module M {\n" + + " uses pkg.m.B;\n" + + "}", + "module M {\n" + + " uses pkg.m.B;\n" + + " uses pkg.m.C;\n" + + "}") + + fun testNoDuplicateUses() = doUsesTest( + "module M { uses pkg.m.C; }", + "module M { uses pkg.m.C; }") + private fun doRequiresTest(text: String, expected: String) = doTest(text, { AddRequiresDirectiveFix(it, "M2") }, expected) - private fun doExportsTest(text: String, expected: String) = doTest(text, { AddExportsDirectiveFix(it, "pkg.m", "M2") }, expected) + private fun doExportsTest(text: String, expected: String, target: String = "M2") = doTest(text, { AddExportsDirectiveFix(it, "pkg.m", target) }, expected) + private fun doUsesTest(text: String, expected: String) = doTest(text, { AddUsesDirectiveFix(it, "pkg.m.C") }, expected) private fun doTest(text: String, fix: (PsiJavaModule) -> IntentionAction, expected: String) { val file = myFixture.configureByText("module-info.java", text) as PsiJavaFile From 65c8cf7b19da383b849d933b38d99feca4896301 Mon Sep 17 00:00:00 2001 From: Mari Baburina Date: Fri, 17 Nov 2017 20:59:04 +0300 Subject: [PATCH 51/81] [gui-test] added CLion GUI test infrastructure --- .../src/com/intellij/testGuiFramework/impl/GuiTestRule.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestRule.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestRule.kt index e9d08705934a..6749b0afd88b 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestRule.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestRule.kt @@ -65,6 +65,8 @@ import java.util.concurrent.TimeUnit class GuiTestRule : TestRule { + var CREATE_NEW_PROJECT_ACTION_NAME = "Create New Project" + private val myRobotTestRule = RobotTestRule() private val myFatalErrorsFlusher = FatalErrorsFlusher() private var myProjectPath: File? = null @@ -156,12 +158,12 @@ class GuiTestRule : TestRule { } private fun returnToTheFirstStepOfWelcomeFrame() { - val welcomeFrameFixture = WelcomeFrameFixture.find(robot()); + val welcomeFrameFixture = WelcomeFrameFixture.find(robot()) val tenSec = org.fest.swing.timing.Timeout.timeout(10, TimeUnit.SECONDS) fun isFirstStep(): Boolean { return try { - val actionLinkFixture = ActionLinkFixture.findActionLinkByName("Create New Project", robot(), welcomeFrameFixture.target(), tenSec) + val actionLinkFixture = ActionLinkFixture.findActionLinkByName(CREATE_NEW_PROJECT_ACTION_NAME, robot(), welcomeFrameFixture.target(), tenSec) actionLinkFixture.target().isShowing } catch (componentLookupException: ComponentLookupException) { false From 79f599f2a384e1fa0804ac136de7a44dc7b96e28 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 17 Nov 2017 19:51:30 +0100 Subject: [PATCH 52/81] [java] drops incorrect PSI method; optimizes ref operations in ModuleHighlightUtil --- .../impl/analysis/ModuleHighlightUtil.java | 56 +++++-------------- .../impl/quickfix/AddModuleDirectiveFix.kt | 2 +- .../com/intellij/psi/PsiUsesStatement.java | 1 - .../impl/compiled/ClsUsesStatementImpl.java | 5 -- .../psi/impl/source/PsiUsesStatementImpl.java | 13 ----- 5 files changed, 14 insertions(+), 63 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index f9a3cf893f1c..3e5815fe2abe 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -171,47 +171,21 @@ public class ModuleHighlightUtil { @NotNull static List checkDuplicateStatements(@NotNull PsiJavaModule module) { List results = ContainerUtil.newSmartList(); - - checkDuplicateRefs( - module.getRequires(), - st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText), - "module.duplicate.requires", - results); - - checkDuplicateRefs( - module.getExports(), - st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), - "module.duplicate.exports", - results); - - checkDuplicateRefs( - module.getOpens(), - st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), - "module.duplicate.opens", - results); - - checkDuplicateRefs( - module.getUses(), - st -> Optional.ofNullable(st.getClassReference()).map(ModuleHighlightUtil::qName), - "module.duplicate.uses", - results); - - checkDuplicateRefs( - module.getProvides(), - st -> Optional.ofNullable(st.getInterfaceReference()).map(ModuleHighlightUtil::qName), - "module.duplicate.provides", - results); - + checkDuplicateRefs(module.getRequires(), st -> st.getModuleName(), "module.duplicate.requires", results); + checkDuplicateRefs(module.getExports(), st -> st.getPackageName(), "module.duplicate.exports", results); + checkDuplicateRefs(module.getOpens(), st -> st.getPackageName(), "module.duplicate.opens", results); + checkDuplicateRefs(module.getUses(), st -> qName(st.getClassReference()), "module.duplicate.uses", results); + checkDuplicateRefs(module.getProvides(), st -> qName(st.getInterfaceReference()), "module.duplicate.provides", results); return results; } - private static void checkDuplicateRefs(Iterable statements, - Function> ref, - @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key, - List results) { + private static void checkDuplicateRefs(Iterable statements, + Function ref, + @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key, + List results) { Set filter = ContainerUtil.newTroveSet(); for (T statement : statements) { - String refText = ref.apply(statement).orElse(null); + String refText = ref.apply(statement); if (refText != null && !filter.add(refText)) { String message = JavaErrorMessages.message(key, refText); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create(); @@ -231,7 +205,7 @@ public class ModuleHighlightUtil { List provides = JBIterable.from(module.getProvides()).toList(); if (!provides.isEmpty()) { Set exports = JBIterable.from(module.getExports()).map(PsiPackageAccessibilityStatement::getPackageName).filter(Objects::nonNull).toSet(); - Set uses = JBIterable.from(module.getUses()).map(PsiUsesStatement::getClassName).filter(Objects::nonNull).toSet(); + Set uses = JBIterable.from(module.getUses()).map(st -> qName(st.getClassReference())).filter(Objects::nonNull).toSet(); for (PsiProvidesStatement statement : provides) { PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); if (ref != null) { @@ -254,10 +228,6 @@ public class ModuleHighlightUtil { return results; } - private static String refText(PsiJavaCodeReferenceElement ref) { - return ref != null ? PsiNameHelper.getQualifiedClassName(ref.getText(), true) : null; - } - private static String qName(PsiJavaCodeReferenceElement ref) { return ref != null ? ref.getQualifiedName() : null; } @@ -329,13 +299,13 @@ public class ModuleHighlightUtil { if (module != null) { PsiElement target = refElement.resolve(); PsiDirectory[] directories = target instanceof PsiPackage ? ((PsiPackage)target).getDirectories(module.getModuleScope(false)) : null; - String packageName = refText(refElement); + String packageName = statement.getPackageName(); HighlightInfoType type = statement.getRole() == Role.OPENS ? HighlightInfoType.WARNING : HighlightInfoType.ERROR; if (directories == null || directories.length == 0) { String message = JavaErrorMessages.message("package.not.found", packageName); return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create(); } - if (PsiUtil.isPackageEmpty(directories, packageName)) { + if (packageName != null && PsiUtil.isPackageEmpty(directories, packageName)) { String message = JavaErrorMessages.message("package.is.empty", packageName); return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create(); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt index 1fe5eccfe9b1..c87df4242386 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDirectiveFix.kt @@ -53,7 +53,7 @@ class AddUsesDirectiveFix(module: PsiJavaModule, private val svcName: String) : override fun getText() = QuickFixBundle.message("module.info.add.uses.name", svcName) override fun invoke(project: Project, file: PsiFile, editor: Editor?, module: PsiJavaModule) { - if (module.uses.find { svcName == it.className } == null) { + if (module.uses.find { svcName == it.classReference?.qualifiedName } == null) { PsiUtil.addModuleStatement(module, PsiKeyword.USES + ' ' + svcName) } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java index 3ff0b9f86e1b..50227e2d677a 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiUsesStatement.java @@ -12,5 +12,4 @@ public interface PsiUsesStatement extends PsiStatement { PsiUsesStatement[] EMPTY_ARRAY = new PsiUsesStatement[0]; @Nullable PsiJavaCodeReferenceElement getClassReference(); - @Nullable String getClassName(); } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java index 7c91af3fafb7..fcd0e2d87db8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsUsesStatementImpl.java @@ -23,11 +23,6 @@ public class ClsUsesStatementImpl extends ClsRepositoryPsiElement Date: Fri, 17 Nov 2017 21:51:29 +0300 Subject: [PATCH 53/81] use containing file instead of element to update Project View --- .../ProjectViewPsiTreeChangeListener.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewPsiTreeChangeListener.java b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewPsiTreeChangeListener.java index 03e43d8fc8d4..b8393940daea 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewPsiTreeChangeListener.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectViewPsiTreeChangeListener.java @@ -28,6 +28,8 @@ import org.jetbrains.annotations.NotNull; import javax.swing.tree.DefaultMutableTreeNode; +import static com.intellij.util.ObjectUtils.notNull; + public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdapter { private final PsiModificationTracker myModificationTracker; private long myOutOfCodeBlockModificationCount; @@ -105,7 +107,7 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap break; } - if (addSubtreeToUpdateByElement(parent)) { + if (addSubtreeToUpdateByElementFile(parent)) { break; } @@ -122,8 +124,8 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap addSubtreeToUpdateByRoot(); } else if (propertyName.equals(PsiTreeChangeEvent.PROP_WRITABLE)){ - if (!addSubtreeToUpdateByElement(element) && element instanceof PsiFile) { - addSubtreeToUpdateByElement(((PsiFile)element).getContainingDirectory()); + if (!addSubtreeToUpdateByElementFile(element) && element instanceof PsiFile) { + addSubtreeToUpdateByElementFile(((PsiFile)element).getContainingDirectory()); } } else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_NAME) || propertyName.equals(PsiTreeChangeEvent.PROP_DIRECTORY_NAME)){ @@ -132,11 +134,11 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap return; } final PsiElement parent = element.getParent(); - if (parent == null || !addSubtreeToUpdateByElement(parent)) { - addSubtreeToUpdateByElement(element); + if (parent == null || !addSubtreeToUpdateByElementFile(parent)) { + addSubtreeToUpdateByElementFile(element); } } - else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_TYPES)){ + else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_TYPES) || propertyName.equals(PsiTreeChangeEvent.PROP_UNLOADED_PSI)) { addSubtreeToUpdateByRoot(); } } @@ -151,4 +153,8 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap AbstractTreeUpdater updater = getUpdater(); return updater != null && updater.addSubtreeToUpdateByElement(element); } + + private boolean addSubtreeToUpdateByElementFile(PsiElement element) { + return element != null && addSubtreeToUpdateByElement(notNull(element.getContainingFile(), element)); + } } From c22d69b11e9faee73c32035415468eeec5d7eca2 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 17 Nov 2017 20:04:59 +0100 Subject: [PATCH 54/81] [performance] cache icon that IDE uses often --- .../intellij/openapi/actionSystem/ex/ComboBoxAction.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java index 6bc25b8d46c3..681823348df0 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java @@ -49,10 +49,14 @@ import java.beans.PropertyChangeListener; public abstract class ComboBoxAction extends AnAction implements CustomComponentAction { private static Icon myIcon = null; private static Icon myDisabledIcon = null; + private static Icon myWin10ComboDropTriagleIcon = null; public static Icon getArrowIcon(boolean enabled) { if (UIUtil.isUnderWin10LookAndFeel()) { - return IconLoader.getIcon("/com/intellij/ide/ui/laf/icons/win10/comboDropTriangle.png"); + if (myWin10ComboDropTriagleIcon == null) { + myWin10ComboDropTriagleIcon = IconLoader.getIcon("/com/intellij/ide/ui/laf/icons/win10/comboDropTriangle.png"); + } + return myWin10ComboDropTriagleIcon; } Icon icon = UIUtil.isUnderDarcula() ? AllIcons.General.ComboArrow : AllIcons.General.ComboBoxButtonArrow; if (myIcon != icon) { From a7e57430802046d65c3e1e164969dbeec5891fc7 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 17 Nov 2017 22:08:25 +0100 Subject: [PATCH 55/81] findResources("SomeDir/") fails (IDEA-182329) --- .../src/com/intellij/util/lang/ClassPath.java | 13 +++--- .../util/lang/UrlClassLoaderTest.java | 42 ++++++++++++++++++- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/platform/util/src/com/intellij/util/lang/ClassPath.java b/platform/util/src/com/intellij/util/lang/ClassPath.java index 03a76797f817..e9dc13257636 100644 --- a/platform/util/src/com/intellij/util/lang/ClassPath.java +++ b/platform/util/src/com/intellij/util/lang/ClassPath.java @@ -266,19 +266,16 @@ public class ClassPath { List loaders = null; if (myCanUseCache && myAllUrlsWereProcessed) { - boolean nameIsDirectory = name.endsWith("/"); - Collection loadersSet = nameIsDirectory ? new SmartList() : new LinkedHashSet(); + Collection loadersSet = new LinkedHashSet(); myCache.iterateLoaders(name, ourLoaderCollector, loadersSet, this); - if (!nameIsDirectory) { + if (name.endsWith("/")) { + myCache.iterateLoaders(name.substring(0, name.length() - 1), ourLoaderCollector, loadersSet, this); + } else { myCache.iterateLoaders(name.concat("/"), ourLoaderCollector, loadersSet, this); } - if (nameIsDirectory) { - loaders = (List)loadersSet; - } else { - loaders = new ArrayList(loadersSet); - } + loaders = new ArrayList(loadersSet); } myLoaders = loaders; diff --git a/platform/util/testSrc/com/intellij/util/lang/UrlClassLoaderTest.java b/platform/util/testSrc/com/intellij/util/lang/UrlClassLoaderTest.java index 89c5e664636c..fd3cd2a2f56b 100644 --- a/platform/util/testSrc/com/intellij/util/lang/UrlClassLoaderTest.java +++ b/platform/util/testSrc/com/intellij/util/lang/UrlClassLoaderTest.java @@ -17,8 +17,7 @@ package com.intellij.util.lang; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.ConcurrencyUtil; -import com.intellij.util.ObjectUtils; +import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import org.junit.Test; @@ -218,4 +217,43 @@ public class UrlClassLoaderTest { return loader.findResource(name); } } + + @Test + public void testFindDirWhenUsingCache() throws IOException { + int counter = 1; + for (String dirName : new String[]{ "dir", "dir/", "dir.class", "dir.class/"}) { + for(String resourceName: new String[] {"a.class", "a.txt"} ) { + File root = FileUtil.createTempDirectory("testFindDirWhenUsingCache", String.valueOf(counter++)); + File subDir = createTestDir(root, dirName); + createTestFile(subDir, resourceName); + + URL url = root.toURI().toURL(); + URLClassLoader standardCl = new URLClassLoader(new URL[] {url}); + + try { + Enumeration resources = standardCl.findResources(dirName); + assertTrue(resources.hasMoreElements()); + URL expectedResourceUrl = resources.nextElement(); + + withCustomCachedClassloader(url, (customCl) -> { + assertNull(customCl.findResource("SomeNonExistentResource.resource")); + checkResourceUrlIsTheSame(customCl, dirName, expectedResourceUrl); + }); + withCustomCachedClassloader(url, (customCl) -> checkResourceUrlIsTheSame(customCl, dirName, expectedResourceUrl)); + } finally { + standardCl.close(); + } + } + } + } + + private static void checkResourceUrlIsTheSame(UrlClassLoader customCl, String resourceName, URL expectedResourceUrl) throws IOException { + Enumeration customClResources = customCl.findResources(resourceName); + assertTrue(customClResources.hasMoreElements()); + assertEquals(expectedResourceUrl, customClResources.nextElement()); + } + + private static void withCustomCachedClassloader(URL url, ThrowableConsumer testAction) throws IOException { + testAction.consume(UrlClassLoader.build().useCache().urls(url).get()); + } } \ No newline at end of file From 8309d42bb5badca4b96cd5dfeda31dda42eacc67 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 16 Nov 2017 21:09:57 +0300 Subject: [PATCH 56/81] git tests: fix auth failure assertion for old Gits Git prior to 1.8.3 (d5ccbe4) didn't report the URL for which the authentication failed. --- .../git4idea/tests/git4idea/remote/GitRemoteTest.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt b/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt index 1906cf76a362..9a1b1739ec8e 100644 --- a/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt +++ b/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt @@ -21,6 +21,7 @@ import com.intellij.util.ThrowableRunnable import git4idea.checkout.GitCheckoutProvider import git4idea.commands.GitHttpAuthService import git4idea.commands.GitHttpAuthenticator +import git4idea.config.GitVersion import git4idea.remote.GitRemoteTest.ConfigScope.GLOBAL import git4idea.remote.GitRemoteTest.ConfigScope.SYSTEM import git4idea.test.GitHttpAuthTestService @@ -86,7 +87,14 @@ class GitRemoteTest : GitPlatformTest() { assertTrue("Clone didn't complete during the reasonable period of time", cloneWaiter.await(30, TimeUnit.SECONDS)) assertFalse("Repository directory shouldn't be created", File(testRoot, projectName).exists()) - assertErrorNotification("Clone failed", "Authentication failed for '$url/'") + + val expectedAuthFailureMessage = if (vcs.version.isLaterOrEqual(GitVersion(1, 8, 3, 0))) { + "Authentication failed for '$url/'" + } + else { + "Authentication failed" + } + assertErrorNotification("Clone failed", expectedAuthFailureMessage) } private fun makeUrl(username: String?) : String { From 71dc6ad33c81abc9ffd90545d2c7c65d3bf712d7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 18 Nov 2017 15:07:11 +0300 Subject: [PATCH 57/81] git tests: reset credential.helper for all tests which need it --- .../tests/git4idea/remote/GitRemoteTest.kt | 46 +++-------------- .../tests/git4idea/test/GitPlatformTest.kt | 50 ++++++++++++++++--- .../plugins/github/test/GithubTest.java | 5 ++ 3 files changed, 55 insertions(+), 46 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt b/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt index 9a1b1739ec8e..38c445857b65 100644 --- a/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt +++ b/plugins/git4idea/tests/git4idea/remote/GitRemoteTest.kt @@ -16,17 +16,12 @@ package git4idea.remote import com.intellij.openapi.components.service -import com.intellij.testFramework.RunAll -import com.intellij.util.ThrowableRunnable import git4idea.checkout.GitCheckoutProvider import git4idea.commands.GitHttpAuthService import git4idea.commands.GitHttpAuthenticator import git4idea.config.GitVersion -import git4idea.remote.GitRemoteTest.ConfigScope.GLOBAL -import git4idea.remote.GitRemoteTest.ConfigScope.SYSTEM import git4idea.test.GitHttpAuthTestService import git4idea.test.GitPlatformTest -import git4idea.test.git import java.io.File import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -35,7 +30,6 @@ class GitRemoteTest : GitPlatformTest() { private lateinit var authenticator : TestAuthenticator private lateinit var authTestService : GitHttpAuthTestService - private lateinit var credentialHelpers: Map private val projectName = "projectA" @@ -45,18 +39,19 @@ class GitRemoteTest : GitPlatformTest() { authenticator = TestAuthenticator() authTestService = service() as GitHttpAuthTestService authTestService.register(authenticator) - - credentialHelpers = readAndResetCredentialHelpers() } override fun tearDown() { - RunAll() - .append(ThrowableRunnable { authTestService.cleanup() }) - .append(ThrowableRunnable { restoreCredentialHelpers() }) - .append(ThrowableRunnable { super.tearDown() }) - .run() + try { + authTestService.cleanup() + } + finally { + super.tearDown() + } } + override fun hasRemoteGitOperation() = true + fun `test clone from http with username`() { val cloneWaiter = cloneOnPooledThread(makeUrl("gituser")) @@ -112,24 +107,6 @@ class GitRemoteTest : GitPlatformTest() { return cloneWaiter } - private fun readAndResetCredentialHelpers(): Map { - val system = readAndResetCredentialHelper(SYSTEM) - val global = readAndResetCredentialHelper(GLOBAL) - return mapOf(SYSTEM to system, GLOBAL to global) - } - - private fun readAndResetCredentialHelper(scope: ConfigScope): String { - val value = git("config ${scope.param()} --get-all credential.helper", true) - git("config ${scope.param()} --unset-all credential.helper", true) - return value - } - - private fun restoreCredentialHelpers() { - credentialHelpers.forEach { scope, value -> - if (value.isNotBlank()) git("config ${scope.param()} credential.helper ${value}", true) - } - } - private fun assertCloneSuccessful(cloneCompleted: CountDownLatch) { assertTrue("Clone didn't complete during the reasonable period of time", cloneCompleted.await(30, TimeUnit.SECONDS)) assertTrue("Repository directory was not found", File(testRoot, projectName).exists()) @@ -212,11 +189,4 @@ class GitRemoteTest : GitPlatformTest() { return usernameAsked } } - - private enum class ConfigScope { - SYSTEM, - GLOBAL; - - fun param() = "--${name.toLowerCase()}" - } } \ No newline at end of file diff --git a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.kt b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.kt index 634e5d0e756a..dd7b5160471d 100644 --- a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.kt +++ b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.kt @@ -22,7 +22,9 @@ import com.intellij.openapi.vcs.Executor import com.intellij.openapi.vcs.Executor.cd import com.intellij.openapi.vcs.VcsConfiguration import com.intellij.openapi.vcs.VcsShowConfirmationOption +import com.intellij.testFramework.RunAll import com.intellij.testFramework.vcs.AbstractVcsTestCase +import com.intellij.util.ThrowableRunnable import com.intellij.vcs.log.VcsFullCommitDetails import com.intellij.vcs.log.impl.VcsLogUtil import com.intellij.vcs.test.VcsPlatformTest @@ -36,6 +38,8 @@ import git4idea.config.GitVcsSettings import git4idea.log.GitLogProvider import git4idea.repo.GitRepository import git4idea.repo.GitRepositoryManager +import git4idea.test.GitPlatformTest.ConfigScope.GLOBAL +import git4idea.test.GitPlatformTest.ConfigScope.SYSTEM import java.io.File abstract class GitPlatformTest : VcsPlatformTest() { @@ -48,6 +52,8 @@ abstract class GitPlatformTest : VcsPlatformTest() { protected lateinit var vcsHelper: MockVcsHelper protected lateinit var logProvider: GitLogProvider + private lateinit var credentialHelpers: Map + @Throws(Exception::class) override fun setUp() { super.setUp() @@ -69,18 +75,19 @@ abstract class GitPlatformTest : VcsPlatformTest() { assumeSupportedGitVersion(vcs) addSilently() removeSilently() + + credentialHelpers = if (hasRemoteGitOperation()) readAndResetCredentialHelpers() else emptyMap() } @Throws(Exception::class) override fun tearDown() { - try { - if (wasInit { dialogManager }) dialogManager.cleanup() - if (wasInit { git }) git.reset() - if (wasInit { settings }) settings.appSettings.setPathToGit(null) - } - finally { - super.tearDown() - } + RunAll() + .append(ThrowableRunnable { restoreCredentialHelpers() }) + .append(ThrowableRunnable { if (wasInit { dialogManager }) dialogManager.cleanup() }) + .append(ThrowableRunnable { if (wasInit { git }) git.reset() }) + .append(ThrowableRunnable { if (wasInit { settings }) settings.appSettings.setPathToGit(null) }) + .append(ThrowableRunnable { super.tearDown() }) + .run() } override fun getDebugLogCategories(): Collection { @@ -89,6 +96,8 @@ abstract class GitPlatformTest : VcsPlatformTest() { "#output." + GitHandler::class.java.name)) } + protected open fun hasRemoteGitOperation() = false + protected open fun createRepository(rootDir: String): GitRepository { return createRepository(project, rootDir) } @@ -160,6 +169,24 @@ abstract class GitPlatformTest : VcsPlatformTest() { hookFile.setExecutable(true, false) } + private fun readAndResetCredentialHelpers(): Map { + val system = readAndResetCredentialHelper(SYSTEM) + val global = readAndResetCredentialHelper(GLOBAL) + return mapOf(SYSTEM to system, GLOBAL to global) + } + + private fun readAndResetCredentialHelper(scope: ConfigScope): String { + val value = git("config ${scope.param()} --get-all credential.helper", true) + git("config ${scope.param()} --unset-all credential.helper", true) + return value + } + + private fun restoreCredentialHelpers() { + credentialHelpers.forEach { scope, value -> + if (value.isNotBlank()) git("config ${scope.param()} credential.helper ${value}", true) + } + } + protected fun readDetails(hashes: List): List = VcsLogUtil.getDetails(logProvider, projectRoot, hashes) protected fun readDetails(hash: String) = readDetails(listOf(hash)).first() @@ -182,4 +209,11 @@ abstract class GitPlatformTest : VcsPlatformTest() { protected data class ReposTrinity(val projectRepo: GitRepository, val parent: File, val bro: File) + + private enum class ConfigScope { + SYSTEM, + GLOBAL; + + fun param() = "--${name.toLowerCase()}" + } } diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java index 7d91830a1abb..f4d572626bcc 100644 --- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java +++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java @@ -75,6 +75,11 @@ public abstract class GithubTest extends GitPlatformTest { VfsTestUtil.createDir (projectRoot, "folder/empty_folder"); } + @Override + protected boolean hasRemoteGitOperation() { + return true; + } + protected void checkNotification(@NotNull NotificationType type, @Nullable String title, @Nullable String content) { Notification actualNotification = vcsNotifier.getLastNotification(); assertNotNull("No notification was shown", actualNotification); From 663f88469fee5b2c6879fa64e959479f7c64f250 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 18 Nov 2017 15:26:33 +0300 Subject: [PATCH 58/81] git tests: skip tests on case-only rename commit for old Gits In Git prior to 1.8.2 `git reset` used to return exit code 1, even if completes successfully. It affects only rare cases, so it was decided not to fix it: IDEA-182150 --- .../tests/git4idea/tests/GitCommitTest.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt index 3d7fc6933f93..7f5367d8744c 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt +++ b/plugins/git4idea/tests/git4idea/tests/GitCommitTest.kt @@ -22,7 +22,9 @@ import com.intellij.openapi.vcs.changes.Change import com.intellij.util.containers.ContainerUtil import git4idea.GitUtil import git4idea.checkin.GitCheckinEnvironment +import git4idea.config.GitVersion import git4idea.test.* +import org.junit.Assume.assumeTrue import java.io.File import java.util.* @@ -133,6 +135,8 @@ class GitCommitTest : GitSingleRepoTest() { } fun `test commit case rename & don't commit one staged file`() { + `assume version where git reset returns 0 exit code on success `() + tac("s.java") generateCaseRename("a.java", "A.java") echo("s.java", "staged") @@ -157,6 +161,8 @@ class GitCommitTest : GitSingleRepoTest() { } fun `test commit case rename & don't commit one staged simple rename, then rename should remain staged`() { + `assume version where git reset returns 0 exit code on success `() + echo("before.txt", "some\ncontent\nere") addCommit("created before.txt") generateCaseRename("a.java", "A.java") @@ -181,6 +187,8 @@ class GitCommitTest : GitSingleRepoTest() { } fun `test commit case rename + one unstaged file & don't commit one staged file`() { + `assume version where git reset returns 0 exit code on success `() + tac("s.java") tac("m.java") generateCaseRename("a.java", "A.java") @@ -209,6 +217,8 @@ class GitCommitTest : GitSingleRepoTest() { } fun `test commit case rename & don't commit a file which is both staged and unstaged, should reset and restore`() { + `assume version where git reset returns 0 exit code on success `() + tac("c.java") generateCaseRename("a.java", "A.java") echo("c.java", "staged") @@ -267,6 +277,11 @@ class GitCommitTest : GitSingleRepoTest() { assertEquals(initialContent + additionalContent, git("show HEAD:A.java")) } + private fun `assume version where git reset returns 0 exit code on success `() { + assumeTrue("Not testing: git reset returns 1 and fails the commit process in ${vcs.version}", + vcs.version.isLaterOrEqual(GitVersion(1, 8, 2, 0))) + } + private fun generateCaseRename(from: String, to: String) { tac(from) git("mv -f $from $to") From 6be0036acc3ea969039376175e0080efa44baf3a Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 18 Nov 2017 13:32:20 +0100 Subject: [PATCH 59/81] fix tests: adjust expected directory name --- .../com/intellij/compiler/CorruptedBuildCachesTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/compiler/tests/com/intellij/compiler/CorruptedBuildCachesTest.java b/java/compiler/tests/com/intellij/compiler/CorruptedBuildCachesTest.java index 878405244b73..06e8c0bdffba 100644 --- a/java/compiler/tests/com/intellij/compiler/CorruptedBuildCachesTest.java +++ b/java/compiler/tests/com/intellij/compiler/CorruptedBuildCachesTest.java @@ -37,19 +37,21 @@ public class CorruptedBuildCachesTest extends BaseCompilerTestCase { } public void testSrcOutMapping() { + final String moduleName = "m"; + final String moduleDirName = moduleName + "_" + Integer.toHexString(moduleName.hashCode()); VirtualFile a = createFile("src/A.java", "class A{}"); - Module m = addModule("m", a.getParent()); + Module m = addModule(moduleName, a.getParent()); make(m); assertOutput(m, fs().file("A.class")); File systemDirectory = BuildManager.getInstance().getProjectSystemDirectory(myProject); - assertTrue(FileUtil.delete(new File(systemDirectory, "targets/java-production/m/src-out"))); + assertTrue(FileUtil.delete(new File(systemDirectory, "targets/java-production/"+moduleDirName+"/src-out"))); changeFile(a, "class A{int b;}"); make(m).assertGenerated("A.class"); make(m).assertUpToDate(); changeFile(a, "class A{int c;}"); - corruptCaches(new File(systemDirectory, "targets/java-production/m/src-out/data")); + corruptCaches(new File(systemDirectory, "targets/java-production/"+moduleDirName+"/src-out/data")); make(m).assertGenerated("A.class"); assertOutput(m, fs().file("A.class")); From 7d5b0ba46c0dbc5db75e747b6375fb3c28ab2486 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 18 Nov 2017 15:46:03 +0300 Subject: [PATCH 60/81] git tests: fix assertion for older Gits Gits prior to 1.7.3 didn't mention the files modified during rebase process. --- plugins/git4idea/tests/git4idea/rebase/GitRebaseBaseTest.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/rebase/GitRebaseBaseTest.kt b/plugins/git4idea/tests/git4idea/rebase/GitRebaseBaseTest.kt index d90d68a51db6..7ef5bd03749d 100644 --- a/plugins/git4idea/tests/git4idea/rebase/GitRebaseBaseTest.kt +++ b/plugins/git4idea/tests/git4idea/rebase/GitRebaseBaseTest.kt @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vcs.Executor import git4idea.GitUtil import git4idea.branch.GitRebaseParams +import git4idea.config.GitVersion import git4idea.repo.GitRepository import git4idea.test.* @@ -205,9 +206,10 @@ abstract class GitRebaseBaseTest : GitPlatformTest() { } protected fun `assert error about unstaged file before continue rebase`(file : String) { + val fileLine = if (vcs.version.isLaterOrEqual(GitVersion(1, 7, 3, 0))) "$file: needs update" else "" assertErrorNotification("Continue Rebase Failed", - """ - $file: needs update + """ + $fileLine You must edit all merge conflicts and then mark them as resolved using git add You can retry or abort rebase. From 6f6e82e364b24b7e750d5d0e956b98da6baf54ca Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 18 Nov 2017 15:53:44 +0300 Subject: [PATCH 61/81] git tests: skip a test for older Gits Tedious to test without "recurse-submodules" which was introduced in 1.7.4 --- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index 4d17acbdf2cd..c28e6e28154d 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.util.io.FileUtil.getRelativePath import com.intellij.openapi.vcs.Executor.cd import com.intellij.openapi.vcs.update.UpdatedFiles import com.intellij.openapi.vfs.VfsUtilCore.virtualToIoFile +import git4idea.config.GitVersion import git4idea.config.UpdateMethod import git4idea.push.GitPushOperation import git4idea.push.GitPushSupport @@ -30,6 +31,7 @@ import git4idea.repo.GitRepository import git4idea.repo.GitRepositoryManager import git4idea.repo.GitSubmoduleInfo import git4idea.test.* +import org.junit.Assume.assumeTrue import java.io.File import java.util.* @@ -60,7 +62,7 @@ class GitSubmoduleTest : GitPlatformTest() { override fun setUp() { super.setUp() - + setUpRepositoryStructure() repositoryManager.updateAllRepositories() } @@ -73,6 +75,8 @@ class GitSubmoduleTest : GitPlatformTest() { } fun `test submodules are updated before superprojects`() { + assumeTrue("Not testing: no --recurse-submodules flag in ${vcs.version}", vcs.version.isLaterOrEqual(GitVersion(1, 7, 4, 0))) + val bro = prepareSecondClone() commitAndPushFromSecondClone(bro) // remote commit to overcome "nothing to do" From e520501a0af5450b4720907e57c2bca4530a072a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 18 Nov 2017 14:28:25 +0100 Subject: [PATCH 62/81] Support PlatformDataKeys.SELECTED_ITEMS in project view reference: OC-16334 Rework AppCode project view actions to work correctly with standard project and scope views --- .../com/intellij/ide/projectView/impl/ProjectViewImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 3cda5bd11899..369121f0a6ee 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -1157,6 +1157,11 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo return selectedElements.isEmpty() ? null : selectedElements.toArray(new NamedLibraryElement[selectedElements.size()]); } + if (PlatformDataKeys.SELECTED_ITEMS.is(dataId)) { + final AbstractProjectViewPane viewPane = getCurrentProjectViewPane(); + return viewPane == null ? null : viewPane.getSelectedElements(); + } + if (QuickActionProvider.KEY.is(dataId)) { return ProjectViewImpl.this; } From 6399455d20b646f5779d7eb5c131c51985c5453a Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Sat, 18 Nov 2017 17:16:15 +0300 Subject: [PATCH 63/81] icons.gant: load icons via ImageIO instead of Toolkit This is an attempt to fix spurious test failures, when we fail to load icon for the second time (probably, because 5s can be not enough). --- .../jetbrains/intellij/build/images/util.kt | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt index 1dcd5bdb3cd2..948410b9fea5 100644 --- a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt +++ b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt @@ -16,8 +16,9 @@ package org.jetbrains.intellij.build.images import com.intellij.openapi.util.text.StringUtil -import java.awt.* +import java.awt.Dimension import java.io.File +import javax.imageio.ImageIO internal val File.children: List get() = if (isDirectory) listFiles().toList() else emptyList() @@ -35,27 +36,12 @@ internal fun isIcon(file: File): Boolean { private fun isImage(name: String) = name.endsWith(".png") || name.endsWith(".gif") internal fun imageSize(file: File): Dimension? { - val image = loadImage(file) ?: return null + val image = ImageIO.read(file) ?: return null val width = image.getWidth(null) val height = image.getHeight(null) return Dimension(width, height) } -private fun loadImage(file: File): Image? { - val image = Toolkit.getDefaultToolkit().createImage(file.absolutePath) - if (!waitForImage(image)) return null - return image -} - -private fun waitForImage(image: Image?): Boolean { - if (image == null) return false - if (image.getWidth(null) > 0) return true - val mediaTracker = MediaTracker(object : Component() {}) - mediaTracker.addImage(image, 1) - mediaTracker.waitForID(1, 5000) - return !mediaTracker.isErrorID(1) -} - internal enum class ImageType(private val suffix: String) { BASIC(""), RETINA("@2x"), DARCULA("_dark"), RETINA_DARCULA("@2x_dark"); From c5f79ef3b2148207046918295b41b3814dc2b224 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 18 Nov 2017 18:08:37 +0100 Subject: [PATCH 64/81] Allow adding custom global search scopes reference: OC-9143 Add 'File added to Xcode project' scope OC-3934 Add 'Files not added to Xcode project' scope to help find and add such files to the project. CPP-505 Better CMake files overview in the project pane --- .../search/PredefinedSearchScopeProvider.java | 16 +------------- .../psi/search/SearchScopeProvider.java | 16 ++++++++++++++ .../PredefinedSearchScopeProviderImpl.java | 21 ++++++------------- .../src/META-INF/LangExtensionPoints.xml | 1 + 4 files changed, 24 insertions(+), 30 deletions(-) create mode 100644 platform/analysis-impl/src/com/intellij/psi/search/SearchScopeProvider.java diff --git a/platform/analysis-impl/src/com/intellij/psi/search/PredefinedSearchScopeProvider.java b/platform/analysis-impl/src/com/intellij/psi/search/PredefinedSearchScopeProvider.java index b0a8e6e50446..1da60759d671 100644 --- a/platform/analysis-impl/src/com/intellij/psi/search/PredefinedSearchScopeProvider.java +++ b/platform/analysis-impl/src/com/intellij/psi/search/PredefinedSearchScopeProvider.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.search; import com.intellij.openapi.actionSystem.DataContext; diff --git a/platform/analysis-impl/src/com/intellij/psi/search/SearchScopeProvider.java b/platform/analysis-impl/src/com/intellij/psi/search/SearchScopeProvider.java new file mode 100644 index 000000000000..aedcbac7c864 --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/psi/search/SearchScopeProvider.java @@ -0,0 +1,16 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.psi.search; + +import com.intellij.openapi.extensions.ExtensionPointName; + +import java.util.List; + +public interface SearchScopeProvider { + ExtensionPointName EP = ExtensionPointName.create("com.intellij.searchScopesProvider"); + + /** + * General project scopes are added after 'Project', 'Everything' but before 'Production', 'Tests', etc. + * @see PredefinedSearchScopeProvider + */ + List getGeneralProjectScopes(); +} diff --git a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java index 4471768a6531..10c4db661566 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.search; import com.intellij.ide.IdeBundle; @@ -27,6 +13,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.module.*; import com.intellij.openapi.project.Project; @@ -76,6 +63,10 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv result.add(GlobalSearchScope.allScope(project)); } + for (SearchScopeProvider each : Extensions.getExtensions(SearchScopeProvider.EP, project)) { + result.addAll(each.getGeneralProjectScopes()); + } + if (ModuleUtil.isSupportedRootType(project, JavaSourceRootType.TEST_SOURCE)) { result.add(GlobalSearchScopesCore.projectProductionScope(project)); result.add(GlobalSearchScopesCore.projectTestScope(project)); diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 41cee2c5356e..970491cb8ef0 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -258,6 +258,7 @@ + From 37cdd1cace35d9e940bf7620a6cd18297c1671d6 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sun, 19 Nov 2017 02:09:28 +0300 Subject: [PATCH 65/81] PY-27061: Django version may be loose --- .../django_manage_commands_provider/_parser/parser.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py b/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py index fe7e72850540..d854e9c799b7 100644 --- a/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py +++ b/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py @@ -97,8 +97,11 @@ def _is_django_10(): :return: is Django >= 1.10 """ try: - from distutils.version import StrictVersion + from distutils.version import StrictVersion, LooseVersion import django - return StrictVersion(django.get_version()) >= StrictVersion("1.10") + try: + return StrictVersion(django.get_version()) >= StrictVersion("1.10") + except ValueError: + return LooseVersion(django.get_version()) >= LooseVersion("1.10") except (ImportError, AttributeError): return False From 1bc4860f1a1ea77d80d4525645faa356c376f235 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 14:13:51 +0300 Subject: [PATCH 66/81] git tests: setup default username for auxiliary repositories Otherwise Git tries to get a username/email from the OS settings, which sometimes fail on test server agents, and it leads to commit failure. --- .../git4idea/tests/git4idea/repo/GitWorkTreeBaseTest.kt | 2 ++ plugins/git4idea/tests/git4idea/test/GitTestUtil.kt | 7 ++++--- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/repo/GitWorkTreeBaseTest.kt b/plugins/git4idea/tests/git4idea/repo/GitWorkTreeBaseTest.kt index c86f1653a5f6..300191ed9503 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitWorkTreeBaseTest.kt +++ b/plugins/git4idea/tests/git4idea/repo/GitWorkTreeBaseTest.kt @@ -23,6 +23,7 @@ import git4idea.config.GitVersion import git4idea.test.GitPlatformTest import git4idea.test.git import git4idea.test.registerRepo +import git4idea.test.setupDefaultUsername import org.junit.Assume.assumeTrue import java.io.File @@ -44,6 +45,7 @@ abstract class GitWorkTreeBaseTest : GitPlatformTest() { val gitDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(File(projectPath, GitUtil.DOT_GIT)) assertNotNull(gitDir) myRepo = registerRepo(project, projectPath) + setupDefaultUsername() assertEquals(1, repositoryManager.repositories.size) assertNotNull(repositoryManager.getRepositoryForRoot(projectRoot)) } diff --git a/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt b/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt index 6f4539ee0d74..cbe0d31a77c8 100644 --- a/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt +++ b/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt @@ -91,11 +91,12 @@ fun GitPlatformTest.cloneRepo(source: String, destination: String, bare: Boolean else { git("clone -- . $destination") } + cd(destination) + setupDefaultUsername() } -fun setupDefaultUsername(project: Project) { - setupUsername(project, USER_NAME, USER_EMAIL) -} +fun setupDefaultUsername(project: Project) = setupUsername(project, USER_NAME, USER_EMAIL) +fun GitPlatformTest.setupDefaultUsername() = setupDefaultUsername(project) fun setupUsername(project: Project, name: String, email: String) { assertFalse("Can not set empty user name ", name.isEmpty()) diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index c28e6e28154d..fc6a80bcd6e2 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -169,7 +169,7 @@ class GitSubmoduleTest : GitPlatformTest() { git("init $moduleName") val child = File(testRoot, moduleName) cd(child) - setupDefaultUsername(project) + setupDefaultUsername() tac("initial.txt", "initial") val parent = "$moduleName.git" git("remote add origin ${testRoot}/$parent") @@ -185,7 +185,10 @@ class GitSubmoduleTest : GitPlatformTest() { private fun prepareSecondClone(): File { cd(testRoot) git("clone --recurse-submodules parent.git bro") - return File(testRoot, "bro") + val broDir = File(testRoot, "bro") + cd(broDir) + setupDefaultUsername() + return broDir } private fun commitAndPushFromSecondClone(bro: File) { From eb213feaa0aed0ef1ffd993effec58b6225fc8a3 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 15:24:14 +0300 Subject: [PATCH 67/81] git tests: add debug logs for test failures "no commit dialog was shown" --- plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt | 3 +++ .../tests/git4idea/cherrypick/GitCherryPickAutoCommitTest.kt | 1 + 2 files changed, 4 insertions(+) diff --git a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt index b66da9186088..e7741575811b 100644 --- a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt +++ b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt @@ -138,6 +138,7 @@ class GitApplyChangesProcess(private val project: Project, waitForChangeListManagerUpdate() if (mergeCompleted) { + LOG.debug("All conflicts resolved, will show commit dialog.") val committed = commit(repository, commit, commitMessage, changeList, successfulCommits, alreadyPicked) if (!committed) return false @@ -198,10 +199,12 @@ class GitApplyChangesProcess(private val project: Project, } val changes = actualList.changes if (changes.isEmpty()) { + LOG.debug("No changes in the $actualList. All changes in the CLM: ${changeListManager.allChanges}") alreadyPicked.add(commit) return true } + LOG.debug("Showing commit dialog for changes: ${changes}") val committed = showCommitDialogAndWaitForCommit(repository, changeList, commitMessage, changes) if (committed) { refreshVfsAndMarkDirty(changes) diff --git a/plugins/git4idea/tests/git4idea/cherrypick/GitCherryPickAutoCommitTest.kt b/plugins/git4idea/tests/git4idea/cherrypick/GitCherryPickAutoCommitTest.kt index cdbc1cfd6753..b564ace8a888 100644 --- a/plugins/git4idea/tests/git4idea/cherrypick/GitCherryPickAutoCommitTest.kt +++ b/plugins/git4idea/tests/git4idea/cherrypick/GitCherryPickAutoCommitTest.kt @@ -74,6 +74,7 @@ class GitCherryPickAutoCommitTest : GitCherryPickTest() { cherryPick(commit) `assert merge dialog was shown`() + `assert commit dialog was shown`() changeListManager.assertChangeListExists("on_master\n\n(cherry picked from commit ${shortHash(commit)})") assertNoNotification() } From 21cc93c3d1dcec8bd3ffe858f511ec68f74379ce Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 15:26:32 +0300 Subject: [PATCH 68/81] git tests: add debug logs for test failures "no changelist for conflicts created" --- plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt index e7741575811b..7854640a2202 100644 --- a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt +++ b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt @@ -251,6 +251,7 @@ class GitApplyChangesProcess(private val project: Project, private fun removeChangeListIfEmpty(changeList: LocalChangeList) { val actualList = changeListManager.getChangeList(changeList.id) if (actualList != null && actualList.changes.isEmpty()) { + LOG.debug("Changelist $actualList is empty, removing.") changeListManager.removeChangeList(actualList) } } From 0481ee393ca86166d9493a6ee168a2d8280b0489 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 15:30:11 +0300 Subject: [PATCH 69/81] git tests: setup default username for auxiliary repositories Otherwise Git tries to get a username/email from the OS settings, which sometimes fail on test server agents, and it leads to commit failure. --- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index fc6a80bcd6e2..259be50611b3 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -152,6 +152,8 @@ class GitSubmoduleTest : GitPlatformTest() { git("submodule add ${FileUtil.toSystemIndependentName(submoduleUrl.path)} ${relativePath ?: ""}") git("commit -m 'Added submodule lib'") git("push origin master") + cd(File(submoduleUrl.path)) + setupDefaultUsername() } /** From c7254c5546371f5d3884538071fffb61a9bec4f7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 15:54:00 +0300 Subject: [PATCH 70/81] git tests: add logs for expected branch operations failures --- .../git4idea/branch/GitBranchWorkerTest.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt index 0fb78f2bcd5d..bac4735cb5c9 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt @@ -18,7 +18,6 @@ package git4idea.branch import com.intellij.dvcs.repo.Repository import com.intellij.notification.Notification import com.intellij.openapi.progress.EmptyProgressIndicator -import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project import com.intellij.openapi.util.Ref import com.intellij.openapi.util.io.FileUtil @@ -948,9 +947,7 @@ class GitBranchWorkerTest : GitPlatformTest() { } open class TestUiHandler : GitBranchUiHandler { - override fun getProgressIndicator(): ProgressIndicator { - return EmptyProgressIndicator() - } + override fun getProgressIndicator() = EmptyProgressIndicator() override fun showSmartOperationDialog(project: Project, changes: List, @@ -966,32 +963,32 @@ class GitBranchWorkerTest : GitPlatformTest() { } override fun notifyErrorWithRollbackProposal(title: String, message: String, rollbackProposal: String): Boolean { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$title\n$message\n$rollbackProposal") } override fun showUnmergedFilesNotification(operationName: String, repositories: Collection) { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$operationName\n$repositories") } override fun showUnmergedFilesMessageWithRollback(operationName: String, rollbackProposal: String): Boolean { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$operationName\n$rollbackProposal") } override fun showUntrackedFilesNotification(operationName: String, root: VirtualFile, relativePaths: Collection) { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$operationName $root\n$relativePaths") } override fun showUntrackedFilesDialogWithRollback(operationName: String, rollbackProposal: String, root: VirtualFile, relativePaths: Collection): Boolean { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$operationName\n$rollbackProposal\n$root\n$relativePaths") } override fun confirmRemoteBranchDeletion(branchName: String, trackingBranches: MutableCollection, repositories: MutableCollection): DeleteRemoteBranchDecision { - throw UnsupportedOperationException() + throw UnsupportedOperationException("$branchName\n$trackingBranches\n$repositories") } } From de197825c215a09eed6e8f2c7911bca11896346a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:39:33 +0300 Subject: [PATCH 71/81] git tests: more debug logs for test failures "no commit dialog was shown" --- plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt index 7854640a2202..7f345cf4a42e 100644 --- a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt +++ b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt @@ -199,7 +199,8 @@ class GitApplyChangesProcess(private val project: Project, } val changes = actualList.changes if (changes.isEmpty()) { - LOG.debug("No changes in the $actualList. All changes in the CLM: ${changeListManager.allChanges}") + val changesString = changeListManager.changeLists.map { it -> "[${it.name}] ${it.changes}" } + LOG.debug("No changes in the $actualList. All changes in the CLM: $changesString") alreadyPicked.add(commit) return true } From 62053f224513fd004910fcbab3ff1b35b202d712 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:39:33 +0300 Subject: [PATCH 72/81] git tests: more debug logs for test failures "no commit dialog was shown" --- plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt index 7f345cf4a42e..dfea90a55a48 100644 --- a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt +++ b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt @@ -138,7 +138,7 @@ class GitApplyChangesProcess(private val project: Project, waitForChangeListManagerUpdate() if (mergeCompleted) { - LOG.debug("All conflicts resolved, will show commit dialog.") + LOG.debug("All conflicts resolved, will show commit dialog. Current default changelist is [$changeList]") val committed = commit(repository, commit, commitMessage, changeList, successfulCommits, alreadyPicked) if (!committed) return false From d9be11b9db16160aba3b7406b96e6a8d92ac7f67 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:45:04 +0300 Subject: [PATCH 73/81] git tests: setup default username for auxiliary repositories Otherwise Git tries to get a username/email from the OS settings, which sometimes fail on test server agents, and it leads to commit failure. --- plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt index 259be50611b3..7ddbb75e3342 100644 --- a/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt +++ b/plugins/git4idea/tests/git4idea/update/GitSubmoduleTest.kt @@ -144,6 +144,8 @@ class GitSubmoduleTest : GitPlatformTest() { youngerRepo = addSubmoduleInProject(younger.remote, younger.name, "alib/younger") mainRepo.git("submodule update --init --recursive") // this initializes the grandchild submodule grandchildRepo = registerRepo(project, "${projectPath}/elder/grandchild") + cd(grandchildRepo) + setupDefaultUsername() grandchildRepo.git("checkout master") // git submodule is initialized in detached HEAD state by default } From af905259e4206f5bae3f9cc91708d3e3474b1864 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:48:30 +0300 Subject: [PATCH 74/81] git tests: add debug logs for test failures "no changelist for conflicts created" --- plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt index dfea90a55a48..cff5a2493d5a 100644 --- a/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt +++ b/plugins/git4idea/src/git4idea/GitApplyChangesProcess.kt @@ -199,8 +199,7 @@ class GitApplyChangesProcess(private val project: Project, } val changes = actualList.changes if (changes.isEmpty()) { - val changesString = changeListManager.changeLists.map { it -> "[${it.name}] ${it.changes}" } - LOG.debug("No changes in the $actualList. All changes in the CLM: $changesString") + LOG.debug("No changes in the $actualList. All changes in the CLM: ${getAllChangesInLogFriendlyPresentation(changeListManager)}") alreadyPicked.add(commit) return true } @@ -220,6 +219,9 @@ class GitApplyChangesProcess(private val project: Project, } } + private fun getAllChangesInLogFriendlyPresentation(changeListManagerEx: ChangeListManagerEx) = + changeListManagerEx.changeLists.map { it -> "[${it.name}] ${it.changes}" } + private fun waitForChangeListManagerUpdate() { val waiter = CountDownLatch(1) changeListManager.invokeAfterUpdate({ @@ -252,7 +254,8 @@ class GitApplyChangesProcess(private val project: Project, private fun removeChangeListIfEmpty(changeList: LocalChangeList) { val actualList = changeListManager.getChangeList(changeList.id) if (actualList != null && actualList.changes.isEmpty()) { - LOG.debug("Changelist $actualList is empty, removing.") + LOG.debug("Changelist $actualList is empty, removing. " + + "All changes in the CLM: ${getAllChangesInLogFriendlyPresentation(changeListManager)}") changeListManager.removeChangeList(actualList) } } From 3322849d5c165e5be5d9f00ae125e6fe884b0e7f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:51:19 +0300 Subject: [PATCH 75/81] cleanup: remove unused field --- .../src/git4idea/crlf/GitCrlfProblemsDetector.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/crlf/GitCrlfProblemsDetector.java b/plugins/git4idea/src/git4idea/crlf/GitCrlfProblemsDetector.java index c66202aafa84..7eefe8127b4b 100644 --- a/plugins/git4idea/src/git4idea/crlf/GitCrlfProblemsDetector.java +++ b/plugins/git4idea/src/git4idea/crlf/GitCrlfProblemsDetector.java @@ -55,7 +55,6 @@ public class GitCrlfProblemsDetector { private static final Logger LOG = Logger.getInstance(GitCrlfProblemsDetector.class); private static final String CRLF = "\r\n"; - @NotNull private final Project myProject; @NotNull private final Git myGit; @NotNull private final GitRepositoryManager myRepositoryManager; @@ -68,7 +67,6 @@ public class GitCrlfProblemsDetector { private GitCrlfProblemsDetector(@NotNull Project project, @NotNull Git git, @NotNull Collection files) { - myProject = project; myRepositoryManager = GitUtil.getRepositoryManager(project); myGit = git; @@ -127,8 +125,8 @@ public class GitCrlfProblemsDetector { } @NotNull - private Map> findFilesWithCrlf(@NotNull Map> allFilesByRoots, - @NotNull Collection rootsWithIncorrectAutoCrlf) { + private static Map> findFilesWithCrlf(@NotNull Map> allFilesByRoots, + @NotNull Collection rootsWithIncorrectAutoCrlf) { Map> filesWithCrlfByRoots = new HashMap<>(); for (Map.Entry> entry : allFilesByRoots.entrySet()) { VirtualFile root = entry.getKey(); @@ -144,7 +142,7 @@ public class GitCrlfProblemsDetector { } @NotNull - private Collection findFilesWithCrlf(@NotNull Collection files) { + private static Collection findFilesWithCrlf(@NotNull Collection files) { Collection filesWithCrlf = new ArrayList<>(); for (VirtualFile file : files) { ProgressIndicatorProvider.checkCanceled(); From b7673b80e71c9a7e38cc2948a1877fee23ea36cb Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 16:53:37 +0300 Subject: [PATCH 76/81] git tests: fix a copy-paste misprint in returning system autocrlf value --- .../tests/git4idea/crlf/GitCrlfProblemsDetectorTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.java b/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.java index 8fce99351c42..8c92f2897bf3 100644 --- a/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.java +++ b/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import static git4idea.test.GitExecutor.git; import static java.util.Arrays.asList; public class GitCrlfProblemsDetectorTest extends GitSingleRepoTest { @@ -50,7 +49,7 @@ public class GitCrlfProblemsDetectorTest extends GitSingleRepoTest { } if (!StringUtil.isEmptyOrSpaces(myOldSystemAutoCrlfValue)) { - git("config --global core.autocrlf " + myOldSystemAutoCrlfValue); + git("config --system core.autocrlf " + myOldSystemAutoCrlfValue); } } finally { From f08946b6668274669600369cc623b065af43bbe0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 17:24:38 +0300 Subject: [PATCH 77/81] git tests: fix several test assertions for Git < 1.7.2 which doesn't know of %B --- plugins/git4idea/tests/git4idea/rebase/GitRewordTest.kt | 6 ++---- plugins/git4idea/tests/git4idea/test/GitExecutor.kt | 2 +- plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt | 2 +- plugins/git4idea/tests/git4idea/test/GitTestUtil.kt | 3 +++ 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/rebase/GitRewordTest.kt b/plugins/git4idea/tests/git4idea/rebase/GitRewordTest.kt index 4da235621e92..494d4d3898b0 100644 --- a/plugins/git4idea/tests/git4idea/rebase/GitRewordTest.kt +++ b/plugins/git4idea/tests/git4idea/rebase/GitRewordTest.kt @@ -55,7 +55,7 @@ class GitRewordTest : GitSingleRepoTest() { val newMessage = "Correct message" GitRewordOperation(repo, commit, newMessage).execute() - assertMessage(newMessage, git("log HEAD^ --no-walk --pretty=%B"), "Message reworded incorrectly") + assertLastMessage(newMessage, "Message reworded incorrectly") } fun `test undo reword`() { @@ -114,9 +114,7 @@ class GitRewordTest : GitSingleRepoTest() { val newMessage = "Subject with trailing spaces \n\nBody \nwith \nspaces." GitRewordOperation(repo, commit, newMessage).execute() - val actualMessage = git("log HEAD --no-walk --pretty=%B") - assertTrue("Message reworded incorrectly. Expected:\n[$newMessage] Actual:\n[$actualMessage]", - StringUtil.equalsIgnoreWhitespaces(newMessage, actualMessage)) + assertLastMessage("Message reworded incorrectly") } // IDEA-175443 diff --git a/plugins/git4idea/tests/git4idea/test/GitExecutor.kt b/plugins/git4idea/tests/git4idea/test/GitExecutor.kt index 44736edc5646..cdd263ad8e1e 100644 --- a/plugins/git4idea/tests/git4idea/test/GitExecutor.kt +++ b/plugins/git4idea/tests/git4idea/test/GitExecutor.kt @@ -122,7 +122,7 @@ private fun last(project: Project) = git(project, "log -1 --pretty=%H") fun GitRepository.lastMessage() = cd { lastMessage(project) } fun GitPlatformTest.lastMessage() = lastMessage(project) -private fun lastMessage(project: Project) = git(project, "log -1 --pretty=%B") +private fun lastMessage(project: Project) = git(project, "log -1 --pretty=${getPrettyFormatTagForFullCommitMessage(project)}") fun GitRepository.log(vararg params: String) = cd { log(project, *params) } fun GitPlatformTest.log(vararg params: String) = log(project, *params) diff --git a/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt b/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt index daaed92240c4..7fdbf0a69341 100644 --- a/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt +++ b/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt @@ -103,7 +103,7 @@ fun GitPlatformTest.assertMessage(actual: String, expected: String, failMessage: fun GitPlatformTest.assertLogMessages(vararg messages: String) { val separator = "\u0001" - val actualMessages = git("log -${messages.size} --pretty=%B${separator}").split(separator) + val actualMessages = git("log -${messages.size} --pretty=${getPrettyFormatTagForFullCommitMessage(project)}${separator}").split(separator) for ((index, message) in messages.withIndex()) { Assertions.assertThat(actualMessages[index].trim()).isEqualToIgnoringWhitespace(message.trimIndent()) } diff --git a/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt b/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt index cbe0d31a77c8..983a10c95ada 100644 --- a/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt +++ b/plugins/git4idea/tests/git4idea/test/GitTestUtil.kt @@ -32,6 +32,7 @@ import git4idea.GitRemoteBranch import git4idea.GitStandardRemoteBranch import git4idea.GitUtil import git4idea.GitVcs +import git4idea.config.GitVersionSpecialty import git4idea.log.GitLogProvider import git4idea.push.GitPushSource import git4idea.push.GitPushTarget @@ -177,3 +178,5 @@ fun GitRepository.resolveConflicts() { this.git("add -u .") } +fun getPrettyFormatTagForFullCommitMessage(project: Project) = + if (GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(GitVcs.getInstance(project).version)) "%B" else "%s%n%n%-b" From 952adac4b0e2539ea8fec3355371e93bd4b52ef2 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 19 Nov 2017 17:25:08 +0300 Subject: [PATCH 78/81] git tests: don't run a test with '--allow-empty-message' for older Git --- .../git4idea/tests/git4idea/history/GitHistoryUtilsTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java index dfa0665e70f1..9ae4047cf45f 100644 --- a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java +++ b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java @@ -31,6 +31,7 @@ import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitFileRevision; import git4idea.GitRevisionNumber; +import git4idea.config.GitVersion; import git4idea.history.browser.SHAHash; import git4idea.test.GitSingleRepoTest; import org.jetbrains.annotations.NotNull; @@ -45,6 +46,7 @@ import static com.intellij.openapi.vcs.Executor.*; import static git4idea.test.GitExecutor.*; import static git4idea.test.GitTestUtil.USER_EMAIL; import static git4idea.test.GitTestUtil.USER_NAME; +import static org.junit.Assume.assumeTrue; /** * Tests for low-level history methods in GitHistoryUtils. @@ -377,6 +379,9 @@ public class GitHistoryUtilsTest extends GitSingleRepoTest { } public void testLoadingDetailsWithoutChanges() throws Exception { + assumeTrue("Not testing: Git doesn't know --allow-empty-message in " + vcs.getVersion(), + vcs.getVersion().isLaterOrEqual(new GitVersion(1, 7, 2, 0))); + List expected = ContainerUtil.newArrayList(); String messageFile = "message.txt"; From 14cb8624cbb2ef298093374c089b859b3719ecb5 Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Fri, 17 Nov 2017 19:22:38 +0300 Subject: [PATCH 79/81] IDEA-182256 RunDashboard: fix NPE when types is added to dashboard - Fix toolbar layout when RC runs and tool window content is not initialized --- .../dashboard/RunDashboardContent.java | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java index 69708551cf83..9b44e58a8bd4 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java @@ -140,21 +140,7 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab myContentManagerListener = new ContentManagerAdapter() { @Override public void contentAdded(ContentManagerEvent event) { - Content content = event.getContent(); - RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content); - if (descriptor == null) { - return; - } - RunnerLayoutUi layoutUi = descriptor.getRunnerLayoutUi(); - if (!(layoutUi instanceof RunnerLayoutUiImpl)) { - return; - } - RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi; - layoutUiImpl.setLeftToolbarVisible(false); - layoutUiImpl.setContentToolbarBefore(false); - List leftToolbarActions = layoutUiImpl.getActions(); - myContentActions.put(content, leftToolbarActions); - updateContentToolbar(content); + onContentAdded(event.getContent()); } @Override @@ -172,17 +158,9 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab if (ContentManagerEvent.ContentOperation.add != event.getOperation()) { return; } - contentAdded(event); - myBuilder.queueUpdate().doWhenDone(() -> myBuilder.accept(RunDashboardNode.class, new TreeVisitor() { - @Override - public boolean visit(@NotNull RunDashboardNode node) { - if (node.getContent() == event.getContent()) { - myBuilder.select(node); - } - return false; - } - })); - showContentPanel(); + Content content = event.getContent(); + onContentAdded(content); + onContentSelectionChanged(content); } }; myContentManager.addContentManagerListener(myContentManagerListener); @@ -261,6 +239,16 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab new TreeSpeedSearch(myTree, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true); setTreeVisible(dashboardManager.isShowConfigurations()); + + // RunDashboardContent may be initialized when some contents have been already added to content manager. + // Process already added content. + for (Content content : myContentManager.getContents()) { + onContentAdded(content); + } + Content selectedContent = myContentManager.getSelectedContent(); + if (selectedContent != null) { + onContentSelectionChanged(selectedContent); + } } private void setTreeVisible(boolean visible) { @@ -331,6 +319,36 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab showMessagePanel(ExecutionBundle.message("run.dashboard.empty.selection.message")); } + private void onContentAdded(Content content) { + RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content); + if (descriptor == null) { + return; + } + RunnerLayoutUi layoutUi = descriptor.getRunnerLayoutUi(); + if (!(layoutUi instanceof RunnerLayoutUiImpl)) { + return; + } + RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi; + layoutUiImpl.setLeftToolbarVisible(false); + layoutUiImpl.setContentToolbarBefore(false); + List leftToolbarActions = layoutUiImpl.getActions(); + myContentActions.put(content, leftToolbarActions); + updateContentToolbar(content); + } + + private void onContentSelectionChanged(Content content) { + myBuilder.queueUpdate().doWhenDone(() -> myBuilder.accept(RunDashboardNode.class, new TreeVisitor() { + @Override + public boolean visit(@NotNull RunDashboardNode node) { + if (node.getContent() == content) { + myBuilder.select(node); + } + return false; + } + })); + showContentPanel(); + } + private void showMessagePanel(String text) { Content selectedContent = myContentManager.getSelectedContent(); if (selectedContent != null) { From d81a1c0c748c38fc986c7f807423e4d825f2a83c Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Fri, 17 Nov 2017 22:03:59 +0300 Subject: [PATCH 80/81] IDEA-182256 RunDashboard: fix NPE when types is added to dashboard - Init tool window listeners when types is added to dashboard --- .../dashboard/RunDashboardManagerImpl.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java index 8e580bc8578a..4c122b4cd960 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java @@ -53,6 +53,7 @@ import javax.swing.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; /** @@ -71,6 +72,7 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS @NotNull private final Set myTypes = ContainerUtil.newHashSet(); @NotNull private final List myGroupers; @NotNull private final Condition myReuseCondition; + @NotNull private final AtomicBoolean myListenersInitialized = new AtomicBoolean(); private boolean myShowConfigurations = true; private float myContentProportion = DEFAULT_CONTENT_PROPORTION; @@ -94,18 +96,17 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS .sorted(RunDashboardGroupingRule.PRIORITY_COMPARATOR) .map(RunDashboardGrouper::new) .collect(Collectors.toList()); - - if (isDashboardEnabled()) { - addRunConfigurationListener(); - } } private static boolean isDashboardEnabled() { return Registry.is("ide.run.dashboard"); } - private void addRunConfigurationListener() { - myProject.getMessageBus().connect(myProject).subscribe(RunManagerListener.TOPIC, new RunManagerListener() { + private void initToolWindowContentListeners() { + if (!myListenersInitialized.compareAndSet(false, true)) return; + + MessageBusConnection connection = myProject.getMessageBus().connect(myProject); + connection.subscribe(RunManagerListener.TOPIC, new RunManagerListener() { private volatile boolean myUpdateStarted; @Override @@ -140,10 +141,6 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS updateDashboard(true); } }); - } - - private void initToolWindowContentListeners() { - MessageBusConnection connection = myProject.getMessageBus().connect(myProject); connection.subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionListener() { @Override public void processStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env, final @NotNull ProcessHandler handler) { @@ -225,8 +222,6 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS myToolWindowContentManager.addContent(myToolWindowContent); myToolWindowContentManagerListener = new ToolWindowContentManagerListener(); - - initToolWindowContentListeners(); } @Override @@ -317,6 +312,9 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS public void setTypes(@NotNull Set types) { myTypes.clear(); myTypes.addAll(types); + if (!myTypes.isEmpty()) { + initToolWindowContentListeners(); + } updateDashboard(true); } @@ -495,6 +493,9 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS public void loadState(State state) { myTypes.clear(); myTypes.addAll(state.configurationTypes); + if (!myTypes.isEmpty()) { + initToolWindowContentListeners(); + } state.ruleStates.forEach(ruleState -> { for (RunDashboardGrouper grouper : myGroupers) { if (grouper.getRule().getName().equals(ruleState.name) && !grouper.getRule().isAlwaysEnabled()) { From 1e9640ebda6fff6a8801b02d9f34bcbca1421c9c Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Sat, 18 Nov 2017 18:01:47 +0300 Subject: [PATCH 81/81] IDEA-182256 RunDashboard: fix NPE when types is added to dashboard - Register tool window when types is added to dashboard --- .../execution/dashboard/RunDashboardManager.java | 2 ++ .../execution/dashboard/RunDashboardManagerImpl.java | 11 ++++++++--- .../dashboard/RunDashboardToolWindowFactory.java | 5 +++++ .../intellij/execution/ui/RunContentManagerImpl.java | 1 + 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardManager.java b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardManager.java index a81e17937966..e1e141747e51 100644 --- a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardManager.java +++ b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardManager.java @@ -57,6 +57,8 @@ public interface RunDashboardManager { void createToolWindowContent(@NotNull ToolWindow toolWindow); + void updateDashboard(boolean withSStructure); + List> getRunConfigurations(); boolean isShowConfigurations(); diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java index 4c122b4cd960..e8cee4905041 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardManagerImpl.java @@ -361,7 +361,8 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS }); } - private void updateDashboard(final boolean withStructure) { + @Override + public void updateDashboard(final boolean withStructure) { final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); if (toolWindowManager == null) return; @@ -374,8 +375,11 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS boolean available = hasContent(); ToolWindow toolWindow = toolWindowManager.getToolWindow(getToolWindowId()); if (toolWindow == null) { + if (!myTypes.isEmpty() || available) { + toolWindow = createToolWindow(toolWindowManager, available); + } if (available) { - createToolWindow(toolWindowManager).show(null); + toolWindow.show(null); } return; } @@ -393,10 +397,11 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS }); } - private ToolWindow createToolWindow(ToolWindowManager toolWindowManager) { + private ToolWindow createToolWindow(ToolWindowManager toolWindowManager, boolean available) { ToolWindow toolWindow = toolWindowManager.registerToolWindow(getToolWindowId(), true, ToolWindowAnchor.BOTTOM, myProject, true); toolWindow.setIcon(getToolWindowIcon()); + toolWindow.setAvailable(available, null); createToolWindowContent(toolWindow); return toolWindow; } diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardToolWindowFactory.java b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardToolWindowFactory.java index 6a7fb2f88ce4..ed77163662d0 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardToolWindowFactory.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardToolWindowFactory.java @@ -28,6 +28,11 @@ import org.jetbrains.annotations.NotNull; public class RunDashboardToolWindowFactory implements ToolWindowFactory, Condition, DumbAware { @Override public boolean value(Project project) { + return !RunDashboardManager.getInstance(project).getTypes().isEmpty(); + } + + @Override + public boolean shouldBeAvailable(@NotNull Project project) { return RunDashboardManager.getInstance(project).isToolWindowAvailable(); } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java index 70abb8c94d6e..8cec7d7d6504 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java @@ -89,6 +89,7 @@ public class RunContentManagerImpl implements RunContentManager, Disposable { } RunDashboardManager dashboardManager = RunDashboardManager.getInstance(myProject); + dashboardManager.updateDashboard(true); initToolWindow(null, dashboardManager.getToolWindowId(), dashboardManager.getToolWindowIcon(), dashboardManager.getDashboardContentManager());